DANE support structures, constructructors and accessors
authorViktor Dukhovni <openssl-users@dukhovni.org>
Tue, 29 Dec 2015 18:28:28 +0000 (13:28 -0500)
committerViktor Dukhovni <openssl-users@dukhovni.org>
Wed, 6 Jan 2016 00:31:49 +0000 (19:31 -0500)
Also tweak some of the code in demos/bio, to enable interactive
testing of BIO_s_accept's use of SSL_dup.  Changed the sconnect
client to authenticate the server, which now exercises the new
SSL_set1_host() function.

Reviewed-by: Richard Levitte <levitte@openssl.org>
21 files changed:
crypto/x509/x509_vfy.c
crypto/x509/x509_vpm.c
demos/bio/client-arg.c
demos/bio/client-conf.c
demos/bio/saccept.c
demos/bio/sconnect.c
demos/bio/server.pem
doc/crypto/X509_VERIFY_PARAM_set_flags.pod
doc/ssl/SSL_CTX_dane_enable.pod [new file with mode: 0644]
doc/ssl/SSL_set1_host.pod [new file with mode: 0644]
doc/ssl/ssl.pod
include/internal/dane.h [new file with mode: 0644]
include/openssl/safestack.h
include/openssl/ssl.h
include/openssl/x509_vfy.h
ssl/record/rec_layer_s3.c
ssl/record/record.h
ssl/ssl_cert.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h

index 57fcf91..1c509a9 100644 (file)
@@ -70,6 +70,7 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 #include <openssl/objects.h>
+#include <internal/dane.h>
 #include <internal/x509_int.h>
 #include "x509_lcl.h"
 
@@ -2072,6 +2073,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
     ctx->current_reasons = 0;
     ctx->tree = NULL;
     ctx->parent = NULL;
+    ctx->dane = NULL;
     /* Zero ex_data to make sure we're cleanup-safe */
     memset(&ctx->ex_data, 0, sizeof(ctx->ex_data));
 
@@ -2263,6 +2265,11 @@ void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
     ctx->param = param;
 }
 
+void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, struct dane_st *dane)
+{
+    ctx->dane = dane;
+}
+
 static int build_chain(X509_STORE_CTX *ctx)
 {
     int (*cb) (int, X509_STORE_CTX *) = ctx->verify_cb;
index 2a15f82..827360d 100644 (file)
@@ -444,6 +444,24 @@ char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
     return param->peername;
 }
 
+/*
+ * Move peername from one param structure to another, freeing any name present
+ * at the target.  If the source is a NULL parameter structure, free and zero
+ * the target peername.
+ */
+void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *to,
+                                     X509_VERIFY_PARAM *from)
+{
+    char *peername = (from != NULL) ? from->peername : NULL;
+
+    if (to->peername != peername) {
+        OPENSSL_free(to->peername);
+        to->peername = peername;
+    }
+    if (from)
+        from->peername = NULL;
+}
+
 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
                                  const char *email, size_t emaillen)
 {
index 99ebff1..630b166 100644 (file)
@@ -1,3 +1,4 @@
+#include <string.h>
 #include <openssl/err.h>
 #include <openssl/ssl.h>
 
@@ -56,7 +57,7 @@ int main(int argc, char **argv)
     if (!SSL_CONF_CTX_finish(cctx)) {
         fprintf(stderr, "Finish error\n");
         ERR_print_errors_fp(stderr);
-        goto err;
+        goto end;
     }
 
     /*
index 2a78315..4e4d4bc 100644 (file)
@@ -1,3 +1,4 @@
+#include <string.h>
 #include <openssl/err.h>
 #include <openssl/ssl.h>
 #include <openssl/conf.h>
@@ -64,7 +65,7 @@ int main(int argc, char **argv)
     if (!SSL_CONF_CTX_finish(cctx)) {
         fprintf(stderr, "Finish error\n");
         ERR_print_errors_fp(stderr);
-        goto err;
+        goto end;
     }
 
     /*
index 0d173aa..b6d0361 100644 (file)
 
 #define CERT_FILE       "server.pem"
 
-BIO *in = NULL;
+static int done = 0;
 
-void close_up()
+void interrupt()
 {
-    BIO_free(in);
+    done = 1;
+}
+
+void sigsetup(void)
+{
+    struct sigaction sa;
+
+    /*
+     * Catch at most once, and don't restart the accept system call.
+     */
+    sa.sa_flags = SA_RESETHAND;
+    sa.sa_handler = interrupt;
+    sigemptyset(&sa.sa_mask);
+    sigaction(SIGINT, &sa, NULL);
 }
 
 int main(int argc, char *argv[])
 {
     char *port = NULL;
+    BIO *in = NULL;
     BIO *ssl_bio, *tmp;
     SSL_CTX *ctx;
     char buf[512];
@@ -38,15 +52,13 @@ int main(int argc, char *argv[])
     else
         port = argv[1];
 
-    signal(SIGINT, close_up);
-
     SSL_load_error_strings();
 
     /* Add ciphers and message digests */
     OpenSSL_add_ssl_algorithms();
 
     ctx = SSL_CTX_new(TLS_server_method());
-    if (!SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM))
+    if (!SSL_CTX_use_certificate_chain_file(ctx, CERT_FILE))
         goto err;
     if (!SSL_CTX_use_PrivateKey_file(ctx, CERT_FILE, SSL_FILETYPE_PEM))
         goto err;
@@ -66,6 +78,9 @@ int main(int argc, char *argv[])
      */
     BIO_set_accept_bios(in, ssl_bio);
 
+    /* Arrange to leave server loop on interrupt */
+    sigsetup();
+
  again:
     /*
      * The first call will setup the accept socket, and the second will get a
@@ -76,7 +91,7 @@ int main(int argc, char *argv[])
     if (BIO_do_accept(in) <= 0)
         goto err;
 
-    for (;;) {
+    while (!done) {
         i = BIO_read(in, buf, 512);
         if (i == 0) {
             /*
index 865d503..2b610cc 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <string.h>
 #include <openssl/err.h>
 #include <openssl/ssl.h>
 
+#define HOSTPORT "localhost:4433"
+#define CAFILE "root.pem"
+
 extern int errno;
 
 int main(argc, argv)
 int argc;
 char *argv[];
 {
-    char *host;
-    BIO *out;
+    const char *hostport = HOSTPORT;
+    const char *CAfile = CAFILE;
+    char *hostname;
+    char *cp;
+    BIO *out = NULL;
     char buf[1024 * 10], *p;
     SSL_CTX *ssl_ctx = NULL;
     SSL *ssl;
     BIO *ssl_bio;
     int i, len, off, ret = 1;
 
-    if (argc <= 1)
-        host = "localhost:4433";
-    else
-        host = argv[1];
+    if (argc > 1)
+        hostport = argv[1];
+    if (argc > 2)
+        CAfile = argv[2];
+
+    hostname = OPENSSL_strdup(hostport);
+    if ((cp = strchr(hostname, ':')) != NULL)
+        *cp = 0;
 
 #ifdef WATT32
     dbug_init();
@@ -45,17 +56,25 @@ char *argv[];
     OpenSSL_add_ssl_algorithms();
     ssl_ctx = SSL_CTX_new(TLS_client_method());
 
+    /* Enable trust chain verification */
+    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
+    SSL_CTX_load_verify_locations(ssl_ctx, CAfile, NULL);
+
     /* Lets make a SSL structure */
     ssl = SSL_new(ssl_ctx);
     SSL_set_connect_state(ssl);
 
+    /* Enable peername verification */
+    if (SSL_set1_host(ssl, hostname) <= 0)
+        goto err;
+
     /* Use it inside an SSL BIO */
     ssl_bio = BIO_new(BIO_f_ssl());
     BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
 
     /* Lets use a connect BIO under the SSL BIO */
     out = BIO_new(BIO_s_connect());
-    BIO_set_conn_hostname(out, host);
+    BIO_set_conn_hostname(out, hostport);
     BIO_set_nbio(out, 1);
     out = BIO_push(ssl_bio, out);
 
index ef0d22a..8a4a51f 100644 (file)
@@ -1,26 +1,52 @@
 subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = Test Server Cert
 issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA
 -----BEGIN CERTIFICATE-----
