16f971622SJuan Castillo /* 2bb41eb7aSMasahiro Yamada * Copyright (c) 2015-2017, 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 44ed2a76eaSJuan Castillo static int key_create_rsa(key_t *key) 456f971622SJuan Castillo { 46*742c4e14SMichalis Pappas BIGNUM *e; 47*742c4e14SMichalis Pappas RSA *rsa = NULL; 486f971622SJuan Castillo 49*742c4e14SMichalis Pappas e = BN_new(); 50*742c4e14SMichalis Pappas if (e == NULL) { 51*742c4e14SMichalis Pappas printf("Cannot create RSA exponent\n"); 52*742c4e14SMichalis Pappas goto err; 53*742c4e14SMichalis Pappas } 54*742c4e14SMichalis Pappas 55*742c4e14SMichalis Pappas if (!BN_set_word(e, RSA_F4)) { 56*742c4e14SMichalis Pappas printf("Cannot assign RSA exponent\n"); 57*742c4e14SMichalis Pappas goto err; 58*742c4e14SMichalis Pappas } 59*742c4e14SMichalis Pappas 60*742c4e14SMichalis Pappas rsa = RSA_new(); 61ccbf890eSJuan Castillo if (rsa == NULL) { 62ccbf890eSJuan Castillo printf("Cannot create RSA key\n"); 63ccbf890eSJuan Castillo goto err; 64ccbf890eSJuan Castillo } 65*742c4e14SMichalis Pappas 66*742c4e14SMichalis Pappas if (!RSA_generate_key_ex(rsa, RSA_KEY_BITS, e, NULL)) { 67*742c4e14SMichalis Pappas printf("Cannot generate RSA key\n"); 68*742c4e14SMichalis Pappas goto err; 69*742c4e14SMichalis Pappas } 70*742c4e14SMichalis 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 76ed2a76eaSJuan Castillo return 1; 77ed2a76eaSJuan Castillo err: 78ed2a76eaSJuan Castillo RSA_free(rsa); 79*742c4e14SMichalis Pappas BN_free(e); 80ed2a76eaSJuan Castillo return 0; 81ed2a76eaSJuan Castillo } 82ed2a76eaSJuan Castillo 83ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 84ed2a76eaSJuan Castillo static int key_create_ecdsa(key_t *key) 85ed2a76eaSJuan Castillo { 86c893c733SMasahiro Yamada EC_KEY *ec; 87ed2a76eaSJuan Castillo 88ccbf890eSJuan Castillo ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 89ccbf890eSJuan Castillo if (ec == NULL) { 90ccbf890eSJuan Castillo printf("Cannot create EC key\n"); 91ccbf890eSJuan Castillo goto err; 92ccbf890eSJuan Castillo } 93ccbf890eSJuan Castillo if (!EC_KEY_generate_key(ec)) { 94ccbf890eSJuan Castillo printf("Cannot generate EC key\n"); 95ccbf890eSJuan Castillo goto err; 96ccbf890eSJuan Castillo } 97ccbf890eSJuan Castillo EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS); 98ccbf890eSJuan Castillo EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); 99ccbf890eSJuan Castillo if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) { 100ccbf890eSJuan Castillo printf("Cannot assign EC key\n"); 101ccbf890eSJuan Castillo goto err; 102ccbf890eSJuan Castillo } 1036f971622SJuan Castillo 104ccbf890eSJuan Castillo return 1; 105ccbf890eSJuan Castillo err: 106ccbf890eSJuan Castillo EC_KEY_free(ec); 107ed2a76eaSJuan Castillo return 0; 108ed2a76eaSJuan Castillo } 109ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 110ed2a76eaSJuan Castillo 111ed2a76eaSJuan Castillo typedef int (*key_create_fn_t)(key_t *key); 112ed2a76eaSJuan Castillo static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { 113ed2a76eaSJuan Castillo key_create_rsa, 114ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 115ed2a76eaSJuan Castillo key_create_ecdsa, 116ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 117ed2a76eaSJuan Castillo }; 118ed2a76eaSJuan Castillo 119ed2a76eaSJuan Castillo int key_create(key_t *key, int type) 120ed2a76eaSJuan Castillo { 121ed2a76eaSJuan Castillo if (type >= KEY_ALG_MAX_NUM) { 122ed2a76eaSJuan Castillo printf("Invalid key type\n"); 123ed2a76eaSJuan Castillo return 0; 124ed2a76eaSJuan Castillo } 125ed2a76eaSJuan Castillo 126ed2a76eaSJuan Castillo if (key_create_fn[type]) { 127ed2a76eaSJuan Castillo return key_create_fn[type](key); 128ed2a76eaSJuan Castillo } 129ccbf890eSJuan Castillo 1306f971622SJuan Castillo return 0; 1316f971622SJuan Castillo } 1326f971622SJuan Castillo 133ccbf890eSJuan Castillo int key_load(key_t *key, unsigned int *err_code) 1346f971622SJuan Castillo { 135c893c733SMasahiro Yamada FILE *fp; 136c893c733SMasahiro Yamada EVP_PKEY *k; 1376f971622SJuan Castillo 1386f971622SJuan Castillo if (key->fn) { 1396f971622SJuan Castillo /* Load key from file */ 1406f971622SJuan Castillo fp = fopen(key->fn, "r"); 1416f971622SJuan Castillo if (fp) { 142ccbf890eSJuan Castillo k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); 1436f971622SJuan Castillo fclose(fp); 1446f971622SJuan Castillo if (k) { 145ccbf890eSJuan Castillo *err_code = KEY_ERR_NONE; 1466f971622SJuan Castillo return 1; 1476f971622SJuan Castillo } else { 148ccbf890eSJuan Castillo ERROR("Cannot load key from %s\n", key->fn); 149ccbf890eSJuan Castillo *err_code = KEY_ERR_LOAD; 1506f971622SJuan Castillo } 1516f971622SJuan Castillo } else { 152ccbf890eSJuan Castillo WARN("Cannot open file %s\n", key->fn); 153ccbf890eSJuan Castillo *err_code = KEY_ERR_OPEN; 1546f971622SJuan Castillo } 1556f971622SJuan Castillo } else { 156ccbf890eSJuan Castillo WARN("Key filename not specified\n"); 157ccbf890eSJuan Castillo *err_code = KEY_ERR_FILENAME; 1586f971622SJuan Castillo } 1596f971622SJuan Castillo 1606f971622SJuan Castillo return 0; 1616f971622SJuan Castillo } 1626f971622SJuan Castillo 1636f971622SJuan Castillo int key_store(key_t *key) 1646f971622SJuan Castillo { 165c893c733SMasahiro Yamada FILE *fp; 1666f971622SJuan Castillo 1676f971622SJuan Castillo if (key->fn) { 1686f971622SJuan Castillo fp = fopen(key->fn, "w"); 1696f971622SJuan Castillo if (fp) { 1706f971622SJuan Castillo PEM_write_PrivateKey(fp, key->key, 1716f971622SJuan Castillo NULL, NULL, 0, NULL, NULL); 1726f971622SJuan Castillo fclose(fp); 1736f971622SJuan Castillo return 1; 1746f971622SJuan Castillo } else { 1756f971622SJuan Castillo ERROR("Cannot create file %s\n", key->fn); 1766f971622SJuan Castillo } 1776f971622SJuan Castillo } else { 1786f971622SJuan Castillo ERROR("Key filename not specified\n"); 1796f971622SJuan Castillo } 1806f971622SJuan Castillo 1816f971622SJuan Castillo return 0; 1826f971622SJuan Castillo } 183ad2c1a9aSJuan Castillo 184ad2c1a9aSJuan Castillo int key_init(void) 185ad2c1a9aSJuan Castillo { 186159807e2SJuan Castillo cmd_opt_t cmd_opt; 187ad2c1a9aSJuan Castillo key_t *key; 188ad2c1a9aSJuan Castillo unsigned int i; 189ad2c1a9aSJuan Castillo 190ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 191ad2c1a9aSJuan Castillo key = &keys[i]; 192ad2c1a9aSJuan Castillo if (key->opt != NULL) { 193159807e2SJuan Castillo cmd_opt.long_opt.name = key->opt; 194159807e2SJuan Castillo cmd_opt.long_opt.has_arg = required_argument; 195159807e2SJuan Castillo cmd_opt.long_opt.flag = NULL; 196159807e2SJuan Castillo cmd_opt.long_opt.val = CMD_OPT_KEY; 197159807e2SJuan Castillo cmd_opt.help_msg = key->help_msg; 198159807e2SJuan Castillo cmd_opt_add(&cmd_opt); 199ad2c1a9aSJuan Castillo } 200ad2c1a9aSJuan Castillo } 201ad2c1a9aSJuan Castillo 202c893c733SMasahiro Yamada return 0; 203ad2c1a9aSJuan Castillo } 204ad2c1a9aSJuan Castillo 205ad2c1a9aSJuan Castillo key_t *key_get_by_opt(const char *opt) 206ad2c1a9aSJuan Castillo { 207c893c733SMasahiro Yamada key_t *key; 208ad2c1a9aSJuan Castillo unsigned int i; 209ad2c1a9aSJuan Castillo 210ad2c1a9aSJuan Castillo /* Sequential search. This is not a performance concern since the number 211ad2c1a9aSJuan Castillo * of keys is bounded and the code runs on a host machine */ 212ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 213ad2c1a9aSJuan Castillo key = &keys[i]; 214ad2c1a9aSJuan Castillo if (0 == strcmp(key->opt, opt)) { 215ad2c1a9aSJuan Castillo return key; 216ad2c1a9aSJuan Castillo } 217ad2c1a9aSJuan Castillo } 218ad2c1a9aSJuan Castillo 219ad2c1a9aSJuan Castillo return NULL; 220ad2c1a9aSJuan Castillo } 221