xref: /rk3399_ARM-atf/tools/cert_create/src/key.c (revision bb3b0c0b09ff1d969ddd49b99642740ce2a07064)
16f971622SJuan Castillo /*
2c512c89cSlaurenw-arm  * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
36f971622SJuan Castillo  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
56f971622SJuan Castillo  */
66f971622SJuan Castillo 
7c512c89cSlaurenw-arm #include <assert.h>
86f971622SJuan Castillo #include <getopt.h>
96f971622SJuan Castillo #include <stdio.h>
106f971622SJuan Castillo #include <stdlib.h>
116f971622SJuan Castillo #include <string.h>
126f971622SJuan Castillo 
13616b3ce2SRobin van der Gracht /* Suppress OpenSSL engine deprecation warnings */
14616b3ce2SRobin van der Gracht #define OPENSSL_SUPPRESS_DEPRECATED
15616b3ce2SRobin van der Gracht 
166f971622SJuan Castillo #include <openssl/conf.h>
17616b3ce2SRobin van der Gracht #include <openssl/engine.h>
186f971622SJuan Castillo #include <openssl/evp.h>
196f971622SJuan Castillo #include <openssl/pem.h>
206f971622SJuan Castillo 
216f971622SJuan Castillo #include "cert.h"
22ad2c1a9aSJuan Castillo #include "cmd_opt.h"
236f971622SJuan Castillo #include "debug.h"
246f971622SJuan Castillo #include "key.h"
256f971622SJuan Castillo #include "sha.h"
266f971622SJuan Castillo 
276f971622SJuan Castillo #define MAX_FILENAME_LEN		1024
286f971622SJuan Castillo 
29b94bf967SPankaj Gupta key_t *keys;
30b94bf967SPankaj Gupta unsigned int num_keys;
31b94bf967SPankaj Gupta 
32cf2dd17dSJuan Pablo Conde #if !USING_OPENSSL3
336f971622SJuan Castillo /*
34ccbf890eSJuan Castillo  * Create a new key container
356f971622SJuan Castillo  */
36762f1ebeSMasahiro Yamada int key_new(key_t *key)
37ccbf890eSJuan Castillo {
38ccbf890eSJuan Castillo 	/* Create key pair container */
39ccbf890eSJuan Castillo 	key->key = EVP_PKEY_new();
40ccbf890eSJuan Castillo 	if (key->key == NULL) {
41ccbf890eSJuan Castillo 		return 0;
42ccbf890eSJuan Castillo 	}
43ccbf890eSJuan Castillo 
44ccbf890eSJuan Castillo 	return 1;
45ccbf890eSJuan Castillo }
46cf2dd17dSJuan Pablo Conde #endif
47ccbf890eSJuan Castillo 
48dfe0f4c2SJustin Chadwell static int key_create_rsa(key_t *key, int key_bits)
496f971622SJuan Castillo {
50cf2dd17dSJuan Pablo Conde #if USING_OPENSSL3
519bc52d33SJuan Pablo Conde 	EVP_PKEY *rsa = EVP_RSA_gen(key_bits);
52ccbf890eSJuan Castillo 	if (rsa == NULL) {
53742c4e14SMichalis Pappas 		printf("Cannot generate RSA key\n");
54ed2a76eaSJuan Castillo 		return 0;
55ed2a76eaSJuan Castillo 	}
569bc52d33SJuan Pablo Conde 	key->key = rsa;
579bc52d33SJuan Pablo Conde 	return 1;
58cf2dd17dSJuan Pablo Conde #else
59cf2dd17dSJuan Pablo Conde 	BIGNUM *e;
60cf2dd17dSJuan Pablo Conde 	RSA *rsa = NULL;
61cf2dd17dSJuan Pablo Conde 
62cf2dd17dSJuan Pablo Conde 	e = BN_new();
63cf2dd17dSJuan Pablo Conde 	if (e == NULL) {
64cf2dd17dSJuan Pablo Conde 		printf("Cannot create RSA exponent\n");
65cf2dd17dSJuan Pablo Conde 		return 0;
66cf2dd17dSJuan Pablo Conde 	}
67cf2dd17dSJuan Pablo Conde 
68cf2dd17dSJuan Pablo Conde 	if (!BN_set_word(e, RSA_F4)) {
69cf2dd17dSJuan Pablo Conde 		printf("Cannot assign RSA exponent\n");
70cf2dd17dSJuan Pablo Conde 		goto err2;
71cf2dd17dSJuan Pablo Conde 	}
72cf2dd17dSJuan Pablo Conde 
73cf2dd17dSJuan Pablo Conde 	rsa = RSA_new();
74cf2dd17dSJuan Pablo Conde 	if (rsa == NULL) {
75cf2dd17dSJuan Pablo Conde 		printf("Cannot create RSA key\n");
76cf2dd17dSJuan Pablo Conde 		goto err2;
77cf2dd17dSJuan Pablo Conde 	}
78cf2dd17dSJuan Pablo Conde 
79cf2dd17dSJuan Pablo Conde 	if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) {
80cf2dd17dSJuan Pablo Conde 		printf("Cannot generate RSA key\n");
81cf2dd17dSJuan Pablo Conde 		goto err;
82cf2dd17dSJuan Pablo Conde 	}
83cf2dd17dSJuan Pablo Conde 
84cf2dd17dSJuan Pablo Conde 	if (!EVP_PKEY_assign_RSA(key->key, rsa)) {
85cf2dd17dSJuan Pablo Conde 		printf("Cannot assign RSA key\n");
86cf2dd17dSJuan Pablo Conde 		goto err;
87cf2dd17dSJuan Pablo Conde 	}
88cf2dd17dSJuan Pablo Conde 
89cf2dd17dSJuan Pablo Conde 	BN_free(e);
90cf2dd17dSJuan Pablo Conde 	return 1;
91cf2dd17dSJuan Pablo Conde 
92cf2dd17dSJuan Pablo Conde err:
93cf2dd17dSJuan Pablo Conde 	RSA_free(rsa);
94cf2dd17dSJuan Pablo Conde err2:
95cf2dd17dSJuan Pablo Conde 	BN_free(e);
96cf2dd17dSJuan Pablo Conde 	return 0;
97cf2dd17dSJuan Pablo Conde #endif
989bc52d33SJuan Pablo Conde }
99ed2a76eaSJuan Castillo 
100ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
101cf2dd17dSJuan Pablo Conde #if USING_OPENSSL3
102e78ba69eSLionel Debieve static int key_create_ecdsa(key_t *key, int key_bits, const char *curve)
103e78ba69eSLionel Debieve {
104e78ba69eSLionel Debieve 	EVP_PKEY *ec = EVP_EC_gen(curve);
105ccbf890eSJuan Castillo 	if (ec == NULL) {
106ccbf890eSJuan Castillo 		printf("Cannot generate EC key\n");
107ed2a76eaSJuan Castillo 		return 0;
108ed2a76eaSJuan Castillo 	}
109e78ba69eSLionel Debieve 
1109bc52d33SJuan Pablo Conde 	key->key = ec;
1119bc52d33SJuan Pablo Conde 	return 1;
112e78ba69eSLionel Debieve }
113e78ba69eSLionel Debieve 
114e78ba69eSLionel Debieve static int key_create_ecdsa_nist(key_t *key, int key_bits)
115e78ba69eSLionel Debieve {
116c512c89cSlaurenw-arm 	if (key_bits == 384) {
117c512c89cSlaurenw-arm 		return key_create_ecdsa(key, key_bits, "secp384r1");
118c512c89cSlaurenw-arm 	} else {
119c512c89cSlaurenw-arm 		assert(key_bits == 256);
120e78ba69eSLionel Debieve 		return key_create_ecdsa(key, key_bits, "prime256v1");
121e78ba69eSLionel Debieve 	}
122c512c89cSlaurenw-arm }
123e78ba69eSLionel Debieve 
124e78ba69eSLionel Debieve static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
125e78ba69eSLionel Debieve {
126e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, "brainpoolP256r1");
127e78ba69eSLionel Debieve }
128e78ba69eSLionel Debieve 
129e78ba69eSLionel Debieve static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
130e78ba69eSLionel Debieve {
131e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, "brainpoolP256t1");
132e78ba69eSLionel Debieve }
133cf2dd17dSJuan Pablo Conde #else
134e78ba69eSLionel Debieve static int key_create_ecdsa(key_t *key, int key_bits, const int curve_id)
135e78ba69eSLionel Debieve {
136cf2dd17dSJuan Pablo Conde 	EC_KEY *ec;
137cf2dd17dSJuan Pablo Conde 
138e78ba69eSLionel Debieve 	ec = EC_KEY_new_by_curve_name(curve_id);
139cf2dd17dSJuan Pablo Conde 	if (ec == NULL) {
140cf2dd17dSJuan Pablo Conde 		printf("Cannot create EC key\n");
141cf2dd17dSJuan Pablo Conde 		return 0;
142cf2dd17dSJuan Pablo Conde 	}
143cf2dd17dSJuan Pablo Conde 	if (!EC_KEY_generate_key(ec)) {
144cf2dd17dSJuan Pablo Conde 		printf("Cannot generate EC key\n");
145cf2dd17dSJuan Pablo Conde 		goto err;
146cf2dd17dSJuan Pablo Conde 	}
147cf2dd17dSJuan Pablo Conde 	EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS);
148cf2dd17dSJuan Pablo Conde 	EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
149cf2dd17dSJuan Pablo Conde 	if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) {
150cf2dd17dSJuan Pablo Conde 		printf("Cannot assign EC key\n");
151cf2dd17dSJuan Pablo Conde 		goto err;
152cf2dd17dSJuan Pablo Conde 	}
153cf2dd17dSJuan Pablo Conde 
154cf2dd17dSJuan Pablo Conde 	return 1;
155cf2dd17dSJuan Pablo Conde 
156cf2dd17dSJuan Pablo Conde err:
157cf2dd17dSJuan Pablo Conde 	EC_KEY_free(ec);
158cf2dd17dSJuan Pablo Conde 	return 0;
1599bc52d33SJuan Pablo Conde }
160e78ba69eSLionel Debieve 
161e78ba69eSLionel Debieve static int key_create_ecdsa_nist(key_t *key, int key_bits)
162e78ba69eSLionel Debieve {
163c512c89cSlaurenw-arm 	if (key_bits == 384) {
164c512c89cSlaurenw-arm 		return key_create_ecdsa(key, key_bits, NID_secp384r1);
165c512c89cSlaurenw-arm 	} else {
166c512c89cSlaurenw-arm 		assert(key_bits == 256);
167e78ba69eSLionel Debieve 		return key_create_ecdsa(key, key_bits, NID_X9_62_prime256v1);
168e78ba69eSLionel Debieve 	}
169c512c89cSlaurenw-arm }
170e78ba69eSLionel Debieve 
171e78ba69eSLionel Debieve static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
172e78ba69eSLionel Debieve {
173e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, NID_brainpoolP256r1);
174e78ba69eSLionel Debieve }
175e78ba69eSLionel Debieve 
176e78ba69eSLionel Debieve static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
177e78ba69eSLionel Debieve {
178e78ba69eSLionel Debieve 	return key_create_ecdsa(key, key_bits, NID_brainpoolP256t1);
179e78ba69eSLionel Debieve }
180e78ba69eSLionel Debieve #endif /* USING_OPENSSL3 */
181ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
182ed2a76eaSJuan Castillo 
183dfe0f4c2SJustin Chadwell typedef int (*key_create_fn_t)(key_t *key, int key_bits);
184ed2a76eaSJuan Castillo static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = {
185e78ba69eSLionel Debieve 	[KEY_ALG_RSA] = key_create_rsa,
186ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC
187e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_NIST] = key_create_ecdsa_nist,
188e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_R] = key_create_ecdsa_brainpool_r,
189e78ba69eSLionel Debieve 	[KEY_ALG_ECDSA_BRAINPOOL_T] = key_create_ecdsa_brainpool_t,
190ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */
191ed2a76eaSJuan Castillo };
192ed2a76eaSJuan Castillo 
193dfe0f4c2SJustin Chadwell int key_create(key_t *key, int type, int key_bits)
194ed2a76eaSJuan Castillo {
195ed2a76eaSJuan Castillo 	if (type >= KEY_ALG_MAX_NUM) {
196ed2a76eaSJuan Castillo 		printf("Invalid key type\n");
197ed2a76eaSJuan Castillo 		return 0;
198ed2a76eaSJuan Castillo 	}
199ed2a76eaSJuan Castillo 
200ed2a76eaSJuan Castillo 	if (key_create_fn[type]) {
201dfe0f4c2SJustin Chadwell 		return key_create_fn[type](key, key_bits);
202ed2a76eaSJuan Castillo 	}
203ccbf890eSJuan Castillo 
2046f971622SJuan Castillo 	return 0;
2056f971622SJuan Castillo }
2066f971622SJuan Castillo 
207616b3ce2SRobin van der Gracht static EVP_PKEY *key_load_pkcs11(const char *uri)
208616b3ce2SRobin van der Gracht {
209616b3ce2SRobin van der Gracht 	char *key_pass;
210616b3ce2SRobin van der Gracht 	EVP_PKEY *pkey;
211616b3ce2SRobin van der Gracht 	ENGINE *e;
212616b3ce2SRobin van der Gracht 
213616b3ce2SRobin van der Gracht 	ENGINE_load_builtin_engines();
214616b3ce2SRobin van der Gracht 	e = ENGINE_by_id("pkcs11");
215616b3ce2SRobin van der Gracht 	if (!e) {
216616b3ce2SRobin van der Gracht 		fprintf(stderr, "Cannot Load PKCS#11 ENGINE\n");
217616b3ce2SRobin van der Gracht 		return NULL;
218616b3ce2SRobin van der Gracht 	}
219616b3ce2SRobin van der Gracht 
220616b3ce2SRobin van der Gracht 	if (!ENGINE_init(e)) {
221616b3ce2SRobin van der Gracht 		fprintf(stderr, "Cannot ENGINE_init\n");
222616b3ce2SRobin van der Gracht 		goto err;
223616b3ce2SRobin van der Gracht 	}
224616b3ce2SRobin van der Gracht 
225616b3ce2SRobin van der Gracht 	key_pass = getenv("PKCS11_PIN");
226616b3ce2SRobin van der Gracht 	if (key_pass) {
227616b3ce2SRobin van der Gracht 		if (!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0)) {
228616b3ce2SRobin van der Gracht 			fprintf(stderr, "Cannot Set PKCS#11 PIN\n");
229616b3ce2SRobin van der Gracht 			goto err;
230616b3ce2SRobin van der Gracht 		}
231616b3ce2SRobin van der Gracht 	}
232616b3ce2SRobin van der Gracht 
233616b3ce2SRobin van der Gracht 	pkey = ENGINE_load_private_key(e, uri, NULL, NULL);
234616b3ce2SRobin van der Gracht 	if (pkey)
235616b3ce2SRobin van der Gracht 		return pkey;
236616b3ce2SRobin van der Gracht err:
237616b3ce2SRobin van der Gracht 	ENGINE_free(e);
238616b3ce2SRobin van der Gracht 	return NULL;
239616b3ce2SRobin van der Gracht 
240616b3ce2SRobin van der Gracht }
241616b3ce2SRobin van der Gracht 
242*bb3b0c0bSSandrine Bailleux unsigned int key_load(key_t *key)
2436f971622SJuan Castillo {
244*bb3b0c0bSSandrine Bailleux 	if (key->fn == NULL) {
245*bb3b0c0bSSandrine Bailleux 		VERBOSE("Key not specified\n");
246*bb3b0c0bSSandrine Bailleux 		return KEY_ERR_FILENAME;
247*bb3b0c0bSSandrine Bailleux 	}
2486f971622SJuan Castillo 
249*bb3b0c0bSSandrine Bailleux 	if (strncmp(key->fn, "pkcs11:", 7) == 0) {
250616b3ce2SRobin van der Gracht 		/* Load key through pkcs11 */
251616b3ce2SRobin van der Gracht 		key->key = key_load_pkcs11(key->fn);
252616b3ce2SRobin van der Gracht 	} else {
2536f971622SJuan Castillo 		/* Load key from file */
254*bb3b0c0bSSandrine Bailleux 		FILE *fp = fopen(key->fn, "r");
255*bb3b0c0bSSandrine Bailleux 		if (fp == NULL) {
256616b3ce2SRobin van der Gracht 			WARN("Cannot open file %s\n", key->fn);
257*bb3b0c0bSSandrine Bailleux 			return KEY_ERR_OPEN;
2586f971622SJuan Castillo 		}
2596f971622SJuan Castillo 
260*bb3b0c0bSSandrine Bailleux 		key->key = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
261*bb3b0c0bSSandrine Bailleux 		fclose(fp);
262*bb3b0c0bSSandrine Bailleux 	}
263*bb3b0c0bSSandrine Bailleux 
264*bb3b0c0bSSandrine Bailleux 	if (key->key == NULL) {
265*bb3b0c0bSSandrine Bailleux 		ERROR("Cannot load key from %s\n", key->fn);
266*bb3b0c0bSSandrine Bailleux 		return KEY_ERR_LOAD;
267*bb3b0c0bSSandrine Bailleux 	}
268*bb3b0c0bSSandrine Bailleux 
269*bb3b0c0bSSandrine Bailleux 	return KEY_ERR_NONE;
2706f971622SJuan Castillo }
2716f971622SJuan Castillo 
2726f971622SJuan Castillo int key_store(key_t *key)
2736f971622SJuan Castillo {
274c893c733SMasahiro Yamada 	FILE *fp;
2756f971622SJuan Castillo 
2766f971622SJuan Castillo 	if (key->fn) {
277616b3ce2SRobin van der Gracht 		if (!strncmp(key->fn, "pkcs11:", 7)) {
278616b3ce2SRobin van der Gracht 			ERROR("PKCS11 URI provided instead of a file");
279616b3ce2SRobin van der Gracht 			return 0;
280616b3ce2SRobin van der Gracht 		}
2816f971622SJuan Castillo 		fp = fopen(key->fn, "w");
2826f971622SJuan Castillo 		if (fp) {
2836f971622SJuan Castillo 			PEM_write_PrivateKey(fp, key->key,
2846f971622SJuan Castillo 					NULL, NULL, 0, NULL, NULL);
2856f971622SJuan Castillo 			fclose(fp);
2866f971622SJuan Castillo 			return 1;
2876f971622SJuan Castillo 		} else {
2886f971622SJuan Castillo 			ERROR("Cannot create file %s\n", key->fn);
2896f971622SJuan Castillo 		}
2906f971622SJuan Castillo 	} else {
2916f971622SJuan Castillo 		ERROR("Key filename not specified\n");
2926f971622SJuan Castillo 	}
2936f971622SJuan Castillo 
2946f971622SJuan Castillo 	return 0;
2956f971622SJuan Castillo }
296ad2c1a9aSJuan Castillo 
297ad2c1a9aSJuan Castillo int key_init(void)
298ad2c1a9aSJuan Castillo {
299159807e2SJuan Castillo 	cmd_opt_t cmd_opt;
300ad2c1a9aSJuan Castillo 	key_t *key;
301ad2c1a9aSJuan Castillo 	unsigned int i;
302ad2c1a9aSJuan Castillo 
303b94bf967SPankaj Gupta 	keys = malloc((num_def_keys * sizeof(def_keys[0]))
304b94bf967SPankaj Gupta #ifdef PDEF_KEYS
305b94bf967SPankaj Gupta 		      + (num_pdef_keys * sizeof(pdef_keys[0]))
306b94bf967SPankaj Gupta #endif
307b94bf967SPankaj Gupta 		      );
308b94bf967SPankaj Gupta 
309b94bf967SPankaj Gupta 	if (keys == NULL) {
310b94bf967SPankaj Gupta 		ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__);
311b94bf967SPankaj Gupta 		return 1;
312b94bf967SPankaj Gupta 	}
313b94bf967SPankaj Gupta 
314b94bf967SPankaj Gupta 	memcpy(&keys[0], &def_keys[0], (num_def_keys * sizeof(def_keys[0])));
315b94bf967SPankaj Gupta #ifdef PDEF_KEYS
316b94bf967SPankaj Gupta 	memcpy(&keys[num_def_keys], &pdef_keys[0],
317b94bf967SPankaj Gupta 		(num_pdef_keys * sizeof(pdef_keys[0])));
318b94bf967SPankaj Gupta 
319b94bf967SPankaj Gupta 	num_keys = num_def_keys + num_pdef_keys;
320b94bf967SPankaj Gupta #else
321b94bf967SPankaj Gupta 	num_keys = num_def_keys;
322b94bf967SPankaj Gupta #endif
323b94bf967SPankaj Gupta 		   ;
324b94bf967SPankaj Gupta 
325ad2c1a9aSJuan Castillo 	for (i = 0; i < num_keys; i++) {
326ad2c1a9aSJuan Castillo 		key = &keys[i];
327ad2c1a9aSJuan Castillo 		if (key->opt != NULL) {
328159807e2SJuan Castillo 			cmd_opt.long_opt.name = key->opt;
329159807e2SJuan Castillo 			cmd_opt.long_opt.has_arg = required_argument;
330159807e2SJuan Castillo 			cmd_opt.long_opt.flag = NULL;
331159807e2SJuan Castillo 			cmd_opt.long_opt.val = CMD_OPT_KEY;
332159807e2SJuan Castillo 			cmd_opt.help_msg = key->help_msg;
333159807e2SJuan Castillo 			cmd_opt_add(&cmd_opt);
334ad2c1a9aSJuan Castillo 		}
335ad2c1a9aSJuan Castillo 	}
336ad2c1a9aSJuan Castillo 
337c893c733SMasahiro Yamada 	return 0;
338ad2c1a9aSJuan Castillo }
339ad2c1a9aSJuan Castillo 
340ad2c1a9aSJuan Castillo key_t *key_get_by_opt(const char *opt)
341ad2c1a9aSJuan Castillo {
342c893c733SMasahiro Yamada 	key_t *key;
343ad2c1a9aSJuan Castillo 	unsigned int i;
344ad2c1a9aSJuan Castillo 
345ad2c1a9aSJuan Castillo 	/* Sequential search. This is not a performance concern since the number
346ad2c1a9aSJuan Castillo 	 * of keys is bounded and the code runs on a host machine */
347ad2c1a9aSJuan Castillo 	for (i = 0; i < num_keys; i++) {
348ad2c1a9aSJuan Castillo 		key = &keys[i];
349ad2c1a9aSJuan Castillo 		if (0 == strcmp(key->opt, opt)) {
350ad2c1a9aSJuan Castillo 			return key;
351ad2c1a9aSJuan Castillo 		}
352ad2c1a9aSJuan Castillo 	}
353ad2c1a9aSJuan Castillo 
354ad2c1a9aSJuan Castillo 	return NULL;
355ad2c1a9aSJuan Castillo }
356cf2dd17dSJuan Pablo Conde 
357cf2dd17dSJuan Pablo Conde void key_cleanup(void)
358cf2dd17dSJuan Pablo Conde {
359cf2dd17dSJuan Pablo Conde 	unsigned int i;
360cf2dd17dSJuan Pablo Conde 
361cf2dd17dSJuan Pablo Conde 	for (i = 0; i < num_keys; i++) {
362cf2dd17dSJuan Pablo Conde 		EVP_PKEY_free(keys[i].key);
363cf2dd17dSJuan Pablo Conde 		if (keys[i].fn != NULL) {
364cf2dd17dSJuan Pablo Conde 			void *ptr = keys[i].fn;
365cf2dd17dSJuan Pablo Conde 
366cf2dd17dSJuan Pablo Conde 			free(ptr);
367cf2dd17dSJuan Pablo Conde 			keys[i].fn = NULL;
368cf2dd17dSJuan Pablo Conde 		}
369cf2dd17dSJuan Pablo Conde 	}
370cf2dd17dSJuan Pablo Conde 	free(keys);
371cf2dd17dSJuan Pablo Conde }
372cf2dd17dSJuan Pablo Conde 
373