-MIIDpTCCAo2gAwIBAgIJAK8ArbvjIOQlMA0GCSqGSIb3DQEBCwUAMHAxCzAJBgNV
+MIIDyTCCArGgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVSzEW
+MBQGA1UECgwNT3BlblNTTCBHcm91cDEiMCAGA1UECwwZRk9SIFRFU1RJTkcgUFVS
+UE9TRVMgT05MWTElMCMGA1UEAwwcT3BlblNTTCBUZXN0IEludGVybWVkaWF0ZSBD
+QTAgFw0xNjAxMDQwODU0NDZaGA8yMTE2MDEwNTA4NTQ0NlowZDELMAkGA1UEBhMC
+VUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBURVNUSU5H
+IFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgU2VydmVyIENlcnQwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDzhPOSNtyyRspmeuUpxfNJKCLTuf7g
+3uQ4zu4iHOmRO5TQci+HhVlLZrHF9XqFXcIP0y4pWDbMSGuiorUmzmfiR7bfSdI/
++qIQt8KXRH6HNG1t8ou0VSvWId5TS5Dq/er5ODUr9OaaDva7EquHIcMvvPQGuI+O
+EAcnleVCy9HVEIySrO4P3CNIicnGkwwiAud05yUAq/gPXBC1hTtmlPD7TVcGVSEi
+Jdvzqqlgv02qedGrkki6GY4S7GjZxrrf7Foc2EP+51LJzwLQx3/JfrCU41NEWAsu
+/Sl0tQabXESN+zJ1pDqoZ3uHMgpQjeGiE0olr+YcsSW/tJmiU9OiAr8RAgMBAAGj
+eDB2MB0GA1UdDgQWBBSCvM8AABPR9zklmifnr9LvIBturDAfBgNVHSMEGDAWgBQ2
+w2yI55X+sL3szj49hqshgYfa2jAJBgNVHRMEAjAAMBMGA1UdJQQMMAoGCCsGAQUF
+BwMBMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAC78R
+sAr4uvkYOu/pSwQ3MYOFqZ0BnPuP0/AZW2zF7TLNy8g36GyH9rKxz2ffQEHRmPQN
+Z11Ohg3z03jw/sVzkgt2U5Ipv923sSeCZcu0nuNex3v9/x72ldYikZNhQOsw+2kr
+hx3OvE9R7xl9eyjz7BknsbY7PC3kiUY8SDdc5Fr/XMkHm3ge65oWYOHBjC5tAr5K
+FGCEjM3syxS+Li5X6yfDGiVSjOU4gJuZDCYbl7cEQexU2deds8EmpJJrrI7s4JcQ
+rraHI8+Hu8X9VLpZE1jl/fKJw3D0i53PoN2WhukIOg1Zv+ajMKQ4ubVfISH2ebox
++ybAZO8hxL6/I08/GQ==
+-----END CERTIFICATE-----
+subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA
+issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Root CA
+-----BEGIN CERTIFICATE-----
+MIIDvjCCAqagAwIBAgIJAPzCy4CUW9/qMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV
 BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT
-VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt
-ZWRpYXRlIENBMB4XDTE1MDcxNDEzMjIwNVoXDTI1MDUyMjEzMjIwNVowZDELMAkG
-A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU
-RVNUSU5HIFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgU2VydmVyIENlcnQw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDzhPOSNtyyRspmeuUpxfNJ
-KCLTuf7g3uQ4zu4iHOmRO5TQci+HhVlLZrHF9XqFXcIP0y4pWDbMSGuiorUmzmfi
-R7bfSdI/+qIQt8KXRH6HNG1t8ou0VSvWId5TS5Dq/er5ODUr9OaaDva7EquHIcMv
-vPQGuI+OEAcnleVCy9HVEIySrO4P3CNIicnGkwwiAud05yUAq/gPXBC1hTtmlPD7
-TVcGVSEiJdvzqqlgv02qedGrkki6GY4S7GjZxrrf7Foc2EP+51LJzwLQx3/JfrCU
-41NEWAsu/Sl0tQabXESN+zJ1pDqoZ3uHMgpQjeGiE0olr+YcsSW/tJmiU9OiAr8R
-AgMBAAGjTjBMMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgXgMCwGCWCGSAGG
-+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0B
-AQsFAAOCAQEAq8v8dvU3Xskb7q5LKbLXxTIF6owFs5uLk2k2msEAQzX7SrYFZwdE
-5e33S71rpDbXiJjyD4Yj0Av5yeRlW0YVFlBZAwgPn29CDCD6+DeQ7AwtXvJhcq9e
-llTLpB1EuXC5UCerQmq99wmfTrK0q4hgK7/5c7mcoD7V1iOEvxI2kmG6ukIupbKi
-P1TNVVET1kPhRG1dFP9rge7j2ssY3/H+j3jlAJnwQQoYg+YCZ6g0atjOrqvywAy3
-5E2d9LPF3TKw2mf4mAxjU6hPDOk0tiMS6g1xdHyeTftPXfN8Gli0T0LpNpy5a24B
-dLPqZEpj0kXT8gTYEROX7tq9gYwpe6FVKw==
+VElORyBQVVJQT1NFUyBPTkxZMR0wGwYDVQQDDBRPcGVuU1NMIFRlc3QgUm9vdCBD
+QTAeFw0xNTA3MTQxMzIyMDVaFw0yNTA2MjExMzIyMDVaMHAxCzAJBgNVBAYTAlVL
+MRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVTVElORyBQ
+VVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJtZWRpYXRl
+IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsErw75CmLYD6pkrG
+W/YhAl/K8L5wJYxDjqu2FghxjD8K308W3EHq4uBxEwR1OHXaM1+6ZZw7/r2I37VL
+IdurBEAIEUdbzx0so74FPawgz5EW2CTqoJnK8F71/vo5Kj1VPwW46CxwxUR3cfvJ
+GNXND2ip0TcyTSPLROXOyQakcVfIGJmdSa1wHKi+c2gMA4emADudZUOYLrg80gr2
+ldePm07ynbVsKKzCcStw8MdmoW9Qt3fLnPJn2TFUUBNWj+4kvL+88edWCVQXKNds
+ysD/CDrH4W/hjyPDStVsM6XpiNU0+L2ZY6fcj3OP8d0goOx45xotMn9m8hNkCGsr
+VXx9IwIDAQABo2MwYTAdBgNVHQ4EFgQUNsNsiOeV/rC97M4+PYarIYGH2towHwYD
+VR0jBBgwFoAUjBkP10IxdwUG4dOxn+s5+3hxOkUwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAANQT0pDWBQoT/RY76xz
+audadGz/dfYnwvSwT0RMFcXLcMVVRNqP0HeR8OP8qLaP7onRbNnEXNfos9pxXYlg
+j+/WjWTBLVcr3pX2Xtmcaqw3CGN9qbQI8B3JkYeijZmc5+3r5MzK/9R0w8Y/T9Xt
+CXEiQhtWHpPrFEfrExeVy2kjJNRctEfq3OTd1bjgX64zvTU7eR+MHFYKPoyMqwIR
+gjoVKinvovEwWoZe5kfMQwJNA3IgoJexX9BXbS8efAYF/ku3tS0laoZS/q6V/o5I
+RvG0OqnNgxhul+96PE5ujSaprsyvBswIUKt+e/BCxGaS6f2AJ8RmtoPOSfT4b9qN
+thI=
 -----END CERTIFICATE-----
 -----BEGIN RSA PRIVATE KEY-----
 MIIEpAIBAAKCAQEA84TzkjbcskbKZnrlKcXzSSgi07n+4N7kOM7uIhzpkTuU0HIv
index df5766c..a2219d2 100644 (file)
@@ -127,7 +127,7 @@ IPv6.  The condensed "::" notation is supported for IPv6 addresses.
 X509_VERIFY_PARAM_set_flags(), X509_VERIFY_PARAM_clear_flags(),
 X509_VERIFY_PARAM_set_purpose(), X509_VERIFY_PARAM_set_trust(),
 X509_VERIFY_PARAM_add0_policy() X509_VERIFY_PARAM_set1_policies(),
-X509_VERIFY_PARAM_set1_host(), X509_VERIFY_PARAM_set_hostflags(),
+X509_VERIFY_PARAM_set1_host(), X509_VERIFY_PARAM_add1_host(),
 X509_VERIFY_PARAM_set1_email(), X509_VERIFY_PARAM_set1_ip() and
 X509_VERIFY_PARAM_set1_ip_asc() return 1 for success and 0 for
 failure.
