aboutsummaryrefslogtreecommitdiff
path: root/common/image-sig.c
diff options
context:
space:
mode:
authorSimon Glass2013-06-13 15:10:01 -0700
committerTom Rini2013-06-26 10:18:56 -0400
commit56518e71041fafdfd7af3a24f263b0a22efbeda9 (patch)
tree03327d88f29d505539dc1fd5a68f88bf16163d28 /common/image-sig.c
parent3e569a6b1eb7ef0c8144f8c243f9e33c834bf003 (diff)
image: Support signing of images
Add support for signing images using a new signature node. The process is handled by fdt_add_verification_data() which now takes parameters to provide the keys and related information. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'common/image-sig.c')
-rw-r--r--common/image-sig.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/common/image-sig.c b/common/image-sig.c
index 841c662cbfd..9b222daa0fd 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -22,6 +22,8 @@
#include <time.h>
#else
#include <common.h>
+#include <malloc.h>
+DECLARE_GLOBAL_DATA_PTR;
#endif /* !USE_HOSTCC*/
#include <errno.h>
#include <image.h>
@@ -40,3 +42,145 @@ struct image_sig_algo *image_get_sig_algo(const char *name)
return NULL;
}
+
+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;
+
+ if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
+ *err_msgp = "Can't get hash algo property";
+ return -1;
+ }
+ 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->fdt_blob = gd_fdt_blob();
+ info->required_keynode = required_keynode;
+ printf("%s:%s", algo_name, info->keyname);
+
+ if (!info->algo) {
+ *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.algo->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 */
+ for (noffset = fdt_first_subnode(fit, image_noffset);
+ noffset >= 0;
+ noffset = fdt_next_subnode(fit, 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;
+ }
+
+ for (noffset = fdt_first_subnode(sig_blob, sig_node);
+ noffset >= 0;
+ noffset = fdt_next_subnode(sig_blob, noffset)) {
+ 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;
+}