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" 416f971622SJuan Castillo #include "debug.h" 426f971622SJuan Castillo #include "key.h" 436f971622SJuan Castillo #include "platform_oid.h" 446f971622SJuan Castillo #include "sha.h" 456f971622SJuan Castillo 466f971622SJuan Castillo #define MAX_FILENAME_LEN 1024 476f971622SJuan Castillo 486f971622SJuan Castillo /* 49*ccbf890eSJuan Castillo * Create a new key container 506f971622SJuan Castillo */ 51*ccbf890eSJuan Castillo static int key_new(key_t *key) 52*ccbf890eSJuan Castillo { 53*ccbf890eSJuan Castillo /* Create key pair container */ 54*ccbf890eSJuan Castillo key->key = EVP_PKEY_new(); 55*ccbf890eSJuan Castillo if (key->key == NULL) { 56*ccbf890eSJuan Castillo return 0; 57*ccbf890eSJuan Castillo } 58*ccbf890eSJuan Castillo 59*ccbf890eSJuan Castillo return 1; 60*ccbf890eSJuan Castillo } 61*ccbf890eSJuan Castillo 62*ccbf890eSJuan Castillo int key_create(key_t *key, int type) 636f971622SJuan Castillo { 646f971622SJuan Castillo RSA *rsa = NULL; 65*ccbf890eSJuan Castillo EC_KEY *ec = NULL; 666f971622SJuan Castillo 67*ccbf890eSJuan Castillo /* Create OpenSSL key container */ 68*ccbf890eSJuan Castillo if (!key_new(key)) { 69*ccbf890eSJuan Castillo goto err; 706f971622SJuan Castillo } 716f971622SJuan Castillo 72*ccbf890eSJuan Castillo switch (type) { 73*ccbf890eSJuan Castillo case KEY_ALG_RSA: 746f971622SJuan Castillo /* Generate a new RSA key */ 756f971622SJuan Castillo rsa = RSA_generate_key(RSA_KEY_BITS, RSA_F4, NULL, NULL); 76*ccbf890eSJuan Castillo if (rsa == NULL) { 77*ccbf890eSJuan Castillo printf("Cannot create RSA key\n"); 78*ccbf890eSJuan Castillo goto err; 79*ccbf890eSJuan Castillo } 80*ccbf890eSJuan Castillo if (!EVP_PKEY_assign_RSA(key->key, rsa)) { 816f971622SJuan Castillo printf("Cannot assign RSA key\n"); 82*ccbf890eSJuan Castillo goto err; 83*ccbf890eSJuan Castillo } 84*ccbf890eSJuan Castillo break; 85*ccbf890eSJuan Castillo case KEY_ALG_ECDSA: 86*ccbf890eSJuan Castillo /* Generate a new ECDSA key */ 87*ccbf890eSJuan Castillo ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 88*ccbf890eSJuan Castillo if (ec == NULL) { 89*ccbf890eSJuan Castillo printf("Cannot create EC key\n"); 90*ccbf890eSJuan Castillo goto err; 91*ccbf890eSJuan Castillo } 92*ccbf890eSJuan Castillo if (!EC_KEY_generate_key(ec)) { 93*ccbf890eSJuan Castillo printf("Cannot generate EC key\n"); 94*ccbf890eSJuan Castillo goto err; 95*ccbf890eSJuan Castillo } 96*ccbf890eSJuan Castillo EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS); 97*ccbf890eSJuan Castillo EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); 98*ccbf890eSJuan Castillo if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) { 99*ccbf890eSJuan Castillo printf("Cannot assign EC key\n"); 100*ccbf890eSJuan Castillo goto err; 101*ccbf890eSJuan Castillo } 102*ccbf890eSJuan Castillo break; 103*ccbf890eSJuan Castillo default: 104*ccbf890eSJuan Castillo goto err; 1056f971622SJuan Castillo } 1066f971622SJuan Castillo 107*ccbf890eSJuan Castillo return 1; 108*ccbf890eSJuan Castillo 109*ccbf890eSJuan Castillo err: 110*ccbf890eSJuan Castillo RSA_free(rsa); 111*ccbf890eSJuan Castillo EC_KEY_free(ec); 112*ccbf890eSJuan Castillo 1136f971622SJuan Castillo return 0; 1146f971622SJuan Castillo } 1156f971622SJuan Castillo 116*ccbf890eSJuan Castillo int key_load(key_t *key, unsigned int *err_code) 1176f971622SJuan Castillo { 1186f971622SJuan Castillo FILE *fp = NULL; 1196f971622SJuan Castillo EVP_PKEY *k = NULL; 1206f971622SJuan Castillo 121*ccbf890eSJuan Castillo /* Create OpenSSL key container */ 122*ccbf890eSJuan Castillo if (!key_new(key)) { 123*ccbf890eSJuan Castillo *err_code = KEY_ERR_MALLOC; 1246f971622SJuan Castillo return 0; 1256f971622SJuan Castillo } 1266f971622SJuan Castillo 1276f971622SJuan Castillo if (key->fn) { 1286f971622SJuan Castillo /* Load key from file */ 1296f971622SJuan Castillo fp = fopen(key->fn, "r"); 1306f971622SJuan Castillo if (fp) { 131*ccbf890eSJuan Castillo k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); 1326f971622SJuan Castillo fclose(fp); 1336f971622SJuan Castillo if (k) { 134*ccbf890eSJuan Castillo *err_code = KEY_ERR_NONE; 1356f971622SJuan Castillo return 1; 1366f971622SJuan Castillo } else { 137*ccbf890eSJuan Castillo ERROR("Cannot load key from %s\n", key->fn); 138*ccbf890eSJuan Castillo *err_code = KEY_ERR_LOAD; 1396f971622SJuan Castillo } 1406f971622SJuan Castillo } else { 141*ccbf890eSJuan Castillo WARN("Cannot open file %s\n", key->fn); 142*ccbf890eSJuan Castillo *err_code = KEY_ERR_OPEN; 1436f971622SJuan Castillo } 1446f971622SJuan Castillo } else { 145*ccbf890eSJuan Castillo WARN("Key filename not specified\n"); 146*ccbf890eSJuan Castillo *err_code = KEY_ERR_FILENAME; 1476f971622SJuan Castillo } 1486f971622SJuan Castillo 1496f971622SJuan Castillo return 0; 1506f971622SJuan Castillo } 1516f971622SJuan Castillo 1526f971622SJuan Castillo int key_store(key_t *key) 1536f971622SJuan Castillo { 1546f971622SJuan Castillo FILE *fp = NULL; 1556f971622SJuan Castillo 1566f971622SJuan Castillo if (key->fn) { 1576f971622SJuan Castillo fp = fopen(key->fn, "w"); 1586f971622SJuan Castillo if (fp) { 1596f971622SJuan Castillo PEM_write_PrivateKey(fp, key->key, 1606f971622SJuan Castillo NULL, NULL, 0, NULL, NULL); 1616f971622SJuan Castillo fclose(fp); 1626f971622SJuan Castillo return 1; 1636f971622SJuan Castillo } else { 1646f971622SJuan Castillo ERROR("Cannot create file %s\n", key->fn); 1656f971622SJuan Castillo } 1666f971622SJuan Castillo } else { 1676f971622SJuan Castillo ERROR("Key filename not specified\n"); 1686f971622SJuan Castillo } 1696f971622SJuan Castillo 1706f971622SJuan Castillo return 0; 1716f971622SJuan Castillo } 172