diff --git a/doc/ssl/SSL_CTX_dane_enable.pod b/doc/ssl/SSL_CTX_dane_enable.pod
new file mode 100644 (file)
index 0000000..66eb1b3
--- /dev/null
@@ -0,0 +1,278 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_dane_enable, SSL_CTX_dane_mtype_set, SSL_dane_enable,
+SSL_dane_tlsa_add, SSL_get0_dane_authority, SSL_get0_dane_tlsa -
+enable DANE TLS authentication of the remote TLS server in the local
+TLS client
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ int SSL_CTX_dane_enable(SSL_CTX *ctx);
+ int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md,
+                            uint8_t mtype, uint8_t ord);
+ int SSL_dane_enable(SSL *s, const char *basedomain);
+ int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
+                       uint8_t mtype, unsigned char *data, size_t dlen);
+ int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki);
+ int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
+                        uint8_t *mtype, unsigned const char **data,
+                        size_t *dlen);
+
+=head1 DESCRIPTION
+
+These functions implement support for DANE TLSA (RFC6698 and RFC7671)
+peer authentication.
+
+SSL_CTX_dane_enable() must be called first to initialize the
+shared state required for DANE support.  Individual connections
+associated with the context can then enable per-connection DANE
+support as appropriate.  DANE authentication is implemented in the
+L<X509_verify_cert(3)> function, and applications that override
+L<X509_verify_cert(3)> via L<SSL_CTX_set_cert_verify_callback(3)>
+are responsible to authenticate the peer chain in whatever manner
+they see fit.
+
+SSL_CTX_dane_mtype_set() may then be called zero or more times to
+to adjust the supported digest algorithms.  This must be done before
+any SSL handles are created for the context.
+
+The B<mtype> argument specifies a DANE TLSA matching type and the
+the B<md> argument specifies the associated digest algorithm handle.
+The B<ord> argument specifies a strength ordinal.  Algorithms with
+a larger strength ordinal are considered more secure.  Strength
+ordinals are used to implement RFC7671 digest algorithm agility.
+Specifying a B<NULL> digest algorithm for a matching type disables
+support for that matching type.  Matching type Full(0) cannot be
+modified or disabled.
+
+By default, matching type C<SHA2-256(1)> (see RFC7218 for definitions
+of the DANE TLSA parameter acronyms) is mapped to C<EVP_sha256()>
+with a strength ordinal of C<1> and matching type C<SHA2-512(2)>
+is mapped to C<EVP_sha512()> with a strength ordinal of C<2>.
+
+SSL_dane_enable() may be called before the SSL handshake is
+initiated with L<SSL_connect(3)> to enable DANE for that connection.
+(The connection must be associated with a DANE-enabled SSL context).
+The B<basedomain> argument specifies the RFC7671 TLSA base domain,
+which will be the primary peer reference identifier for certificate
+name checks.  Additional server names can be specified via
+L<SSL_add1_host(3)>.  The B<basedomain> is used as the default SNI
+hint if none has yet been specified via L<SSL_set_tlsext_host_name(3)>.
+
+SSL_dane_tlsa_add() may then be called one or more times, to
+load each of the TLSA records that apply to the remote TLS peer.
+(This too must be done prior to the beginning of the SSL handshake).
+The arguments specify the fields of the TLSA record.  The B<data>
+field is provided in binary (wire RDATA) form, not the hexadecimal ASCII
+presentation form, with an explicit length passed via B<dlen>.
+A return value of 0 indicates that "unusable" TLSA records
+(with invalid or unsupported parameters) were provided, a negative
+return value indicates an internal error in processing the records.
+If DANE authentication is enabled, but no TLSA records are added
+successfully, authentication will fail, and the handshake may not
+complete, depending on the B<mode> argument of L<SSL_set_verify(3)>
+and any verification callback.
+
+SSL_get0_dane_authority() can be used to get more detailed information
+about the matched DANE trust-anchor after successful connection
+completion.  The return value is negative if DANE verification
+failed (or was not enabled), 0 if an EE TLSA record directly matched
+the leaf certificate, or a positive number indicating the depth at
+which a TA record matched an issuer certificate.
+
+If the B<mcert> argument is not B<NULL> and a TLSA record matched
+a chain certificate, a pointer to the matching certificate is
+returned via B<mcert>.  The returned address is a short-term internal
+reference to the certificate and must not be freed by the application.
+Applications that want to retain access to the certificate can call
+L<X509_up_ref(3)> to obtain a long-term reference which must then
+be freed via L<X509_free(3)> once no longer needed.
+
+If no TLSA records directly matched any elements of the certificate
+chain, but a DANE-TA(2) SPKI(1) Full(0) record provided the public
+key that signed an element of the chain, then that key is returned
+via B<mspki> argument (if not NULL).  In this case the return value
+is the depth of the top-most element of the validated certificate
+chain.  As with B<mcert> this is a short-term internal reference,
+and L<EVP_PKEY_up_ref(3)> and L<EVP_PKEY_free(3)> can be used to
+acquire and release long-term references respectively.
+
+SSL_get0_dane_tlsa() can be used to retrieve the fields of the
+TLSA record that matched the peer certificate chain.  The return
+value indicates the match depth or failure to match just as with
+SSL_get0_dane_authority().  When the return value is non-negative,
+the storage pointed to by the B<usage>, B<selector>, B<mtype> and
+B<data> parameters is updated to the corresponding TLSA record
+fields.  The B<data> field is in binary wire form, and is therefore
+not NUL-terminated, its length is returned via the B<dlen> parameter.
+If any of these parameters is NULL, the corresponding field
+is not returned.  The B<data> parameter is set to a short-term
+internal-copy of the associated data field and must not be freed
+by the application.  Applications that need long-term access to
+this field need to copy the content.
+
+=head1 RETURN VALUES
+
+The functions SSL_CTX_dane_enable(), SSL_CTX_dane_mtype_set(),
+SSL_dane_enable() and SSL_dane_tlsa_add() return a positive value
+on success.  Negative return values indicate resource problems (out
+of memory, etc.) in the SSL library, while a return value of B<0>
+indicates incorrect usage or invalid input, such as an unsupported
+TLSA record certificate usage, selector or matching type.  Invalid
+input also includes malformed data, either a digest length that
+does not match the digest algorithm, or a C<Full(0)> (binary ASN.1
+DER form) certificate or a public key that fails to parse.
+
+The functions SSL_get0_dane_authority() and SSL_get0_dane_tlsa()
+return a negative value when DANE authentication failed or was not
+enabled, a non-negative value indicates the chain depth at which
+the TLSA record matched a chain certificate, or the depth of the
+top-most certificate, when the TLSA record is a full public key
+that is its signer.
+
+=head1 EXAMPLE
+
+Suppose "smtp.example.com" is the MX host of the domain "example.com",
+and has DNSSEC-validated TLSA records.  The calls below will perform
+DANE authentication and arrange to match either the MX hostname or
+the destination domain name in the SMTP server certificate.  Wildcards
+are supported, but must match the entire label.  The actual name
+matched in the certificate (which might be a wildcard) is retrieved,
+and must be copied by the application if it is to be retained beyond
+the lifetime of the SSL connection.
+
+  SSL_CTX *ctx;
+  SSL *ssl;
+  int num_usable = 0;
+  const char *nexthop_domain = "example.com";
+  const char *dane_tlsa_domain = "smtp.example.com";
+  uint8_t usage, selector, mtype;
+
+  if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL)
+    /* handle error */
+  if (SSL_CTX_dane_enable(ctx) <= 0)
+    /* handle error */
+
+  if ((ssl = SSL_new(ctx)) == NULL)
+    /* handle error */
+
+  if (SSL_dane_enable(ssl, dane_tlsa_domain) <= 0)
+    /* handle error */
+  if (!SSL_add1_host(ssl, nexthop_domain))
+    /* handle error */
+  SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+
+  for (... each TLSA record ...) {
+    unsigned char *data;
+    size_t len;
+    int ret;
+
+    /* set usage, selector, mtype, data, len */
+
+    /* Opportunistic DANE TLS clients treat usages 0, 1 as unusable. */
+    switch (usage) {
+    case 0:     /* PKIX-TA(0) */
+    case 1:     /* PKIX-EE(1) */
+        continue;
+    }
+
+    ret = SSL_dane_tlsa_add(ssl, usage, selector, mtype, data, len);
+    /* free data as approriate */
+
+    if (ret < 0)
+        /* handle SSL library internal error */
+    else if (ret == 0)
+        /* handle unusable TLSA record */
+    else
+      ++num_usable;
+  }
+
+  /*
+   * Opportunistic DANE clients use unauthenticated TLS when all TLSA records
+   * are unusable, so continue the handshake even if authentication fails.
+   */
+  if (num_usable == 0) {
+    int (*cb)(int ok, X509_STORE_CTX *sctx) = NULL;
+
+    /* Log all records unusable? */
+    /* Set cb to a non-NULL callback of your choice? */
+
+    SSL_set_verify(ssl, SSL_VERIFY_NONE, cb);
+  }
+
+  /* Perform SSL_connect() handshake and handle errors here */
+
+  if (SSL_get_verify_result(ssl) == X509_V_OK) {
+    const char *peername = SSL_get0_peername(ssl);
+    EVP_PKEY *mspki = NULL;
+
+    int depth = SSL_get0_dane_authority(s, NULL, &mspki);
+    if (depth >= 0) {
+        (void) SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, NULL, NULL);
+        printf("DANE TLSA %d %d %d %s at depth %d\n", usage, selector, mtype,
+               (mspki != NULL) ? "TA public key verified certificate" :
+               depth ? "matched TA certificate" : "matched EE certificate",
+               depth);
+    }
+    if (peername != NULL) {
+      /* Name checks were in scope and matched the peername */
+      printf(bio, "Verified peername: %s\n", peername);
+    }
+  } else {
+    /*
+     * Not authenticated, presumably all TLSA rrs unusable, but possibly a
+     * callback suppressed connection termination despite presence of TLSA
+     * usable RRs none of which matched.  Do whatever is appropriate for
+     * unauthenticated connections.
+     */
+  }
+
+=head1 NOTES
+
+It is expected that the majority of clients employing DANE TLS will
+be doing "opportunistic DANE TLS" in the sense of RFC7672 and
+RFC7435.  That is, they will use DANE authentication when
+DNSSEC-validated TLSA records are published for a given peer, and
+otherwise will use unauthenticated TLS or even cleartext.
+
+Such applications should generally treat any TLSA records published
+by the peer with usages PKIX-TA(0) and PKIX-EE(1) as "unusable",
+and should not include them among the TLSA records used to authenticate
+peer connections.  In addition, some TLSA records with supported
+usages may be "unusable" as a result of invalid or unsupported
+parameters.
+
+When a peer has TLSA records, but none are "usable",  an opportunistic
+application must avoid cleartext, but cannot authenticate the peer,
+and so should generally proceed with an unauthenticated connection.
+Opportunistic applications need to note the return value of each
+call to SSL_dane_tlsa_add(), and if all return 0 (due to invalid
+or unsupported parameters) disable peer authentication by calling
+L<SSL_set_verify(3)> with B<mode> equal to B<SSL_VERIFY_NONE>.
+
+=head1 SEE ALSO
+
+L<SSL_new(3)>,
+L<SSL_add1_host(3)>,
+L<SSL_set_hostflags(3)>,
+L<SSL_set_tlsext_host_name(3)>,
+L<SSL_set_verify(3)>,
+L<SSL_CTX_set_cert_verify_callback(3)>,
+L<X509_verify_cert(3)>,
+L<SSL_connect(3)>,
+L<SSL_get0_peername(3)>,
+L<EVP_get_digestbyname(3)>,
+L<X509_up_ref(3)>,
+L<X509_free(3)>,
+L<EVP_PKEY_up_ref(3)>,
+L<EVP_PKEY_free(3)>
+
+=head1 HISTORY
+
+These functions were first added to OpenSSL 1.1.0.
+
+=cut
diff --git a/doc/ssl/SSL_set1_host.pod b/doc/ssl/SSL_set1_host.pod
new file mode 100644 (file)
index 0000000..b008a5f
--- /dev/null
@@ -0,0 +1,115 @@
+=pod
+
+=head1 NAME
+
+ SSL_set1_host, SSL_add1_host, SSL_set_hostflags, SSL_get0_peername -
+ SSL server verification parameters
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+ #include <openssl/x509_vfy.h>
+
+ int SSL_set1_host(SSL *s, const char *hostname);
+ int SSL_add1_host(SSL *s, const char *hostname);
+ void SSL_set_hostflags(SSL *s, unsigned int flags);
+ const char *SSL_get0_peername(SSL *s);
+
+=head1 DESCRIPTION
+
+These functions configure server hostname checks in the SSL client.
+
+SSL_set1_host() sets the expected DNS hostname to B<name> clearing
+any previously specified host name or names.  If B<name> is NULL,
+or the empty string the list of hostnames is cleared, and name
+checks are not performed on the peer certificate.  When a non-empty
+B<name> is specified, certificate verification automatically checks
+the peer hostname via L<X509_check_host(3)> with B<flags> as specified
+via SSL_set_hostflags().  Clients that enable DANE TLSA authentication
+via L<SSL_dane_enable(3)> should leave it to that function to set
+the primary reference identifier of the peer, and should not call
+SSL_set1_host().
+
+SSL_add1_host() adds B<name> as an additional reference identifier
+that can match the peer's certificate.  Any previous names set via
+SSL_set1_host() or SSL_add1_host() are retained, no change is made
+if B<name> is NULL or empty.  When multiple names are configured,
+the peer is considered verified when any name matches.  This function
+is required for DANE TLA in the presence of service name indirection
+via CNAME, MX or SRV records as specified in RFC7671, RFC7672 or
+RFC7673.
+
+SSL_set_hostflags() sets the B<flags> that will be passed to
+L<X509_check_host(3)> when name checks are applicable, by default
+the B<flags> value is 0.  See L<X509_check_host(3)> for the list
+of available flags and their meaning.
+
+SSL_get0_peername() returns the DNS hostname or subject CommonName
+from the peer certificate that matched one of the reference
+identifiers.  When wildcard matching is not disabled, the name
+matched in the peer certificate may be a wildcard name.  When one
+of the reference identifiers configured via SSL_set1_host() or
+SSL_add1_host() starts with ".", which indicates a parent domain prefix
+rather than a fixed name, the matched peer name may be a sub-domain
+of the reference identifier.  The returned string is allocated by
+the library and is no longer valid once the associated B<ssl> handle
+is cleared or freed, or a renegotiation takes place.  Applications
+must not free the return value.
+
+SSL clients are advised to use these functions in preference to
+explicitly calling L<X509_check_host(3)>.  Hostname checks are out
+of scope with the RFC7671 DANE-EE(3) certificate usage, and the
+internal check will be suppressed as appropriate when DANE is
+enabled.
+
+=head1 RETURN VALUES
+
+SSL_set1_host() and SSL_add1_host() return 1 for success and 0 for
+failure.
+
+SSL_get0_peername() returns NULL if peername verification is not
+applicable (as with RFC7671 DANE-EE(3)), or no trusted peername was
+matched.  Otherwise, it returns the matched peername.  To determine
+whether verification succeeded call L<SSL_get_verify_result(3)>.
+
+=head1 NOTES
+
+=head1 EXAMPLE
+
+Suppose "smtp.example.com" is the MX host of the domain "example.com".
+The calls below will arrange to match either the MX hostname or the
+destination domain name in the SMTP server certificate.  Wildcards
+are supported, but must match the entire label.  The actual name
+matched in the certificate (which might be a wildcard) is retrieved,
+and must be copied by the application if it is to be retained beyond
+the lifetime of the SSL connection.
+
+  SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+  if (!SSL_set1_host(ssl, "smtp.example.com")) {
+    /* handle error */
+  }
+  if (!SSL_add1_host(ssl, "example.com")) {
+    /* handle error */
+  }
+
+  /* XXX: Perform SSL_connect() handshake and handle errors here */
+
+  if (SSL_get_verify_result(ssl) == X509_V_OK) {
+      const char *peername = SSL_get0_peername(ssl);
+
+      if (peername != NULL) {
+          /* Name checks were in scope and matched the peername */
+      }
+  }
+
+=head1 SEE ALSO
+
+L<X509_check_host(3)>,
+L<SSL_get_verify_result(3)>.
+L<SSL_dane_enable(3)>.
+
+=head1 HISTORY
+
+These functions were first added to OpenSSL 1.1.0.
+
+=cut
index adcec5f..bb3bc94 100644 (file)
@@ -447,6 +447,25 @@ success or 0 on failure.
 
 =item SSL *B<SSL_dup>(SSL *ssl);
 
