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