diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/image-fit-sig.c | 151 | ||||
| -rw-r--r-- | boot/image-fit.c | 12 |
2 files changed, 115 insertions, 48 deletions
diff --git a/boot/image-fit-sig.c b/boot/image-fit-sig.c index 495d7768f68..a461d591a0e 100644 --- a/boot/image-fit-sig.c +++ b/boot/image-fit-sig.c @@ -65,7 +65,8 @@ struct image_region *fit_region_make_list(const void *fit, static int fit_image_setup_verify(struct image_sign_info *info, const void *fit, int noffset, - int required_keynode, char **err_msgp) + const void *key_blob, int required_keynode, + char **err_msgp) { const char *algo_name; const char *padding_name; @@ -91,7 +92,7 @@ static int fit_image_setup_verify(struct image_sign_info *info, 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->fdt_blob = key_blob; info->required_keynode = required_keynode; printf("%s:%s", algo_name, info->keyname); @@ -104,7 +105,8 @@ static int fit_image_setup_verify(struct image_sign_info *info, } int fit_image_check_sig(const void *fit, int noffset, const void *data, - size_t size, int required_keynode, char **err_msgp) + size_t size, const void *key_blob, int required_keynode, + char **err_msgp) { struct image_sign_info info; struct image_region region; @@ -112,8 +114,8 @@ int fit_image_check_sig(const void *fit, int noffset, const void *data, int fit_value_len; *err_msgp = NULL; - if (fit_image_setup_verify(&info, fit, noffset, required_keynode, - err_msgp)) + if (fit_image_setup_verify(&info, fit, noffset, key_blob, + required_keynode, err_msgp)) return -1; if (fit_image_hash_get_value(fit, noffset, &fit_value, @@ -135,7 +137,7 @@ int fit_image_check_sig(const void *fit, int noffset, const void *data, static int fit_image_verify_sig(const void *fit, int image_noffset, const char *data, size_t size, - const void *sig_blob, int sig_offset) + const void *key_blob, int key_offset) { int noffset; char *err_msg = ""; @@ -156,8 +158,8 @@ static int fit_image_verify_sig(const void *fit, int image_noffset, } if (!strncmp(name, FIT_SIG_NODENAME, strlen(FIT_SIG_NODENAME))) { - ret = fit_image_check_sig(fit, noffset, data, - size, -1, &err_msg); + ret = fit_image_check_sig(fit, noffset, data, size, + key_blob, -1, &err_msg); if (ret) { puts("- "); } else { @@ -184,34 +186,34 @@ error: int fit_image_verify_required_sigs(const void *fit, int image_noffset, const char *data, size_t size, - const void *sig_blob, int *no_sigsp) + const void *key_blob, int *no_sigsp) { int verify_count = 0; int noffset; - int sig_node; + int key_node; /* Work out what we need to verify */ *no_sigsp = 1; - sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); - if (sig_node < 0) { + key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME); + if (key_node < 0) { debug("%s: No signature node found: %s\n", __func__, - fdt_strerror(sig_node)); + fdt_strerror(key_node)); return 0; } - fdt_for_each_subnode(noffset, sig_blob, sig_node) { + fdt_for_each_subnode(noffset, key_blob, key_node) { const char *required; int ret; - required = fdt_getprop(sig_blob, noffset, FIT_KEY_REQUIRED, + required = fdt_getprop(key_blob, noffset, FIT_KEY_REQUIRED, NULL); if (!required || strcmp(required, "image")) continue; ret = fit_image_verify_sig(fit, image_noffset, data, size, - sig_blob, noffset); + key_blob, noffset); if (ret) { printf("Failed to verify required signature '%s'\n", - fit_get_name(sig_blob, noffset, NULL)); + fit_get_name(key_blob, noffset, NULL)); return ret; } verify_count++; @@ -226,20 +228,35 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset, /** * fit_config_check_sig() - Check the signature of a config * + * Here we are looking at a particular signature that needs verification (here + * signature-1): + * + * configurations { + * default = "conf-1"; + * conf-1 { + * kernel = "kernel-1"; + * fdt = "fdt-1"; + * signature-1 { + * algo = "sha1,rsa2048"; + * value = <...conf 1 signature...>; + * }; + * }; + * * @fit: FIT to check - * @noffset: Offset of configuration node (e.g. /configurations/conf-1) - * @required_keynode: Offset in the control FDT of the required key node, + * @noffset: Offset of the signature node being checked (e.g. + * /configurations/conf-1/signature-1) + * @conf_noffset: Offset of configuration node (e.g. /configurations/conf-1) + * @key_blob: Blob containing the keys to check against + * @required_keynode: Offset in @key_blob of the required key node, * if any. If this is given, then the configuration wil not * pass verification unless that key is used. If this is * -1 then any signature will do. - * @conf_noffset: Offset of the configuration subnode being checked (e.g. - * /configurations/conf-1/kernel) * @err_msgp: In the event of an error, this will be pointed to a * help error string to display to the user. * Return: 0 if all verified ok, <0 on error */ -static int fit_config_check_sig(const void *fit, int noffset, - int required_keynode, int conf_noffset, +static int fit_config_check_sig(const void *fit, int noffset, int conf_noffset, + const void *key_blob, int required_keynode, char **err_msgp) { static char * const exc_prop[] = { @@ -262,12 +279,12 @@ static int fit_config_check_sig(const void *fit, int noffset, int count; config_name = fit_get_name(fit, conf_noffset, NULL); - debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(), + debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, key_blob, fit_get_name(fit, noffset, NULL), - fit_get_name(gd_fdt_blob(), required_keynode, NULL)); + fit_get_name(key_blob, required_keynode, NULL)); *err_msgp = NULL; - if (fit_image_setup_verify(&info, fit, noffset, required_keynode, - err_msgp)) + if (fit_image_setup_verify(&info, fit, noffset, key_blob, + required_keynode, err_msgp)) return -1; if (fit_image_hash_get_value(fit, noffset, &fit_value, @@ -368,8 +385,35 @@ static int fit_config_check_sig(const void *fit, int noffset, return 0; } -static int fit_config_verify_sig(const void *fit, int conf_noffset, - const void *sig_blob, int sig_offset) +/** + * fit_config_verify_key() - Verify that a configuration is signed with a key + * + * Here we are looking at a particular configuration that needs verification: + * + * configurations { + * default = "conf-1"; + * conf-1 { + * kernel = "kernel-1"; + * fdt = "fdt-1"; + * signature-1 { + * algo = "sha1,rsa2048"; + * value = <...conf 1 signature...>; + * }; + * }; + * + * We must check each of the signature subnodes of conf-1. Hopefully one of them + * will match the key at key_offset. + * + * @fit: FIT to check + * @conf_noffset: Offset of the configuration node to check (e.g. + * /configurations/conf-1) + * @key_blob: Blob containing the keys to check against + * @key_offset: Offset of the key to check within @key_blob + * @return 0 if OK, -EPERM if any signatures did not verify, or the + * configuration node has an invalid name + */ +static int fit_config_verify_key(const void *fit, int conf_noffset, + const void *key_blob, int key_offset) { int noffset; char *err_msg = "No 'signature' subnode found"; @@ -382,8 +426,9 @@ static int fit_config_verify_sig(const void *fit, int conf_noffset, if (!strncmp(name, FIT_SIG_NODENAME, strlen(FIT_SIG_NODENAME))) { - ret = fit_config_check_sig(fit, noffset, sig_offset, - conf_noffset, &err_msg); + ret = fit_config_check_sig(fit, noffset, conf_noffset, + key_blob, key_offset, + &err_msg); if (ret) { puts("- "); } else { @@ -409,12 +454,25 @@ error: return -EPERM; } -static int fit_config_verify_required_sigs(const void *fit, int conf_noffset, - const void *sig_blob) +/** + * fit_config_verify_required_keys() - verify any required signatures for config + * + * This looks through all the signatures we expect and verifies that at least + * all the required ones are valid signatures for the configuration + * + * @fit: FIT to check + * @conf_noffset: Offset of the configuration node to check (e.g. + * /configurations/conf-1) + * @key_blob: Blob containing the keys to check against + * @return 0 if OK, -EPERM if any signatures did not verify, or the + * configuration node has an invalid name + */ +static int fit_config_verify_required_keys(const void *fit, int conf_noffset, + const void *key_blob) { const char *name = fit_get_name(fit, conf_noffset, NULL); int noffset; - int sig_node; + int key_node; int verified = 0; int reqd_sigs = 0; bool reqd_policy_all = true; @@ -430,38 +488,45 @@ static int fit_config_verify_required_sigs(const void *fit, int conf_noffset, } /* Work out what we need to verify */ - sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME); - if (sig_node < 0) { + key_node = fdt_subnode_offset(key_blob, 0, FIT_SIG_NODENAME); + if (key_node < 0) { debug("%s: No signature node found: %s\n", __func__, - fdt_strerror(sig_node)); + fdt_strerror(key_node)); return 0; } /* Get required-mode policy property from DTB */ - reqd_mode = fdt_getprop(sig_blob, sig_node, "required-mode", NULL); + reqd_mode = fdt_getprop(key_blob, key_node, "required-mode", NULL); if (reqd_mode && !strcmp(reqd_mode, "any")) reqd_policy_all = false; debug("%s: required-mode policy set to '%s'\n", __func__, reqd_policy_all ? "all" : "any"); - fdt_for_each_subnode(noffset, sig_blob, sig_node) { + /* + * The algorithm here is a little convoluted due to how we want it to + * work. Here we work through each of the signature nodes in the + * public-key area. These are in the U-Boot control devicetree. Each + * node was created by signing a configuration, so we check if it is + * 'required' and if so, request that it be verified. + */ + fdt_for_each_subnode(noffset, key_blob, key_node) { const char *required; int ret; - required = fdt_getprop(sig_blob, noffset, FIT_KEY_REQUIRED, + required = fdt_getprop(key_blob, noffset, FIT_KEY_REQUIRED, NULL); if (!required || strcmp(required, "conf")) continue; reqd_sigs++; - ret = fit_config_verify_sig(fit, conf_noffset, sig_blob, + ret = fit_config_verify_key(fit, conf_noffset, key_blob, noffset); if (ret) { if (reqd_policy_all) { printf("Failed to verify required signature '%s'\n", - fit_get_name(sig_blob, noffset, NULL)); + fit_get_name(key_blob, noffset, NULL)); return ret; } } else { @@ -481,6 +546,6 @@ static int fit_config_verify_required_sigs(const void *fit, int conf_noffset, int fit_config_verify(const void *fit, int conf_noffset) { - return fit_config_verify_required_sigs(fit, conf_noffset, + return fit_config_verify_required_keys(fit, conf_noffset, gd_fdt_blob()); } diff --git a/boot/image-fit.c b/boot/image-fit.c index 85a6f223c85..f01cafe4e27 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -1309,7 +1309,8 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data, } int fit_image_verify_with_data(const void *fit, int image_noffset, - const void *data, size_t size) + const void *key_blob, const void *data, + size_t size) { int noffset = 0; char *err_msg = ""; @@ -1319,7 +1320,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset, /* Verify all required signatures */ if (FIT_IMAGE_ENABLE_VERIFY && fit_image_verify_required_sigs(fit, image_noffset, data, size, - gd_fdt_blob(), &verify_all)) { + key_blob, &verify_all)) { err_msg = "Unable to verify required signature"; goto error; } @@ -1342,8 +1343,8 @@ int fit_image_verify_with_data(const void *fit, int image_noffset, } else if (FIT_IMAGE_ENABLE_VERIFY && verify_all && !strncmp(name, FIT_SIG_NODENAME, strlen(FIT_SIG_NODENAME))) { - ret = fit_image_check_sig(fit, noffset, data, - size, -1, &err_msg); + ret = fit_image_check_sig(fit, noffset, data, size, + gd_fdt_blob(), -1, &err_msg); /* * Show an indication on failure, but do not return @@ -1406,7 +1407,8 @@ int fit_image_verify(const void *fit, int image_noffset) goto err; } - return fit_image_verify_with_data(fit, image_noffset, data, size); + return fit_image_verify_with_data(fit, image_noffset, gd_fdt_blob(), + data, size); err: printf("error!\n%s in '%s' image node\n", err_msg, |