+SSL_dup() allows applications to configure an SSL handle for use
+in multiple SSL connections, and then duplicate it prior to initiating
+each connection with the duplicated handle.
+Use of SSL_dup() avoids the need to repeat the configuration of the
+handles for each connection.
+This is used internally by L<BIO_s_accept(3)> to construct
+per-connection SSL handles after L<accept(2)>.
+
+For SSL_dup() to work, the connection MUST be in its initial state
+and MUST NOT have not yet have started the SSL handshake.
+For connections that are not in their initial state SSL_dup() just
+increments an internal reference count and returns the I<same>
+handle.
+It may be possible to use L<SSL_clear(3)> to recycle an SSL handle
+that is not in its initial state for re-use, but this is best
+avoided.
+Instead, save and restore the session, if desired, and construct a
+fresh handle for each connection.
+
 =item STACK *B<SSL_dup_CA_list>(STACK *sk);
 
 =item void B<SSL_free>(SSL *ssl);
diff --git a/include/internal/dane.h b/include/internal/dane.h
new file mode 100644 (file)
index 0000000..cbe33f3
--- /dev/null
@@ -0,0 +1,147 @@
+/* dane.h */
+/*
+ * Written by Viktor Dukhovni (viktor@openssl.org) for the OpenSSL project
+ * 2015.
+ */
+/* ====================================================================
+ * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#ifndef HEADER_INTERNAL_DANE_H
+#define HEADER_INTERNAL_DANE_H
+
+#include <openssl/safestack.h>
+
+/*-
+ * Certificate usages:
+ * https://tools.ietf.org/html/rfc6698#section-2.1.1
+ */
+#define DANETLS_USAGE_PKIX_TA   0
+#define DANETLS_USAGE_PKIX_EE   1
+#define DANETLS_USAGE_DANE_TA   2
+#define DANETLS_USAGE_DANE_EE   3
+#define DANETLS_USAGE_LAST      DANETLS_USAGE_DANE_EE
+
+/*-
+ * Selectors:
+ * https://tools.ietf.org/html/rfc6698#section-2.1.2
+ */
+#define DANETLS_SELECTOR_CERT   0
+#define DANETLS_SELECTOR_SPKI   1
+#define DANETLS_SELECTOR_LAST   DANETLS_SELECTOR_SPKI
+
+/*-
+ * Matching types:
+ * https://tools.ietf.org/html/rfc6698#section-2.1.3
+ */
+#define DANETLS_MATCHING_FULL   0
+#define DANETLS_MATCHING_2256   1
+#define DANETLS_MATCHING_2512   2
+#define DANETLS_MATCHING_LAST   DANETLS_MATCHING_2512
+
+typedef struct danetls_record_st {
+    uint8_t usage;
+    uint8_t selector;
+    uint8_t mtype;
+    unsigned char *data;
+    size_t dlen;
+    EVP_PKEY *spki;
+} danetls_record;
+
+/*
+ * Shared DANE context
+ */
+struct dane_ctx_st {
+    const EVP_MD  **mdevp;      /* mtype -> digest */
+    uint8_t        *mdord;      /* mtype -> preference */
+    uint8_t         mdmax;      /* highest supported mtype */
+};
+
+/*
+ * Per connection DANE state
+ */
+struct dane_st {
+    struct dane_ctx_st *dctx;
+    STACK_OF(danetls_record) *trecs;
+    STACK_OF(X509) *certs;      /* DANE-TA(2) Cert(0) Full(0) certs */
+    danetls_record *mtlsa;      /* Matching TLSA record */
+    X509           *mcert;      /* DANE matched cert */
+    uint32_t        umask;      /* Usages present */
+    int             mdpth;      /* Depth of matched cert */
+    int             pdpth;      /* Depth of PKIX trust */
+};
+
+#define DANETLS_ENABLED(dane)  ((dane) && ((dane)->trecs != NULL))
+
+#define DANETLS_USAGE_BIT(u)   (((uint32_t)1) << u)
+
+#define DANETLS_PKIX_TA_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_PKIX_TA))
+#define DANETLS_PKIX_EE_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_PKIX_EE))
+#define DANETLS_DANE_TA_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_DANE_TA))
+#define DANETLS_DANE_EE_MASK (DANETLS_USAGE_BIT(DANETLS_USAGE_DANE_EE))
+
+#define DANETLS_PKIX_MASK (DANETLS_PKIX_TA_MASK | DANETLS_PKIX_EE_MASK)
+#define DANETLS_DANE_MASK (DANETLS_DANE_TA_MASK | DANETLS_DANE_EE_MASK)
+#define DANETLS_TA_MASK (DANETLS_PKIX_TA_MASK | DANETLS_DANE_TA_MASK)
+#define DANETLS_EE_MASK (DANETLS_PKIX_EE_MASK | DANETLS_DANE_EE_MASK)
+
+#define DANETLS_HAS_PKIX(dane) ((dane) && ((dane)->umask & DANETLS_PKIX_MASK))
+#define DANETLS_HAS_DANE(dane) ((dane) && ((dane)->umask & DANETLS_DANE_MASK))
+#define DANETLS_HAS_TA(dane)   ((dane) && ((dane)->umask & DANETLS_TA_MASK))
+#define DANETLS_HAS_EE(dane)   ((dane) && ((dane)->umask & DANETLS_EE_MASK))
+
+#define DANETLS_HAS_PKIX_TA(dane) ((dane)&&((dane)->umask & DANETLS_PKIX_TA_MASK))
+#define DANETLS_HAS_PKIX_EE(dane) ((dane)&&((dane)->umask & DANETLS_PKIX_EE_MASK))
+#define DANETLS_HAS_DANE_TA(dane) ((dane)&&((dane)->umask & DANETLS_DANE_TA_MASK))
+#define DANETLS_HAS_DANE_EE(dane) ((dane)&&((dane)->umask & DANETLS_DANE_EE_MASK))
+
+#endif /* HEADER_INTERNAL_DANE_H */
index cce3afd..94b8af4 100644 (file)
@@ -2045,6 +2045,29 @@ DECLARE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void)
 # define sk_X509_VERIFY_PARAM_sort(st) SKM_sk_sort(X509_VERIFY_PARAM, (st))
 # define sk_X509_VERIFY_PARAM_is_sorted(st) SKM_sk_is_sorted(X509_VERIFY_PARAM, (st))
 
