diff options
| -rw-r--r-- | include/sbat.h | 19 | ||||
| -rw-r--r-- | pe.c | 32 | ||||
| -rw-r--r-- | sbat.c | 117 |
3 files changed, 167 insertions, 1 deletions
diff --git a/include/sbat.h b/include/sbat.h index acda5ef6..ab2325bd 100644 --- a/include/sbat.h +++ b/include/sbat.h @@ -6,5 +6,24 @@ #ifndef SBAT_H_ #define SBAT_H_ +#include "shim.h" + +struct sbat_entry { + const CHAR8 *component_name; + const CHAR8 *component_generation; + const CHAR8 *vendor_name; + const CHAR8 *vendor_package_name; + const CHAR8 *vendor_version; + const CHAR8 *vendor_url; +}; + +struct sbat { + unsigned int size; + struct sbat_entry **entries; +}; + +EFI_STATUS parse_sbat(char *sbat_base, size_t sbat_size, char *buffer, + struct sbat *sbat); + #endif /* !SBAT_H_ */ // vim:fenc=utf-8:tw=75:noet @@ -1039,9 +1039,41 @@ handle_image (void *data, unsigned int datasize, } if (secure_mode ()) { + int res; + unsigned int i; + struct sbat sbat = { 0 }; + struct sbat_entry *entry = NULL; + + if (SBATBase && SBATSize) { + res = parse_sbat(SBATBase, SBATSize, buffer, &sbat); + if (res < 0) { + console_print(L"SBAT data not correct: %r\n", res); + return EFI_UNSUPPORTED; + } + + dprint(L"SBAT data\n"); + for (i = 0; i < sbat.size; i++) { + entry = sbat.entries[i]; + dprint(L"%a, %a, %a, %a, %a, %a\n", + entry->component_name, + entry->component_generation, + entry->vendor_name, + entry->vendor_package_name, + entry->vendor_version, + entry->vendor_url); + } + } else { + perror(L"SBAT data not found\n"); + return EFI_UNSUPPORTED; + } + efi_status = verify_buffer(data, datasize, &context, sha256hash, sha1hash); + if (sbat.entries) + for (i = 0; i < sbat.size; i++) + FreePool(sbat.entries[i]); + if (EFI_ERROR(efi_status)) { if (verbose) console_print(L"Verification failed: %r\n", efi_status); @@ -3,6 +3,121 @@ * sbat.c - parse SBAT data from the .sbat section data */ -#include "shim.h" +#include "sbat.h" + +CHAR8 * +get_sbat_field(CHAR8 *current, CHAR8 *end, const CHAR8 ** field, char delim) +{ + CHAR8 *offset; + + if (!field || !current || !end || current >= end) + return NULL; + + offset = strchrnula(current, delim); + *field = current; + + if (!*offset) + return NULL; + + *offset = '\0'; + return offset + 1; +} + +EFI_STATUS parse_sbat_entry(CHAR8 **current, CHAR8 *end, + struct sbat_entry **sbat_entry) +{ + struct sbat_entry *entry = NULL; + + entry = AllocateZeroPool(sizeof(*entry)); + if (!entry) + return EFI_OUT_OF_RESOURCES; + + *current = get_sbat_field(*current, end, &entry->component_name, ','); + if (!entry->component_name) + goto error; + + *current = get_sbat_field(*current, end, &entry->component_generation,','); + if (!entry->component_generation) + goto error; + + *current = get_sbat_field(*current, end, &entry->vendor_name,','); + if (!entry->vendor_name) + goto error; + + *current = get_sbat_field(*current, end, &entry->vendor_package_name, ','); + if (!entry->vendor_package_name) + goto error; + + *current = get_sbat_field(*current, end, &entry->vendor_version,','); + if (!entry->vendor_version) + goto error; + + *current = get_sbat_field(*current, end, &entry->vendor_url,'\n'); + if (!entry->vendor_url) + goto error; + + *sbat_entry = entry; + + return EFI_SUCCESS; + +error: + FreePool(entry); + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS parse_sbat(char *sbat_base, size_t sbat_size, char *buffer, + struct sbat *sbat) +{ + CHAR8 *current = (CHAR8 *) sbat_base; + CHAR8 *end = (CHAR8 *) sbat_base + sbat_size; + EFI_STATUS efi_status = EFI_SUCCESS; + struct sbat_entry *entry; + struct sbat_entry **entries; + unsigned int i; + + while ((*current == '\r' || *current == '\n') && current < end) + current++; + + if (current == end) + return EFI_INVALID_PARAMETER; + + while ((*end == '\r' || *end == '\n') && end < current) + end--; + + *(end - 1) = '\0'; + + do { + entry = NULL; + efi_status = parse_sbat_entry(¤t, end, &entry); + if (EFI_ERROR(efi_status)) + goto error; + + if (end < current) { + efi_status = EFI_INVALID_PARAMETER; + goto error; + } + + if (entry) { + entries = ReallocatePool(sbat->entries, + sbat->size * sizeof(entry), + (sbat->size + 1) * sizeof(entry)); + if (!entries) { + efi_status = EFI_OUT_OF_RESOURCES; + goto error; + } + + sbat->entries = entries; + sbat->entries[sbat->size] = entry; + sbat->size++; + } + } while (entry && *current != '\0'); + + return efi_status; +error: + perror(L"Failed to parse SBAT data: %r\n", efi_status); + for (i = 0; i < sbat->size; i++) + FreePool(sbat->entries[i]); + return efi_status; +} // vim:fenc=utf-8:tw=75:noet |
