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