+# define sk_danetls_record_new(cmp) SKM_sk_new(danetls_record, (cmp))
+# define sk_danetls_record_new_null() SKM_sk_new_null(danetls_record)
+# define sk_danetls_record_free(st) SKM_sk_free(danetls_record, (st))
+# define sk_danetls_record_num(st) SKM_sk_num(danetls_record, (st))
+# define sk_danetls_record_value(st, i) SKM_sk_value(danetls_record, (st), (i))
+# define sk_danetls_record_set(st, i, val) SKM_sk_set(danetls_record, (st), (i), (val))
+# define sk_danetls_record_zero(st) SKM_sk_zero(danetls_record, (st))
+# define sk_danetls_record_push(st, val) SKM_sk_push(danetls_record, (st), (val))
+# define sk_danetls_record_unshift(st, val) SKM_sk_unshift(danetls_record, (st), (val))
+# define sk_danetls_record_find(st, val) SKM_sk_find(danetls_record, (st), (val))
+# define sk_danetls_record_find_ex(st, val) SKM_sk_find_ex(danetls_record, (st), (val))
+# define sk_danetls_record_delete(st, i) SKM_sk_delete(danetls_record, (st), (i))
+# define sk_danetls_record_delete_ptr(st, ptr) SKM_sk_delete_ptr(danetls_record, (st), (ptr))
+# define sk_danetls_record_insert(st, val, i) SKM_sk_insert(danetls_record, (st), (val), (i))
+# define sk_danetls_record_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(danetls_record, (st), (cmp))
+# define sk_danetls_record_dup(st) SKM_sk_dup(danetls_record, st)
+# define sk_danetls_record_pop_free(st, free_func) SKM_sk_pop_free(danetls_record, (st), (free_func))
+# define sk_danetls_record_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(danetls_record, (st), (copy_func), (free_func))
+# define sk_danetls_record_shift(st) SKM_sk_shift(danetls_record, (st))
+# define sk_danetls_record_pop(st) SKM_sk_pop(danetls_record, (st))
+# define sk_danetls_record_sort(st) SKM_sk_sort(danetls_record, (st))
+# define sk_danetls_record_is_sorted(st) SKM_sk_is_sorted(danetls_record, (st))
+
 # define sk_nid_triple_new(cmp) SKM_sk_new(nid_triple, (cmp))
 # define sk_nid_triple_new_null() SKM_sk_new_null(nid_triple)
 # define sk_nid_triple_free(st) SKM_sk_free(nid_triple, (st))
index 0d22ab7..e634294 100644 (file)
@@ -327,6 +327,8 @@ typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
 
 DECLARE_STACK_OF(SSL_CIPHER)
 
+DECLARE_STACK_OF(danetls_record)
+
 /* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/
 typedef struct srtp_protection_profile_st {
     const char *name;
@@ -1533,6 +1535,27 @@ __owur int SSL_set_purpose(SSL *s, int purpose);
 __owur int SSL_CTX_set_trust(SSL_CTX *s, int trust);
 __owur int SSL_set_trust(SSL *s, int trust);
 
+__owur int SSL_set1_host(SSL *s, const char *hostname);
+__owur int SSL_add1_host(SSL *s, const char *hostname);
+__owur const char *SSL_get0_peername(SSL *s);
+void SSL_set_hostflags(SSL *s, unsigned int flags);
+
+__owur int SSL_CTX_dane_enable(SSL_CTX *ctx);
+__owur int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md,
+                                  uint8_t mtype, uint8_t ord);
+__owur int SSL_dane_enable(SSL *s, const char *basedomain);
+__owur int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
+                             uint8_t mtype, unsigned char *data, size_t dlen);
+__owur int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki);
+__owur int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
+                              uint8_t *mtype, unsigned const char **data,
+                              size_t *dlen);
+/*
+ * Bridge opacity barrier between libcrypt and libssl, also needed to support
+ * offline testing in test/danetest.c
+ */
+struct dane_st *SSL_get0_dane(SSL *ssl);
+
 __owur int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
 __owur int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
 
@@ -1919,6 +1942,9 @@ void ERR_load_SSL_strings(void);
 /* Function codes. */
 # define SSL_F_CHECK_SUITEB_CIPHER_LIST                   331
 # define SSL_F_D2I_SSL_SESSION                            103
+# define SSL_F_DANE_CTX_ENABLE                            347
+# define SSL_F_DANE_MTYPE_SET                             393
+# define SSL_F_DANE_TLSA_ADD                              394
 # define SSL_F_DO_DTLS1_WRITE                             245
 # define SSL_F_DO_SSL3_WRITE                              104
 # define SSL_F_DTLS1_ACCEPT                               246
@@ -2059,6 +2085,7 @@ void ERR_load_SSL_strings(void);
 # define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE             179
 # define SSL_F_SSL_CTX_USE_SERVERINFO                     336
 # define SSL_F_SSL_CTX_USE_SERVERINFO_FILE                337
+# define SSL_F_SSL_DANE_ENABLE                            395
 # define SSL_F_SSL_DO_CONFIG                              391
 # define SSL_F_SSL_DO_HANDSHAKE                           180
 # define SSL_F_SSL_GET_NEW_SESSION                        181
@@ -2232,8 +2259,20 @@ void ERR_load_SSL_strings(void);
 # define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE    307
 # define SSL_R_COMPRESSION_LIBRARY_ERROR                  142
 # define SSL_R_CONNECTION_TYPE_NOT_SET                    144
+# define SSL_R_CONTEXT_NOT_DANE_ENABLED                   167
 # define SSL_R_COOKIE_GEN_CALLBACK_FAILURE                400
 # define SSL_R_COOKIE_MISMATCH                            308
+# define SSL_R_DANE_ALREADY_ENABLED                       172
+# define SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL            173
+# define SSL_R_DANE_NOT_ENABLED                           175
+# define SSL_R_DANE_TLSA_BAD_CERTIFICATE                  180
+# define SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE            184
+# define SSL_R_DANE_TLSA_BAD_DATA_LENGTH                  189
+# define SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH                192
+# define SSL_R_DANE_TLSA_BAD_MATCHING_TYPE                200
+# define SSL_R_DANE_TLSA_BAD_PUBLIC_KEY                   201
+# define SSL_R_DANE_TLSA_BAD_SELECTOR                     202
+# define SSL_R_DANE_TLSA_NULL_DATA                        203
 # define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED              145
 # define SSL_R_DATA_LENGTH_TOO_LONG                       146
 # define SSL_R_DECRYPTION_FAILED                          147
@@ -2253,6 +2292,7 @@ void ERR_load_SSL_strings(void);
 # define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST         354
 # define SSL_R_ENCRYPTED_LENGTH_TOO_LONG                  150
 # define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST              151
+# define SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN             204
 # define SSL_R_EXCESSIVE_MESSAGE_SIZE                     152
 # define SSL_R_EXTRA_DATA_IN_MESSAGE                      153
 # define SSL_R_FAILED_TO_INIT_ASYNC                       405
index 5e65998..e37c2f7 100644 (file)
@@ -263,6 +263,7 @@ struct x509_store_ctx_st {      /* X509_STORE_CTX */
     /* For CRL path validation: parent context */
     X509_STORE_CTX *parent;
     CRYPTO_EX_DATA ex_data;
+    struct dane_st *dane;
 } /* X509_STORE_CTX */ ;
 
 void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
