Fix build with recent LibreSSL, when including DANE. Bug 2386
[exim.git] / src / src / dane-openssl.c
index 6c2b1dbdedafff179c7a3f8a4719d5e8fc6b0c51..4ac5747c9a5a2bfb91aa2f7c81dd2e7194d90a9e 100644 (file)
@@ -2,7 +2,7 @@
  *  Author: Viktor Dukhovni
  *  License: THIS CODE IS IN THE PUBLIC DOMAIN.
  *
- * Copyright (c) The Exim Maintainers 2014 - 2016
+ * Copyright (c) The Exim Maintainers 2014 - 2019
  */
 #include <stdio.h>
 #include <string.h>
 
 #if OPENSSL_VERSION_NUMBER < 0x1000000fL
 # error "OpenSSL 1.0.0 or higher required"
-#else   /* remainder of file */
+#endif
 
 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
 # define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509)
 #endif
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-# define EXIM_HAVE_ASN1_MACROS
-# define EXIM_OPAQUE_X509
-#else
-# define X509_STORE_CTX_get_verify(ctx)                (ctx)->verify
-# define X509_STORE_CTX_get_verify_cb(ctx)     (ctx)->verify_cb
-# define X509_STORE_CTX_get0_cert(ctx)         (ctx)->cert
-# define X509_STORE_CTX_get0_chain(ctx)                (ctx)->chain
-# define X509_STORE_CTX_get0_untrusted(ctx)    (ctx)->untrusted
-
-# define X509_STORE_CTX_set_verify(ctx, verify_chain)  (ctx)->verify = (verify_chain)
-# define X509_STORE_CTX_set0_verified_chain(ctx, sk)   (ctx)->chain = (sk)
-# define X509_STORE_CTX_set_error_depth(ctx, val)      (ctx)->error_depth = (val)
-# define X509_STORE_CTX_set_current_cert(ctx, cert)    (ctx)->current_cert = (cert)
+
+#ifdef LIBRESSL_VERSION_NUMBER /* LibreSSL */
+# if LIBRESSL_VERSION_NUMBER >= 0x2090000fL
+#  define EXIM_HAVE_ASN1_MACROS
+# endif
+#else                          /* OpenSSL */
+# if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#  define EXIM_HAVE_ASN1_MACROS
+#  define EXIM_OPAQUE_X509
+# else
+#  define X509_STORE_CTX_get_verify(ctx)               (ctx)->verify
+#  define X509_STORE_CTX_get_verify_cb(ctx)    (ctx)->verify_cb
+#  define X509_STORE_CTX_get0_cert(ctx)                (ctx)->cert
+#  define X509_STORE_CTX_get0_chain(ctx)               (ctx)->chain
+#  define X509_STORE_CTX_get0_untrusted(ctx)   (ctx)->untrusted
+
+#  define X509_STORE_CTX_set_verify(ctx, verify_chain) (ctx)->verify = (verify_chain)
+#  define X509_STORE_CTX_set0_verified_chain(ctx, sk)  (ctx)->chain = (sk)
+#  define X509_STORE_CTX_set_error_depth(ctx, val)     (ctx)->error_depth = (val)
+#  define X509_STORE_CTX_set_current_cert(ctx, cert)   (ctx)->current_cert = (cert)
+
+#  define ASN1_STRING_get0_data        ASN1_STRING_data
+#  define X509_getm_notBefore  X509_get_notBefore
+#  define X509_getm_notAfter   X509_get_notAfter
+
+#  define CRYPTO_ONCE_STATIC_INIT 0
+#  define CRYPTO_THREAD_run_once        run_once
+typedef int CRYPTO_ONCE;
+# endif
 #endif
 
 
@@ -57,6 +72,7 @@
 #define DANESSL_F_SET_TRUST_ANCHOR     110
 #define DANESSL_F_VERIFY_CERT          111
 #define DANESSL_F_WRAP_CERT            112
+#define DANESSL_F_DANESSL_VERIFY_CHAIN 113
 
 #define DANESSL_R_BAD_CERT             100
 #define DANESSL_R_BAD_CERT_PKEY                101
