X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fimage-sig.c;h=004fbc525b5c0dcac81e6fcf974f52806cdd1898;hb=42b4d14e34322cba4f4c855fff43688a89c0fbeb;hp=48788f9100023bc4a41ce345c8d04cfbde45e816;hpb=12df2abe3e159d622701611766c085b860329f78;p=oweals%2Fu-boot.git diff --git a/common/image-sig.c b/common/image-sig.c index 48788f9100..004fbc525b 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -1,7 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2013, Google Inc. - * - * SPDX-License-Identifier: GPL-2.0+ */ #ifdef USE_HOSTCC @@ -13,8 +12,8 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include -#include -#include +#include +#include #define IMAGE_MAX_HASHED_NODES 100 @@ -32,70 +31,104 @@ void *image_get_host_blob(void) struct checksum_algo checksum_algos[] = { { - "sha1", - SHA1_SUM_LEN, - RSA2048_BYTES, -#if IMAGE_ENABLE_SIGN - EVP_sha1, -#endif - sha1_calculate, - padding_sha1_rsa2048, - }, - { - "sha256", - SHA256_SUM_LEN, - RSA2048_BYTES, + .name = "sha1", + .checksum_len = SHA1_SUM_LEN, + .der_len = SHA1_DER_LEN, + .der_prefix = sha1_der_prefix, #if IMAGE_ENABLE_SIGN - EVP_sha256, + .calculate_sign = EVP_sha1, #endif - sha256_calculate, - padding_sha256_rsa2048, + .calculate = hash_calculate, }, { - "sha256", - SHA256_SUM_LEN, - RSA4096_BYTES, + .name = "sha256", + .checksum_len = SHA256_SUM_LEN, + .der_len = SHA256_DER_LEN, + .der_prefix = sha256_der_prefix, #if IMAGE_ENABLE_SIGN - EVP_sha256, + .calculate_sign = EVP_sha256, #endif - sha256_calculate, - padding_sha256_rsa4096, + .calculate = hash_calculate, } }; -struct image_sig_algo image_sig_algos[] = { +struct crypto_algo crypto_algos[] = { { - "sha1,rsa2048", - rsa_sign, - rsa_add_verify_data, - rsa_verify, - &checksum_algos[0], + .name = "rsa2048", + .key_len = RSA2048_BYTES, + .sign = rsa_sign, + .add_verify_data = rsa_add_verify_data, + .verify = rsa_verify, }, { - "sha256,rsa2048", - rsa_sign, - rsa_add_verify_data, - rsa_verify, - &checksum_algos[1], + .name = "rsa4096", + .key_len = RSA4096_BYTES, + .sign = rsa_sign, + .add_verify_data = rsa_add_verify_data, + .verify = rsa_verify, + } + +}; + +struct padding_algo padding_algos[] = { + { + .name = "pkcs-1.5", + .verify = padding_pkcs_15_verify, }, +#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT { - "sha256,rsa4096", - rsa_sign, - rsa_add_verify_data, - rsa_verify, - &checksum_algos[2], + .name = "pss", + .verify = padding_pss_verify, } - +#endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */ }; -struct image_sig_algo *image_get_sig_algo(const char *name) +struct checksum_algo *image_get_checksum_algo(const char *full_name) { int i; + const char *name; + + for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) { + name = checksum_algos[i].name; + /* Make sure names match and next char is a comma */ + if (!strncmp(name, full_name, strlen(name)) && + full_name[strlen(name)] == ',') + return &checksum_algos[i]; + } + + return NULL; +} - for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) { - if (!strcmp(image_sig_algos[i].name, name)) - return &image_sig_algos[i]; +struct crypto_algo *image_get_crypto_algo(const char *full_name) +{ + int i; + const char *name; + + /* Move name to after the comma */ + name = strchr(full_name, ','); + if (!name) + return NULL; + name += 1; + + for (i = 0; i < ARRAY_SIZE(crypto_algos); i++) { + if (!strcmp(crypto_algos[i].name, name)) + return &crypto_algos[i]; + } + + return NULL; +} + +struct padding_algo *image_get_padding_algo(const char *name) +{ + int i; + + if (!name) + return NULL; + + for (i = 0; i < ARRAY_SIZE(padding_algos); i++) { + if (!strcmp(padding_algos[i].name, name)) + return &padding_algos[i]; } return NULL; @@ -150,21 +183,35 @@ static int fit_image_setup_verify(struct image_sign_info *info, char **err_msgp) { char *algo_name; + const char *padding_name; + + if (fdt_totalsize(fit) > CONFIG_FIT_SIGNATURE_MAX_SIZE) { + *err_msgp = "Total size too large"; + return 1; + } if (fit_image_hash_get_algo(fit, noffset, &algo_name)) { *err_msgp = "Can't get hash algo property"; return -1; } + + padding_name = fdt_getprop(fit, noffset, "padding", NULL); + if (!padding_name) + padding_name = RSA_DEFAULT_PADDING_NAME; + memset(info, '\0', sizeof(*info)); info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL); info->fit = (void *)fit; info->node_offset = noffset; - info->algo = image_get_sig_algo(algo_name); + info->name = algo_name; + info->checksum = image_get_checksum_algo(algo_name); + info->crypto = image_get_crypto_algo(algo_name); + info->padding = image_get_padding_algo(padding_name); info->fdt_blob = gd_fdt_blob(); info->required_keynode = required_keynode; printf("%s:%s", algo_name, info->keyname); - if (!info->algo) { + if (!info->checksum || !info->crypto || !info->padding) { *err_msgp = "Unknown signature algorithm"; return -1; } @@ -194,7 +241,7 @@ int fit_image_check_sig(const void *fit, int noffset, const void *data, region.data = data; region.size = size; - if (info.algo->verify(&info, ®ion, 1, fit_value, fit_value_len)) { + if (info.crypto->verify(&info, ®ion, 1, fit_value, fit_value_len)) { *err_msgp = "Verification failed"; return -1; } @@ -212,9 +259,7 @@ static int fit_image_verify_sig(const void *fit, int image_noffset, int ret; /* Process all hash subnodes of the component image node */ - for (noffset = fdt_first_subnode(fit, image_noffset); - noffset >= 0; - noffset = fdt_next_subnode(fit, noffset)) { + fdt_for_each_subnode(noffset, fit, image_noffset) { const char *name = fit_get_name(fit, noffset, NULL); if (!strncmp(name, FIT_SIG_NODENAME, @@ -262,9 +307,7 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset, return 0; } - for (noffset = fdt_first_subnode(sig_blob, sig_node); - noffset >= 0; - noffset = fdt_next_subnode(sig_blob, noffset)) { + fdt_for_each_subnode(noffset, sig_blob, sig_node) { const char *required; int ret; @@ -326,6 +369,11 @@ int fit_config_check_sig(const void *fit, int noffset, int required_keynode, return -1; } + if (prop && prop_len > 0 && prop[prop_len - 1] != '\0') { + *err_msgp = "hashed-nodes property must be null-terminated"; + return -1; + } + /* Add a sanity check here since we are using the stack */ if (count > IMAGE_MAX_HASHED_NODES) { *err_msgp = "Number of hashed nodes exceeds maximum"; @@ -343,7 +391,7 @@ int fit_config_check_sig(const void *fit, int noffset, int required_keynode, /* * Each node can generate one region for each sub-node. Allow for - * 7 sub-nodes (hash@1, signature@1, etc.) and some extra. + * 7 sub-nodes (hash-1, signature-1, etc.) and some extra. */ max_regions = 20 + count * 7; struct fdt_region fdt_regions[max_regions]; @@ -369,8 +417,11 @@ int fit_config_check_sig(const void *fit, int noffset, int required_keynode, /* Add the strings */ strings = fdt_getprop(fit, noffset, "hashed-strings", NULL); if (strings) { - fdt_regions[count].offset = fdt_off_dt_strings(fit) + - fdt32_to_cpu(strings[0]); + /* + * The strings region offset must be a static 0x0. + * This is set in tool/image-host.c + */ + fdt_regions[count].offset = fdt_off_dt_strings(fit); fdt_regions[count].size = fdt32_to_cpu(strings[1]); count++; } @@ -379,8 +430,8 @@ int fit_config_check_sig(const void *fit, int noffset, int required_keynode, struct image_region region[count]; fit_region_make_list(fit, fdt_regions, count, region); - if (info.algo->verify(&info, region, count, fit_value, - fit_value_len)) { + if (info.crypto->verify(&info, region, count, fit_value, + fit_value_len)) { *err_msgp = "Verification failed"; return -1; } @@ -397,9 +448,7 @@ static int fit_config_verify_sig(const void *fit, int conf_noffset, int ret; /* Process all hash subnodes of the component conf node */ - for (noffset = fdt_first_subnode(fit, conf_noffset); - noffset >= 0; - noffset = fdt_next_subnode(fit, noffset)) { + fdt_for_each_subnode(noffset, fit, conf_noffset) { const char *name = fit_get_name(fit, noffset, NULL); if (!strncmp(name, FIT_SIG_NODENAME, @@ -444,9 +493,7 @@ int fit_config_verify_required_sigs(const void *fit, int conf_noffset, return 0; } - for (noffset = fdt_first_subnode(sig_blob, sig_node); - noffset >= 0; - noffset = fdt_next_subnode(sig_blob, noffset)) { + fdt_for_each_subnode(noffset, sig_blob, sig_node) { const char *required; int ret;