diff options
author | Tom Rini <trini@konsulko.com> | 2020-07-05 18:13:12 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-07-05 18:13:12 -0400 |
commit | 621e09cb3bf7e6d4fce9dd5e6de97e057adebc3a (patch) | |
tree | c2fcb855263939c0cf2a19d7c192fb9a74679d3b /lib | |
parent | df3d0a3f95dd9109b889c5411204f133451b7a7e (diff) | |
parent | 93f6201af71d9a0a521c99212e6066778270a357 (diff) |
Merge tag 'efi-2020-10-rc1' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi into next
Pull request for UEFI sub-system for efi-2020-10-rc1
This series comprises error corrections for the UEFI subsystem:
* correct consideration of timestamps for variable authentication
* correct collection of data regions for code authentication
* correct unit tests to test loading dbx
* enable FAT_WRITE as required by the UEFI spec
The boot manager uses log functions instead of printf() and debug().
The UEFI intialization state is exported.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/Kconfig | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 26 | ||||
-rw-r--r-- | lib/efi_loader/efi_image_loader.c | 64 | ||||
-rw-r--r-- | lib/efi_loader/efi_setup.c | 9 | ||||
-rw-r--r-- | lib/efi_loader/efi_signature.c | 152 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable.c | 54 |
6 files changed, 166 insertions, 141 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index aad37b7155..6c9df3a767 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -15,6 +15,8 @@ config EFI_LOADER select HAVE_BLOCK_DEVICE select REGEX imply CFB_CONSOLE_ANSI + imply FAT + imply FAT_WRITE imply USB_KEYBOARD_FN_KEYS imply VIDEO_ANSI help diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index e144b3e7f4..e268e9c4b8 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Rob Clark */ +#define LOG_CATEGORY LOGC_EFI + #include <common.h> #include <charset.h> #include <log.h> @@ -203,14 +205,14 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) if (lo.attributes & LOAD_OPTION_ACTIVE) { u32 attributes; - debug("%s: trying to load \"%ls\" from %pD\n", - __func__, lo.label, lo.file_path); + log_debug("%s: trying to load \"%ls\" from %pD\n", + __func__, lo.label, lo.file_path); ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path, NULL, 0, handle)); if (ret != EFI_SUCCESS) { - printf("Loading from Boot%04X '%ls' failed\n", n, - lo.label); + log_warning("Loading %ls '%ls' failed\n", + varname, lo.label); goto error; } @@ -224,11 +226,11 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) if (ret != EFI_SUCCESS) { if (EFI_CALL(efi_unload_image(*handle)) != EFI_SUCCESS) - printf("Unloading image failed\n"); + log_err("Unloading image failed\n"); goto error; } - printf("Booting: %ls\n", lo.label); + log_info("Booting: %ls\n", lo.label); } else { ret = EFI_LOAD_ERROR; } @@ -268,7 +270,7 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle) if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) { /* BootNext does exist here */ if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16)) - printf("BootNext must be 16-bit integer\n"); + log_err("BootNext must be 16-bit integer\n"); /* delete BootNext */ ret = EFI_CALL(efi_set_variable( @@ -283,24 +285,26 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle) ret = try_load_entry(bootnext, handle); if (ret == EFI_SUCCESS) return ret; - printf("Loading from BootNext failed, falling back to BootOrder\n"); + log_warning( + "Loading from BootNext failed, falling back to BootOrder\n"); } } else { - printf("Deleting BootNext failed\n"); + log_err("Deleting BootNext failed\n"); } } /* BootOrder */ bootorder = get_var(L"BootOrder", &efi_global_variable_guid, &size); if (!bootorder) { - printf("BootOrder not defined\n"); + log_info("BootOrder not defined\n"); ret = EFI_NOT_FOUND; goto error; } num = size / sizeof(uint16_t); for (i = 0; i < num; i++) { - debug("%s: trying to load Boot%04X\n", __func__, bootorder[i]); + log_debug("%s trying to load Boot%04X\n", __func__, + bootorder[i]); ret = try_load_entry(bootorder[i], handle); if (ret == EFI_SUCCESS) break; diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 230d41ae5e..06a2ebdb90 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -325,8 +325,8 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, authoff = opt->DataDirectory[ctidx].VirtualAddress; authsz = opt->DataDirectory[ctidx].Size; } else { - debug("%s: Invalid optional header magic %x\n", __func__, - nt->OptionalHeader.Magic); + EFI_PRINT("%s: Invalid optional header magic %x\n", __func__, + nt->OptionalHeader.Magic); goto err; } @@ -336,7 +336,7 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, nt->FileHeader.SizeOfOptionalHeader); sorted = calloc(sizeof(IMAGE_SECTION_HEADER *), num_sections); if (!sorted) { - debug("%s: Out of memory\n", __func__); + EFI_PRINT("%s: Out of memory\n", __func__); goto err; } @@ -355,13 +355,13 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, efi_image_region_add(regs, efi + sorted[i]->PointerToRawData, efi + sorted[i]->PointerToRawData + size, 0); - debug("section[%d](%s): raw: 0x%x-0x%x, virt: %x-%x\n", - i, sorted[i]->Name, - sorted[i]->PointerToRawData, - sorted[i]->PointerToRawData + size, - sorted[i]->VirtualAddress, - sorted[i]->VirtualAddress - + sorted[i]->Misc.VirtualSize); + EFI_PRINT("section[%d](%s): raw: 0x%x-0x%x, virt: %x-%x\n", + i, sorted[i]->Name, + sorted[i]->PointerToRawData, + sorted[i]->PointerToRawData + size, + sorted[i]->VirtualAddress, + sorted[i]->VirtualAddress + + sorted[i]->Misc.VirtualSize); bytes_hashed += size; } @@ -369,8 +369,8 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, /* 3. Extra data excluding Certificates Table */ if (bytes_hashed + authsz < len) { - debug("extra data for hash: %zu\n", - len - (bytes_hashed + authsz)); + EFI_PRINT("extra data for hash: %lu\n", + len - (bytes_hashed + authsz)); efi_image_region_add(regs, efi + bytes_hashed, efi + len - authsz, 0); } @@ -378,18 +378,19 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp, /* Return Certificates Table */ if (authsz) { if (len < authoff + authsz) { - debug("%s: Size for auth too large: %u >= %zu\n", - __func__, authsz, len - authoff); + EFI_PRINT("%s: Size for auth too large: %u >= %zu\n", + __func__, authsz, len - authoff); goto err; } if (authsz < sizeof(*auth)) { - debug("%s: Size for auth too small: %u < %zu\n", - __func__, authsz, sizeof(*auth)); + EFI_PRINT("%s: Size for auth too small: %u < %zu\n", + __func__, authsz, sizeof(*auth)); goto err; } *auth = efi + authoff; *auth_len = authsz; - debug("WIN_CERTIFICATE: 0x%x, size: 0x%x\n", authoff, authsz); + EFI_PRINT("WIN_CERTIFICATE: 0x%x, size: 0x%x\n", authoff, + authsz); } else { *auth = NULL; *auth_len = 0; @@ -423,19 +424,19 @@ static bool efi_image_unsigned_authenticate(struct efi_image_regions *regs) dbx = efi_sigstore_parse_sigdb(L"dbx"); if (!dbx) { - debug("Getting signature database(dbx) failed\n"); + EFI_PRINT("Getting signature database(dbx) failed\n"); goto out; } db = efi_sigstore_parse_sigdb(L"db"); if (!db) { - debug("Getting signature database(db) failed\n"); + EFI_PRINT("Getting signature database(db) failed\n"); goto out; } /* try black-list first */ if (efi_signature_verify_with_sigdb(regs, NULL, dbx, NULL)) { - debug("Image is not signed and rejected by \"dbx\"\n"); + EFI_PRINT("Image is not signed and rejected by \"dbx\"\n"); goto out; } @@ -443,7 +444,7 @@ static bool efi_image_unsigned_authenticate(struct efi_image_regions *regs) if (efi_signature_verify_with_sigdb(regs, NULL, db, NULL)) ret = true; else - debug("Image is not signed and not found in \"db\" or \"dbx\"\n"); + EFI_PRINT("Image is not signed and not found in \"db\" or \"dbx\"\n"); out: efi_sigstore_free(db); @@ -504,7 +505,7 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) if (!efi_image_parse(efi, efi_size, ®s, &wincerts, &wincerts_len)) { - debug("Parsing PE executable image failed\n"); + EFI_PRINT("Parsing PE executable image failed\n"); goto err; } @@ -520,13 +521,13 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) */ db = efi_sigstore_parse_sigdb(L"db"); if (!db) { - debug("Getting signature database(db) failed\n"); + EFI_PRINT("Getting signature database(db) failed\n"); goto err; } dbx = efi_sigstore_parse_sigdb(L"dbx"); if (!dbx) { - debug("Getting signature database(dbx) failed\n"); + EFI_PRINT("Getting signature database(dbx) failed\n"); goto err; } @@ -535,26 +536,27 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) (void *)wincert < (void *)wincerts + wincerts_len; wincert = (void *)wincert + ALIGN(wincert->dwLength, 8)) { if (wincert->dwLength < sizeof(*wincert)) { - debug("%s: dwLength too small: %u < %zu\n", - __func__, wincert->dwLength, sizeof(*wincert)); + EFI_PRINT("%s: dwLength too small: %u < %zu\n", + __func__, wincert->dwLength, + sizeof(*wincert)); goto err; } msg = pkcs7_parse_message((void *)wincert + sizeof(*wincert), wincert->dwLength - sizeof(*wincert)); if (IS_ERR(msg)) { - debug("Parsing image's signature failed\n"); + EFI_PRINT("Parsing image's signature failed\n"); msg = NULL; goto err; } /* try black-list first */ if (efi_signature_verify_with_sigdb(regs, msg, dbx, NULL)) { - debug("Signature was rejected by \"dbx\"\n"); + EFI_PRINT("Signature was rejected by \"dbx\"\n"); goto err; } if (!efi_signature_verify_signers(msg, dbx)) { - debug("Signer was rejected by \"dbx\"\n"); + EFI_PRINT("Signer was rejected by \"dbx\"\n"); goto err; } else { ret = true; @@ -562,14 +564,14 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) /* try white-list */ if (!efi_signature_verify_with_sigdb(regs, msg, db, &cert)) { - debug("Verifying signature with \"db\" failed\n"); + EFI_PRINT("Verifying signature with \"db\" failed\n"); goto err; } else { ret = true; } if (!efi_signature_verify_cert(cert, dbx)) { - debug("Certificate was rejected by \"dbx\"\n"); + EFI_PRINT("Certificate was rejected by \"dbx\"\n"); goto err; } else { ret = true; diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index dd0c53fc23..a3b05a4a9b 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -11,7 +11,7 @@ #define OBJ_LIST_NOT_INITIALIZED 1 -static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; +efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; /* * Allow unaligned memory access. @@ -140,6 +140,10 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; + ret = efi_console_register(); + if (ret != EFI_SUCCESS) + goto out; + #ifdef CONFIG_PARTITIONS ret = efi_disk_register(); if (ret != EFI_SUCCESS) @@ -185,9 +189,6 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; - ret = efi_console_register(); - if (ret != EFI_SUCCESS) - goto out; #if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO) ret = efi_gop_register(); if (ret != EFI_SUCCESS) diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c index 6685253856..e05c471c61 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -42,14 +42,14 @@ static bool efi_hash_regions(struct efi_image_regions *regs, void **hash, *size = 0; *hash = calloc(1, SHA256_SUM_LEN); if (!*hash) { - debug("Out of memory\n"); + EFI_PRINT("Out of memory\n"); return false; } *size = SHA256_SUM_LEN; hash_calculate("sha256", regs->reg, regs->num, *hash); #ifdef DEBUG - debug("hash calculated:\n"); + EFI_PRINT("hash calculated:\n"); print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, *hash, SHA256_SUM_LEN, false); #endif @@ -75,7 +75,7 @@ static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash, *size = 0; *hash = calloc(1, SHA256_SUM_LEN); if (!*hash) { - debug("Out of memory\n"); + EFI_PRINT("Out of memory\n"); free(msg); return false; } @@ -86,7 +86,7 @@ static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash, hash_calculate("sha256", ®tmp, 1, *hash); #ifdef DEBUG - debug("hash calculated based on contentInfo:\n"); + EFI_PRINT("hash calculated based on contentInfo:\n"); print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, *hash, SHA256_SUM_LEN, false); #endif @@ -119,8 +119,8 @@ static bool efi_signature_verify(struct efi_image_regions *regs, char c; bool verified; - debug("%s: Enter, %p, %p, %p(issuer: %s, subject: %s)\n", __func__, - regs, ps_info, cert, cert->issuer, cert->subject); + EFI_PRINT("%s: Enter, %p, %p, %p(issuer: %s, subject: %s)\n", __func__, + regs, ps_info, cert, cert->issuer, cert->subject); verified = false; @@ -138,7 +138,8 @@ static bool efi_signature_verify(struct efi_image_regions *regs, info.checksum = image_get_checksum_algo("sha256,rsa2048"); info.name = "sha256,rsa2048"; } else { - debug("unknown msg digest algo: %s\n", ps_info->sig->hash_algo); + EFI_PRINT("unknown msg digest algo: %s\n", + ps_info->sig->hash_algo); goto out; } info.crypto = image_get_crypto_algo(info.name); @@ -147,21 +148,22 @@ static bool efi_signature_verify(struct efi_image_regions *regs, info.keylen = cert->pub->keylen; /* verify signature */ - debug("%s: crypto: %s, signature len:%x\n", __func__, - info.name, ps_info->sig->s_size); + EFI_PRINT("%s: crypto: %s, signature len:%x\n", __func__, + info.name, ps_info->sig->s_size); if (ps_info->aa_set & (1UL << sinfo_has_message_digest)) { - debug("%s: RSA verify authentication attribute\n", __func__); + EFI_PRINT("%s: RSA verify authentication attribute\n", + __func__); /* * NOTE: This path will be executed only for * PE image authentication */ /* check if hash matches digest first */ - debug("checking msg digest first, len:0x%x\n", - ps_info->msgdigest_len); + EFI_PRINT("checking msg digest first, len:0x%x\n", + ps_info->msgdigest_len); #ifdef DEBUG - debug("hash in database:\n"); + EFI_PRINT("hash in database:\n"); print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, ps_info->msgdigest, ps_info->msgdigest_len, false); @@ -173,14 +175,14 @@ static bool efi_signature_verify(struct efi_image_regions *regs, /* for authenticated variable */ if (ps_info->msgdigest_len != size || memcmp(hash, ps_info->msgdigest, size)) { - debug("Digest doesn't match\n"); + EFI_PRINT("Digest doesn't match\n"); free(hash); goto out; } free(hash); } else { - debug("Digesting image failed\n"); + EFI_PRINT("Digesting image failed\n"); goto out; } @@ -195,7 +197,7 @@ static bool efi_signature_verify(struct efi_image_regions *regs, ps_info->sig->s, ps_info->sig->s_size)) verified = true; } else { - debug("%s: RSA verify content data\n", __func__); + EFI_PRINT("%s: RSA verify content data\n", __func__); /* against all data */ if (!rsa_verify(&info, regs->reg, regs->num, ps_info->sig->s, ps_info->sig->s_size)) @@ -203,7 +205,7 @@ static bool efi_signature_verify(struct efi_image_regions *regs, } out: - debug("%s: Exit, verified: %d\n", __func__, verified); + EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified); return verified; } @@ -233,26 +235,26 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs, struct efi_sig_data *sig_data; bool verified = false; - debug("%s: Enter, %p, %p, %p, %p\n", __func__, - regs, signed_info, siglist, valid_cert); + EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, + regs, signed_info, siglist, valid_cert); if (!signed_info) { void *hash; size_t size; - debug("%s: unsigned image\n", __func__); + EFI_PRINT("%s: unsigned image\n", __func__); /* * verify based on calculated hash value * TODO: support other hash algorithms */ if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) { - debug("Digest algorithm is not supported: %pUl\n", - &siglist->sig_type); + EFI_PRINT("Digest algorithm is not supported: %pUl\n", + &siglist->sig_type); goto out; } if (!efi_hash_regions(regs, &hash, &size)) { - debug("Digesting unsigned image failed\n"); + EFI_PRINT("Digesting unsigned image failed\n"); goto out; } @@ -260,7 +262,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs, for (sig_data = siglist->sig_data_list; sig_data; sig_data = sig_data->next) { #ifdef DEBUG - debug("Msg digest in database:\n"); + EFI_PRINT("Msg digest in database:\n"); print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, sig_data->data, sig_data->size, false); #endif @@ -275,10 +277,10 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs, goto out; } - debug("%s: signed image\n", __func__); + EFI_PRINT("%s: signed image\n", __func__); if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509)) { - debug("Signature type is not supported: %pUl\n", - &siglist->sig_type); + EFI_PRINT("Signature type is not supported: %pUl\n", + &siglist->sig_type); goto out; } @@ -289,7 +291,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs, cert = x509_cert_parse(sig_data->data, sig_data->size); if (IS_ERR(cert)) { - debug("Parsing x509 certificate failed\n"); + EFI_PRINT("Parsing x509 certificate failed\n"); goto out; } @@ -306,7 +308,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs, } out: - debug("%s: Exit, verified: %d\n", __func__, verified); + EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified); return verified; } @@ -331,7 +333,7 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs, struct efi_signature_store *siglist; bool verified = false; - debug("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, cert); + EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, cert); if (!db) goto out; @@ -341,7 +343,7 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs, /* for unsigned image */ if (!msg) { - debug("%s: Verify unsigned image with db\n", __func__); + EFI_PRINT("%s: Verify unsigned image with db\n", __func__); for (siglist = db; siglist; siglist = siglist->next) if (efi_signature_verify_with_list(regs, NULL, NULL, siglist, cert)) { @@ -353,10 +355,10 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs, } /* for signed image or variable */ - debug("%s: Verify signed image with db\n", __func__); + EFI_PRINT("%s: Verify signed image with db\n", __func__); for (info = msg->signed_infos; info; info = info->next) { - debug("Signed Info: digest algo: %s, pkey algo: %s\n", - info->sig->hash_algo, info->sig->pkey_algo); + EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n", + info->sig->hash_algo, info->sig->pkey_algo); for (siglist = db; siglist; siglist = siglist->next) { if (efi_signature_verify_with_list(regs, msg, info, @@ -368,7 +370,7 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs, } out: - debug("%s: Exit, verified: %d\n", __func__, verified); + EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified); return verified; } @@ -400,21 +402,21 @@ static bool efi_search_siglist(struct x509_certificate *cert, if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256)) { /* TODO: other hash algos */ - debug("Certificate's digest type is not supported: %pUl\n", - &siglist->sig_type); + EFI_PRINT("Certificate's digest type is not supported: %pUl\n", + &siglist->sig_type); goto out; } /* calculate hash of TBSCertificate */ msg = calloc(1, SHA256_SUM_LEN); if (!msg) { - debug("Out of memory\n"); + EFI_PRINT("Out of memory\n"); goto out; } hash = calloc(1, SHA256_SUM_LEN); if (!hash) { - debug("Out of memory\n"); + EFI_PRINT("Out of memory\n"); goto out; } @@ -465,7 +467,7 @@ bool efi_signature_verify_cert(struct x509_certificate *cert, time64_t revoc_time; bool found = false; - debug("%s: Enter, %p, %p\n", __func__, dbx, cert); + EFI_PRINT("%s: Enter, %p, %p\n", __func__, dbx, cert); if (!cert) return false; @@ -480,7 +482,7 @@ bool efi_signature_verify_cert(struct x509_certificate *cert, } } - debug("%s: Exit, verified: %d\n", __func__, !found); + EFI_PRINT("%s: Exit, verified: %d\n", __func__, !found); return !found; } @@ -501,7 +503,7 @@ bool efi_signature_verify_signers(struct pkcs7_message *msg, struct pkcs7_signed_info *info; bool found = false; - debug("%s: Enter, %p, %p\n", __func__, msg, dbx); + EFI_PRINT("%s: Enter, %p, %p\n", __func__, msg, dbx); if (!msg) goto out; @@ -514,20 +516,24 @@ bool efi_signature_verify_signers(struct pkcs7_message *msg, } } out: - debug("%s: Exit, verified: %d\n", __func__, !found); + EFI_PRINT("%s: Exit, verified: %d\n", __func__, !found); return !found; } /** - * efi_image_region_add - add an entry of region + * efi_image_region_add() - add an entry of region * @regs: Pointer to array of regions - * @start: Start address of region - * @end: End address of region + * @start: Start address of region (included) + * @end: End address of region (excluded) * @nocheck: flag against overlapped regions * - * Take one entry of region [@start, @end] and append it to the list - * pointed to by @regs. If @nocheck is false, overlapping among entries - * will be checked first. + * Take one entry of region [@start, @end[ and insert it into the list. + * + * * If @nocheck is false, the list will be sorted ascending by address. + * Overlapping entries will not be allowed. + * + * * If @nocheck is true, the list will be sorted ascending by sequence + * of adding the entries. Overlapping is allowed. * * Return: status code */ @@ -539,7 +545,7 @@ efi_status_t efi_image_region_add(struct efi_image_regions *regs, int i, j; if (regs->num >= regs->max) { - debug("%s: no more room for regions\n", __func__); + EFI_PRINT("%s: no more room for regions\n", __func__); return EFI_OUT_OF_RESOURCES; } @@ -551,22 +557,21 @@ efi_status_t efi_image_region_add(struct efi_image_regions *regs, if (nocheck) continue; - if (start > reg->data + reg->size) + /* new data after registered region */ + if (start >= reg->data + reg->size) continue; - if ((start >= reg->data && start < reg->data + reg->size) || - (end > reg->data && end < reg->data + reg->size)) { - debug("%s: new region already part of another\n", - __func__); - return EFI_INVALID_PARAMETER; - } - - if (start < reg->data && end < reg->data + reg->size) { + /* new data preceding registered region */ + if (end <= reg->data) { for (j = regs->num - 1; j >= i; j--) - memcpy(®s->reg[j], ®s->reg[j + 1], + memcpy(®s->reg[j + 1], ®s->reg[j], sizeof(*reg)); break; } + + /* new data overlapping registered region */ + EFI_PRINT("%s: new region already part of another\n", __func__); + return EFI_INVALID_PARAMETER; } reg = ®s->reg[i]; @@ -649,14 +654,14 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl) if (esl->signature_list_size <= (sizeof(*esl) + esl->signature_header_size)) { - debug("Siglist in wrong format\n"); + EFI_PRINT("Siglist in wrong format\n"); return NULL; } /* Create a head */ siglist = calloc(sizeof(*siglist), 1); if (!siglist) { - debug("Out of memory\n"); + EFI_PRINT("Out of memory\n"); goto err; } memcpy(&siglist->sig_type, &esl->signature_type, sizeof(efi_guid_t)); @@ -671,14 +676,14 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl) while (left > 0) { /* Signature must exist if there is remaining data. */ if (left < esl->signature_size) { - debug("Certificate is too small\n"); + EFI_PRINT("Certificate is too small\n"); goto err; } sig_data = calloc(esl->signature_size - sizeof(esd->signature_owner), 1); if (!sig_data) { - debug("Out of memory\n"); + EFI_PRINT("Out of memory\n"); goto err; } @@ -689,7 +694,7 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl) - sizeof(esd->signature_owner); sig_data->data = malloc(sig_data->size); if (!sig_data->data) { - debug("Out of memory\n"); + EFI_PRINT("Out of memory\n"); goto err; } memcpy(sig_data->data, esd->signature_data, sig_data->size); @@ -735,7 +740,7 @@ struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name) } else if (!u16_strcmp(name, L"db") || !u16_strcmp(name, L"dbx")) { vendor = &efi_guid_image_security_database; } else { - debug("unknown signature database, %ls\n", name); + EFI_PRINT("unknown signature database, %ls\n", name); return NULL; } @@ -743,23 +748,23 @@ struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name) db_size = 0; ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, NULL)); if (ret == EFI_NOT_FOUND) { - debug("variable, %ls, not found\n", name); + EFI_PRINT("variable, %ls, not found\n", name); sigstore = calloc(sizeof(*sigstore), 1); return sigstore; } else if (ret != EFI_BUFFER_TOO_SMALL) { - debug("Getting variable, %ls, failed\n", name); + EFI_PRINT("Getting variable, %ls, failed\n", name); return NULL; } db = malloc(db_size); if (!db) { - debug("Out of memory\n"); + EFI_PRINT("Out of memory\n"); return NULL; } ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, db)); if (ret != EFI_SUCCESS) { - debug("Getting variable, %ls, failed\n", name); + EFI_PRINT("Getting variable, %ls, failed\n", name); goto err; } @@ -768,19 +773,20 @@ struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name) while (db_size > 0) { /* List must exist if there is remaining data. */ if (db_size < sizeof(*esl)) { - debug("variable, %ls, in wrong format\n", name); + EFI_PRINT("variable, %ls, in wrong format\n", name); goto err; } if (db_size < esl->signature_list_size) { - debug("variable, %ls, in wrong format\n", name); + EFI_PRINT("variable, %ls, in wrong format\n", name); goto err; } /* Parse a single siglist. */ siglist = efi_sigstore_parse_siglist(esl); if (!siglist) { - debug("Parsing signature list of %ls failed\n", name); + EFI_PRINT("Parsing signature list of %ls failed\n", + name); goto err; } diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 6271dbcf41..efaba869ef 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -35,7 +35,8 @@ static u8 efi_vendor_keys; static efi_status_t efi_get_variable_common(u16 *variable_name, const efi_guid_t *vendor, u32 *attributes, - efi_uintn_t *data_size, void *data); + efi_uintn_t *data_size, void *data, + u64 *timep); static efi_status_t efi_set_variable_common(u16 *variable_name, const efi_guid_t *vendor, @@ -243,7 +244,8 @@ static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode) { efi_status_t ret; - debug("Switching secure state from %d to %d\n", efi_secure_mode, mode); + EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode, + mode); if (mode == EFI_MODE_DEPLOYED) { ret = efi_set_secure_state(1, 0, 0, 1); @@ -308,7 +310,7 @@ static efi_status_t efi_init_secure_state(void) size = 0; ret = efi_get_variable_common(L"PK", &efi_global_variable_guid, - NULL, &size, NULL); + NULL, &size, NULL, NULL); if (ret == EFI_BUFFER_TOO_SMALL) { if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) mode = EFI_MODE_USER; @@ -394,16 +396,16 @@ static struct pkcs7_message *efi_variable_parse_signature(const void *buf, * TODO: * The header should be composed in a more refined manner. */ - debug("Makeshift prefix added to authentication data\n"); + EFI_PRINT("Makeshift prefix added to authentication data\n"); ebuflen = sizeof(pkcs7_hdr) + buflen; if (ebuflen <= 0x7f) { - debug("Data is too short\n"); + EFI_PRINT("Data is too short\n"); return NULL; } ebuf = malloc(ebuflen); if (!ebuf) { - debug("Out of memory\n"); + EFI_PRINT("Out of memory\n"); return NULL; } @@ -480,11 +482,15 @@ static efi_status_t efi_variable_authenticate(u16 *variable, if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7)) goto err; + memcpy(×tamp, &auth->time_stamp, sizeof(timestamp)); + if (timestamp.pad1 || timestamp.nanosecond || timestamp.timezone || + timestamp.daylight || timestamp.pad2) + goto err; + *data += sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength; *data_size -= (sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength); - memcpy(×tamp, &auth->time_stamp, sizeof(timestamp)); memset(&tm, 0, sizeof(tm)); tm.tm_year = timestamp.year; tm.tm_mon = timestamp.month; @@ -527,7 +533,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable, auth->auth_info.hdr.dwLength - sizeof(auth->auth_info)); if (!var_sig) { - debug("Parsing variable's signature failed\n"); + EFI_PRINT("Parsing variable's signature failed\n"); goto err; } @@ -558,20 +564,20 @@ static efi_status_t efi_variable_authenticate(u16 *variable, /* verify signature */ if (efi_signature_verify_with_sigdb(regs, var_sig, truststore, NULL)) { - debug("Verified\n"); + EFI_PRINT("Verified\n"); } else { if (truststore2 && efi_signature_verify_with_sigdb(regs, var_sig, truststore2, NULL)) { - debug("Verified\n"); + EFI_PRINT("Verified\n"); } else { - debug("Verifying variable's signature failed\n"); + EFI_PRINT("Verifying variable's signature failed\n"); goto err; } } /* finished checking */ - *time = rtc_mktime(&tm); + *time = new_time; ret = EFI_SUCCESS; err: @@ -596,7 +602,8 @@ static efi_status_t efi_variable_authenticate(u16 *variable, static efi_status_t efi_get_variable_common(u16 *variable_name, const efi_guid_t *vendor, u32 *attributes, - efi_uintn_t *data_size, void *data) + efi_uintn_t *data_size, void *data, + u64 *timep) { char *native_name; efi_status_t ret; @@ -606,7 +613,7 @@ static efi_status_t efi_get_variable_common(u16 *variable_name, u32 attr; if (!variable_name || !vendor || !data_size) - return EFI_EXIT(EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; ret = efi_to_native(&native_name, variable_name, vendor); if (ret) @@ -621,6 +628,9 @@ static efi_status_t efi_get_variable_common(u16 *variable_name, val = parse_attr(val, &attr, &time); + if (timep) + *timep = time; + in_size = *data_size; if ((s = prefix(val, "(blob)"))) { @@ -640,7 +650,7 @@ static efi_status_t efi_get_variable_common(u16 *variable_name, } if (!data) { - debug("Variable with no data shouldn't exist.\n"); + EFI_PRINT("Variable with no data shouldn't exist.\n"); return EFI_INVALID_PARAMETER; } @@ -659,7 +669,7 @@ static efi_status_t efi_get_variable_common(u16 *variable_name, } if (!data) { - debug("Variable with no data shouldn't exist.\n"); + EFI_PRINT("Variable with no data shouldn't exist.\n"); return EFI_INVALID_PARAMETER; } @@ -704,7 +714,7 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, data_size, data); ret = efi_get_variable_common(variable_name, vendor, attributes, - data_size, data); + data_size, data, NULL); return EFI_EXIT(ret); } @@ -900,7 +910,7 @@ static efi_status_t efi_set_variable_common(u16 *variable_name, old_size = 0; attr = 0; ret = efi_get_variable_common(variable_name, vendor, &attr, - &old_size, NULL); + &old_size, NULL, &time); append = !!(attributes & EFI_VARIABLE_APPEND_WRITE); attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE; delete = !append && (!data_size || !attributes); @@ -940,8 +950,8 @@ static efi_status_t efi_set_variable_common(u16 *variable_name, /* authentication is mandatory */ if (!(attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) { - debug("%ls: AUTHENTICATED_WRITE_ACCESS required\n", - variable_name); + EFI_PRINT("%ls: AUTHENTICATED_WRITE_ACCESS required\n", + variable_name); ret = EFI_INVALID_PARAMETER; goto err; } @@ -970,7 +980,7 @@ static efi_status_t efi_set_variable_common(u16 *variable_name, if (attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) { - debug("Secure boot is not configured\n"); + EFI_PRINT("Secure boot is not configured\n"); ret = EFI_INVALID_PARAMETER; goto err; } @@ -991,7 +1001,7 @@ static efi_status_t efi_set_variable_common(u16 *variable_name, goto err; } ret = efi_get_variable_common(variable_name, vendor, - &attr, &old_size, old_data); + &attr, &old_size, old_data, NULL); if (ret != EFI_SUCCESS) goto err; } else { |