summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/x509/x509_vfy.c7
-rw-r--r--crypto/x509/x509_vpm.c18
-rw-r--r--demos/bio/client-arg.c3
-rw-r--r--demos/bio/client-conf.c3
-rw-r--r--demos/bio/saccept.c29
-rw-r--r--demos/bio/sconnect.c33
-rw-r--r--demos/bio/server.pem64
-rw-r--r--doc/crypto/X509_VERIFY_PARAM_set_flags.pod2
-rw-r--r--doc/ssl/SSL_CTX_dane_enable.pod278
-rw-r--r--doc/ssl/SSL_set1_host.pod115
-rw-r--r--doc/ssl/ssl.pod19
-rw-r--r--include/internal/dane.h147
-rw-r--r--include/openssl/safestack.h23
-rw-r--r--include/openssl/ssl.h40
-rw-r--r--include/openssl/x509_vfy.h8
-rw-r--r--ssl/record/rec_layer_s3.c9
-rw-r--r--ssl/record/record.h1
-rw-r--r--ssl/ssl_cert.c15
-rw-r--r--ssl/ssl_err.c22
-rw-r--r--ssl/ssl_lib.c517
-rw-r--r--ssl/ssl_locl.h8
21 files changed, 1284 insertions, 77 deletions
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 57fcf91b30..1c509a9961 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -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;
diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c
index 2a15f82ea1..827360d622 100644
--- a/crypto/x509/x509_vpm.c
+++ b/crypto/x509/x509_vpm.c
@@ -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)
{
diff --git a/demos/bio/client-arg.c b/demos/bio/client-arg.c
index 99ebff1f2a..630b166779 100644
--- a/demos/bio/client-arg.c
+++ b/demos/bio/client-arg.c
@@ -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;
}
/*
diff --git a/demos/bio/client-conf.c b/demos/bio/client-conf.c
index 2a78315165..4e4d4bc8df 100644
--- a/demos/bio/client-conf.c
+++ b/demos/bio/client-conf.c
@@ -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;
}
/*
diff --git a/demos/bio/saccept.c b/demos/bio/saccept.c
index 0d173aa039..b6d0361a9c 100644
--- a/demos/bio/saccept.c
+++ b/demos/bio/saccept.c
@@ -18,16 +18,30 @@
#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) {
/*
diff --git a/demos/bio/sconnect.c b/demos/bio/sconnect.c
index 865d503956..2b610cc8b5 100644
--- a/demos/bio/sconnect.c
+++ b/demos/bio/sconnect.c
@@ -11,27 +11,38 @@
#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);
diff --git a/demos/bio/server.pem b/demos/bio/server.pem
index ef0d22a67b..8a4a51f9f0 100644
--- a/demos/bio/server.pem
+++ b/demos/bio/server.pem
@@ -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
diff --git a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
index df5766cdef..a2219d2aae 100644
--- a/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
+++ b/doc/crypto/X509_VERIFY_PARAM_set_flags.pod
@@ -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
index 0000000000..66eb1b3d8d
--- /dev/null
+++ b/doc/ssl/SSL_CTX_dane_enable.pod
@@ -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
index 0000000000..b008a5ff6e
--- /dev/null
+++ b/doc/ssl/SSL_set1_host.pod
@@ -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
diff --git a/doc/ssl/ssl.pod b/doc/ssl/ssl.pod
index adcec5ffa9..bb3bc94809 100644
--- a/doc/ssl/ssl.pod
+++ b/doc/ssl/ssl.pod
@@ -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
index 0000000000..cbe33f3e48
--- /dev/null
+++ b/include/internal/dane.h
@@ -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