aboutsummaryrefslogtreecommitdiff
path: root/hw/core
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2024-12-14 08:42:53 -0500
committerStefan Hajnoczi <stefanha@redhat.com>2024-12-14 08:42:53 -0500
commitca80a5d026a280762e0772615f1988db542b3ade (patch)
treee16560067dcf7a8210d5b9ab430a9b46e178b2a8 /hw/core
parent94b57605c1c084d2cb399d868a53f123aafb9f55 (diff)
parent456b247eeab067095b680fa4b0fec48137969593 (diff)
downloadqemu-ca80a5d026a280762e0772615f1988db542b3ade.zip
qemu-ca80a5d026a280762e0772615f1988db542b3ade.tar.gz
qemu-ca80a5d026a280762e0772615f1988db542b3ade.tar.bz2
Merge tag 'hw-misc-20241214' of https://github.com/philmd/qemu into staging
Misc HW patch queue - Support string data for extendPCR in VirtIO NSM device (Dorjoy) - Have PCI_BUS implement TYPE_FW_CFG_DATA_GENERATOR_INTERFACE (Phil) - Decouple AHCI from PCI (Bernhard) - Add status to usb_msd_packet_complete (Nick) - Header cleanups (Alex, Phil) # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmdcwx4ACgkQ4+MsLN6t # wN52NRAAlFWIbtUMNt37pqUCmbf9f/rpYAfvKvMQ1h1u73VfOPdFpE9TEySj8+rm # PM/kqsjRuTxrWreEon8SBqnKmXKSLOQ2CbB3TjCy2hlfa6vs5UtTdmzN4l1cagG5 # MtOOjh0yKUAel5DhI3NxA94HJf2dHSSY9dT+6+82eYnVNCBWvTuQp/xDq1TxsW4/ # KAD+ZFDCrUVSGqkU3ZcyHmHxuuFjo8pCfFGsCf9kHAjCxtj5M0GFjMIOcT4WAAnW # PvAM1q84ceBx5LiObEYWu+NB95Xy3YvAjCMFNRIhS64C0SR6o+HhKo9TSprMmpW6 # ncDnNmg85SbUc5yhojvkg25D63uh5NROh9J3gqoibX+Jc1poZN/Xjt98EzqmrLiv # cYyzs4FO5r1sdVBGrRi7iRhFui61chfTJrPbNYePRABGUgxXBjPNwTUm0OwHLdi9 # X9ehbYlYlxHqV0WGq1j47uMB5/SuyeXzYDO4im6fpk7RrpliNysa5zB1vBuDUNpR # Bu5ypprg80km20SjFieC5R0LIT+A38H2ir2qo9buJ+wd2X/n/nqxK4Ucl1s8PLBF # 76WPLIMOV71bshlEEh6KVn+U978BsY4yPr0dZ+javNvGRzZx8ioPK+2OCT+XN39N # oeCcTnC+9YTyYeWJqmY3Hd/kqM+32Jl7FdEEoE0EADz3fSPcvQs= # =cxm9 # -----END PGP SIGNATURE----- # gpg: Signature made Fri 13 Dec 2024 18:28:30 EST # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * tag 'hw-misc-20241214' of https://github.com/philmd/qemu: hw/xtensa: Include missing 'exec/tswap.h' header hw/sh4/r2d: Include missing 'exec/tswap.h' header hw/mips: Include missing 'exec/tswap.h' header hw/ide/ahci: Extract TYPE_SYSBUS_AHCI into dedicated file hw/ide/ahci: Decouple from PCI hw/usb/hcd-xhci-pci: Indentation fix hw/usb/hcd-xhci-nec: Remove unused XHCINecState::flags field hw/usb/msd: Add status to usb_msd_packet_complete() function hw/net/can: clean-up unnecessary includes hw/nvram/fw_cfg: Remove fw_cfg_add_extra_pci_roots() hw: Use pci_bus_add_fw_cfg_extra_pci_roots() hw/pci: Add pci_bus_add_fw_cfg_extra_pci_roots() helper hw/pci: Have PCI_BUS implement TYPE_FW_CFG_DATA_GENERATOR_INTERFACE hw/nvram/fw_cfg: Skip FW_CFG_DATA_GENERATOR when no data to generate hw/nvram/fw_cfg: Pass QOM parent to fw_cfg_add_file_from_generator() hw/nvram/fw_cfg: Rename fw_cfg_add_[file]_from_generator() hw/riscv/virt: Remove pointless GPEX_HOST() cast hw/virtio/virtio-nsm: Support string data for extendPCR hw/core/eif: Use stateful qcrypto apis docs/nitro-enclave: Fix terminal commands formatting Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw/core')
-rw-r--r--hw/core/eif.c202
1 files changed, 77 insertions, 125 deletions
diff --git a/hw/core/eif.c b/hw/core/eif.c
index a7128b7..513caec 100644
--- a/hw/core/eif.c
+++ b/hw/core/eif.c
@@ -187,10 +187,16 @@ static void safe_unlink(char *f)
* Upon success, the caller is reponsible for unlinking and freeing *kernel_path
*/
static bool read_eif_kernel(FILE *f, uint64_t size, char **kernel_path,
- uint8_t *kernel, uint32_t *crc, Error **errp)
+ QCryptoHash *hash0, QCryptoHash *hash1,
+ uint32_t *crc, Error **errp)
{
size_t got;
FILE *tmp_file = NULL;
+ uint8_t *kernel = g_try_malloc(size);
+ if (!kernel) {
+ error_setg(errp, "Out of memory reading kernel section");
+ goto cleanup;
+ }
*kernel_path = NULL;
if (!get_tmp_file("eif-kernel-XXXXXX", kernel_path, errp)) {
@@ -218,6 +224,11 @@ static bool read_eif_kernel(FILE *f, uint64_t size, char **kernel_path,
}
*crc = crc32(*crc, kernel, size);
+ if (qcrypto_hash_update(hash0, (char *)kernel, size, errp) != 0 ||
+ qcrypto_hash_update(hash1, (char *)kernel, size, errp) != 0) {
+ goto cleanup;
+ }
+ g_free(kernel);
fclose(tmp_file);
return true;
@@ -229,10 +240,12 @@ static bool read_eif_kernel(FILE *f, uint64_t size, char **kernel_path,
g_free(*kernel_path);
*kernel_path = NULL;
+ g_free(kernel);
return false;
}
static bool read_eif_cmdline(FILE *f, uint64_t size, char *cmdline,
+ QCryptoHash *hash0, QCryptoHash *hash1,
uint32_t *crc, Error **errp)
{
size_t got = fread(cmdline, 1, size, f);
@@ -242,28 +255,47 @@ static bool read_eif_cmdline(FILE *f, uint64_t size, char *cmdline,
}
*crc = crc32(*crc, (uint8_t *)cmdline, size);
+ if (qcrypto_hash_update(hash0, cmdline, size, errp) != 0 ||
+ qcrypto_hash_update(hash1, cmdline, size, errp) != 0) {
+ return false;
+ }
return true;
}
static bool read_eif_ramdisk(FILE *eif, FILE *initrd, uint64_t size,
- uint8_t *ramdisk, uint32_t *crc, Error **errp)
+ QCryptoHash *hash0, QCryptoHash *h, uint32_t *crc,
+ Error **errp)
{
size_t got;
+ bool ret = false;
+ uint8_t *ramdisk = g_try_malloc(size);
+ if (!ramdisk) {
+ error_setg(errp, "Out of memory reading initrd section");
+ goto cleanup;
+ }
got = fread(ramdisk, 1, size, eif);
if ((uint64_t) got != size) {
error_setg(errp, "Failed to read EIF ramdisk section data");
- return false;
+ goto cleanup;
}
got = fwrite(ramdisk, 1, size, initrd);
if ((uint64_t) got != size) {
error_setg(errp, "Failed to write EIF ramdisk data to temporary file");
- return false;
+ goto cleanup;
}
*crc = crc32(*crc, ramdisk, size);
- return true;
+ if (qcrypto_hash_update(hash0, (char *)ramdisk, size, errp) != 0 ||
+ qcrypto_hash_update(h, (char *)ramdisk, size, errp) != 0) {
+ goto cleanup;
+ }
+ ret = true;
+
+ cleanup:
+ g_free(ramdisk);
+ return ret;
}
static bool get_signature_fingerprint_sha384(FILE *eif, uint64_t size,
@@ -391,34 +423,10 @@ static long get_file_size(FILE *f, Error **errp)
return size;
}
-static bool get_SHA384_digest(GList *list, uint8_t *digest, Error **errp)
+static bool get_SHA384_hash(QCryptoHash *h, uint8_t *hash, Error **errp)
{
- size_t digest_len = QCRYPTO_HASH_DIGEST_LEN_SHA384;
- size_t list_len = g_list_length(list);
- struct iovec *iovec_list = g_new0(struct iovec, list_len);
- bool ret = true;
- GList *l;
- int i;
-
- for (i = 0, l = list; l != NULL; l = l->next, i++) {
- iovec_list[i] = *(struct iovec *) l->data;
- }
-
- if (qcrypto_hash_bytesv(QCRYPTO_HASH_ALGO_SHA384, iovec_list, list_len,
- &digest, &digest_len, errp) < 0) {
- ret = false;
- }
-
- g_free(iovec_list);
- return ret;
-}
-
-static void free_iovec(struct iovec *iov)
-{
- if (iov) {
- g_free(iov->iov_base);
- g_free(iov);
- }
+ size_t hash_len = QCRYPTO_HASH_DIGEST_LEN_SHA384;
+ return qcrypto_hash_finalize_bytes(h, &hash, &hash_len, errp) == 0;
}
/*
@@ -427,8 +435,8 @@ static void free_iovec(struct iovec *iov)
*/
bool read_eif_file(const char *eif_path, const char *machine_initrd,
char **kernel_path, char **initrd_path, char **cmdline,
- uint8_t *image_sha384, uint8_t *bootstrap_sha384,
- uint8_t *app_sha384, uint8_t *fingerprint_sha384,
+ uint8_t *image_hash, uint8_t *bootstrap_hash,
+ uint8_t *app_hash, uint8_t *fingerprint_hash,
bool *signature_found, Error **errp)
{
FILE *f = NULL;
@@ -438,18 +446,29 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
uint32_t crc = 0;
EifHeader eif_header;
bool seen_sections[EIF_SECTION_MAX] = {false};
- /* kernel + ramdisks + cmdline sha384 hash */
- GList *iov_PCR0 = NULL;
- /* kernel + boot ramdisk + cmdline sha384 hash */
- GList *iov_PCR1 = NULL;
- /* application ramdisk(s) hash */
- GList *iov_PCR2 = NULL;
- uint8_t *ptr = NULL;
- struct iovec *iov_ptr = NULL;
+ /* kernel + ramdisks + cmdline SHA384 hash */
+ g_autoptr(QCryptoHash) hash0 = NULL;
+ /* kernel + boot ramdisk + cmdline SHA384 hash */
+ g_autoptr(QCryptoHash) hash1 = NULL;
+ /* application ramdisk(s) SHA384 hash */
+ g_autoptr(QCryptoHash) hash2 = NULL;
*signature_found = false;
*kernel_path = *initrd_path = *cmdline = NULL;
+ hash0 = qcrypto_hash_new(QCRYPTO_HASH_ALGO_SHA384, errp);
+ if (!hash0) {
+ goto cleanup;
+ }
+ hash1 = qcrypto_hash_new(QCRYPTO_HASH_ALGO_SHA384, errp);
+ if (!hash1) {
+ goto cleanup;
+ }
+ hash2 = qcrypto_hash_new(QCRYPTO_HASH_ALGO_SHA384, errp);
+ if (!hash2) {
+ goto cleanup;
+ }
+
f = fopen(eif_path, "rb");
if (f == NULL) {
error_setg_errno(errp, errno, "Failed to open %s", eif_path);
@@ -517,21 +536,8 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
goto cleanup;
}
- ptr = g_try_malloc(hdr.section_size);
- if (!ptr) {
- error_setg(errp, "Out of memory reading kernel section");
- goto cleanup;
- }
-
- iov_ptr = g_malloc(sizeof(struct iovec));
- iov_ptr->iov_base = ptr;
- iov_ptr->iov_len = hdr.section_size;
-
- iov_PCR0 = g_list_append(iov_PCR0, iov_ptr);
- iov_PCR1 = g_list_append(iov_PCR1, iov_ptr);
-
- if (!read_eif_kernel(f, hdr.section_size, kernel_path, ptr, &crc,
- errp)) {
+ if (!read_eif_kernel(f, hdr.section_size, kernel_path, hash0,
+ hash1, &crc, errp)) {
goto cleanup;
}
@@ -539,7 +545,6 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
case EIF_SECTION_CMDLINE:
{
uint64_t size;
- uint8_t *cmdline_copy;
if (seen_sections[EIF_SECTION_CMDLINE]) {
error_setg(errp, "Invalid EIF image. More than 1 cmdline "
"section");
@@ -551,33 +556,26 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
error_setg(errp, "Out of memory reading command line section");
goto cleanup;
}
- if (!read_eif_cmdline(f, size, *cmdline, &crc, errp)) {
+ if (!read_eif_cmdline(f, size, *cmdline, hash0, hash1, &crc,
+ errp)) {
goto cleanup;
}
(*cmdline)[size] = '\0';
- /*
- * We make a copy of '*cmdline' for putting it in iovecs so that
- * we can easily free all the iovec entries later as we cannot
- * free '*cmdline' which is used by the caller.
- */
- cmdline_copy = g_memdup2(*cmdline, size);
-
- iov_ptr = g_malloc(sizeof(struct iovec));
- iov_ptr->iov_base = cmdline_copy;
- iov_ptr->iov_len = size;
-
- iov_PCR0 = g_list_append(iov_PCR0, iov_ptr);
- iov_PCR1 = g_list_append(iov_PCR1, iov_ptr);
break;
}
case EIF_SECTION_RAMDISK:
{
+ QCryptoHash *h = hash2;
if (!seen_sections[EIF_SECTION_RAMDISK]) {
/*
* If this is the first time we are seeing a ramdisk section,
- * we need to create the initrd temporary file.
+ * we need to:
+ * 1) hash it into bootstrap (hash1) instead of app (hash2)
+ * along with image (hash0)
+ * 2) create the initrd temporary file.
*/
+ h = hash1;
if (!get_tmp_file("eif-initrd-XXXXXX", initrd_path, errp)) {
goto cleanup;
}
@@ -589,29 +587,7 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
}
}
- ptr = g_try_malloc(hdr.section_size);
- if (!ptr) {
- error_setg(errp, "Out of memory reading initrd section");
- goto cleanup;
- }
-
- iov_ptr = g_malloc(sizeof(struct iovec));
- iov_ptr->iov_base = ptr;
- iov_ptr->iov_len = hdr.section_size;
-
- iov_PCR0 = g_list_append(iov_PCR0, iov_ptr);
- /*
- * If it's the first ramdisk, we need to hash it into bootstrap
- * i.e., iov_PCR1, otherwise we need to hash it into app i.e.,
- * iov_PCR2.
- */
- if (!seen_sections[EIF_SECTION_RAMDISK]) {
- iov_PCR1 = g_list_append(iov_PCR1, iov_ptr);
- } else {
- iov_PCR2 = g_list_append(iov_PCR2, iov_ptr);
- }
-
- if (!read_eif_ramdisk(f, initrd_path_f, hdr.section_size, ptr,
+ if (!read_eif_ramdisk(f, initrd_path_f, hdr.section_size, hash0, h,
&crc, errp)) {
goto cleanup;
}
@@ -621,7 +597,7 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
case EIF_SECTION_SIGNATURE:
*signature_found = true;
if (!get_signature_fingerprint_sha384(f, hdr.section_size,
- fingerprint_sha384, &crc,
+ fingerprint_hash, &crc,
errp)) {
goto cleanup;
}
@@ -692,52 +668,28 @@ bool read_eif_file(const char *eif_path, const char *machine_initrd,
goto cleanup;
}
- ptr = g_try_malloc(machine_initrd_size);
- if (!ptr) {
- error_setg(errp, "Out of memory reading initrd file");
- goto cleanup;
- }
-
- iov_ptr = g_malloc(sizeof(struct iovec));
- iov_ptr->iov_base = ptr;
- iov_ptr->iov_len = machine_initrd_size;
-
- iov_PCR0 = g_list_append(iov_PCR0, iov_ptr);
- iov_PCR2 = g_list_append(iov_PCR2, iov_ptr);
-
if (!read_eif_ramdisk(machine_initrd_f, initrd_path_f,
- machine_initrd_size, ptr, &crc, errp)) {
+ machine_initrd_size, hash0, hash2, &crc, errp)) {
goto cleanup;
}
}
- if (!get_SHA384_digest(iov_PCR0, image_sha384, errp)) {
+ if (!get_SHA384_hash(hash0, image_hash, errp)) {
goto cleanup;
}
- if (!get_SHA384_digest(iov_PCR1, bootstrap_sha384, errp)) {
+ if (!get_SHA384_hash(hash1, bootstrap_hash, errp)) {
goto cleanup;
}
- if (!get_SHA384_digest(iov_PCR2, app_sha384, errp)) {
+ if (!get_SHA384_hash(hash2, app_hash, errp)) {
goto cleanup;
}
- /*
- * We only need to free iov_PCR0 entries because iov_PCR1 and
- * iov_PCR2 iovec entries are subsets of iov_PCR0 iovec entries.
- */
- g_list_free_full(iov_PCR0, (GDestroyNotify) free_iovec);
- g_list_free(iov_PCR1);
- g_list_free(iov_PCR2);
fclose(f);
fclose(initrd_path_f);
safe_fclose(machine_initrd_f);
return true;
cleanup:
- g_list_free_full(iov_PCR0, (GDestroyNotify) free_iovec);
- g_list_free(iov_PCR1);
- g_list_free(iov_PCR2);
-
safe_fclose(f);
safe_fclose(initrd_path_f);
safe_fclose(machine_initrd_f);