Blame view

lib/rsa/rsa-sign.c 17.6 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
19c402afa   Simon Glass   image: Add RSA su...
2
3
  /*
   * Copyright (c) 2013, Google Inc.
19c402afa   Simon Glass   image: Add RSA su...
4
5
6
7
8
   */
  
  #include "mkimage.h"
  #include <stdio.h>
  #include <string.h>
19c402afa   Simon Glass   image: Add RSA su...
9
10
  #include <image.h>
  #include <time.h>
c3b432816   Jelle van der Waa   rsa: Fix build wi...
11
  #include <openssl/bn.h>
19c402afa   Simon Glass   image: Add RSA su...
12
13
14
15
16
  #include <openssl/rsa.h>
  #include <openssl/pem.h>
  #include <openssl/err.h>
  #include <openssl/ssl.h>
  #include <openssl/evp.h>
f1ca1fdeb   George McCollister   mkimage: Add supp...
17
  #include <openssl/engine.h>
19c402afa   Simon Glass   image: Add RSA su...
18
19
20
21
  
  #if OPENSSL_VERSION_NUMBER >= 0x10000000L
  #define HAVE_ERR_REMOVE_THREAD_STATE
  #endif
7ac1a432a   Caliph Nomble   rsa: Fix LibreSSL...
22
23
  #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
  	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
c3b432816   Jelle van der Waa   rsa: Fix build wi...
24
25
26
27
28
29
30
31
32
33
34
  static void RSA_get0_key(const RSA *r,
                   const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
  {
     if (n != NULL)
         *n = r->n;
     if (e != NULL)
         *e = r->e;
     if (d != NULL)
         *d = r->d;
  }
  #endif
19c402afa   Simon Glass   image: Add RSA su...
35
36
37
38
39
40
41
42
43
44
45
46
47
  static int rsa_err(const char *msg)
  {
  	unsigned long sslErr = ERR_get_error();
  
  	fprintf(stderr, "%s", msg);
  	fprintf(stderr, ": %s
  ",
  		ERR_error_string(sslErr, 0));
  
  	return -1;
  }
  
  /**
f1ca1fdeb   George McCollister   mkimage: Add supp...
48
   * rsa_pem_get_pub_key() - read a public key from a .crt file
19c402afa   Simon Glass   image: Add RSA su...
49
50
51
52
53
54
   *
   * @keydir:	Directory containins the key
   * @name	Name of key file (will have a .crt extension)
   * @rsap	Returns RSA object, or NULL on failure
   * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
   */
f1ca1fdeb   George McCollister   mkimage: Add supp...
55
  static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap)
