key.c revision 1.7
1/* $Id: key.c,v 1.7 2022/12/18 12:08:49 tb 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 37/* 38 * Create an RSA key with the default KBITS number of bits. 39 */ 40EVP_PKEY * 41rsa_key_create(FILE *f, const char *fname) 42{ 43 EVP_PKEY_CTX *ctx = NULL; 44 EVP_PKEY *pkey = NULL; 45 46 /* First, create the context and the key. */ 47 48 if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) { 49 warnx("EVP_PKEY_CTX_new_id"); 50 goto err; 51 } else if (EVP_PKEY_keygen_init(ctx) <= 0) { 52 warnx("EVP_PKEY_keygen_init"); 53 goto err; 54 } else if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) { 55 warnx("EVP_PKEY_set_rsa_keygen_bits"); 56 goto err; 57 } else if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { 58 warnx("EVP_PKEY_keygen"); 59 goto err; 60 } 61 62 /* Serialise the key to the disc. */ 63 64 if (PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) 65 goto out; 66 67 warnx("%s: PEM_write_PrivateKey", fname); 68 69err: 70 EVP_PKEY_free(pkey); 71 pkey = NULL; 72out: 73 EVP_PKEY_CTX_free(ctx); 74 return pkey; 75} 76 77EVP_PKEY * 78ec_key_create(FILE *f, const char *fname) 79{ 80 EC_KEY *eckey = NULL; 81 EVP_PKEY *pkey = NULL; 82 83 if ((eckey = EC_KEY_new_by_curve_name(NID_secp384r1)) == NULL ) { 84 warnx("EC_KEY_new_by_curve_name"); 85 goto err; 86 } 87 88 if (!EC_KEY_generate_key(eckey)) { 89 warnx("EC_KEY_generate_key"); 90 goto err; 91 } 92 93 /* set OPENSSL_EC_NAMED_CURVE to be able to load the key */ 94 95 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); 96 97 /* Serialise the key to the disc in EC format */ 98 99 if (!PEM_write_ECPrivateKey(f, eckey, NULL, NULL, 0, NULL, NULL)) { 100 warnx("%s: PEM_write_ECPrivateKey", fname); 101 goto err; 102 } 103 104 /* Convert the EC key into a PKEY structure */ 105 106 if ((pkey = EVP_PKEY_new()) == NULL) { 107 warnx("EVP_PKEY_new"); 108 goto err; 109 } 110 if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 111 warnx("EVP_PKEY_assign_EC_KEY"); 112 goto err; 113 } 114 115 goto out; 116 117err: 118 EVP_PKEY_free(pkey); 119 pkey = NULL; 120out: 121 EC_KEY_free(eckey); 122 return pkey; 123} 124 125 126 127EVP_PKEY * 128key_load(FILE *f, const char *fname) 129{ 130 EVP_PKEY *pkey; 131 132 pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL); 133 if (pkey == NULL) { 134 warnx("%s: PEM_read_PrivateKey", fname); 135 return NULL; 136 } 137 if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA || 138 EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) 139 return pkey; 140 141 warnx("%s: unsupported key type", fname); 142 EVP_PKEY_free(pkey); 143 return NULL; 144} 145