xref: /rk3399_rockchip-uboot/lib/rsa/rsa-sign.c (revision e0f2f15534146729fdf2ce58b740121fd67eea1c)
119c402afSSimon Glass /*
219c402afSSimon Glass  * Copyright (c) 2013, Google Inc.
319c402afSSimon Glass  *
41a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
519c402afSSimon Glass  */
619c402afSSimon Glass 
719c402afSSimon Glass #include "mkimage.h"
819c402afSSimon Glass #include <stdio.h>
919c402afSSimon Glass #include <string.h>
1019c402afSSimon Glass #include <image.h>
1119c402afSSimon Glass #include <time.h>
1219c402afSSimon Glass #include <openssl/rsa.h>
1319c402afSSimon Glass #include <openssl/pem.h>
1419c402afSSimon Glass #include <openssl/err.h>
1519c402afSSimon Glass #include <openssl/ssl.h>
1619c402afSSimon Glass #include <openssl/evp.h>
1719c402afSSimon Glass 
1819c402afSSimon Glass #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1919c402afSSimon Glass #define HAVE_ERR_REMOVE_THREAD_STATE
2019c402afSSimon Glass #endif
2119c402afSSimon Glass 
2219c402afSSimon Glass static int rsa_err(const char *msg)
2319c402afSSimon Glass {
2419c402afSSimon Glass 	unsigned long sslErr = ERR_get_error();
2519c402afSSimon Glass 
2619c402afSSimon Glass 	fprintf(stderr, "%s", msg);
2719c402afSSimon Glass 	fprintf(stderr, ": %s\n",
2819c402afSSimon Glass 		ERR_error_string(sslErr, 0));
2919c402afSSimon Glass 
3019c402afSSimon Glass 	return -1;
3119c402afSSimon Glass }
3219c402afSSimon Glass 
3319c402afSSimon Glass /**
3419c402afSSimon Glass  * rsa_get_pub_key() - read a public key from a .crt file
3519c402afSSimon Glass  *
3619c402afSSimon Glass  * @keydir:	Directory containins the key
3719c402afSSimon Glass  * @name	Name of key file (will have a .crt extension)
3819c402afSSimon Glass  * @rsap	Returns RSA object, or NULL on failure
3919c402afSSimon Glass  * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
4019c402afSSimon Glass  */
4119c402afSSimon Glass static int rsa_get_pub_key(const char *keydir, const char *name, RSA **rsap)
4219c402afSSimon Glass {
4319c402afSSimon Glass 	char path[1024];
4419c402afSSimon Glass 	EVP_PKEY *key;
4519c402afSSimon Glass 	X509 *cert;
4619c402afSSimon Glass 	RSA *rsa;
4719c402afSSimon Glass 	FILE *f;
4819c402afSSimon Glass 	int ret;
4919c402afSSimon Glass 
5019c402afSSimon Glass 	*rsap = NULL;
5119c402afSSimon Glass 	snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
5219c402afSSimon Glass 	f = fopen(path, "r");
5319c402afSSimon Glass 	if (!f) {
5419c402afSSimon Glass 		fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
5519c402afSSimon Glass 			path, strerror(errno));
5619c402afSSimon Glass 		return -EACCES;
5719c402afSSimon Glass 	}
5819c402afSSimon Glass 
5919c402afSSimon Glass 	/* Read the certificate */
6019c402afSSimon Glass 	cert = NULL;
6119c402afSSimon Glass 	if (!PEM_read_X509(f, &cert, NULL, NULL)) {
6219c402afSSimon Glass 		rsa_err("Couldn't read certificate");
6319c402afSSimon Glass 		ret = -EINVAL;
6419c402afSSimon Glass 		goto err_cert;
6519c402afSSimon Glass 	}
6619c402afSSimon Glass 
6719c402afSSimon Glass 	/* Get the public key from the certificate. */
6819c402afSSimon Glass 	key = X509_get_pubkey(cert);
6919c402afSSimon Glass 	if (!key) {
7019c402afSSimon Glass 		rsa_err("Couldn't read public key\n");
7119c402afSSimon Glass 		ret = -EINVAL;
7219c402afSSimon Glass 		goto err_pubkey;
7319c402afSSimon Glass 	}
7419c402afSSimon Glass 
7519c402afSSimon Glass 	/* Convert to a RSA_style key. */
7619c402afSSimon Glass 	rsa = EVP_PKEY_get1_RSA(key);
7719c402afSSimon Glass 	if (!rsa) {
7819c402afSSimon Glass 		rsa_err("Couldn't convert to a RSA style key");
7919c402afSSimon Glass 		goto err_rsa;
8019c402afSSimon Glass 	}
8119c402afSSimon Glass 	fclose(f);
8219c402afSSimon Glass 	EVP_PKEY_free(key);
8319c402afSSimon Glass 	X509_free(cert);
8419c402afSSimon Glass 	*rsap = rsa;
8519c402afSSimon Glass 
8619c402afSSimon Glass 	return 0;
8719c402afSSimon Glass 
8819c402afSSimon Glass err_rsa:
8919c402afSSimon Glass 	EVP_PKEY_free(key);
9019c402afSSimon Glass err_pubkey:
9119c402afSSimon Glass 	X509_free(cert);
9219c402afSSimon Glass err_cert:
9319c402afSSimon Glass 	fclose(f);
9419c402afSSimon Glass 	return ret;
9519c402afSSimon Glass }
9619c402afSSimon Glass 
9719c402afSSimon Glass /**
9819c402afSSimon Glass  * rsa_get_priv_key() - read a private key from a .key file
9919c402afSSimon Glass  *
10019c402afSSimon Glass  * @keydir:	Directory containins the key
10119c402afSSimon Glass  * @name	Name of key file (will have a .key extension)
10219c402afSSimon Glass  * @rsap	Returns RSA object, or NULL on failure
10319c402afSSimon Glass  * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
10419c402afSSimon Glass  */
10519c402afSSimon Glass static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
10619c402afSSimon Glass {
10719c402afSSimon Glass 	char path[1024];
10819c402afSSimon Glass 	RSA *rsa;
10919c402afSSimon Glass 	FILE *f;
11019c402afSSimon Glass 
11119c402afSSimon Glass 	*rsap = NULL;
11219c402afSSimon Glass 	snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
11319c402afSSimon Glass 	f = fopen(path, "r");
11419c402afSSimon Glass 	if (!f) {
11519c402afSSimon Glass 		fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
11619c402afSSimon Glass 			path, strerror(errno));
11719c402afSSimon Glass 		return -ENOENT;
11819c402afSSimon Glass 	}
11919c402afSSimon Glass 
12019c402afSSimon Glass 	rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
12119c402afSSimon Glass 	if (!rsa) {
12219c402afSSimon Glass 		rsa_err("Failure reading private key");
12319c402afSSimon Glass 		fclose(f);
12419c402afSSimon Glass 		return -EPROTO;
12519c402afSSimon Glass 	}
12619c402afSSimon Glass 	fclose(f);
12719c402afSSimon Glass 	*rsap = rsa;
12819c402afSSimon Glass 
12919c402afSSimon Glass 	return 0;
13019c402afSSimon Glass }
13119c402afSSimon Glass 
13219c402afSSimon Glass static int rsa_init(void)
13319c402afSSimon Glass {
13419c402afSSimon Glass 	int ret;
13519c402afSSimon Glass 
13619c402afSSimon Glass 	ret = SSL_library_init();
13719c402afSSimon Glass 	if (!ret) {
13819c402afSSimon Glass 		fprintf(stderr, "Failure to init SSL library\n");
13919c402afSSimon Glass 		return -1;
14019c402afSSimon Glass 	}
14119c402afSSimon Glass 	SSL_load_error_strings();
14219c402afSSimon Glass 
14319c402afSSimon Glass 	OpenSSL_add_all_algorithms();
14419c402afSSimon Glass 	OpenSSL_add_all_digests();
14519c402afSSimon Glass 	OpenSSL_add_all_ciphers();
14619c402afSSimon Glass 
14719c402afSSimon Glass 	return 0;
14819c402afSSimon Glass }
14919c402afSSimon Glass 
15019c402afSSimon Glass static void rsa_remove(void)
15119c402afSSimon Glass {
15219c402afSSimon Glass 	CRYPTO_cleanup_all_ex_data();
15319c402afSSimon Glass 	ERR_free_strings();
15419c402afSSimon Glass #ifdef HAVE_ERR_REMOVE_THREAD_STATE
15519c402afSSimon Glass 	ERR_remove_thread_state(NULL);
15619c402afSSimon Glass #else
15719c402afSSimon Glass 	ERR_remove_state(0);
15819c402afSSimon Glass #endif
15919c402afSSimon Glass 	EVP_cleanup();
16019c402afSSimon Glass }
16119c402afSSimon Glass 
162646257d1SHeiko Schocher static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
163646257d1SHeiko Schocher 		const struct image_region region[], int region_count,
164646257d1SHeiko Schocher 		uint8_t **sigp, uint *sig_size)
16519c402afSSimon Glass {
16619c402afSSimon Glass 	EVP_PKEY *key;
16719c402afSSimon Glass 	EVP_MD_CTX *context;
16819c402afSSimon Glass 	int size, ret = 0;
16919c402afSSimon Glass 	uint8_t *sig;
17019c402afSSimon Glass 	int i;
17119c402afSSimon Glass 
17219c402afSSimon Glass 	key = EVP_PKEY_new();
17319c402afSSimon Glass 	if (!key)
17419c402afSSimon Glass 		return rsa_err("EVP_PKEY object creation failed");
17519c402afSSimon Glass 
17619c402afSSimon Glass 	if (!EVP_PKEY_set1_RSA(key, rsa)) {
17719c402afSSimon Glass 		ret = rsa_err("EVP key setup failed");
17819c402afSSimon Glass 		goto err_set;
17919c402afSSimon Glass 	}
18019c402afSSimon Glass 
18119c402afSSimon Glass 	size = EVP_PKEY_size(key);
18219c402afSSimon Glass 	sig = malloc(size);
18319c402afSSimon Glass 	if (!sig) {
18419c402afSSimon Glass 		fprintf(stderr, "Out of memory for signature (%d bytes)\n",
18519c402afSSimon Glass 			size);
18619c402afSSimon Glass 		ret = -ENOMEM;
18719c402afSSimon Glass 		goto err_alloc;
18819c402afSSimon Glass 	}
18919c402afSSimon Glass 
19019c402afSSimon Glass 	context = EVP_MD_CTX_create();
19119c402afSSimon Glass 	if (!context) {
19219c402afSSimon Glass 		ret = rsa_err("EVP context creation failed");
19319c402afSSimon Glass 		goto err_create;
19419c402afSSimon Glass 	}
19519c402afSSimon Glass 	EVP_MD_CTX_init(context);
19629a23f9dSHeiko Schocher 	if (!EVP_SignInit(context, checksum_algo->calculate_sign())) {
19719c402afSSimon Glass 		ret = rsa_err("Signer setup failed");
19819c402afSSimon Glass 		goto err_sign;
19919c402afSSimon Glass 	}
20019c402afSSimon Glass 
20119c402afSSimon Glass 	for (i = 0; i < region_count; i++) {
20219c402afSSimon Glass 		if (!EVP_SignUpdate(context, region[i].data, region[i].size)) {
20319c402afSSimon Glass 			ret = rsa_err("Signing data failed");
20419c402afSSimon Glass 			goto err_sign;
20519c402afSSimon Glass 		}
20619c402afSSimon Glass 	}
20719c402afSSimon Glass 
20819c402afSSimon Glass 	if (!EVP_SignFinal(context, sig, sig_size, key)) {
20919c402afSSimon Glass 		ret = rsa_err("Could not obtain signature");
21019c402afSSimon Glass 		goto err_sign;
21119c402afSSimon Glass 	}
21219c402afSSimon Glass 	EVP_MD_CTX_cleanup(context);
21319c402afSSimon Glass 	EVP_MD_CTX_destroy(context);
21419c402afSSimon Glass 	EVP_PKEY_free(key);
21519c402afSSimon Glass 
21619c402afSSimon Glass 	debug("Got signature: %d bytes, expected %d\n", *sig_size, size);
21719c402afSSimon Glass 	*sigp = sig;
21819c402afSSimon Glass 	*sig_size = size;
21919c402afSSimon Glass 
22019c402afSSimon Glass 	return 0;
22119c402afSSimon Glass 
22219c402afSSimon Glass err_sign:
22319c402afSSimon Glass 	EVP_MD_CTX_destroy(context);
22419c402afSSimon Glass err_create:
22519c402afSSimon Glass 	free(sig);
22619c402afSSimon Glass err_alloc:
22719c402afSSimon Glass err_set:
22819c402afSSimon Glass 	EVP_PKEY_free(key);
22919c402afSSimon Glass 	return ret;
23019c402afSSimon Glass }
23119c402afSSimon Glass 
23219c402afSSimon Glass int rsa_sign(struct image_sign_info *info,
23319c402afSSimon Glass 	     const struct image_region region[], int region_count,
23419c402afSSimon Glass 	     uint8_t **sigp, uint *sig_len)
23519c402afSSimon Glass {
23619c402afSSimon Glass 	RSA *rsa;
23719c402afSSimon Glass 	int ret;
23819c402afSSimon Glass 
23919c402afSSimon Glass 	ret = rsa_init();
24019c402afSSimon Glass 	if (ret)
24119c402afSSimon Glass 		return ret;
24219c402afSSimon Glass 
24319c402afSSimon Glass 	ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
24419c402afSSimon Glass 	if (ret)
24519c402afSSimon Glass 		goto err_priv;
246646257d1SHeiko Schocher 	ret = rsa_sign_with_key(rsa, info->algo->checksum, region,
247646257d1SHeiko Schocher 				region_count, sigp, sig_len);
24819c402afSSimon Glass 	if (ret)
24919c402afSSimon Glass 		goto err_sign;
25019c402afSSimon Glass 
25119c402afSSimon Glass 	RSA_free(rsa);
25219c402afSSimon Glass 	rsa_remove();
25319c402afSSimon Glass 
25419c402afSSimon Glass 	return ret;
25519c402afSSimon Glass 
25619c402afSSimon Glass err_sign:
25719c402afSSimon Glass 	RSA_free(rsa);
25819c402afSSimon Glass err_priv:
25919c402afSSimon Glass 	rsa_remove();
26019c402afSSimon Glass 	return ret;
26119c402afSSimon Glass }
26219c402afSSimon Glass 
26319c402afSSimon Glass /*
264*e0f2f155SMichael van der Westhuizen  * rsa_get_exponent(): - Get the public exponent from an RSA key
265*e0f2f155SMichael van der Westhuizen  */
266*e0f2f155SMichael van der Westhuizen static int rsa_get_exponent(RSA *key, uint64_t *e)
267*e0f2f155SMichael van der Westhuizen {
268*e0f2f155SMichael van der Westhuizen 	int ret;
269*e0f2f155SMichael van der Westhuizen 	BIGNUM *bn_te;
270*e0f2f155SMichael van der Westhuizen 	uint64_t te;
271*e0f2f155SMichael van der Westhuizen 
272*e0f2f155SMichael van der Westhuizen 	ret = -EINVAL;
273*e0f2f155SMichael van der Westhuizen 	bn_te = NULL;
274*e0f2f155SMichael van der Westhuizen 
275*e0f2f155SMichael van der Westhuizen 	if (!e)
276*e0f2f155SMichael van der Westhuizen 		goto cleanup;
277*e0f2f155SMichael van der Westhuizen 
278*e0f2f155SMichael van der Westhuizen 	if (BN_num_bits(key->e) > 64)
279*e0f2f155SMichael van der Westhuizen 		goto cleanup;
280*e0f2f155SMichael van der Westhuizen 
281*e0f2f155SMichael van der Westhuizen 	*e = BN_get_word(key->e);
282*e0f2f155SMichael van der Westhuizen 
283*e0f2f155SMichael van der Westhuizen 	if (BN_num_bits(key->e) < 33) {
284*e0f2f155SMichael van der Westhuizen 		ret = 0;
285*e0f2f155SMichael van der Westhuizen 		goto cleanup;
286*e0f2f155SMichael van der Westhuizen 	}
287*e0f2f155SMichael van der Westhuizen 
288*e0f2f155SMichael van der Westhuizen 	bn_te = BN_dup(key->e);
289*e0f2f155SMichael van der Westhuizen 	if (!bn_te)
290*e0f2f155SMichael van der Westhuizen 		goto cleanup;
291*e0f2f155SMichael van der Westhuizen 
292*e0f2f155SMichael van der Westhuizen 	if (!BN_rshift(bn_te, bn_te, 32))
293*e0f2f155SMichael van der Westhuizen 		goto cleanup;
294*e0f2f155SMichael van der Westhuizen 
295*e0f2f155SMichael van der Westhuizen 	if (!BN_mask_bits(bn_te, 32))
296*e0f2f155SMichael van der Westhuizen 		goto cleanup;
297*e0f2f155SMichael van der Westhuizen 
298*e0f2f155SMichael van der Westhuizen 	te = BN_get_word(bn_te);
299*e0f2f155SMichael van der Westhuizen 	te <<= 32;
300*e0f2f155SMichael van der Westhuizen 	*e |= te;
301*e0f2f155SMichael van der Westhuizen 	ret = 0;
302*e0f2f155SMichael van der Westhuizen 
303*e0f2f155SMichael van der Westhuizen cleanup:
304*e0f2f155SMichael van der Westhuizen 	if (bn_te)
305*e0f2f155SMichael van der Westhuizen 		BN_free(bn_te);
306*e0f2f155SMichael van der Westhuizen 
307*e0f2f155SMichael van der Westhuizen 	return ret;
308*e0f2f155SMichael van der Westhuizen }
309*e0f2f155SMichael van der Westhuizen 
310*e0f2f155SMichael van der Westhuizen /*
31119c402afSSimon Glass  * rsa_get_params(): - Get the important parameters of an RSA public key
31219c402afSSimon Glass  */
313*e0f2f155SMichael van der Westhuizen int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp,
314*e0f2f155SMichael van der Westhuizen 		   BIGNUM **modulusp, BIGNUM **r_squaredp)
31519c402afSSimon Glass {
31619c402afSSimon Glass 	BIGNUM *big1, *big2, *big32, *big2_32;
31719c402afSSimon Glass 	BIGNUM *n, *r, *r_squared, *tmp;
31819c402afSSimon Glass 	BN_CTX *bn_ctx = BN_CTX_new();
31919c402afSSimon Glass 	int ret = 0;
32019c402afSSimon Glass 
32119c402afSSimon Glass 	/* Initialize BIGNUMs */
32219c402afSSimon Glass 	big1 = BN_new();
32319c402afSSimon Glass 	big2 = BN_new();
32419c402afSSimon Glass 	big32 = BN_new();
32519c402afSSimon Glass 	r = BN_new();
32619c402afSSimon Glass 	r_squared = BN_new();
32719c402afSSimon Glass 	tmp = BN_new();
32819c402afSSimon Glass 	big2_32 = BN_new();
32919c402afSSimon Glass 	n = BN_new();
33019c402afSSimon Glass 	if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
33119c402afSSimon Glass 	    !n) {
33219c402afSSimon Glass 		fprintf(stderr, "Out of memory (bignum)\n");
33319c402afSSimon Glass 		return -ENOMEM;
33419c402afSSimon Glass 	}
33519c402afSSimon Glass 
336*e0f2f155SMichael van der Westhuizen 	if (0 != rsa_get_exponent(key, exponent))
337*e0f2f155SMichael van der Westhuizen 		ret = -1;
338*e0f2f155SMichael van der Westhuizen 
33919c402afSSimon Glass 	if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) ||
34019c402afSSimon Glass 	    !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
34119c402afSSimon Glass 		ret = -1;
34219c402afSSimon Glass 
34319c402afSSimon Glass 	/* big2_32 = 2^32 */
34419c402afSSimon Glass 	if (!BN_exp(big2_32, big2, big32, bn_ctx))
34519c402afSSimon Glass 		ret = -1;
34619c402afSSimon Glass 
34719c402afSSimon Glass 	/* Calculate n0_inv = -1 / n[0] mod 2^32 */
34819c402afSSimon Glass 	if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
34919c402afSSimon Glass 	    !BN_sub(tmp, big2_32, tmp))
35019c402afSSimon Glass 		ret = -1;
35119c402afSSimon Glass 	*n0_invp = BN_get_word(tmp);
35219c402afSSimon Glass 
35319c402afSSimon Glass 	/* Calculate R = 2^(# of key bits) */
35419c402afSSimon Glass 	if (!BN_set_word(tmp, BN_num_bits(n)) ||
35519c402afSSimon Glass 	    !BN_exp(r, big2, tmp, bn_ctx))
35619c402afSSimon Glass 		ret = -1;
35719c402afSSimon Glass 
35819c402afSSimon Glass 	/* Calculate r_squared = R^2 mod n */
35919c402afSSimon Glass 	if (!BN_copy(r_squared, r) ||
36019c402afSSimon Glass 	    !BN_mul(tmp, r_squared, r, bn_ctx) ||
36119c402afSSimon Glass 	    !BN_mod(r_squared, tmp, n, bn_ctx))
36219c402afSSimon Glass 		ret = -1;
36319c402afSSimon Glass 
36419c402afSSimon Glass 	*modulusp = n;
36519c402afSSimon Glass 	*r_squaredp = r_squared;
36619c402afSSimon Glass 
36719c402afSSimon Glass 	BN_free(big1);
36819c402afSSimon Glass 	BN_free(big2);
36919c402afSSimon Glass 	BN_free(big32);
37019c402afSSimon Glass 	BN_free(r);
37119c402afSSimon Glass 	BN_free(tmp);
37219c402afSSimon Glass 	BN_free(big2_32);
37319c402afSSimon Glass 	if (ret) {
37419c402afSSimon Glass 		fprintf(stderr, "Bignum operations failed\n");
37519c402afSSimon Glass 		return -ENOMEM;
37619c402afSSimon Glass 	}
37719c402afSSimon Glass 
37819c402afSSimon Glass 	return ret;
37919c402afSSimon Glass }
38019c402afSSimon Glass 
38119c402afSSimon Glass static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
38219c402afSSimon Glass 			  BIGNUM *num, int num_bits)
38319c402afSSimon Glass {
38419c402afSSimon Glass 	int nwords = num_bits / 32;
38519c402afSSimon Glass 	int size;
38619c402afSSimon Glass 	uint32_t *buf, *ptr;
38719c402afSSimon Glass 	BIGNUM *tmp, *big2, *big32, *big2_32;
38819c402afSSimon Glass 	BN_CTX *ctx;
38919c402afSSimon Glass 	int ret;
39019c402afSSimon Glass 
39119c402afSSimon Glass 	tmp = BN_new();
39219c402afSSimon Glass 	big2 = BN_new();
39319c402afSSimon Glass 	big32 = BN_new();
39419c402afSSimon Glass 	big2_32 = BN_new();
39519c402afSSimon Glass 	if (!tmp || !big2 || !big32 || !big2_32) {
39619c402afSSimon Glass 		fprintf(stderr, "Out of memory (bignum)\n");
39719c402afSSimon Glass 		return -ENOMEM;
39819c402afSSimon Glass 	}
39919c402afSSimon Glass 	ctx = BN_CTX_new();
40019c402afSSimon Glass 	if (!tmp) {
40119c402afSSimon Glass 		fprintf(stderr, "Out of memory (bignum context)\n");
40219c402afSSimon Glass 		return -ENOMEM;
40319c402afSSimon Glass 	}
40419c402afSSimon Glass 	BN_set_word(big2, 2L);
40519c402afSSimon Glass 	BN_set_word(big32, 32L);
40619c402afSSimon Glass 	BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
40719c402afSSimon Glass 
40819c402afSSimon Glass 	size = nwords * sizeof(uint32_t);
40919c402afSSimon Glass 	buf = malloc(size);
41019c402afSSimon Glass 	if (!buf) {
41119c402afSSimon Glass 		fprintf(stderr, "Out of memory (%d bytes)\n", size);
41219c402afSSimon Glass 		return -ENOMEM;
41319c402afSSimon Glass 	}
41419c402afSSimon Glass 
41519c402afSSimon Glass 	/* Write out modulus as big endian array of integers */
41619c402afSSimon Glass 	for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
41719c402afSSimon Glass 		BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
41819c402afSSimon Glass 		*ptr = cpu_to_fdt32(BN_get_word(tmp));
41919c402afSSimon Glass 		BN_rshift(num, num, 32); /*  N = N/B */
42019c402afSSimon Glass 	}
42119c402afSSimon Glass 
42219c402afSSimon Glass 	ret = fdt_setprop(blob, noffset, prop_name, buf, size);
42319c402afSSimon Glass 	if (ret) {
42419c402afSSimon Glass 		fprintf(stderr, "Failed to write public key to FIT\n");
42519c402afSSimon Glass 		return -ENOSPC;
42619c402afSSimon Glass 	}
42719c402afSSimon Glass 	free(buf);
42819c402afSSimon Glass 	BN_free(tmp);
42919c402afSSimon Glass 	BN_free(big2);
43019c402afSSimon Glass 	BN_free(big32);
43119c402afSSimon Glass 	BN_free(big2_32);
43219c402afSSimon Glass 
43319c402afSSimon Glass 	return ret;
43419c402afSSimon Glass }
43519c402afSSimon Glass 
43619c402afSSimon Glass int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
43719c402afSSimon Glass {
43819c402afSSimon Glass 	BIGNUM *modulus, *r_squared;
439*e0f2f155SMichael van der Westhuizen 	uint64_t exponent;
44019c402afSSimon Glass 	uint32_t n0_inv;
44119c402afSSimon Glass 	int parent, node;
44219c402afSSimon Glass 	char name[100];
44319c402afSSimon Glass 	int ret;
44419c402afSSimon Glass 	int bits;
44519c402afSSimon Glass 	RSA *rsa;
44619c402afSSimon Glass 
44719c402afSSimon Glass 	debug("%s: Getting verification data\n", __func__);
44819c402afSSimon Glass 	ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa);
44919c402afSSimon Glass 	if (ret)
45019c402afSSimon Glass 		return ret;
451*e0f2f155SMichael van der Westhuizen 	ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
45219c402afSSimon Glass 	if (ret)
45319c402afSSimon Glass 		return ret;
45419c402afSSimon Glass 	bits = BN_num_bits(modulus);
45519c402afSSimon Glass 	parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
45619c402afSSimon Glass 	if (parent == -FDT_ERR_NOTFOUND) {
45719c402afSSimon Glass 		parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
45819c402afSSimon Glass 		if (parent < 0) {
459597a8b2cSSimon Glass 			ret = parent;
460597a8b2cSSimon Glass 			if (ret != -FDT_ERR_NOSPACE) {
46119c402afSSimon Glass 				fprintf(stderr, "Couldn't create signature node: %s\n",
46219c402afSSimon Glass 					fdt_strerror(parent));
46319c402afSSimon Glass 			}
46419c402afSSimon Glass 		}
465597a8b2cSSimon Glass 	}
466597a8b2cSSimon Glass 	if (ret)
467597a8b2cSSimon Glass 		goto done;
46819c402afSSimon Glass 
46919c402afSSimon Glass 	/* Either create or overwrite the named key node */
47019c402afSSimon Glass 	snprintf(name, sizeof(name), "key-%s", info->keyname);
47119c402afSSimon Glass 	node = fdt_subnode_offset(keydest, parent, name);
47219c402afSSimon Glass 	if (node == -FDT_ERR_NOTFOUND) {
47319c402afSSimon Glass 		node = fdt_add_subnode(keydest, parent, name);
47419c402afSSimon Glass 		if (node < 0) {
475597a8b2cSSimon Glass 			ret = node;
476597a8b2cSSimon Glass 			if (ret != -FDT_ERR_NOSPACE) {
47719c402afSSimon Glass 				fprintf(stderr, "Could not create key subnode: %s\n",
47819c402afSSimon Glass 					fdt_strerror(node));
479597a8b2cSSimon Glass 			}
48019c402afSSimon Glass 		}
48119c402afSSimon Glass 	} else if (node < 0) {
48219c402afSSimon Glass 		fprintf(stderr, "Cannot select keys parent: %s\n",
48319c402afSSimon Glass 			fdt_strerror(node));
484597a8b2cSSimon Glass 		ret = node;
48519c402afSSimon Glass 	}
48619c402afSSimon Glass 
487597a8b2cSSimon Glass 	if (!ret) {
48819c402afSSimon Glass 		ret = fdt_setprop_string(keydest, node, "key-name-hint",
48919c402afSSimon Glass 				 info->keyname);
490597a8b2cSSimon Glass 	}
4914f427a42SSimon Glass 	if (!ret)
4924f427a42SSimon Glass 		ret = fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
4934f427a42SSimon Glass 	if (!ret)
4944f427a42SSimon Glass 		ret = fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
4954f427a42SSimon Glass 	if (!ret) {
496*e0f2f155SMichael van der Westhuizen 		ret = fdt_setprop_u64(keydest, node, "rsa,exponent", exponent);
497*e0f2f155SMichael van der Westhuizen 	}
498*e0f2f155SMichael van der Westhuizen 	if (!ret) {
4994f427a42SSimon Glass 		ret = fdt_add_bignum(keydest, node, "rsa,modulus", modulus,
5004f427a42SSimon Glass 				     bits);
5014f427a42SSimon Glass 	}
5024f427a42SSimon Glass 	if (!ret) {
5034f427a42SSimon Glass 		ret = fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared,
5044f427a42SSimon Glass 				     bits);
5054f427a42SSimon Glass 	}
5064f427a42SSimon Glass 	if (!ret) {
5074f427a42SSimon Glass 		ret = fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
50819c402afSSimon Glass 					 info->algo->name);
5094f427a42SSimon Glass 	}
51019c402afSSimon Glass 	if (info->require_keys) {
5114f427a42SSimon Glass 		ret = fdt_setprop_string(keydest, node, "required",
51219c402afSSimon Glass 					 info->require_keys);
51319c402afSSimon Glass 	}
514597a8b2cSSimon Glass done:
51519c402afSSimon Glass 	BN_free(modulus);
51619c402afSSimon Glass 	BN_free(r_squared);
51719c402afSSimon Glass 	if (ret)
518597a8b2cSSimon Glass 		return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
51919c402afSSimon Glass 
52019c402afSSimon Glass 	return 0;
52119c402afSSimon Glass }
522