]> git.sur5r.net Git - u-boot/blob - common/image-sig.c
mtd: nand: mxs_nand: add minimal ECC support
[u-boot] / common / image-sig.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013, Google Inc.
4  */
5
6 #ifdef USE_HOSTCC
7 #include "mkimage.h"
8 #include <time.h>
9 #else
10 #include <common.h>
11 #include <malloc.h>
12 DECLARE_GLOBAL_DATA_PTR;
13 #endif /* !USE_HOSTCC*/
14 #include <image.h>
15 #include <u-boot/rsa.h>
16 #include <u-boot/rsa-checksum.h>
17
18 #define IMAGE_MAX_HASHED_NODES          100
19
20 #ifdef USE_HOSTCC
21 void *host_blob;
22 void image_set_host_blob(void *blob)
23 {
24         host_blob = blob;
25 }
26 void *image_get_host_blob(void)
27 {
28         return host_blob;
29 }
30 #endif
31
32 struct checksum_algo checksum_algos[] = {
33         {
34                 .name = "sha1",
35                 .checksum_len = SHA1_SUM_LEN,
36                 .der_len = SHA1_DER_LEN,
37                 .der_prefix = sha1_der_prefix,
38 #if IMAGE_ENABLE_SIGN
39                 .calculate_sign = EVP_sha1,
40 #endif
41                 .calculate = hash_calculate,
42         },
43         {
44                 .name = "sha256",
45                 .checksum_len = SHA256_SUM_LEN,
46                 .der_len = SHA256_DER_LEN,
47                 .der_prefix = sha256_der_prefix,
48 #if IMAGE_ENABLE_SIGN
49                 .calculate_sign = EVP_sha256,
50 #endif
51                 .calculate = hash_calculate,
52         }
53
54 };
55
56 struct crypto_algo crypto_algos[] = {
57         {
58                 .name = "rsa2048",
59                 .key_len = RSA2048_BYTES,
60                 .sign = rsa_sign,
61                 .add_verify_data = rsa_add_verify_data,
62                 .verify = rsa_verify,
63         },
64         {
65                 .name = "rsa4096",
66                 .key_len = RSA4096_BYTES,
67                 .sign = rsa_sign,
68                 .add_verify_data = rsa_add_verify_data,
69                 .verify = rsa_verify,
70         }
71
72 };
73
74 struct checksum_algo *image_get_checksum_algo(const char *full_name)
75 {
76         int i;
77         const char *name;
78
79         for (i = 0; i < ARRAY_SIZE(checksum_algos); i++) {
80                 name = checksum_algos[i].name;
81                 /* Make sure names match and next char is a comma */
82                 if (!strncmp(name, full_name, strlen(name)) &&
83                     full_name[strlen(name)] == ',')
84                         return &checksum_algos[i];
85         }
86
87         return NULL;
88 }
89
90 struct crypto_algo *image_get_crypto_algo(const char *full_name)
91 {
92         int i;
93         const char *name;
94
95         /* Move name to after the comma */
96         name = strchr(full_name, ',');
97         if (!name)
98                 return NULL;
99         name += 1;
100
101         for (i = 0; i < ARRAY_SIZE(crypto_algos); i++) {
102                 if (!strcmp(crypto_algos[i].name, name))
103                         return &crypto_algos[i];
104         }
105
106         return NULL;
107 }
108
109 /**
110  * fit_region_make_list() - Make a list of image regions
111  *
112  * Given a list of fdt_regions, create a list of image_regions. This is a
113  * simple conversion routine since the FDT and image code use different
114  * structures.
115  *
116  * @fit: FIT image
117  * @fdt_regions: Pointer to FDT regions
118  * @count: Number of FDT regions
119  * @region: Pointer to image regions, which must hold @count records. If
120  * region is NULL, then (except for an SPL build) the array will be
121  * allocated.
122  * @return: Pointer to image regions
123  */
124 struct image_region *fit_region_make_list(const void *fit,
125                 struct fdt_region *fdt_regions, int count,
126                 struct image_region *region)
127 {
128         int i;
129
130         debug("Hash regions:\n");
131         debug("%10s %10s\n", "Offset", "Size");
132
133         /*
134          * Use malloc() except in SPL (to save code size). In SPL the caller
135          * must allocate the array.
136          */
137 #ifndef CONFIG_SPL_BUILD
138         if (!region)
139                 region = calloc(sizeof(*region), count);
140 #endif
141         if (!region)
142                 return NULL;
143         for (i = 0; i < count; i++) {
144                 debug("%10x %10x\n", fdt_regions[i].offset,
145                       fdt_regions[i].size);
146                 region[i].data = fit + fdt_regions[i].offset;
147                 region[i].size = fdt_regions[i].size;
148         }
149
150         return region;
151 }
152
153 static int fit_image_setup_verify(struct image_sign_info *info,
154                 const void *fit, int noffset, int required_keynode,
155                 char **err_msgp)
156 {
157         char *algo_name;
158
159         if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
160                 *err_msgp = "Can't get hash algo property";
161                 return -1;
162         }
163         memset(info, '\0', sizeof(*info));
164         info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
165         info->fit = (void *)fit;
166         info->node_offset = noffset;
167         info->name = algo_name;
168         info->checksum = image_get_checksum_algo(algo_name);
169         info->crypto = image_get_crypto_algo(algo_name);
170         info->fdt_blob = gd_fdt_blob();
171         info->required_keynode = required_keynode;
172         printf("%s:%s", algo_name, info->keyname);
173
174         if (!info->checksum || !info->crypto) {
175                 *err_msgp = "Unknown signature algorithm";
176                 return -1;
177         }
178
179         return 0;
180 }
181
182 int fit_image_check_sig(const void *fit, int noffset, const void *data,
183                 size_t size, int required_keynode, char **err_msgp)
184 {
185         struct image_sign_info info;
186         struct image_region region;
187         uint8_t *fit_value;
188         int fit_value_len;
189
190         *err_msgp = NULL;
191         if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
192                                    err_msgp))
193                 return -1;
194
195         if (fit_image_hash_get_value(fit, noffset, &fit_value,
196                                      &fit_value_len)) {
197                 *err_msgp = "Can't get hash value property";
198                 return -1;
199         }
200
201         region.data = data;
202         region.size = size;
203
204         if (info.crypto->verify(&info, &region, 1, fit_value, fit_value_len)) {
205                 *err_msgp = "Verification failed";
206                 return -1;
207         }
208
209         return 0;
210 }
211
212 static int fit_image_verify_sig(const void *fit, int image_noffset,
213                 const char *data, size_t size, const void *sig_blob,
214                 int sig_offset)
215 {
216         int noffset;
217         char *err_msg = "";
218         int verified = 0;
219         int ret;
220
221         /* Process all hash subnodes of the component image node */
222         fdt_for_each_subnode(noffset, fit, image_noffset) {
223                 const char *name = fit_get_name(fit, noffset, NULL);
224
225                 if (!strncmp(name, FIT_SIG_NODENAME,
226                              strlen(FIT_SIG_NODENAME))) {
227                         ret = fit_image_check_sig(fit, noffset, data,
228                                                         size, -1, &err_msg);
229                         if (ret) {
230                                 puts("- ");
231                         } else {
232                                 puts("+ ");
233                                 verified = 1;
234                                 break;
235                         }
236                 }
237         }
238
239         if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
240                 err_msg = "Corrupted or truncated tree";
241                 goto error;
242         }
243
244         return verified ? 0 : -EPERM;
245
246 error:
247         printf(" error!\n%s for '%s' hash node in '%s' image node\n",
248                err_msg, fit_get_name(fit, noffset, NULL),
249                fit_get_name(fit, image_noffset, NULL));
250         return -1;
251 }
252
253 int fit_image_verify_required_sigs(const void *fit, int image_noffset,
254                 const char *data, size_t size, const void *sig_blob,
255                 int *no_sigsp)
256 {
257         int verify_count = 0;
258         int noffset;
259         int sig_node;
260
261         /* Work out what we need to verify */
262         *no_sigsp = 1;
263         sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
264         if (sig_node < 0) {
265                 debug("%s: No signature node found: %s\n", __func__,
266                       fdt_strerror(sig_node));
267                 return 0;
268         }
269
270         fdt_for_each_subnode(noffset, sig_blob, sig_node) {
271                 const char *required;
272                 int ret;
273
274                 required = fdt_getprop(sig_blob, noffset, "required", NULL);
275                 if (!required || strcmp(required, "image"))
276                         continue;
277                 ret = fit_image_verify_sig(fit, image_noffset, data, size,
278                                         sig_blob, noffset);
279                 if (ret) {
280                         printf("Failed to verify required signature '%s'\n",
281                                fit_get_name(sig_blob, noffset, NULL));
282                         return ret;
283                 }
284                 verify_count++;
285         }
286
287         if (verify_count)
288                 *no_sigsp = 0;
289
290         return 0;
291 }
292
293 int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
294                          char **err_msgp)
295 {
296         char * const exc_prop[] = {"data"};
297         const char *prop, *end, *name;
298         struct image_sign_info info;
299         const uint32_t *strings;
300         uint8_t *fit_value;
301         int fit_value_len;
302         int max_regions;
303         int i, prop_len;
304         char path[200];
305         int count;
306
307         debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
308               fit_get_name(fit, noffset, NULL),
309               fit_get_name(gd_fdt_blob(), required_keynode, NULL));
310         *err_msgp = NULL;
311         if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
312                                    err_msgp))
313                 return -1;
314
315         if (fit_image_hash_get_value(fit, noffset, &fit_value,
316                                      &fit_value_len)) {
317                 *err_msgp = "Can't get hash value property";
318                 return -1;
319         }
320
321         /* Count the number of strings in the property */
322         prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
323         end = prop ? prop + prop_len : prop;
324         for (name = prop, count = 0; name < end; name++)
325                 if (!*name)
326                         count++;
327         if (!count) {
328                 *err_msgp = "Can't get hashed-nodes property";
329                 return -1;
330         }
331
332         /* Add a sanity check here since we are using the stack */
333         if (count > IMAGE_MAX_HASHED_NODES) {
334                 *err_msgp = "Number of hashed nodes exceeds maximum";
335                 return -1;
336         }
337
338         /* Create a list of node names from those strings */
339         char *node_inc[count];
340
341         debug("Hash nodes (%d):\n", count);
342         for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
343                 debug("   '%s'\n", name);
344                 node_inc[i] = (char *)name;
345         }
346
347         /*
348          * Each node can generate one region for each sub-node. Allow for
349          * 7 sub-nodes (hash-1, signature-1, etc.) and some extra.
350          */
351         max_regions = 20 + count * 7;
352         struct fdt_region fdt_regions[max_regions];
353
354         /* Get a list of regions to hash */
355         count = fdt_find_regions(fit, node_inc, count,
356                         exc_prop, ARRAY_SIZE(exc_prop),
357                         fdt_regions, max_regions - 1,
358                         path, sizeof(path), 0);
359         if (count < 0) {
360                 *err_msgp = "Failed to hash configuration";
361                 return -1;
362         }
363         if (count == 0) {
364                 *err_msgp = "No data to hash";
365                 return -1;
366         }
367         if (count >= max_regions - 1) {
368                 *err_msgp = "Too many hash regions";
369                 return -1;
370         }
371
372         /* Add the strings */
373         strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
374         if (strings) {
375                 fdt_regions[count].offset = fdt_off_dt_strings(fit) +
376                                 fdt32_to_cpu(strings[0]);
377                 fdt_regions[count].size = fdt32_to_cpu(strings[1]);
378                 count++;
379         }
380
381         /* Allocate the region list on the stack */
382         struct image_region region[count];
383
384         fit_region_make_list(fit, fdt_regions, count, region);
385         if (info.crypto->verify(&info, region, count, fit_value,
386                                 fit_value_len)) {
387                 *err_msgp = "Verification failed";
388                 return -1;
389         }
390
391         return 0;
392 }
393
394 static int fit_config_verify_sig(const void *fit, int conf_noffset,
395                 const void *sig_blob, int sig_offset)
396 {
397         int noffset;
398         char *err_msg = "";
399         int verified = 0;
400         int ret;
401
402         /* Process all hash subnodes of the component conf node */
403         fdt_for_each_subnode(noffset, fit, conf_noffset) {
404                 const char *name = fit_get_name(fit, noffset, NULL);
405
406                 if (!strncmp(name, FIT_SIG_NODENAME,
407                              strlen(FIT_SIG_NODENAME))) {
408                         ret = fit_config_check_sig(fit, noffset, sig_offset,
409                                                    &err_msg);
410                         if (ret) {
411                                 puts("- ");
412                         } else {
413                                 puts("+ ");
414                                 verified = 1;
415                                 break;
416                         }
417                 }
418         }
419
420         if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
421                 err_msg = "Corrupted or truncated tree";
422                 goto error;
423         }
424
425         return verified ? 0 : -EPERM;
426
427 error:
428         printf(" error!\n%s for '%s' hash node in '%s' config node\n",
429                err_msg, fit_get_name(fit, noffset, NULL),
430                fit_get_name(fit, conf_noffset, NULL));
431         return -1;
432 }
433
434 int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
435                 const void *sig_blob)
436 {
437         int noffset;
438         int sig_node;
439
440         /* Work out what we need to verify */
441         sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
442         if (sig_node < 0) {
443                 debug("%s: No signature node found: %s\n", __func__,
444                       fdt_strerror(sig_node));
445                 return 0;
446         }
447
448         fdt_for_each_subnode(noffset, sig_blob, sig_node) {
449                 const char *required;
450                 int ret;
451
452                 required = fdt_getprop(sig_blob, noffset, "required", NULL);
453                 if (!required || strcmp(required, "conf"))
454                         continue;
455                 ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
456                                             noffset);
457                 if (ret) {
458                         printf("Failed to verify required signature '%s'\n",
459                                fit_get_name(sig_blob, noffset, NULL));
460                         return ret;
461                 }
462         }
463
464         return 0;
465 }
466
467 int fit_config_verify(const void *fit, int conf_noffset)
468 {
469         return fit_config_verify_required_sigs(fit, conf_noffset,
470                                                gd_fdt_blob());
471 }