• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <getopt.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include <openssl/conf.h>
13 #include <openssl/evp.h>
14 #include <openssl/pem.h>
15 
16 #include "cert.h"
17 #include "cmd_opt.h"
18 #include "debug.h"
19 #include "key.h"
20 #include "sha.h"
21 
22 #define MAX_FILENAME_LEN		1024
23 
24 /*
25  * Create a new key container
26  */
key_new(key_t * key)27 int key_new(key_t *key)
28 {
29 	/* Create key pair container */
30 	key->key = EVP_PKEY_new();
31 	if (key->key == NULL) {
32 		return 0;
33 	}
34 
35 	return 1;
36 }
37 
key_create_rsa(key_t * key,int key_bits)38 static int key_create_rsa(key_t *key, int key_bits)
39 {
40 	BIGNUM *e;
41 	RSA *rsa = NULL;
42 
43 	e = BN_new();
44 	if (e == NULL) {
45 		printf("Cannot create RSA exponent\n");
46 		goto err;
47 	}
48 
49 	if (!BN_set_word(e, RSA_F4)) {
50 		printf("Cannot assign RSA exponent\n");
51 		goto err;
52 	}
53 
54 	rsa = RSA_new();
55 	if (rsa == NULL) {
56 		printf("Cannot create RSA key\n");
57 		goto err;
58 	}
59 
60 	if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) {
61 		printf("Cannot generate RSA key\n");
62 		goto err;
63 	}
64 
65 	if (!EVP_PKEY_assign_RSA(key->key, rsa)) {
66 		printf("Cannot assign RSA key\n");
67 		goto err;
68 	}
69 
70 	BN_free(e);
71 	return 1;
72 err:
73 	RSA_free(rsa);
74 	BN_free(e);
75 	return 0;
76 }
77 
78 #ifndef OPENSSL_NO_EC
key_create_ecdsa(key_t * key,int key_bits)79 static int key_create_ecdsa(key_t *key, int key_bits)
80 {
81 	EC_KEY *ec;
82 
83 	ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
84 	if (ec == NULL) {
85 		printf("Cannot create EC key\n");
86 		goto err;
87 	}
88 	if (!EC_KEY_generate_key(ec)) {
89 		printf("Cannot generate EC key\n");
90 		goto err;
91 	}
92 	EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS);
93 	EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
94 	if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) {
95 		printf("Cannot assign EC key\n");
96 		goto err;
97 	}
98 
99 	return 1;
100 err:
101 	EC_KEY_free(ec);
102 	return 0;
103 }
104 #endif /* OPENSSL_NO_EC */
105 
106 typedef int (*key_create_fn_t)(key_t *key, int key_bits);
107 static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = {
108 	key_create_rsa, 	/* KEY_ALG_RSA */
109 #ifndef OPENSSL_NO_EC
110 	key_create_ecdsa, 	/* KEY_ALG_ECDSA */
111 #endif /* OPENSSL_NO_EC */
112 };
113 
key_create(key_t * key,int type,int key_bits)114 int key_create(key_t *key, int type, int key_bits)
115 {
116 	if (type >= KEY_ALG_MAX_NUM) {
117 		printf("Invalid key type\n");
118 		return 0;
119 	}
120 
121 	if (key_create_fn[type]) {
122 		return key_create_fn[type](key, key_bits);
123 	}
124 
125 	return 0;
126 }
127 
key_load(key_t * key,unsigned int * err_code)128 int key_load(key_t *key, unsigned int *err_code)
129 {
130 	FILE *fp;
131 	EVP_PKEY *k;
132 
133 	if (key->fn) {
134 		/* Load key from file */
135 		fp = fopen(key->fn, "r");
136 		if (fp) {
137 			k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL);
138 			fclose(fp);
139 			if (k) {
140 				*err_code = KEY_ERR_NONE;
141 				return 1;
142 			} else {
143 				ERROR("Cannot load key from %s\n", key->fn);
144 				*err_code = KEY_ERR_LOAD;
145 			}
146 		} else {
147 			WARN("Cannot open file %s\n", key->fn);
148 			*err_code = KEY_ERR_OPEN;
149 		}
150 	} else {
151 		WARN("Key filename not specified\n");
152 		*err_code = KEY_ERR_FILENAME;
153 	}
154 
155 	return 0;
156 }
157 
key_store(key_t * key)158 int key_store(key_t *key)
159 {
160 	FILE *fp;
161 
162 	if (key->fn) {
163 		fp = fopen(key->fn, "w");
164 		if (fp) {
165 			PEM_write_PrivateKey(fp, key->key,
166 					NULL, NULL, 0, NULL, NULL);
167 			fclose(fp);
168 			return 1;
169 		} else {
170 			ERROR("Cannot create file %s\n", key->fn);
171 		}
172 	} else {
173 		ERROR("Key filename not specified\n");
174 	}
175 
176 	return 0;
177 }
178 
key_init(void)179 int key_init(void)
180 {
181 	cmd_opt_t cmd_opt;
182 	key_t *key;
183 	unsigned int i;
184 
185 	for (i = 0; i < num_keys; i++) {
186 		key = &keys[i];
187 		if (key->opt != NULL) {
188 			cmd_opt.long_opt.name = key->opt;
189 			cmd_opt.long_opt.has_arg = required_argument;
190 			cmd_opt.long_opt.flag = NULL;
191 			cmd_opt.long_opt.val = CMD_OPT_KEY;
192 			cmd_opt.help_msg = key->help_msg;
193 			cmd_opt_add(&cmd_opt);
194 		}
195 	}
196 
197 	return 0;
198 }
199 
key_get_by_opt(const char * opt)200 key_t *key_get_by_opt(const char *opt)
201 {
202 	key_t *key;
203 	unsigned int i;
204 
205 	/* Sequential search. This is not a performance concern since the number
206 	 * of keys is bounded and the code runs on a host machine */
207 	for (i = 0; i < num_keys; i++) {
208 		key = &keys[i];
209 		if (0 == strcmp(key->opt, opt)) {
210 			return key;
211 		}
212 	}
213 
214 	return NULL;
215 }
216