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