lib: rsa: decouple rsa from FIT image verification
authorAKASHI Takahiro <takahiro.akashi@linaro.org>
Fri, 21 Feb 2020 06:12:55 +0000 (15:12 +0900)
committerTom Rini <trini@konsulko.com>
Thu, 12 Mar 2020 12:20:38 +0000 (08:20 -0400)
Introduce new configuration, CONFIG_RSA_VERIFY which will decouple building
RSA functions from FIT verification and allow for adding a RSA-based
signature verification for other file formats, in particular PE file
for UEFI secure boot.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Kconfig
common/Kconfig
common/Makefile
common/image-fit-sig.c [new file with mode: 0644]
common/image-fit.c
common/image-sig.c
include/image.h
lib/rsa/Kconfig
lib/rsa/Makefile
lib/rsa/rsa-verify.c
tools/Makefile

diff --git a/Kconfig b/Kconfig
index 66148ce477908e3129c9e3b3804c7fb7fbc1855b..e2387b2ff8e7c4de2cc8104944fd952e8bfeb2e6 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -354,6 +354,8 @@ config FIT_SIGNATURE
        depends on DM
        select HASH
        select RSA
+       select RSA_VERIFY
+       select IMAGE_SIGN_INFO
        help
          This option enables signature verification of FIT uImages,
          using a hash signed and verified using RSA. If
@@ -442,6 +444,8 @@ config SPL_FIT_SIGNATURE
        depends on SPL_DM
        select SPL_FIT
        select SPL_RSA
+       select SPL_RSA_VERIFY
+       select IMAGE_SIGN_INFO
 
 config SPL_LOAD_FIT
        bool "Enable SPL loading U-Boot as a FIT (basic fitImage features)"
index 46e4193fc83a2a798ef08d2d7b1972efdb77de36..a2a9b8deed29b7d4adf6a53dacfa39f75eeb0ddb 100644 (file)
@@ -1045,3 +1045,10 @@ config BLOBLIST_ADDR
 endmenu
 
 source "common/spl/Kconfig"
+
+config IMAGE_SIGN_INFO
+       bool
+       select SHA1
+       select SHA256
+       help
+         Enable image_sign_info helper functions.
index 896e4af91d4cdaeb5ad0d7086a60777ed55d0aad..702f2396cf466119f47aa218643a4d5dc9d7dd92 100644 (file)
@@ -112,7 +112,8 @@ obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
 obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
 obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
 obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
-obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-sig.o
+obj-$(CONFIG_IMAGE_SIGN_INFO) += image-sig.o
+obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-fit-sig.o
 obj-$(CONFIG_$(SPL_TPL_)FIT_CIPHER) += image-cipher.o
 obj-$(CONFIG_IO_TRACE) += iotrace.o
 obj-y += memsize.o
