16f971622SJuan Castillo /* 26f971622SJuan Castillo * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 36f971622SJuan Castillo * 46f971622SJuan Castillo * Redistribution and use in source and binary forms, with or without 56f971622SJuan Castillo * modification, are permitted provided that the following conditions are met: 66f971622SJuan Castillo * 76f971622SJuan Castillo * Redistributions of source code must retain the above copyright notice, this 86f971622SJuan Castillo * list of conditions and the following disclaimer. 96f971622SJuan Castillo * 106f971622SJuan Castillo * Redistributions in binary form must reproduce the above copyright notice, 116f971622SJuan Castillo * this list of conditions and the following disclaimer in the documentation 126f971622SJuan Castillo * and/or other materials provided with the distribution. 136f971622SJuan Castillo * 146f971622SJuan Castillo * Neither the name of ARM nor the names of its contributors may be used 156f971622SJuan Castillo * to endorse or promote products derived from this software without specific 166f971622SJuan Castillo * prior written permission. 176f971622SJuan Castillo * 186f971622SJuan Castillo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 196f971622SJuan Castillo * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 206f971622SJuan Castillo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 216f971622SJuan Castillo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 226f971622SJuan Castillo * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 236f971622SJuan Castillo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 246f971622SJuan Castillo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 256f971622SJuan Castillo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 266f971622SJuan Castillo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 276f971622SJuan Castillo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 286f971622SJuan Castillo * POSSIBILITY OF SUCH DAMAGE. 296f971622SJuan Castillo */ 306f971622SJuan Castillo 316f971622SJuan Castillo #include <getopt.h> 326f971622SJuan Castillo #include <stdio.h> 336f971622SJuan Castillo #include <stdlib.h> 346f971622SJuan Castillo #include <string.h> 356f971622SJuan Castillo 366f971622SJuan Castillo #include <openssl/conf.h> 376f971622SJuan Castillo #include <openssl/evp.h> 386f971622SJuan Castillo #include <openssl/pem.h> 396f971622SJuan Castillo 406f971622SJuan Castillo #include "cert.h" 41ad2c1a9aSJuan Castillo #include "cmd_opt.h" 426f971622SJuan Castillo #include "debug.h" 436f971622SJuan Castillo #include "key.h" 446f971622SJuan Castillo #include "platform_oid.h" 456f971622SJuan Castillo #include "sha.h" 466f971622SJuan Castillo 476f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 486f971622SJuan Castillo 496f971622SJuan Castillo /* 50ccbf890eSJuan Castillo * Create a new key container 516f971622SJuan Castillo */ 52*762f1ebeSMasahiro Yamada int key_new(key_t *key) 53ccbf890eSJuan Castillo { 54ccbf890eSJuan Castillo /* Create key pair container */ 55ccbf890eSJuan Castillo key->key = EVP_PKEY_new(); 56ccbf890eSJuan Castillo if (key->key == NULL) { 57ccbf890eSJuan Castillo return 0; 58ccbf890eSJuan Castillo } 59ccbf890eSJuan Castillo 60ccbf890eSJuan Castillo return 1; 61ccbf890eSJuan Castillo } 62ccbf890eSJuan Castillo 63ed2a76eaSJuan Castillo static int key_create_rsa(key_t *key) 646f971622SJuan Castillo { 656f971622SJuan Castillo RSA *rsa = NULL; 666f971622SJuan Castillo 676f971622SJuan Castillo rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL); 68ccbf890eSJuan Castillo if (rsa == NULL) { 69ccbf890eSJuan Castillo printf("Cannot create RSA key\n"); 70ccbf890eSJuan Castillo goto err; 71ccbf890eSJuan Castillo } 72ccbf890eSJuan Castillo if (!EVP_PKEY_assign_RSA(key->key, rsa)) { 736f971622SJuan Castillo printf("Cannot assign RSA key\n"); 74ccbf890eSJuan Castillo goto err; 75ccbf890eSJuan Castillo } 76ed2a76eaSJuan Castillo 77ed2a76eaSJuan Castillo return 1; 78ed2a76eaSJuan Castillo err: 79ed2a76eaSJuan Castillo RSA_free(rsa); 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 { 86ed2a76eaSJuan Castillo EC_KEY *ec = NULL; 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 { 1356f971622SJuan Castillo FILE *fp = NULL; 1366f971622SJuan Castillo EVP_PKEY *k = NULL; 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 { 1656f971622SJuan Castillo FILE *fp = NULL; 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 int rc = 0; 189ad2c1a9aSJuan Castillo unsigned int i; 190ad2c1a9aSJuan Castillo 191ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 192ad2c1a9aSJuan Castillo key = &keys[i]; 193ad2c1a9aSJuan Castillo if (key->opt != NULL) { 194159807e2SJuan Castillo cmd_opt.long_opt.name = key->opt; 195159807e2SJuan Castillo cmd_opt.long_opt.has_arg = required_argument; 196159807e2SJuan Castillo cmd_opt.long_opt.flag = NULL; 197159807e2SJuan Castillo cmd_opt.long_opt.val = CMD_OPT_KEY; 198159807e2SJuan Castillo cmd_opt.help_msg = key->help_msg; 199159807e2SJuan Castillo cmd_opt_add(&cmd_opt); 200ad2c1a9aSJuan Castillo } 201ad2c1a9aSJuan Castillo } 202ad2c1a9aSJuan Castillo 203ad2c1a9aSJuan Castillo return rc; 204ad2c1a9aSJuan Castillo } 205ad2c1a9aSJuan Castillo 206ad2c1a9aSJuan Castillo key_t *key_get_by_opt(const char *opt) 207ad2c1a9aSJuan Castillo { 208ad2c1a9aSJuan Castillo key_t *key = NULL; 209ad2c1a9aSJuan Castillo unsigned int i; 210ad2c1a9aSJuan Castillo 211ad2c1a9aSJuan Castillo /* Sequential search. This is not a performance concern since the number 212ad2c1a9aSJuan Castillo * of keys is bounded and the code runs on a host machine */ 213ad2c1a9aSJuan Castillo for (i = 0; i < num_keys; i++) { 214ad2c1a9aSJuan Castillo key = &keys[i]; 215ad2c1a9aSJuan Castillo if (0 == strcmp(key->opt, opt)) { 216ad2c1a9aSJuan Castillo return key; 217ad2c1a9aSJuan Castillo } 218ad2c1a9aSJuan Castillo } 219ad2c1a9aSJuan Castillo 220ad2c1a9aSJuan Castillo return NULL; 221ad2c1a9aSJuan Castillo } 222