]> git.sur5r.net Git - u-boot/blob - common/image-sig.c
spi: cadence_qspi: Fix warning cast from pointer to integer of different size
[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 (fdt_totalsize(fit) > CONFIG_FIT_SIGNATURE_MAX_SIZE) {
160                 *err_msgp = "Total size too large";
161                 return 1;
162         }
163
164         if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
165                 *err_msgp = "Can't get hash algo property";
166                 return -1;
167         }
168         memset(info, '\0', sizeof(*info));
169         info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
170         info->fit = (void *)fit;
171         info->node_offset = noffset;
172         info->name = algo_name;
173         info->checksum = image_get_checksum_algo(algo_name);
174         info->crypto = image_get_crypto_algo(algo_name);
175         info->fdt_blob = gd_fdt_blob();
176         info->required_keynode = required_keynode;
177         printf("%s:%s", algo_name, info->keyname);
178
179         if (!info->checksum || !info->crypto) {
180                 *err_msgp = "Unknown signature algorithm";
181                 return -1;
182         }
183
184         return 0;
185 }
186
187 int fit_image_check_sig(const void *fit, int noffset, const void *data,
188                 size_t size, int required_keynode, char **err_msgp)
189 {
190         struct image_sign_info info;
191         struct image_region region;
192         uint8_t *fit_value;
193         int fit_value_len;
194
195         *err_msgp = NULL;
196         if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
197                                    err_msgp))
198                 return -1;
199
200         if (fit_image_hash_get_value(fit, noffset, &fit_value,
201                                      &fit_value_len)) {
202                 *err_msgp = "Can't get hash value property";
203                 return -1;
204         }
205
206         region.data = data;
207         region.size = size;
208
209         if (info.crypto->verify(&info, &region, 1, fit_value, fit_value_len)) {
210                 *err_msgp = "Verification failed";
211                 return -1;
212         }
213
214         return 0;
215 }
216
217 static int fit_image_verify_sig(const void *fit, int image_noffset,
218                 const char *data, size_t size, const void *sig_blob,
219                 int sig_offset)
220 {
221         int noffset;
222         char *err_msg = "";
223         int verified = 0;
224         int ret;
225
226         /* Process all hash subnodes of the component image node */
227         fdt_for_each_subnode(noffset, fit, image_noffset) {
228                 const char *name = fit_get_name(fit, noffset, NULL);
229
230                 if (!strncmp(name, FIT_SIG_NODENAME,
231                              strlen(FIT_SIG_NODENAME))) {
232                         ret = fit_image_check_sig(fit, noffset, data,
233                                                         size, -1, &err_msg);
234                         if (ret) {
235                                 puts("- ");
236                         } else {
237                                 puts("+ ");
238                                 verified = 1;
239                                 break;
240                         }
241                 }
242         }
243
244         if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
245                 err_msg = "Corrupted or truncated tree";
246                 goto error;
247         }
248
249         return verified ? 0 : -EPERM;
250
251 error:
252         printf(" error!\n%s for '%s' hash node in '%s' image node\n",
253                err_msg, fit_get_name(fit, noffset, NULL),
254                fit_get_name(fit, image_noffset, NULL));
255         return -1;
256 }
257
258 int fit_image_verify_required_sigs(const void *fit, int image_noffset,
259                 const char *data, size_t size, const void *sig_blob,
260                 int *no_sigsp)
261 {
262         int verify_count = 0;
263         int noffset;
264         int sig_node;
265
266         /* Work out what we need to verify */
267         *no_sigsp = 1;
268         sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
269         if (sig_node < 0) {
270                 debug("%s: No signature node found: %s\n", __func__,
271                       fdt_strerror(sig_node));
272                 return 0;
273         }
274
275         fdt_for_each_subnode(noffset, sig_blob, sig_node) {
276                 const char *required;
277                 int ret;
278
279                 required = fdt_getprop(sig_blob, noffset, "required", NULL);
280                 if (!required || strcmp(required, "image"))
281                         continue;
282                 ret = fit_image_verify_sig(fit, image_noffset, data, size,
283                                         sig_blob, noffset);
284                 if (ret) {
285                         printf("Failed to verify required signature '%s'\n",
286                                fit_get_name(sig_blob, noffset, NULL));
287                         return ret;
288                 }
289                 verify_count++;
290         }
291
292         if (verify_count)
293                 *no_sigsp = 0;
294
295         return 0;
296 }
297
298 int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
299                          char **err_msgp)
300 {
301         char * const exc_prop[] = {"data"};
302         const char *prop, *end, *name;
303         struct image_sign_info info;
304         const uint32_t *strings;
305         uint8_t *fit_value;
306         int fit_value_len;
307         int max_regions;
308         int i, prop_len;
309         char path[200];
310         int count;
311
312         debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
313               fit_get_name(fit, noffset, NULL),
314               fit_get_name(gd_fdt_blob(), required_keynode, NULL));
315         *err_msgp = NULL;
316         if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
317                                    err_msgp))
318                 return -1;
319
320         if (fit_image_hash_get_value(fit, noffset, &fit_value,
321                                      &fit_value_len)) {
322                 *err_msgp = "Can't get hash value property";
323                 return -1;
324         }
325
326         /* Count the number of strings in the property */
327         prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
328         end = prop ? prop + prop_len : prop;
329         for (name = prop, count = 0; name < end; name++)
330                 if (!*name)
331                         count++;
332         if (!count) {
333                 *err_msgp = "Can't get hashed-nodes property";
334                 return -1;
335         }
336
337         /* Add a sanity check here since we are using the stack */
338         if (count > IMAGE_MAX_HASHED_NODES) {
339                 *err_msgp = "Number of hashed nodes exceeds maximum";
340                 return -1;
341         }
342
343         /* Create a list of node names from those strings */
344         char *node_inc[count];
345
346         debug("Hash nodes (%d):\n", count);
347         for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
348                 debug("   '%s'\n", name);
349                 node_inc[i] = (char *)name;
350         }
351
352         /*
353          * Each node can generate one region for each sub-node. Allow for
354          * 7 sub-nodes (hash-1, signature-1, etc.) and some extra.
355          */
356         max_regions = 20 + count * 7;
357         struct fdt_region fdt_regions[max_regions];
358
359         /* Get a list of regions to hash */
360         count = fdt_find_regions(fit, node_inc, count,
361                         exc_prop, ARRAY_SIZE(exc_prop),
362                         fdt_regions, max_regions - 1,
363                         path, sizeof(path), 0);
364         if (count < 0) {
365                 *err_msgp = "Failed to hash configuration";
366                 return -1;
367         }
368         if (count == 0) {
369                 *err_msgp = "No data to hash";
370                 return -1;
371         }
372         if (count >= max_regions - 1) {
373                 *err_msgp = "Too many hash regions";
374                 return -1;
375         }
376
377         /* Add the strings */
378         strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
379         if (strings) {
380                 /*
381                  * The strings region offset must be a static 0x0.
382                  * This is set in tool/image-host.c
383                  */
384                 fdt_regions[count].offset = fdt_off_dt_strings(fit);
385                 fdt_regions[count].size = fdt32_to_cpu(strings[1]);
386                 count++;
387         }
388
389         /* Allocate the region list on the stack */
390         struct image_region region[count];
391
392         fit_region_make_list(fit, fdt_regions, count, region);
393         if (info.crypto->verify(&info, region, count, fit_value,
394                                 fit_value_len)) {
395                 *err_msgp = "Verification failed";
396                 return -1;
397         }
398
399         return 0;
400 }
401
402 static int fit_config_verify_sig(const void *fit, int conf_noffset,
403                 const void *sig_blob, int sig_offset)
404 {
405         int noffset;
406         char *err_msg = "";
407         int verified = 0;
408         int ret;
409
410         /* Process all hash subnodes of the component conf node */
411         fdt_for_each_subnode(noffset, fit, conf_noffset) {
412                 const char *name = fit_get_name(fit, noffset, NULL);
413
414                 if (!strncmp(name, FIT_SIG_NODENAME,
415                              strlen(FIT_SIG_NODENAME))) {
416                         ret = fit_config_check_sig(fit, noffset, sig_offset,
417                                                    &err_msg);
418                         if (ret) {
419                                 puts("- ");
420                         } else {
421                                 puts("+ ");
422                                 verified = 1;
423                                 break;
424                         }
425                 }
426         }
427
428         if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
429                 err_msg = "Corrupted or truncated tree";
430                 goto error;
431         }
432
433         return verified ? 0 : -EPERM;
434
435 error:
436         printf(" error!\n%s for '%s' hash node in '%s' config node\n",
437                err_msg, fit_get_name(fit, noffset, NULL),
438                fit_get_name(fit, conf_noffset, NULL));
439         return -1;
440 }
441
442 int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
443                 const void *sig_blob)
444 {
445         int noffset;
446         int sig_node;
447
448         /* Work out what we need to verify */
449         sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
450         if (sig_node < 0) {
451                 debug("%s: No signature node found: %s\n", __func__,
452                       fdt_strerror(sig_node));
453                 return 0;
454         }
455
456         fdt_for_each_subnode(noffset, sig_blob, sig_node) {
457                 const char *required;
458                 int ret;
459
460                 required = fdt_getprop(sig_blob, noffset, "required", NULL);
461                 if (!required || strcmp(required, "conf"))
462                         continue;
463                 ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
464                                             noffset);
465                 if (ret) {
466                         printf("Failed to verify required signature '%s'\n",
467                                fit_get_name(sig_blob, noffset, NULL));
468                         return ret;
469                 }
470         }
471
472         return 0;
473 }
474
475 int fit_config_verify(const void *fit, int conf_noffset)
476 {
477         return fit_config_verify_required_sigs(fit, conf_noffset,
478                                                gd_fdt_blob());
479 }