"Das U-Boot" Source Tree
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2013, Google Inc.
4 *
5 * (C) Copyright 2008 Semihalf
6 *
7 * (C) Copyright 2000-2006
8 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
9 */
10
11#include "mkimage.h"
12#include <bootm.h>
13#include <fdt_region.h>
14#include <image.h>
15#include <version.h>
16
17#if CONFIG_IS_ENABLED(FIT_SIGNATURE)
18#include <openssl/pem.h>
19#include <openssl/evp.h>
20#endif
21
22/**
23 * fit_set_hash_value - set hash value in requested has node
24 * @fit: pointer to the FIT format image header
25 * @noffset: hash node offset
26 * @value: hash value to be set
27 * @value_len: hash value length
28 *
29 * fit_set_hash_value() attempts to set hash value in a node at offset
30 * given and returns operation status to the caller.
31 *
32 * returns
33 * 0, on success
34 * -1, on failure
35 */
36static int fit_set_hash_value(void *fit, int noffset, uint8_t *value,
37 int value_len)
38{
39 int ret;
40
41 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
42 if (ret) {
43 fprintf(stderr, "Can't set hash '%s' property for '%s' node(%s)\n",
44 FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL),
45 fdt_strerror(ret));
46 return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
47 }
48
49 return 0;
50}
51
52/**
53 * fit_image_process_hash - Process a single subnode of the images/ node
54 *
55 * Check each subnode and process accordingly. For hash nodes we generate
56 * a hash of the supplied data and store it in the node.
57 *
58 * @fit: pointer to the FIT format image header
59 * @image_name: name of image being processed (used to display errors)
60 * @noffset: subnode offset
61 * @data: data to process
62 * @size: size of data in bytes
63 * Return: 0 if ok, -1 on error
64 */
65static int fit_image_process_hash(void *fit, const char *image_name,
66 int noffset, const void *data, size_t size)
67{
68 uint8_t value[FIT_MAX_HASH_LEN];
69 const char *node_name;
70 int value_len;
71 const char *algo;
72 int ret;
73
74 node_name = fit_get_name(fit, noffset, NULL);
75
76 if (fit_image_hash_get_algo(fit, noffset, &algo)) {
77 fprintf(stderr,
78 "Can't get hash algo property for '%s' hash node in '%s' image node\n",
79 node_name, image_name);
80 return -ENOENT;
81 }
82
83 if (calculate_hash(data, size, algo, value, &value_len)) {
84 fprintf(stderr,
85 "Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n",
86 algo, node_name, image_name);
87 return -EPROTONOSUPPORT;
88 }
89
90 ret = fit_set_hash_value(fit, noffset, value, value_len);
91 if (ret) {
92 fprintf(stderr, "Can't set hash value for '%s' hash node in '%s' image node\n",
93 node_name, image_name);
94 return ret;
95 }
96
97 return 0;
98}
99
100/**
101 * fit_image_write_sig() - write the signature to a FIT
102 *
103 * This writes the signature and signer data to the FIT.
104 *
105 * @fit: pointer to the FIT format image header
106 * @noffset: hash node offset
107 * @value: signature value to be set
108 * @value_len: signature value length
109 * @comment: Text comment to write (NULL for none)
110 *
111 * returns
112 * 0, on success
113 * -FDT_ERR_..., on failure
114 */
115static int fit_image_write_sig(void *fit, int noffset, uint8_t *value,
116 int value_len, const char *comment, const char *region_prop,
117 int region_proplen, const char *cmdname, const char *algo_name)
118{
119 int string_size;
120 int ret;
121
122 /*
123 * Get the current string size, before we update the FIT and add
124 * more
125 */
126 string_size = fdt_size_dt_strings(fit);
127
128 ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
129 if (!ret) {
130 ret = fdt_setprop_string(fit, noffset, "signer-name",
131 "mkimage");
132 }
133 if (!ret) {
134 ret = fdt_setprop_string(fit, noffset, "signer-version",
135 PLAIN_VERSION);
136 }
137 if (comment && !ret)
138 ret = fdt_setprop_string(fit, noffset, "comment", comment);
139 if (!ret) {
140 time_t timestamp = imagetool_get_source_date(cmdname,
141 time(NULL));
142 uint32_t t = cpu_to_uimage(timestamp);
143
144 ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
145 sizeof(uint32_t));
146 }
147 if (region_prop && !ret) {
148 uint32_t strdata[2];
149
150 ret = fdt_setprop(fit, noffset, "hashed-nodes",
151 region_prop, region_proplen);
152 /* This is a legacy offset, it is unused, and must remain 0. */
153 strdata[0] = 0;
154 strdata[1] = cpu_to_fdt32(string_size);
155 if (!ret) {
156 ret = fdt_setprop(fit, noffset, "hashed-strings",
157 strdata, sizeof(strdata));
158 }
159 }
160 if (algo_name && !ret)
161 ret = fdt_setprop_string(fit, noffset, "algo", algo_name);
162
163 return ret;
164}
165
166static int fit_image_setup_sig(struct image_sign_info *info,
167 const char *keydir, const char *keyfile, void *fit,
168 const char *image_name, int noffset, const char *require_keys,
169 const char *engine_id, const char *algo_name)
170{
171 const char *node_name;
172 const char *padding_name;
173
174 node_name = fit_get_name(fit, noffset, NULL);
175 if (!algo_name) {
176 if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
177 fprintf(stderr,
178 "Can't get algo property for '%s' signature node in '%s' image node\n",
179 node_name, image_name);
180 return -1;
181 }
182 }
183
184 padding_name = fdt_getprop(fit, noffset, "padding", NULL);
185
186 memset(info, '\0', sizeof(*info));
187 info->keydir = keydir;
188 info->keyfile = keyfile;
189 info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
190 info->fit = fit;
191 info->node_offset = noffset;
192 info->name = strdup(algo_name);
193 info->checksum = image_get_checksum_algo(algo_name);
194 info->crypto = image_get_crypto_algo(algo_name);
195 info->padding = image_get_padding_algo(padding_name);
196 info->require_keys = require_keys;
197 info->engine_id = engine_id;
198 if (!info->checksum || !info->crypto) {
199 fprintf(stderr,
200 "Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
201 algo_name, node_name, image_name);
202 return -1;
203 }
204
205 return 0;
206}
207
208/**
209 * fit_image_process_sig- Process a single subnode of the images/ node
210 *
211 * Check each subnode and process accordingly. For signature nodes we
212 * generate a signed hash of the supplied data and store it in the node.
213 *
214 * @keydir: Directory containing keys to use for signing
215 * @keydest: Destination FDT blob to write public keys into (NULL if none)
216 * @fit: pointer to the FIT format image header
217 * @image_name: name of image being processed (used to display errors)
218 * @noffset: subnode offset
219 * @data: data to process
220 * @size: size of data in bytes
221 * @comment: Comment to add to signature nodes
222 * @require_keys: Mark all keys as 'required'
223 * @engine_id: Engine to use for signing
224 * Return: keydest node if @keydest is non-NULL, else 0 if none; -ve error code
225 * on failure
226 */
227static int fit_image_process_sig(const char *keydir, const char *keyfile,
228 void *keydest, void *fit, const char *image_name,
229 int noffset, const void *data, size_t size,
230 const char *comment, int require_keys, const char *engine_id,
231 const char *cmdname, const char *algo_name)
232{
233 struct image_sign_info info;
234 struct image_region region;
235 const char *node_name;
236 uint8_t *value;
237 uint value_len;
238 int ret;
239
240 if (fit_image_setup_sig(&info, keydir, keyfile, fit, image_name,
241 noffset, require_keys ? "image" : NULL,
242 engine_id, algo_name))
243 return -1;
244
245 node_name = fit_get_name(fit, noffset, NULL);
246 region.data = data;
247 region.size = size;
248 ret = info.crypto->sign(&info, ®ion, 1, &value, &value_len);
249 if (ret) {
250 fprintf(stderr, "Failed to sign '%s' signature node in '%s' image node: %d\n",
251 node_name, image_name, ret);
252
253 /* We allow keys to be missing */
254 if (ret == -ENOENT)
255 return 0;
256 return -1;
257 }
258
259 ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
260 NULL, 0, cmdname, algo_name);
261 if (ret) {
262 if (ret == -FDT_ERR_NOSPACE)
263 return -ENOSPC;
264 fprintf(stderr,
265 "Can't write signature for '%s' signature node in '%s' conf node: %s\n",
266 node_name, image_name, fdt_strerror(ret));
267 return -1;
268 }
269 free(value);
270
271 /* Get keyname again, as FDT has changed and invalidated our pointer */
272 info.keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
273
274 /*
275 * Write the public key into the supplied FDT file; this might fail
276 * several times, since we try signing with successively increasing
277 * size values
278 */
279 if (keydest) {
280 ret = info.crypto->add_verify_data(&info, keydest);
281 if (ret < 0) {
282 fprintf(stderr,
283 "Failed to add verification data for '%s' signature node in '%s' image node\n",
284 node_name, image_name);
285 return ret;
286 }
287 /* Return the node that was written to */
288 return ret;
289 }
290
291 return 0;
292}
293
294static int fit_image_read_data(char *filename, unsigned char *data,
295 int expected_size)
296{
297 struct stat sbuf;
298 int fd, ret = -1;
299 ssize_t n;
300
301 /* Open file */
302 fd = open(filename, O_RDONLY | O_BINARY);
303 if (fd < 0) {
304 fprintf(stderr, "Can't open file %s (err=%d => %s)\n",
305 filename, errno, strerror(errno));
306 return -1;
307 }
308
309 /* Compute file size */
310 if (fstat(fd, &sbuf) < 0) {
311 fprintf(stderr, "Can't fstat file %s (err=%d => %s)\n",
312 filename, errno, strerror(errno));
313 goto err;
314 }
315
316 /* Check file size */
317 if (sbuf.st_size != expected_size) {
318 fprintf(stderr, "File %s don't have the expected size (size=%lld, expected=%d)\n",
319 filename, (long long)sbuf.st_size, expected_size);
320 goto err;
321 }
322
323 /* Read data */
324 n = read(fd, data, sbuf.st_size);
325 if (n < 0) {
326 fprintf(stderr, "Can't read file %s (err=%d => %s)\n",
327 filename, errno, strerror(errno));
328 goto err;
329 }
330
331 /* Check that we have read all the file */
332 if (n != sbuf.st_size) {
333 fprintf(stderr, "Can't read all file %s (read %zd bytes, expected %lld)\n",
334 filename, n, (long long)sbuf.st_size);
335 goto err;
336 }
337
338 ret = 0;
339
340err:
341 close(fd);
342 return ret;
343}
344
345static int fit_image_read_key_iv_data(const char *keydir, const char *key_iv_name,
346 unsigned char *key_iv_data, int expected_size)
347{
348 char filename[PATH_MAX];
349 int ret;
350
351 ret = snprintf(filename, sizeof(filename), "%s/%s%s",
352 keydir, key_iv_name, ".bin");
353 if (ret >= sizeof(filename)) {
354 fprintf(stderr, "Can't format the key or IV filename when setting up the cipher: insufficient buffer space\n");
355 return -1;
356 }
357 if (ret < 0) {
358 fprintf(stderr, "Can't format the key or IV filename when setting up the cipher: snprintf error\n");
359 return -1;
360 }
361
362 ret = fit_image_read_data(filename, key_iv_data, expected_size);
363
364 return ret;
365}
366
367/**
368 * get_random_data() - fill buffer with random data
369 *
370 * There is no common cryptographically safe function in Linux and BSD.
371 * Hence directly access the /dev/urandom PRNG.
372 *
373 * @data: buffer to fill
374 * @size: buffer size
375 */
376static int get_random_data(void *data, size_t size)
377{
378 int fd;
379 int ret;
380
381 fd = open("/dev/urandom", O_RDONLY);
382 if (fd < 0) {
383 perror("Failed to open /dev/urandom");
384 return -1;
385 }
386
387 while (size) {
388 ssize_t count;
389
390 count = read(fd, data, size);
391 if (count < 0) {
392 if (errno == EINTR) {
393 continue;
394 } else {
395 perror("Failed to read from /dev/urandom");
396 ret = -1;
397 goto out;
398 }
399 }
400 data += count;
401 size -= count;
402 }
403 ret = 0;
404out:
405 close(fd);
406
407 return ret;
408}
409
410static int fit_image_setup_cipher(struct image_cipher_info *info,
411 const char *keydir, void *fit,
412 const char *image_name, int image_noffset,
413 int noffset)
414{
415 char *algo_name;
416 int ret = -1;
417
418 if (fit_image_cipher_get_algo(fit, noffset, &algo_name)) {
419 fprintf(stderr, "Can't get algo name for cipher in image '%s'\n",
420 image_name);
421 goto out;
422 }
423
424 info->keydir = keydir;
425
426 /* Read the key name */
427 info->keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
428 if (!info->keyname) {
429 fprintf(stderr, "Can't get key name for cipher in image '%s'\n",
430 image_name);
431 goto out;
432 }
433
434 /*
435 * Read the IV name
436 *
437 * If this property is not provided then mkimage will generate
438 * a random IV and store it in the FIT image
439 */
440 info->ivname = fdt_getprop(fit, noffset, "iv-name-hint", NULL);
441
442 info->fit = fit;
443 info->node_noffset = noffset;
444 info->name = algo_name;
445
446 info->cipher = image_get_cipher_algo(algo_name);
447 if (!info->cipher) {
448 fprintf(stderr, "Can't get algo for cipher '%s'\n", image_name);
449 goto out;
450 }
451
452 info->key = malloc(info->cipher->key_len);
453 if (!info->key) {
454 fprintf(stderr, "Can't allocate memory for key\n");
455 ret = -1;
456 goto out;
457 }
458
459 /* Read the key in the file */
460 ret = fit_image_read_key_iv_data(info->keydir, info->keyname,
461 (unsigned char *)info->key,
462 info->cipher->key_len);
463 if (ret < 0)
464 goto out;
465
466 info->iv = malloc(info->cipher->iv_len);
467 if (!info->iv) {
468 fprintf(stderr, "Can't allocate memory for iv\n");
469 ret = -1;
470 goto out;
471 }
472
473 if (info->ivname) {
474 /* Read the IV in the file */
475 ret = fit_image_read_key_iv_data(info->keydir, info->ivname,
476 (unsigned char *)info->iv,
477 info->cipher->iv_len);
478 if (ret < 0)
479 goto out;
480 } else {
481 /* Generate an ramdom IV */
482 ret = get_random_data((void *)info->iv, info->cipher->iv_len);
483 }
484
485 out:
486 return ret;
487}
488
489int fit_image_write_cipher(void *fit, int image_noffset, int noffset,
490 const void *data, size_t size,
491 unsigned char *data_ciphered, int data_ciphered_len)
492{
493 int ret = -1;
494
495 /* Replace data with ciphered data */
496 ret = fdt_setprop(fit, image_noffset, FIT_DATA_PROP,
497 data_ciphered, data_ciphered_len);
498 if (ret == -FDT_ERR_NOSPACE) {
499 ret = -ENOSPC;
500 goto out;
501 }
502 if (ret) {
503 fprintf(stderr, "Can't replace data with ciphered data (err = %d)\n", ret);
504 goto out;
505 }
506
507 /* add non ciphered data size */
508 ret = fdt_setprop_u32(fit, image_noffset, "data-size-unciphered", size);
509 if (ret == -FDT_ERR_NOSPACE) {
510 ret = -ENOSPC;
511 goto out;
512 }
513 if (ret) {
514 fprintf(stderr, "Can't add unciphered data size (err = %d)\n", ret);
515 goto out;
516 }
517
518 out:
519 return ret;
520}
521
522static int
523fit_image_process_cipher(const char *keydir, void *keydest, void *fit,
524 const char *image_name, int image_noffset,
525 int node_noffset, const void *data, size_t size,
526 const char *cmdname)
527{
528 struct image_cipher_info info;
529 unsigned char *data_ciphered = NULL;
530 int data_ciphered_len;
531 int ret;
532
533 memset(&info, 0, sizeof(info));
534
535 ret = fit_image_setup_cipher(&info, keydir, fit, image_name,
536 image_noffset, node_noffset);
537 if (ret)
538 goto out;
539
540 ret = info.cipher->encrypt(&info, data, size,
541 &data_ciphered, &data_ciphered_len);
542 if (ret)
543 goto out;
544
545 /*
546 * Write the public key into the supplied FDT file; this might fail
547 * several times, since we try signing with successively increasing
548 * size values
549 * And, if needed, write the iv in the FIT file
550 */
551 if (keydest || (!keydest && !info.ivname)) {
552 ret = info.cipher->add_cipher_data(&info, keydest, fit, node_noffset);
553 if (ret) {
554 fprintf(stderr,
555 "Failed to add verification data for cipher '%s' in image '%s'\n",
556 info.keyname, image_name);
557 goto out;
558 }
559 }
560
561 ret = fit_image_write_cipher(fit, image_noffset, node_noffset,
562 data, size,
563 data_ciphered, data_ciphered_len);
564
565 out:
566 free(data_ciphered);
567 free((void *)info.key);
568 free((void *)info.iv);
569 return ret;
570}
571
572int fit_image_cipher_data(const char *keydir, void *keydest,
573 void *fit, int image_noffset, const char *comment,
574 int require_keys, const char *engine_id,
575 const char *cmdname)
576{
577 const char *image_name;
578 const void *data;
579 size_t size;
580 int cipher_node_offset, len;
581
582 /* Get image name */
583 image_name = fit_get_name(fit, image_noffset, NULL);
584 if (!image_name) {
585 fprintf(stderr, "Can't get image name\n");
586 return -1;
587 }
588
589 /* Get image data and data length */
590 if (fit_image_get_emb_data(fit, image_noffset, &data, &size)) {
591 fprintf(stderr, "Can't get image data/size\n");
592 return -1;
593 }
594
595 /*
596 * Don't cipher ciphered data.
597 *
598 * If the data-size-unciphered property is present the data for this
599 * image is already encrypted. This is important as 'mkimage -F' can be
600 * run multiple times on a FIT image.
601 */
602 if (fdt_getprop(fit, image_noffset, "data-size-unciphered", &len))
603 return 0;
604 if (len != -FDT_ERR_NOTFOUND) {
605 fprintf(stderr, "Failure testing for data-size-unciphered\n");
606 return -1;
607 }
608
609 /* Process cipher node if present */
610 cipher_node_offset = fdt_subnode_offset(fit, image_noffset,
611 FIT_CIPHER_NODENAME);
612 if (cipher_node_offset == -FDT_ERR_NOTFOUND)
613 return 0;
614 if (cipher_node_offset < 0) {
615 fprintf(stderr, "Failure getting cipher node\n");
616 return -1;
617 }
618 if (!IMAGE_ENABLE_ENCRYPT || !keydir)
619 return 0;
620 return fit_image_process_cipher(keydir, keydest, fit, image_name,
621 image_noffset, cipher_node_offset, data, size, cmdname);
622}
623
624/**
625 * fit_image_add_verification_data() - calculate/set verig. data for image node
626 *
627 * This adds hash and signature values for an component image node.
628 *
629 * All existing hash subnodes are checked, if algorithm property is set to
630 * one of the supported hash algorithms, hash value is computed and
631 * corresponding hash node property is set, for example:
632 *
633 * Input component image node structure:
634 *
635 * o image-1 (at image_noffset)
636 * | - data = [binary data]
637 * o hash-1
638 * |- algo = "sha1"
639 *
640 * Output component image node structure:
641 *
642 * o image-1 (at image_noffset)
643 * | - data = [binary data]
644 * o hash-1
645 * |- algo = "sha1"
646 * |- value = sha1(data)
647 *
648 * For signature details, please see doc/uImage.FIT/signature.txt
649 *
650 * @keydir Directory containing *.key and *.crt files (or NULL)
651 * @keydest FDT Blob to write public keys into (NULL if none)
652 * @fit: Pointer to the FIT format image header
653 * @image_noffset: Requested component image node
654 * @comment: Comment to add to signature nodes
655 * @require_keys: Mark all keys as 'required'
656 * @engine_id: Engine to use for signing
657 * @return: 0 on success, <0 on failure
658 */
659int fit_image_add_verification_data(const char *keydir, const char *keyfile,
660 void *keydest, void *fit, int image_noffset,
661 const char *comment, int require_keys, const char *engine_id,
662 const char *cmdname, const char* algo_name)
663{
664 const char *image_name;
665 const void *data;
666 size_t size;
667 int noffset;
668
669 /* Get image data and data length */
670 if (fit_image_get_emb_data(fit, image_noffset, &data, &size)) {
671 fprintf(stderr, "Can't get image data/size\n");
672 return -1;
673 }
674
675 image_name = fit_get_name(fit, image_noffset, NULL);
676
677 /* Process all hash subnodes of the component image node */
678 for (noffset = fdt_first_subnode(fit, image_noffset);
679 noffset >= 0;
680 noffset = fdt_next_subnode(fit, noffset)) {
681 const char *node_name;
682 int ret = 0;
683
684 /*
685 * Check subnode name, must be equal to "hash" or "signature".
686 * Multiple hash nodes require unique unit node
687 * names, e.g. hash-1, hash-2, signature-1, etc.
688 */
689 node_name = fit_get_name(fit, noffset, NULL);
690 if (!strncmp(node_name, FIT_HASH_NODENAME,
691 strlen(FIT_HASH_NODENAME))) {
692 ret = fit_image_process_hash(fit, image_name, noffset,
693 data, size);
694 } else if (IMAGE_ENABLE_SIGN && (keydir || keyfile) &&
695 !strncmp(node_name, FIT_SIG_NODENAME,
696 strlen(FIT_SIG_NODENAME))) {
697 ret = fit_image_process_sig(keydir, keyfile, keydest,
698 fit, image_name, noffset, data, size,
699 comment, require_keys, engine_id, cmdname,
700 algo_name);
701 }
702 if (ret < 0)
703 return ret;
704 }
705
706 return 0;
707}
708
709struct strlist {
710 int count;
711 char **strings;
712};
713
714static void strlist_init(struct strlist *list)
715{
716 memset(list, '\0', sizeof(*list));
717}
718
719static void strlist_free(struct strlist *list)
720{
721 int i;
722
723 for (i = 0; i < list->count; i++)
724 free(list->strings[i]);
725 free(list->strings);
726}
727
728static int strlist_add(struct strlist *list, const char *str)
729{
730 char *dup;
731
732 dup = strdup(str);
733 list->strings = realloc(list->strings,
734 (list->count + 1) * sizeof(char *));
735 if (!list || !str)
736 return -1;
737 list->strings[list->count++] = dup;
738
739 return 0;
740}
741
742static const char *fit_config_get_image_list(const void *fit, int noffset,
743 int *lenp, int *allow_missingp)
744{
745 static const char default_list[] = FIT_KERNEL_PROP "\0"
746 FIT_FDT_PROP "\0" FIT_SCRIPT_PROP;
747 const char *prop;
748
749 /* If there is an "sign-image" property, use that */
750 prop = fdt_getprop(fit, noffset, "sign-images", lenp);
751 if (prop) {
752 *allow_missingp = 0;
753 return *lenp ? prop : NULL;
754 }
755
756 /* Default image list */
757 *allow_missingp = 1;
758 *lenp = sizeof(default_list);
759
760 return default_list;
761}
762
763/**
764 * fit_config_add_hash() - Add a list of nodes to hash for an image
765 *
766 * This adds a list of paths to image nodes (as referred to by a particular
767 * offset) that need to be hashed, to protect a configuration
768 *
769 * @fit: Pointer to the FIT format image header
770 * @image_noffset: Offset of image to process (e.g. /images/kernel-1)
771 * @node_inc: List of nodes to add to
772 * @conf_name Configuration-node name, child of /configurations node (only
773 * used for error messages)
774 * @sig_name Signature-node name (only used for error messages)
775 * @iname: Name of image being processed (e.g. "kernel-1" (only used
776 * for error messages)
777 */
778static int fit_config_add_hash(const void *fit, int image_noffset,
779 struct strlist *node_inc, const char *conf_name,
780 const char *sig_name, const char *iname)
781{
782 char path[200];
783 int noffset;
784 int hash_count;
785 int ret;
786
787 ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
788 if (ret < 0)
789 goto err_path;
790 if (strlist_add(node_inc, path))
791 goto err_mem;
792
793 /* Add all this image's hashes */
794 hash_count = 0;
795 for (noffset = fdt_first_subnode(fit, image_noffset);
796 noffset >= 0;
797 noffset = fdt_next_subnode(fit, noffset)) {
798 const char *name = fit_get_name(fit, noffset, NULL);
799
800 if (strncmp(name, FIT_HASH_NODENAME,
801 strlen(FIT_HASH_NODENAME)))
802 continue;
803 ret = fdt_get_path(fit, noffset, path, sizeof(path));
804 if (ret < 0)
805 goto err_path;
806 if (strlist_add(node_inc, path))
807 goto err_mem;
808 hash_count++;
809 }
810
811 if (!hash_count) {
812 fprintf(stderr,
813 "Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
814 conf_name, sig_name, iname);
815 return -ENOMSG;
816 }
817
818 /* Add this image's cipher node if present */
819 noffset = fdt_subnode_offset(fit, image_noffset,
820 FIT_CIPHER_NODENAME);
821 if (noffset != -FDT_ERR_NOTFOUND) {
822 if (noffset < 0) {
823 fprintf(stderr,
824 "Failed to get cipher node in configuration '%s/%s' image '%s': %s\n",
825 conf_name, sig_name, iname,
826 fdt_strerror(noffset));
827 return -EIO;
828 }
829 ret = fdt_get_path(fit, noffset, path, sizeof(path));
830 if (ret < 0)
831 goto err_path;
832 if (strlist_add(node_inc, path))
833 goto err_mem;
834 }
835
836 return 0;
837
838err_mem:
839 fprintf(stderr, "Out of memory processing configuration '%s/%s'\n", conf_name,
840 sig_name);
841 return -ENOMEM;
842
843err_path:
844 fprintf(stderr, "Failed to get path for image '%s' in configuration '%s/%s': %s\n",
845 iname, conf_name, sig_name, fdt_strerror(ret));
846 return -ENOENT;
847}
848
849/**
850 * fit_config_get_hash_list() - Get the regions to sign
851 *
852 * This calculates a list of nodes to hash for this particular configuration,
853 * returning it as a string list (struct strlist, not a devicetree string list)
854 *
855 * @fit: Pointer to the FIT format image header
856 * @conf_noffset: Offset of configuration node to sign (child of
857 * /configurations node)
858 * @sig_offset: Offset of signature node containing info about how to sign it
859 * (child of 'signatures' node)
860 * @return 0 if OK, -ENOENT if an image referred to by the configuration cannot
861 * be found, -ENOMSG if ther were no images in the configuration
862 */
863static int fit_config_get_hash_list(const void *fit, int conf_noffset,
864 int sig_offset, struct strlist *node_inc)
865{
866 int allow_missing;
867 const char *prop, *iname, *end;
868 const char *conf_name, *sig_name;
869 char name[200];
870 int image_count;
871 int ret, len;
872
873 conf_name = fit_get_name(fit, conf_noffset, NULL);
874 sig_name = fit_get_name(fit, sig_offset, NULL);
875
876 /*
877 * Build a list of nodes we need to hash. We always need the root
878 * node and the configuration.
879 */
880 strlist_init(node_inc);
881 snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name);
882 if (strlist_add(node_inc, "/") ||
883 strlist_add(node_inc, name))
884 goto err_mem;
885
886 /* Get a list of images that we intend to sign */
887 prop = fit_config_get_image_list(fit, sig_offset, &len,
888 &allow_missing);
889 if (!prop)
890 return 0;
891
892 /* Locate the images */
893 end = prop + len;
894 image_count = 0;
895 for (iname = prop; iname < end; iname += strlen(iname) + 1) {
896 int image_noffset;
897 int index, max_index;
898
899 max_index = fdt_stringlist_count(fit, conf_noffset, iname);
900
901 for (index = 0; index < max_index; index++) {
902 image_noffset = fit_conf_get_prop_node_index(fit, conf_noffset,
903 iname, index);
904
905 if (image_noffset < 0) {
906 fprintf(stderr,
907 "Failed to find image '%s' in configuration '%s/%s'\n",
908 iname, conf_name, sig_name);
909 if (allow_missing)
910 continue;
911
912 return -ENOENT;
913 }
914
915 ret = fit_config_add_hash(fit, image_noffset, node_inc,
916 conf_name, sig_name, iname);
917 if (ret < 0)
918 return ret;
919
920 image_count++;
921 }
922 }
923
924 if (!image_count) {
925 fprintf(stderr, "Failed to find any images for configuration '%s/%s'\n",
926 conf_name, sig_name);
927 return -ENOMSG;
928 }
929
930 return 0;
931
932err_mem:
933 fprintf(stderr, "Out of memory processing configuration '%s/%s'\n", conf_name,
934 sig_name);
935 return -ENOMEM;
936}
937
938/**
939 * fit_config_get_regions() - Get the regions to sign
940 *
941 * This calculates a list of node to hash for this particular configuration,
942 * then finds which regions of the devicetree they correspond to.
943 *
944 * @fit: Pointer to the FIT format image header
945 * @conf_noffset: Offset of configuration node to sign (child of
946 * /configurations node)
947 * @sig_offset: Offset of signature node containing info about how to sign it
948 * (child of 'signatures' node)
949 * @regionp: Returns list of regions that need to be hashed (allocated; must be
950 * freed by the caller)
951 * @region_count: Returns number of regions
952 * @region_propp: Returns string-list property containing the list of nodes
953 * that correspond to the regions. Each entry is a full path to the node.
954 * This is in devicetree format, i.e. a \0 between each string. This is
955 * allocated and must be freed by the caller.
956 * @region_proplen: Returns length of *@@region_propp in bytes
957 * @return 0 if OK, -ENOMEM if out of memory, -EIO if the regions to hash could
958 * not be found, -EINVAL if no registers were found to hash
959 */
960static int fit_config_get_regions(const void *fit, int conf_noffset,
961 int sig_offset, struct image_region **regionp,
962 int *region_countp, char **region_propp,
963 int *region_proplen)
964{
965 char * const exc_prop[] = {
966 FIT_DATA_PROP,
967 FIT_DATA_SIZE_PROP,
968 FIT_DATA_POSITION_PROP,
969 FIT_DATA_OFFSET_PROP,
970 };
971 struct strlist node_inc;
972 struct image_region *region;
973 struct fdt_region fdt_regions[100];
974 const char *conf_name, *sig_name;
975 char path[200];
976 int count, i;
977 char *region_prop;
978 int ret, len;
979
980 conf_name = fit_get_name(fit, conf_noffset, NULL);
981 sig_name = fit_get_name(fit, sig_offset, NULL);
982 debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
983
984 /* Get a list of nodes we want to hash */
985 ret = fit_config_get_hash_list(fit, conf_noffset, sig_offset,
986 &node_inc);
987 if (ret)
988 return ret;
989
990 /* Get a list of regions to hash */
991 count = fdt_find_regions(fit, node_inc.strings, node_inc.count,
992 exc_prop, ARRAY_SIZE(exc_prop),
993 fdt_regions, ARRAY_SIZE(fdt_regions),
994 path, sizeof(path), 1);
995 if (count < 0) {
996 fprintf(stderr, "Failed to hash configuration '%s/%s': %s\n", conf_name,
997 sig_name, fdt_strerror(ret));
998 return -EIO;
999 }
1000 if (count == 0) {
1001 fprintf(stderr, "No data to hash for configuration '%s/%s': %s\n",
1002 conf_name, sig_name, fdt_strerror(ret));
1003 return -EINVAL;
1004 }
1005
1006 /* Build our list of data blocks */
1007 region = fit_region_make_list(fit, fdt_regions, count, NULL);
1008 if (!region) {
1009 fprintf(stderr, "Out of memory hashing configuration '%s/%s'\n",
1010 conf_name, sig_name);
1011 return -ENOMEM;
1012 }
1013
1014 /* Create a list of all hashed properties */
1015 debug("Hash nodes:\n");
1016 for (i = len = 0; i < node_inc.count; i++) {
1017 debug(" %s\n", node_inc.strings[i]);
1018 len += strlen(node_inc.strings[i]) + 1;
1019 }
1020 region_prop = malloc(len);
1021 if (!region_prop) {
1022 fprintf(stderr, "Out of memory setting up regions for configuration '%s/%s'\n",
1023 conf_name, sig_name);
1024 return -ENOMEM;
1025 }
1026 for (i = len = 0; i < node_inc.count;
1027 len += strlen(node_inc.strings[i]) + 1, i++)
1028 strcpy(region_prop + len, node_inc.strings[i]);
1029 strlist_free(&node_inc);
1030
1031 *region_countp = count;
1032 *regionp = region;
1033 *region_propp = region_prop;
1034 *region_proplen = len;
1035
1036 return 0;
1037}
1038
1039/**
1040 * fit_config_process_sig - Process a single subnode of the configurations/ node
1041 *
1042 * Generate a signed hash of the supplied data and store it in the node.
1043 *
1044 * @keydir: Directory containing keys to use for signing
1045 * @keydest: Destination FDT blob to write public keys into (NULL if none)
1046 * @fit: pointer to the FIT format image header
1047 * @conf_name name of config being processed (used to display errors)
1048 * @conf_noffset: Offset of configuration node, e.g. '/configurations/conf-1'
1049 * @noffset: subnode offset, e.g. '/configurations/conf-1/sig-1'
1050 * @comment: Comment to add to signature nodes
1051 * @require_keys: Mark all keys as 'required'
1052 * @engine_id: Engine to use for signing
1053 * @cmdname: Command name used when reporting errors
1054 * @return keydest node if @keydest is non-NULL, else 0 if none; -ve error code
1055 * on failure
1056 */
1057static int fit_config_process_sig(const char *keydir, const char *keyfile,
1058 void *keydest, void *fit, const char *conf_name,
1059 int conf_noffset, int noffset, const char *comment,
1060 int require_keys, const char *engine_id, const char *cmdname,
1061 const char *algo_name)
1062{
1063 struct image_sign_info info;
1064 const char *node_name;
1065 struct image_region *region;
1066 char *region_prop;
1067 int region_proplen;
1068 int region_count;
1069 uint8_t *value;
1070 uint value_len;
1071 int ret;
1072
1073 node_name = fit_get_name(fit, noffset, NULL);
1074 if (fit_config_get_regions(fit, conf_noffset, noffset, ®ion,
1075 ®ion_count, ®ion_prop,
1076 ®ion_proplen))
1077 return -1;
1078
1079 if (fit_image_setup_sig(&info, keydir, keyfile, fit, conf_name, noffset,
1080 require_keys ? "conf" : NULL, engine_id,
1081 algo_name))
1082 return -1;
1083
1084 ret = info.crypto->sign(&info, region, region_count, &value,
1085 &value_len);
1086 free(region);
1087 if (ret) {
1088 fprintf(stderr, "Failed to sign '%s' signature node in '%s' conf node\n",
1089 node_name, conf_name);
1090
1091 /* We allow keys to be missing */
1092 if (ret == -ENOENT)
1093 return 0;
1094 return -1;
1095 }
1096
1097 ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
1098 region_prop, region_proplen, cmdname,
1099 algo_name);
1100 if (ret) {
1101 if (ret == -FDT_ERR_NOSPACE)
1102 return -ENOSPC;
1103 fprintf(stderr,
1104 "Can't write signature for '%s' signature node in '%s' conf node: %s\n",
1105 node_name, conf_name, fdt_strerror(ret));
1106 return -1;
1107 }
1108 free(value);
1109 free(region_prop);
1110
1111 /* Get keyname again, as FDT has changed and invalidated our pointer */
1112 info.keyname = fdt_getprop(fit, noffset, FIT_KEY_HINT, NULL);
1113
1114 /* Write the public key into the supplied FDT file */
1115 if (keydest) {
1116 ret = info.crypto->add_verify_data(&info, keydest);
1117 if (ret < 0) {
1118 fprintf(stderr,
1119 "Failed to add verification data for '%s' signature node in '%s' configuration node\n",
1120 node_name, conf_name);
1121 }
1122 return ret;
1123 }
1124
1125 return 0;
1126}
1127
1128static int fit_config_add_verification_data(const char *keydir,
1129 const char *keyfile, void *keydest, void *fit, int conf_noffset,
1130 const char *comment, int require_keys, const char *engine_id,
1131 const char *cmdname, const char *algo_name,
1132 struct image_summary *summary)
1133{
1134 const char *conf_name;
1135 int noffset;
1136
1137 conf_name = fit_get_name(fit, conf_noffset, NULL);
1138
1139 /* Process all hash subnodes of the configuration node */
1140 for (noffset = fdt_first_subnode(fit, conf_noffset);
1141 noffset >= 0;
1142 noffset = fdt_next_subnode(fit, noffset)) {
1143 const char *node_name;
1144 int ret = 0;
1145
1146 node_name = fit_get_name(fit, noffset, NULL);
1147 if (!strncmp(node_name, FIT_SIG_NODENAME,
1148 strlen(FIT_SIG_NODENAME))) {
1149 ret = fit_config_process_sig(keydir, keyfile, keydest,
1150 fit, conf_name, conf_noffset, noffset, comment,
1151 require_keys, engine_id, cmdname, algo_name);
1152 if (ret < 0)
1153 return ret;
1154
1155 summary->sig_offset = noffset;
1156 fdt_get_path(fit, noffset, summary->sig_path,
1157 sizeof(summary->sig_path));
1158
1159 if (keydest) {
1160 summary->keydest_offset = ret;
1161 fdt_get_path(keydest, ret,
1162 summary->keydest_path,
1163 sizeof(summary->keydest_path));
1164 }
1165 }
1166 }
1167
1168 return 0;
1169}
1170
1171#if CONFIG_IS_ENABLED(FIT_SIGNATURE)
1172/*
1173 * 0) open file (open)
1174 * 1) read certificate (PEM_read_X509)
1175 * 2) get public key (X509_get_pubkey)
1176 * 3) provide der format (d2i_RSAPublicKey)
1177 */
1178static int read_pub_key(const char *keydir, const void *name,
1179 unsigned char **pubkey, int *pubkey_len)
1180{
1181 char path[1024];
1182 EVP_PKEY *key = NULL;
1183 X509 *cert;
1184 FILE *f;
1185 int ret;
1186
1187 memset(path, 0, 1024);
1188 snprintf(path, sizeof(path), "%s/%s.crt", keydir, (char *)name);
1189
1190 /* Open certificate file */
1191 f = fopen(path, "r");
1192 if (!f) {
1193 fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
1194 path, strerror(errno));
1195 return -EACCES;
1196 }
1197
1198 /* Read the certificate */
1199 cert = NULL;
1200 if (!PEM_read_X509(f, &cert, NULL, NULL)) {
1201 fprintf(stderr, "Couldn't read certificate");
1202 ret = -EINVAL;
1203 goto err_cert;
1204 }
1205
1206 /* Get the public key from the certificate. */
1207 key = X509_get_pubkey(cert);
1208 if (!key) {
1209 fprintf(stderr, "Couldn't read public key\n");
1210 ret = -EINVAL;
1211 goto err_pubkey;
1212 }
1213
1214 /* Get DER form */
1215 ret = i2d_PublicKey(key, pubkey);
1216 if (ret < 0) {
1217 fprintf(stderr, "Couldn't get DER form\n");
1218 ret = -EINVAL;
1219 goto err_pubkey;
1220 }
1221
1222 *pubkey_len = ret;
1223 ret = 0;
1224
1225err_pubkey:
1226 X509_free(cert);
1227err_cert:
1228 fclose(f);
1229 return ret;
1230}
1231
1232int fit_pre_load_data(const char *keydir, void *keydest, void *fit)
1233{
1234 int pre_load_noffset;
1235 const void *algo_name;
1236 const void *key_name;
1237 unsigned char *pubkey = NULL;
1238 int ret, pubkey_len;
1239
1240 if (!keydir || !keydest || !fit)
1241 return 0;
1242
1243 /* Search node pre-load sig */
1244 pre_load_noffset = fdt_path_offset(keydest, IMAGE_PRE_LOAD_PATH);
1245 if (pre_load_noffset < 0) {
1246 ret = 0;
1247 goto out;
1248 }
1249
1250 algo_name = fdt_getprop(keydest, pre_load_noffset, "algo-name", NULL);
1251 key_name = fdt_getprop(keydest, pre_load_noffset, "key-name", NULL);
1252
1253 /* Check that all mandatory properties are present */
1254 if (!algo_name || !key_name) {
1255 if (!algo_name)
1256 fprintf(stderr, "The property algo-name is missing in the node %s\n",
1257 IMAGE_PRE_LOAD_PATH);
1258 if (!key_name)
1259 fprintf(stderr, "The property key-name is missing in the node %s\n",
1260 IMAGE_PRE_LOAD_PATH);
1261 ret = -EINVAL;
1262 goto out;
1263 }
1264
1265 /* Read public key */
1266 ret = read_pub_key(keydir, key_name, &pubkey, &pubkey_len);
1267 if (ret < 0)
1268 goto out;
1269
1270 /* Add the public key to the device tree */
1271 ret = fdt_setprop(keydest, pre_load_noffset, "public-key",
1272 pubkey, pubkey_len);
1273 if (ret)
1274 fprintf(stderr, "Can't set public-key in node %s (ret = %d)\n",
1275 IMAGE_PRE_LOAD_PATH, ret);
1276
1277 out:
1278 return ret;
1279}
1280#endif
1281
1282int fit_cipher_data(const char *keydir, void *keydest, void *fit,
1283 const char *comment, int require_keys,
1284 const char *engine_id, const char *cmdname)
1285{
1286 int images_noffset;
1287 int noffset;
1288 int ret;
1289
1290 /* Find images parent node offset */
1291 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1292 if (images_noffset < 0) {
1293 fprintf(stderr, "Can't find images parent node '%s' (%s)\n",
1294 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
1295 return images_noffset;
1296 }
1297
1298 /* Process its subnodes, print out component images details */
1299 for (noffset = fdt_first_subnode(fit, images_noffset);
1300 noffset >= 0;
1301 noffset = fdt_next_subnode(fit, noffset)) {
1302 /*
1303 * Direct child node of the images parent node,
1304 * i.e. component image node.
1305 */
1306 ret = fit_image_cipher_data(keydir, keydest,
1307 fit, noffset, comment,
1308 require_keys, engine_id,
1309 cmdname);
1310 if (ret)
1311 return ret;
1312 }
1313
1314 return 0;
1315}
1316
1317int fit_add_verification_data(const char *keydir, const char *keyfile,
1318 void *keydest, void *fit, const char *comment,
1319 int require_keys, const char *engine_id,
1320 const char *cmdname, const char *algo_name,
1321 struct image_summary *summary)
1322{
1323 int images_noffset, confs_noffset;
1324 int noffset;
1325 int ret;
1326
1327 /* Find images parent node offset */
1328 images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
1329 if (images_noffset < 0) {
1330 fprintf(stderr, "Can't find images parent node '%s' (%s)\n",
1331 FIT_IMAGES_PATH, fdt_strerror(images_noffset));
1332 return images_noffset;
1333 }
1334
1335 /* Process its subnodes, print out component images details */
1336 for (noffset = fdt_first_subnode(fit, images_noffset);
1337 noffset >= 0;
1338 noffset = fdt_next_subnode(fit, noffset)) {
1339 /*
1340 * Direct child node of the images parent node,
1341 * i.e. component image node.
1342 */
1343 ret = fit_image_add_verification_data(keydir, keyfile, keydest,
1344 fit, noffset, comment, require_keys, engine_id,
1345 cmdname, algo_name);
1346 if (ret) {
1347 fprintf(stderr, "Can't add verification data for node '%s' (%s)\n",
1348 fdt_get_name(fit, noffset, NULL),
1349 strerror(-ret));
1350 return ret;
1351 }
1352 }
1353
1354 /* If there are no keys, we can't sign configurations */
1355 if (!IMAGE_ENABLE_SIGN || !(keydir || keyfile))
1356 return 0;
1357
1358 /* Find configurations parent node offset */
1359 confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
1360 if (confs_noffset < 0) {
1361 fprintf(stderr, "Can't find images parent node '%s' (%s)\n",
1362 FIT_CONFS_PATH, fdt_strerror(confs_noffset));
1363 return -ENOENT;
1364 }
1365
1366 /* Process its subnodes, print out component images details */
1367 for (noffset = fdt_first_subnode(fit, confs_noffset);
1368 noffset >= 0;
1369 noffset = fdt_next_subnode(fit, noffset)) {
1370 ret = fit_config_add_verification_data(keydir, keyfile, keydest,
1371 fit, noffset, comment,
1372 require_keys,
1373 engine_id, cmdname,
1374 algo_name, summary);
1375 if (ret)
1376 return ret;
1377 }
1378
1379 return 0;
1380}
1381
1382#ifdef CONFIG_FIT_SIGNATURE
1383int fit_check_sign(const void *fit, const void *key,
1384 const char *fit_uname_config)
1385{
1386 int cfg_noffset;
1387 int ret;
1388
1389 cfg_noffset = fit_conf_get_node(fit, fit_uname_config);
1390 if (!cfg_noffset)
1391 return -1;
1392
1393 printf("Verifying Hash Integrity for node '%s'... ",
1394 fdt_get_name(fit, cfg_noffset, NULL));
1395 ret = fit_config_verify(fit, cfg_noffset);
1396 if (ret)
1397 return ret;
1398 printf("Verified OK, loading images\n");
1399 ret = bootm_host_load_images(fit, cfg_noffset);
1400
1401 return ret;
1402}
1403#endif