commit 7d2a2ace4dcbea184a9363adac6ecb9731ada286 from: Omar Polo date: Wed Jan 24 18:23:30 2024 UTC add certs.[ch] adapted from gmid. we'll soon use it to provide client certificates support in telescope. commit - 7251d7ad3d769b5e29bbf3d7d2a14855ee09ac83 commit + 7d2a2ace4dcbea184a9363adac6ecb9731ada286 blob - a369d33771d41e1c1a16c6b2b775229d4390b0e0 blob + 50f3c6a232db5209e86526c2a045844bfae08fc0 --- Makefile.am +++ Makefile.am @@ -4,7 +4,9 @@ bin_PROGRAMS = telescope EXTRA_telescope_SOURCES = compat/ohash.h compat/queue.h compat/imsg.h contrib -telescope_SOURCES = cmd.c \ +telescope_SOURCES = certs.c \ + certs.h \ + cmd.c \ cmd.gen.c \ cmd.h \ compat.h \ blob - /dev/null blob + cc75de3d7d482e933ac57faa09aec2859f9180a8 (mode 644) --- /dev/null +++ certs.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2021, 2023, 2024 Omar Polo + * Copyright (c) 2019 Renaud Allard + * Copyright (c) 2016 Kristaps Dzonsons + * Copyright (c) 2008 Pierre-Yves Ritschard + * Copyright (c) 2008 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "compat.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "certs.h" + +/* + * Default number of bits when creating a new RSA key. + */ +#define KBITS 4096 + +static EVP_PKEY * +rsa_key_create(FILE *f, const char *fname) +{ + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + int ret = -1; + + /* First, create the context and the key. */ + + if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) + goto done; + + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto done; + + if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KBITS) <= 0) + goto done; + + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + goto done; + + /* Serialize the key to the disc. */ + if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) + goto done; + + ret = 0; + done: + if (ret == -1) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + EVP_PKEY_CTX_free(ctx); + return pkey; +} + +static EVP_PKEY * +ec_key_create(FILE *f, const char *fname) +{ + EC_KEY *eckey = NULL; + EVP_PKEY *pkey = NULL; + int ret = -1; + + if ((eckey = EC_KEY_new_by_curve_name(NID_secp384r1)) == NULL) + goto done; + + if (!EC_KEY_generate_key(eckey)) + goto done; + + /* Serialise the key to the disc in EC format */ + if (!PEM_write_ECPrivateKey(f, eckey, NULL, NULL, 0, NULL, NULL)) + goto done; + + /* Convert the EC key into a PKEY structure */ + if ((pkey = EVP_PKEY_new()) == NULL) + goto done; + + if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) + goto done; + + ret = 0; + done: + if (ret == -1) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + EC_KEY_free(eckey); + return pkey; +} + +int +cert_new(const char *common_name, const char *certpath, const char *keypath, + int eckey) +{ + EVP_PKEY *pkey = NULL; + X509 *x509 = NULL; + X509_NAME *name = NULL; + FILE *fp = NULL; + int ret = -1; + const unsigned char *cn = (const unsigned char*)common_name; + + if ((fp = fopen(keypath, "w")) == NULL) + goto done; + + if (eckey) + pkey = ec_key_create(fp, keypath); + else + pkey = rsa_key_create(fp, keypath); + if (pkey == NULL) + goto done; + + if (fflush(fp) == EOF || fclose(fp) == EOF) + goto done; + fp = NULL; + + if ((x509 = X509_new()) == NULL) + goto done; + + ASN1_INTEGER_set(X509_get_serialNumber(x509), 0); + X509_gmtime_adj(X509_get_notBefore(x509), 0); + X509_gmtime_adj(X509_get_notAfter(x509), 315360000L); /* 10 years */ + X509_set_version(x509, 2); // v3 + + if (!X509_set_pubkey(x509, pkey)) + goto done; + + if ((name = X509_NAME_new()) == NULL) + goto done; + + if (!X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, cn, + -1, -1, 0)) + goto done; + + X509_set_subject_name(x509, name); + X509_set_issuer_name(x509, name); + + if (!X509_sign(x509, pkey, EVP_sha256())) + goto done; + + if ((fp = fopen(certpath, "w")) == NULL) + goto done; + + if (!PEM_write_X509(fp, x509)) + goto done; + + if (fflush(fp) == EOF) + goto done; + + ret = 0; + done: + if (pkey) + EVP_PKEY_free(pkey); + if (x509) + X509_free(x509); + if (name) + X509_NAME_free(name); + if (fp) + fclose(fp); + + if (ret == -1) { + (void) unlink(certpath); + (void) unlink(keypath); + } + return (ret); +} blob - /dev/null blob + c50f46afdb218208b3c062887aca4274c3d8fec9 (mode 644) --- /dev/null +++ certs.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021, 2023, 2024 Omar Polo + * Copyright (c) 2019 Renaud Allard + * Copyright (c) 2016 Kristaps Dzonsons + * Copyright (c) 2008 Pierre-Yves Ritschard + * Copyright (c) 2008 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +int cert_new(const char *, const char *, const char *, int); blob - f27c7a8c60e27416fbcf0bda1586a278c6d23694 blob + a8ee2a6f78f72f3a016b5eec18422499923c42bb --- configure.ac +++ configure.ac @@ -143,6 +143,14 @@ AC_SEARCH_LIBS([ohash_init], [util], [], [ AC_CHECK_FUNCS([asr_run]) +AC_SEARCH_LIBS([RAND_add], [crypto], [:], [ + AC_MSG_ERROR([can't find libcrypto]) +]) + +AC_SEARCH_LIBS([SSL_CTX_new], [ssl], [:], [ + AC_MSG_ERROR([can't find libssl]) +]) + # don't check for landlock: it currently unusable. dnl AC_CHECK_HEADERS([linux/landlock.h])