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