16f971622SJuan Castillo /* 2*b94bf967SPankaj Gupta * Copyright (c) 2015-2021, 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 24*b94bf967SPankaj Gupta key_t *keys; 25*b94bf967SPankaj Gupta unsigned int num_keys; 26*b94bf967SPankaj 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 { 43742c4e14SMichalis Pappas BIGNUM *e; 44742c4e14SMichalis Pappas RSA *rsa = NULL; 456f971622SJuan Castillo 46742c4e14SMichalis Pappas e = BN_new(); 47742c4e14SMichalis Pappas if (e == NULL) { 48742c4e14SMichalis Pappas printf("Cannot create RSA exponent\n"); 49742c4e14SMichalis Pappas goto err; 50742c4e14SMichalis Pappas } 51742c4e14SMichalis Pappas 52742c4e14SMichalis Pappas if (!BN_set_word(e, RSA_F4)) { 53742c4e14SMichalis Pappas printf("Cannot assign RSA exponent\n"); 54742c4e14SMichalis Pappas goto err; 55742c4e14SMichalis Pappas } 56742c4e14SMichalis Pappas 57742c4e14SMichalis Pappas rsa = RSA_new(); 58ccbf890eSJuan Castillo if (rsa == NULL) { 59ccbf890eSJuan Castillo printf("Cannot create RSA key\n"); 60ccbf890eSJuan Castillo goto err; 61ccbf890eSJuan Castillo } 62742c4e14SMichalis Pappas 63dfe0f4c2SJustin Chadwell if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) { 64742c4e14SMichalis Pappas printf("Cannot generate RSA key\n"); 65742c4e14SMichalis Pappas goto err; 66742c4e14SMichalis Pappas } 67742c4e14SMichalis Pappas 68ccbf890eSJuan Castillo if (!EVP_PKEY_assign_RSA(key->key, rsa)) { 696f971622SJuan Castillo printf("Cannot assign RSA key\n"); 70ccbf890eSJuan Castillo goto err; 71ccbf890eSJuan Castillo } 72ed2a76eaSJuan Castillo 7365ec13bcSJustin Chadwell BN_free(e); 74ed2a76eaSJuan Castillo return 1; 75ed2a76eaSJuan Castillo err: 76ed2a76eaSJuan Castillo RSA_free(rsa); 77742c4e14SMichalis Pappas BN_free(e); 78ed2a76eaSJuan Castillo return 0; 79ed2a76eaSJuan Castillo } 80ed2a76eaSJuan Castillo 81ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 82dfe0f4c2SJustin Chadwell static int key_create_ecdsa(key_t *key, int key_bits) 83ed2a76eaSJuan Castillo { 84c893c733SMasahiro Yamada EC_KEY *ec; 85ed2a76eaSJuan Castillo 86ccbf890eSJuan Castillo ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 87ccbf890eSJuan Castillo if (ec == NULL) { 88ccbf890eSJuan Castillo printf("Cannot create EC key\n"); 89ccbf890eSJuan Castillo goto err; 90ccbf890eSJuan Castillo } 91ccbf890eSJuan Castillo if (!EC_KEY_generate_key(ec)) { 92ccbf890eSJuan Castillo printf("Cannot generate EC key\n"); 93ccbf890eSJuan Castillo goto err; 94ccbf890eSJuan Castillo } 95ccbf890eSJuan Castillo EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS); 96ccbf890eSJuan Castillo EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); 97ccbf890eSJuan Castillo if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) { 98ccbf890eSJuan Castillo printf("Cannot assign EC key\n"); 99ccbf890eSJuan Castillo goto err; 100ccbf890eSJuan Castillo } 1016f971622SJuan Castillo 102ccbf890eSJuan Castillo return 1; 103ccbf890eSJuan Castillo err: 104ccbf890eSJuan Castillo EC_KEY_free(ec); 105ed2a76eaSJuan Castillo return 0; 106ed2a76eaSJuan Castillo } 107ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 108ed2a76eaSJuan Castillo 109dfe0f4c2SJustin Chadwell typedef int (*key_create_fn_t)(key_t *key, int key_bits); 110ed2a76eaSJuan Castillo static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { 1111727de0eSQixiang Xu key_create_rsa, /* KEY_ALG_RSA */ 112ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 1131727de0eSQixiang Xu key_create_ecdsa, /* KEY_ALG_ECDSA */ 114ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 115ed2a76eaSJuan Castillo }; 116ed2a76eaSJuan Castillo 117dfe0f4c2SJustin Chadwell int key_create(key_t *key, int type, int key_bits) 118ed2a76eaSJuan Castillo { 119ed2a76eaSJuan Castillo if (type >= KEY_ALG_MAX_NUM) { 120ed2a76eaSJuan Castillo printf("Invalid key type\n"); 121ed2a76eaSJuan Castillo return 0; 122ed2a76eaSJuan Castillo } 123ed2a76eaSJuan Castillo 124ed2a76eaSJuan Castillo if (key_create_fn[type]) { 125dfe0f4c2SJustin Chadwell return key_create_fn[type](key, key_bits); 126ed2a76eaSJuan Castillo } 127ccbf890eSJuan Castillo 1286f971622SJuan Castillo return 0; 1296f971622SJuan Castillo } 1306f971622SJuan Castillo 131ccbf890eSJuan Castillo int key_load(key_t *key, unsigned int *err_code) 1326f971622SJuan Castillo { 133c893c733SMasahiro Yamada FILE *fp; 134c893c733SMasahiro Yamada EVP_PKEY *k; 1356f971622SJuan Castillo 1366f971622SJuan Castillo if (key->fn) { 1376f971622SJuan Castillo /* Load key from file */ 1386f971622SJuan Castillo fp = fopen(key->fn, "r"); 1396f971622SJuan Castillo if (fp) { 140ccbf890eSJuan Castillo k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); 1416f971622SJuan Castillo fclose(fp); 1426f971622SJuan Castillo if (k) { 143ccbf890eSJuan Castillo *err_code = KEY_ERR_NONE; 1446f971622SJuan Castillo return 1; 1456f971622SJuan Castillo } else { 146ccbf890eSJuan Castillo ERROR("Cannot load key from %s\n", key->fn); 147ccbf890eSJuan Castillo *err_code = KEY_ERR_LOAD; 1486f971622SJuan Castillo } 1496f971622SJuan Castillo } else { 150ccbf890eSJuan Castillo WARN("Cannot open file %s\n", key->fn); 151ccbf890eSJuan Castillo *err_code = KEY_ERR_OPEN; 1526f971622SJuan Castillo } 1536f971622SJuan Castillo } else { 154ccbf890eSJuan Castillo WARN("Key filename not specified\n"); 155ccbf890eSJuan Castillo *err_code = KEY_ERR_FILENAME; 1566f971622SJuan Castillo } 1576f971622SJuan Castillo 1586f971622SJuan Castillo return 0; 1596f971622SJuan Castillo } 1606f971622SJuan Castillo 1616f971622SJuan Castillo int key_store(key_t *key) 1626f971622SJuan Castillo { 163c893c733SMasahiro Yamada FILE *fp; 1646f971622SJuan Castillo 1656f971622SJuan Castillo if (key->fn) { 1666f971622SJuan Castillo fp = fopen(key->fn, "w"); 1676f971622SJuan Castillo if (fp) { 1686f971622SJuan Castillo PEM_write_PrivateKey(fp, key->key, 1696f971622SJuan Castillo NULL, NULL, 0, NULL, NULL); 1706f971622SJuan Castillo fclose(fp); 1716f971622SJuan Castillo return 1; 1726f971622SJuan Castillo } else { 1736f971622SJuan Castillo ERROR("Cannot create file %s\n", key->fn); 1746f971622SJuan Castillo } 1756f971622SJuan Castillo } else { 1766f971622SJuan Castillo ERROR("Key filename not specified\n"); 1776f971622SJuan Castillo } 1786f971622SJuan Castillo 1796f971622SJuan Castillo return 0; 1806f971622SJuan Castillo } 181ad2c1a9aSJuan Castillo 182ad2c1a9aSJuan Castillo int key_init(void) 183ad2c1a9aSJuan Castillo { 184159807e2SJuan Castillo cmd_opt_t cmd_opt; 185ad2c1a9aSJuan Castillo key_t *key; 186ad2c1a9aSJuan Castillo unsigned int i; 187ad2c1a9aSJuan Castillo 188*b94bf967SPankaj Gupta keys = malloc((num_def_keys * sizeof(def_keys[0])) 189*b94bf967SPankaj Gupta #ifdef PDEF_KEYS 190*b94bf967SPankaj Gupta + (num_pdef_keys * sizeof(pdef_keys[0])) 191*b94bf967SPankaj Gupta #endif 192*b94bf967SPankaj Gupta ); 193*b94bf967SPankaj Gupta 194*b94bf967SPankaj Gupta if (keys == NULL) { 195*b94bf967SPankaj Gupta ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); 196*b94bf967SPankaj Gupta return 1; 197*b94bf967SPankaj Gupta } 198*b94bf967SPankaj Gupta 199*b94bf967SPankaj Gupta memcpy(&keys[0], &def_keys[0], (num_def_keys * sizeof(def_keys[0]))); 200*b94bf967SPankaj Gupta #ifdef PDEF_KEYS 201*b94bf967SPankaj Gupta memcpy(&keys[num_def_keys], &pdef_keys[0], 202*b94bf967SPankaj Gupta (num_pdef_keys * sizeof(pdef_keys[0]))); 203*b94bf967SPankaj Gupta 204*b94bf967SPankaj Gupta num_keys = num_def_keys + num_pdef_keys; 205*b94bf967SPankaj Gupta #else 206*b94bf967SPankaj Gupta num_keys = num_def_keys; 207*b94bf967SPankaj Gupta #endif 208*b94bf967SPankaj Gupta ; 209*b94bf967SPankaj Gupta 210ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 211ad2c1a9aSJuan Castillo key = &keys[i]; 212ad2c1a9aSJuan Castillo if (key->opt != NULL) { 213159807e2SJuan Castillo cmd_opt.long_opt.name = key->opt; 214159807e2SJuan Castillo cmd_opt.long_opt.has_arg = required_argument; 215159807e2SJuan Castillo cmd_opt.long_opt.flag = NULL; 216159807e2SJuan Castillo cmd_opt.long_opt.val = CMD_OPT_KEY; 217159807e2SJuan Castillo cmd_opt.help_msg = key->help_msg; 218159807e2SJuan Castillo cmd_opt_add(&cmd_opt); 219ad2c1a9aSJuan Castillo } 220ad2c1a9aSJuan Castillo } 221ad2c1a9aSJuan Castillo 222c893c733SMasahiro Yamada return 0; 223ad2c1a9aSJuan Castillo } 224ad2c1a9aSJuan Castillo 225ad2c1a9aSJuan Castillo key_t *key_get_by_opt(const char *opt) 226ad2c1a9aSJuan Castillo { 227c893c733SMasahiro Yamada key_t *key; 228ad2c1a9aSJuan Castillo unsigned int i; 229ad2c1a9aSJuan Castillo 230ad2c1a9aSJuan Castillo /* Sequential search. This is not a performance concern since the number 231ad2c1a9aSJuan Castillo * of keys is bounded and the code runs on a host machine */ 232ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 233ad2c1a9aSJuan Castillo key = &keys[i]; 234ad2c1a9aSJuan Castillo if (0 == strcmp(key->opt, opt)) { 235ad2c1a9aSJuan Castillo return key; 236ad2c1a9aSJuan Castillo } 237ad2c1a9aSJuan Castillo } 238ad2c1a9aSJuan Castillo 239ad2c1a9aSJuan Castillo return NULL; 240ad2c1a9aSJuan Castillo } 241