19c402afa   Simon Glass   image: Add RSA su...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  {
  	char path[1024];
  	EVP_PKEY *key;
  	X509 *cert;
  	RSA *rsa;
  	FILE *f;
  	int ret;
  
  	*rsap = NULL;
  	snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
  	f = fopen(path, "r");
  	if (!f) {
  		fprintf(stderr, "Couldn't open RSA certificate: '%s': %s
  ",
  			path, strerror(errno));
  		return -EACCES;
  	}
  
  	/* Read the certificate */
  	cert = NULL;
  	if (!PEM_read_X509(f, &cert, NULL, NULL)) {
  		rsa_err("Couldn't read certificate");
  		ret = -EINVAL;
  		goto err_cert;
  	}
  
  	/* Get the public key from the certificate. */
  	key = X509_get_pubkey(cert);
  	if (!key) {
  		rsa_err("Couldn't read public key
  ");
  		ret = -EINVAL;
  		goto err_pubkey;
  	}
  
  	/* Convert to a RSA_style key. */
  	rsa = EVP_PKEY_get1_RSA(key);
  	if (!rsa) {
  		rsa_err("Couldn't convert to a RSA style key");
542671623   Simon Glass   rsa: Fix two erro...
95
  		ret = -EINVAL;
19c402afa   Simon Glass   image: Add RSA su...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  		goto err_rsa;
  	}
  	fclose(f);
  	EVP_PKEY_free(key);
  	X509_free(cert);
  	*rsap = rsa;
  
  	return 0;
  
  err_rsa:
  	EVP_PKEY_free(key);
  err_pubkey:
  	X509_free(cert);
  err_cert:
  	fclose(f);
  	return ret;
  }
  
  /**
f1ca1fdeb   George McCollister   mkimage: Add supp...
115
   * rsa_engine_get_pub_key() - read a public key from given engine
19c402afa   Simon Glass   image: Add RSA su...
116
   *
f1ca1fdeb   George McCollister   mkimage: Add supp...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
   * @keydir:	Key prefix
   * @name	Name of key
   * @engine	Engine to use
   * @rsap	Returns RSA object, or NULL on failure
   * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
   */
  static int rsa_engine_get_pub_key(const char *keydir, const char *name,
  				  ENGINE *engine, RSA **rsap)
  {
  	const char *engine_id;
  	char key_id[1024];
  	EVP_PKEY *key;
  	RSA *rsa;
  	int ret;
  
  	*rsap = NULL;
  
  	engine_id = ENGINE_get_id(engine);
  
  	if (engine_id && !strcmp(engine_id, "pkcs11")) {
  		if (keydir)
  			snprintf(key_id, sizeof(key_id),
  				 "pkcs11:%s;object=%s;type=public",
  				 keydir, name);
  		else
  			snprintf(key_id, sizeof(key_id),
  				 "pkcs11:object=%s;type=public",
  				 name);
  	} else {
  		fprintf(stderr, "Engine not supported
  ");
  		return -ENOTSUP;
  	}
  
  	key = ENGINE_load_public_key(engine, key_id, NULL, NULL);
  	if (!key)
  		return rsa_err("Failure loading public key from engine");
  
  	/* Convert to a RSA_style key. */
  	rsa = EVP_PKEY_get1_RSA(key);
  	if (!rsa) {
  		rsa_err("Couldn't convert to a RSA style key");
  		ret = -EINVAL;
  		goto err_rsa;
  	}
  
  	EVP_PKEY_free(key);
  	*rsap = rsa;
  
  	return 0;
  
  err_rsa:
  	EVP_PKEY_free(key);
  	return ret;
  }
  
  /**
   * rsa_get_pub_key() - read a public key
   *
   * @keydir:	Directory containing the key (PEM file) or key prefix (engine)
   * @name	Name of key file (will have a .crt extension)
   * @engine	Engine to use
   * @rsap	Returns RSA object, or NULL on failure
   * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
   */
  static int rsa_get_pub_key(const char *keydir, const char *name,
  			   ENGINE *engine, RSA **rsap)
  {
  	if (engine)
  		return rsa_engine_get_pub_key(keydir, name, engine, rsap);
  	return rsa_pem_get_pub_key(keydir, name, rsap);
  }
  
  /**
   * rsa_pem_get_priv_key() - read a private key from a .key file
   *
   * @keydir:	Directory containing the key
19c402afa   Simon Glass   image: Add RSA su...
194
195
196
197
   * @name	Name of key file (will have a .key extension)
   * @rsap	Returns RSA object, or NULL on failure
   * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
   */
f1ca1fdeb   George McCollister   mkimage: Add supp...
198
199
  static int rsa_pem_get_priv_key(const char *keydir, const char *name,
  				RSA **rsap)
19c402afa   Simon Glass   image: Add RSA su...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
  {
  	char path[1024];
  	RSA *rsa;
  	FILE *f;
  
  	*rsap = NULL;
  	snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
  	f = fopen(path, "r");
  	if (!f) {
  		fprintf(stderr, "Couldn't open RSA private key: '%s': %s
  ",
  			path, strerror(errno));
  		return -ENOENT;
  	}
  
  	rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
  	if (!rsa) {
  		rsa_err("Failure reading private key");
  		fclose(f);
  		return -EPROTO;
  	}
  	fclose(f);
  	*rsap = rsa;
  
  	return 0;
  }
f1ca1fdeb   George McCollister   mkimage: Add supp...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  /**
   * rsa_engine_get_priv_key() - read a private key from given engine
   *
   * @keydir:	Key prefix
   * @name	Name of key
   * @engine	Engine to use
   * @rsap	Returns RSA object, or NULL on failure
   * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
   */
  static int rsa_engine_get_priv_key(const char *keydir, const char *name,
  				   ENGINE *engine, RSA **rsap)
  {
  	const char *engine_id;
  	char key_id[1024];
  	EVP_PKEY *key;
  	RSA *rsa;
  	int ret;
  
  	*rsap = NULL;
  
  	engine_id = ENGINE_get_id(engine);
  
  	if (engine_id && !strcmp(engine_id, "pkcs11")) {
  		if (keydir)
  			snprintf(key_id, sizeof(key_id),
  				 "pkcs11:%s;object=%s;type=private",
  				 keydir, name);
  		else
  			snprintf(key_id, sizeof(key_id),
  				 "pkcs11:object=%s;type=private",
  				 name);
  	} else {
  		fprintf(stderr, "Engine not supported
  ");
  		return -ENOTSUP;
  	}
  
  	key = ENGINE_load_private_key(engine, key_id, NULL, NULL);
  	if (!key)
  		return rsa_err("Failure loading private key from engine");
  
  	/* Convert to a RSA_style key. */
  	rsa = EVP_PKEY_get1_RSA(key);
  	if (!rsa) {
  		rsa_err("Couldn't convert to a RSA style key");
  		ret = -EINVAL;
  		goto err_rsa;
  	}
  
  	EVP_PKEY_free(key);
  	*rsap = rsa;
  
  	return 0;
  
  err_rsa:
  	EVP_PKEY_free(key);
  	return ret;
  }
  
  /**
   * rsa_get_priv_key() - read a private key
   *
   * @keydir:	Directory containing the key (PEM file) or key prefix (engine)
   * @name	Name of key
   * @engine	Engine to use for signing
   * @rsap	Returns RSA object, or NULL on failure
   * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
   */
  static int rsa_get_priv_key(const char *keydir, const char *name,
  			    ENGINE *engine, RSA **rsap)
  {
  	if (engine)
  		return rsa_engine_get_priv_key(keydir, name, engine, rsap);
  	return rsa_pem_get_priv_key(keydir, name, rsap);
  }
19c402afa   Simon Glass   image: Add RSA su...
301
302
303
  static int rsa_init(void)
  {
  	int ret;
7ac1a432a   Caliph Nomble   rsa: Fix LibreSSL...
304
305
  #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
  	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
19c402afa   Simon Glass   image: Add RSA su...
306
  	ret = SSL_library_init();
c3b432816   Jelle van der Waa   rsa: Fix build wi...
307
308
309
  #else
  	ret = OPENSSL_init_ssl(0, NULL);
  #endif
19c402afa   Simon Glass   image: Add RSA su...
310
311
312
313
314
  	if (!ret) {
  		fprintf(stderr, "Failure to init SSL library
  ");
  		return -1;
  	}
7ac1a432a   Caliph Nomble   rsa: Fix LibreSSL...
315
316
  #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
  	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
19c402afa   Simon Glass   image: Add RSA su...
317
318
319
320
321
  	SSL_load_error_strings();
  
  	OpenSSL_add_all_algorithms();
  	OpenSSL_add_all_digests();
  	OpenSSL_add_all_ciphers();
c3b432816   Jelle van der Waa   rsa: Fix build wi...
322
  #endif
19c402afa   Simon Glass   image: Add RSA su...
323
324
325
  
  	return 0;
  }
f1ca1fdeb   George McCollister   mkimage: Add supp...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  static int rsa_engine_init(const char *engine_id, ENGINE **pe)
  {
  	ENGINE *e;
  	int ret;
  
  	ENGINE_load_builtin_engines();
  
  	e = ENGINE_by_id(engine_id);
  	if (!e) {
  		fprintf(stderr, "Engine isn't available
  ");
  		ret = -1;
  		goto err_engine_by_id;
  	}
  
  	if (!ENGINE_init(e)) {
  		fprintf(stderr, "Couldn't initialize engine
  ");
  		ret = -1;
  		goto err_engine_init;
  	}
  
  	if (!ENGINE_set_default_RSA(e)) {
  		fprintf(stderr, "Couldn't set engine as default for RSA
  ");
  		ret = -1;
  		goto err_set_rsa;
  	}
  
  	*pe = e;
  
  	return 0;
  
  err_set_rsa:
  	ENGINE_finish(e);
  err_engine_init:
  	ENGINE_free(e);
  err_engine_by_id:
7ac1a432a   Caliph Nomble   rsa: Fix LibreSSL...
364
365
  #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
  	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
f1ca1fdeb   George McCollister   mkimage: Add supp...
366
  	ENGINE_cleanup();
c3b432816   Jelle van der Waa   rsa: Fix build wi...
367
  #endif
f1ca1fdeb   George McCollister   mkimage: Add supp...
368
369
  	return ret;
  }
19c402afa   Simon Glass   image: Add RSA su...
370
371
  static void rsa_remove(void)
  {
7ac1a432a   Caliph Nomble   rsa: Fix LibreSSL...
372
373
  #if OPENSSL_VERSION_NUMBER < 0x10100000L || \
  	(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
19c402afa   Simon Glass   image: Add RSA su...
374
375
376
377
378
379
380
381
  	CRYPTO_cleanup_all_ex_data();
  	ERR_free_strings();
  #ifdef HAVE_ERR_REMOVE_THREAD_STATE
  	ERR_remove_thread_state(NULL);
  #else
  	ERR_remove_state(0);
  #endif
  	EVP_cleanup();
c3b432816   Jelle van der Waa   rsa: Fix build wi...
382
  #endif
19c402afa   Simon Glass   image: Add RSA su...
383
  }
f1ca1fdeb   George McCollister   mkimage: Add supp...
384
385
386
387
388
389
390
  static void rsa_engine_remove(ENGINE *e)
  {
  	if (e) {
  		ENGINE_finish(e);
  		ENGINE_free(e);
  	}
  }
20031567e   Philippe Reynes   rsa: add a struct...
391
392
  static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo,
  			     struct checksum_algo *checksum_algo,
646257d1f   Heiko Schocher   rsa: add sha256-r...
393
394
  		const struct image_region region[], int region_count,
  		uint8_t **sigp, uint *sig_size)
19c402afa   Simon Glass   image: Add RSA su...
395
396
  {
  	EVP_PKEY *key;
20031567e   Philippe Reynes   rsa: add a struct...
397
  	EVP_PKEY_CTX *ckey;
19c402afa   Simon Glass   image: Add RSA su...
398
  	EVP_MD_CTX *context;
3b5d6979f   Philippe Reynes   rsa: use new open...
399
400
  	int ret = 0;
  	size_t size;
19c402afa   Simon Glass   image: Add RSA su...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
  	uint8_t *sig;
  	int i;
  
  	key = EVP_PKEY_new();
  	if (!key)
  		return rsa_err("EVP_PKEY object creation failed");
  
  	if (!EVP_PKEY_set1_RSA(key, rsa)) {
  		ret = rsa_err("EVP key setup failed");
  		goto err_set;
  	}
  
  	size = EVP_PKEY_size(key);
  	sig = malloc(size);
  	if (!sig) {
3b5d6979f   Philippe Reynes   rsa: use new open...
416
417
  		fprintf(stderr, "Out of memory for signature (%zu bytes)
  ",
19c402afa   Simon Glass   image: Add RSA su...
418
419
420
421
422
423
424
425
426
427
428
  			size);
  		ret = -ENOMEM;
  		goto err_alloc;
  	}
  
  	context = EVP_MD_CTX_create();
  	if (!context) {
  		ret = rsa_err("EVP context creation failed");
  		goto err_create;
  	}
  	EVP_MD_CTX_init(context);
20031567e   Philippe Reynes   rsa: add a struct...
429
430
431
432
433
434
435
436
  
  	ckey = EVP_PKEY_CTX_new(key, NULL);
  	if (!ckey) {
  		ret = rsa_err("EVP key context creation failed");
  		goto err_create;
  	}
  
  	if (EVP_DigestSignInit(context, &ckey,
3b5d6979f   Philippe Reynes   rsa: use new open...
437
438
  			       checksum_algo->calculate_sign(),
  			       NULL, key) <= 0) {
19c402afa   Simon Glass   image: Add RSA su...
439
440
441
  		ret = rsa_err("Signer setup failed");
  		goto err_sign;
  	}
061daa0b6   Philippe Reynes   rsa: add support ...
442
443
444
445
446
447
448
449
450
  #ifdef CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT
  	if (padding_algo && !strcmp(padding_algo->name, "pss")) {
  		if (EVP_PKEY_CTX_set_rsa_padding(ckey,
  						 RSA_PKCS1_PSS_PADDING) <= 0) {
  			ret = rsa_err("Signer padding setup failed");
  			goto err_sign;
  		}
  	}
  #endif /* CONFIG_FIT_ENABLE_RSASSA_PSS_SUPPORT */
19c402afa   Simon Glass   image: Add RSA su...
451
  	for (i = 0; i < region_count; i++) {
3b5d6979f   Philippe Reynes   rsa: use new open...
452
453
  		if (!EVP_DigestSignUpdate(context, region[i].data,
  					  region[i].size)) {
19c402afa   Simon Glass   image: Add RSA su...
454
455
456
457
  			ret = rsa_err("Signing data failed");
  			goto err_sign;
  		}
  	}
3b5d6979f   Philippe Reynes   rsa: use new open...
458
  	if (!EVP_DigestSignFinal(context, sig, &size)) {
19c402afa   Simon Glass   image: Add RSA su...
459
460
461
  		ret = rsa_err("Could not obtain signature");
  		goto err_sign;
  	}
3b5d6979f   Philippe Reynes   rsa: use new open...
462

7ac1a432a   Caliph Nomble   rsa: Fix LibreSSL...
463
464
  	#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
  		(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
c3b432816   Jelle van der Waa   rsa: Fix build wi...
465
466
467
468
  		EVP_MD_CTX_cleanup(context);
  	#else
  		EVP_MD_CTX_reset(context);
  	#endif
19c402afa   Simon Glass   image: Add RSA su...
469
470
  	EVP_MD_CTX_destroy(context);
  	EVP_PKEY_free(key);
3b5d6979f   Philippe Reynes   rsa: use new open...
471
472
  	debug("Got signature: %d bytes, expected %zu
  ", *sig_size, size);
19c402afa   Simon Glass   image: Add RSA su...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
  	*sigp = sig;
  	*sig_size = size;
  
  	return 0;
  
  err_sign:
  	EVP_MD_CTX_destroy(context);
  err_create:
  	free(sig);
  err_alloc:
  err_set:
  	EVP_PKEY_free(key);
  	return ret;
  }
  
  int rsa_sign(struct image_sign_info *info,
  	     const struct image_region region[], int region_count,
  	     uint8_t **sigp, uint *sig_len)
  {
  	RSA *rsa;
f1ca1fdeb   George McCollister   mkimage: Add supp...
493
  	ENGINE *e = NULL;
19c402afa   Simon Glass   image: Add RSA su...
494
495
496
497
498
  	int ret;
  
  	ret = rsa_init();
  	if (ret)
  		return ret;
f1ca1fdeb   George McCollister   mkimage: Add supp...
499
500
501
502
503
504
505
  	if (info->engine_id) {
  		ret = rsa_engine_init(info->engine_id, &e);
  		if (ret)
  			goto err_engine;
  	}
  
  	ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
19c402afa   Simon Glass   image: Add RSA su...
506
507
  	if (ret)
  		goto err_priv;
20031567e   Philippe Reynes   rsa: add a struct...
508
  	ret = rsa_sign_with_key(rsa, info->padding, info->checksum, region,
646257d1f   Heiko Schocher   rsa: add sha256-r...
509
  				region_count, sigp, sig_len);
19c402afa   Simon Glass   image: Add RSA su...
510
511
512
513
  	if (ret)
  		goto err_sign;
  
  	RSA_free(rsa);
f1ca1fdeb   George McCollister   mkimage: Add supp...
514
515
  	if (info->engine_id)
  		rsa_engine_remove(e);
19c402afa   Simon Glass   image: Add RSA su...
516
517
518
519
520
521
522
  	rsa_remove();
  
  	return ret;
  
  err_sign:
  	RSA_free(rsa);
  err_priv:
f1ca1fdeb   George McCollister   mkimage: Add supp...
523
524
525
  	if (info->engine_id)
  		rsa_engine_remove(e);
  err_engine:
19c402afa   Simon Glass   image: Add RSA su...
526
527
528
529
530
  	rsa_remove();
  	return ret;
  }
  
  /*
e0f2f1553   Michael van der Westhuizen   Implement general...
531
532
533
534
535
536
   * rsa_get_exponent(): - Get the public exponent from an RSA key
   */
  static int rsa_get_exponent(RSA *key, uint64_t *e)
  {
  	int ret;
  	BIGNUM *bn_te;
c3b432816   Jelle van der Waa   rsa: Fix build wi...
537
  	const BIGNUM *key_e;
e0f2f1553   Michael van der Westhuizen   Implement general...
538
539
540
541
542
543
544
  	uint64_t te;
  
  	ret = -EINVAL;
  	bn_te = NULL;
  
  	if (!e)
  		goto cleanup;
c3b432816   Jelle van der Waa   rsa: Fix build wi...
545
546
  	RSA_get0_key(key, NULL, &key_e, NULL);
  	if (BN_num_bits(key_e) > 64)
e0f2f1553   Michael van der Westhuizen   Implement general...
547
  		goto cleanup;
c3b432816   Jelle van der Waa   rsa: Fix build wi...
548
  	*e = BN_get_word(key_e);
e0f2f1553   Michael van der Westhuizen   Implement general...
549

c3b432816   Jelle van der Waa   rsa: Fix build wi...
550
  	if (BN_num_bits(key_e) < 33) {
e0f2f1553   Michael van der Westhuizen   Implement general...
551
552
553
  		ret = 0;
  		goto cleanup;
  	}
c3b432816   Jelle van der Waa   rsa: Fix build wi...
554
  	bn_te = BN_dup(key_e);
e0f2f1553   Michael van der Westhuizen   Implement general...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
  	if (!bn_te)
  		goto cleanup;
  
  	if (!BN_rshift(bn_te, bn_te, 32))
  		goto cleanup;
  
  	if (!BN_mask_bits(bn_te, 32))
  		goto cleanup;
  
  	te = BN_get_word(bn_te);
  	te <<= 32;
  	*e |= te;
  	ret = 0;
  
  cleanup:
  	if (bn_te)
  		BN_free(bn_te);
  
  	return ret;
  }
  
  /*
19c402afa   Simon Glass   image: Add RSA su...
577
578
   * rsa_get_params(): - Get the important parameters of an RSA public key
   */
e0f2f1553   Michael van der Westhuizen   Implement general...
579
580
  int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
  		   BIGNUM **modulusp, BIGNUM **r_squaredp)
19c402afa   Simon Glass   image: Add RSA su...
581
582
583
  {
  	BIGNUM *big1, *big2, *big32, *big2_32;
  	BIGNUM *n, *r, *r_squared, *tmp;
c3b432816   Jelle van der Waa   rsa: Fix build wi...
584
  	const BIGNUM *key_n;
19c402afa   Simon Glass   image: Add RSA su...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
  	BN_CTX *bn_ctx = BN_CTX_new();
  	int ret = 0;
  
  	/* Initialize BIGNUMs */
  	big1 = BN_new();
  	big2 = BN_new();
  	big32 = BN_new();
  	r = BN_new();
  	r_squared = BN_new();
  	tmp = BN_new();
  	big2_32 = BN_new();
  	n = BN_new();
  	if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
  	    !n) {
  		fprintf(stderr, "Out of memory (bignum)
  ");
  		return -ENOMEM;
  	}
e0f2f1553   Michael van der Westhuizen   Implement general...
603
604
  	if (0 != rsa_get_exponent(key, exponent))
  		ret = -1;
c3b432816   Jelle van der Waa   rsa: Fix build wi...
605
606
  	RSA_get0_key(key, &key_n, NULL, NULL);
  	if (!BN_copy(n, key_n) || !BN_set_word(big1, 1L) ||
19c402afa   Simon Glass   image: Add RSA su...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
  	    !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
  		ret = -1;
  
  	/* big2_32 = 2^32 */
  	if (!BN_exp(big2_32, big2, big32, bn_ctx))
  		ret = -1;
  
  	/* Calculate n0_inv = -1 / n[0] mod 2^32 */
  	if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
  	    !BN_sub(tmp, big2_32, tmp))
  		ret = -1;
  	*n0_invp = BN_get_word(tmp);
  
  	/* Calculate R = 2^(# of key bits) */
  	if (!BN_set_word(tmp, BN_num_bits(n)) ||
  	    !BN_exp(r, big2, tmp, bn_ctx))
  		ret = -1;
  
  	/* Calculate r_squared = R^2 mod n */
  	if (!BN_copy(r_squared, r) ||
  	    !BN_mul(tmp, r_squared, r, bn_ctx) ||
  	    !BN_mod(r_squared, tmp, n, bn_ctx))
  		ret = -1;
  
  	*modulusp = n;
  	*r_squaredp = r_squared;
  
  	BN_free(big1);
  	BN_free(big2);
  	BN_free(big32);
  	BN_free(r);
  	BN_free(tmp);
  	BN_free(big2_32);
  	if (ret) {
  		fprintf(stderr, "Bignum operations failed
  ");
  		return -ENOMEM;
  	}
  
  	return ret;
  }
  
  static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
  			  BIGNUM *num, int num_bits)
  {
  	int nwords = num_bits / 32;
  	int size;
  	uint32_t *buf, *ptr;
  	BIGNUM *tmp, *big2, *big32, *big2_32;
  	BN_CTX *ctx;
  	int ret;
  
  	tmp = BN_new();
  	big2 = BN_new();
  	big32 = BN_new();
  	big2_32 = BN_new();
8a682e03d   Simon Glass   rsa: Fix missing ...
663
664
665
666
667
668
669
670
671
  
  	/*
  	 * Note: This code assumes that all of the above succeed, or all fail.
  	 * In practice memory allocations generally do not fail (unless the
  	 * process is killed), so it does not seem worth handling each of these
  	 * as a separate case. Technicaly this could leak memory on failure,
  	 * but a) it won't happen in practice, and b) it doesn't matter as we
  	 * will immediately exit with a failure code.
  	 */
19c402afa   Simon Glass   image: Add RSA su...
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
  	if (!tmp || !big2 || !big32 || !big2_32) {
  		fprintf(stderr, "Out of memory (bignum)
  ");
  		return -ENOMEM;
  	}
  	ctx = BN_CTX_new();
  	if (!tmp) {
  		fprintf(stderr, "Out of memory (bignum context)
  ");
  		return -ENOMEM;
  	}
  	BN_set_word(big2, 2L);
  	BN_set_word(big32, 32L);
  	BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
  
  	size = nwords * sizeof(uint32_t);
  	buf = malloc(size);
  	if (!buf) {
  		fprintf(stderr, "Out of memory (%d bytes)
  ", size);
  		return -ENOMEM;
  	}
  
  	/* Write out modulus as big endian array of integers */
  	for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
  		BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
  		*ptr = cpu_to_fdt32(BN_get_word(tmp));
  		BN_rshift(num, num, 32); /*  N = N/B */
  	}
713fb2dcb   mario.six@gdsys.cc   tools, rsa: Furth...
701
702
703
704
  	/*
  	 * We try signing with successively increasing size values, so this
  	 * might fail several times
  	 */
19c402afa   Simon Glass   image: Add RSA su...
705
  	ret = fdt_setprop(blob, noffset, prop_name, buf, size);
19c402afa   Simon Glass   image: Add RSA su...
706
707
708
709
710
  	free(buf);
  	BN_free(tmp);
  	BN_free(big2);
  	BN_free(big32);
  	BN_free(big2_32);
8a682e03d   Simon Glass   rsa: Fix missing ...
711
  	return ret ? -FDT_ERR_NOSPACE : 0;
19c402afa   Simon Glass   image: Add RSA su...
712
713
714
715
716
  }
  
  int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
  {
  	BIGNUM *modulus, *r_squared;
e0f2f1553   Michael van der Westhuizen   Implement general...
717
  	uint64_t exponent;
19c402afa   Simon Glass   image: Add RSA su...
718
719
720
721
722
723
  	uint32_t n0_inv;
  	int parent, node;
  	char name[100];
  	int ret;
  	int bits;
  	RSA *rsa;
f1ca1fdeb   George McCollister   mkimage: Add supp...
724
  	ENGINE *e = NULL;
19c402afa   Simon Glass   image: Add RSA su...
725
726
727
  
  	debug("%s: Getting verification data
  ", __func__);
f1ca1fdeb   George McCollister   mkimage: Add supp...
728
729
730
731
732
733
  	if (info->engine_id) {
  		ret = rsa_engine_init(info->engine_id, &e);
  		if (ret)
  			return ret;
  	}
  	ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
19c402afa   Simon Glass   image: Add RSA su...
734
  	if (ret)
f1ca1fdeb   George McCollister   mkimage: Add supp...
735
  		goto err_get_pub_key;
e0f2f1553   Michael van der Westhuizen   Implement general...
736
  	ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
19c402afa   Simon Glass   image: Add RSA su...
737
  	if (ret)
f1ca1fdeb   George McCollister   mkimage: Add supp...
738
  		goto err_get_params;
19c402afa   Simon Glass   image: Add RSA su...
739
740
741
742
743
  	bits = BN_num_bits(modulus);
  	parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
  	if (parent == -FDT_ERR_NOTFOUND) {
  		parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
  		if (parent < 0) {
597a8b2c6   Simon Glass   mkimage: Automati...
744
745
746
747
748
749
  			ret = parent;
  			if (ret != -FDT_ERR_NOSPACE) {
  				fprintf(stderr, "Couldn't create signature node: %s
  ",
  					fdt_strerror(parent));
  			}
19c402afa   Simon Glass   image: Add RSA su...
750
751
  		}
  	}
597a8b2c6   Simon Glass   mkimage: Automati...
752
753
  	if (ret)
  		goto done;
19c402afa   Simon Glass   image: Add RSA su...
754
755
756
757
758
759
760
  
  	/* Either create or overwrite the named key node */
  	snprintf(name, sizeof(name), "key-%s", info->keyname);
  	node = fdt_subnode_offset(keydest, parent, name);
  	if (node == -FDT_ERR_NOTFOUND) {
  		node = fdt_add_subnode(keydest, parent, name);
  		if (node < 0) {
597a8b2c6   Simon Glass   mkimage: Automati...
761
762
763
764
765
766
  			ret = node;
  			if (ret != -FDT_ERR_NOSPACE) {
  				fprintf(stderr, "Could not create key subnode: %s
  ",
  					fdt_strerror(node));
  			}
19c402afa   Simon Glass   image: Add RSA su...
767
768
769
770
771
  		}
  	} else if (node < 0) {
  		fprintf(stderr, "Cannot select keys parent: %s
  ",
  			fdt_strerror(node));
597a8b2c6   Simon Glass   mkimage: Automati...
772
  		ret = node;
19c402afa   Simon Glass   image: Add RSA su...
773
  	}
597a8b2c6   Simon Glass   mkimage: Automati...
774
775
  	if (!ret) {
  		ret = fdt_setprop_string(keydest, node, "key-name-hint",
19c402afa   Simon Glass   image: Add RSA su...
776
  				 info->keyname);
597a8b2c6   Simon Glass   mkimage: Automati...
777
  	}
4f427a421   Simon Glass   fdt: Update funct...
778
779
780
781
782
  	if (!ret)
  		ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
  	if (!ret)
  		ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
  	if (!ret) {
e0f2f1553   Michael van der Westhuizen   Implement general...
783
784
785
  		ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
  	}
  	if (!ret) {
4f427a421   Simon Glass   fdt: Update funct...
786
787
788
789
790
791
792
793
794
  		ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus,
  				     bits);
  	}
  	if (!ret) {
  		ret = fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared,
  				     bits);
  	}
  	if (!ret) {
  		ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
83dd98e01   Andrew Duda   image: Combine im...
795
  					 info->name);
4f427a421   Simon Glass   fdt: Update funct...
796
  	}
2b9ec762c   mario.six@gdsys.cc   rsa: Fix return v...
797
  	if (!ret && info->require_keys) {
4f427a421   Simon Glass   fdt: Update funct...
798
799
  		ret = fdt_setprop_string(keydest, node, "required",
  					 info->require_keys);
19c402afa   Simon Glass   image: Add RSA su...
800
  	}
597a8b2c6   Simon Glass   mkimage: Automati...
801
  done:
19c402afa   Simon Glass   image: Add RSA su...
802
803
804
  	BN_free(modulus);
  	BN_free(r_squared);
  	if (ret)
f1ca1fdeb   George McCollister   mkimage: Add supp...
805
806
807
808
809
810
  		ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
  err_get_params:
  	RSA_free(rsa);
  err_get_pub_key:
  	if (info->engine_id)
  		rsa_engine_remove(e);
19c402afa   Simon Glass   image: Add RSA su...
811

f1ca1fdeb   George McCollister   mkimage: Add supp...
812
  	return ret;
19c402afa   Simon Glass   image: Add RSA su...
813
  }