key.c revision 1.1
1/* $Id: key.c,v 1.1 2019/06/12 11:09:25 gilles 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 */ 41EVP_PKEY * 42rsa_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 70err: 71 EVP_PKEY_free(pkey); 72 pkey = NULL; 73out: 74 EVP_PKEY_CTX_free(ctx); 75 return pkey; 76} 77 78EVP_PKEY * 79ec_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()) == NULL ) { 85 warnx("EC_KEY_new"); 86 goto err; 87 } else if ((eckey = EC_KEY_new_by_curve_name(ECCTYPE)) == NULL ) { 88 warnx("EC_GROUP_new_by_curve_name"); 89 goto err; 90 } 91 92 if (!EC_KEY_generate_key(eckey)) { 93 warnx("EC_KEY_generate_key"); 94 goto err; 95 } 96 97 /* set OPENSSL_EC_NAMED_CURVE to be able to load the key */ 98 99 EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); 100 101 /* Serialise the key to the disc in EC format */ 102 103 if (!PEM_write_ECPrivateKey(f, eckey, NULL, NULL, 0, NULL, NULL)) { 104 warnx("PEM_write_ECPrivateKey"); 105 goto err; 106 } 107 108 /* Convert the EC key into a PKEY structure */ 109 110 if ((pkey=EVP_PKEY_new()) == NULL) { 111 warnx("EVP_PKEY_new"); 112 goto err; 113 } 114 if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) { 115 warnx("EVP_PKEY_assign_EC_KEY"); 116 goto err; 117 } 118 119 warnx("%s: PEM_write_ECPrivateKey", fname); 120 121 goto out; 122 123err: 124 EC_KEY_free(eckey); 125 EVP_PKEY_free(pkey); 126 pkey = NULL; 127out: 128 return pkey; 129} 130 131 132 133EVP_PKEY * 134key_load(FILE *f, const char *fname) 135{ 136 EVP_PKEY *pkey; 137 138 pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL); 139 if (pkey == NULL) { 140 warnx("%s: PEM_read_PrivateKey", fname); 141 return NULL; 142 } else if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA || 143 EVP_PKEY_type(pkey->type) == EVP_PKEY_EC ) 144 return pkey; 145 146 warnx("%s: unsupported key type", fname); 147 EVP_PKEY_free(pkey); 148 return NULL; 149} 150