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