blob: 580c74470939c580f8181583df1d860c7afb8b56 [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"
Simon Glass336d4612020-02-03 07:36:16 -07007#include <malloc.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)
138 snprintf(key_id, sizeof(key_id),
139 "pkcs11:%s;object=%s;type=public",
140 keydir, name);
141 else
142 snprintf(key_id, sizeof(key_id),
143 "pkcs11:object=%s;type=public",
144 name);
Vesa Jääskeläinen5b123e02019-06-16 20:53:38 +0300145 } else if (engine_id) {
146 if (keydir)
147 snprintf(key_id, sizeof(key_id),
148 "%s%s",
149 keydir, name);
150 else
151 snprintf(key_id, sizeof(key_id),
152 "%s",
153 name);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600154 } else {
155 fprintf(stderr, "Engine not supported\n");
156 return -ENOTSUP;
157 }
158
159 key = ENGINE_load_public_key(engine, key_id, NULL, NULL);
160 if (!key)
161 return rsa_err("Failure loading public key from engine");
162
163 /* Convert to a RSA_style key. */
164 rsa = EVP_PKEY_get1_RSA(key);
165 if (!rsa) {
166 rsa_err("Couldn't convert to a RSA style key");
167 ret = -EINVAL;
168 goto err_rsa;
169 }
170
171 EVP_PKEY_free(key);
172 *rsap = rsa;
173
174 return 0;
175
176err_rsa:
177 EVP_PKEY_free(key);
178 return ret;
179}
180
181/**
182 * rsa_get_pub_key() - read a public key
183 *
184 * @keydir: Directory containing the key (PEM file) or key prefix (engine)
185 * @name Name of key file (will have a .crt extension)
186 * @engine Engine to use
187 * @rsap Returns RSA object, or NULL on failure
188 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
189 */
190static int rsa_get_pub_key(const char *keydir, const char *name,
191 ENGINE *engine, RSA **rsap)
192{
193 if (engine)
194 return rsa_engine_get_pub_key(keydir, name, engine, rsap);
195 return rsa_pem_get_pub_key(keydir, name, rsap);
196}
197
198/**
199 * rsa_pem_get_priv_key() - read a private key from a .key file
200 *
201 * @keydir: Directory containing the key
Simon Glass19c402a2013-06-13 15:10:02 -0700202 * @name Name of key file (will have a .key extension)
203 * @rsap Returns RSA object, or NULL on failure
204 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
205 */
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600206static int rsa_pem_get_priv_key(const char *keydir, const char *name,
207 RSA **rsap)
Simon Glass19c402a2013-06-13 15:10:02 -0700208{
209 char path[1024];
210 RSA *rsa;
211 FILE *f;
212
213 *rsap = NULL;
214 snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
215 f = fopen(path, "r");
216 if (!f) {
217 fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
218 path, strerror(errno));
219 return -ENOENT;
220 }
221
222 rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
223 if (!rsa) {
224 rsa_err("Failure reading private key");
225 fclose(f);
226 return -EPROTO;
227 }
228 fclose(f);
229 *rsap = rsa;
230
231 return 0;
232}
233
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600234/**
235 * rsa_engine_get_priv_key() - read a private key from given engine
236 *
237 * @keydir: Key prefix
238 * @name Name of key
239 * @engine Engine to use
240 * @rsap Returns RSA object, or NULL on failure
241 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
242 */
243static int rsa_engine_get_priv_key(const char *keydir, const char *name,
244 ENGINE *engine, RSA **rsap)
245{
246 const char *engine_id;
247 char key_id[1024];
248 EVP_PKEY *key;
249 RSA *rsa;
250 int ret;
251
252 *rsap = NULL;
253
254 engine_id = ENGINE_get_id(engine);
255
256 if (engine_id && !strcmp(engine_id, "pkcs11")) {
257 if (keydir)
258 snprintf(key_id, sizeof(key_id),
259 "pkcs11:%s;object=%s;type=private",
260 keydir, name);
261 else
262 snprintf(key_id, sizeof(key_id),
263 "pkcs11:object=%s;type=private",
264 name);
Vesa Jääskeläinen5b123e02019-06-16 20:53:38 +0300265 } else if (engine_id) {
266 if (keydir)
267 snprintf(key_id, sizeof(key_id),
268 "%s%s",
269 keydir, name);
270 else
271 snprintf(key_id, sizeof(key_id),
272 "%s",
273 name);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600274 } else {
275 fprintf(stderr, "Engine not supported\n");
276 return -ENOTSUP;
277 }
278
279 key = ENGINE_load_private_key(engine, key_id, NULL, NULL);
280 if (!key)
281 return rsa_err("Failure loading private key from engine");
282
283 /* Convert to a RSA_style key. */
284 rsa = EVP_PKEY_get1_RSA(key);
285 if (!rsa) {
286 rsa_err("Couldn't convert to a RSA style key");
287 ret = -EINVAL;
288 goto err_rsa;
289 }
290
291 EVP_PKEY_free(key);
292 *rsap = rsa;
293
294 return 0;
295
296err_rsa:
297 EVP_PKEY_free(key);
298 return ret;
299}
300
301/**
302 * rsa_get_priv_key() - read a private key
303 *
304 * @keydir: Directory containing the key (PEM file) or key prefix (engine)
305 * @name Name of key
306 * @engine Engine to use for signing
307 * @rsap Returns RSA object, or NULL on failure
308 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
309 */
310static int rsa_get_priv_key(const char *keydir, const char *name,
311 ENGINE *engine, RSA **rsap)
312{
313 if (engine)
314 return rsa_engine_get_priv_key(keydir, name, engine, rsap);
315 return rsa_pem_get_priv_key(keydir, name, rsap);
316}
317
Simon Glass19c402a2013-06-13 15:10:02 -0700318static int rsa_init(void)
319{
320 int ret;
321
Caliph Nomble7ac1a432018-07-25 22:13:03 -0400322#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
323 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
Simon Glass19c402a2013-06-13 15:10:02 -0700324 ret = SSL_library_init();
Jelle van der Waac3b43282017-05-08 21:31:19 +0200325#else
326 ret = OPENSSL_init_ssl(0, NULL);
327#endif
Simon Glass19c402a2013-06-13 15:10:02 -0700328 if (!ret) {
329 fprintf(stderr, "Failure to init SSL library\n");
330 return -1;
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 SSL_load_error_strings();
335
336 OpenSSL_add_all_algorithms();
337 OpenSSL_add_all_digests();
338 OpenSSL_add_all_ciphers();
Jelle van der Waac3b43282017-05-08 21:31:19 +0200339#endif
Simon Glass19c402a2013-06-13 15:10:02 -0700340
341 return 0;
342}
343
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600344static int rsa_engine_init(const char *engine_id, ENGINE **pe)
345{
346 ENGINE *e;
347 int ret;
348
349 ENGINE_load_builtin_engines();
350
351 e = ENGINE_by_id(engine_id);
352 if (!e) {
353 fprintf(stderr, "Engine isn't available\n");
354 ret = -1;
355 goto err_engine_by_id;
356 }
357
358 if (!ENGINE_init(e)) {
359 fprintf(stderr, "Couldn't initialize engine\n");
360 ret = -1;
361 goto err_engine_init;
362 }
363
364 if (!ENGINE_set_default_RSA(e)) {
365 fprintf(stderr, "Couldn't set engine as default for RSA\n");
366 ret = -1;
367 goto err_set_rsa;
368 }
369
370 *pe = e;
371
372 return 0;
373
374err_set_rsa:
375 ENGINE_finish(e);
376err_engine_init:
377 ENGINE_free(e);
378err_engine_by_id:
Caliph Nomble7ac1a432018-07-25 22:13:03 -0400379#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
380 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600381 ENGINE_cleanup();
Jelle van der Waac3b43282017-05-08 21:31:19 +0200382#endif
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600383 return ret;
384}
385
Simon Glass19c402a2013-06-13 15:10:02 -0700386static void rsa_remove(void)
387{
Caliph Nomble7ac1a432018-07-25 22:13:03 -0400388#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
389 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
Simon Glass19c402a2013-06-13 15:10:02 -0700390 CRYPTO_cleanup_all_ex_data();
391 ERR_free_strings();
392#ifdef HAVE_ERR_REMOVE_THREAD_STATE
393 ERR_remove_thread_state(NULL);
394#else
395 ERR_remove_state(0);
396#endif
397 EVP_cleanup();
Jelle van der Waac3b43282017-05-08 21:31:19 +0200398#endif
Simon Glass19c402a2013-06-13 15:10:02 -0700399}
400
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600401static void rsa_engine_remove(ENGINE *e)
402{
403 if (e) {
404 ENGINE_finish(e);
405 ENGINE_free(e);
406 }
407}
408
Philippe Reynes20031562018-11-14 13:51:00 +0100409static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo,
410 struct checksum_algo *checksum_algo,
Heiko Schocher646257d2014-03-03 12:19:26 +0100411 const struct image_region region[], int region_count,
412 uint8_t **sigp, uint *sig_size)
Simon Glass19c402a2013-06-13 15:10:02 -0700413{
414 EVP_PKEY *key;
Philippe Reynes20031562018-11-14 13:51:00 +0100415 EVP_PKEY_CTX *ckey;
Simon Glass19c402a2013-06-13 15:10:02 -0700416 EVP_MD_CTX *context;
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100417 int ret = 0;
418 size_t size;
Simon Glass19c402a2013-06-13 15:10:02 -0700419 uint8_t *sig;
420 int i;
421
422 key = EVP_PKEY_new();
423 if (!key)
424 return rsa_err("EVP_PKEY object creation failed");
425
426 if (!EVP_PKEY_set1_RSA(key, rsa)) {
427 ret = rsa_err("EVP key setup failed");
428 goto err_set;
429 }
430
431 size = EVP_PKEY_size(key);
432 sig = malloc(size);
433 if (!sig) {
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100434 fprintf(stderr, "Out of memory for signature (%zu bytes)\n",
Simon Glass19c402a2013-06-13 15:10:02 -0700435 size);
436 ret = -ENOMEM;
437 goto err_alloc;
438 }
439
440 context = EVP_MD_CTX_create();
441 if (!context) {
442 ret = rsa_err("EVP context creation failed");
443 goto err_create;
444 }
445 EVP_MD_CTX_init(context);
Philippe Reynes20031562018-11-14 13:51:00 +0100446
447 ckey = EVP_PKEY_CTX_new(key, NULL);
448 if (!ckey) {
449 ret = rsa_err("EVP key context creation failed");
450 goto err_create;
451 }
452
453 if (EVP_DigestSignInit(context, &ckey,
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100454 checksum_algo->calculate_sign(),
455 NULL, key) <= 0) {
Simon Glass19c402a2013-06-13 15:10:02 -0700456 ret = rsa_err("Signer setup failed");
457 goto err_sign;
458 }
459
Philippe Reynes061daa02018-11-14 13:51:01 +0100460#ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
461 if (padding_algo && !strcmp(padding_algo->name, "pss")) {
462 if (EVP_PKEY_CTX_set_rsa_padding(ckey,
463 RSA_PKCS1_PSS_PADDING) <= 0) {
464 ret = rsa_err("Signer padding setup failed");
465 goto err_sign;
466 }
467 }
468#endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
469
Simon Glass19c402a2013-06-13 15:10:02 -0700470 for (i = 0; i < region_count; i++) {
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100471 if (!EVP_DigestSignUpdate(context, region[i].data,
472 region[i].size)) {
Simon Glass19c402a2013-06-13 15:10:02 -0700473 ret = rsa_err("Signing data failed");
474 goto err_sign;
475 }
476 }
477
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100478 if (!EVP_DigestSignFinal(context, sig, &size)) {
Simon Glass19c402a2013-06-13 15:10:02 -0700479 ret = rsa_err("Could not obtain signature");
480 goto err_sign;
481 }
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100482
Caliph Nomble7ac1a432018-07-25 22:13:03 -0400483 #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
484 (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
Jelle van der Waac3b43282017-05-08 21:31:19 +0200485 EVP_MD_CTX_cleanup(context);
486 #else
487 EVP_MD_CTX_reset(context);
488 #endif
Simon Glass19c402a2013-06-13 15:10:02 -0700489 EVP_MD_CTX_destroy(context);
490 EVP_PKEY_free(key);
491
Philippe Reynes3b5d6972018-11-14 13:50:59 +0100492 debug("Got signature: %d bytes, expected %zu\n", *sig_size, size);
Simon Glass19c402a2013-06-13 15:10:02 -0700493 *sigp = sig;
494 *sig_size = size;
495
496 return 0;
497
498err_sign:
499 EVP_MD_CTX_destroy(context);
500err_create:
501 free(sig);
502err_alloc:
503err_set:
504 EVP_PKEY_free(key);
505 return ret;
506}
507
508int rsa_sign(struct image_sign_info *info,
509 const struct image_region region[], int region_count,
510 uint8_t **sigp, uint *sig_len)
511{
512 RSA *rsa;
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600513 ENGINE *e = NULL;
Simon Glass19c402a2013-06-13 15:10:02 -0700514 int ret;
515
516 ret = rsa_init();
517 if (ret)
518 return ret;
519
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600520 if (info->engine_id) {
521 ret = rsa_engine_init(info->engine_id, &e);
522 if (ret)
523 goto err_engine;
524 }
525
526 ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
Simon Glass19c402a2013-06-13 15:10:02 -0700527 if (ret)
528 goto err_priv;
Philippe Reynes20031562018-11-14 13:51:00 +0100529 ret = rsa_sign_with_key(rsa, info->padding, info->checksum, region,
Heiko Schocher646257d2014-03-03 12:19:26 +0100530 region_count, sigp, sig_len);
Simon Glass19c402a2013-06-13 15:10:02 -0700531 if (ret)
532 goto err_sign;
533
534 RSA_free(rsa);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600535 if (info->engine_id)
536 rsa_engine_remove(e);
Simon Glass19c402a2013-06-13 15:10:02 -0700537 rsa_remove();
538
539 return ret;
540
541err_sign:
542 RSA_free(rsa);
543err_priv:
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600544 if (info->engine_id)
545 rsa_engine_remove(e);
546err_engine:
Simon Glass19c402a2013-06-13 15:10:02 -0700547 rsa_remove();
548 return ret;
549}
550
551/*
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200552 * rsa_get_exponent(): - Get the public exponent from an RSA key
553 */
554static int rsa_get_exponent(RSA *key, uint64_t *e)
555{
556 int ret;
557 BIGNUM *bn_te;
Jelle van der Waac3b43282017-05-08 21:31:19 +0200558 const BIGNUM *key_e;
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200559 uint64_t te;
560
561 ret = -EINVAL;
562 bn_te = NULL;
563
564 if (!e)
565 goto cleanup;
566
Jelle van der Waac3b43282017-05-08 21:31:19 +0200567 RSA_get0_key(key, NULL, &key_e, NULL);
568 if (BN_num_bits(key_e) > 64)
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200569 goto cleanup;
570
Jelle van der Waac3b43282017-05-08 21:31:19 +0200571 *e = BN_get_word(key_e);
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200572
Jelle van der Waac3b43282017-05-08 21:31:19 +0200573 if (BN_num_bits(key_e) < 33) {
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200574 ret = 0;
575 goto cleanup;
576 }
577
Jelle van der Waac3b43282017-05-08 21:31:19 +0200578 bn_te = BN_dup(key_e);
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200579 if (!bn_te)
580 goto cleanup;
581
582 if (!BN_rshift(bn_te, bn_te, 32))
583 goto cleanup;
584
585 if (!BN_mask_bits(bn_te, 32))
586 goto cleanup;
587
588 te = BN_get_word(bn_te);
589 te <<= 32;
590 *e |= te;
591 ret = 0;
592
593cleanup:
594 if (bn_te)
595 BN_free(bn_te);
596
597 return ret;
598}
599
600/*
Simon Glass19c402a2013-06-13 15:10:02 -0700601 * rsa_get_params(): - Get the important parameters of an RSA public key
602 */
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200603int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
604 BIGNUM **modulusp, BIGNUM **r_squaredp)
Simon Glass19c402a2013-06-13 15:10:02 -0700605{
606 BIGNUM *big1, *big2, *big32, *big2_32;
607 BIGNUM *n, *r, *r_squared, *tmp;
Jelle van der Waac3b43282017-05-08 21:31:19 +0200608 const BIGNUM *key_n;
Simon Glass19c402a2013-06-13 15:10:02 -0700609 BN_CTX *bn_ctx = BN_CTX_new();
610 int ret = 0;
611
612 /* Initialize BIGNUMs */
613 big1 = BN_new();
614 big2 = BN_new();
615 big32 = BN_new();
616 r = BN_new();
617 r_squared = BN_new();
618 tmp = BN_new();
619 big2_32 = BN_new();
620 n = BN_new();
621 if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
622 !n) {
623 fprintf(stderr, "Out of memory (bignum)\n");
624 return -ENOMEM;
625 }
626
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200627 if (0 != rsa_get_exponent(key, exponent))
628 ret = -1;
629
Jelle van der Waac3b43282017-05-08 21:31:19 +0200630 RSA_get0_key(key, &key_n, NULL, NULL);
631 if (!BN_copy(n, key_n) || !BN_set_word(big1, 1L) ||
Simon Glass19c402a2013-06-13 15:10:02 -0700632 !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
633 ret = -1;
634
635 /* big2_32 = 2^32 */
636 if (!BN_exp(big2_32, big2, big32, bn_ctx))
637 ret = -1;
638
639 /* Calculate n0_inv = -1 / n[0] mod 2^32 */
640 if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
641 !BN_sub(tmp, big2_32, tmp))
642 ret = -1;
643 *n0_invp = BN_get_word(tmp);
644
645 /* Calculate R = 2^(# of key bits) */
646 if (!BN_set_word(tmp, BN_num_bits(n)) ||
647 !BN_exp(r, big2, tmp, bn_ctx))
648 ret = -1;
649
650 /* Calculate r_squared = R^2 mod n */
651 if (!BN_copy(r_squared, r) ||
652 !BN_mul(tmp, r_squared, r, bn_ctx) ||
653 !BN_mod(r_squared, tmp, n, bn_ctx))
654 ret = -1;
655
656 *modulusp = n;
657 *r_squaredp = r_squared;
658
659 BN_free(big1);
660 BN_free(big2);
661 BN_free(big32);
662 BN_free(r);
663 BN_free(tmp);
664 BN_free(big2_32);
665 if (ret) {
666 fprintf(stderr, "Bignum operations failed\n");
667 return -ENOMEM;
668 }
669
670 return ret;
671}
672
673static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
674 BIGNUM *num, int num_bits)
675{
676 int nwords = num_bits / 32;
677 int size;
678 uint32_t *buf, *ptr;
679 BIGNUM *tmp, *big2, *big32, *big2_32;
680 BN_CTX *ctx;
681 int ret;
682
683 tmp = BN_new();
684 big2 = BN_new();
685 big32 = BN_new();
686 big2_32 = BN_new();
Simon Glass8a682e02018-06-12 00:05:00 -0600687
688 /*
689 * Note: This code assumes that all of the above succeed, or all fail.
690 * In practice memory allocations generally do not fail (unless the
691 * process is killed), so it does not seem worth handling each of these
692 * as a separate case. Technicaly this could leak memory on failure,
693 * but a) it won't happen in practice, and b) it doesn't matter as we
694 * will immediately exit with a failure code.
695 */
Simon Glass19c402a2013-06-13 15:10:02 -0700696 if (!tmp || !big2 || !big32 || !big2_32) {
697 fprintf(stderr, "Out of memory (bignum)\n");
698 return -ENOMEM;
699 }
700 ctx = BN_CTX_new();
701 if (!tmp) {
702 fprintf(stderr, "Out of memory (bignum context)\n");
703 return -ENOMEM;
704 }
705 BN_set_word(big2, 2L);
706 BN_set_word(big32, 32L);
707 BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
708
709 size = nwords * sizeof(uint32_t);
710 buf = malloc(size);
711 if (!buf) {
712 fprintf(stderr, "Out of memory (%d bytes)\n", size);
713 return -ENOMEM;
714 }
715
716 /* Write out modulus as big endian array of integers */
717 for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
718 BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
719 *ptr = cpu_to_fdt32(BN_get_word(tmp));
720 BN_rshift(num, num, 32); /* N = N/B */
721 }
722
mario.six@gdsys.cc713fb2d2016-07-22 08:58:40 +0200723 /*
724 * We try signing with successively increasing size values, so this
725 * might fail several times
726 */
Simon Glass19c402a2013-06-13 15:10:02 -0700727 ret = fdt_setprop(blob, noffset, prop_name, buf, size);
Simon Glass19c402a2013-06-13 15:10:02 -0700728 free(buf);
729 BN_free(tmp);
730 BN_free(big2);
731 BN_free(big32);
732 BN_free(big2_32);
733
Simon Glass8a682e02018-06-12 00:05:00 -0600734 return ret ? -FDT_ERR_NOSPACE : 0;
Simon Glass19c402a2013-06-13 15:10:02 -0700735}
736
737int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
738{
739 BIGNUM *modulus, *r_squared;
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200740 uint64_t exponent;
Simon Glass19c402a2013-06-13 15:10:02 -0700741 uint32_t n0_inv;
742 int parent, node;
743 char name[100];
744 int ret;
745 int bits;
746 RSA *rsa;
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600747 ENGINE *e = NULL;
Simon Glass19c402a2013-06-13 15:10:02 -0700748
749 debug("%s: Getting verification data\n", __func__);
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600750 if (info->engine_id) {
751 ret = rsa_engine_init(info->engine_id, &e);
752 if (ret)
753 return ret;
754 }
755 ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
Simon Glass19c402a2013-06-13 15:10:02 -0700756 if (ret)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600757 goto err_get_pub_key;
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200758 ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
Simon Glass19c402a2013-06-13 15:10:02 -0700759 if (ret)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600760 goto err_get_params;
Simon Glass19c402a2013-06-13 15:10:02 -0700761 bits = BN_num_bits(modulus);
762 parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
763 if (parent == -FDT_ERR_NOTFOUND) {
764 parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
765 if (parent < 0) {
Simon Glass597a8b22014-06-12 07:24:42 -0600766 ret = parent;
767 if (ret != -FDT_ERR_NOSPACE) {
768 fprintf(stderr, "Couldn't create signature node: %s\n",
769 fdt_strerror(parent));
770 }
Simon Glass19c402a2013-06-13 15:10:02 -0700771 }
772 }
Simon Glass597a8b22014-06-12 07:24:42 -0600773 if (ret)
774 goto done;
Simon Glass19c402a2013-06-13 15:10:02 -0700775
776 /* Either create or overwrite the named key node */
777 snprintf(name, sizeof(name), "key-%s", info->keyname);
778 node = fdt_subnode_offset(keydest, parent, name);
779 if (node == -FDT_ERR_NOTFOUND) {
780 node = fdt_add_subnode(keydest, parent, name);
781 if (node < 0) {
Simon Glass597a8b22014-06-12 07:24:42 -0600782 ret = node;
783 if (ret != -FDT_ERR_NOSPACE) {
784 fprintf(stderr, "Could not create key subnode: %s\n",
785 fdt_strerror(node));
786 }
Simon Glass19c402a2013-06-13 15:10:02 -0700787 }
788 } else if (node < 0) {
789 fprintf(stderr, "Cannot select keys parent: %s\n",
790 fdt_strerror(node));
Simon Glass597a8b22014-06-12 07:24:42 -0600791 ret = node;
Simon Glass19c402a2013-06-13 15:10:02 -0700792 }
793
Simon Glass597a8b22014-06-12 07:24:42 -0600794 if (!ret) {
Simon Glass72188f52020-03-18 11:44:06 -0600795 ret = fdt_setprop_string(keydest, node, FIT_KEY_HINT,
796 info->keyname);
Simon Glass597a8b22014-06-12 07:24:42 -0600797 }
Simon Glass4f427a42014-06-02 22:04:51 -0600798 if (!ret)
799 ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
800 if (!ret)
801 ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
802 if (!ret) {
Michael van der Westhuizene0f2f152014-07-02 10:17:26 +0200803 ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
804 }
805 if (!ret) {
Simon Glass4f427a42014-06-02 22:04:51 -0600806 ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus,
807 bits);
808 }
809 if (!ret) {
810 ret = fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared,
811 bits);
812 }
813 if (!ret) {
814 ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
Andrew Duda83dd98e2016-11-08 18:53:41 +0000815 info->name);
Simon Glass4f427a42014-06-02 22:04:51 -0600816 }
mario.six@gdsys.cc2b9ec762016-07-19 11:07:07 +0200817 if (!ret && info->require_keys) {
Simon Glass72188f52020-03-18 11:44:06 -0600818 ret = fdt_setprop_string(keydest, node, FIT_KEY_REQUIRED,
Simon Glass4f427a42014-06-02 22:04:51 -0600819 info->require_keys);
Simon Glass19c402a2013-06-13 15:10:02 -0700820 }
Simon Glass597a8b22014-06-12 07:24:42 -0600821done:
Simon Glass19c402a2013-06-13 15:10:02 -0700822 BN_free(modulus);
823 BN_free(r_squared);
824 if (ret)
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600825 ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
826err_get_params:
827 RSA_free(rsa);
828err_get_pub_key:
829 if (info->engine_id)
830 rsa_engine_remove(e);
Simon Glass19c402a2013-06-13 15:10:02 -0700831
George McCollisterf1ca1fd2017-01-06 13:14:17 -0600832 return ret;
Simon Glass19c402a2013-06-13 15:10:02 -0700833}