@@ -528,6 +529,12 @@ X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx);
 void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
 int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
 
+/*
+ * Bridge opacity barrier between libcrypt and libssl, also needed to support
+ * offline testing in test/danetest.c
+ */
+void X509_STORE_CTX_set0_dane(X509_STORE_CTX *ctx, struct dane_st *dane);
+
 /* X509_VERIFY_PARAM functions */
 
 X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void);
@@ -558,6 +565,7 @@ int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
                                      unsigned int flags);
 char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *);
+void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *, X509_VERIFY_PARAM *);
 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
                                  const char *email, size_t emaillen);
 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
index ae31f5d..5398912 100644 (file)
@@ -208,15 +208,6 @@ int RECORD_LAYER_set_data(RECORD_LAYER *rl, const unsigned char *buf, int len)
     return 1;
 }
 
-void RECORD_LAYER_dup(RECORD_LAYER *dst, RECORD_LAYER *src)
-{
-    /*
-     * Currently only called from SSL_dup...which only seems to expect the
-     * rstate to be duplicated and nothing else from the RECORD_LAYER???
-     */
-    dst->rstate = src->rstate;
-}
-
 void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl)
 {
     memset(rl->read_sequence, 0, sizeof(rl->read_sequence));
index 9637071..af10166 100644 (file)
@@ -321,7 +321,6 @@ void RECORD_LAYER_release(RECORD_LAYER *rl);
 int RECORD_LAYER_read_pending(RECORD_LAYER *rl);
 int RECORD_LAYER_write_pending(RECORD_LAYER *rl);
 int RECORD_LAYER_set_data(RECORD_LAYER *rl, const unsigned char *buf, int len);
-void RECORD_LAYER_dup(RECORD_LAYER *dst, RECORD_LAYER *src);
 void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl);
 void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl);
 int RECORD_LAYER_setup_comp_buffer(RECORD_LAYER *rl);
index 597de0a..7f01bcc 100644 (file)
@@ -486,6 +486,7 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
     int i;
     X509_STORE *verify_store;
     X509_STORE_CTX ctx;
+    X509_VERIFY_PARAM *param;
 
     if (s->cert->verify_store)
         verify_store = s->cert->verify_store;
@@ -500,10 +501,16 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
         SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB);
         return (0);
     }
+    param = X509_STORE_CTX_get0_param(&ctx);
+
     /* Set suite B flags if needed */
     X509_STORE_CTX_set_flags(&ctx, tls1_suiteb(s));
     X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s);
 
+    /* Verify via DANE if enabled */
+    if (DANETLS_ENABLED(&s->dane))
+        X509_STORE_CTX_set0_dane(&ctx, &s->dane);
+
     /*
      * We need to inherit the verify parameters. These can be determined by
      * the context: if its a server it will verify SSL client certificates or
@@ -512,9 +519,9 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
 
     X509_STORE_CTX_set_default(&ctx, s->server ? "ssl_client" : "ssl_server");
     /*
-     * Anything non-default in "param" should overwrite anything in the ctx.
+     * Anything non-default in "s->param" should overwrite anything in the ctx.
      */
-    X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param);
+    X509_VERIFY_PARAM_set1(param, s->param);
 
     if (s->verify_callback)
         X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
@@ -534,6 +541,10 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
     }
 
     s->verify_result = ctx.error;
+
+    /* Move peername from the store context params to the SSL handle's */
+    X509_VERIFY_PARAM_move_peername(s->param, param);
+
     X509_STORE_CTX_cleanup(&ctx);
 
     return (i);
index d9dbf99..cfa4179 100644 (file)
@@ -72,6 +72,9 @@
 static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_CHECK_SUITEB_CIPHER_LIST), "check_suiteb_cipher_list"},
     {ERR_FUNC(SSL_F_D2I_SSL_SESSION), "d2i_SSL_SESSION"},
+    {ERR_FUNC(SSL_F_DANE_CTX_ENABLE), "dane_ctx_enable"},
+    {ERR_FUNC(SSL_F_DANE_MTYPE_SET), "dane_mtype_set"},
+    {ERR_FUNC(SSL_F_DANE_TLSA_ADD), "dane_tlsa_add"},
     {ERR_FUNC(SSL_F_DO_DTLS1_WRITE), "do_dtls1_write"},
     {ERR_FUNC(SSL_F_DO_SSL3_WRITE), "DO_SSL3_WRITE"},
     {ERR_FUNC(SSL_F_DTLS1_ACCEPT), "dtls1_accept"},
@@ -262,6 +265,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_SSL_CTX_USE_SERVERINFO), "SSL_CTX_use_serverinfo"},
     {ERR_FUNC(SSL_F_SSL_CTX_USE_SERVERINFO_FILE),
      "SSL_CTX_use_serverinfo_file"},
+    {ERR_FUNC(SSL_F_SSL_DANE_ENABLE), "SSL_dane_enable"},
     {ERR_FUNC(SSL_F_SSL_DO_CONFIG), "ssl_do_config"},
     {ERR_FUNC(SSL_F_SSL_DO_HANDSHAKE), "SSL_do_handshake"},
     {ERR_FUNC(SSL_F_SSL_GET_NEW_SESSION), "ssl_get_new_session"},
@@ -491,9 +495,25 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
     {ERR_REASON(SSL_R_COMPRESSION_LIBRARY_ERROR),
      "compression library error"},
     {ERR_REASON(SSL_R_CONNECTION_TYPE_NOT_SET), "connection type not set"},
+    {ERR_REASON(SSL_R_CONTEXT_NOT_DANE_ENABLED), "context not dane enabled"},
     {ERR_REASON(SSL_R_COOKIE_GEN_CALLBACK_FAILURE),
      "cookie gen callback failure"},
     {ERR_REASON(SSL_R_COOKIE_MISMATCH), "cookie mismatch"},
+    {ERR_REASON(SSL_R_DANE_ALREADY_ENABLED), "dane already enabled"},
+    {ERR_REASON(SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL),
+     "dane cannot override mtype full"},
+    {ERR_REASON(SSL_R_DANE_NOT_ENABLED), "dane not enabled"},
+    {ERR_REASON(SSL_R_DANE_TLSA_BAD_CERTIFICATE), "dane tlsa bad certificate"},
+    {ERR_REASON(SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE),
+     "dane tlsa bad certificate usage"},
+    {ERR_REASON(SSL_R_DANE_TLSA_BAD_DATA_LENGTH), "dane tlsa bad data length"},
+    {ERR_REASON(SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH),
+     "dane tlsa bad digest length"},
+    {ERR_REASON(SSL_R_DANE_TLSA_BAD_MATCHING_TYPE),
+     "dane tlsa bad matching type"},
+    {ERR_REASON(SSL_R_DANE_TLSA_BAD_PUBLIC_KEY), "dane tlsa bad public key"},
+    {ERR_REASON(SSL_R_DANE_TLSA_BAD_SELECTOR), "dane tlsa bad selector"},
+    {ERR_REASON(SSL_R_DANE_TLSA_NULL_DATA), "dane tlsa null data"},
     {ERR_REASON(SSL_R_DATA_BETWEEN_CCS_AND_FINISHED),
      "data between ccs and finished"},
     {ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG), "data length too long"},
@@ -524,6 +544,8 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
      "encrypted length too long"},
     {ERR_REASON(SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST),
      "error in received cipher list"},
+    {ERR_REASON(SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN),
+     "error setting tlsa base domain"},
     {ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE), "excessive message size"},
     {ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE), "extra data in message"},
     {ERR_REASON(SSL_R_FAILED_TO_INIT_ASYNC), "failed to init async"},
index 760014d..f0f1264 100644 (file)
@@ -197,6 +197,333 @@ struct ssl_async_args {
     } f;
 };
 
