aboutsummaryrefslogtreecommitdiff
path: root/utils.c
diff options
context:
space:
mode:
authorOmar Polo <op@omarpolo.com>2023-06-11 11:03:59 +0000
committerOmar Polo <op@omarpolo.com>2023-06-11 11:03:59 +0000
commit86693a33abd5e8c31530adb3045c9f4664d4d6c9 (patch)
tree3ef25d39266c92a62ece902799cc23b76812e0d0 /utils.c
parentf81a97b3569478a36e5cbe95229efd1b831b7a7b (diff)
add a privsep crypto engine
Incorporate the OpenSMTPD' privsep crypto engine. The idea behind it is to never load the certificate' private keys in a networked process, instead they are loaded in a separate process (the `crypto' one) which signs payloads on the behalf of the server processes. This way, we greatly reduce the risk of leaking the certificate' private key should the server process be compromised. This currently compiles only on LibreSSL (portable fix is in the way).
Diffstat (limited to 'utils.c')
-rw-r--r--utils.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/utils.c b/utils.c
index b8f09c7..c5f91a1 100644
--- a/utils.c
+++ b/utils.c
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2021 Omar Polo <op@omarpolo.com>
+ * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+ * Copyright (c) 2008 Reyk Floeter <reyk@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -20,6 +22,7 @@
#include <string.h>
#include <openssl/bn.h>
+#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509_vfy.h>
#include <openssl/x509v3.h>
@@ -246,6 +249,90 @@ end:
return ret;
}
+void
+ssl_error(const char *where)
+{
+ unsigned long code;
+ char errbuf[128];
+
+ while ((code = ERR_get_error()) != 0) {
+ ERR_error_string_n(code, errbuf, sizeof(errbuf));
+ log_debug("debug: SSL library error: %s: %s", where, errbuf);
+ }
+}
+
+char *
+ssl_pubkey_hash(const char *buf, size_t len)
+{
+ static const char hex[] = "0123456789abcdef";
+ BIO *in;
+ X509 *x509 = NULL;
+ char *hash = NULL;
+ size_t off;
+ char digest[EVP_MAX_MD_SIZE];
+ int dlen, i;
+
+ if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
+ log_warnx("%s: BIO_new_mem_buf failed", __func__);
+ return NULL;
+ }
+
+ if ((x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL) {
+ log_warnx("%s: PEM_read_bio_X509 failed", __func__);
+ ssl_error("PEM_read_bio_X509");
+ goto fail;
+ }
+
+ if ((hash = malloc(TLS_CERT_HASH_SIZE)) == NULL) {
+ log_warn("%s: malloc", __func__);
+ goto fail;
+ }
+
+ if (X509_pubkey_digest(x509, EVP_sha256(), digest, &dlen) != 1) {
+ log_warnx("%s: X509_pubkey_digest failed", __func__);
+ ssl_error("X509_pubkey_digest");
+ free(hash);
+ hash = NULL;
+ goto fail;
+ }
+
+ if (TLS_CERT_HASH_SIZE < 2 * dlen + sizeof("SHA256:"))
+ fatalx("%s: hash buffer too small", __func__);
+
+ off = strlcpy(hash, "SHA256:", TLS_CERT_HASH_SIZE);
+ for (i = 0; i < dlen; ++i) {
+ hash[off++] = hex[(digest[i] >> 4) & 0xf];
+ hash[off++] = hex[digest[i] & 0xf];
+ }
+ hash[off] = '\0';
+
+ fail:
+ BIO_free(in);
+ if (x509)
+ X509_free(x509);
+ return hash;
+}
+
+EVP_PKEY *
+ssl_load_pkey(const char *buf, size_t len)
+{
+ BIO *in;
+ EVP_PKEY *pkey;
+
+ if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
+ log_warnx("%s: BIO_new_mem_buf failed", __func__);
+ return NULL;
+ }
+
+ if ((pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL)) == NULL) {
+ log_warnx("%s: PEM_read_bio_PrivateKey failed", __func__);
+ ssl_error("PEM_read_bio_PrivateKey");
+ }
+
+ BIO_free(in);
+ return pkey;
+}
+
struct vhost *
new_vhost(void)
{