blob: 8c6637e3287e5d3fd069c3523bdd7b196c11544c [file] [log] [blame]
Simon Glass19c402a2013-06-13 15:10:02 -07001/*
2 * Copyright (c) 2013, Google Inc.
3 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02004 * SPDX-License-Identifier: GPL-2.0+
Simon Glass19c402a2013-06-13 15:10:02 -07005 */
6
7#include "mkimage.h"
8#include <stdio.h>
9#include <string.h>
Simon Glass19c402a2013-06-13 15:10:02 -070010#include <image.h>
11#include <time.h>
12#include <openssl/rsa.h>
13#include <openssl/pem.h>
14#include <openssl/err.h>
15#include <openssl/ssl.h>
16#include <openssl/evp.h>
George McCollisterf1ca1fd2017-01-06 13:14:17 -060017#include <openssl/engine.h>
Simon Glass19c402a2013-06-13 15:10:02 -070018
19#if OPENSSL_VERSION_NUMBER >= 0x10000000L
20#define HAVE_ERR_REMOVE_THREAD_STATE
21#endif
22
23static int rsa_err(const char *msg)
24{
25 unsigned long sslErr = ERR_get_error();
26
27 fprintf(stderr, "%s", msg);
28 fprintf(stderr, ": %s\n",
29 ERR_error_string(sslErr, 0));
30
31 return -1;
32}
33
34/**
George McCollisterf1ca1fd2017-01-06 13:14:17 -060035 * rsa_pem_get_pub_key() - read a public key from a .crt file
Simon Glass19c402a2013-06-13 15:10:02 -070036 *
37 * @keydir: Directory containins the key
38 * @name Name of key file (will have a .crt extension)
39 * @rsap Returns RSA object, or NULL on failure
40 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
41 */
George McCollisterf1ca1fd2017-01-06 13:14:17 -060042static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap)
Simon Glass19c402a2013-06-13 15:10:02 -070043{
44 char path[1024];
45 EVP_PKEY *key;
46 X509 *cert;
47 RSA *rsa;
48 FILE *f;
49 int ret;
50
51 *rsap = NULL;
52 snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
53 f = fopen(path, "r");
54 if (!f) {
55 fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
56 path, strerror(errno));
57 return -EACCES;
58 }
59
60 /* Read the certificate */
61 cert = NULL;
62 if (!PEM_read_X509(f, &cert, NULL, NULL)) {
63 rsa_err("Couldn't read certificate");
64 ret = -EINVAL;
65 goto err_cert;
66 }
67
68 /* Get the public key from the certificate. */
69 key = X509_get_pubkey(cert);
70 if (!key) {
71 rsa_err("Couldn't read public key\n");
72 ret = -EINVAL;
73 goto err_pubkey;
74 }
75
76 /* Convert to a RSA_style key. */
77 rsa = EVP_PKEY_get1_RSA(key);
78 if (!rsa) {
79 rsa_err("Couldn't convert to a RSA style key");
Simon Glass54267162014-07-30 10:00:17 -060080 ret = -EINVAL;
Simon Glass19c402a2013-06-13 15:10:02 -070081 goto err_rsa;
82 }
83 fclose(f);
84 EVP_PKEY_free(key);
85 X509_free(cert);
86 *rsap = rsa;
87
88 return 0;
89
90err_rsa:
91 EVP_PKEY_free(key);
92err_pubkey:
93 X509_free(cert);
94err_cert:
95 fclose(f);
96 return ret;
97}
98
99/**
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600100 * rsa_engine_get_pub_key() - read a public key from given engine
Simon Glass19c402a2013-06-13 15:10:02 -0700101 *
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600102 * @keydir: Key prefix
103 * @name Name of key
104 * @engine Engine to use
105 * @rsap Returns RSA object, or NULL on failure
106 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
107 */
108static int rsa_engine_get_pub_key(const char *keydir, const char *name,
109 ENGINE *engine, RSA **rsap)
110{
111 const char *engine_id;
112 char key_id[1024];
113 EVP_PKEY *key;
114 RSA *rsa;
115 int ret;
116
117 *rsap = NULL;
118
119 engine_id = ENGINE_get_id(engine);
120
121 if (engine_id && !strcmp(engine_id, "pkcs11")) {
122 if (keydir)
123 snprintf(key_id, sizeof(key_id),
124 "pkcs11:%s;object=%s;type=public",
125 keydir, name);
126 else
127 snprintf(key_id, sizeof(key_id),
128 "pkcs11:object=%s;type=public",
129 name);
130 } else {
131 fprintf(stderr, "Engine not supported\n");
132 return -ENOTSUP;
133 }
134
135 key = ENGINE_load_public_key(engine, key_id, NULL, NULL);
136 if (!key)
137 return rsa_err("Failure loading public key from engine");
138
139 /* Convert to a RSA_style key. */
140 rsa = EVP_PKEY_get1_RSA(key);
141 if (!rsa) {
142 rsa_err("Couldn't convert to a RSA style key");
143 ret = -EINVAL;
144 goto err_rsa;
145 }
146
147 EVP_PKEY_free(key);
148 *rsap = rsa;
149
150 return 0;
151
152err_rsa:
153 EVP_PKEY_free(key);
154 return ret;
155}
156
157/**
158 * rsa_get_pub_key() - read a public key
159 *
160 * @keydir: Directory containing the key (PEM file) or key prefix (engine)
161 * @name Name of key file (will have a .crt extension)
162 * @engine Engine to use
163 * @rsap Returns RSA object, or NULL on failure
164 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
165 */
166static int rsa_get_pub_key(const char *keydir, const char *name,
167 ENGINE *engine, RSA **rsap)
168{
169 if (engine)
170 return rsa_engine_get_pub_key(keydir, name, engine, rsap);
171 return rsa_pem_get_pub_key(keydir, name, rsap);
172}
173
174/**
175 * rsa_pem_get_priv_key() - read a private key from a .key file
176 *
177 * @keydir: Directory containing the key
Simon Glass19c402a2013-06-13 15:10:02 -0700178 * @name Name of key file (will have a .key extension)
179 * @rsap Returns RSA object, or NULL on failure
180 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
181 */
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600182static int rsa_pem_get_priv_key(const char *keydir, const char *name,
183 RSA **rsap)
Simon Glass19c402a2013-06-13 15:10:02 -0700184{
185 char path[1024];
186 RSA *rsa;
187 FILE *f;
188
189 *rsap = NULL;
190 snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
191 f = fopen(path, "r");
192 if (!f) {
193 fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
194 path, strerror(errno));
195 return -ENOENT;
196 }
197
198 rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
199 if (!rsa) {
200 rsa_err("Failure reading private key");
201 fclose(f);
202 return -EPROTO;
203 }
204 fclose(f);
205 *rsap = rsa;
206
207 return 0;
208}
209
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600210/**
211 * rsa_engine_get_priv_key() - read a private key from given engine
212 *
213 * @keydir: Key prefix
214 * @name Name of key
215 * @engine Engine to use
216 * @rsap Returns RSA object, or NULL on failure
217 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
218 */
219static int rsa_engine_get_priv_key(const char *keydir, const char *name,
220 ENGINE *engine, RSA **rsap)
221{
222 const char *engine_id;
223 char key_id[1024];
224 EVP_PKEY *key;
225 RSA *rsa;
226 int ret;
227
228 *rsap = NULL;
229
230 engine_id = ENGINE_get_id(engine);
231
232 if (engine_id && !strcmp(engine_id, "pkcs11")) {
233 if (keydir)
234 snprintf(key_id, sizeof(key_id),
235 "pkcs11:%s;object=%s;type=private",
236 keydir, name);
237 else
238 snprintf(key_id, sizeof(key_id),
239 "pkcs11:object=%s;type=private",
240 name);
241 } else {
242 fprintf(stderr, "Engine not supported\n");
243 return -ENOTSUP;
244 }
245
246 key = ENGINE_load_private_key(engine, key_id, NULL, NULL);
247 if (!key)
248 return rsa_err("Failure loading private key from engine");
249
250 /* Convert to a RSA_style key. */
251 rsa = EVP_PKEY_get1_RSA(key);
252 if (!rsa) {
253 rsa_err("Couldn't convert to a RSA style key");
254 ret = -EINVAL;
255 goto err_rsa;
256 }
257
258 EVP_PKEY_free(key);
259 *rsap = rsa;
260
261 return 0;
262
263err_rsa:
264 EVP_PKEY_free(key);
265 return ret;
266}
267
268/**
269 * rsa_get_priv_key() - read a private key
270 *
271 * @keydir: Directory containing the key (PEM file) or key prefix (engine)
272 * @name Name of key
273 * @engine Engine to use for signing
274 * @rsap Returns RSA object, or NULL on failure
275 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
276 */
277static int rsa_get_priv_key(const char *keydir, const char *name,
278 ENGINE *engine, RSA **rsap)
279{
280 if (engine)
281 return rsa_engine_get_priv_key(keydir, name, engine, rsap);
282 return rsa_pem_get_priv_key(keydir, name, rsap);
283}
284
Simon Glass19c402a2013-06-13 15:10:02 -0700285static int rsa_init(void)
286{
287 int ret;
288
289 ret = SSL_library_init();
290 if (!ret) {
291 fprintf(stderr, "Failure to init SSL library\n");
292 return -1;
293 }
294 SSL_load_error_strings();
295
296 OpenSSL_add_all_algorithms();
297 OpenSSL_add_all_digests();
298 OpenSSL_add_all_ciphers();
299
300 return 0;
301}
302
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600303static int rsa_engine_init(const char *engine_id, ENGINE **pe)
304{
305 ENGINE *e;
306 int ret;
307
308 ENGINE_load_builtin_engines();
309
310 e = ENGINE_by_id(engine_id);
311 if (!e) {
312 fprintf(stderr, "Engine isn't available\n");
313 ret = -1;
314 goto err_engine_by_id;
315 }
316
317 if (!ENGINE_init(e)) {
318 fprintf(stderr, "Couldn't initialize engine\n");
319 ret = -1;
320 goto err_engine_init;
321 }
322
323 if (!ENGINE_set_default_RSA(e)) {
324 fprintf(stderr, "Couldn't set engine as default for RSA\n");
325 ret = -1;
326 goto err_set_rsa;
327 }
328
329 *pe = e;
330
331 return 0;
332
333err_set_rsa:
334 ENGINE_finish(e);
335err_engine_init:
336 ENGINE_free(e);
337err_engine_by_id:
338 ENGINE_cleanup();
339 return ret;
340}
341
Simon Glass19c402a2013-06-13 15:10:02 -0700342static void rsa_remove(void)
343{
344 CRYPTO_cleanup_all_ex_data();
345 ERR_free_strings();
346#ifdef HAVE_ERR_REMOVE_THREAD_STATE
347 ERR_remove_thread_state(NULL);
348#else
349 ERR_remove_state(0);
350#endif
351 EVP_cleanup();
352}
353
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600354static void rsa_engine_remove(ENGINE *e)
355{
356 if (e) {
357 ENGINE_finish(e);
358 ENGINE_free(e);
359 }
360}
361
Heiko Schocher646257d2014-03-03 12:19:26 +0100362static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
363 const struct image_region region[], int region_count,
364 uint8_t **sigp, uint *sig_size)
Simon Glass19c402a2013-06-13 15:10:02 -0700365{
366 EVP_PKEY *key;
367 EVP_MD_CTX *context;
368 int size, ret = 0;
369 uint8_t *sig;
370 int i;
371
372 key = EVP_PKEY_new();
373 if (!key)
374 return rsa_err("EVP_PKEY object creation failed");
375
376 if (!EVP_PKEY_set1_RSA(key, rsa)) {
377 ret = rsa_err("EVP key setup failed");
378 goto err_set;
379 }
380
381 size = EVP_PKEY_size(key);
382 sig = malloc(size);
383 if (!sig) {
384 fprintf(stderr, "Out of memory for signature (%d bytes)\n",
385 size);
386 ret = -ENOMEM;
387 goto err_alloc;
388 }
389
390 context = EVP_MD_CTX_create();
391 if (!context) {
392 ret = rsa_err("EVP context creation failed");
393 goto err_create;
394 }
395 EVP_MD_CTX_init(context);
Heiko Schocher29a23f92014-03-03 12:19:30 +0100396 if (!EVP_SignInit(context, checksum_algo->calculate_sign())) {
Simon Glass19c402a2013-06-13 15:10:02 -0700397 ret = rsa_err("Signer setup failed");
398 goto err_sign;
399 }
400
401 for (i = 0; i < region_count; i++) {
402 if (!EVP_SignUpdate(context, region[i].data, region[i].size)) {
403 ret = rsa_err("Signing data failed");
404 goto err_sign;
405 }
406 }
407
408 if (!EVP_SignFinal(context, sig, sig_size, key)) {
409 ret = rsa_err("Could not obtain signature");
410 goto err_sign;
411 }
412 EVP_MD_CTX_cleanup(context);
413 EVP_MD_CTX_destroy(context);
414 EVP_PKEY_free(key);
415
416 debug("Got signature: %d bytes, expected %d\n", *sig_size, size);
417 *sigp = sig;
418 *sig_size = size;
419
420 return 0;
421
422err_sign:
423 EVP_MD_CTX_destroy(context);
424err_create:
425 free(sig);
426err_alloc:
427err_set:
428 EVP_PKEY_free(key);
429 return ret;
430}
431
432int rsa_sign(struct image_sign_info *info,
433 const struct image_region region[], int region_count,
434 uint8_t **sigp, uint *sig_len)
435{
436 RSA *rsa;
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600437 ENGINE *e = NULL;
Simon Glass19c402a2013-06-13 15:10:02 -0700438 int ret;
439
440 ret = rsa_init();
441 if (ret)
442 return ret;
443
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600444 if (info->engine_id) {
445 ret = rsa_engine_init(info->engine_id, &e);
446 if (ret)
447 goto err_engine;
448 }
449
450 ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
Simon Glass19c402a2013-06-13 15:10:02 -0700451 if (ret)
452 goto err_priv;
Andrew Duda83dd98e2016-11-08 18:53:41 +0000453 ret = rsa_sign_with_key(rsa, info->checksum, region,
Heiko Schocher646257d2014-03-03 12:19:26 +0100454 region_count, sigp, sig_len);
Simon Glass19c402a2013-06-13 15:10:02 -0700455 if (ret)
456 goto err_sign;
457
458 RSA_free(rsa);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600459 if (info->engine_id)
460 rsa_engine_remove(e);
Simon Glass19c402a2013-06-13 15:10:02 -0700461 rsa_remove();
462
463 return ret;
464
465err_sign:
466 RSA_free(rsa);
467err_priv:
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600468 if (info->engine_id)
469 rsa_engine_remove(e);
470err_engine:
Simon Glass19c402a2013-06-13 15:10:02 -0700471 rsa_remove();
472 return ret;
473}
474
475/*
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200476 * rsa_get_exponent(): - Get the public exponent from an RSA key
477 */
478static int rsa_get_exponent(RSA *key, uint64_t *e)
479{
480 int ret;
481 BIGNUM *bn_te;
482 uint64_t te;
483
484 ret = -EINVAL;
485 bn_te = NULL;
486
487 if (!e)
488 goto cleanup;
489
490 if (BN_num_bits(key->e) > 64)
491 goto cleanup;
492
493 *e = BN_get_word(key->e);
494
495 if (BN_num_bits(key->e) < 33) {
496 ret = 0;
497 goto cleanup;
498 }
499
500 bn_te = BN_dup(key->e);
501 if (!bn_te)
502 goto cleanup;
503
504 if (!BN_rshift(bn_te, bn_te, 32))
505 goto cleanup;
506
507 if (!BN_mask_bits(bn_te, 32))
508 goto cleanup;
509
510 te = BN_get_word(bn_te);
511 te <<= 32;
512 *e |= te;
513 ret = 0;
514
515cleanup:
516 if (bn_te)
517 BN_free(bn_te);
518
519 return ret;
520}
521
522/*
Simon Glass19c402a2013-06-13 15:10:02 -0700523 * rsa_get_params(): - Get the important parameters of an RSA public key
524 */
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200525int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
526 BIGNUM **modulusp, BIGNUM **r_squaredp)
Simon Glass19c402a2013-06-13 15:10:02 -0700527{
528 BIGNUM *big1, *big2, *big32, *big2_32;
529 BIGNUM *n, *r, *r_squared, *tmp;
530 BN_CTX *bn_ctx = BN_CTX_new();
531 int ret = 0;
532
533 /* Initialize BIGNUMs */
534 big1 = BN_new();
535 big2 = BN_new();
536 big32 = BN_new();
537 r = BN_new();
538 r_squared = BN_new();
539 tmp = BN_new();
540 big2_32 = BN_new();
541 n = BN_new();
542 if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
543 !n) {
544 fprintf(stderr, "Out of memory (bignum)\n");
545 return -ENOMEM;
546 }
547
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200548 if (0 != rsa_get_exponent(key, exponent))
549 ret = -1;
550
Simon Glass19c402a2013-06-13 15:10:02 -0700551 if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) ||
552 !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
553 ret = -1;
554
555 /* big2_32 = 2^32 */
556 if (!BN_exp(big2_32, big2, big32, bn_ctx))
557 ret = -1;
558
559 /* Calculate n0_inv = -1 / n[0] mod 2^32 */
560 if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
561 !BN_sub(tmp, big2_32, tmp))
562 ret = -1;
563 *n0_invp = BN_get_word(tmp);
564
565 /* Calculate R = 2^(# of key bits) */
566 if (!BN_set_word(tmp, BN_num_bits(n)) ||
567 !BN_exp(r, big2, tmp, bn_ctx))
568 ret = -1;
569
570 /* Calculate r_squared = R^2 mod n */
571 if (!BN_copy(r_squared, r) ||
572 !BN_mul(tmp, r_squared, r, bn_ctx) ||
573 !BN_mod(r_squared, tmp, n, bn_ctx))
574 ret = -1;
575
576 *modulusp = n;
577 *r_squaredp = r_squared;
578
579 BN_free(big1);
580 BN_free(big2);
581 BN_free(big32);
582 BN_free(r);
583 BN_free(tmp);
584 BN_free(big2_32);
585 if (ret) {
586 fprintf(stderr, "Bignum operations failed\n");
587 return -ENOMEM;
588 }
589
590 return ret;
591}
592
593static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
594 BIGNUM *num, int num_bits)
595{
596 int nwords = num_bits / 32;
597 int size;
598 uint32_t *buf, *ptr;
599 BIGNUM *tmp, *big2, *big32, *big2_32;
600 BN_CTX *ctx;
601 int ret;
602
603 tmp = BN_new();
604 big2 = BN_new();
605 big32 = BN_new();
606 big2_32 = BN_new();
607 if (!tmp || !big2 || !big32 || !big2_32) {
608 fprintf(stderr, "Out of memory (bignum)\n");
609 return -ENOMEM;
610 }
611 ctx = BN_CTX_new();
612 if (!tmp) {
613 fprintf(stderr, "Out of memory (bignum context)\n");
614 return -ENOMEM;
615 }
616 BN_set_word(big2, 2L);
617 BN_set_word(big32, 32L);
618 BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
619
620 size = nwords * sizeof(uint32_t);
621 buf = malloc(size);
622 if (!buf) {
623 fprintf(stderr, "Out of memory (%d bytes)\n", size);
624 return -ENOMEM;
625 }
626
627 /* Write out modulus as big endian array of integers */
628 for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
629 BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
630 *ptr = cpu_to_fdt32(BN_get_word(tmp));
631 BN_rshift(num, num, 32); /* N = N/B */
632 }
633
mario.six@gdsys.cc713fb2d2016-07-22 08:58:40 +0200634 /*
635 * We try signing with successively increasing size values, so this
636 * might fail several times
637 */
Simon Glass19c402a2013-06-13 15:10:02 -0700638 ret = fdt_setprop(blob, noffset, prop_name, buf, size);
mario.six@gdsys.cc2b9ec762016-07-19 11:07:07 +0200639 if (ret)
640 return -FDT_ERR_NOSPACE;
Simon Glass19c402a2013-06-13 15:10:02 -0700641 free(buf);
642 BN_free(tmp);
643 BN_free(big2);
644 BN_free(big32);
645 BN_free(big2_32);
646
647 return ret;
648}
649
650int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
651{
652 BIGNUM *modulus, *r_squared;
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200653 uint64_t exponent;
Simon Glass19c402a2013-06-13 15:10:02 -0700654 uint32_t n0_inv;
655 int parent, node;
656 char name[100];
657 int ret;
658 int bits;
659 RSA *rsa;
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600660 ENGINE *e = NULL;
Simon Glass19c402a2013-06-13 15:10:02 -0700661
662 debug("%s: Getting verification data\n", __func__);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600663 if (info->engine_id) {
664 ret = rsa_engine_init(info->engine_id, &e);
665 if (ret)
666 return ret;
667 }
668 ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
Simon Glass19c402a2013-06-13 15:10:02 -0700669 if (ret)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600670 goto err_get_pub_key;
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200671 ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
Simon Glass19c402a2013-06-13 15:10:02 -0700672 if (ret)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600673 goto err_get_params;
Simon Glass19c402a2013-06-13 15:10:02 -0700674 bits = BN_num_bits(modulus);
675 parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
676 if (parent == -FDT_ERR_NOTFOUND) {
677 parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
678 if (parent < 0) {
Simon Glass597a8b22014-06-12 07:24:42 -0600679 ret = parent;
680 if (ret != -FDT_ERR_NOSPACE) {
681 fprintf(stderr, "Couldn't create signature node: %s\n",
682 fdt_strerror(parent));
683 }
Simon Glass19c402a2013-06-13 15:10:02 -0700684 }
685 }
Simon Glass597a8b22014-06-12 07:24:42 -0600686 if (ret)
687 goto done;
Simon Glass19c402a2013-06-13 15:10:02 -0700688
689 /* Either create or overwrite the named key node */
690 snprintf(name, sizeof(name), "key-%s", info->keyname);
691 node = fdt_subnode_offset(keydest, parent, name);
692 if (node == -FDT_ERR_NOTFOUND) {
693 node = fdt_add_subnode(keydest, parent, name);
694 if (node < 0) {
Simon Glass597a8b22014-06-12 07:24:42 -0600695 ret = node;
696 if (ret != -FDT_ERR_NOSPACE) {
697 fprintf(stderr, "Could not create key subnode: %s\n",
698 fdt_strerror(node));
699 }
Simon Glass19c402a2013-06-13 15:10:02 -0700700 }
701 } else if (node < 0) {
702 fprintf(stderr, "Cannot select keys parent: %s\n",
703 fdt_strerror(node));
Simon Glass597a8b22014-06-12 07:24:42 -0600704 ret = node;
Simon Glass19c402a2013-06-13 15:10:02 -0700705 }
706
Simon Glass597a8b22014-06-12 07:24:42 -0600707 if (!ret) {
708 ret = fdt_setprop_string(keydest, node, "key-name-hint",
Simon Glass19c402a2013-06-13 15:10:02 -0700709 info->keyname);
Simon Glass597a8b22014-06-12 07:24:42 -0600710 }
Simon Glass4f427a42014-06-02 22:04:51 -0600711 if (!ret)
712 ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
713 if (!ret)
714 ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
715 if (!ret) {
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200716 ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
717 }
718 if (!ret) {
Simon Glass4f427a42014-06-02 22:04:51 -0600719 ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus,
720 bits);
721 }
722 if (!ret) {
723 ret = fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared,
724 bits);
725 }
726 if (!ret) {
727 ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
Andrew Duda83dd98e2016-11-08 18:53:41 +0000728 info->name);
Simon Glass4f427a42014-06-02 22:04:51 -0600729 }
mario.six@gdsys.cc2b9ec762016-07-19 11:07:07 +0200730 if (!ret && info->require_keys) {
Simon Glass4f427a42014-06-02 22:04:51 -0600731 ret = fdt_setprop_string(keydest, node, "required",
732 info->require_keys);
Simon Glass19c402a2013-06-13 15:10:02 -0700733 }
Simon Glass597a8b22014-06-12 07:24:42 -0600734done:
Simon Glass19c402a2013-06-13 15:10:02 -0700735 BN_free(modulus);
736 BN_free(r_squared);
737 if (ret)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600738 ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
739err_get_params:
740 RSA_free(rsa);
741err_get_pub_key:
742 if (info->engine_id)
743 rsa_engine_remove(e);
Simon Glass19c402a2013-06-13 15:10:02 -0700744
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600745 return ret;
Simon Glass19c402a2013-06-13 15:10:02 -0700746}