1 /* $Id: key.c,v 1.9 2024/05/09 06:08:11 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/ec.h> 27 #include <openssl/obj_mac.h> 28 29 #include "key.h" 30 31 /* 32 * Default number of bits when creating a new RSA key. 33 */ 34 #define KBITS 4096 35 36 /* 37 * Create an RSA key with the default KBITS number of bits. 38 */ 39 EVP_PKEY * 40 rsa_key_create(FILE *f, const char *fname) 41 { 42 EVP_PKEY_CTX *ctx = NULL; 43 EVP_PKEY *pkey = NULL; 44 45 if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) { 46 warnx("EVP_PKEY_CTX_new_id"); 47 goto err; 48 } 49 if (EVP_PKEY_keygen_init(ctx) <= 0) { 50 warnx("EVP_PKEY_keygen_init"); 51 goto err; 52 } 53 if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) { 54 warnx("EVP_PKEY_set_rsa_keygen_bits"); 55 goto err; 56 } 57 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 warnx("%s: PEM_write_PrivateKey", fname); 66 goto err; 67 } 68 69 EVP_PKEY_CTX_free(ctx); 70 return pkey; 71 72 err: 73 EVP_PKEY_free(pkey); 74 EVP_PKEY_CTX_free(ctx); 75 return NULL; 76 } 77 78 EVP_PKEY * 79 ec_key_create(FILE *f, const char *fname) 80 { 81 EVP_PKEY_CTX *ctx = NULL; 82 EVP_PKEY *pkey = NULL; 83 84 if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) { 85 warnx("EVP_PKEY_CTX_new_id"); 86 goto err; 87 } 88 if (EVP_PKEY_keygen_init(ctx) <= 0) { 89 warnx("EVP_PKEY_keygen_init"); 90 goto err; 91 } 92 if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_secp384r1) <= 0) { 93 warnx("EVP_PKEY_CTX_set_ec_paramgen_curve_nid"); 94 goto err; 95 } 96 if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { 97 warnx("EVP_PKEY_keygen"); 98 goto err; 99 } 100 101 /* Serialise the key to the disc. */ 102 103 if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) { 104 warnx("%s: PEM_write_PrivateKey", fname); 105 goto err; 106 } 107 108 EVP_PKEY_CTX_free(ctx); 109 return pkey; 110 111 err: 112 EVP_PKEY_free(pkey); 113 EVP_PKEY_CTX_free(ctx); 114 return NULL; 115 } 116 117 EVP_PKEY * 118 key_load(FILE *f, const char *fname) 119 { 120 EVP_PKEY *pkey; 121 122 pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL); 123 if (pkey == NULL) { 124 warnx("%s: PEM_read_PrivateKey", fname); 125 return NULL; 126 } 127 if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA || 128 EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) 129 return pkey; 130 131 warnx("%s: unsupported key type", fname); 132 EVP_PKEY_free(pkey); 133 return NULL; 134 } 135