@@ -75,6 +91,7 @@
 #ifndef OPENSSL_NO_ERR
 #define        DANESSL_F_PLACEHOLDER           0               /* FIRST! Value TBD */
 static ERR_STRING_DATA dane_str_functs[] = {
+    /* error                           string */
     {DANESSL_F_PLACEHOLDER,            "DANE library"},        /* FIRST!!! */
     {DANESSL_F_ADD_SKID,               "add_skid"},
     {DANESSL_F_ADD_TLSA,               "DANESSL_add_tlsa"},
@@ -92,6 +109,7 @@ static ERR_STRING_DATA dane_str_functs[] = {
     {0,                                        NULL}
 };
 static ERR_STRING_DATA dane_str_reasons[] = {
+    /* error                           string */
     {DANESSL_R_BAD_CERT,       "Bad TLSA record certificate"},
     {DANESSL_R_BAD_CERT_PKEY,  "Bad TLSA record certificate public key"},
     {DANESSL_R_BAD_DATA_LENGTH,        "Bad TLSA record digest length"},
@@ -229,7 +247,6 @@ int matched;
  */
 for (matched = 0; !matched && slist; slist = slist->next)
   {
-  dane_mtype_list m;
   unsigned char mdbuf[EVP_MAX_MD_SIZE];
   unsigned char *buf = NULL;
   unsigned char *buf2;
@@ -242,12 +259,12 @@ for (matched = 0; !matched && slist; slist = slist->next)
     {
     case DANESSL_SELECTOR_CERT:
       len = i2d_X509(cert, NULL);
-      buf2 = buf = (unsigned char *) OPENSSL_malloc(len);
+      buf2 = buf = US  OPENSSL_malloc(len);
       if(buf) i2d_X509(cert, &buf2);
       break;
     case DANESSL_SELECTOR_SPKI:
       len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
-      buf2 = buf = (unsigned char *) OPENSSL_malloc(len);
+      buf2 = buf = US  OPENSSL_malloc(len);
       if(buf) i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &buf2);
       break;
     }
@@ -262,9 +279,8 @@ for (matched = 0; !matched && slist; slist = slist->next)
   /*
    * Loop over each mtype and data element
    */
-  for (m = slist->value->mtype; !matched && m; m = m->next)
+  for (dane_mtype_list m = slist->value->mtype; !matched && m; m = m->next)
     {
-    dane_data_list d;
     unsigned char *cmpbuf = buf;
     unsigned int cmplen = len;
 
@@ -278,7 +294,7 @@ for (matched = 0; !matched && slist; slist = slist->next)
       if (!EVP_Digest(buf, len, cmpbuf, &cmplen, m->value->md, 0))
          matched = -1;
       }
-    for (d = m->value->data; !matched && d; d = d->next)
+    for (dane_data_list d = m->value->data; !matched && d; d = d->next)
        if (  cmplen == d->value->datalen
           && memcmp(cmpbuf, d->value->data, cmplen) == 0)
            matched = slist->value->selector + 1;
@@ -293,13 +309,14 @@ return matched;
 static int
 push_ext(X509 *cert, X509_EXTENSION *ext)
 {
-    if (ext) {
-       if (X509_add_ext(cert, ext, -1))
-           return 1;
-       X509_EXTENSION_free(ext);
-    }
-    DANEerr(DANESSL_F_PUSH_EXT, ERR_R_MALLOC_FAILURE);
-    return 0;
+if (ext)
+  {
+  if (X509_add_ext(cert, ext, -1))
+      return 1;
+  X509_EXTENSION_free(ext);
+  }
+DANEerr(DANESSL_F_PUSH_EXT, ERR_R_MALLOC_FAILURE);
+return 0;
 }
 
 static int
@@ -338,7 +355,7 @@ static int
 add_akid(X509 *cert, AUTHORITY_KEYID *akid)
 {
 int nid = NID_authority_key_identifier;
-ASN1_STRING *id;
+ASN1_OCTET_STRING *id;
 unsigned char c = 0;
 int ret = 0;
 
@@ -349,8 +366,8 @@ int ret = 0;
  * exempt from any potential (off by default for now in OpenSSL)
  * self-signature checks!
  */
-id =  (akid && akid->keyid) ? akid->keyid : 0;
-if (id && ASN1_STRING_length(id) == 1 && *ASN1_STRING_data(id) == c)
+id =  akid && akid->keyid ? akid->keyid : 0;
+if (id && ASN1_STRING_length(id) == 1 && *ASN1_STRING_get0_data(id) == c)
   c = 1;
 
 if (  (akid = AUTHORITY_KEYID_new()) != 0
@@ -382,10 +399,9 @@ akid_issuer_name(AUTHORITY_KEYID *akid)
 {
 if (akid && akid->issuer)
   {
-  int     i;
   GENERAL_NAMES *gens = akid->issuer;
 
-  for (i = 0; i < sk_GENERAL_NAME_num(gens); ++i)
+  for (int i = 0; i < sk_GENERAL_NAME_num(gens); ++i)
     {
     GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
 
@@ -397,16 +413,16 @@ return 0;
 }
 
 static int
-set_issuer_name(X509 *cert, AUTHORITY_KEYID *akid)
+set_issuer_name(X509 *cert, AUTHORITY_KEYID *akid, X509_NAME *subj)
 {
 X509_NAME *name = akid_issuer_name(akid);
 
 /*
- * If subject's akid specifies an authority key identifer issuer name, we
+ * If subject's akid specifies an authority key identifier issuer name, we
  * must use that.
  */
 return X509_set_issuer_name(cert,
-                           name ? name : X509_get_subject_name(cert));
+                           name ? name : subj);
 }
 
 static int
@@ -488,10 +504,10 @@ akid = X509_get_ext_d2i(subject, NID_authority_key_identifier, 0, 0);
  */
 if (  !X509_set_version(cert, 2)
    || !set_serial(cert, akid, subject)
+   || !set_issuer_name(cert, akid, name)
+   || !X509_gmtime_adj(X509_getm_notBefore(cert), -30 * 86400L)
+   || !X509_gmtime_adj(X509_getm_notAfter(cert), 30 * 86400L)
    || !X509_set_subject_name(cert, name)
-   || !set_issuer_name(cert, akid)
-   || !X509_gmtime_adj(X509_get_notBefore(cert), -30 * 86400L)
-   || !X509_gmtime_adj(X509_get_notAfter(cert), 30 * 86400L)
    || !X509_set_pubkey(cert, newkey)
    || !add_ext(0, cert, NID_basic_constraints, "CA:TRUE")
    || (!top && !add_akid(cert, akid))
@@ -519,7 +535,7 @@ if (dane->depth < 0)
 
 /*
  * If the TA certificate is self-issued, or need not be, use it directly.
- * Otherwise, synthesize requisuite ancestors.
+ * Otherwise, synthesize requisite ancestors.
  */
 if (  !wrap_to_root
    || X509_check_issued(tacert, tacert) == X509_V_OK)
@@ -533,8 +549,6 @@ return 0;
 static int
 ta_signed(ssl_dane *dane, X509 *cert, int depth)
 {
-dane_cert_list x;
-dane_pkey_list k;
 EVP_PKEY *pk;
 int done = 0;
 
@@ -545,7 +559,7 @@ int done = 0;
  * first (name comparisons), before we bother with signature checks
  * (public key operations).
  */
-for (x = dane->certs; !done && x; x = x->next)
+for (dane_cert_list x = dane->certs; !done && x; x = x->next)
   {
   if (X509_check_issued(x->value, cert) == X509_V_OK)
     {
@@ -585,7 +599,7 @@ for (x = dane->certs; !done && x; x = x->next)
  * This may push errors onto the stack when the certificate signature is
  * not of the right type or length, throw these away,
  */
-for (k = dane->pkeys; !done && k; k = k->next)
+for (dane_pkey_list k = dane->pkeys; !done && k; k = k->next)
   if (X509_verify(cert, k->value) > 0)
     done = wrap_issuer(dane, k->value, cert, depth, WRAP_MID) ? 1 : -1;
   else
@@ -598,8 +612,6 @@ static int
 set_trust_anchor(X509_STORE_CTX *ctx, ssl_dane *dane, X509 *cert)
 {
 int matched = 0;
-int n;
-int i;
 int depth = 0;
 EVP_PKEY *takey;
 X509 *ca;
@@ -635,8 +647,9 @@ if (!(in = sk_X509_dup(in)))
  *
  * Caller ensures that the initial certificate is not self-signed.
  */
-for (n = sk_X509_num(in); n > 0; --n, ++depth)
+for (int n = sk_X509_num(in); n > 0; --n, ++depth)
   {
+  int i;
   for (i = 0; i < n; ++i)
     if (X509_check_issued(sk_X509_value(in, i), cert) == X509_V_OK)
       break;
@@ -657,7 +670,7 @@ for (n = sk_X509_num(in); n > 0; --n, ++depth)
     {
     if (grow_chain(dane, UNTRUSTED, ca))
       {
-      if (!X509_check_issued(ca, ca) == X509_V_OK)
+      if (X509_check_issued(ca, ca) != X509_V_OK)
        {
        /* Restart with issuer as subject */
        cert = ca;
@@ -719,11 +732,12 @@ if (matched > 0)
     STACK_OF(X509) * sk = sk_X509_new_null();
     if (sk && sk_X509_push(sk, cert))
       {
-      X509_STORE_CTX_set0_verified_chain(ctx, sk);
       X509_up_ref(cert);
+      X509_STORE_CTX_set0_verified_chain(ctx, sk);
       }
     else
       {
+      if (sk) sk_X509_free(sk);
       DANEerr(DANESSL_F_CHECK_END_ENTITY, ERR_R_MALLOC_FAILURE);
       return -1;
       }
@@ -736,9 +750,8 @@ static int
 match_name(const char *certid, ssl_dane *dane)
 {
 int multi = dane->multi;
-dane_host_list hosts;
 
-for (hosts = dane->hosts; hosts; hosts = hosts->next)
+for (dane_host_list hosts = dane->hosts; hosts; hosts = hosts->next)
   {
   int match_subdomain = 0;
   const char *domain = hosts->value;
@@ -780,10 +793,10 @@ for (hosts = dane->hosts; hosts; hosts = hosts->next)
 return 0;
 }
 
-static char *
-check_name(char *name, int len)
+static const char *
+check_name(const char *name, int len)
 {
-char *cp = name + len;
+const char *cp = name + len;
 
 while (len > 0 && !*--cp)
   --len;                          /* Ignore trailing NULs */
@@ -804,14 +817,14 @@ if (cp - name != len)               /* Guard against internal NULs */
 return name;
 }
 
-static char *
+static const char *
 parse_dns_name(const GENERAL_NAME *gn)
 {
 if (gn->type != GEN_DNS)
   return 0;
 if (ASN1_STRING_type(gn->d.ia5) != V_ASN1_IA5STRING)
   return 0;
-return check_name((char *) ASN1_STRING_data(gn->d.ia5),
+return check_name(CCS  ASN1_STRING_get0_data(gn->d.ia5),
                  ASN1_STRING_length(gn->d.ia5));
 }
 
@@ -835,12 +848,12 @@ if (!(entry_str = X509_NAME_ENTRY_get_data(entry)))
 
 if ((len = ASN1_STRING_to_UTF8(&namebuf, entry_str)) < 0)
   return 0;
-if (len <= 0 || check_name((char *) namebuf, len) == 0)
+if (len <= 0 || check_name(CS  namebuf, len) == 0)
   {
   OPENSSL_free(namebuf);
   return 0;
   }
-return (char *) namebuf;
+return CS  namebuf;
 }
 
 static int
@@ -854,9 +867,8 @@ gens = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
 if (gens)
   {
   int n = sk_GENERAL_NAME_num(gens);
-  int i;
 
-  for (i = 0; i < n; ++i)
+  for (int i = 0; i < n; ++i)
     {
     const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
     const char *certid;
@@ -901,7 +913,8 @@ verify_chain(X509_STORE_CTX *ctx)
 {
 int (*cb)(int, X509_STORE_CTX *) = X509_STORE_CTX_get_verify_cb(ctx);
 X509 *cert = X509_STORE_CTX_get0_cert(ctx);
-int chain_length = sk_X509_num(X509_STORE_CTX_get0_chain(ctx));
+STACK_OF(X509) * chain = X509_STORE_CTX_get0_chain(ctx);
+int chain_length = sk_X509_num(chain);
 int ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx();
 SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_idx);
 ssl_dane *dane = SSL_get_ex_data(ssl, dane_idx);
@@ -911,6 +924,7 @@ int matched = 0;
 
 DEBUG(D_tls) debug_printf("Dane verify_chain\n");
 
+/* Restore OpenSSL's internal_verify() as the signature check function */
 X509_STORE_CTX_set_verify(ctx, dane->verify);
 
 if ((matched = name_check(dane, cert)) < 0)
@@ -934,17 +948,17 @@ matched = 0;
  * matched a usage 2 trust anchor.
  *
  * XXX: internal_verify() doesn't callback with top certs that are not
- * self-issued.  This should be fixed in a future OpenSSL.
+ * self-issued.  This is fixed in OpenSSL 1.1.0.
  */
 if (dane->roots && sk_X509_num(dane->roots))
   {
-  X509 *top = sk_X509_value(X509_STORE_CTX_get0_chain(ctx), dane->depth);
+  X509 *top = sk_X509_value(chain, dane->depth);
 
   dane->mdpth = dane->depth;
   dane->match = top;
   X509_up_ref(top);
 
-#ifndef NO_CALLBACK_WORKAROUND
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
   if (X509_check_issued(top, top) != X509_V_OK)
     {
     X509_STORE_CTX_set_error_depth(ctx, dane->depth);
@@ -955,7 +969,7 @@ if (dane->roots && sk_X509_num(dane->roots))
 #endif
   /* Pop synthetic trust-anchor ancestors off the chain! */
   while (--chain_length > dane->depth)
-      X509_free(sk_X509_pop(X509_STORE_CTX_get0_chain(ctx)));
+      X509_free(sk_X509_pop(chain));
   }
 else
   {
@@ -973,7 +987,7 @@ else
   if (!matched && issuer_rrs)
     for (n = chain_length-1; !matched && n >= 0; --n)
       {
-      xn = sk_X509_value(X509_STORE_CTX_get0_chain(ctx), n);
+      xn = sk_X509_value(chain, n);
       if (n > 0 || X509_check_issued(xn, xn) == X509_V_OK)
        matched = match(issuer_rrs, xn, n);
       }
@@ -996,7 +1010,8 @@ else
     }
   }
 
-return (X509_STORE_CTX_get_verify(ctx))(ctx);
+/* Tail recurse into OpenSSL's internal_verify */
+return dane->verify(ctx);
 }
 
 static void
@@ -1083,7 +1098,7 @@ if (dane->selectors[DANESSL_USAGE_DANE_EE])
        */
       X509_STORE_CTX_trusted_stack(ctx, dane->roots);
       X509_STORE_CTX_set_chain(ctx, dane->chain);
-      OPENSSL_assert(X509_STORE_CTX_get0_untrusted(ctx) == dane->chain);
+      OPENSSL_assert(dane->chain == X509_STORE_CTX_get0_untrusted(ctx));
       }
     }
 
@@ -1141,10 +1156,9 @@ return l;
 static void
 list_free(void *list, void (*f)(void *))
 {
-dane_list head;
 dane_list next;
 
-for (head = (dane_list) list; head; head = next)
+for (dane_list head = (dane_list) list; head; head = next)
   {
   next = head->next;
   if (f && head->value)
@@ -1153,10 +1167,16 @@ for (head = (dane_list) list; head; head = next)
   }
 }
 
+static void
+ossl_free(void * p)
+{
+OPENSSL_free(p);
+}
+
 static void
 dane_mtype_free(void *p)
 {
-list_free(((dane_mtype) p)->data, CRYPTO_free);
+list_free(((dane_mtype) p)->data, ossl_free);
 OPENSSL_free(p);
 }
 
@@ -1187,7 +1207,6 @@ void
 DANESSL_cleanup(SSL *ssl)
 {
 ssl_dane *dane;
-int u;
 
 DEBUG(D_tls) debug_printf("Dane lib-cleanup\n");
 
@@ -1197,8 +1216,8 @@ if (dane_idx < 0 || !(dane = SSL_get_ex_data(ssl, dane_idx)))
 
 dane_reset(dane);
 if (dane->hosts)
-  list_free(dane->hosts, CRYPTO_free);
-for (u = 0; u <= DANESSL_USAGE_LAST; ++u)
+  list_free(dane->hosts, ossl_free);
+for (int u = 0; u <= DANESSL_USAGE_LAST; ++u)
   if (dane->selectors[u])
     list_free(dane->selectors[u], dane_selector_free);
 if (dane->pkeys)
@@ -1218,7 +1237,7 @@ while (*src)
   dane_host_list elem = (dane_host_list) OPENSSL_malloc(sizeof(*elem));
   if (elem == 0)
     {
-    list_free(head, CRYPTO_free);
+    list_free(head, ossl_free);
     return 0;
     }
   elem->value = OPENSSL_strdup(*src++);
@@ -1259,28 +1278,36 @@ DANESSL_verify_chain(SSL *ssl, STACK_OF(X509) *chain)
 {
 int ret;
 X509 *cert;
-X509_STORE_CTX store_ctx;
+X509_STORE_CTX store_ctx;
 SSL_CTX *ssl_ctx = SSL_get_SSL_CTX(ssl);
 X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
 int store_ctx_idx = SSL_get_ex_data_X509_STORE_CTX_idx();
 
 cert = sk_X509_value(chain, 0);
-if (!X509_STORE_CTX_init(&store_ctx, store, cert, chain))
+if (!(store_ctx = X509_STORE_CTX_new()))
+  {
+  DANEerr(DANESSL_F_DANESSL_VERIFY_CHAIN, ERR_R_MALLOC_FAILURE);
+  return 0;
+  }
+if (!X509_STORE_CTX_init(store_ctx, store, cert, chain))
+  {
+  X509_STORE_CTX_free(store_ctx);
   return 0;
-X509_STORE_CTX_set_ex_data(&store_ctx, store_ctx_idx, ssl);
+  }
+X509_STORE_CTX_set_ex_data(store_ctx, store_ctx_idx, ssl);
 
-X509_STORE_CTX_set_default(&store_ctx,
+X509_STORE_CTX_set_default(store_ctx,
             SSL_is_server(ssl) ? "ssl_client" : "ssl_server");
-X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&store_ctx),
+X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(store_ctx),
             SSL_get0_param(ssl));
 
 if (SSL_get_verify_callback(ssl))
-  X509_STORE_CTX_set_verify_cb(&store_ctx, SSL_get_verify_callback(ssl));
+  X509_STORE_CTX_set_verify_cb(store_ctx, SSL_get_verify_callback(ssl));
 
-ret = verify_cert(&store_ctx, NULL);
+ret = verify_cert(store_ctx, NULL);
 
-SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(&store_ctx));
-X509_STORE_CTX_cleanup(&store_ctx);
+SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(store_ctx));
+X509_STORE_CTX_cleanup(store_ctx);
 
 return (ret);
 }
@@ -1340,38 +1367,38 @@ if (selector > DANESSL_SELECTOR_LAST)
   return 0;
   }
 
-    /* Support built-in standard one-digit mtypes */
-  if (mdname && *mdname && mdname[1] == '\0')
-    switch (*mdname - '0')
-    {
-    case DANESSL_MATCHING_FULL: mdname = 0;       break;
-    case DANESSL_MATCHING_2256: mdname = "sha256"; break;
-    case DANESSL_MATCHING_2512: mdname = "sha512"; break;
-    }
-  if (mdname && *mdname && (md = EVP_get_digestbyname(mdname)) == 0)
-    {
-    DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_DIGEST);
-    return 0;
-    }
-  if (mdname && *mdname && dlen != EVP_MD_size(md))
-    {
-    DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_DATA_LENGTH);
-    return 0;
-    }
-  if (!data)
-    {
-    DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_NULL_DATA);
-    return 0;
-    }
+/* Support built-in standard one-digit mtypes */
+if (mdname && *mdname && mdname[1] == '\0')
+  switch (*mdname - '0')
+  {
+  case DANESSL_MATCHING_FULL: mdname = 0;         break;
+  case DANESSL_MATCHING_2256: mdname = "sha256"; break;
+  case DANESSL_MATCHING_2512: mdname = "sha512"; break;
+  }
+if (mdname && *mdname && !(md = EVP_get_digestbyname(mdname)))
+  {
+  DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_DIGEST);
+  return 0;
+  }
+if (mdname && *mdname && dlen != EVP_MD_size(md))
+  {
+  DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_DATA_LENGTH);
+  return 0;
+  }
+if (!data)
+  {
+  DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_NULL_DATA);
+  return 0;
+  }
 
-  /*
  * Full Certificate or Public Key when NULL or empty digest name
  */
-  if (!mdname || !*mdname)
-    {
-    X509 *x = 0;
-    EVP_PKEY *k = 0;
-    const unsigned char *p = data;
+/*
+ * Full Certificate or Public Key when NULL or empty digest name
+ */
+if (!mdname || !*mdname)
+  {
+  X509 *x = 0;
+  EVP_PKEY *k = 0;
+  const unsigned char *p = data;
 
 #define xklistinit(lvar, ltype, var, freeFunc) do { \
          (lvar) = (ltype) OPENSSL_malloc(sizeof(*(lvar))); \
@@ -1449,7 +1476,7 @@ if (!m)
   {
   if ((m = (dane_mtype_list) list_alloc(sizeof(*m->value))) == 0)
     {
-    list_free(d, CRYPTO_free);
+    list_free(d, ossl_free);
     xkfreeret(0);
     }
   m->value->data = 0;
@@ -1506,7 +1533,6 @@ int
 DANESSL_init(SSL *ssl, const char *sni_domain, const char **hostnames)
 {
 ssl_dane *dane;
-int i;
 
 DEBUG(D_tls) debug_printf("Dane ssl_init\n");
 if (dane_idx < 0)
@@ -1545,7 +1571,7 @@ dane->multi = 0;                  /* Future SSL control interface */
 dane->count = 0;
 dane->hosts = 0;
 
-for (i = 0; i <= DANESSL_USAGE_LAST; ++i)
+for (int i = 0; i <= DANESSL_USAGE_LAST; ++i)
   dane->selectors[i] = 0;
 
 if (hostnames && (dane->hosts = host_list_init(hostnames)) == 0)
@@ -1590,31 +1616,6 @@ DANEerr(DANESSL_F_CTX_INIT, DANESSL_R_LIBRARY_INIT);
 return -1;
 }
 
-static int
-init_once(volatile int *value, int (*init)(void), void (*postinit)(void))
-{
-int wlock = 0;
-
-CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
-if (*value < 0)
-  {
-  CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
-  CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
-  wlock = 1;
-  if (*value < 0)
-    {
-    *value = init();
-    if (postinit)
-      postinit();
-    }
-  }
-if (wlock)
-    CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
-else
-    CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
-return *value;
-}
-
 static void
 dane_init(void)
 {
@@ -1622,10 +1623,15 @@ dane_init(void)
  * Store library id in zeroth function slot, used to locate the library
  * name.  This must be done before we load the error strings.
  */
+err_lib_dane = ERR_get_next_error_library();
+
 #ifndef OPENSSL_NO_ERR
-dane_str_functs[0].error |= ERR_PACK(err_lib_dane, 0, 0);
-ERR_load_strings(err_lib_dane, dane_str_functs);
-ERR_load_strings(err_lib_dane, dane_str_reasons);
+if (err_lib_dane > 0)
+  {
+  dane_str_functs[0].error |= ERR_PACK(err_lib_dane, 0, 0);
+  ERR_load_strings(err_lib_dane, dane_str_functs);
+  ERR_load_strings(err_lib_dane, dane_str_reasons);
+  }
 #endif
 
 /*
@@ -1650,6 +1656,32 @@ dane_idx = SSL_get_ex_new_index(0, 0, 0, 0, 0);
 }
 
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+static void
+run_once(volatile int * once, void (*init)(void))
+{
+int wlock = 0;
+
+CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
+if (!*once)
+  {
+  CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+  CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+  wlock = 1;
+  if (!*once)
+    {
+    *once = 1;
+    init();
+    }
+  }
+if (wlock)
+  CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+else
+  CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
+}
+#endif
+
+
 
 /*
 
@@ -1666,9 +1698,10 @@ Return
 int
 DANESSL_library_init(void)
 {
+static CRYPTO_ONCE once = CRYPTO_ONCE_STATIC_INIT;
+
 DEBUG(D_tls) debug_printf("Dane lib-init\n");
-if (err_lib_dane < 0)
-  init_once(&err_lib_dane, ERR_get_next_error_library, dane_init);
+(void) CRYPTO_THREAD_run_once(&once, dane_init);
 
 #if defined(LN_sha256)
 /* No DANE without SHA256 support */
@@ -1680,6 +1713,5 @@ return 0;
 }
 
 
-#endif /* OPENSSL_VERSION_NUMBER */
 /* vi: aw ai sw=2
 */