1 /* 2 * Copyright (c) 2015-2022, 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 key_t *keys; 25 unsigned int num_keys; 26 27 #if !USING_OPENSSL3 28 /* 29 * Create a new key container 30 */ 31 int key_new(key_t *key) 32 { 33 /* Create key pair container */ 34 key->key = EVP_PKEY_new(); 35 if (key->key == NULL) { 36 return 0; 37 } 38 39 return 1; 40 } 41 #endif 42 43 static int key_create_rsa(key_t *key, int key_bits) 44 { 45 #if USING_OPENSSL3 46 EVP_PKEY *rsa = EVP_RSA_gen(key_bits); 47 if (rsa == NULL) { 48 printf("Cannot generate RSA key\n"); 49 return 0; 50 } 51 key->key = rsa; 52 return 1; 53 #else 54 BIGNUM *e; 55 RSA *rsa = NULL; 56 57 e = BN_new(); 58 if (e == NULL) { 59 printf("Cannot create RSA exponent\n"); 60 return 0; 61 } 62 63 if (!BN_set_word(e, RSA_F4)) { 64 printf("Cannot assign RSA exponent\n"); 65 goto err2; 66 } 67 68 rsa = RSA_new(); 69 if (rsa == NULL) { 70 printf("Cannot create RSA key\n"); 71 goto err2; 72 } 73 74 if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) { 75 printf("Cannot generate RSA key\n"); 76 goto err; 77 } 78 79 if (!EVP_PKEY_assign_RSA(key->key, rsa)) { 80 printf("Cannot assign RSA key\n"); 81 goto err; 82 } 83 84 BN_free(e); 85 return 1; 86 87 err: 88 RSA_free(rsa); 89 err2: 90 BN_free(e); 91 return 0; 92 #endif 93 } 94 95 #ifndef OPENSSL_NO_EC 96 static int key_create_ecdsa(key_t *key, int key_bits) 97 { 98 #if USING_OPENSSL3 99 EVP_PKEY *ec = EVP_EC_gen("prime256v1"); 100 if (ec == NULL) { 101 printf("Cannot generate EC key\n"); 102 return 0; 103 } 104 key->key = ec; 105 return 1; 106 #else 107 EC_KEY *ec; 108 109 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 110 if (ec == NULL) { 111 printf("Cannot create EC key\n"); 112 return 0; 113 } 114 if (!EC_KEY_generate_key(ec)) { 115 printf("Cannot generate EC key\n"); 116 goto err; 117 } 118 EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS); 119 EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); 120 if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) { 121 printf("Cannot assign EC key\n"); 122 goto err; 123 } 124 125 return 1; 126 127 err: 128 EC_KEY_free(ec); 129 return 0; 130 #endif 131 } 132 #endif /* OPENSSL_NO_EC */ 133 134 typedef int (*key_create_fn_t)(key_t *key, int key_bits); 135 static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { 136 key_create_rsa, /* KEY_ALG_RSA */ 137 #ifndef OPENSSL_NO_EC 138 key_create_ecdsa, /* KEY_ALG_ECDSA */ 139 #endif /* OPENSSL_NO_EC */ 140 }; 141 142 int key_create(key_t *key, int type, int key_bits) 143 { 144 if (type >= KEY_ALG_MAX_NUM) { 145 printf("Invalid key type\n"); 146 return 0; 147 } 148 149 if (key_create_fn[type]) { 150 return key_create_fn[type](key, key_bits); 151 } 152 153 return 0; 154 } 155 156 int key_load(key_t *key, unsigned int *err_code) 157 { 158 FILE *fp; 159 EVP_PKEY *k; 160 161 if (key->fn) { 162 /* Load key from file */ 163 fp = fopen(key->fn, "r"); 164 if (fp) { 165 k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); 166 fclose(fp); 167 if (k) { 168 *err_code = KEY_ERR_NONE; 169 return 1; 170 } else { 171 ERROR("Cannot load key from %s\n", key->fn); 172 *err_code = KEY_ERR_LOAD; 173 } 174 } else { 175 WARN("Cannot open file %s\n", key->fn); 176 *err_code = KEY_ERR_OPEN; 177 } 178 } else { 179 WARN("Key filename not specified\n"); 180 *err_code = KEY_ERR_FILENAME; 181 } 182 183 return 0; 184 } 185 186 int key_store(key_t *key) 187 { 188 FILE *fp; 189 190 if (key->fn) { 191 fp = fopen(key->fn, "w"); 192 if (fp) { 193 PEM_write_PrivateKey(fp, key->key, 194 NULL, NULL, 0, NULL, NULL); 195 fclose(fp); 196 return 1; 197 } else { 198 ERROR("Cannot create file %s\n", key->fn); 199 } 200 } else { 201 ERROR("Key filename not specified\n"); 202 } 203 204 return 0; 205 } 206 207 int key_init(void) 208 { 209 cmd_opt_t cmd_opt; 210 key_t *key; 211 unsigned int i; 212 213 keys = malloc((num_def_keys * sizeof(def_keys[0])) 214 #ifdef PDEF_KEYS 215 + (num_pdef_keys * sizeof(pdef_keys[0])) 216 #endif 217 ); 218 219 if (keys == NULL) { 220 ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); 221 return 1; 222 } 223 224 memcpy(&keys[0], &def_keys[0], (num_def_keys * sizeof(def_keys[0]))); 225 #ifdef PDEF_KEYS 226 memcpy(&keys[num_def_keys], &pdef_keys[0], 227 (num_pdef_keys * sizeof(pdef_keys[0]))); 228 229 num_keys = num_def_keys + num_pdef_keys; 230 #else 231 num_keys = num_def_keys; 232 #endif 233 ; 234 235 for (i = 0; i < num_keys; i++) { 236 key = &keys[i]; 237 if (key->opt != NULL) { 238 cmd_opt.long_opt.name = key->opt; 239 cmd_opt.long_opt.has_arg = required_argument; 240 cmd_opt.long_opt.flag = NULL; 241 cmd_opt.long_opt.val = CMD_OPT_KEY; 242 cmd_opt.help_msg = key->help_msg; 243 cmd_opt_add(&cmd_opt); 244 } 245 } 246 247 return 0; 248 } 249 250 key_t *key_get_by_opt(const char *opt) 251 { 252 key_t *key; 253 unsigned int i; 254 255 /* Sequential search. This is not a performance concern since the number 256 * of keys is bounded and the code runs on a host machine */ 257 for (i = 0; i < num_keys; i++) { 258 key = &keys[i]; 259 if (0 == strcmp(key->opt, opt)) { 260 return key; 261 } 262 } 263 264 return NULL; 265 } 266 267 void key_cleanup(void) 268 { 269 unsigned int i; 270 271 for (i = 0; i < num_keys; i++) { 272 EVP_PKEY_free(keys[i].key); 273 if (keys[i].fn != NULL) { 274 void *ptr = keys[i].fn; 275 276 free(ptr); 277 keys[i].fn = NULL; 278 } 279 } 280 free(keys); 281 } 282 283