16f971622SJuan Castillo /* 2*9bc52d33SJuan Pablo Conde * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. 36f971622SJuan Castillo * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 56f971622SJuan Castillo */ 66f971622SJuan Castillo 76f971622SJuan Castillo #include <getopt.h> 86f971622SJuan Castillo #include <stdio.h> 96f971622SJuan Castillo #include <stdlib.h> 106f971622SJuan Castillo #include <string.h> 116f971622SJuan Castillo 126f971622SJuan Castillo #include <openssl/conf.h> 136f971622SJuan Castillo #include <openssl/evp.h> 146f971622SJuan Castillo #include <openssl/pem.h> 156f971622SJuan Castillo 166f971622SJuan Castillo #include "cert.h" 17ad2c1a9aSJuan Castillo #include "cmd_opt.h" 186f971622SJuan Castillo #include "debug.h" 196f971622SJuan Castillo #include "key.h" 206f971622SJuan Castillo #include "sha.h" 216f971622SJuan Castillo 226f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 236f971622SJuan Castillo 24b94bf967SPankaj Gupta key_t *keys; 25b94bf967SPankaj Gupta unsigned int num_keys; 26b94bf967SPankaj Gupta 276f971622SJuan Castillo /* 28ccbf890eSJuan Castillo * Create a new key container 296f971622SJuan Castillo */ 30762f1ebeSMasahiro Yamada int key_new(key_t *key) 31ccbf890eSJuan Castillo { 32ccbf890eSJuan Castillo /* Create key pair container */ 33ccbf890eSJuan Castillo key->key = EVP_PKEY_new(); 34ccbf890eSJuan Castillo if (key->key == NULL) { 35ccbf890eSJuan Castillo return 0; 36ccbf890eSJuan Castillo } 37ccbf890eSJuan Castillo 38ccbf890eSJuan Castillo return 1; 39ccbf890eSJuan Castillo } 40ccbf890eSJuan Castillo 41dfe0f4c2SJustin Chadwell static int key_create_rsa(key_t *key, int key_bits) 426f971622SJuan Castillo { 43*9bc52d33SJuan Pablo Conde EVP_PKEY *rsa = EVP_RSA_gen(key_bits); 44ccbf890eSJuan Castillo if (rsa == NULL) { 45742c4e14SMichalis Pappas printf("Cannot generate RSA key\n"); 46ed2a76eaSJuan Castillo return 0; 47ed2a76eaSJuan Castillo } 48*9bc52d33SJuan Pablo Conde key->key = rsa; 49*9bc52d33SJuan Pablo Conde return 1; 50*9bc52d33SJuan Pablo Conde } 51ed2a76eaSJuan Castillo 52ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 53dfe0f4c2SJustin Chadwell static int key_create_ecdsa(key_t *key, int key_bits) 54ed2a76eaSJuan Castillo { 55*9bc52d33SJuan Pablo Conde EVP_PKEY *ec = EVP_EC_gen("prime256v1"); 56ccbf890eSJuan Castillo if (ec == NULL) { 57ccbf890eSJuan Castillo printf("Cannot generate EC key\n"); 58ed2a76eaSJuan Castillo return 0; 59ed2a76eaSJuan Castillo } 60*9bc52d33SJuan Pablo Conde key->key = ec; 61*9bc52d33SJuan Pablo Conde return 1; 62*9bc52d33SJuan Pablo Conde } 63ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 64ed2a76eaSJuan Castillo 65dfe0f4c2SJustin Chadwell typedef int (*key_create_fn_t)(key_t *key, int key_bits); 66ed2a76eaSJuan Castillo static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { 671727de0eSQixiang Xu key_create_rsa, /* KEY_ALG_RSA */ 68ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 691727de0eSQixiang Xu key_create_ecdsa, /* KEY_ALG_ECDSA */ 70ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 71ed2a76eaSJuan Castillo }; 72ed2a76eaSJuan Castillo 73dfe0f4c2SJustin Chadwell int key_create(key_t *key, int type, int key_bits) 74ed2a76eaSJuan Castillo { 75ed2a76eaSJuan Castillo if (type >= KEY_ALG_MAX_NUM) { 76ed2a76eaSJuan Castillo printf("Invalid key type\n"); 77ed2a76eaSJuan Castillo return 0; 78ed2a76eaSJuan Castillo } 79ed2a76eaSJuan Castillo 80ed2a76eaSJuan Castillo if (key_create_fn[type]) { 81dfe0f4c2SJustin Chadwell return key_create_fn[type](key, key_bits); 82ed2a76eaSJuan Castillo } 83ccbf890eSJuan Castillo 846f971622SJuan Castillo return 0; 856f971622SJuan Castillo } 866f971622SJuan Castillo 87ccbf890eSJuan Castillo int key_load(key_t *key, unsigned int *err_code) 886f971622SJuan Castillo { 89c893c733SMasahiro Yamada FILE *fp; 90c893c733SMasahiro Yamada EVP_PKEY *k; 916f971622SJuan Castillo 926f971622SJuan Castillo if (key->fn) { 936f971622SJuan Castillo /* Load key from file */ 946f971622SJuan Castillo fp = fopen(key->fn, "r"); 956f971622SJuan Castillo if (fp) { 96ccbf890eSJuan Castillo k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); 976f971622SJuan Castillo fclose(fp); 986f971622SJuan Castillo if (k) { 99ccbf890eSJuan Castillo *err_code = KEY_ERR_NONE; 1006f971622SJuan Castillo return 1; 1016f971622SJuan Castillo } else { 102ccbf890eSJuan Castillo ERROR("Cannot load key from %s\n", key->fn); 103ccbf890eSJuan Castillo *err_code = KEY_ERR_LOAD; 1046f971622SJuan Castillo } 1056f971622SJuan Castillo } else { 106ccbf890eSJuan Castillo WARN("Cannot open file %s\n", key->fn); 107ccbf890eSJuan Castillo *err_code = KEY_ERR_OPEN; 1086f971622SJuan Castillo } 1096f971622SJuan Castillo } else { 110ccbf890eSJuan Castillo WARN("Key filename not specified\n"); 111ccbf890eSJuan Castillo *err_code = KEY_ERR_FILENAME; 1126f971622SJuan Castillo } 1136f971622SJuan Castillo 1146f971622SJuan Castillo return 0; 1156f971622SJuan Castillo } 1166f971622SJuan Castillo 1176f971622SJuan Castillo int key_store(key_t *key) 1186f971622SJuan Castillo { 119c893c733SMasahiro Yamada FILE *fp; 1206f971622SJuan Castillo 1216f971622SJuan Castillo if (key->fn) { 1226f971622SJuan Castillo fp = fopen(key->fn, "w"); 1236f971622SJuan Castillo if (fp) { 1246f971622SJuan Castillo PEM_write_PrivateKey(fp, key->key, 1256f971622SJuan Castillo NULL, NULL, 0, NULL, NULL); 1266f971622SJuan Castillo fclose(fp); 1276f971622SJuan Castillo return 1; 1286f971622SJuan Castillo } else { 1296f971622SJuan Castillo ERROR("Cannot create file %s\n", key->fn); 1306f971622SJuan Castillo } 1316f971622SJuan Castillo } else { 1326f971622SJuan Castillo ERROR("Key filename not specified\n"); 1336f971622SJuan Castillo } 1346f971622SJuan Castillo 1356f971622SJuan Castillo return 0; 1366f971622SJuan Castillo } 137ad2c1a9aSJuan Castillo 138ad2c1a9aSJuan Castillo int key_init(void) 139ad2c1a9aSJuan Castillo { 140159807e2SJuan Castillo cmd_opt_t cmd_opt; 141ad2c1a9aSJuan Castillo key_t *key; 142ad2c1a9aSJuan Castillo unsigned int i; 143ad2c1a9aSJuan Castillo 144b94bf967SPankaj Gupta keys = malloc((num_def_keys * sizeof(def_keys[0])) 145b94bf967SPankaj Gupta #ifdef PDEF_KEYS 146b94bf967SPankaj Gupta + (num_pdef_keys * sizeof(pdef_keys[0])) 147b94bf967SPankaj Gupta #endif 148b94bf967SPankaj Gupta ); 149b94bf967SPankaj Gupta 150b94bf967SPankaj Gupta if (keys == NULL) { 151b94bf967SPankaj Gupta ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); 152b94bf967SPankaj Gupta return 1; 153b94bf967SPankaj Gupta } 154b94bf967SPankaj Gupta 155b94bf967SPankaj Gupta memcpy(&keys[0], &def_keys[0], (num_def_keys * sizeof(def_keys[0]))); 156b94bf967SPankaj Gupta #ifdef PDEF_KEYS 157b94bf967SPankaj Gupta memcpy(&keys[num_def_keys], &pdef_keys[0], 158b94bf967SPankaj Gupta (num_pdef_keys * sizeof(pdef_keys[0]))); 159b94bf967SPankaj Gupta 160b94bf967SPankaj Gupta num_keys = num_def_keys + num_pdef_keys; 161b94bf967SPankaj Gupta #else 162b94bf967SPankaj Gupta num_keys = num_def_keys; 163b94bf967SPankaj Gupta #endif 164b94bf967SPankaj Gupta ; 165b94bf967SPankaj Gupta 166ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 167ad2c1a9aSJuan Castillo key = &keys[i]; 168ad2c1a9aSJuan Castillo if (key->opt != NULL) { 169159807e2SJuan Castillo cmd_opt.long_opt.name = key->opt; 170159807e2SJuan Castillo cmd_opt.long_opt.has_arg = required_argument; 171159807e2SJuan Castillo cmd_opt.long_opt.flag = NULL; 172159807e2SJuan Castillo cmd_opt.long_opt.val = CMD_OPT_KEY; 173159807e2SJuan Castillo cmd_opt.help_msg = key->help_msg; 174159807e2SJuan Castillo cmd_opt_add(&cmd_opt); 175ad2c1a9aSJuan Castillo } 176ad2c1a9aSJuan Castillo } 177ad2c1a9aSJuan Castillo 178c893c733SMasahiro Yamada return 0; 179ad2c1a9aSJuan Castillo } 180ad2c1a9aSJuan Castillo 181ad2c1a9aSJuan Castillo key_t *key_get_by_opt(const char *opt) 182ad2c1a9aSJuan Castillo { 183c893c733SMasahiro Yamada key_t *key; 184ad2c1a9aSJuan Castillo unsigned int i; 185ad2c1a9aSJuan Castillo 186ad2c1a9aSJuan Castillo /* Sequential search. This is not a performance concern since the number 187ad2c1a9aSJuan Castillo * of keys is bounded and the code runs on a host machine */ 188ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 189ad2c1a9aSJuan Castillo key = &keys[i]; 190ad2c1a9aSJuan Castillo if (0 == strcmp(key->opt, opt)) { 191ad2c1a9aSJuan Castillo return key; 192ad2c1a9aSJuan Castillo } 193ad2c1a9aSJuan Castillo } 194ad2c1a9aSJuan Castillo 195ad2c1a9aSJuan Castillo return NULL; 196ad2c1a9aSJuan Castillo } 197