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