Home | History | Annotate | Download | only in src
      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  */
     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 
     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
     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 
    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 
    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 
    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 
    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 
    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