xref: /rk3399_ARM-atf/tools/cert_create/src/key.c (revision ea6f8452f6eb561a0fa96a712da93fcdba40cd9c)
16f971622SJuan Castillo /*
2cf2dd17dSJuan Pablo Conde  * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
36f971622SJuan Castillo  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
56f971622SJuan Castillo  */
66f971622SJuan Castillo 
76f971622SJuan Castillo #include <getopt.h>
86f971622SJuan Castillo #include <stdio.h>
96f971622SJuan Castillo #include <stdlib.h>
106f971622SJuan Castillo #include <string.h>
116f971622SJuan Castillo 
126f971622SJuan Castillo #include <openssl/conf.h>
136f971622SJuan Castillo #include <openssl/evp.h>
146f971622SJuan Castillo #include <openssl/pem.h>
156f971622SJuan Castillo 
166f971622SJuan Castillo #include "cert.h"
17ad2c1a9aSJuan Castillo #include "cmd_opt.h"
186f971622SJuan Castillo #include "debug.h"
196f971622SJuan Castillo #include "key.h"
206f971622SJuan Castillo #include "sha.h"
216f971622SJuan Castillo 
226f971622SJuan Castillo #define MAX_FILENAME_LEN		1024
236f971622SJuan Castillo 
24b94bf967SPankaj Gupta key_t *keys;
25b94bf967SPankaj Gupta unsigned int num_keys;
26b94bf967SPankaj Gupta 
27cf2dd17dSJuan Pablo Conde #if !USING_OPENSSL3
286f971622SJuan Castillo /*
29ccbf890eSJuan Castillo  * Create a new key container
306f971622SJuan Castillo  */
31762f1ebeSMasahiro Yamada int key_new(key_t *key)
32ccbf890eSJuan Castillo {
33ccbf890eSJuan Castillo 	/* Create key pair container */
34ccbf890eSJuan Castillo 	key->key = EVP_PKEY_new();
35ccbf890eSJuan Castillo 	if (key->key == NULL) {
36ccbf890eSJuan Castillo 		return 0;
37ccbf890eSJuan Castillo 	}
38ccbf890eSJuan Castillo 
39ccbf890eSJuan Castillo 	return 1;
40ccbf890eSJuan Castillo }
41cf2dd17dSJuan Pablo Conde #endif
42ccbf890eSJuan Castillo 
43dfe0f4c2SJustin Chadwell static int key_create_rsa(key_t *key, int key_bits)
446f971622SJuan Castillo {
45cf2dd17dSJuan Pablo Conde #if USING_OPENSSL3
469bc52d33SJuan Pablo Conde 	EVP_PKEY *rsa = EVP_RSA_gen(key_bits);
47ccbf890eSJuan Castillo 	if (rsa == NULL) {
48742c4e14SMichalis Pappas 		printf("Cannot generate RSA key\n");
49ed2a76eaSJuan Castillo 		return 0;
50ed2a76eaSJuan Castillo 	}
519bc52d33SJuan Pablo Conde 	key->key = rsa;
529bc52d33SJuan Pablo Conde 	return 1;
53cf2dd17dSJuan Pablo Conde #else
54cf2dd17dSJuan Pablo Conde 	BIGNUM *e;
55cf2dd17dSJuan Pablo Conde 	RSA *rsa = NULL;
56cf2dd17dSJuan Pablo Conde 
57cf2dd17dSJuan Pablo Conde 	e = BN_new();
58cf2dd17dSJuan Pablo Conde 	if (e == NULL) {
59cf2dd17dSJuan Pablo Conde 		printf("Cannot create RSA exponent\n");
60cf2dd17dSJuan Pablo Conde 		return 0;
61cf2dd17dSJuan Pablo Conde 	}
62cf2dd17dSJuan Pablo Conde 
63cf2dd17dSJuan Pablo Conde 	if (!BN_set_word(e, RSA_F4)) {
64cf2dd17dSJuan Pablo Conde 		printf("Cannot assign RSA exponent\n");
65cf2dd17dSJuan Pablo Conde 		goto err2;
66cf2dd17dSJuan Pablo Conde 	}
67cf2dd17dSJuan Pablo Conde 
68cf2dd17dSJuan Pablo Conde 	rsa = RSA_new();
69cf2dd17dSJuan Pablo Conde 	if (rsa == NULL) {
70cf2dd17dSJuan Pablo Conde 		printf("Cannot create RSA key\n");
71cf2dd17dSJuan Pablo Conde 		goto err2;
72cf2dd17dSJuan Pablo Conde 	}
73cf2dd17dSJuan Pablo Conde 
74cf2dd17dSJuan Pablo Conde 	if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) {
75cf2dd17dSJuan Pablo Conde 		printf("Cannot generate RSA key\n");
76cf2dd17dSJuan Pablo Conde 		goto err;
77cf2dd17dSJuan Pablo Conde 	}
78cf2dd17dSJuan Pablo Conde 
79cf2dd17dSJuan Pablo Conde 	if (!EVP_PKEY_assign_RSA(key->key, rsa)) {
80cf2dd17dSJuan Pablo Conde 		printf("Cannot assign RSA key\n");
81cf2dd17dSJuan Pablo Conde 		goto err;
82cf2dd17dSJuan Pablo Conde 	}
83cf2dd17dSJuan Pablo Conde 
84cf2dd17dSJuan Pablo Conde 	BN_free(e);
85cf2dd17dSJuan Pablo Conde 	return 1;
86cf2dd17dSJuan Pablo Conde 
87cf2dd17dSJuan Pablo Conde err:
88cf2dd17dSJuan Pablo Conde 	RSA_free(rsa);
89cf2dd17dSJuan Pablo Conde err2:
90cf2dd17dSJuan Pablo Conde 	BN_free(e);
91cf2dd17dSJuan Pablo Conde 	return 0;
92cf2dd17dSJuan Pablo Conde #endif
939bc52d33SJuan Pablo Conde }
94ed2a76eaSJuan Castillo 
95ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
96cf2dd17dSJuan Pablo Conde #if USING_OPENSSL3
97e78ba69eSLionel Debieve static int key_create_ecdsa(key_t *key, int key_bits, const char *curve)
98e78ba69eSLionel Debieve {
99e78ba69eSLionel Debieve 	EVP_PKEY *ec = EVP_EC_gen(curve);
100ccbf890eSJuan Castillo 	if (ec == NULL) {
101ccbf890eSJuan Castillo 		printf("Cannot generate EC key\n");
102ed2a76eaSJuan Castillo 		return 0;
103ed2a76eaSJuan Castillo 	}
104e78ba69eSLionel Debieve 
1059bc52d33SJuan Pablo Conde 	key->key = ec;
1069bc52d33SJuan Pablo Conde 	return 1;
107e78ba69eSLionel Debieve }
108e78ba69eSLionel Debieve 
109e78ba69eSLionel Debieve static int key_create_ecdsa_nist(key_t *key, int key_bits)
110e78ba69eSLionel Debieve {
111e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, "prime256v1");
112e78ba69eSLionel Debieve }
113e78ba69eSLionel Debieve 
114e78ba69eSLionel Debieve static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
115e78ba69eSLionel Debieve {
116e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, "brainpoolP256r1");
117e78ba69eSLionel Debieve }
118e78ba69eSLionel Debieve 
119e78ba69eSLionel Debieve static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
120e78ba69eSLionel Debieve {
121e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, "brainpoolP256t1");
122e78ba69eSLionel Debieve }
123cf2dd17dSJuan Pablo Conde #else
124e78ba69eSLionel Debieve static int key_create_ecdsa(key_t *key, int key_bits, const int curve_id)
125e78ba69eSLionel Debieve {
126cf2dd17dSJuan Pablo Conde 	EC_KEY *ec;
127cf2dd17dSJuan Pablo Conde 
128e78ba69eSLionel Debieve 	ec = EC_KEY_new_by_curve_name(curve_id);
129cf2dd17dSJuan Pablo Conde 	if (ec == NULL) {
130cf2dd17dSJuan Pablo Conde 		printf("Cannot create EC key\n");
131cf2dd17dSJuan Pablo Conde 		return 0;
132cf2dd17dSJuan Pablo Conde 	}
133cf2dd17dSJuan Pablo Conde 	if (!EC_KEY_generate_key(ec)) {
134cf2dd17dSJuan Pablo Conde 		printf("Cannot generate EC key\n");
135cf2dd17dSJuan Pablo Conde 		goto err;
136cf2dd17dSJuan Pablo Conde 	}
137cf2dd17dSJuan Pablo Conde 	EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS);
138cf2dd17dSJuan Pablo Conde 	EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
139cf2dd17dSJuan Pablo Conde 	if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) {
140cf2dd17dSJuan Pablo Conde 		printf("Cannot assign EC key\n");
141cf2dd17dSJuan Pablo Conde 		goto err;
142cf2dd17dSJuan Pablo Conde 	}
143cf2dd17dSJuan Pablo Conde 
144cf2dd17dSJuan Pablo Conde 	return 1;
145cf2dd17dSJuan Pablo Conde 
146cf2dd17dSJuan Pablo Conde err:
147cf2dd17dSJuan Pablo Conde 	EC_KEY_free(ec);
148cf2dd17dSJuan Pablo Conde 	return 0;
1499bc52d33SJuan Pablo Conde }
150e78ba69eSLionel Debieve 
151e78ba69eSLionel Debieve static int key_create_ecdsa_nist(key_t *key, int key_bits)
152e78ba69eSLionel Debieve {
153e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, NID_X9_62_prime256v1);
154e78ba69eSLionel Debieve }
155e78ba69eSLionel Debieve 
156e78ba69eSLionel Debieve static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
157e78ba69eSLionel Debieve {
158e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, NID_brainpoolP256r1);
159e78ba69eSLionel Debieve }
160e78ba69eSLionel Debieve 
161e78ba69eSLionel Debieve static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
162e78ba69eSLionel Debieve {
163e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, NID_brainpoolP256t1);
164e78ba69eSLionel Debieve }
165e78ba69eSLionel Debieve #endif /* USING_OPENSSL3 */
166ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
167ed2a76eaSJuan Castillo 
168dfe0f4c2SJustin Chadwell typedef int (*key_create_fn_t)(key_t *key, int key_bits);
169ed2a76eaSJuan Castillo static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = {
170e78ba69eSLionel Debieve 	[KEY_ALG_RSA] = key_create_rsa,
171ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
172e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_NIST] = key_create_ecdsa_nist,
173e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_R] = key_create_ecdsa_brainpool_r,
174e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_T] = key_create_ecdsa_brainpool_t,
175ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
176ed2a76eaSJuan Castillo };
177ed2a76eaSJuan Castillo 
178dfe0f4c2SJustin Chadwell int key_create(key_t *key, int type, int key_bits)
179ed2a76eaSJuan Castillo {
180ed2a76eaSJuan Castillo 	if (type >= KEY_ALG_MAX_NUM) {
181ed2a76eaSJuan Castillo 		printf("Invalid key type\n");
182ed2a76eaSJuan Castillo 		return 0;
183ed2a76eaSJuan Castillo 	}
184ed2a76eaSJuan Castillo 
185ed2a76eaSJuan Castillo 	if (key_create_fn[type]) {
186dfe0f4c2SJustin Chadwell 		return key_create_fn[type](key, key_bits);
187ed2a76eaSJuan Castillo 	}
188ccbf890eSJuan Castillo 
1896f971622SJuan Castillo 	return 0;
1906f971622SJuan Castillo }
1916f971622SJuan Castillo 
192ccbf890eSJuan Castillo int key_load(key_t *key, unsigned int *err_code)
1936f971622SJuan Castillo {
194c893c733SMasahiro Yamada 	FILE *fp;
1956f971622SJuan Castillo 
1966f971622SJuan Castillo 	if (key->fn) {
1976f971622SJuan Castillo 		/* Load key from file */
1986f971622SJuan Castillo 		fp = fopen(key->fn, "r");
1996f971622SJuan Castillo 		if (fp) {
200*ea6f8452SRobin van der Gracht 			key->key = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
2016f971622SJuan Castillo 			fclose(fp);
202*ea6f8452SRobin van der Gracht 			if (key->key) {
203ccbf890eSJuan Castillo 				*err_code = KEY_ERR_NONE;
2046f971622SJuan Castillo 				return 1;
2056f971622SJuan Castillo 			} else {
206ccbf890eSJuan Castillo 				ERROR("Cannot load key from %s\n", key->fn);
207ccbf890eSJuan Castillo 				*err_code = KEY_ERR_LOAD;
2086f971622SJuan Castillo 			}
2096f971622SJuan Castillo 		} else {
210ccbf890eSJuan Castillo 			WARN("Cannot open file %s\n", key->fn);
211ccbf890eSJuan Castillo 			*err_code = KEY_ERR_OPEN;
2126f971622SJuan Castillo 		}
2136f971622SJuan Castillo 	} else {
21476a85cfaSlaurenw-arm 		VERBOSE("Key filename not specified\n");
215ccbf890eSJuan Castillo 		*err_code = KEY_ERR_FILENAME;
2166f971622SJuan Castillo 	}
2176f971622SJuan Castillo 
2186f971622SJuan Castillo 	return 0;
2196f971622SJuan Castillo }
2206f971622SJuan Castillo 
2216f971622SJuan Castillo int key_store(key_t *key)
2226f971622SJuan Castillo {
223c893c733SMasahiro Yamada 	FILE *fp;
2246f971622SJuan Castillo 
2256f971622SJuan Castillo 	if (key->fn) {
2266f971622SJuan Castillo 		fp = fopen(key->fn, "w");
2276f971622SJuan Castillo 		if (fp) {
2286f971622SJuan Castillo 			PEM_write_PrivateKey(fp, key->key,
2296f971622SJuan Castillo 					NULL, NULL, 0, NULL, NULL);
2306f971622SJuan Castillo 			fclose(fp);
2316f971622SJuan Castillo 			return 1;
2326f971622SJuan Castillo 		} else {
2336f971622SJuan Castillo 			ERROR("Cannot create file %s\n", key->fn);
2346f971622SJuan Castillo 		}
2356f971622SJuan Castillo 	} else {
2366f971622SJuan Castillo 		ERROR("Key filename not specified\n");
2376f971622SJuan Castillo 	}
2386f971622SJuan Castillo 
2396f971622SJuan Castillo 	return 0;
2406f971622SJuan Castillo }
241ad2c1a9aSJuan Castillo 
242ad2c1a9aSJuan Castillo int key_init(void)
243ad2c1a9aSJuan Castillo {
244159807e2SJuan Castillo 	cmd_opt_t cmd_opt;
245ad2c1a9aSJuan Castillo 	key_t *key;
246ad2c1a9aSJuan Castillo 	unsigned int i;
247ad2c1a9aSJuan Castillo 
248b94bf967SPankaj Gupta 	keys = malloc((num_def_keys * sizeof(def_keys[0]))
249b94bf967SPankaj Gupta #ifdef PDEF_KEYS
250b94bf967SPankaj Gupta 		      + (num_pdef_keys * sizeof(pdef_keys[0]))
251b94bf967SPankaj Gupta #endif
252b94bf967SPankaj Gupta 		      );
253b94bf967SPankaj Gupta 
254b94bf967SPankaj Gupta 	if (keys == NULL) {
255b94bf967SPankaj Gupta 		ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__);
256b94bf967SPankaj Gupta 		return 1;
257b94bf967SPankaj Gupta 	}
258b94bf967SPankaj Gupta 
259b94bf967SPankaj Gupta 	memcpy(&keys[0], &def_keys[0], (num_def_keys * sizeof(def_keys[0])));
260b94bf967SPankaj Gupta #ifdef PDEF_KEYS
261b94bf967SPankaj Gupta 	memcpy(&keys[num_def_keys], &pdef_keys[0],
262b94bf967SPankaj Gupta 		(num_pdef_keys * sizeof(pdef_keys[0])));
263b94bf967SPankaj Gupta 
264b94bf967SPankaj Gupta 	num_keys = num_def_keys + num_pdef_keys;
265b94bf967SPankaj Gupta #else
266b94bf967SPankaj Gupta 	num_keys = num_def_keys;
267b94bf967SPankaj Gupta #endif
268b94bf967SPankaj Gupta 		   ;
269b94bf967SPankaj Gupta 
270ad2c1a9aSJuan Castillo 	for (i = 0; i < num_keys; i++) {
271ad2c1a9aSJuan Castillo 		key = &keys[i];
272ad2c1a9aSJuan Castillo 		if (key->opt != NULL) {
273159807e2SJuan Castillo 			cmd_opt.long_opt.name = key->opt;
274159807e2SJuan Castillo 			cmd_opt.long_opt.has_arg = required_argument;
275159807e2SJuan Castillo 			cmd_opt.long_opt.flag = NULL;
276159807e2SJuan Castillo 			cmd_opt.long_opt.val = CMD_OPT_KEY;
277159807e2SJuan Castillo 			cmd_opt.help_msg = key->help_msg;
278159807e2SJuan Castillo 			cmd_opt_add(&cmd_opt);
279ad2c1a9aSJuan Castillo 		}
280ad2c1a9aSJuan Castillo 	}
281ad2c1a9aSJuan Castillo 
282c893c733SMasahiro Yamada 	return 0;
283ad2c1a9aSJuan Castillo }
284ad2c1a9aSJuan Castillo 
285ad2c1a9aSJuan Castillo key_t *key_get_by_opt(const char *opt)
286ad2c1a9aSJuan Castillo {
287c893c733SMasahiro Yamada 	key_t *key;
288ad2c1a9aSJuan Castillo 	unsigned int i;
289ad2c1a9aSJuan Castillo 
290ad2c1a9aSJuan Castillo 	/* Sequential search. This is not a performance concern since the number
291ad2c1a9aSJuan Castillo 	 * of keys is bounded and the code runs on a host machine */
292ad2c1a9aSJuan Castillo 	for (i = 0; i < num_keys; i++) {
293ad2c1a9aSJuan Castillo 		key = &keys[i];
294ad2c1a9aSJuan Castillo 		if (0 == strcmp(key->opt, opt)) {
295ad2c1a9aSJuan Castillo 			return key;
296ad2c1a9aSJuan Castillo 		}
297ad2c1a9aSJuan Castillo 	}
298ad2c1a9aSJuan Castillo 
299ad2c1a9aSJuan Castillo 	return NULL;
300ad2c1a9aSJuan Castillo }
301cf2dd17dSJuan Pablo Conde 
302cf2dd17dSJuan Pablo Conde void key_cleanup(void)
303cf2dd17dSJuan Pablo Conde {
304cf2dd17dSJuan Pablo Conde 	unsigned int i;
305cf2dd17dSJuan Pablo Conde 
306cf2dd17dSJuan Pablo Conde 	for (i = 0; i < num_keys; i++) {
307cf2dd17dSJuan Pablo Conde 		EVP_PKEY_free(keys[i].key);
308cf2dd17dSJuan Pablo Conde 		if (keys[i].fn != NULL) {
309cf2dd17dSJuan Pablo Conde 			void *ptr = keys[i].fn;
310cf2dd17dSJuan Pablo Conde 
311cf2dd17dSJuan Pablo Conde 			free(ptr);
312cf2dd17dSJuan Pablo Conde 			keys[i].fn = NULL;
313cf2dd17dSJuan Pablo Conde 		}
314cf2dd17dSJuan Pablo Conde 	}
315cf2dd17dSJuan Pablo Conde 	free(keys);
316cf2dd17dSJuan Pablo Conde }
317cf2dd17dSJuan Pablo Conde 
318