From 32546c7caa1626bbef860cf81e53d10e29fca5cb Mon Sep 17 00:00:00 2001 From: Nicola Di Lieto Date: Wed, 12 Jan 2022 19:37:46 +0100 Subject: [PATCH] Compatiility with LibreSSL limitations as of LibreSSL version 3.4.2: uacme: --must-staple doesn't work. This is because LibreSSL does not support NID_tlsfeature and therefore it can't add the necessary extension to the certificate request. ualpn: doesn't work at all and probably never will. This is because the TLS implementation of LibreSSL is completely different. --- configure.ac | 15 ++++++++++++++- crypto.c | 45 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index 9278e6a..604ce6e 100644 --- a/configure.ac +++ b/configure.ac @@ -278,6 +278,12 @@ if test "x$OPT_OPENSSL" != "xno"; then AC_SUBST(USE_OPENSSL, [1]) USE_OPENSSL="yes"], [AC_MSG_ERROR([openssl check failed])]) + AC_MSG_CHECKING([if OpenSSL is really LibreSSL]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include + int main() {return LIBRESSL_VERSION_NUMBER;}])], + LIBRESSL=yes + AC_MSG_RESULT([yes]), + AC_MSG_RESULT([no])) fi fi AM_CONDITIONAL(ENABLE_READFILE, test "x$USE_OPENSSL" != "xyes") @@ -305,12 +311,19 @@ if test "x$OPT_MBEDTLS" != "xno"; then fi fi -OPT_UALPN=yes +if test "x$LIBRESSL" = "xyes"; then + OPT_UALPN=no +else + OPT_UALPN=yes +fi AC_ARG_WITH(ualpn, [AS_HELP_STRING([--with-ualpn], [enable ualpn]) AS_HELP_STRING([--without-ualpn], [disable ualpn])], OPT_UALPN=$withval) if test "x$OPT_UALPN" != "xno"; then + if test "x$LIBRESSL" = "xyes"; then + AC_MSG_ERROR([ualpn is not compatible with LibreSSL]) + fi AM_PROG_AR AC_CHECK_HEADERS([netinet/tcp.h], [], AC_MSG_ERROR([ualpn requires netinet/tcp.h])) diff --git a/crypto.c b/crypto.c index 7b5e343..0daab4a 100644 --- a/crypto.c +++ b/crypto.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "base64.h" @@ -544,18 +545,21 @@ static bool rsa_params(privkey_t key, char **m, char **e) } #elif defined(USE_OPENSSL) unsigned char *data = NULL; + const BIGNUM *bm = NULL; + const BIGNUM *be = NULL; RSA *rsa = EVP_PKEY_get0_RSA(key); if (!rsa) { openssl_error("rsa_params"); goto out; } - r = BN_num_bytes(RSA_get0_n(rsa)); + RSA_get0_key(rsa, &bm, &be, NULL); + r = BN_num_bytes(bm); data = calloc(1, r); if (!data) { warn("rsa_params: calloc failed"); goto out; } - if (BN_bn2bin(RSA_get0_n(rsa), data) != r) { + if (BN_bn2bin(bm, data) != r) { openssl_error("rsa_params"); goto out; } @@ -565,13 +569,13 @@ static bool rsa_params(privkey_t key, char **m, char **e) goto out; } free(data); - r = BN_num_bytes(RSA_get0_e(rsa)); + r = BN_num_bytes(be); data = calloc(1, r); if (!data) { warn("rsa_params: calloc failed"); goto out; } - if (BN_bn2bin(RSA_get0_e(rsa), data) != r) { + if (BN_bn2bin(be, data) != r) { openssl_error("rsa_params"); goto out; } @@ -1230,18 +1234,21 @@ bool ec_decode(size_t hash_size, unsigned char **sig, size_t *sig_size) #endif #elif defined(USE_OPENSSL) const unsigned char *p = *sig; + const BIGNUM *br = NULL; + const BIGNUM *bs = NULL; ECDSA_SIG *s = d2i_ECDSA_SIG(NULL, &p, *sig_size); if (!s) { openssl_error("ec_decode"); return false; } + ECDSA_SIG_get0(s, &br, &bs); unsigned char *tmp = calloc(1, 2*hash_size); if (!tmp) { warn("ec_decode: calloc failed"); ECDSA_SIG_free(s); return false; } - r = BN_num_bytes(ECDSA_SIG_get0_r(s)); + r = BN_num_bytes(br); unsigned char *data = calloc(1, r); if (!data) { warn("ec_decode: calloc failed"); @@ -1249,7 +1256,7 @@ bool ec_decode(size_t hash_size, unsigned char **sig, size_t *sig_size) free(tmp); return false; } - if (BN_bn2bin(ECDSA_SIG_get0_r(s), data) != r) { + if (BN_bn2bin(br, data) != r) { openssl_error("ec_decode"); ECDSA_SIG_free(s); free(data); @@ -1262,7 +1269,7 @@ bool ec_decode(size_t hash_size, unsigned char **sig, size_t *sig_size) memcpy(tmp + hash_size - r, data, r); free(data); - r = BN_num_bytes(ECDSA_SIG_get0_s(s)); + r = BN_num_bytes(bs); data = calloc(1, r); if (!data) { warn("ec_decode: calloc failed"); @@ -1270,7 +1277,7 @@ bool ec_decode(size_t hash_size, unsigned char **sig, size_t *sig_size) free(tmp); return false; } - if (BN_bn2bin(ECDSA_SIG_get0_s(s), data) != r) { + if (BN_bn2bin(bs, data) != r) { openssl_error("ec_decode"); ECDSA_SIG_free(s); free(data); @@ -2283,6 +2290,11 @@ char *csr_gen(char * const *names, bool status_req, privkey_t key) } sk_X509_EXTENSION_push(exts, ext); if (status_req) { +#if defined(LIBRESSL_VERSION_NUMBER) + warnx("csr_gen: -m, --must-staple is not supported by LibreSSL " + "- consider recompiling with OpenSSL"); + goto out; +#endif ext = X509V3_EXT_conf_nid(NULL, NULL, NID_tlsfeature, "status_request"); if (!ext) { @@ -4254,9 +4266,24 @@ bool cert_valid(const char *certfile, char * const *names, int validity, int ncrt = cert_load(crt, 2, "%s", certfile); if (ncrt <= 0) goto out; - int days_left, sec; + int days_left; const ASN1_TIME *tm = X509_get0_notAfter(crt[0]); +#if defined(LIBRESSL_VERSION_NUMBER) + struct tm tcrt; + if (tm && ASN1_time_parse((const char *)tm->data, tm->length, &tcrt, + tm->type) != -1) { + time_t now = time(NULL); + struct tm *tnow = gmtime(&now); + if (!tnow) { + warnx("cert_valid: gmtime overflow"); + goto out; + } + days_left = difftime(mktime(&tcrt), mktime(tnow))/(3600*24); + } else { +#else + int sec; if (!tm || !ASN1_TIME_diff(&days_left, &sec, NULL, tm)) { +#endif warnx("cert_valid: invalid expiration time format in %s", certfile); goto out; }