blob: 40ca1e1f57320aaf52d3c1aa2a8d1a76d7817fb5 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass19c402a2013-06-13 15:10:02 -07002/*
3 * Copyright (c) 2013, Google Inc.
Simon Glass19c402a2013-06-13 15:10:02 -07004 */
5
6#include "mkimage.h"
Jonathan Gray0ff042d2020-05-15 22:20:34 +10007#include <stdlib.h>
Simon Glass19c402a2013-06-13 15:10:02 -07008#include <stdio.h>
9#include <string.h>
Simon Glass19c402a2013-06-13 15:10:02 -070010#include <image.h>
11#include <time.h>
Jelle van der Waac3b43282017-05-08 21:31:19 +020012#include <openssl/bn.h>
Simon Glass19c402a2013-06-13 15:10:02 -070013#include <openssl/rsa.h>
14#include <openssl/pem.h>
15#include <openssl/err.h>
16#include <openssl/ssl.h>
17#include <openssl/evp.h>
George McCollisterf1ca1fd2017-01-06 13:14:17 -060018#include <openssl/engine.h>
Simon Glass19c402a2013-06-13 15:10:02 -070019
20#if OPENSSL_VERSION_NUMBER >= 0x10000000L
21#define HAVE_ERR_REMOVE_THREAD_STATE
22#endif
23
Caliph Nomble7ac1a432018-07-25 22:13:03 -040024#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
25 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
Jelle van der Waac3b43282017-05-08 21:31:19 +020026static void RSA_get0_key(const RSA *r,
27 const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
28{
29 if (n != NULL)
30 *n = r->n;
31 if (e != NULL)
32 *e = r->e;
33 if (d != NULL)
34 *d = r->d;
35}
36#endif
37
Simon Glass19c402a2013-06-13 15:10:02 -070038static int rsa_err(const char *msg)
39{
40 unsigned long sslErr = ERR_get_error();
41
42 fprintf(stderr, "%s", msg);
43 fprintf(stderr, ": %s\n",
44 ERR_error_string(sslErr, 0));
45
46 return -1;
47}
48
49/**
George McCollisterf1ca1fd2017-01-06 13:14:17 -060050 * rsa_pem_get_pub_key() - read a public key from a .crt file
Simon Glass19c402a2013-06-13 15:10:02 -070051 *
52 * @keydir: Directory containins the key
53 * @name Name of key file (will have a .crt extension)
54 * @rsap Returns RSA object, or NULL on failure
55 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
56 */
George McCollisterf1ca1fd2017-01-06 13:14:17 -060057static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap)
Simon Glass19c402a2013-06-13 15:10:02 -070058{
59 char path[1024];
60 EVP_PKEY *key;
61 X509 *cert;
62 RSA *rsa;
63 FILE *f;
64 int ret;
65
66 *rsap = NULL;
67 snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
68 f = fopen(path, "r");
69 if (!f) {
70 fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
71 path, strerror(errno));
72 return -EACCES;
73 }
74
75 /* Read the certificate */
76 cert = NULL;
77 if (!PEM_read_X509(f, &cert, NULL, NULL)) {
78 rsa_err("Couldn't read certificate");
79 ret = -EINVAL;
80 goto err_cert;
81 }
82
83 /* Get the public key from the certificate. */
84 key = X509_get_pubkey(cert);
85 if (!key) {
86 rsa_err("Couldn't read public key\n");
87 ret = -EINVAL;
88 goto err_pubkey;
89 }
90
91 /* Convert to a RSA_style key. */
92 rsa = EVP_PKEY_get1_RSA(key);
93 if (!rsa) {
94 rsa_err("Couldn't convert to a RSA style key");
Simon Glass54267162014-07-30 10:00:17 -060095 ret = -EINVAL;
Simon Glass19c402a2013-06-13 15:10:02 -070096 goto err_rsa;
97 }
98 fclose(f);
99 EVP_PKEY_free(key);
100 X509_free(cert);
101 *rsap = rsa;
102
103 return 0;
104
105err_rsa:
106 EVP_PKEY_free(key);
107err_pubkey:
108 X509_free(cert);
109err_cert:
110 fclose(f);
111 return ret;
112}
113
114/**
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600115 * rsa_engine_get_pub_key() - read a public key from given engine
Simon Glass19c402a2013-06-13 15:10:02 -0700116 *
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600117 * @keydir: Key prefix
118 * @name Name of key
119 * @engine Engine to use
120 * @rsap Returns RSA object, or NULL on failure
121 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
122 */
123static int rsa_engine_get_pub_key(const char *keydir, const char *name,
124 ENGINE *engine, RSA **rsap)
125{
126 const char *engine_id;
127 char key_id[1024];
128 EVP_PKEY *key;
129 RSA *rsa;
130 int ret;
131
132 *rsap = NULL;
133
134 engine_id = ENGINE_get_id(engine);
135
136 if (engine_id && !strcmp(engine_id, "pkcs11")) {
137 if (keydir)
Jan Luebbe24bf6e82020-05-13 12:26:24 +0200138 if (strstr(keydir, "object="))
139 snprintf(key_id, sizeof(key_id),
140 "pkcs11:%s;type=public",
141 keydir);
142 else
143 snprintf(key_id, sizeof(key_id),
144 "pkcs11:%s;object=%s;type=public",
145 keydir, name);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600146 else
147 snprintf(key_id, sizeof(key_id),
148 "pkcs11:object=%s;type=public",
149 name);
Vesa Jääskeläinen5b123e02019-06-16 20:53:38 +0300150 } else if (engine_id) {
151 if (keydir)
152 snprintf(key_id, sizeof(key_id),
153 "%s%s",
154 keydir, name);
155 else
156 snprintf(key_id, sizeof(key_id),
157 "%s",
158 name);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600159 } else {
160 fprintf(stderr, "Engine not supported\n");
161 return -ENOTSUP;
162 }
163
164 key = ENGINE_load_public_key(engine, key_id, NULL, NULL);
165 if (!key)
166 return rsa_err("Failure loading public key from engine");
167
168 /* Convert to a RSA_style key. */
169 rsa = EVP_PKEY_get1_RSA(key);
170 if (!rsa) {
171 rsa_err("Couldn't convert to a RSA style key");
172 ret = -EINVAL;
173 goto err_rsa;
174 }
175
176 EVP_PKEY_free(key);
177 *rsap = rsa;
178
179 return 0;
180
181err_rsa:
182 EVP_PKEY_free(key);
183 return ret;
184}
185
186/**
187 * rsa_get_pub_key() - read a public key
188 *
189 * @keydir: Directory containing the key (PEM file) or key prefix (engine)
190 * @name Name of key file (will have a .crt extension)
191 * @engine Engine to use
192 * @rsap Returns RSA object, or NULL on failure
193 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
194 */
195static int rsa_get_pub_key(const char *keydir, const char *name,
196 ENGINE *engine, RSA **rsap)
197{
198 if (engine)
199 return rsa_engine_get_pub_key(keydir, name, engine, rsap);
200 return rsa_pem_get_pub_key(keydir, name, rsap);
201}
202
203/**
204 * rsa_pem_get_priv_key() - read a private key from a .key file
205 *
206 * @keydir: Directory containing the key
Simon Glass19c402a2013-06-13 15:10:02 -0700207 * @name Name of key file (will have a .key extension)
208 * @rsap Returns RSA object, or NULL on failure
209 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
210 */
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600211static int rsa_pem_get_priv_key(const char *keydir, const char *name,
212 RSA **rsap)
Simon Glass19c402a2013-06-13 15:10:02 -0700213{
214 char path[1024];
215 RSA *rsa;
216 FILE *f;
217
218 *rsap = NULL;
219 snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
220 f = fopen(path, "r");
221 if (!f) {
222 fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
223 path, strerror(errno));
224 return -ENOENT;
225 }
226
227 rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
228 if (!rsa) {
229 rsa_err("Failure reading private key");
230 fclose(f);
231 return -EPROTO;
232 }
233 fclose(f);
234 *rsap = rsa;
235
236 return 0;
237}
238
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600239/**
240 * rsa_engine_get_priv_key() - read a private key from given engine
241 *
242 * @keydir: Key prefix
243 * @name Name of key
244 * @engine Engine to use
245 * @rsap Returns RSA object, or NULL on failure
246 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
247 */
248static int rsa_engine_get_priv_key(const char *keydir, const char *name,
249 ENGINE *engine, RSA **rsap)
250{
251 const char *engine_id;
252 char key_id[1024];
253 EVP_PKEY *key;
254 RSA *rsa;
255 int ret;
256
257 *rsap = NULL;
258
259 engine_id = ENGINE_get_id(engine);
260
261 if (engine_id && !strcmp(engine_id, "pkcs11")) {
262 if (keydir)
Jan Luebbe24bf6e82020-05-13 12:26:24 +0200263 if (strstr(keydir, "object="))
264 snprintf(key_id, sizeof(key_id),
265 "pkcs11:%s;type=private",
266 keydir);
267 else
268 snprintf(key_id, sizeof(key_id),
269 "pkcs11:%s;object=%s;type=private",
270 keydir, name);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600271 else
272 snprintf(key_id, sizeof(key_id),
273 "pkcs11:object=%s;type=private",
274 name);
Vesa Jääskeläinen5b123e02019-06-16 20:53:38 +0300275 } else if (engine_id) {
276 if (keydir)
277 snprintf(key_id, sizeof(key_id),
278 "%s%s",
279 keydir, name);
280 else
281 snprintf(key_id, sizeof(key_id),
282 "%s",
283 name);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600284 } else {
285 fprintf(stderr, "Engine not supported\n");
286 return -ENOTSUP;
287 }
288
289 key = ENGINE_load_private_key(engine, key_id, NULL, NULL);
290 if (!key)
291 return rsa_err("Failure loading private key from engine");
292
293 /* Convert to a RSA_style key. */
294 rsa = EVP_PKEY_get1_RSA(key);
295 if (!rsa) {
296 rsa_err("Couldn't convert to a RSA style key");
297 ret = -EINVAL;
298 goto err_rsa;
299 }
300
301 EVP_PKEY_free(key);
302 *rsap = rsa;
303
304 return 0;
305
306err_rsa:
307 EVP_PKEY_free(key);
308 return ret;
309}
310
311/**
312 * rsa_get_priv_key() - read a private key
313 *
314 * @keydir: Directory containing the key (PEM file) or key prefix (engine)
315 * @name Name of key
316 * @engine Engine to use for signing
317 * @rsap Returns RSA object, or NULL on failure
318 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
319 */
320static int rsa_get_priv_key(const char *keydir, const char *name,
321 ENGINE *engine, RSA **rsap)
322{
323 if (engine)
324 return rsa_engine_get_priv_key(keydir, name, engine, rsap);
325 return rsa_pem_get_priv_key(keydir, name, rsap);
326}
327
Simon Glass19c402a2013-06-13 15:10:02 -0700328static int rsa_init(void)
329{
330 int ret;
331
Caliph Nomble7ac1a432018-07-25 22:13:03 -0400332#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
333 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
Simon Glass19c402a2013-06-13 15:10:02 -0700334 ret = SSL_library_init();
Jelle van der Waac3b43282017-05-08 21:31:19 +0200335#else
336 ret = OPENSSL_init_ssl(0, NULL);
337#endif
Simon Glass19c402a2013-06-13 15:10:02 -0700338 if (!ret) {
339 fprintf(stderr, "Failure to init SSL library\n");
340 return -1;
341 }
Caliph Nomble7ac1a432018-07-25 22:13:03 -0400342#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
343 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
Simon Glass19c402a2013-06-13 15:10:02 -0700344 SSL_load_error_strings();
345
346 OpenSSL_add_all_algorithms();
347 OpenSSL_add_all_digests();
348 OpenSSL_add_all_ciphers();
Jelle van der Waac3b43282017-05-08 21:31:19 +0200349#endif
Simon Glass19c402a2013-06-13 15:10:02 -0700350
351 return 0;
352}
353
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600354static int rsa_engine_init(const char *engine_id, ENGINE **pe)
355{
356 ENGINE *e;
357 int ret;
358
359 ENGINE_load_builtin_engines();
360
361 e = ENGINE_by_id(engine_id);
362 if (!e) {
363 fprintf(stderr, "Engine isn't available\n");
364 ret = -1;
365 goto err_engine_by_id;
366 }
367
368 if (!ENGINE_init(e)) {
369 fprintf(stderr, "Couldn't initialize engine\n");
370 ret = -1;
371 goto err_engine_init;
372 }
373
374 if (!ENGINE_set_default_RSA(e)) {
375 fprintf(stderr, "Couldn't set engine as default for RSA\n");
376 ret = -1;
377 goto err_set_rsa;
378 }
379
380 *pe = e;
381
382 return 0;
383
384err_set_rsa:
385 ENGINE_finish(e);
386err_engine_init:
387 ENGINE_free(e);
388err_engine_by_id:
Caliph Nomble7ac1a432018-07-25 22:13:03 -0400389#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
390 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600391 ENGINE_cleanup();
Jelle van der Waac3b43282017-05-08 21:31:19 +0200392#endif
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600393 return ret;
394}
395
Simon Glass19c402a2013-06-13 15:10:02 -0700396static void rsa_remove(void)
397{
Caliph Nomble7ac1a432018-07-25 22:13:03 -0400398#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
399 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
Simon Glass19c402a2013-06-13 15:10:02 -0700400 CRYPTO_cleanup_all_ex_data();
401 ERR_free_strings();
402#ifdef HAVE_ERR_REMOVE_THREAD_STATE
403 ERR_remove_thread_state(NULL);
404#else
405 ERR_remove_state(0);
406#endif
407 EVP_cleanup();
Jelle van der Waac3b43282017-05-08 21:31:19 +0200408#endif
Simon Glass19c402a2013-06-13 15:10:02 -0700409}
410
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600411static void rsa_engine_remove(ENGINE *e)
412{
413 if (e) {
414 ENGINE_finish(e);
415 ENGINE_free(e);
416 }
417}
418
Philippe Reynes20031562018-11-14 13:51:00 +0100419static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo,
420 struct checksum_algo *checksum_algo,
Heiko Schocher646257d2014-03-03 12:19:26 +0100421 const struct image_region region[], int region_count,
422 uint8_t **sigp, uint *sig_size)
Simon Glass19c402a2013-06-13 15:10:02 -0700423{
424 EVP_PKEY *key;
Philippe Reynes20031562018-11-14 13:51:00 +0100425 EVP_PKEY_CTX *ckey;
Simon Glass19c402a2013-06-13 15:10:02 -0700426 EVP_MD_CTX *context;
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100427 int ret = 0;
428 size_t size;
Simon Glass19c402a2013-06-13 15:10:02 -0700429 uint8_t *sig;
430 int i;
431
432 key = EVP_PKEY_new();
433 if (!key)
434 return rsa_err("EVP_PKEY object creation failed");
435
436 if (!EVP_PKEY_set1_RSA(key, rsa)) {
437 ret = rsa_err("EVP key setup failed");
438 goto err_set;
439 }
440
441 size = EVP_PKEY_size(key);
442 sig = malloc(size);
443 if (!sig) {
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100444 fprintf(stderr, "Out of memory for signature (%zu bytes)\n",
Simon Glass19c402a2013-06-13 15:10:02 -0700445 size);
446 ret = -ENOMEM;
447 goto err_alloc;
448 }
449
450 context = EVP_MD_CTX_create();
451 if (!context) {
452 ret = rsa_err("EVP context creation failed");
453 goto err_create;
454 }
455 EVP_MD_CTX_init(context);
Philippe Reynes20031562018-11-14 13:51:00 +0100456
457 ckey = EVP_PKEY_CTX_new(key, NULL);
458 if (!ckey) {
459 ret = rsa_err("EVP key context creation failed");
460 goto err_create;
461 }
462
463 if (EVP_DigestSignInit(context, &ckey,
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100464 checksum_algo->calculate_sign(),
465 NULL, key) <= 0) {
Simon Glass19c402a2013-06-13 15:10:02 -0700466 ret = rsa_err("Signer setup failed");
467 goto err_sign;
468 }
469
Philippe Reynes061daa02018-11-14 13:51:01 +0100470#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
471 if (padding_algo && !strcmp(padding_algo->name, "pss")) {
472 if (EVP_PKEY_CTX_set_rsa_padding(ckey,
473 RSA_PKCS1_PSS_PADDING) <= 0) {
474 ret = rsa_err("Signer padding setup failed");
475 goto err_sign;
476 }
477 }
478#endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
479
Simon Glass19c402a2013-06-13 15:10:02 -0700480 for (i = 0; i < region_count; i++) {
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100481 if (!EVP_DigestSignUpdate(context, region[i].data,
482 region[i].size)) {
Simon Glass19c402a2013-06-13 15:10:02 -0700483 ret = rsa_err("Signing data failed");
484 goto err_sign;
485 }
486 }
487
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100488 if (!EVP_DigestSignFinal(context, sig, &size)) {
Simon Glass19c402a2013-06-13 15:10:02 -0700489 ret = rsa_err("Could not obtain signature");
490 goto err_sign;
491 }
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100492
Caliph Nomble7ac1a432018-07-25 22:13:03 -0400493 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
494 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
Jelle van der Waac3b43282017-05-08 21:31:19 +0200495 EVP_MD_CTX_cleanup(context);
496 #else
497 EVP_MD_CTX_reset(context);
498 #endif
Simon Glass19c402a2013-06-13 15:10:02 -0700499 EVP_MD_CTX_destroy(context);
500 EVP_PKEY_free(key);
501
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100502 debug("Got signature: %d bytes, expected %zu\n", *sig_size, size);
Simon Glass19c402a2013-06-13 15:10:02 -0700503 *sigp = sig;
504 *sig_size = size;
505
506 return 0;
507
508err_sign:
509 EVP_MD_CTX_destroy(context);
510err_create:
511 free(sig);
512err_alloc:
513err_set:
514 EVP_PKEY_free(key);
515 return ret;
516}
517
518int rsa_sign(struct image_sign_info *info,
519 const struct image_region region[], int region_count,
520 uint8_t **sigp, uint *sig_len)
521{
522 RSA *rsa;
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600523 ENGINE *e = NULL;
Simon Glass19c402a2013-06-13 15:10:02 -0700524 int ret;
525
526 ret = rsa_init();
527 if (ret)
528 return ret;
529
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600530 if (info->engine_id) {
531 ret = rsa_engine_init(info->engine_id, &e);
532 if (ret)
533 goto err_engine;
534 }
535
536 ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
Simon Glass19c402a2013-06-13 15:10:02 -0700537 if (ret)
538 goto err_priv;
Philippe Reynes20031562018-11-14 13:51:00 +0100539 ret = rsa_sign_with_key(rsa, info->padding, info->checksum, region,
Heiko Schocher646257d2014-03-03 12:19:26 +0100540 region_count, sigp, sig_len);
Simon Glass19c402a2013-06-13 15:10:02 -0700541 if (ret)
542 goto err_sign;
543
544 RSA_free(rsa);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600545 if (info->engine_id)
546 rsa_engine_remove(e);
Simon Glass19c402a2013-06-13 15:10:02 -0700547 rsa_remove();
548
549 return ret;
550
551err_sign:
552 RSA_free(rsa);
553err_priv:
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600554 if (info->engine_id)
555 rsa_engine_remove(e);
556err_engine:
Simon Glass19c402a2013-06-13 15:10:02 -0700557 rsa_remove();
558 return ret;
559}
560
561/*
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200562 * rsa_get_exponent(): - Get the public exponent from an RSA key
563 */
564static int rsa_get_exponent(RSA *key, uint64_t *e)
565{
566 int ret;
567 BIGNUM *bn_te;
Jelle van der Waac3b43282017-05-08 21:31:19 +0200568 const BIGNUM *key_e;
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200569 uint64_t te;
570
571 ret = -EINVAL;
572 bn_te = NULL;
573
574 if (!e)
575 goto cleanup;
576
Jelle van der Waac3b43282017-05-08 21:31:19 +0200577 RSA_get0_key(key, NULL, &key_e, NULL);
578 if (BN_num_bits(key_e) > 64)
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200579 goto cleanup;
580
Jelle van der Waac3b43282017-05-08 21:31:19 +0200581 *e = BN_get_word(key_e);
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200582
Jelle van der Waac3b43282017-05-08 21:31:19 +0200583 if (BN_num_bits(key_e) < 33) {
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200584 ret = 0;
585 goto cleanup;
586 }
587
Jelle van der Waac3b43282017-05-08 21:31:19 +0200588 bn_te = BN_dup(key_e);
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200589 if (!bn_te)
590 goto cleanup;
591
592 if (!BN_rshift(bn_te, bn_te, 32))
593 goto cleanup;
594
595 if (!BN_mask_bits(bn_te, 32))
596 goto cleanup;
597
598 te = BN_get_word(bn_te);
599 te <<= 32;
600 *e |= te;
601 ret = 0;
602
603cleanup:
604 if (bn_te)
605 BN_free(bn_te);
606
607 return ret;
608}
609
610/*
Simon Glass19c402a2013-06-13 15:10:02 -0700611 * rsa_get_params(): - Get the important parameters of an RSA public key
612 */
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200613int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
614 BIGNUM **modulusp, BIGNUM **r_squaredp)
Simon Glass19c402a2013-06-13 15:10:02 -0700615{
616 BIGNUM *big1, *big2, *big32, *big2_32;
617 BIGNUM *n, *r, *r_squared, *tmp;
Jelle van der Waac3b43282017-05-08 21:31:19 +0200618 const BIGNUM *key_n;
Simon Glass19c402a2013-06-13 15:10:02 -0700619 BN_CTX *bn_ctx = BN_CTX_new();
620 int ret = 0;
621
622 /* Initialize BIGNUMs */
623 big1 = BN_new();
624 big2 = BN_new();
625 big32 = BN_new();
626 r = BN_new();
627 r_squared = BN_new();
628 tmp = BN_new();
629 big2_32 = BN_new();
630 n = BN_new();
631 if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
632 !n) {
633 fprintf(stderr, "Out of memory (bignum)\n");
634 return -ENOMEM;
635 }
636
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200637 if (0 != rsa_get_exponent(key, exponent))
638 ret = -1;
639
Jelle van der Waac3b43282017-05-08 21:31:19 +0200640 RSA_get0_key(key, &key_n, NULL, NULL);
641 if (!BN_copy(n, key_n) || !BN_set_word(big1, 1L) ||
Simon Glass19c402a2013-06-13 15:10:02 -0700642 !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
643 ret = -1;
644
645 /* big2_32 = 2^32 */
646 if (!BN_exp(big2_32, big2, big32, bn_ctx))
647 ret = -1;
648
649 /* Calculate n0_inv = -1 / n[0] mod 2^32 */
650 if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
651 !BN_sub(tmp, big2_32, tmp))
652 ret = -1;
653 *n0_invp = BN_get_word(tmp);
654
655 /* Calculate R = 2^(# of key bits) */
656 if (!BN_set_word(tmp, BN_num_bits(n)) ||
657 !BN_exp(r, big2, tmp, bn_ctx))
658 ret = -1;
659
660 /* Calculate r_squared = R^2 mod n */
661 if (!BN_copy(r_squared, r) ||
662 !BN_mul(tmp, r_squared, r, bn_ctx) ||
663 !BN_mod(r_squared, tmp, n, bn_ctx))
664 ret = -1;
665
666 *modulusp = n;
667 *r_squaredp = r_squared;
668
669 BN_free(big1);
670 BN_free(big2);
671 BN_free(big32);
672 BN_free(r);
673 BN_free(tmp);
674 BN_free(big2_32);
675 if (ret) {
676 fprintf(stderr, "Bignum operations failed\n");
677 return -ENOMEM;
678 }
679
680 return ret;
681}
682
683static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
684 BIGNUM *num, int num_bits)
685{
686 int nwords = num_bits / 32;
687 int size;
688 uint32_t *buf, *ptr;
689 BIGNUM *tmp, *big2, *big32, *big2_32;
690 BN_CTX *ctx;
691 int ret;
692
693 tmp = BN_new();
694 big2 = BN_new();
695 big32 = BN_new();
696 big2_32 = BN_new();
Simon Glass8a682e02018-06-12 00:05:00 -0600697
698 /*
699 * Note: This code assumes that all of the above succeed, or all fail.
700 * In practice memory allocations generally do not fail (unless the
701 * process is killed), so it does not seem worth handling each of these
702 * as a separate case. Technicaly this could leak memory on failure,
703 * but a) it won't happen in practice, and b) it doesn't matter as we
704 * will immediately exit with a failure code.
705 */
Simon Glass19c402a2013-06-13 15:10:02 -0700706 if (!tmp || !big2 || !big32 || !big2_32) {
707 fprintf(stderr, "Out of memory (bignum)\n");
708 return -ENOMEM;
709 }
710 ctx = BN_CTX_new();
711 if (!tmp) {
712 fprintf(stderr, "Out of memory (bignum context)\n");
713 return -ENOMEM;
714 }
715 BN_set_word(big2, 2L);
716 BN_set_word(big32, 32L);
717 BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
718
719 size = nwords * sizeof(uint32_t);
720 buf = malloc(size);
721 if (!buf) {
722 fprintf(stderr, "Out of memory (%d bytes)\n", size);
723 return -ENOMEM;
724 }
725
726 /* Write out modulus as big endian array of integers */
727 for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
728 BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
729 *ptr = cpu_to_fdt32(BN_get_word(tmp));
730 BN_rshift(num, num, 32); /* N = N/B */
731 }
732
mario.six@gdsys.cc713fb2d2016-07-22 08:58:40 +0200733 /*
734 * We try signing with successively increasing size values, so this
735 * might fail several times
736 */
Simon Glass19c402a2013-06-13 15:10:02 -0700737 ret = fdt_setprop(blob, noffset, prop_name, buf, size);
Simon Glass19c402a2013-06-13 15:10:02 -0700738 free(buf);
739 BN_free(tmp);
740 BN_free(big2);
741 BN_free(big32);
742 BN_free(big2_32);
743
Simon Glass8a682e02018-06-12 00:05:00 -0600744 return ret ? -FDT_ERR_NOSPACE : 0;
Simon Glass19c402a2013-06-13 15:10:02 -0700745}
746
747int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
748{
749 BIGNUM *modulus, *r_squared;
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200750 uint64_t exponent;
Simon Glass19c402a2013-06-13 15:10:02 -0700751 uint32_t n0_inv;
752 int parent, node;
753 char name[100];
754 int ret;
755 int bits;
756 RSA *rsa;
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600757 ENGINE *e = NULL;
Simon Glass19c402a2013-06-13 15:10:02 -0700758
759 debug("%s: Getting verification data\n", __func__);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600760 if (info->engine_id) {
761 ret = rsa_engine_init(info->engine_id, &e);
762 if (ret)
763 return ret;
764 }
765 ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
Simon Glass19c402a2013-06-13 15:10:02 -0700766 if (ret)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600767 goto err_get_pub_key;
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200768 ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
Simon Glass19c402a2013-06-13 15:10:02 -0700769 if (ret)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600770 goto err_get_params;
Simon Glass19c402a2013-06-13 15:10:02 -0700771 bits = BN_num_bits(modulus);
772 parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
773 if (parent == -FDT_ERR_NOTFOUND) {
774 parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
775 if (parent < 0) {
Simon Glass597a8b22014-06-12 07:24:42 -0600776 ret = parent;
777 if (ret != -FDT_ERR_NOSPACE) {
778 fprintf(stderr, "Couldn't create signature node: %s\n",
779 fdt_strerror(parent));
780 }
Simon Glass19c402a2013-06-13 15:10:02 -0700781 }
782 }
Simon Glass597a8b22014-06-12 07:24:42 -0600783 if (ret)
784 goto done;
Simon Glass19c402a2013-06-13 15:10:02 -0700785
786 /* Either create or overwrite the named key node */
787 snprintf(name, sizeof(name), "key-%s", info->keyname);
788 node = fdt_subnode_offset(keydest, parent, name);
789 if (node == -FDT_ERR_NOTFOUND) {
790 node = fdt_add_subnode(keydest, parent, name);
791 if (node < 0) {
Simon Glass597a8b22014-06-12 07:24:42 -0600792 ret = node;
793 if (ret != -FDT_ERR_NOSPACE) {
794 fprintf(stderr, "Could not create key subnode: %s\n",
795 fdt_strerror(node));
796 }
Simon Glass19c402a2013-06-13 15:10:02 -0700797 }
798 } else if (node < 0) {
799 fprintf(stderr, "Cannot select keys parent: %s\n",
800 fdt_strerror(node));
Simon Glass597a8b22014-06-12 07:24:42 -0600801 ret = node;
Simon Glass19c402a2013-06-13 15:10:02 -0700802 }
803
Simon Glass597a8b22014-06-12 07:24:42 -0600804 if (!ret) {
Simon Glass72188f52020-03-18 11:44:06 -0600805 ret = fdt_setprop_string(keydest, node, FIT_KEY_HINT,
806 info->keyname);
Simon Glass597a8b22014-06-12 07:24:42 -0600807 }
Simon Glass4f427a42014-06-02 22:04:51 -0600808 if (!ret)
809 ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
810 if (!ret)
811 ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
812 if (!ret) {
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200813 ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
814 }
815 if (!ret) {
Simon Glass4f427a42014-06-02 22:04:51 -0600816 ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus,
817 bits);
818 }
819 if (!ret) {
820 ret = fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared,
821 bits);
822 }
823 if (!ret) {
824 ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
Andrew Duda83dd98e2016-11-08 18:53:41 +0000825 info->name);
Simon Glass4f427a42014-06-02 22:04:51 -0600826 }
mario.six@gdsys.cc2b9ec762016-07-19 11:07:07 +0200827 if (!ret && info->require_keys) {
Simon Glass72188f52020-03-18 11:44:06 -0600828 ret = fdt_setprop_string(keydest, node, FIT_KEY_REQUIRED,
Simon Glass4f427a42014-06-02 22:04:51 -0600829 info->require_keys);
Simon Glass19c402a2013-06-13 15:10:02 -0700830 }
Simon Glass597a8b22014-06-12 07:24:42 -0600831done:
Simon Glass19c402a2013-06-13 15:10:02 -0700832 BN_free(modulus);
833 BN_free(r_squared);
834 if (ret)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600835 ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
836err_get_params:
837 RSA_free(rsa);
838err_get_pub_key:
839 if (info->engine_id)
840 rsa_engine_remove(e);
Simon Glass19c402a2013-06-13 15:10:02 -0700841
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600842 return ret;
Simon Glass19c402a2013-06-13 15:10:02 -0700843}