1*0ef8c397Stb /* $Id: key.c,v 1.9 2024/05/09 06:08:11 tb Exp $ */
23e86e78bSgilles /*
33e86e78bSgilles * Copyright (c) 2019 Renaud Allard <renaud@allard.it>
43e86e78bSgilles * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv>
53e86e78bSgilles *
63e86e78bSgilles * Permission to use, copy, modify, and distribute this software for any
73e86e78bSgilles * purpose with or without fee is hereby granted, provided that the above
83e86e78bSgilles * copyright notice and this permission notice appear in all copies.
93e86e78bSgilles *
103e86e78bSgilles * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
113e86e78bSgilles * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
123e86e78bSgilles * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
133e86e78bSgilles * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
143e86e78bSgilles * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
153e86e78bSgilles * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
163e86e78bSgilles * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
173e86e78bSgilles */
183e86e78bSgilles
193e86e78bSgilles #include <err.h>
203e86e78bSgilles #include <stdlib.h>
213e86e78bSgilles #include <unistd.h>
223e86e78bSgilles
233e86e78bSgilles #include <openssl/evp.h>
243e86e78bSgilles #include <openssl/pem.h>
253e86e78bSgilles #include <openssl/rsa.h>
263e86e78bSgilles #include <openssl/ec.h>
273e86e78bSgilles #include <openssl/obj_mac.h>
283e86e78bSgilles
293e86e78bSgilles #include "key.h"
303e86e78bSgilles
313e86e78bSgilles /*
323e86e78bSgilles * Default number of bits when creating a new RSA key.
333e86e78bSgilles */
343e86e78bSgilles #define KBITS 4096
353e86e78bSgilles
363e86e78bSgilles /*
373e86e78bSgilles * Create an RSA key with the default KBITS number of bits.
383e86e78bSgilles */
393e86e78bSgilles EVP_PKEY *
rsa_key_create(FILE * f,const char * fname)403e86e78bSgilles rsa_key_create(FILE *f, const char *fname)
413e86e78bSgilles {
423e86e78bSgilles EVP_PKEY_CTX *ctx = NULL;
433e86e78bSgilles EVP_PKEY *pkey = NULL;
443e86e78bSgilles
453e86e78bSgilles if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) {
463e86e78bSgilles warnx("EVP_PKEY_CTX_new_id");
473e86e78bSgilles goto err;
48*0ef8c397Stb }
49*0ef8c397Stb if (EVP_PKEY_keygen_init(ctx) <= 0) {
503e86e78bSgilles warnx("EVP_PKEY_keygen_init");
513e86e78bSgilles goto err;
52*0ef8c397Stb }
53*0ef8c397Stb if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) {
543e86e78bSgilles warnx("EVP_PKEY_set_rsa_keygen_bits");
553e86e78bSgilles goto err;
56*0ef8c397Stb }
57*0ef8c397Stb if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
583e86e78bSgilles warnx("EVP_PKEY_keygen");
593e86e78bSgilles goto err;
603e86e78bSgilles }
613e86e78bSgilles
623e86e78bSgilles /* Serialise the key to the disc. */
633e86e78bSgilles
64*0ef8c397Stb if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
653e86e78bSgilles warnx("%s: PEM_write_PrivateKey", fname);
66*0ef8c397Stb goto err;
67*0ef8c397Stb }
68*0ef8c397Stb
69*0ef8c397Stb EVP_PKEY_CTX_free(ctx);
70*0ef8c397Stb return pkey;
713e86e78bSgilles
723e86e78bSgilles err:
733e86e78bSgilles EVP_PKEY_free(pkey);
743e86e78bSgilles EVP_PKEY_CTX_free(ctx);
75*0ef8c397Stb return NULL;
763e86e78bSgilles }
773e86e78bSgilles
783e86e78bSgilles EVP_PKEY *
ec_key_create(FILE * f,const char * fname)793e86e78bSgilles ec_key_create(FILE *f, const char *fname)
803e86e78bSgilles {
81*0ef8c397Stb EVP_PKEY_CTX *ctx = NULL;
823e86e78bSgilles EVP_PKEY *pkey = NULL;
833e86e78bSgilles
84*0ef8c397Stb if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) {
85*0ef8c397Stb warnx("EVP_PKEY_CTX_new_id");
86*0ef8c397Stb goto err;
87*0ef8c397Stb }
88*0ef8c397Stb if (EVP_PKEY_keygen_init(ctx) <= 0) {
89*0ef8c397Stb warnx("EVP_PKEY_keygen_init");
90*0ef8c397Stb goto err;
91*0ef8c397Stb }
92*0ef8c397Stb if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, NID_secp384r1) <= 0) {
93*0ef8c397Stb warnx("EVP_PKEY_CTX_set_ec_paramgen_curve_nid");
94*0ef8c397Stb goto err;
95*0ef8c397Stb }
96*0ef8c397Stb if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
97*0ef8c397Stb warnx("EVP_PKEY_keygen");
983e86e78bSgilles goto err;
993e86e78bSgilles }
1003e86e78bSgilles
101*0ef8c397Stb /* Serialise the key to the disc. */
102*0ef8c397Stb
103*0ef8c397Stb if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
104*0ef8c397Stb warnx("%s: PEM_write_PrivateKey", fname);
1053e86e78bSgilles goto err;
1063e86e78bSgilles }
1073e86e78bSgilles
108*0ef8c397Stb EVP_PKEY_CTX_free(ctx);
109*0ef8c397Stb return pkey;
1103e86e78bSgilles
1113e86e78bSgilles err:
1123e86e78bSgilles EVP_PKEY_free(pkey);
113*0ef8c397Stb EVP_PKEY_CTX_free(ctx);
114*0ef8c397Stb return NULL;
1153e86e78bSgilles }
1163e86e78bSgilles
1173e86e78bSgilles EVP_PKEY *
key_load(FILE * f,const char * fname)1183e86e78bSgilles key_load(FILE *f, const char *fname)
1193e86e78bSgilles {
1203e86e78bSgilles EVP_PKEY *pkey;
1213e86e78bSgilles
1223e86e78bSgilles pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL);
1233e86e78bSgilles if (pkey == NULL) {
1243e86e78bSgilles warnx("%s: PEM_read_PrivateKey", fname);
1253e86e78bSgilles return NULL;
126e9900e80Stb }
127e9900e80Stb if (EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA ||
128e9900e80Stb EVP_PKEY_base_id(pkey) == EVP_PKEY_EC)
1293e86e78bSgilles return pkey;
1303e86e78bSgilles
1313e86e78bSgilles warnx("%s: unsupported key type", fname);
1323e86e78bSgilles EVP_PKEY_free(pkey);
1333e86e78bSgilles return NULL;
1343e86e78bSgilles }
135