xref: /rk3399_ARM-atf/tools/cert_create/src/key.c (revision 82cb2c1ad9897473743f08437d0a3995bed561b9)
1 /*
2  * Copyright (c) 2015, 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 "platform_oid.h"
21 #include "sha.h"
22 
23 #define MAX_FILENAME_LEN		1024
24 
25 /*
26  * Create a new key container
27  */
28 int key_new(key_t *key)
29 {
30 	/* Create key pair container */
31 	key->key = EVP_PKEY_new();
32 	if (key->key == NULL) {
33 		return 0;
34 	}
35 
36 	return 1;
37 }
38 
39 static int key_create_rsa(key_t *key)
40 {
41 	RSA *rsa;
42 
43 	rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL);
44 	if (rsa == NULL) {
45 		printf("Cannot create RSA key\n");
46 		goto err;
47 	}
48 	if (!EVP_PKEY_assign_RSA(key->key, rsa)) {
49 		printf("Cannot assign RSA key\n");
50 		goto err;
51 	}
52 
53 	return 1;
54 err:
55 	RSA_free(rsa);
56 	return 0;
57 }
58 
59 #ifndef OPENSSL_NO_EC
60 static int key_create_ecdsa(key_t *key)
61 {
62 	EC_KEY *ec;
63 
64 	ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
65 	if (ec == NULL) {
66 		printf("Cannot create EC key\n");
67 		goto err;
68 	}
69 	if (!EC_KEY_generate_key(ec)) {
70 		printf("Cannot generate EC key\n");
71 		goto err;
72 	}
73 	EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS);
74 	EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
75 	if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) {
76 		printf("Cannot assign EC key\n");
77 		goto err;
78 	}
79 
80 	return 1;
81 err:
82 	EC_KEY_free(ec);
83 	return 0;
84 }
85 #endif /* OPENSSL_NO_EC */
86 
87 typedef int (*key_create_fn_t)(key_t *key);
88 static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = {
89 	key_create_rsa,
90 #ifndef OPENSSL_NO_EC
91 	key_create_ecdsa,
92 #endif /* OPENSSL_NO_EC */
93 };
94 
95 int key_create(key_t *key, int type)
96 {
97 	if (type >= KEY_ALG_MAX_NUM) {
98 		printf("Invalid key type\n");
99 		return 0;
100 	}
101 
102 	if (key_create_fn[type]) {
103 		return key_create_fn[type](key);
104 	}
105 
106 	return 0;
107 }
108 
109 int key_load(key_t *key, unsigned int *err_code)
110 {
111 	FILE *fp;
112 	EVP_PKEY *k;
113 
114 	if (key->fn) {
115 		/* Load key from file */
116 		fp = fopen(key->fn, "r");
117 		if (fp) {
118 			k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL);
119 			fclose(fp);
120 			if (k) {
121 				*err_code = KEY_ERR_NONE;
122 				return 1;
123 			} else {
124 				ERROR("Cannot load key from %s\n", key->fn);
125 				*err_code = KEY_ERR_LOAD;
126 			}
127 		} else {
128 			WARN("Cannot open file %s\n", key->fn);
129 			*err_code = KEY_ERR_OPEN;
130 		}
131 	} else {
132 		WARN("Key filename not specified\n");
133 		*err_code = KEY_ERR_FILENAME;
134 	}
135 
136 	return 0;
137 }
138 
139 int key_store(key_t *key)
140 {
141 	FILE *fp;
142 
143 	if (key->fn) {
144 		fp = fopen(key->fn, "w");
145 		if (fp) {
146 			PEM_write_PrivateKey(fp, key->key,
147 					NULL, NULL, 0, NULL, NULL);
148 			fclose(fp);
149 			return 1;
150 		} else {
151 			ERROR("Cannot create file %s\n", key->fn);
152 		}
153 	} else {
154 		ERROR("Key filename not specified\n");
155 	}
156 
157 	return 0;
158 }
159 
160 int key_init(void)
161 {
162 	cmd_opt_t cmd_opt;
163 	key_t *key;
164 	unsigned int i;
165 
166 	for (i = 0; i < num_keys; i++) {
167 		key = &keys[i];
168 		if (key->opt != NULL) {
169 			cmd_opt.long_opt.name = key->opt;
170 			cmd_opt.long_opt.has_arg = required_argument;
171 			cmd_opt.long_opt.flag = NULL;
172 			cmd_opt.long_opt.val = CMD_OPT_KEY;
173 			cmd_opt.help_msg = key->help_msg;
174 			cmd_opt_add(&cmd_opt);
175 		}
176 	}
177 
178 	return 0;
179 }
180 
181 key_t *key_get_by_opt(const char *opt)
182 {
183 	key_t *key;
184 	unsigned int i;
185 
186 	/* Sequential search. This is not a performance concern since the number
187 	 * of keys is bounded and the code runs on a host machine */
188 	for (i = 0; i < num_keys; i++) {
189 		key = &keys[i];
190 		if (0 == strcmp(key->opt, opt)) {
191 			return key;
192 		}
193 	}
194 
195 	return NULL;
196 }
197