1 /* $Id: key.c,v 1.2 2019/06/17 15:41:59 florian Exp $ */ 2 /* 3 * Copyright (c) 2019 Renaud Allard <renaud@allard.it> 4 * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <err.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 23 #include <openssl/evp.h> 24 #include <openssl/pem.h> 25 #include <openssl/rsa.h> 26 #include <openssl/ecdsa.h> 27 #include <openssl/ec.h> 28 #include <openssl/obj_mac.h> 29 30 #include "key.h" 31 32 /* 33 * Default number of bits when creating a new RSA key. 34 */ 35 #define KBITS 4096 36 #define ECCTYPE NID_secp384r1 37 38 /* 39 * Create an RSA key with the default KBITS number of bits. 40 */ 41 EVP_PKEY * 42 rsa_key_create(FILE *f, const char *fname) 43 { 44 EVP_PKEY_CTX *ctx = NULL; 45 EVP_PKEY *pkey = NULL; 46 47 /* First, create the context and the key. */ 48 49 if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) { 50 warnx("EVP_PKEY_CTX_new_id"); 51 goto err; 52 } else if (EVP_PKEY_keygen_init(ctx) <= 0) { 53 warnx("EVP_PKEY_keygen_init"); 54 goto err; 55 } else if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) { 56 warnx("EVP_PKEY_set_rsa_keygen_bits"); 57 goto err; 58 } else if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { 59 warnx("EVP_PKEY_keygen"); 60 goto err; 61 } 62 63 /* Serialise the key to the disc. */ 64 65 if (PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) 66 goto out; 67 68 warnx("%s: PEM_write_PrivateKey", fname); 69 70 err: 71 EVP_PKEY_free(pkey); 72 pkey = NULL; 73 out: 74 EVP_PKEY_CTX_free(ctx); 75 return pkey; 76 } 77 78 EVP_PKEY * 79 ec_key_create(FILE *f, const char *fname) 80 { 81 EC_KEY *eckey = NULL; 82 EVP_PKEY *pkey = NULL; 83 84 if ((eckey = EC_KEY_new_by_curve_name(ECCTYPE)) == NULL ) { 85 warnx("EC_KEY_new_by_curve_name"); 86 goto err; 87 } 88 89 if (!EC_KEY_generate_key(eckey)) { 90 warnx("EC_KEY_generate_key"); 91 goto err; 92 } 93 94 /* set OPENSSL_EC_NAMED_CURVE to be able to load the key */ 95 96 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); 97 98 /* Serialise the key to the disc in EC format */ 99 100 if (!PEM_write_ECPrivateKey(f, eckey, NULL, NULL, 0, NULL, NULL)) { 101 warnx("PEM_write_ECPrivateKey"); 102 goto err; 103 } 104 105 /* Convert the EC key into a PKEY structure */ 106 107 if ((pkey=EVP_PKEY_new()) == NULL) { 108 warnx("EVP_PKEY_new"); 109 goto err; 110 } 111 if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 112 warnx("EVP_PKEY_assign_EC_KEY"); 113 goto err; 114 } 115 116 warnx("%s: PEM_write_ECPrivateKey", fname); 117 118 goto out; 119 120 err: 121 EC_KEY_free(eckey); 122 EVP_PKEY_free(pkey); 123 pkey = NULL; 124 out: 125 return pkey; 126 } 127 128 129 130 EVP_PKEY * 131 key_load(FILE *f, const char *fname) 132 { 133 EVP_PKEY *pkey; 134 135 pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL); 136 if (pkey == NULL) { 137 warnx("%s: PEM_read_PrivateKey", fname); 138 return NULL; 139 } else if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA || 140 EVP_PKEY_type(pkey->type) == EVP_PKEY_EC ) 141 return pkey; 142 143 warnx("%s: unsupported key type", fname); 144 EVP_PKEY_free(pkey); 145 return NULL; 146 } 147