]> git.sur5r.net Git - u-boot/blob - common/image-sig.c
image: Support signing of images
[u-boot] / common / image-sig.c
1 /*
2  * Copyright (c) 2013, Google Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17  * MA 02111-1307 USA
18  */
19
20 #ifdef USE_HOSTCC
21 #include "mkimage.h"
22 #include <time.h>
23 #else
24 #include <common.h>
25 #include <malloc.h>
26 DECLARE_GLOBAL_DATA_PTR;
27 #endif /* !USE_HOSTCC*/
28 #include <errno.h>
29 #include <image.h>
30
31 struct image_sig_algo image_sig_algos[] = {
32 };
33
34 struct image_sig_algo *image_get_sig_algo(const char *name)
35 {
36         int i;
37
38         for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) {
39                 if (!strcmp(image_sig_algos[i].name, name))
40                         return &image_sig_algos[i];
41         }
42
43         return NULL;
44 }
45
46 static int fit_image_setup_verify(struct image_sign_info *info,
47                 const void *fit, int noffset, int required_keynode,
48                 char **err_msgp)
49 {
50         char *algo_name;
51
52         if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
53                 *err_msgp = "Can't get hash algo property";
54                 return -1;
55         }
56         memset(info, '\0', sizeof(*info));
57         info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
58         info->fit = (void *)fit;
59         info->node_offset = noffset;
60         info->algo = image_get_sig_algo(algo_name);
61         info->fdt_blob = gd_fdt_blob();
62         info->required_keynode = required_keynode;
63         printf("%s:%s", algo_name, info->keyname);
64
65         if (!info->algo) {
66                 *err_msgp = "Unknown signature algorithm";
67                 return -1;
68         }
69
70         return 0;
71 }
72
73 int fit_image_check_sig(const void *fit, int noffset, const void *data,
74                 size_t size, int required_keynode, char **err_msgp)
75 {
76         struct image_sign_info info;
77         struct image_region region;
78         uint8_t *fit_value;
79         int fit_value_len;
80
81         *err_msgp = NULL;
82         if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
83                                    err_msgp))
84                 return -1;
85
86         if (fit_image_hash_get_value(fit, noffset, &fit_value,
87                                      &fit_value_len)) {
88                 *err_msgp = "Can't get hash value property";
89                 return -1;
90         }
91
92         region.data = data;
93         region.size = size;
94
95         if (info.algo->verify(&info, &region, 1, fit_value, fit_value_len)) {
96                 *err_msgp = "Verification failed";
97                 return -1;
98         }
99
100         return 0;
101 }
102
103 static int fit_image_verify_sig(const void *fit, int image_noffset,
104                 const char *data, size_t size, const void *sig_blob,
105                 int sig_offset)
106 {
107         int noffset;
108         char *err_msg = "";
109         int verified = 0;
110         int ret;
111
112         /* Process all hash subnodes of the component image node */
113         for (noffset = fdt_first_subnode(fit, image_noffset);
114              noffset >= 0;
115              noffset = fdt_next_subnode(fit, noffset)) {
116                 const char *name = fit_get_name(fit, noffset, NULL);
117
118                 if (!strncmp(name, FIT_SIG_NODENAME,
119                              strlen(FIT_SIG_NODENAME))) {
120                         ret = fit_image_check_sig(fit, noffset, data,
121                                                         size, -1, &err_msg);
122                         if (ret) {
123                                 puts("- ");
124                         } else {
125                                 puts("+ ");
126                                 verified = 1;
127                                 break;
128                         }
129                 }
130         }
131
132         if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
133                 err_msg = "Corrupted or truncated tree";
134                 goto error;
135         }
136
137         return verified ? 0 : -EPERM;
138
139 error:
140         printf(" error!\n%s for '%s' hash node in '%s' image node\n",
141                err_msg, fit_get_name(fit, noffset, NULL),
142                fit_get_name(fit, image_noffset, NULL));
143         return -1;
144 }
145
146 int fit_image_verify_required_sigs(const void *fit, int image_noffset,
147                 const char *data, size_t size, const void *sig_blob,
148                 int *no_sigsp)
149 {
150         int verify_count = 0;
151         int noffset;
152         int sig_node;
153
154         /* Work out what we need to verify */
155         *no_sigsp = 1;
156         sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
157         if (sig_node < 0) {
158                 debug("%s: No signature node found: %s\n", __func__,
159                       fdt_strerror(sig_node));
160                 return 0;
161         }
162
163         for (noffset = fdt_first_subnode(sig_blob, sig_node);
164              noffset >= 0;
165              noffset = fdt_next_subnode(sig_blob, noffset)) {
166                 const char *required;
167                 int ret;
168
169                 required = fdt_getprop(sig_blob, noffset, "required", NULL);
170                 if (!required || strcmp(required, "image"))
171                         continue;
172                 ret = fit_image_verify_sig(fit, image_noffset, data, size,
173                                         sig_blob, noffset);
174                 if (ret) {
175                         printf("Failed to verify required signature '%s'\n",
176                                fit_get_name(sig_blob, noffset, NULL));
177                         return ret;
178                 }
179                 verify_count++;
180         }
181
182         if (verify_count)
183                 *no_sigsp = 0;
184
185         return 0;
186 }