diff --git a/common/image-fit-sig.c b/common/image-fit-sig.c
new file mode 100644 (file)
index 0000000..f6caeb0
--- /dev/null
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013, Google Inc.
+ */
+
+#ifdef USE_HOSTCC
+#include "mkimage.h"
+#include <time.h>
+#else
+#include <common.h>
+#include <malloc.h>
+DECLARE_GLOBAL_DATA_PTR;
+#endif /* !USE_HOSTCC*/
+#include <image.h>
+#include <u-boot/rsa.h>
+#include <u-boot/rsa-checksum.h>
+
+#define IMAGE_MAX_HASHED_NODES         100
+
+#ifdef USE_HOSTCC
+void *host_blob;
+
+void image_set_host_blob(void *blob)
+{
+       host_blob = blob;
+}
+
+void *image_get_host_blob(void)
+{
+       return host_blob;
+}
+#endif
+
+/**
+ * fit_region_make_list() - Make a list of image regions
+ *
+ * Given a list of fdt_regions, create a list of image_regions. This is a
+ * simple conversion routine since the FDT and image code use different
+ * structures.
+ *
+ * @fit: FIT image
+ * @fdt_regions: Pointer to FDT regions
+ * @count: Number of FDT regions
+ * @region: Pointer to image regions, which must hold @count records. If
+ * region is NULL, then (except for an SPL build) the array will be
+ * allocated.
+ * @return: Pointer to image regions
+ */
+struct image_region *fit_region_make_list(const void *fit,
+                                         struct fdt_region *fdt_regions,
+                                         int count,
+                                         struct image_region *region)
+{
+       int i;
+
+       debug("Hash regions:\n");
+       debug("%10s %10s\n", "Offset", "Size");
+
+       /*
+        * Use malloc() except in SPL (to save code size). In SPL the caller
+        * must allocate the array.
+        */
+#ifndef CONFIG_SPL_BUILD
+       if (!region)
+               region = calloc(sizeof(*region), count);
+#endif
+       if (!region)
+               return NULL;
+       for (i = 0; i < count; i++) {
+               debug("%10x %10x\n", fdt_regions[i].offset,
+                     fdt_regions[i].size);
+               region[i].data = fit + fdt_regions[i].offset;
+               region[i].size = fdt_regions[i].size;
+       }
+
+       return region;
+}
+
+static int fit_image_setup_verify(struct image_sign_info *info,
+                                 const void *fit, int noffset,
+                                 int required_keynode, 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->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->checksum || !info->crypto || !info->padding) {
+               *err_msgp = "Unknown signature algorithm";
+               return -1;
+       }
+
+       return 0;
+}
+
+int fit_image_check_sig(const void *fit, int noffset, const void *data,
+                       size_t size, int required_keynode, char **err_msgp)
+{
+       struct image_sign_info info;
+       struct image_region region;
+       uint8_t *fit_value;
+       int fit_value_len;
+
+       *err_msgp = NULL;
+       if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+                                  err_msgp))
+               return -1;
+
+       if (fit_image_hash_get_value(fit, noffset, &fit_value,
+                                    &fit_value_len)) {
+               *err_msgp = "Can't get hash value property";
+               return -1;
+       }
+
+       region.data = data;
+       region.size = size;
+
+       if (info.crypto->verify(&info, &region, 1, fit_value, fit_value_len)) {
+               *err_msgp = "Verification failed";
+               return -1;
+       }
+
+       return 0;
+}
+
+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)
+{
+       int noffset;
+       char *err_msg = "";
+       int verified = 0;
+       int ret;
+
+       /* Process all hash subnodes of the component image node */
+       fdt_for_each_subnode(noffset, fit, image_noffset) {
+               const char *name = fit_get_name(fit, noffset, NULL);
+
+               if (!strncmp(name, FIT_SIG_NODENAME,
+                            strlen(FIT_SIG_NODENAME))) {
+                       ret = fit_image_check_sig(fit, noffset, data,
+                                                 size, -1, &err_msg);
+                       if (ret) {
+                               puts("- ");
+                       } else {
+                               puts("+ ");
+                               verified = 1;
+                               break;
+                       }
+               }
+       }
+
+       if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+               err_msg = "Corrupted or truncated tree";
+               goto error;
+       }
+
+       return verified ? 0 : -EPERM;
+
+error:
+       printf(" error!\n%s for '%s' hash node in '%s' image node\n",
+              err_msg, fit_get_name(fit, noffset, NULL),
+              fit_get_name(fit, image_noffset, NULL));
+       return -1;
+}
+
+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)
+{
+       int verify_count = 0;
+       int noffset;
+       int sig_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) {
+               debug("%s: No signature node found: %s\n", __func__,
+                     fdt_strerror(sig_node));
+               return 0;
+       }
+
+       fdt_for_each_subnode(noffset, sig_blob, sig_node) {
+               const char *required;
+               int ret;
+
+               required = fdt_getprop(sig_blob, noffset, "required", NULL);
+               if (!required || strcmp(required, "image"))
+                       continue;
+               ret = fit_image_verify_sig(fit, image_noffset, data, size,
+                                          sig_blob, noffset);
+               if (ret) {
+                       printf("Failed to verify required signature '%s'\n",
+                              fit_get_name(sig_blob, noffset, NULL));
+                       return ret;
+               }
+               verify_count++;
+       }
+
+       if (verify_count)
+               *no_sigsp = 0;
+
+       return 0;
+}
+
+int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
+                        char **err_msgp)
+{
+       char * const exc_prop[] = {"data"};
+       const char *prop, *end, *name;
+       struct image_sign_info info;
+       const uint32_t *strings;
+       uint8_t *fit_value;
+       int fit_value_len;
+       int max_regions;
+       int i, prop_len;
+       char path[200];
+       int count;
+
+       debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
+             fit_get_name(fit, noffset, NULL),
+             fit_get_name(gd_fdt_blob(), required_keynode, NULL));
+       *err_msgp = NULL;
+       if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+                                  err_msgp))
+               return -1;
+
+       if (fit_image_hash_get_value(fit, noffset, &fit_value,
+                                    &fit_value_len)) {
+               *err_msgp = "Can't get hash value property";
+               return -1;
+       }
+
+       /* Count the number of strings in the property */
+       prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
+       end = prop ? prop + prop_len : prop;
+       for (name = prop, count = 0; name < end; name++)
+               if (!*name)
+                       count++;
+       if (!count) {
+               *err_msgp = "Can't get hashed-nodes property";
+               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";
+               return -1;
+       }
+
+       /* Create a list of node names from those strings */
+       char *node_inc[count];
+
+       debug("Hash nodes (%d):\n", count);
+       for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
+               debug("   '%s'\n", name);
+               node_inc[i] = (char *)name;
+       }
+
+       /*
+        * Each node can generate one region for each sub-node. Allow for
+        * 7 sub-nodes (hash-1, signature-1, etc.) and some extra.
+        */
+       max_regions = 20 + count * 7;
+       struct fdt_region fdt_regions[max_regions];
+
+       /* Get a list of regions to hash */
+       count = fdt_find_regions(fit, node_inc, count,
+                                exc_prop, ARRAY_SIZE(exc_prop),
+                                fdt_regions, max_regions - 1,
+                                path, sizeof(path), 0);
+       if (count < 0) {
+               *err_msgp = "Failed to hash configuration";
+               return -1;
+       }
+       if (count == 0) {
+               *err_msgp = "No data to hash";
+               return -1;
+       }
+       if (count >= max_regions - 1) {
+               *err_msgp = "Too many hash regions";
+               return -1;
+       }
+
+       /* Add the strings */
+       strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
+       if (strings) {
+               /*
+                * 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++;
+       }
+
+       /* Allocate the region list on the stack */
+       struct image_region region[count];
+
+       fit_region_make_list(fit, fdt_regions, count, region);
+       if (info.crypto->verify(&info, region, count, fit_value,
+                               fit_value_len)) {
+               *err_msgp = "Verification failed";
+               return -1;
+       }
+
+       return 0;
+}
+
+static int fit_config_verify_sig(const void *fit, int conf_noffset,
+                                const void *sig_blob, int sig_offset)
+{
+       int noffset;
+       char *err_msg = "";
+       int verified = 0;
+       int ret;
+
+       /* Process all hash subnodes of the component conf node */
+       fdt_for_each_subnode(noffset, fit, conf_noffset) {
+               const char *name = fit_get_name(fit, noffset, NULL);
+
+               if (!strncmp(name, FIT_SIG_NODENAME,
+                            strlen(FIT_SIG_NODENAME))) {
+                       ret = fit_config_check_sig(fit, noffset, sig_offset,
+                                                  &err_msg);
+                       if (ret) {
+                               puts("- ");
+                       } else {
+                               puts("+ ");
+                               verified = 1;
+                               break;
+                       }
+               }
+       }
+
+       if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+               err_msg = "Corrupted or truncated tree";
+               goto error;
+       }
+
+       return verified ? 0 : -EPERM;
+
+error:
+       printf(" error!\n%s for '%s' hash node in '%s' config node\n",
+              err_msg, fit_get_name(fit, noffset, NULL),
+              fit_get_name(fit, conf_noffset, NULL));
+       return -1;
+}
+
+int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
+                                   const void *sig_blob)
+{
+       int noffset;
+       int sig_node;
+
+       /* Work out what we need to verify */
+       sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
+       if (sig_node < 0) {
+               debug("%s: No signature node found: %s\n", __func__,
+                     fdt_strerror(sig_node));
+               return 0;
+       }
+
+       fdt_for_each_subnode(noffset, sig_blob, sig_node) {
+               const char *required;
+               int ret;
+
+               required = fdt_getprop(sig_blob, noffset, "required", NULL);
+               if (!required || strcmp(required, "conf"))
+                       continue;
+               ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
+                                           noffset);
+               if (ret) {
+                       printf("Failed to verify required signature '%s'\n",
+                              fit_get_name(sig_blob, noffset, NULL));
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+int fit_config_verify(const void *fit, int conf_noffset)
+{
+       return fit_config_verify_required_sigs(fit, conf_noffset,
+                                              gd_fdt_blob());
+}
index f3bb00c98a55d966c3e68869bd180db8a6fefcc9..9357e66e1f9e648ac3f8c03d0ab2ef040ad3318e 100644 (file)
@@ -1269,7 +1269,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
        int ret;
 
        /* Verify all required signatures */
-       if (IMAGE_ENABLE_VERIFY &&
+       if (FIT_IMAGE_ENABLE_VERIFY &&
            fit_image_verify_required_sigs(fit, image_noffset, data, size,
                                           gd_fdt_blob(), &verify_all)) {
                err_msg = "Unable to verify required signature";
@@ -1291,7 +1291,7 @@ int fit_image_verify_with_data(const void *fit, int image_noffset,
                                                 &err_msg))
                                goto error;
                        puts("+ ");
-               } else if (IMAGE_ENABLE_VERIFY && verify_all &&
+               } 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,
@@ -1949,7 +1949,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
                if (image_type == IH_TYPE_KERNEL)
                        images->fit_uname_cfg = fit_base_uname_config;
 
-               if (IMAGE_ENABLE_VERIFY && images->verify) {
+               if (FIT_IMAGE_ENABLE_VERIFY && images->verify) {
                        puts("   Verifying Hash Integrity ... ");
                        if (fit_config_verify(fit, cfg_noffset)) {
                                puts("Bad Data Hash\n");
index 639a1124504f5c0450e950912e98e8f5c1023fa0..84b2c0439cf8965a6a7e55cd0a2ec316f4c475ed 100644 (file)
@@ -17,18 +17,6 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #define IMAGE_MAX_HASHED_NODES         100
 
-#ifdef USE_HOSTCC
-void *host_blob;
-void image_set_host_blob(void *blob)
-{
-       host_blob = blob;
-}
-void *image_get_host_blob(void)
-{
-       return host_blob;
-}
-#endif
-
 struct checksum_algo checksum_algos[] = {
        {
                .name = "sha1",
@@ -162,387 +150,3 @@ struct padding_algo *image_get_padding_algo(const char *name)
 
        return NULL;
 }
-
-/**
- * fit_region_make_list() - Make a list of image regions
- *
- * Given a list of fdt_regions, create a list of image_regions. This is a
- * simple conversion routine since the FDT and image code use different
- * structures.
- *
- * @fit: FIT image
- * @fdt_regions: Pointer to FDT regions
- * @count: Number of FDT regions
- * @region: Pointer to image regions, which must hold @count records. If
- * region is NULL, then (except for an SPL build) the array will be
- * allocated.
- * @return: Pointer to image regions
- */
-struct image_region *fit_region_make_list(const void *fit,
-               struct fdt_region *fdt_regions, int count,
-               struct image_region *region)
-{
-       int i;
-
-       debug("Hash regions:\n");
-       debug("%10s %10s\n", "Offset", "Size");
-
-       /*
-        * Use malloc() except in SPL (to save code size). In SPL the caller
-        * must allocate the array.
-        */
-#ifndef CONFIG_SPL_BUILD
-       if (!region)
-               region = calloc(sizeof(*region), count);
-#endif
-       if (!region)
-               return NULL;
-       for (i = 0; i < count; i++) {
-               debug("%10x %10x\n", fdt_regions[i].offset,
-                     fdt_regions[i].size);
-               region[i].data = fit + fdt_regions[i].offset;
-               region[i].size = fdt_regions[i].size;
-       }
-
-       return region;
-}
-
-static int fit_image_setup_verify(struct image_sign_info *info,
-               const void *fit, int noffset, int required_keynode,
-               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->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->checksum || !info->crypto || !info->padding) {
-               *err_msgp = "Unknown signature algorithm";
-               return -1;
-       }
-
-       return 0;
-}
-
-int fit_image_check_sig(const void *fit, int noffset, const void *data,
-               size_t size, int required_keynode, char **err_msgp)
-{
-       struct image_sign_info info;
-       struct image_region region;
-       uint8_t *fit_value;
-       int fit_value_len;
-
-       *err_msgp = NULL;
-       if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
-                                  err_msgp))
-               return -1;
-
-       if (fit_image_hash_get_value(fit, noffset, &fit_value,
-                                    &fit_value_len)) {
-               *err_msgp = "Can't get hash value property";
-               return -1;
-       }
-
-       region.data = data;
-       region.size = size;
-
-       if (info.crypto->verify(&info, &region, 1, fit_value, fit_value_len)) {
-               *err_msgp = "Verification failed";
-               return -1;
-       }
-
-       return 0;
-}
-
-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)
-{
-       int noffset;
-       char *err_msg = "";
-       int verified = 0;
-       int ret;
-
-       /* Process all hash subnodes of the component image node */
-       fdt_for_each_subnode(noffset, fit, image_noffset) {
-               const char *name = fit_get_name(fit, noffset, NULL);
-
-               if (!strncmp(name, FIT_SIG_NODENAME,
-                            strlen(FIT_SIG_NODENAME))) {
-                       ret = fit_image_check_sig(fit, noffset, data,
-                                                       size, -1, &err_msg);
-                       if (ret) {
-                               puts("- ");
-                       } else {
-                               puts("+ ");
-                               verified = 1;
-                               break;
-                       }
-               }
-       }
-
-       if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
-               err_msg = "Corrupted or truncated tree";
-               goto error;
-       }
-
-       return verified ? 0 : -EPERM;
-
-error:
-       printf(" error!\n%s for '%s' hash node in '%s' image node\n",
-              err_msg, fit_get_name(fit, noffset, NULL),
-              fit_get_name(fit, image_noffset, NULL));
-       return -1;
-}
-
-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)
-{
-       int verify_count = 0;
-       int noffset;
-       int sig_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) {
-               debug("%s: No signature node found: %s\n", __func__,
-                     fdt_strerror(sig_node));
-               return 0;
-       }
-
-       fdt_for_each_subnode(noffset, sig_blob, sig_node) {
-               const char *required;
-               int ret;
-
-               required = fdt_getprop(sig_blob, noffset, "required", NULL);
-               if (!required || strcmp(required, "image"))
-                       continue;
-               ret = fit_image_verify_sig(fit, image_noffset, data, size,
-                                       sig_blob, noffset);
-               if (ret) {
-                       printf("Failed to verify required signature '%s'\n",
-                              fit_get_name(sig_blob, noffset, NULL));
-                       return ret;
-               }
-               verify_count++;
-       }
-
-       if (verify_count)
-               *no_sigsp = 0;
-
-       return 0;
-}
-
-int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
-                        char **err_msgp)
-{
-       char * const exc_prop[] = {"data"};
-       const char *prop, *end, *name;
-       struct image_sign_info info;
-       const uint32_t *strings;
-       uint8_t *fit_value;
-       int fit_value_len;
-       int max_regions;
-       int i, prop_len;
-       char path[200];
-       int count;
-
-       debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
-             fit_get_name(fit, noffset, NULL),
-             fit_get_name(gd_fdt_blob(), required_keynode, NULL));
-       *err_msgp = NULL;
-       if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
-                                  err_msgp))
-               return -1;
-
-       if (fit_image_hash_get_value(fit, noffset, &fit_value,
-                                    &fit_value_len)) {
-               *err_msgp = "Can't get hash value property";
-               return -1;
-       }
-
-       /* Count the number of strings in the property */
-       prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
-       end = prop ? prop + prop_len : prop;
-       for (name = prop, count = 0; name < end; name++)
-               if (!*name)
-                       count++;
-       if (!count) {
-               *err_msgp = "Can't get hashed-nodes property";
-               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";
-               return -1;
-       }
-
-       /* Create a list of node names from those strings */
-       char *node_inc[count];
-
-       debug("Hash nodes (%d):\n", count);
-       for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
-               debug("   '%s'\n", name);
-               node_inc[i] = (char *)name;
-       }
-
-       /*
-        * Each node can generate one region for each sub-node. Allow for
-        * 7 sub-nodes (hash-1, signature-1, etc.) and some extra.
-        */
-       max_regions = 20 + count * 7;
-       struct fdt_region fdt_regions[max_regions];
-
-       /* Get a list of regions to hash */
-       count = fdt_find_regions(fit, node_inc, count,
-                       exc_prop, ARRAY_SIZE(exc_prop),
-                       fdt_regions, max_regions - 1,
-                       path, sizeof(path), 0);
-       if (count < 0) {
-               *err_msgp = "Failed to hash configuration";
-               return -1;
-       }
-       if (count == 0) {
-               *err_msgp = "No data to hash";
-               return -1;
-       }
-       if (count >= max_regions - 1) {
-               *err_msgp = "Too many hash regions";
-               return -1;
-       }
-
-       /* Add the strings */
-       strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
-       if (strings) {
-               /*
-                * 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++;
-       }
-
-       /* Allocate the region list on the stack */
-       struct image_region region[count];
-
-       fit_region_make_list(fit, fdt_regions, count, region);
-       if (info.crypto->verify(&info, region, count, fit_value,
-                               fit_value_len)) {
-               *err_msgp = "Verification failed";
-               return -1;
-       }
-
-       return 0;
-}
-
-static int fit_config_verify_sig(const void *fit, int conf_noffset,
-               const void *sig_blob, int sig_offset)
-{
-       int noffset;
-       char *err_msg = "";
-       int verified = 0;
-       int ret;
-
-       /* Process all hash subnodes of the component conf node */
-       fdt_for_each_subnode(noffset, fit, conf_noffset) {
-               const char *name = fit_get_name(fit, noffset, NULL);
-
-               if (!strncmp(name, FIT_SIG_NODENAME,
-                            strlen(FIT_SIG_NODENAME))) {
-                       ret = fit_config_check_sig(fit, noffset, sig_offset,
-                                                  &err_msg);
-                       if (ret) {
-                               puts("- ");
-                       } else {
-                               puts("+ ");
-                               verified = 1;
-                               break;
-                       }
-               }
-       }
-
-       if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
-               err_msg = "Corrupted or truncated tree";
-               goto error;
-       }
-
-       return verified ? 0 : -EPERM;
-
-error:
-       printf(" error!\n%s for '%s' hash node in '%s' config node\n",
-              err_msg, fit_get_name(fit, noffset, NULL),
-              fit_get_name(fit, conf_noffset, NULL));
-       return -1;
-}
-
-int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
-               const void *sig_blob)
-{
-       int noffset;
-       int sig_node;
-
-       /* Work out what we need to verify */
-       sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
-       if (sig_node < 0) {
-               debug("%s: No signature node found: %s\n", __func__,
-                     fdt_strerror(sig_node));
-               return 0;
-       }
-
-       fdt_for_each_subnode(noffset, sig_blob, sig_node) {
-               const char *required;
-               int ret;
-
-               required = fdt_getprop(sig_blob, noffset, "required", NULL);
-               if (!required || strcmp(required, "conf"))
-                       continue;
-               ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
-                                           noffset);
-               if (ret) {
-                       printf("Failed to verify required signature '%s'\n",
-                              fit_get_name(sig_blob, noffset, NULL));
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-int fit_config_verify(const void *fit, int conf_noffset)
-{
-       return fit_config_verify_required_sigs(fit, conf_noffset,
-                                              gd_fdt_blob());
-}
index 645daeea507bdbb602be3e0cecef7e7137b820c2..928d9d5069e15d4d0b0de1e35cab23bf7760f453 100644 (file)
@@ -1114,6 +1114,7 @@ int fit_conf_get_prop_node(const void *fit, int noffset,
 
 int fit_check_ramdisk(const void *fit, int os_noffset,
                uint8_t arch, int verify);
+#endif /* IMAGE_ENABLE_FIT */
 
 int calculate_hash(const void *data, int data_len, const char *algo,
                        uint8_t *value, int *value_len);
@@ -1126,16 +1127,20 @@ int calculate_hash(const void *data, int data_len, const char *algo,
 # if defined(CONFIG_FIT_SIGNATURE)
 #  define IMAGE_ENABLE_SIGN    1
 #  define IMAGE_ENABLE_VERIFY  1
+#  define FIT_IMAGE_ENABLE_VERIFY      1
 #  include <openssl/evp.h>
 # else
 #  define IMAGE_ENABLE_SIGN    0
 #  define IMAGE_ENABLE_VERIFY  0
+#  define FIT_IMAGE_ENABLE_VERIFY      0
 # endif
 #else
 # define IMAGE_ENABLE_SIGN     0
-# define IMAGE_ENABLE_VERIFY   CONFIG_IS_ENABLED(FIT_SIGNATURE)
+# define IMAGE_ENABLE_VERIFY           CONFIG_IS_ENABLED(RSA_VERIFY)
+# define FIT_IMAGE_ENABLE_VERIFY       CONFIG_IS_ENABLED(FIT_SIGNATURE)
 #endif
 
+#if IMAGE_ENABLE_FIT
 #ifdef USE_HOSTCC
 void *image_get_host_blob(void);
 void image_set_host_blob(void *host_blob);
@@ -1149,6 +1154,7 @@ void image_set_host_blob(void *host_blob);
 #else
 #define IMAGE_ENABLE_BEST_MATCH        0
 #endif
+#endif /* IMAGE_ENABLE_FIT */
 
 /* Information passed to the signing routines */
 struct image_sign_info {
@@ -1166,16 +1172,12 @@ struct image_sign_info {
        const char *engine_id;          /* Engine to use for signing */
 };
 
-#endif /* Allow struct image_region to always be defined for rsa.h */
-
 /* A part of an image, used for hashing */
 struct image_region {
        const void *data;
        int size;
 };
 
-#if IMAGE_ENABLE_FIT
-
 #if IMAGE_ENABLE_VERIFY
 # include <u-boot/rsa-checksum.h>
 #endif
@@ -1276,6 +1278,8 @@ struct crypto_algo *image_get_crypto_algo(const char *full_name);
  */
 struct padding_algo *image_get_padding_algo(const char *name);
 
+#if IMAGE_ENABLE_FIT
+
 /**
  * fit_image_verify_required_sigs() - Verify signatures marked as 'required'
  *
index 2b33f323bcccff0f3a792b71d3f270050b1449fa..18a075c17478dc6215bfad66595b37e791b754bb 100644 (file)
@@ -18,6 +18,16 @@ if RSA
 config SPL_RSA
        bool "Use RSA Library within SPL"
 
+config SPL_RSA_VERIFY
+       bool
+       help
+         Add RSA signature verification support in SPL.
+
+config RSA_VERIFY
+       bool
+       help
+         Add RSA signature verification support.
+
 config RSA_SOFTWARE_EXP
        bool "Enable driver for RSA Modular Exponentiation in software"
        depends on DM
index a51c6e1685fb720474a8d2dfea1b03b45e96467a..c07305188e0ce5f1357387fccca26430b33e55cb 100644 (file)
@@ -5,5 +5,5 @@
 # (C) Copyright 2000-2007
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
-obj-$(CONFIG_$(SPL_)FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o
+obj-$(CONFIG_$(SPL_)RSA_VERIFY) += rsa-verify.o rsa-checksum.o
 obj-$(CONFIG_RSA_SOFTWARE_EXP) += rsa-mod-exp.o
index 326a5e4ea97e5fc369c72520b627e5a040c071c9..3dd30c8b8bc7524ca08e5fe874feeb7e34062779 100644 (file)
@@ -271,6 +271,7 @@ out:
 }
 #endif
 
+#if CONFIG_IS_ENABLED(FIT_SIGNATURE)
 /**
  * rsa_verify_key() - Verify a signature against some data using RSA Key
  *
@@ -342,7 +343,9 @@ static int rsa_verify_key(struct image_sign_info *info,
 
        return 0;
 }
+#endif
 
+#if CONFIG_IS_ENABLED(FIT_SIGNATURE)
 /**
  * rsa_verify_with_keynode() - Verify a signature against some data using
  * information in node with prperties of RSA Key like modulus, exponent etc.
@@ -396,18 +399,22 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
 
        return ret;
 }
+#else
+static int rsa_verify_with_keynode(struct image_sign_info *info,
+                                  const void *hash, uint8_t *sig,
+                                  uint sig_len, int node)
+{
+       return -EACCES;
+}
+#endif
 
 int rsa_verify(struct image_sign_info *info,
               const struct image_region region[], int region_count,
               uint8_t *sig, uint sig_len)
 {
-       const void *blob = info->fdt_blob;
        /* Reserve memory for maximum checksum-length */
        uint8_t hash[info->crypto->key_len];
-       int ndepth, noffset;
-       int sig_node, node;
-       char name[100];
-       int ret;
+       int ret = -EACCES;
 
        /*
         * Verify that the checksum-length does not exceed the
@@ -420,12 +427,6 @@ int rsa_verify(struct image_sign_info *info,
                return -EINVAL;
        }
 
-       sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
-       if (sig_node < 0) {
-               debug("%s: No signature node found\n", __func__);
-               return -ENOENT;
-       }
-
        /* Calculate checksum with checksum-algorithm */
        ret = info->checksum->calculate(info->checksum->name,
                                        region, region_count, hash);
@@ -434,29 +435,44 @@ int rsa_verify(struct image_sign_info *info,
                return -EINVAL;
        }
 
-       /* See if we must use a particular key */
-       if (info->required_keynode != -1) {
-               ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
-                       info->required_keynode);
-               return ret;
-       }
+       if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
+               const void *blob = info->fdt_blob;
+               int ndepth, noffset;
+               int sig_node, node;
+               char name[100];
 
-       /* Look for a key that matches our hint */
-       snprintf(name, sizeof(name), "key-%s", info->keyname);
-       node = fdt_subnode_offset(blob, sig_node, name);
-       ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
-       if (!ret)
-               return ret;
+               sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
+               if (sig_node < 0) {
+                       debug("%s: No signature node found\n", __func__);
+                       return -ENOENT;
+               }
 
-       /* No luck, so try each of the keys in turn */
-       for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
-                       (noffset >= 0) && (ndepth > 0);
-                       noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
-               if (ndepth == 1 && noffset != node) {
+               /* See if we must use a particular key */
+               if (info->required_keynode != -1) {
                        ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
-                                                     noffset);
-                       if (!ret)
-                               break;
+                                                     info->required_keynode);
+                       return ret;
+               }
+
+               /* Look for a key that matches our hint */
+               snprintf(name, sizeof(name), "key-%s", info->keyname);
+               node = fdt_subnode_offset(blob, sig_node, name);
+               ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
+               if (!ret)
+                       return ret;
+
+               /* No luck, so try each of the keys in turn */
+               for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node,
+                                                        &ndepth);
+                    (noffset >= 0) && (ndepth > 0);
+                    noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
+                       if (ndepth == 1 && noffset != node) {
+                               ret = rsa_verify_with_keynode(info, hash,
+                                                             sig, sig_len,
+                                                             noffset);
+                               if (!ret)
+                                       break;
+                       }
                }
        }
 
index 99be724b82a554b761c363d63010a4fa14d64956..3b9ae90369a8a3f70b8c42b411e8183f8a2449a7 100644 (file)
@@ -58,7 +58,7 @@ hostprogs-$(CONFIG_FIT_SIGNATURE) += fit_info fit_check_sign
 hostprogs-$(CONFIG_CMD_BOOTEFI_SELFTEST) += file2include
 
 FIT_OBJS-$(CONFIG_FIT) := fit_common.o fit_image.o image-host.o common/image-fit.o
-FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
+FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o common/image-fit-sig.o
 FIT_CIPHER_OBJS-$(CONFIG_FIT_CIPHER) := common/image-cipher.o
 
 # The following files are synced with upstream DTC.