+static const struct {
+    uint8_t mtype;
+    uint8_t ord;
+    int     nid;
+} dane_mds[] = {
+    { DANETLS_MATCHING_FULL, 0, NID_undef },
+    { DANETLS_MATCHING_2256, 1, NID_sha256 },
+    { DANETLS_MATCHING_2512, 2, NID_sha512 },
+};
+
+static int dane_ctx_enable(struct dane_ctx_st *dctx)
+{
+    const EVP_MD **mdevp;
+    uint8_t *mdord;
+    uint8_t mdmax = DANETLS_MATCHING_LAST;
+    int n = ((int) mdmax) + 1;          /* int to handle PrivMatch(255) */
+    size_t i;
+
+    mdevp = OPENSSL_zalloc(n * sizeof(*mdevp));
+    mdord = OPENSSL_zalloc(n * sizeof(*mdord));
+
+    if (mdord == NULL || mdevp == NULL) {
+        OPENSSL_free(mdevp);
+        SSLerr(SSL_F_DANE_CTX_ENABLE, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    /* Install default entries */
+    for (i = 0; i < OSSL_NELEM(dane_mds); ++i) {
+        const EVP_MD *md;
+
+        if (dane_mds[i].nid == NID_undef ||
+            (md = EVP_get_digestbynid(dane_mds[i].nid)) == NULL)
+            continue;
+        mdevp[dane_mds[i].mtype] = md;
+        mdord[dane_mds[i].mtype] = dane_mds[i].ord;
+    }
+
+    dctx->mdevp = mdevp;
+    dctx->mdord = mdord;
+    dctx->mdmax = mdmax;
+
+    return 1;
+}
+
+static void dane_ctx_final(struct dane_ctx_st *dctx)
+{
+    OPENSSL_free(dctx->mdevp);
+    dctx->mdevp = NULL;
+
+    OPENSSL_free(dctx->mdord);
+    dctx->mdord = NULL;
+    dctx->mdmax = 0;
+}
+
+static void tlsa_free(danetls_record *t)
+{
+    if (t == NULL)
+        return;
+    OPENSSL_free(t->data);
+    EVP_PKEY_free(t->spki);
+    OPENSSL_free(t);
+}
+
+static void dane_final(struct dane_st *dane)
+{
+    sk_danetls_record_pop_free(dane->trecs, tlsa_free);
+    dane->trecs = NULL;
+
+    sk_X509_pop_free(dane->certs, X509_free);
+    dane->certs = NULL;
+
+    X509_free(dane->mcert);
+    dane->mcert = NULL;
+    dane->mtlsa = NULL;
+    dane->mdpth = -1;
+    dane->pdpth = -1;
+}
+
+/*
+ * dane_copy - Copy dane configuration, sans verification state.
+ */
+static int ssl_dane_dup(SSL *to, SSL *from)
+{
+    int num;
+    int i;
+
+    if (!DANETLS_ENABLED(&from->dane))
+        return 1;
+
+    dane_final(&to->dane);
+
+    num  = sk_danetls_record_num(from->dane.trecs);
+    for (i = 0; i < num; ++i) {
+        danetls_record *t = sk_danetls_record_value(from->dane.trecs, i);
+        if (SSL_dane_tlsa_add(to, t->usage, t->selector, t->mtype,
+                              t->data, t->dlen) <= 0)
+            return 0;
+    }
+    return 1;
+}
+
+static int dane_mtype_set(
+    struct dane_ctx_st *dctx,
+    const EVP_MD *md,
+    uint8_t mtype,
+    uint8_t ord)
+{
+    int i;
+
+    if (mtype == DANETLS_MATCHING_FULL && md != NULL) {
+        SSLerr(SSL_F_DANE_MTYPE_SET,
+                SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL);
+        return 0;
+    }
+
+    if (mtype > dctx->mdmax) {
+        const EVP_MD **mdevp;
+        uint8_t *mdord;
+        int n = ((int) mtype) + 1;
+
+        mdevp = OPENSSL_realloc(dctx->mdevp, n * sizeof(*mdevp));
+        if (mdevp == NULL) {
+            SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE);
+            return -1;
+        }
+        dctx->mdevp = mdevp;
+
+        mdord = OPENSSL_realloc(dctx->mdord, n * sizeof(*mdord));
+        if (mdord == NULL) {
+            SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE);
+            return -1;
+        }
+        dctx->mdord = mdord;
+
+        /* Zero-fill any gaps */
+        for (i = dctx->mdmax+1; i < mtype; ++i) {
+            mdevp[i] = NULL;
+            mdord[i] = 0;
+        }
+
+        dctx->mdmax = mtype;
+    }
+
+    dctx->mdevp[mtype] = md;
+    /* Coerce ordinal of disabled matching types to 0 */
+    dctx->mdord[mtype] = (md == NULL) ? 0 : ord;
+
+    return 1;
+}
+
+static const EVP_MD *tlsa_md_get(struct dane_st *dane, uint8_t mtype)
+{
+    if (mtype > dane->dctx->mdmax)
+        return NULL;
+    return dane->dctx->mdevp[mtype];
+}
+
+static int dane_tlsa_add(
+    struct dane_st *dane,
+    uint8_t usage,
+    uint8_t selector,
+    uint8_t mtype,
+    unsigned char *data,
+    size_t dlen)
+{
+    danetls_record *t;
+    const EVP_MD *md = NULL;
+    int ilen = (int)dlen;
+    int i;
+
+    if (dane->trecs == NULL) {
+        SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_NOT_ENABLED);
+        return -1;
+    }
+
+    if (ilen < 0 || dlen != (size_t)ilen) {
+        SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DATA_LENGTH);
+        return 0;
+    }
+
+    if (usage > DANETLS_USAGE_LAST) {
+        SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE);
+        return 0;
+    }
+
+    if (selector > DANETLS_SELECTOR_LAST) {
+        SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_SELECTOR);
+        return 0;
+    }
+
+    if (mtype != DANETLS_MATCHING_FULL) {
+        md = tlsa_md_get(dane, mtype);
+        if (md == NULL) {
+            SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_MATCHING_TYPE);
+            return 0;
+        }
+    }
+
+    if (md != NULL && dlen != (size_t)EVP_MD_size(md)) {
+        SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH);
+        return 0;
+    }
+    if (!data) {
+        SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_NULL_DATA);
+        return 0;
+    }
+
+    if ((t = OPENSSL_zalloc(sizeof(*t))) == NULL) {
+        SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+        return -1;
+    }
+
+    t->usage = usage;
+    t->selector = selector;
+    t->mtype = mtype;
+    t->data = OPENSSL_malloc(ilen);
+    if (t->data == NULL) {
+        tlsa_free(t);
+        SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+        return -1;
+    }
+    memcpy(t->data, data, ilen);
+    t->dlen = ilen;
+
+    /* Validate and cache full certificate or public key */
+    if (mtype == DANETLS_MATCHING_FULL) {
+        const unsigned char *p = data;
+        X509 *cert = NULL;
+        EVP_PKEY *pkey = NULL;
+
+        switch (selector) {
+        case DANETLS_SELECTOR_CERT:
+            if (!d2i_X509(&cert, &p, dlen) || p < data ||
+                dlen != (size_t)(p - data)) {
+                tlsa_free(t);
+                SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
+                return 0;
+            }
+            if (X509_get0_pubkey(cert) == NULL) {
+                tlsa_free(t);
+                SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
+                return 0;
+            }
+
+            if ((DANETLS_USAGE_BIT(usage) & DANETLS_TA_MASK) == 0) {
+                X509_free(cert);
+                break;
+            }
+
+            /*
+             * For usage DANE-TA(2), we support authentication via "2 0 0" TLSA
+             * records that contain full certificates of trust-anchors that are
+             * not present in the wire chain.  For usage PKIX-TA(0), we augment
+             * the chain with untrusted Full(0) certificates from DNS, in case
+             * they are missing from the chain.
+             */
+            if ((dane->certs == NULL &&
+                 (dane->certs = sk_X509_new_null()) == NULL) ||
+                !sk_X509_push(dane->certs, cert)) {
+                SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+                X509_free(cert);
+                tlsa_free(t);
+                return -1;
+            }
+            break;
+
+        case DANETLS_SELECTOR_SPKI:
+            if (!d2i_PUBKEY(&pkey, &p, dlen) || p < data ||
+                dlen != (size_t)(p - data)) {
+                tlsa_free(t);
+                SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY);
+                return 0;
+            }
+
+            /*
+             * For usage DANE-TA(2), we support authentication via "2 1 0" TLSA
+             * records that contain full bare keys of trust-anchors that are
+             * not present in the wire chain.
+             */
+            if (usage == DANETLS_USAGE_DANE_TA)
+                t->spki = pkey;
+            else
+                EVP_PKEY_free(pkey);
+            break;
+        }
+    }
+
+    /*-
+     * Find the right insertion point for the new record.
+     *
+     * See crypto/x509/x509_vfy.c.  We sort DANE-EE(3) records first, so that
+     * they can be processed first, as they require no chain building, and no
+     * expiration or hostname checks.  Because DANE-EE(3) is numerically
+     * largest, this is accomplished via descending sort by "usage".
+     *
+     * We also sort in descending order by matching ordinal to simplify
+     * the implementation of digest agility in the verification code.
+     *
+     * The choice of order for the selector is not significant, so we
+     * use the same descending order for consistency.
+     */
+    for (i = 0; i < sk_danetls_record_num(dane->trecs); ++i) {
+        danetls_record *rec = sk_danetls_record_value(dane->trecs, i);
+        if (rec->usage > usage)
+            continue;
+        if (rec->usage < usage)
+            break;
+        if (rec->selector > selector)
+            continue;
+        if (rec->selector < selector)
+            break;
+        if (dane->dctx->mdord[rec->mtype] > dane->dctx->mdord[mtype])
+            continue;
+        break;
+    }
+
+    if (!sk_danetls_record_insert(dane->trecs, t, i)) {
+        tlsa_free(t);
+        SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
+        return -1;
+    }
+    dane->umask |= DANETLS_USAGE_BIT(usage);
+
+    return 1;
+}
+
 static void clear_ciphers(SSL *s)
 {
     /* clear the current cipher */
@@ -237,6 +564,16 @@ int SSL_clear(SSL *s)
     clear_ciphers(s);
     s->first_packet = 0;
 
+    /* Reset DANE verification result state */
+    s->dane.mdpth = -1;
+    s->dane.pdpth = -1;
+    X509_free(s->dane.mcert);
+    s->dane.mcert = NULL;
+    s->dane.mtlsa = NULL;
+
+    /* Clear the verification result peername */
+    X509_VERIFY_PARAM_move_peername(s->param, NULL);
+
     /*
      * Check to see if we were changed into a different method, if so, revert
      * back if we are not doing session-id reuse.
@@ -497,6 +834,121 @@ int SSL_set_trust(SSL *s, int trust)
     return X509_VERIFY_PARAM_set_trust(s->param, trust);
 }
 
+int SSL_set1_host(SSL *s, const char *hostname)
+{
+    return X509_VERIFY_PARAM_set1_host(s->param, hostname, 0);
+}
+
+int SSL_add1_host(SSL *s, const char *hostname)
+{
+    return X509_VERIFY_PARAM_add1_host(s->param, hostname, 0);
+}
+
+void SSL_set_hostflags(SSL *s, unsigned int flags)
+{
+    X509_VERIFY_PARAM_set_hostflags(s->param, flags);
+}
+
+const char *SSL_get0_peername(SSL *s)
+{
+    return X509_VERIFY_PARAM_get0_peername(s->param);
+}
+
+int SSL_CTX_dane_enable(SSL_CTX *ctx)
+{
+    return dane_ctx_enable(&ctx->dane);
+}
+
+int SSL_dane_enable(SSL *s, const char *basedomain)
+{
+    struct dane_st *dane = &s->dane;
+
+    if (s->ctx->dane.mdmax == 0) {
+        SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_CONTEXT_NOT_DANE_ENABLED);
+        return 0;
+    }
+    if (dane->trecs != NULL) {
+        SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_DANE_ALREADY_ENABLED);
+        return 0;
+    }
+
+    /* Primary RFC6125 reference identifier */
+    if (!X509_VERIFY_PARAM_set1_host(s->param, basedomain, 0)) {
+        SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
+        return -1;
+    }
+
+    /* Default SNI name */
+    if (s->tlsext_hostname == NULL) {
+       if (!SSL_set_tlsext_host_name(s, basedomain))
+           return -1;
+    }
+
+    dane->mdpth = -1;
+    dane->pdpth = -1;
+    dane->dctx = &s->ctx->dane;
+    dane->trecs = sk_danetls_record_new_null();
+
+    if (dane->trecs == NULL) {
+        SSLerr(SSL_F_SSL_DANE_ENABLE, ERR_R_MALLOC_FAILURE);
+        return -1;
+    }
+    return 1;
+}
+
+int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki)
+{
+    struct dane_st *dane = &s->dane;
+
+    if (!DANETLS_ENABLED(dane))
+        return -1;
+    if (dane->mtlsa) {
+        if (mcert)
+            *mcert = dane->mcert;
+        if (mspki)
+            *mspki = (dane->mcert == NULL) ? dane->mtlsa->spki : NULL;
+    }
+    return dane->mdpth;
+}
+
+int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
+                       uint8_t *mtype, unsigned const char **data, size_t *dlen)
+{
+    struct dane_st *dane = &s->dane;
+
+    if (!DANETLS_ENABLED(dane))
+        return -1;
+    if (dane->mtlsa) {
+        if (usage)
+            *usage = dane->mtlsa->usage;
+        if (selector)
+            *selector = dane->mtlsa->selector;
+        if (mtype)
+            *mtype = dane->mtlsa->mtype;
+        if (data)
+            *data = dane->mtlsa->data;
+        if (dlen)
+            *dlen = dane->mtlsa->dlen;
+    }
+    return dane->mdpth;
+}
+
+struct dane_st *SSL_get0_dane(SSL *s)
+{
+    return &s->dane;
+}
+
+int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
+                      uint8_t mtype, unsigned char *data, size_t dlen)
+{
+    return dane_tlsa_add(&s->dane, usage, selector, mtype, data, dlen);
+}
+
+int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md, uint8_t mtype, uint8_t ord)
+{
+    return dane_mtype_set(&ctx->dane, md, mtype, ord);
+}
+
 int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm)
 {
     return X509_VERIFY_PARAM_set1(ctx->param, vpm);
@@ -543,6 +995,7 @@ void SSL_free(SSL *s)
 #endif
 
     X509_VERIFY_PARAM_free(s->param);
+    dane_final(&s->dane);
     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
 
     if (s->bbio != NULL) {
@@ -877,9 +1330,10 @@ int SSL_copy_session_id(SSL *t, const SSL *f)
      * what if we are setup for one protocol version but want to talk another
      */
     if (t->method != f->method) {
-        t->method->ssl_free(t); /* cleanup current */
-        t->method = f->method;  /* change method */
-        t->method->ssl_new(t);  /* setup new */
+        t->method->ssl_free(t);
+        t->method = f->method;
+        if (t->method->ssl_new(t) == 0)
+            return 0;
     }
 
     CRYPTO_add(&f->cert->references, 1, CRYPTO_LOCK_SSL_CERT);
@@ -1922,6 +2376,7 @@ void SSL_CTX_free(SSL_CTX *a)
 #endif
 
     X509_VERIFY_PARAM_free(a->param);
+    dane_ctx_final(&a->dane);
 
     /*
      * Free internal session cache. However: the remove_cb() may reference
@@ -2346,24 +2801,23 @@ const SSL_METHOD *SSL_get_ssl_method(SSL *s)
 
 int SSL_set_ssl_method(SSL *s, const SSL_METHOD *meth)
 {
-    int conn = -1;
     int ret = 1;
 
     if (s->method != meth) {
-        if (s->handshake_func != NULL)
-            conn = (s->handshake_func == s->method->ssl_connect);
+        const SSL_METHOD *sm = s->method;
+        int (*hf)(SSL *) = s->handshake_func;
 
-        if (s->method->version == meth->version)
+        if (sm->version == meth->version)
             s->method = meth;
         else {
-            s->method->ssl_free(s);
+            sm->ssl_free(s);
             s->method = meth;
             ret = s->method->ssl_new(s);
         }
 
-        if (conn == 1)
+        if (hf == sm->ssl_connect)
             s->handshake_func = meth->ssl_connect;
-        else if (conn == 0)
+        else if (hf == sm->ssl_accept)
             s->handshake_func = meth->ssl_accept;
     }
     return (ret);
@@ -2554,14 +3008,23 @@ SSL *SSL_dup(SSL *s)
     SSL *ret;
     int i;
 
+    /* If we're not quiescent, just up_ref! */
+    if (!SSL_in_init(s) || !SSL_in_before(s)) {
+        CRYPTO_add(&s->references, 1, CRYPTO_LOCK_SSL);
+        return s;
+    }
+
+    /*
+     * Otherwise, copy configuration state, and session if set.
+     */
     if ((ret = SSL_new(SSL_get_SSL_CTX(s))) == NULL)
         return (NULL);
 
-    ret->version = s->version;
-    ret->method = s->method;
-
     if (s->session != NULL) {
-        /* This copies session-id, SSL_METHOD, sid_ctx, and 'cert' */
+        /*
+         * Arranges to share the same session via up_ref.  This "copies"
+         * session-id, SSL_METHOD, sid_ctx, and 'cert'
+         */
         if (!SSL_copy_session_id(ret, s))
             goto err;
     } else {
@@ -2571,10 +3034,8 @@ SSL *SSL_dup(SSL *s)
          * point to the same object, and thus we can't use
          * SSL_copy_session_id.
          */
-
-        ret->method->ssl_free(ret);
-        ret->method = s->method;
-        ret->method->ssl_new(ret);
+        if (!SSL_set_ssl_method(ret, s->method))
+            goto err;
 
         if (s->cert != NULL) {
             ssl_cert_free(ret->cert);
@@ -2587,6 +3048,8 @@ SSL *SSL_dup(SSL *s)
             goto err;
     }
 
+    ssl_dane_dup(ret, s);
+    ret->version = s->version;
     ret->options = s->options;
     ret->mode = s->mode;
     SSL_set_max_cert_list(ret, SSL_get_max_cert_list(s));
@@ -2617,19 +3080,15 @@ SSL *SSL_dup(SSL *s)
         } else
             ret->wbio = ret->rbio;
     }
-    ret->rwstate = s->rwstate;
-    ret->handshake_func = s->handshake_func;
+
     ret->server = s->server;
-    ret->renegotiate = s->renegotiate;
-    ret->new_session = s->new_session;
-    ret->quiet_shutdown = s->quiet_shutdown;
+    if (s->handshake_func) {
+        if (s->server)
+            SSL_set_accept_state(ret);
+        else
+            SSL_set_connect_state(ret);
+    }
     ret->shutdown = s->shutdown;
-    ret->statem = s->statem;      /* SSL_dup does not really work at any state,
-                                   * though */
-    RECORD_LAYER_dup(&ret->rlayer, &s->rlayer);
-    ret->init_num = 0;          /* would have to copy ret->init_buf,
-                                 * ret->init_msg, ret->init_num,
-                                 * ret->init_off */
     ret->hit = s->hit;
 
     ret->default_passwd_callback = s->default_passwd_callback;
index 7e07297..fee7fa6 100644 (file)
 #include "record/record.h"
 #include "statem/statem.h"
 #include "packet_locl.h"
+#include "internal/dane.h"
 
 # ifdef OPENSSL_BUILD_SHLIBSSL
 #  undef OPENSSL_EXTERN
@@ -925,6 +926,9 @@ struct ssl_ctx_st {
     unsigned char *alpn_client_proto_list;
     unsigned alpn_client_proto_list_len;
 
+    /* Shared DANE context */
+    struct dane_ctx_st dane;
+
     /* SRTP profiles we are willing to do from RFC 5764 */
     STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
     /*
@@ -1007,6 +1011,10 @@ struct ssl_st {
     void *msg_callback_arg;
     int hit;                    /* reusing a previous session */
     X509_VERIFY_PARAM *param;
+
+    /* Per connection DANE state */
+    struct dane_st dane;
+
     /* crypto */
     STACK_OF(SSL_CIPHER) *cipher_list;
     STACK_OF(SSL_CIPHER) *cipher_list_by_id;