diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 23 | ||||
-rw-r--r-- | lib/Makefile | 1 | ||||
-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 | 52 | ||||
-rw-r--r-- | lib/fdtdec.c | 6 | ||||
-rw-r--r-- | lib/hashtable.c | 8 | ||||
-rw-r--r-- | lib/sha512.c | 383 | ||||
-rw-r--r-- | lib/trace.c | 8 | ||||
-rw-r--r-- | lib/vsprintf.c | 2 |
13 files changed, 586 insertions, 150 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index af5c38afd9..fc7d68487b 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -345,6 +345,29 @@ config SHA256 The SHA256 algorithm produces a 256-bit (32-byte) hash value (digest). +config SHA512_ALGO + bool "Enable SHA512 algorithm" + help + This option enables support of internal SHA512 algorithm. + +config SHA512 + bool "Enable SHA512 support" + depends on SHA512_ALGO + help + This option enables support of hashing using SHA512 algorithm. + The hash is calculated in software. + The SHA512 algorithm produces a 512-bit (64-byte) hash value + (digest). + +config SHA384 + bool "Enable SHA384 support" + depends on SHA512_ALGO + help + This option enables support of hashing using SHA384 algorithm. + The hash is calculated in software. + The SHA384 algorithm produces a 384-bit (48-byte) hash value + (digest). + config SHA_HW_ACCEL bool "Enable hashing using hardware" help diff --git a/lib/Makefile b/lib/Makefile index dc5761966c..1dc06c57d5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_$(SPL_)MD5) += md5.o obj-$(CONFIG_$(SPL_)RSA) += rsa/ obj-$(CONFIG_SHA1) += sha1.o obj-$(CONFIG_SHA256) += sha256.o +obj-$(CONFIG_SHA512_ALGO) += sha512.o obj-$(CONFIG_$(SPL_)ZLIB) += zlib/ obj-$(CONFIG_$(SPL_)ZSTD) += zstd/ 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 c262cb5972..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; @@ -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 { diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 1f2b763acc..0dd7ff1ac3 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1294,9 +1294,11 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename, /* find a matching node and return the phandle to that */ fdt_for_each_subnode(node, blob, parent) { const char *name = fdt_get_name(blob, node, NULL); - phys_addr_t addr, size; + fdt_addr_t addr; + fdt_size_t size; - addr = fdtdec_get_addr_size(blob, node, "reg", &size); + addr = fdtdec_get_addr_size_fixed(blob, node, "reg", 0, na, ns, + &size, false); if (addr == FDT_ADDR_T_NONE) { debug("failed to read address/size for %s\n", name); continue; diff --git a/lib/hashtable.c b/lib/hashtable.c index b96dbe19be..7b6781bc35 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -110,8 +110,10 @@ int hcreate_r(size_t nel, struct hsearch_data *htab) } /* There is still another table active. Return with error. */ - if (htab->table != NULL) + if (htab->table != NULL) { + __set_errno(EINVAL); return 0; + } /* Change nel to the first prime number not smaller as nel. */ nel |= 1; /* make odd */ @@ -124,8 +126,10 @@ int hcreate_r(size_t nel, struct hsearch_data *htab) /* allocate memory and zero out */ htab->table = (struct env_entry_node *)calloc(htab->size + 1, sizeof(struct env_entry_node)); - if (htab->table == NULL) + if (htab->table == NULL) { + __set_errno(ENOMEM); return 0; + } /* everything went alright */ return 1; diff --git a/lib/sha512.c b/lib/sha512.c new file mode 100644 index 0000000000..f1e2acf0fb --- /dev/null +++ b/lib/sha512.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * FIPS-180-2 compliant SHA-512 and SHA-384 implementation + * + * SHA-512 code by Jean-Luc Cooke <jlcooke@certainkey.com> + * + * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> + * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> + * Copyright (c) 2003 Kyle McMartin <kyle@debian.org> + * Copyright (c) 2020 Reuben Dowle <reuben.dowle@4rf.com> + */ + +#ifndef USE_HOSTCC +#include <common.h> +#include <linux/string.h> +#else +#include <string.h> +#endif /* USE_HOSTCC */ +#include <watchdog.h> +#include <u-boot/sha512.h> + +const uint8_t sha384_der_prefix[SHA384_DER_LEN] = { + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, + 0x00, 0x04, 0x30 +}; + +const uint8_t sha512_der_prefix[SHA512_DER_LEN] = { + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40 +}; + +#define SHA384_H0 0xcbbb9d5dc1059ed8ULL +#define SHA384_H1 0x629a292a367cd507ULL +#define SHA384_H2 0x9159015a3070dd17ULL +#define SHA384_H3 0x152fecd8f70e5939ULL +#define SHA384_H4 0x67332667ffc00b31ULL +#define SHA384_H5 0x8eb44a8768581511ULL +#define SHA384_H6 0xdb0c2e0d64f98fa7ULL +#define SHA384_H7 0x47b5481dbefa4fa4ULL + +#define SHA512_H0 0x6a09e667f3bcc908ULL +#define SHA512_H1 0xbb67ae8584caa73bULL +#define SHA512_H2 0x3c6ef372fe94f82bULL +#define SHA512_H3 0xa54ff53a5f1d36f1ULL +#define SHA512_H4 0x510e527fade682d1ULL +#define SHA512_H5 0x9b05688c2b3e6c1fULL +#define SHA512_H6 0x1f83d9abfb41bd6bULL +#define SHA512_H7 0x5be0cd19137e2179ULL + +static inline uint64_t Ch(uint64_t x, uint64_t y, uint64_t z) +{ + return z ^ (x & (y ^ z)); +} + +static inline uint64_t Maj(uint64_t x, uint64_t y, uint64_t z) +{ + return (x & y) | (z & (x | y)); +} + +static const uint64_t sha512_K[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, +}; + +static inline uint64_t ror64(uint64_t word, unsigned int shift) +{ + return (word >> (shift & 63)) | (word << ((-shift) & 63)); +} + +#define e0(x) (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39)) +#define e1(x) (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41)) +#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7)) +#define s1(x) (ror64(x,19) ^ ror64(x,61) ^ (x >> 6)) + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) { \ + (n) = ( (unsigned long long) (b)[(i) ] << 56 ) \ + | ( (unsigned long long) (b)[(i) + 1] << 48 ) \ + | ( (unsigned long long) (b)[(i) + 2] << 40 ) \ + | ( (unsigned long long) (b)[(i) + 3] << 32 ) \ + | ( (unsigned long long) (b)[(i) + 4] << 24 ) \ + | ( (unsigned long long) (b)[(i) + 5] << 16 ) \ + | ( (unsigned long long) (b)[(i) + 6] << 8 ) \ + | ( (unsigned long long) (b)[(i) + 7] ); \ +} +#endif +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) { \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif + +static inline void LOAD_OP(int I, uint64_t *W, const uint8_t *input) +{ + GET_UINT64_BE(W[I], input, I*8); +} + +static inline void BLEND_OP(int I, uint64_t *W) +{ + W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]); +} + +static void +sha512_transform(uint64_t *state, const uint8_t *input) +{ + uint64_t a, b, c, d, e, f, g, h, t1, t2; + + int i; + uint64_t W[16]; + + /* load the state into our registers */ + a=state[0]; b=state[1]; c=state[2]; d=state[3]; + e=state[4]; f=state[5]; g=state[6]; h=state[7]; + + /* now iterate */ + for (i=0; i<80; i+=8) { + if (!(i & 8)) { + int j; + + if (i < 16) { + /* load the input */ + for (j = 0; j < 16; j++) + LOAD_OP(i + j, W, input); + } else { + for (j = 0; j < 16; j++) { + BLEND_OP(i + j, W); + } + } + } + + t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[(i & 15)]; + t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; + t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1]; + t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; + t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2]; + t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; + t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3]; + t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; + t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4]; + t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; + t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5]; + t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; + t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6]; + t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; + t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7]; + t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; + } + + state[0] += a; state[1] += b; state[2] += c; state[3] += d; + state[4] += e; state[5] += f; state[6] += g; state[7] += h; + + /* erase our data */ + a = b = c = d = e = f = g = h = t1 = t2 = 0; +} + +static void sha512_block_fn(sha512_context *sst, const uint8_t *src, + int blocks) +{ + while (blocks--) { + sha512_transform(sst->state, src); + src += SHA512_BLOCK_SIZE; + } +} + +static void sha512_base_do_update(sha512_context *sctx, + const uint8_t *data, + unsigned int len) +{ + unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE; + + sctx->count[0] += len; + if (sctx->count[0] < len) + sctx->count[1]++; + + if (unlikely((partial + len) >= SHA512_BLOCK_SIZE)) { + int blocks; + + if (partial) { + int p = SHA512_BLOCK_SIZE - partial; + + memcpy(sctx->buf + partial, data, p); + data += p; + len -= p; + + sha512_block_fn(sctx, sctx->buf, 1); + } + + blocks = len / SHA512_BLOCK_SIZE; + len %= SHA512_BLOCK_SIZE; + + if (blocks) { + sha512_block_fn(sctx, data, blocks); + data += blocks * SHA512_BLOCK_SIZE; + } + partial = 0; + } + if (len) + memcpy(sctx->buf + partial, data, len); +} + +static void sha512_base_do_finalize(sha512_context *sctx) +{ + const int bit_offset = SHA512_BLOCK_SIZE - sizeof(uint64_t[2]); + uint64_t *bits = (uint64_t *)(sctx->buf + bit_offset); + unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE; + + sctx->buf[partial++] = 0x80; + if (partial > bit_offset) { + memset(sctx->buf + partial, 0x0, SHA512_BLOCK_SIZE - partial); + partial = 0; + + sha512_block_fn(sctx, sctx->buf, 1); + } + + memset(sctx->buf + partial, 0x0, bit_offset - partial); + bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61); + bits[1] = cpu_to_be64(sctx->count[0] << 3); + sha512_block_fn(sctx, sctx->buf, 1); +} + +#if defined(CONFIG_SHA384) +void sha384_starts(sha512_context * ctx) +{ + ctx->state[0] = SHA384_H0; + ctx->state[1] = SHA384_H1; + ctx->state[2] = SHA384_H2; + ctx->state[3] = SHA384_H3; + ctx->state[4] = SHA384_H4; + ctx->state[5] = SHA384_H5; + ctx->state[6] = SHA384_H6; + ctx->state[7] = SHA384_H7; + ctx->count[0] = ctx->count[1] = 0; +} + +void sha384_update(sha512_context *ctx, const uint8_t *input, uint32_t length) +{ + sha512_base_do_update(ctx, input, length); +} + +void sha384_finish(sha512_context * ctx, uint8_t digest[SHA384_SUM_LEN]) +{ + int i; + + sha512_base_do_finalize(ctx); + for(i=0; i<SHA384_SUM_LEN / sizeof(uint64_t); i++) + PUT_UINT64_BE(ctx->state[i], digest, i * 8); +} + +/* + * Output = SHA-512( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha384_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + sha512_context ctx; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + const unsigned char *end; + unsigned char *curr; + int chunk; +#endif + + sha384_starts(&ctx); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + curr = (unsigned char *)input; + end = input + ilen; + while (curr < end) { + chunk = end - curr; + if (chunk > chunk_sz) + chunk = chunk_sz; + sha384_update(&ctx, curr, chunk); + curr += chunk; + WATCHDOG_RESET(); + } +#else + sha384_update(&ctx, input, ilen); +#endif + + sha384_finish(&ctx, output); +} + +#endif + +#if defined(CONFIG_SHA512) +void sha512_starts(sha512_context * ctx) +{ + ctx->state[0] = SHA512_H0; + ctx->state[1] = SHA512_H1; + ctx->state[2] = SHA512_H2; + ctx->state[3] = SHA512_H3; + ctx->state[4] = SHA512_H4; + ctx->state[5] = SHA512_H5; + ctx->state[6] = SHA512_H6; + ctx->state[7] = SHA512_H7; + ctx->count[0] = ctx->count[1] = 0; +} + +void sha512_update(sha512_context *ctx, const uint8_t *input, uint32_t length) +{ + sha512_base_do_update(ctx, input, length); +} + +void sha512_finish(sha512_context * ctx, uint8_t digest[SHA512_SUM_LEN]) +{ + int i; + + sha512_base_do_finalize(ctx); + for(i=0; i<SHA512_SUM_LEN / sizeof(uint64_t); i++) + PUT_UINT64_BE(ctx->state[i], digest, i * 8); +} + +/* + * Output = SHA-512( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha512_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + sha512_context ctx; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + const unsigned char *end; + unsigned char *curr; + int chunk; +#endif + + sha512_starts(&ctx); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) + curr = (unsigned char *)input; + end = input + ilen; + while (curr < end) { + chunk = end - curr; + if (chunk > chunk_sz) + chunk = chunk_sz; + sha512_update(&ctx, curr, chunk); + curr += chunk; + WATCHDOG_RESET(); + } +#else + sha512_update(&ctx, input, ilen); +#endif + + sha512_finish(&ctx, output); +} +#endif diff --git a/lib/trace.c b/lib/trace.c index ea8c8e0d40..831283c283 100644 --- a/lib/trace.c +++ b/lib/trace.c @@ -57,12 +57,12 @@ static inline uintptr_t __attribute__((no_instrument_function)) return offset / FUNC_SITE_SIZE; } -#ifdef CONFIG_EFI_LOADER +#if defined(CONFIG_EFI_LOADER) && defined(CONFIG_ARM) /** * trace_gd - the value of the gd register */ -static volatile void *trace_gd; +static volatile gd_t *trace_gd; /** * trace_save_gd() - save the value of the gd register @@ -82,10 +82,10 @@ static void __attribute__((no_instrument_function)) trace_save_gd(void) */ static void __attribute__((no_instrument_function)) trace_swap_gd(void) { - volatile void *temp_gd = trace_gd; + volatile gd_t *temp_gd = trace_gd; trace_gd = gd; - gd = temp_gd; + set_gd(temp_gd); } #else diff --git a/lib/vsprintf.c b/lib/vsprintf.c index de9ef902b9..9dc96c81c6 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -26,8 +26,6 @@ #include <linux/types.h> #include <linux/string.h> -#define noinline __attribute__((noinline)) - /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') |