16f971622SJuan Castillo /* 265ec13bcSJustin Chadwell * Copyright (c) 2015-2019, 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 16bb41eb7aSMasahiro Yamada #if USE_TBBR_DEFS 17bb41eb7aSMasahiro Yamada #include <tbbr_oid.h> 18bb41eb7aSMasahiro Yamada #else 19bb41eb7aSMasahiro Yamada #include <platform_oid.h> 20bb41eb7aSMasahiro Yamada #endif 21bb41eb7aSMasahiro Yamada 226f971622SJuan Castillo #include "cert.h" 23ad2c1a9aSJuan Castillo #include "cmd_opt.h" 246f971622SJuan Castillo #include "debug.h" 256f971622SJuan Castillo #include "key.h" 266f971622SJuan Castillo #include "sha.h" 276f971622SJuan Castillo 286f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 296f971622SJuan Castillo 306f971622SJuan Castillo /* 31ccbf890eSJuan Castillo * Create a new key container 326f971622SJuan Castillo */ 33762f1ebeSMasahiro Yamada int key_new(key_t *key) 34ccbf890eSJuan Castillo { 35ccbf890eSJuan Castillo /* Create key pair container */ 36ccbf890eSJuan Castillo key->key = EVP_PKEY_new(); 37ccbf890eSJuan Castillo if (key->key == NULL) { 38ccbf890eSJuan Castillo return 0; 39ccbf890eSJuan Castillo } 40ccbf890eSJuan Castillo 41ccbf890eSJuan Castillo return 1; 42ccbf890eSJuan Castillo } 43ccbf890eSJuan Castillo 44*dfe0f4c2SJustin Chadwell static int key_create_rsa(key_t *key, int key_bits) 456f971622SJuan Castillo { 46742c4e14SMichalis Pappas BIGNUM *e; 47742c4e14SMichalis Pappas RSA *rsa = NULL; 486f971622SJuan Castillo 49742c4e14SMichalis Pappas e = BN_new(); 50742c4e14SMichalis Pappas if (e == NULL) { 51742c4e14SMichalis Pappas printf("Cannot create RSA exponent\n"); 52742c4e14SMichalis Pappas goto err; 53742c4e14SMichalis Pappas } 54742c4e14SMichalis Pappas 55742c4e14SMichalis Pappas if (!BN_set_word(e, RSA_F4)) { 56742c4e14SMichalis Pappas printf("Cannot assign RSA exponent\n"); 57742c4e14SMichalis Pappas goto err; 58742c4e14SMichalis Pappas } 59742c4e14SMichalis Pappas 60742c4e14SMichalis Pappas rsa = RSA_new(); 61ccbf890eSJuan Castillo if (rsa == NULL) { 62ccbf890eSJuan Castillo printf("Cannot create RSA key\n"); 63ccbf890eSJuan Castillo goto err; 64ccbf890eSJuan Castillo } 65742c4e14SMichalis Pappas 66*dfe0f4c2SJustin Chadwell if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) { 67742c4e14SMichalis Pappas printf("Cannot generate RSA key\n"); 68742c4e14SMichalis Pappas goto err; 69742c4e14SMichalis Pappas } 70742c4e14SMichalis Pappas 71ccbf890eSJuan Castillo if (!EVP_PKEY_assign_RSA(key->key, rsa)) { 726f971622SJuan Castillo printf("Cannot assign RSA key\n"); 73ccbf890eSJuan Castillo goto err; 74ccbf890eSJuan Castillo } 75ed2a76eaSJuan Castillo 7665ec13bcSJustin Chadwell BN_free(e); 77ed2a76eaSJuan Castillo return 1; 78ed2a76eaSJuan Castillo err: 79ed2a76eaSJuan Castillo RSA_free(rsa); 80742c4e14SMichalis Pappas BN_free(e); 81ed2a76eaSJuan Castillo return 0; 82ed2a76eaSJuan Castillo } 83ed2a76eaSJuan Castillo 84ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 85*dfe0f4c2SJustin Chadwell static int key_create_ecdsa(key_t *key, int key_bits) 86ed2a76eaSJuan Castillo { 87c893c733SMasahiro Yamada EC_KEY *ec; 88ed2a76eaSJuan Castillo 89ccbf890eSJuan Castillo ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 90ccbf890eSJuan Castillo if (ec == NULL) { 91ccbf890eSJuan Castillo printf("Cannot create EC key\n"); 92ccbf890eSJuan Castillo goto err; 93ccbf890eSJuan Castillo } 94ccbf890eSJuan Castillo if (!EC_KEY_generate_key(ec)) { 95ccbf890eSJuan Castillo printf("Cannot generate EC key\n"); 96ccbf890eSJuan Castillo goto err; 97ccbf890eSJuan Castillo } 98ccbf890eSJuan Castillo EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS); 99ccbf890eSJuan Castillo EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); 100ccbf890eSJuan Castillo if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) { 101ccbf890eSJuan Castillo printf("Cannot assign EC key\n"); 102ccbf890eSJuan Castillo goto err; 103ccbf890eSJuan Castillo } 1046f971622SJuan Castillo 105ccbf890eSJuan Castillo return 1; 106ccbf890eSJuan Castillo err: 107ccbf890eSJuan Castillo EC_KEY_free(ec); 108ed2a76eaSJuan Castillo return 0; 109ed2a76eaSJuan Castillo } 110ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 111ed2a76eaSJuan Castillo 112*dfe0f4c2SJustin Chadwell typedef int (*key_create_fn_t)(key_t *key, int key_bits); 113ed2a76eaSJuan Castillo static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { 1141727de0eSQixiang Xu key_create_rsa, /* KEY_ALG_RSA */ 1151727de0eSQixiang Xu key_create_rsa, /* KEY_ALG_RSA_1_5 */ 116ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 1171727de0eSQixiang Xu key_create_ecdsa, /* KEY_ALG_ECDSA */ 118ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 119ed2a76eaSJuan Castillo }; 120ed2a76eaSJuan Castillo 121*dfe0f4c2SJustin Chadwell int key_create(key_t *key, int type, int key_bits) 122ed2a76eaSJuan Castillo { 123ed2a76eaSJuan Castillo if (type >= KEY_ALG_MAX_NUM) { 124ed2a76eaSJuan Castillo printf("Invalid key type\n"); 125ed2a76eaSJuan Castillo return 0; 126ed2a76eaSJuan Castillo } 127ed2a76eaSJuan Castillo 128ed2a76eaSJuan Castillo if (key_create_fn[type]) { 129*dfe0f4c2SJustin Chadwell return key_create_fn[type](key, key_bits); 130ed2a76eaSJuan Castillo } 131ccbf890eSJuan Castillo 1326f971622SJuan Castillo return 0; 1336f971622SJuan Castillo } 1346f971622SJuan Castillo 135ccbf890eSJuan Castillo int key_load(key_t *key, unsigned int *err_code) 1366f971622SJuan Castillo { 137c893c733SMasahiro Yamada FILE *fp; 138c893c733SMasahiro Yamada EVP_PKEY *k; 1396f971622SJuan Castillo 1406f971622SJuan Castillo if (key->fn) { 1416f971622SJuan Castillo /* Load key from file */ 1426f971622SJuan Castillo fp = fopen(key->fn, "r"); 1436f971622SJuan Castillo if (fp) { 144ccbf890eSJuan Castillo k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); 1456f971622SJuan Castillo fclose(fp); 1466f971622SJuan Castillo if (k) { 147ccbf890eSJuan Castillo *err_code = KEY_ERR_NONE; 1486f971622SJuan Castillo return 1; 1496f971622SJuan Castillo } else { 150ccbf890eSJuan Castillo ERROR("Cannot load key from %s\n", key->fn); 151ccbf890eSJuan Castillo *err_code = KEY_ERR_LOAD; 1526f971622SJuan Castillo } 1536f971622SJuan Castillo } else { 154ccbf890eSJuan Castillo WARN("Cannot open file %s\n", key->fn); 155ccbf890eSJuan Castillo *err_code = KEY_ERR_OPEN; 1566f971622SJuan Castillo } 1576f971622SJuan Castillo } else { 158ccbf890eSJuan Castillo WARN("Key filename not specified\n"); 159ccbf890eSJuan Castillo *err_code = KEY_ERR_FILENAME; 1606f971622SJuan Castillo } 1616f971622SJuan Castillo 1626f971622SJuan Castillo return 0; 1636f971622SJuan Castillo } 1646f971622SJuan Castillo 1656f971622SJuan Castillo int key_store(key_t *key) 1666f971622SJuan Castillo { 167c893c733SMasahiro Yamada FILE *fp; 1686f971622SJuan Castillo 1696f971622SJuan Castillo if (key->fn) { 1706f971622SJuan Castillo fp = fopen(key->fn, "w"); 1716f971622SJuan Castillo if (fp) { 1726f971622SJuan Castillo PEM_write_PrivateKey(fp, key->key, 1736f971622SJuan Castillo NULL, NULL, 0, NULL, NULL); 1746f971622SJuan Castillo fclose(fp); 1756f971622SJuan Castillo return 1; 1766f971622SJuan Castillo } else { 1776f971622SJuan Castillo ERROR("Cannot create file %s\n", key->fn); 1786f971622SJuan Castillo } 1796f971622SJuan Castillo } else { 1806f971622SJuan Castillo ERROR("Key filename not specified\n"); 1816f971622SJuan Castillo } 1826f971622SJuan Castillo 1836f971622SJuan Castillo return 0; 1846f971622SJuan Castillo } 185ad2c1a9aSJuan Castillo 186ad2c1a9aSJuan Castillo int key_init(void) 187ad2c1a9aSJuan Castillo { 188159807e2SJuan Castillo cmd_opt_t cmd_opt; 189ad2c1a9aSJuan Castillo key_t *key; 190ad2c1a9aSJuan Castillo unsigned int i; 191ad2c1a9aSJuan Castillo 192ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 193ad2c1a9aSJuan Castillo key = &keys[i]; 194ad2c1a9aSJuan Castillo if (key->opt != NULL) { 195159807e2SJuan Castillo cmd_opt.long_opt.name = key->opt; 196159807e2SJuan Castillo cmd_opt.long_opt.has_arg = required_argument; 197159807e2SJuan Castillo cmd_opt.long_opt.flag = NULL; 198159807e2SJuan Castillo cmd_opt.long_opt.val = CMD_OPT_KEY; 199159807e2SJuan Castillo cmd_opt.help_msg = key->help_msg; 200159807e2SJuan Castillo cmd_opt_add(&cmd_opt); 201ad2c1a9aSJuan Castillo } 202ad2c1a9aSJuan Castillo } 203ad2c1a9aSJuan Castillo 204c893c733SMasahiro Yamada return 0; 205ad2c1a9aSJuan Castillo } 206ad2c1a9aSJuan Castillo 207ad2c1a9aSJuan Castillo key_t *key_get_by_opt(const char *opt) 208ad2c1a9aSJuan Castillo { 209c893c733SMasahiro Yamada key_t *key; 210ad2c1a9aSJuan Castillo unsigned int i; 211ad2c1a9aSJuan Castillo 212ad2c1a9aSJuan Castillo /* Sequential search. This is not a performance concern since the number 213ad2c1a9aSJuan Castillo * of keys is bounded and the code runs on a host machine */ 214ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 215ad2c1a9aSJuan Castillo key = &keys[i]; 216ad2c1a9aSJuan Castillo if (0 == strcmp(key->opt, opt)) { 217ad2c1a9aSJuan Castillo return key; 218ad2c1a9aSJuan Castillo } 219ad2c1a9aSJuan Castillo } 220ad2c1a9aSJuan Castillo 221ad2c1a9aSJuan Castillo return NULL; 222ad2c1a9aSJuan Castillo } 223