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