Attention is currently required from: Jason Glenesk, Raul Rangel, Marshall Dawson, Felix Held. Kangheui Won has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/60290 )
Change subject: amdfwtool: generate hashes for signed fw ......................................................................
amdfwtool: generate hashes for signed fw
Generate SHA256/SHA384 hash of the signed firmware so we can pass it to the PSP. The PSP will use these hashes to verify that those signed firmwares are what we integrated.
BUG=b:203597980 TEST=build guybrush
Signed-off-by: Kangheui Won khwon@chromium.org Change-Id: I50d278536ba1eac754eb8a39c4c2e428a2371c44 --- M src/soc/amd/cezanne/Makefile.inc M util/amdfwtool/Makefile M util/amdfwtool/Makefile.inc M util/amdfwtool/amdfwtool.c M util/amdfwtool/amdfwtool.h 5 files changed, 154 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/90/60290/1
diff --git a/src/soc/amd/cezanne/Makefile.inc b/src/soc/amd/cezanne/Makefile.inc index 69f78f1..c6a1e68 100644 --- a/src/soc/amd/cezanne/Makefile.inc +++ b/src/soc/amd/cezanne/Makefile.inc @@ -305,6 +305,19 @@ build_complete:: $(obj)/amdfw_a.rom $(obj)/amdfw_b.rom $(CBFSTOOL) $(obj)/coreboot.rom write -u -r SIGNED_AMDFW_A -i 0 -f $(obj)/amdfw_a.rom.signed $(CBFSTOOL) $(obj)/coreboot.rom write -u -r SIGNED_AMDFW_B -i 0 -f $(obj)/amdfw_b.rom.signed + +cbfs-files-y += apu/amdfw_a_hash +apu/amdfw_a_hash-file := $(obj)/amdfw_a.rom.signed.hash +apu/amdfw_a_hash-type := raw + +$(obj)/amdfw_a.rom.signed.hash: $(obj)/amdfw_a.rom + +cbfs-files-y += apu/amdfw_b_hash +apu/amdfw_b_hash-file := $(obj)/amdfw_b.rom.signed.hash +apu/amdfw_b_hash-type := raw + +$(obj)/amdfw_b.rom.signed.hash: $(obj)/amdfw_b.rom + endif # CONFIG_SEPARATE_SIGNED_AMDFW endif
diff --git a/util/amdfwtool/Makefile b/util/amdfwtool/Makefile index 1805459..03f0e1e 100644 --- a/util/amdfwtool/Makefile +++ b/util/amdfwtool/Makefile @@ -8,6 +8,10 @@ WERROR=-Werror -Wno-unused-function CFLAGS=-O2 -Wall -Wextra -Wshadow ${WERROR}
+HOSTPKGCONFIG ?= pkg-config +CFLAGS += $(shell $(HOSTPKGCONFIG) --cflags libcrypto 2>/dev/null) +LDFLAGS += $(shell $(HOSTPKGCONFIG) --libs libcrypto 2>/dev/null) + all: $(TARGET)
$(TARGET): $(OBJ) diff --git a/util/amdfwtool/Makefile.inc b/util/amdfwtool/Makefile.inc index f772299..64b3af4 100644 --- a/util/amdfwtool/Makefile.inc +++ b/util/amdfwtool/Makefile.inc @@ -4,9 +4,14 @@
AMDFWTOOLCFLAGS=-O2 -Wall -Wextra -Wshadow -Werror -Wno-unused-function
+HOSTPKGCONFIG ?= pkg-config + +AMDFWTOOLCFLAGS += $(shell $(HOSTPKGCONFIG) --cflags libcrypto 2>/dev/null) +LDFLAGS += $(shell $(HOSTPKGCONFIG) --libs libcrypto 2>/dev/null) + $(objutil)/amdfwtool/%.o: $(top)/util/amdfwtool/%.c # $(HEADER) $(HOSTCC) $(AMDFWTOOLCFLAGS) $(HOSTCFLAGS) -c -o $@ $<
$(objutil)/amdfwtool/amdfwtool: $(addprefix $(objutil)/amdfwtool/,$(amdfwtoolobj)) printf " AMDFWTOOL\n" - $(HOSTCC) $(addprefix $(objutil)/amdfwtool/,$(amdfwtoolobj)) -o $@ + $(HOSTCC) $(addprefix $(objutil)/amdfwtool/,$(amdfwtoolobj)) $(LDFLAGS) -o $@ diff --git a/util/amdfwtool/amdfwtool.c b/util/amdfwtool/amdfwtool.c index 3cd207a..22f2ad3 100644 --- a/util/amdfwtool/amdfwtool.c +++ b/util/amdfwtool/amdfwtool.c @@ -48,6 +48,7 @@
#include <fcntl.h> #include <errno.h> +#include <openssl/sha.h> #include <stdbool.h> #include <stdio.h> #include <sys/stat.h> @@ -569,6 +570,47 @@ return psp_id; }
+static int add_sha(amd_fw_entry *entry, void *buf) +{ + uint8_t hash[SHA384_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA512_CTX sha384; + struct amd_fw_header *header = (struct amd_fw_header *)buf; + size_t len = header->size_total - sizeof(struct amd_fw_header); + uint8_t *body = (uint8_t *)buf + sizeof(struct amd_fw_header); + + /* Exclude signature at the end of file from hash calculation. + * sig_id == 2 -> SHA384, RSA4096 is used + * sig_id == 2 -> SHA256, RSA2048 is used + */ + if (header->sig_id == 2) + len -= 0x200; + else if (header->sig_id == 0) + len -= 0x100; + else + return -1; + + if (len > header->size_total) + return -1; + + if (header->sig_id == 2) { + SHA384_Init(&sha384); + SHA384_Update(&sha384, body, len); + SHA384_Final(hash, &sha384); + entry->sha_len = SHA384_DIGEST_LENGTH; + } else if (header->sig_id == 0) { + SHA256_Init(&sha256); + SHA256_Update(&sha256, body, len); + SHA256_Final(hash, &sha256); + entry->sha_len = SHA256_DIGEST_LENGTH; + } + + memcpy(entry->sha, hash, entry->sha_len); + entry->subtype = header->fw_subtype; + + return 0; +} + static void integrate_firmwares(context *ctx, embedded_firmware *romsig, amd_fw_entry *fw_table) @@ -660,6 +702,69 @@ } }
+static void write_or_fail(int fd, void *ptr, size_t size) +{ + ssize_t written; + written = write(fd, ptr, size); + if (written > 0) { + size -= written; + if (size) + size -= write(fd, (uint8_t *)ptr + written, size); + } + + if (size) { + fprintf(stderr, "Error writing to file: %s\n", strerror(errno)); + exit(-1); + } +} + +static void write_psp_firmware_hash(const char *filename, + amd_fw_entry *fw_table) +{ + unsigned int i; + struct psp_fw_hash_table hash_header; + int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666); + + if (fd < 0) { + fprintf(stderr, "Error opening file: %s: %s\n", + filename, strerror(errno)); + exit(-1); + } + + memset(&hash_header, 0, sizeof(hash_header)); + + for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) { + if (fw_table[i].sha_len == SHA256_DIGEST_LENGTH) + hash_header.no_of_entries_256++; + else if (fw_table[i].sha_len == SHA384_DIGEST_LENGTH) + hash_header.no_of_entries_384++; + } + + write_or_fail(fd, &hash_header, sizeof(hash_header)); + + for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) { + if (fw_table[i].sha_len == SHA256_DIGEST_LENGTH) { + uint16_t type = fw_table[i].type; + uint16_t subtype = fw_table[i].subtype; + write_or_fail(fd, &type, sizeof(type)); + write_or_fail(fd, &subtype, sizeof(subtype)); + write_or_fail(fd, fw_table[i].sha, SHA256_DIGEST_LENGTH); + } + } + + for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) { + if (fw_table[i].sha_len == SHA384_DIGEST_LENGTH) { + uint16_t type = fw_table[i].type; + uint16_t subtype = fw_table[i].subtype; + write_or_fail(fd, &type, sizeof(type)); + write_or_fail(fd, &subtype, sizeof(subtype)); + write_or_fail(fd, fw_table[i].sha, SHA384_DIGEST_LENGTH); + } + } + + close(fd); +} + static void process_signed_psp_firmwares(const char *signed_rom, amd_fw_entry *fw_table, uint64_t signed_start_addr) @@ -669,6 +774,7 @@ int signed_rom_fd; ssize_t bytes; uint8_t *buf; + char *signed_rom_hash; struct amd_fw_header header; struct stat fd_stat;
@@ -760,6 +866,9 @@ } }
+ if (add_sha(&fw_table[i], buf)) + exit(-1); + fw_table[i].addr_signed = signed_start_addr; fw_table[i].file_size = (uint32_t)fd_stat.st_size;
@@ -770,6 +879,16 @@ }
close(signed_rom_fd); + + signed_rom_hash = malloc(strlen(signed_rom) + 6); + if (!signed_rom_hash) { + fprintf(stderr, "malloc(%lu) failed\n", strlen(signed_rom) + 6); + exit(-1); + } + strcpy(signed_rom_hash, signed_rom); + strcat(signed_rom_hash, ".hash"); + write_psp_firmware_hash(signed_rom_hash, fw_table); + free(signed_rom_hash); }
static void integrate_psp_firmwares(context *ctx, diff --git a/util/amdfwtool/amdfwtool.h b/util/amdfwtool/amdfwtool.h index 9ea0b29..9c9bb63 100644 --- a/util/amdfwtool/amdfwtool.h +++ b/util/amdfwtool/amdfwtool.h @@ -237,12 +237,15 @@ #define PSP_BOTH (PSP_LVL1 | PSP_LVL2) typedef struct _amd_fw_entry { amd_fw_type type; + uint8_t subtype; char *filename; uint8_t subprog; int level; uint64_t other; uint64_t addr_signed; uint32_t file_size; + uint8_t sha[48]; + uint32_t sha_len; } amd_fw_entry;
struct amd_fw_header { @@ -267,6 +270,15 @@ uint8_t reserved_80[128]; } __attribute__((packed));
+struct psp_fw_hash_table { + uint16_t version; + uint16_t no_of_entries_256; + uint16_t no_of_entries_384; + /* These two are pointers but the PSP is 32-bit only. */ + uint32_t fw_hash_256; + uint32_t fw_hash_384; +} __attribute__((packed)); + typedef struct _amd_cb_config { bool have_whitelist; bool unlock_secure;