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 { 46c893c733SMasahiro Yamada RSA *rsa; 476f971622SJuan Castillo 486f971622SJuan Castillo rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL); 49ccbf890eSJuan Castillo if (rsa == NULL) { 50ccbf890eSJuan Castillo printf("Cannot create RSA key\n"); 51ccbf890eSJuan Castillo goto err; 52ccbf890eSJuan Castillo } 53ccbf890eSJuan Castillo if (!EVP_PKEY_assign_RSA(key->key, rsa)) { 546f971622SJuan Castillo printf("Cannot assign RSA key\n"); 55ccbf890eSJuan Castillo goto err; 56ccbf890eSJuan Castillo } 57ed2a76eaSJuan Castillo 58ed2a76eaSJuan Castillo return 1; 59ed2a76eaSJuan Castillo err: 60ed2a76eaSJuan Castillo RSA_free(rsa); 61ed2a76eaSJuan Castillo return 0; 62ed2a76eaSJuan Castillo } 63ed2a76eaSJuan Castillo 64ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 65ed2a76eaSJuan Castillo static int key_create_ecdsa(key_t *key) 66ed2a76eaSJuan Castillo { 67c893c733SMasahiro Yamada EC_KEY *ec; 68ed2a76eaSJuan Castillo 69ccbf890eSJuan Castillo ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 70ccbf890eSJuan Castillo if (ec == NULL) { 71ccbf890eSJuan Castillo printf("Cannot create EC key\n"); 72ccbf890eSJuan Castillo goto err; 73ccbf890eSJuan Castillo } 74ccbf890eSJuan Castillo if (!EC_KEY_generate_key(ec)) { 75ccbf890eSJuan Castillo printf("Cannot generate EC key\n"); 76ccbf890eSJuan Castillo goto err; 77ccbf890eSJuan Castillo } 78ccbf890eSJuan Castillo EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS); 79ccbf890eSJuan Castillo EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); 80ccbf890eSJuan Castillo if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) { 81ccbf890eSJuan Castillo printf("Cannot assign EC key\n"); 82ccbf890eSJuan Castillo goto err; 83ccbf890eSJuan Castillo } 846f971622SJuan Castillo 85ccbf890eSJuan Castillo return 1; 86ccbf890eSJuan Castillo err: 87ccbf890eSJuan Castillo EC_KEY_free(ec); 88ed2a76eaSJuan Castillo return 0; 89ed2a76eaSJuan Castillo } 90ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 91ed2a76eaSJuan Castillo 92ed2a76eaSJuan Castillo typedef int (*key_create_fn_t)(key_t *key); 93ed2a76eaSJuan Castillo static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { 94*1727de0eSQixiang Xu key_create_rsa, /* KEY_ALG_RSA */ 95*1727de0eSQixiang Xu key_create_rsa, /* KEY_ALG_RSA_1_5 */ 96ed2a76eaSJuan Castillo #ifndef OPENSSL_NO_EC 97*1727de0eSQixiang Xu key_create_ecdsa, /* KEY_ALG_ECDSA */ 98ed2a76eaSJuan Castillo #endif /* OPENSSL_NO_EC */ 99ed2a76eaSJuan Castillo }; 100ed2a76eaSJuan Castillo 101ed2a76eaSJuan Castillo int key_create(key_t *key, int type) 102ed2a76eaSJuan Castillo { 103ed2a76eaSJuan Castillo if (type >= KEY_ALG_MAX_NUM) { 104ed2a76eaSJuan Castillo printf("Invalid key type\n"); 105ed2a76eaSJuan Castillo return 0; 106ed2a76eaSJuan Castillo } 107ed2a76eaSJuan Castillo 108ed2a76eaSJuan Castillo if (key_create_fn[type]) { 109ed2a76eaSJuan Castillo return key_create_fn[type](key); 110ed2a76eaSJuan Castillo } 111ccbf890eSJuan Castillo 1126f971622SJuan Castillo return 0; 1136f971622SJuan Castillo } 1146f971622SJuan Castillo 115ccbf890eSJuan Castillo int key_load(key_t *key, unsigned int *err_code) 1166f971622SJuan Castillo { 117c893c733SMasahiro Yamada FILE *fp; 118c893c733SMasahiro Yamada EVP_PKEY *k; 1196f971622SJuan Castillo 1206f971622SJuan Castillo if (key->fn) { 1216f971622SJuan Castillo /* Load key from file */ 1226f971622SJuan Castillo fp = fopen(key->fn, "r"); 1236f971622SJuan Castillo if (fp) { 124ccbf890eSJuan Castillo k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); 1256f971622SJuan Castillo fclose(fp); 1266f971622SJuan Castillo if (k) { 127ccbf890eSJuan Castillo *err_code = KEY_ERR_NONE; 1286f971622SJuan Castillo return 1; 1296f971622SJuan Castillo } else { 130ccbf890eSJuan Castillo ERROR("Cannot load key from %s\n", key->fn); 131ccbf890eSJuan Castillo *err_code = KEY_ERR_LOAD; 1326f971622SJuan Castillo } 1336f971622SJuan Castillo } else { 134ccbf890eSJuan Castillo WARN("Cannot open file %s\n", key->fn); 135ccbf890eSJuan Castillo *err_code = KEY_ERR_OPEN; 1366f971622SJuan Castillo } 1376f971622SJuan Castillo } else { 138ccbf890eSJuan Castillo WARN("Key filename not specified\n"); 139ccbf890eSJuan Castillo *err_code = KEY_ERR_FILENAME; 1406f971622SJuan Castillo } 1416f971622SJuan Castillo 1426f971622SJuan Castillo return 0; 1436f971622SJuan Castillo } 1446f971622SJuan Castillo 1456f971622SJuan Castillo int key_store(key_t *key) 1466f971622SJuan Castillo { 147c893c733SMasahiro Yamada FILE *fp; 1486f971622SJuan Castillo 1496f971622SJuan Castillo if (key->fn) { 1506f971622SJuan Castillo fp = fopen(key->fn, "w"); 1516f971622SJuan Castillo if (fp) { 1526f971622SJuan Castillo PEM_write_PrivateKey(fp, key->key, 1536f971622SJuan Castillo NULL, NULL, 0, NULL, NULL); 1546f971622SJuan Castillo fclose(fp); 1556f971622SJuan Castillo return 1; 1566f971622SJuan Castillo } else { 1576f971622SJuan Castillo ERROR("Cannot create file %s\n", key->fn); 1586f971622SJuan Castillo } 1596f971622SJuan Castillo } else { 1606f971622SJuan Castillo ERROR("Key filename not specified\n"); 1616f971622SJuan Castillo } 1626f971622SJuan Castillo 1636f971622SJuan Castillo return 0; 1646f971622SJuan Castillo } 165ad2c1a9aSJuan Castillo 166ad2c1a9aSJuan Castillo int key_init(void) 167ad2c1a9aSJuan Castillo { 168159807e2SJuan Castillo cmd_opt_t cmd_opt; 169ad2c1a9aSJuan Castillo key_t *key; 170ad2c1a9aSJuan Castillo unsigned int i; 171ad2c1a9aSJuan Castillo 172ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 173ad2c1a9aSJuan Castillo key = &keys[i]; 174ad2c1a9aSJuan Castillo if (key->opt != NULL) { 175159807e2SJuan Castillo cmd_opt.long_opt.name = key->opt; 176159807e2SJuan Castillo cmd_opt.long_opt.has_arg = required_argument; 177159807e2SJuan Castillo cmd_opt.long_opt.flag = NULL; 178159807e2SJuan Castillo cmd_opt.long_opt.val = CMD_OPT_KEY; 179159807e2SJuan Castillo cmd_opt.help_msg = key->help_msg; 180159807e2SJuan Castillo cmd_opt_add(&cmd_opt); 181ad2c1a9aSJuan Castillo } 182ad2c1a9aSJuan Castillo } 183ad2c1a9aSJuan Castillo 184c893c733SMasahiro Yamada return 0; 185ad2c1a9aSJuan Castillo } 186ad2c1a9aSJuan Castillo 187ad2c1a9aSJuan Castillo key_t *key_get_by_opt(const char *opt) 188ad2c1a9aSJuan Castillo { 189c893c733SMasahiro Yamada key_t *key; 190ad2c1a9aSJuan Castillo unsigned int i; 191ad2c1a9aSJuan Castillo 192ad2c1a9aSJuan Castillo /* Sequential search. This is not a performance concern since the number 193ad2c1a9aSJuan Castillo * of keys is bounded and the code runs on a host machine */ 194ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 195ad2c1a9aSJuan Castillo key = &keys[i]; 196ad2c1a9aSJuan Castillo if (0 == strcmp(key->opt, opt)) { 197ad2c1a9aSJuan Castillo return key; 198ad2c1a9aSJuan Castillo } 199ad2c1a9aSJuan Castillo } 200ad2c1a9aSJuan Castillo 201ad2c1a9aSJuan Castillo return NULL; 202ad2c1a9aSJuan Castillo } 203