summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/s_apps.h1
-rw-r--r--apps/s_cb.c78
-rw-r--r--apps/s_client.c16
-rw-r--r--crypto/x509/x509_txt.c10
-rw-r--r--crypto/x509/x509_vfy.c8
-rw-r--r--doc/apps/s_client.pod9
-rw-r--r--doc/ssl/SSL_CTX_dane_enable.pod30
-rw-r--r--include/openssl/x509_vfy.h2
-rw-r--r--ssl/ssl_lib.c4
-rwxr-xr-xtest/certs/mkcert.sh2
-rw-r--r--test/danetest.c8
-rw-r--r--test/danetest.in178
12 files changed, 294 insertions, 52 deletions
diff --git a/apps/s_apps.h b/apps/s_apps.h
index e9b6f40288..8e12c2146c 100644
--- a/apps/s_apps.h
+++ b/apps/s_apps.h
@@ -192,6 +192,7 @@ void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc);
void ssl_excert_free(SSL_EXCERT *exc);
int args_excert(int option, SSL_EXCERT **pexc);
int load_excert(SSL_EXCERT **pexc);
+void print_verify_detail(SSL *s, BIO *bio);
void print_ssl_summary(SSL *s);
#ifdef HEADER_SSL_H
int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str,
diff --git a/apps/s_cb.c b/apps/s_cb.c
index 096471a86f..30c9147d5c 100644
--- a/apps/s_cb.c
+++ b/apps/s_cb.c
@@ -167,7 +167,7 @@ int verify_callback(int ok, X509_STORE_CTX *ctx)
if (verify_depth >= depth) {
if (!verify_return_error)
ok = 1;
- verify_error = X509_V_OK;
+ verify_error = err;
} else {
ok = 0;
verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
@@ -1086,6 +1086,80 @@ static void print_raw_cipherlist(SSL *s)
BIO_puts(bio_err, "\n");
}
+/*
+ * Hex encoder for TLSA RRdata, not ':' delimited.
+ */
+static char *hexencode(const unsigned char *data, size_t len)
+{
+ static const char *hex = "0123456789abcdef";
+ char *out;
+ char *cp;
+ size_t outlen = 2 * len + 1;
+ int ilen = (int) outlen;
+
+ if (outlen < len || ilen < 0 || outlen != (size_t)ilen) {
+ BIO_printf(bio_err, "%s: %" PRIu64 "-byte buffer too large to hexencode\n",
+ opt_getprog(), (uint64_t)len);
+ exit(1);
+ }
+ cp = out = app_malloc(ilen, "TLSA hex data buffer");
+
+ while (ilen-- > 0) {
+ *cp++ = hex[(*data >> 4) & 0x0f];
+ *cp++ = hex[*data++ & 0x0f];
+ }
+ *cp = '\0';
+ return out;
+}
+
+void print_verify_detail(SSL *s, BIO *bio)
+{
+ int mdpth;
+ EVP_PKEY *mspki;
+ long verify_err = SSL_get_verify_result(s);
+
+ if (verify_err == X509_V_OK) {
+ const char *peername = SSL_get0_peername(s);
+
+ BIO_printf(bio, "Verification: OK\n");
+ if (peername != NULL)
+ BIO_printf(bio, "Verified peername: %s\n", peername);
+ } else {
+ const char *reason = X509_verify_cert_error_string(verify_err);
+
+ BIO_printf(bio, "Verification error: %s\n", reason);
+ }
+
+ if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) {
+ uint8_t usage, selector, mtype;
+ const unsigned char *data = NULL;
+ size_t dlen = 0;
+ char *hexdata;
+
+ mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen);
+
+ /*
+ * The TLSA data field can be quite long when it is a certificate,
+ * public key or even a SHA2-512 digest. Because the initial octets of
+ * ASN.1 certificates and public keys contain mostly boilerplate OIDs
+ * and lengths, we show the last 12 bytes of the data instead, as these
+ * are more likely to distinguish distinct TLSA records.
+ */
+#define TLSA_TAIL_SIZE 12
+ if (dlen > TLSA_TAIL_SIZE)
+ hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE);
+ else
+ hexdata = hexencode(data, dlen);
+ BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n",
+ usage, selector, mtype,
+ (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata,
+ (mspki != NULL) ? "signed the certificate" :
+ mdpth ? "matched TA certificate" : "matched EE certificate",
+ mdpth);
+ OPENSSL_free(hexdata);
+ }
+}
+
void print_ssl_summary(SSL *s)
{
const SSL_CIPHER *c;
@@ -1100,12 +1174,14 @@ void print_ssl_summary(SSL *s)
peer = SSL_get_peer_certificate(s);
if (peer) {
int nid;
+
BIO_puts(bio_err, "Peer certificate: ");
X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
0, XN_FLAG_ONELINE);
BIO_puts(bio_err, "\n");
if (SSL_get_peer_signature_nid(s, &nid))
BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid));
+ print_verify_detail(s, bio_err);
} else
BIO_puts(bio_err, "No peer certificate\n");
X509_free(peer);
diff --git a/apps/s_client.c b/apps/s_client.c
index 39e3e48288..8fe16121a9 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -2461,9 +2461,6 @@ static void print_stuff(BIO *bio, SSL *s, int full)
const SSL_CIPHER *c;
X509_NAME *xn;
int i;
- int mdpth;
- EVP_PKEY *mspki;
- const char *peername;
#ifndef OPENSSL_NO_COMP
const COMP_METHOD *comp, *expansion;
#endif
@@ -2525,18 +2522,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
BIO_number_read(SSL_get_rbio(s)),
BIO_number_written(SSL_get_wbio(s)));
}
- if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) {
- uint8_t usage, selector, mtype;
- mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, NULL, NULL);
- BIO_printf(bio, "DANE TLSA %d %d %d %s at depth %d\n",
- usage, selector, mtype,
- (mspki != NULL) ? "TA public key verified certificate" :
- mdpth ? "matched TA certificate" : "matched EE certificate",
- mdpth);
- }
- if (SSL_get_verify_result(s) == X509_V_OK &&
- (peername = SSL_get0_peername(s)) != NULL)
- BIO_printf(bio, "Verified peername: %s\n", peername);
+ print_verify_detail(s, bio);
BIO_printf(bio, (SSL_session_reused(s) ? "---\nReused, " : "---\nNew, "));
c = SSL_get_current_cipher(s);
BIO_printf(bio, "%s, Cipher is %s\n",
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index 0e480644e5..884c3afdd4 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -69,11 +69,11 @@
const char *X509_verify_cert_error_string(long n)
{
- static char buf[100];
-
switch ((int)n) {
case X509_V_OK:
return ("ok");
+ case X509_V_ERR_UNSPECIFIED:
+ return ("unspecified certificate verification error");
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
return ("unable to get issuer certificate");
case X509_V_ERR_UNABLE_TO_GET_CRL:
@@ -202,9 +202,11 @@ const char *X509_verify_cert_error_string(long n)
return ("Email address mismatch");
case X509_V_ERR_IP_ADDRESS_MISMATCH:
return ("IP address mismatch");
+ case X509_V_ERR_DANE_NO_MATCH:
+ return ("No matching DANE TLSA records");
default:
- BIO_snprintf(buf, sizeof buf, "error number %ld", n);
- return (buf);
+ /* Printing an error number into a static buffer is not thread-safe */
+ return ("unknown certificate verification error");
}
}
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 113c116ef6..f8b9b503ac 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -2631,7 +2631,7 @@ static int check_dane_pkeys(X509_STORE_CTX *ctx)
X509_verify(cert, t->spki) <= 0)
continue;
- /* Clear PKIX-?? matches that failed to panned out to a full chain */
+ /* Clear any PKIX-?? matches that failed to extend to a full chain */
X509_free(dane->mcert);
dane->mcert = NULL;
@@ -2711,7 +2711,7 @@ static int dane_verify(X509_STORE_CTX *ctx)
return 0;
ctx->current_cert = cert;
ctx->error_depth = 0;
- ctx->error = X509_V_ERR_CERT_UNTRUSTED;
+ ctx->error = X509_V_ERR_DANE_NO_MATCH;
return ctx->verify_cb(0, ctx);
}
@@ -3026,7 +3026,7 @@ static int build_chain(X509_STORE_CTX *ctx)
ctx->error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
else if (DANETLS_ENABLED(dane) &&
(!DANETLS_HAS_PKIX(dane) || dane->pdpth >= 0))
- ctx->error = X509_V_ERR_CERT_UNTRUSTED;
+ ctx->error = X509_V_ERR_DANE_NO_MATCH;
else if (ss && sk_X509_num(ctx->chain) == 1)
ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
else if (ss)
@@ -3035,8 +3035,6 @@ static int build_chain(X509_STORE_CTX *ctx)
ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
else
ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
- if (DANETLS_ENABLED(dane))
- dane_reset(dane);
return ctx->verify_cb(0, ctx);
}
}
diff --git a/doc/apps/s_client.pod b/doc/apps/s_client.pod
index 1cd04dd169..394c6494d7 100644
--- a/doc/apps/s_client.pod
+++ b/doc/apps/s_client.pod
@@ -202,18 +202,17 @@ fields that specify the usage, selector, matching type and associated
data, with the last of these encoded in hexadecimal. Optional
whitespace is ignored in the associated data field. For example:
- $ openssl s_client -starttls smtp -connect smtp.example.com:25 \
+ $ openssl s_client -brief -starttls smtp \
+ -connect smtp.example.com:25 \
-dane_tlsa_domain smtp.example.com \
-dane_tlsa_rrdata "2 1 1
B111DD8A1C2091A89BD4FD60C57F0716CCE50FEEFF8137CDBEE0326E 02CF362B" \
-dane_tlsa_rrdata "2 1 1
60B87575447DCBA2A36B7D11AC09FB24A9DB406FEE12D2CC90180517 616E8A18"
- CONNECTED(00000003)
...
- DANE TLSA 2 1 1 matched TA certificate at depth 1
+ Verification: OK
Verified peername: smtp.example.com
- ...
- Verify return code: 0 (ok)
+ DANE TLSA 2 1 1 ...ee12d2cc90180517616e8a18 matched TA certificate at depth 1
...
=item B<-attime>, B<-check_ss_sig>, B<-crl_check>, B<-crl_check_all>,
diff --git a/doc/ssl/SSL_CTX_dane_enable.pod b/doc/ssl/SSL_CTX_dane_enable.pod
index a9c24e1b34..36e969950b 100644
--- a/doc/ssl/SSL_CTX_dane_enable.pod
+++ b/doc/ssl/SSL_CTX_dane_enable.pod
@@ -82,6 +82,9 @@ 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.
+The complete verified chain can be retrieved via L<SSL_get0_verified_chain(3)>.
+The return value is an index into this verified chain, rather than the list of
+certificates sent by the peer as returned by L<SSL_get_peer_cert_chain(3)>.
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>.
@@ -203,9 +206,27 @@ the lifetime of the SSL connection.
SSL_set_verify(ssl, SSL_VERIFY_NONE, cb);
}
+ /*
+ * Load any saved session for resumption, making sure that the previous
+ * session applied the same security and authentication requirements that
+ * would be expected of a fresh connection.
+ */
+
/* Perform SSL_connect() handshake and handle errors here */
- if (SSL_get_verify_result(ssl) == X509_V_OK) {
+ if (SSL_session_resumed(ssl)) {
+ if (SSL_get_verify_result(ssl) == X509_V_OK) {
+ /*
+ * Resumed session was originally verified, this connection is
+ * authenticated.
+ */
+ } else {
+ /*
+ * Resumed session was not originally verified, this connection is not
+ * authenticated.
+ */
+ }
+ } else if (SSL_get_verify_result(ssl) == X509_V_OK) {
const char *peername = SSL_get0_peername(ssl);
EVP_PKEY *mspki = NULL;
@@ -260,12 +281,15 @@ 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_get0_verified_chain(3)>,
+L<SSL_get_peer_cert_chain(3)>,
+L<SSL_get_verify_result(3)>,
L<SSL_connect(3)>,
L<SSL_get0_peername(3)>,
-L<EVP_get_digestbyname(3)>,
+L<X509_verify_cert(3)>,
L<X509_up_ref(3)>,
L<X509_free(3)>,
+L<EVP_get_digestbyname(3)>,
L<EVP_PKEY_up_ref(3)>,
L<EVP_PKEY_free(3)>
diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h
index 4e458d20ff..2ed1e4c007 100644
--- a/include/openssl/x509_vfy.h
+++ b/include/openssl/x509_vfy.h
@@ -355,6 +355,8 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
# define X509_V_ERR_HOSTNAME_MISMATCH 62
# define X509_V_ERR_EMAIL_MISMATCH 63
# define X509_V_ERR_IP_ADDRESS_MISMATCH 64
+/* DANE TLSA errors */
+# define X509_V_ERR_DANE_NO_MATCH 65
/* The application is not happy */
# define X509_V_ERR_APPLICATION_VERIFICATION 50
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index aac23926ca..fc72d39701 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -913,7 +913,7 @@ int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki)
{
struct dane_st *dane = &s->dane;
- if (!DANETLS_ENABLED(dane))
+ if (!DANETLS_ENABLED(dane) || s->verify_result != X509_V_OK)
return -1;
if (dane->mtlsa) {
if (mcert)
@@ -929,7 +929,7 @@ int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
{
struct dane_st *dane = &s->dane;
- if (!DANETLS_ENABLED(dane))
+ if (!DANETLS_ENABLED(dane) || s->verify_result != X509_V_OK)
return -1;
if (dane->mtlsa) {
if (usage)
diff --git a/test/certs/mkcert.sh b/test/certs/mkcert.sh
index d5870c7d20..7b892d2fed 100755
--- a/test/certs/mkcert.sh
+++ b/test/certs/mkcert.sh
@@ -36,7 +36,7 @@ key() {
args=(-algorithm "$alg")
case $alg in
rsa) args=("${args[@]}" -pkeyopt rsa_keygen_bits:$bits );;
- ecdsa) args=("${args[@]}" -pkeyopt "ec_paramgen_curve:$bits")
+ ec) args=("${args[@]}" -pkeyopt "ec_paramgen_curve:$bits")
args=("${args[@]}" -pkeyopt ec_param_enc:named_curve);;
*) printf "Unsupported key algorithm: %s\n" "$alg" >&2; return 1;;
esac
diff --git a/test/danetest.c b/test/danetest.c
index cad751f4ba..b9ccd404d3 100644
--- a/test/danetest.c
+++ b/test/danetest.c
@@ -413,7 +413,15 @@ static int test_tlsafile(SSL_CTX *ctx, const char *basename,
ok = verify_chain(ssl, chain);
sk_X509_pop_free(chain, X509_free);
err = SSL_get_verify_result(ssl);
+ /*
+ * Peek under the hood, normally TLSA match data is hidden when
+ * verification fails, we can obtain any suppressed data by setting the
+ * verification result to X509_V_OK before looking.
+ */
+ SSL_set_verify_result(ssl, X509_V_OK);
mdpth = SSL_get0_dane_authority(ssl, NULL, NULL);
+ /* Not needed any more, but lead by example and put the error back. */
+ SSL_set_verify_result(ssl, err);
SSL_free(ssl);
if (ok < 0) {
diff --git a/test/danetest.in b/test/danetest.in
index a9a01c06b4..7db0400245 100644
--- a/test/danetest.in
+++ b/test/danetest.in
@@ -101,7 +101,7 @@ yBKzbWcWMavIefhyAiEAsIia0rOBTuZL3dWn9qmN6kPLQ1BJRpy1CkQEy97uH9Y=
-----END CERTIFICATE-----
# 5
-1 1 27 -1
+1 1 65 -1
3 0 1 588FD5F414E3327EAFE3169DC040AE161247D1296BF38304AB9CF464850A1366
subject=
issuer=
@@ -116,7 +116,7 @@ yBKzbWcWMavIefhyAiEAsIia0rOBTuZL3dWn9qmN6kPLQ1BJRpy1CkQEy97uH9Y=
-----END CERTIFICATE-----
# 6
-1 1 27 -1
+1 1 65 -1
3 1 1 05C66146D7909EAE2379825F6D0F5284146B79598DA12E403DC29C33147CF33F
subject=
issuer=
@@ -131,7 +131,7 @@ yBKzbWcWMavIefhyAiEAsIia0rOBTuZL3dWn9qmN6kPLQ1BJRpy1CkQEy97uH9Y=
-----END CERTIFICATE-----
# 7
-1 1 27 -1
+1 1 65 -1
3 0 2 42BEE929852C8063A0D619B53D0DD35703BBAD2FC25F2055F737C7A14DDFEA544491F8C00F50FA083BD0AD1B5C98529994FF811BBA5E5170CC6EE9F3ED5563E2
subject=
issuer=
@@ -146,7 +146,7 @@ yBKzbWcWMavIefhyAiEAsIia0rOBTuZL3dWn9qmN6kPLQ1BJRpy1CkQEy97uH9Y=
-----END CERTIFICATE-----
# 8
-1 1 27 -1
+1 1 65 -1
3 1 2 D91A3E5DC34879CD77AD1E989F56FA78FACADF05EF8D445EDF5652BD58EE392C87C02F84C0119D62309041F2D5128A73399DF25D1F47BCD497357EAF1A1009A4
subject=
issuer=
@@ -1212,7 +1212,7 @@ vBCcrtNYKWa/JfwFmOq6bHk8WNzDU3zF
# 33
# Missing intermediate CA
-1 1 20 -1
+1 1 20 0
1 0 1 BEDC04764CECAE80AEE454D332758F50847DCA424216466E4012E0DEAE1F2E5F
subject= /CN=example.com
issuer= /CN=Issuer CA
@@ -1253,7 +1253,7 @@ GoTXBNutM50ph9QYUtxZNvISlHBjkRGB
# 35
# Wrong leaf digest
-1 3 27 -1
+1 3 65 -1
1 0 2 F756CCD61F3CA50D017653911701CA0052AF0B29E273DD263DD23643D86D4369D03686BD1369EF54BB2DC2DAE3CE4F05AF39D54648F94D54AA86B259AEAD9924
subject= /CN=example.com
issuer= /CN=Issuer CA
@@ -1301,7 +1301,7 @@ vBCcrtNYKWa/JfwFmOq6bHk8WNzDU3zF
# 36
# Wrong intermediate digest
-1 2 27 -1
+1 2 65 -1
0 0 1 0DAA76425A1FC398C55A643D5A2485AE4CC2B64B9515A75054722B2E83C31BBE
subject= /CN=example.com
issuer= /CN=Issuer CA
@@ -1335,7 +1335,7 @@ GcTNPLx5FgPUSI93B1l9t5gNnBc+f90OzXyjCA==
# 37
# Wrong root digest
-1 2 27 -1
+1 2 65 -1
0 0 1 FE7C8E01110627A782765E468D8CB4D2CC7907EAC4BA5974CD92B540ED2AAC3D
subject= /CN=example.com
issuer= /CN=Issuer CA
@@ -1370,7 +1370,7 @@ GcTNPLx5FgPUSI93B1l9t5gNnBc+f90OzXyjCA==
## -- Mixed usage cases
# 38
-# DANE-EE beats DANE-TA
+# DANE-EE(3) beats DANE-TA(2)
1 3 0 0
3 1 2 CB861AF6DDED185EE04472A9092052CCC735120C34785E72C996C94B122EBA6F329BE630B1B4C6E2756E7A75392C21E253C6AEACC31FD45FF4595DED375FAF62
2 1 2 5F414D4D7BFDF22E39952D9F46C51370FDD050F10C55B4CDB42E40FA98611FDE23EEE9B23315EE1ECDB198C7419E9A2D6742860E4806AF45164507799C3B452E
@@ -1419,7 +1419,7 @@ vBCcrtNYKWa/JfwFmOq6bHk8WNzDU3zF
-----END CERTIFICATE-----
# 39
-# DANE-TA depth 1 beats DANE-TA depth 2
+# DANE-TA(2) depth 1 beats DANE-TA(2) depth 2
1 3 0 1
2 1 2 1F484106F765B6F1AC483CC509CDAD36486A83D1BA115F562516F407C1109303658408B455824DA0785A252B205DBEECB1AFB5DB869E8AAC242091B63F258F05
2 1 2 5F414D4D7BFDF22E39952D9F46C51370FDD050F10C55B4CDB42E40FA98611FDE23EEE9B23315EE1ECDB198C7419E9A2D6742860E4806AF45164507799C3B452E
@@ -1468,7 +1468,7 @@ vBCcrtNYKWa/JfwFmOq6bHk8WNzDU3zF
-----END CERTIFICATE-----
# 40
-# DANE-TA depth 2 beats PKIX-TA depth 1
+# DANE-TA(2) depth 2 beats PKIX-TA(0) depth 1
1 3 0 2
2 0 1 FE7C8E01110627A782765E468D8CB4D2CC7907EAC4BA5974CD92B540ED2AAC3C
0 0 1 0DAA76425A1FC398C55A643D5A2485AE4CC2B64B9515A75054722B2E83C31BBD
@@ -1517,7 +1517,7 @@ vBCcrtNYKWa/JfwFmOq6bHk8WNzDU3zF
-----END CERTIFICATE-----
# 41
-# DANE-TA depth 2 beats PKIX-EE depth 0
+# DANE-TA(2) depth 2 beats PKIX-EE depth 0
1 3 0 2
2 0 1 FE7C8E01110627A782765E468D8CB4D2CC7907EAC4BA5974CD92B540ED2AAC3C
0 0 1 0DAA76425A1FC398C55A643D5A2485AE4CC2B64B9515A75054722B2E83C31BBD
@@ -1566,7 +1566,7 @@ vBCcrtNYKWa/JfwFmOq6bHk8WNzDU3zF
-----END CERTIFICATE-----
# 42
-# DANE-TA Full(0) root "from DNS":
+# DANE-TA(2) Full(0) root "from DNS":
1 2 0 2
2 0 0 308201643082010BA003020102020101300A06082A8648CE3D04030230123110300E06035504030C07526F6F742043413020170D3135313231333233313330385A180F33303135303431353233313330385A30123110300E06035504030C07526F6F742043413059301306072A8648CE3D020106082A8648CE3D03010703420004D1DA578FD18FB86456B0D91B5656BDD68D4DDBD250E337571127C75E0560F41D0AF91BFAF8805F80C28C026A14D4FE8C30A9673B9EC0C05A84AA810D1341B76CA350304E301D0603551D0E04160414E4BD405F052A820DDF9883F93D7D3F90AAEC723F301F0603551D23041830168014E4BD405F052A820DDF9883F93D7D3F90AAEC723F300C0603551D13040530030101FF300A06082A8648CE3D040302034700304402206869E6AA9F9B4D4BF308091A5A7AB2C30E3619B0D75E528819468E4BB926F4C9022017F1B8458611966FBC109CAED3582966BF25FC0598EABA6C793C58DCC3537CC5
subject= /CN=example.com
@@ -1600,7 +1600,7 @@ GcTNPLx5FgPUSI93B1l9t5gNnBc+f90OzXyjCA==
-----END CERTIFICATE-----
# 43
-# DANE-TA Full(0) intermediate "from DNS":
+# DANE-TA(2) Full(0) intermediate "from DNS":
1 1 0 1
2 0 0 308201683082010DA003020102020102300A06082A8648CE3D04030230123110300E06035504030C07526F6F742043413020170D3135313231333233323030395A180F33303135303431353233323030395A30143112301006035504030C094973737565722043413059301306072A8648CE3D020106082A8648CE3D030107034200047D4BAE18B49F5DC69D0A3C85C66A3E2119DE92CFAD081FAD55C12D510EC97B6C00E13695A8D9713548FE60DF15573390433E2A1BD92DB4B7AA016EC6185DC5AFA350304E301D0603551D0E041604147AB75A3CD295CA5DF7C5150916E18FF5CC376A15301F0603551D23041830168014E4BD405F052A820DDF9883F93D7D3F90AAEC723F300C0603551D13040530030101FF300A06082A8648CE3D0403020349003046022100831DCD882DA8785D50E41020898C0248879DDDF72D701D1DC1DE6BE08155B43E022100B84B2FB519C4CD3CBC791603D4488F7707597DB7980D9C173E7FDD0ECD7CA308
subject= /CN=example.com
@@ -1620,7 +1620,7 @@ GoTXBNutM50ph9QYUtxZNvISlHBjkRGB
-----END CERTIFICATE-----
# 44
-# DANE-TA(3) SPKI(1) Full(0) intermediate "from DNS":
+# DANE-TA(2) SPKI(1) Full(0) intermediate "from DNS":
1 1 0 0
2 1 0 3059301306072A8648CE3D020106082A8648CE3D030107034200047D4BAE18B49F5DC69D0A3C85C66A3E2119DE92CFAD081FAD55C12D510EC97B6C00E13695A8D9713548FE60DF15573390433E2A1BD92DB4B7AA016EC6185DC5AF
subject= /CN=example.com
@@ -1640,7 +1640,7 @@ GoTXBNutM50ph9QYUtxZNvISlHBjkRGB
-----END CERTIFICATE-----
# 45
-# DANE-TA(3) SPKI(1) Full(0) root "from DNS":
+# DANE-TA(2) SPKI(1) Full(0) root "from DNS":
1 2 0 1
2 1 0 3059301306072A8648CE3D020106082A8648CE3D03010703420004D1DA578FD18FB86456B0D91B5656BDD68D4DDBD250E337571127C75E0560F41D0AF91BFAF8805F80C28C026A14D4FE8C30A9673B9EC0C05A84AA810D1341B76C
subject= /CN=example.com
@@ -1673,3 +1673,149 @@ AgNJADBGAiEAgx3NiC2oeF1Q5BAgiYwCSIed3fctcB0dwd5r4IFVtD4CIQC4Sy+1
GcTNPLx5FgPUSI93B1l9t5gNnBc+f90OzXyjCA==
-----END CERTIFICATE-----
+# 46
+# Mismatched name "example.org", should still succeed given a
+# DANE-EE(3) match.
+1 3 0 0
+3 1 1 ee1477190203f5d8b4767f4451b89e7367cdec7f6965a4988227983562ac8270
+subject= CN = example.org
+issuer= CN = CA2
+notBefore=Feb 6 22:39:47 2016 GMT
+notAfter=Feb 7 22:39:47 2116 GMT
+-----BEGIN CERTIFICATE-----
+MIIBkDCCATWgAwIBAgIBAjAKBggqhkjOPQQDAjAOMQwwCgYDVQQDDANDQTIwIBcN
+MTYwMjA2MjIzOTQ3WhgPMjExNjAyMDcyMjM5NDdaMBYxFDASBgNVBAMMC2V4YW1w
+bGUub3JnMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/YCEn0pxClPTvpjioxU4
+ajopRa4j/6XTqxy9zqn1AcMCiVWp6j22B6RpLmKEHoRHQxFzebd2juTXIDq81CID
+z6N6MHgwHQYDVR0OBBYEFOrSA+2YKXa5KR6k0687CZuhai5OMB8GA1UdIwQYMBaA
+FLTY4vqgjcQ01aCcB8AYVbUhEU7VMAkGA1UdEwQCMAAwEwYDVR0lBAwwCgYIKwYB
+BQUHAwEwFgYDVR0RBA8wDYILZXhhbXBsZS5vcmcwCgYIKoZIzj0EAwIDSQAwRgIh
+AKSsLwlidPiSrgda6XWihov4D4KHu6ZX3ZAAZ2uiBAefAiEArCq5WiO3Zeunl0Ct
+PyDiaL1QKbJ7lnqPQCS1o8xn+RI=
+-----END CERTIFICATE-----
+subject= CN = CA2
+issuer= CN = Root CA2
+notBefore=Feb 6 22:39:13 2016 GMT
+notAfter=Feb 7 22:39:13 2116 GMT
+-----BEGIN CERTIFICATE-----
+MIIBYjCCAQigAwIBAgIBAjAKBggqhkjOPQQDAjATMREwDwYDVQQDDAhSb290IENB
+MjAgFw0xNjAyMDYyMjM5MTNaGA8yMTE2MDIwNzIyMzkxM1owDjEMMAoGA1UEAwwD
+Q0EyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYr6zgBxpsxA31IFiGyb6uaGC
+CQdNMyJfDgqCihsU1eOEuauzXO7tydCbjfRmhqQK1EGd254IjcGY+37tZEbvPKNQ
+ME4wHQYDVR0OBBYEFLTY4vqgjcQ01aCcB8AYVbUhEU7VMB8GA1UdIwQYMBaAFBRb
++/qrntsksembakoZTwTZk8AXMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSAAw
+RQIgX2fmMykyiuryf1AeKyc1j8HgmM8u/nyQfJnTCwvYUcECIQC6JHd3ybV9eJQo
+7sfr/jV+rRlZY2iaRv160BWYd82L7g==
+-----END CERTIFICATE-----
+subject= CN = Root CA2
+issuer= CN = Root CA2
+notBefore=Feb 6 22:38:48 2016 GMT
+notAfter=Feb 7 22:38:48 2116 GMT
+-----BEGIN CERTIFICATE-----
+MIIBaDCCAQ2gAwIBAgIBATAKBggqhkjOPQQDAjATMREwDwYDVQQDDAhSb290IENB
+MjAgFw0xNjAyMDYyMjM4NDhaGA8yMTE2MDIwNzIyMzg0OFowEzERMA8GA1UEAwwI
+Um9vdCBDQTIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATlTxAPKteg+L1LmxMl
+sbAFMxj6/322nR5RRGeF07KZRBFPaFZLgwZ1DuNrwM3wxxNdUyoZ6iAyDmwNf3K1
+42/Uo1AwTjAdBgNVHQ4EFgQUFFv7+que2ySx6ZtqShlPBNmTwBcwHwYDVR0jBBgw
+FoAUFFv7+que2ySx6ZtqShlPBNmTwBcwDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQD
+AgNJADBGAiEAumhPWZ37swl10awM/amX+jv0UlUyJBf8RGA6QMG5bwICIQDbinER
+fEevg+GOsr1P6nNMCAsQd9NwsvTQ+jm+TBArWQ==
+-----END CERTIFICATE-----
+
+# 47
+# Mismatched name "example.org", should fail despite a DANE-TA(2)
+# match for the intermediate CA.
+1 3 62 1
+2 1 1 946af0956378efaba7ee1bbedc17af110ea8de19c079a98e77398724a3708a1f
+subject= CN = example.org
+issuer= CN = CA2
+notBefore=Feb 6 22:39:47 2016 GMT
+notAfter=Feb 7 22:39:47 2116 GMT
+-----BEGIN CERTIFICATE-----
+MIIBkDCCATWgAwIBAgIBAjAKBggqhkjOPQQDAjAOMQwwCgYDVQQDDANDQTIwIBcN
+MTYwMjA2MjIzOTQ3WhgPMjExNjAyMDcyMjM5NDdaMBYxFDASBgNVBAMMC2V4YW1w
+bGUub3JnMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/YCEn0pxClPTvpjioxU4
+ajopRa4j/6XTqxy9zqn1AcMCiVWp6j22B6RpLmKEHoRHQxFzebd2juTXIDq81CID
+z6N6MHgwHQYDVR0OBBYEFOrSA+2YKXa5KR6k0687CZuhai5OMB8GA1UdIwQYMBaA
+FLTY4vqgjcQ01aCcB8AYVbUhEU7VMAkGA1UdEwQCMAAwEwYDVR0lBAwwCgYIKwYB
+BQUHAwEwFgYDVR0RBA8wDYILZXhhbXBsZS5vcmcwCgYIKoZIzj0EAwIDSQAwRgIh
+AKSsLwlidPiSrgda6XWihov4D4KHu6ZX3ZAAZ2uiBAefAiEArCq5WiO3Zeunl0Ct
+PyDiaL1QKbJ7lnqPQCS1o8xn+RI=
+-----END CERTIFICATE-----
+subject= CN = CA2
+issuer= CN = Root CA2
+notBefore=Feb 6 22:39:13 2016 GMT
+notAfter=Feb 7 22:39:13 2116 GMT
+-----BEGIN CERTIFICATE-----
+MIIBYjCCAQigAwIBAgIBAjAKBggqhkjOPQQDAjATMREwDwYDVQQDDAhSb290IENB
+MjAgFw0xNjAyMDYyMjM5MTNaGA8yMTE2MDIwNzIyMzkxM1owDjEMMAoGA1UEAwwD
+Q0EyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYr6zgBxpsxA31IFiGyb6uaGC
+CQdNMyJfDgqCihsU1eOEuauzXO7tydCbjfRmhqQK1EGd254IjcGY+37tZEbvPKNQ
+ME4wHQYDVR0OBBYEFLTY4vqgjcQ01aCcB8AYVbUhEU7VMB8GA1UdIwQYMBaAFBRb
++/qrntsksembakoZTwTZk8AXMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSAAw
+RQIgX2fmMykyiuryf1AeKyc1j8HgmM8u/nyQfJnTCwvYUcECIQC6JHd3ybV9eJQo
+7sfr/jV+rRlZY2iaRv160BWYd82L7g==
+-----END CERTIFICATE-----
+subject= CN = Root CA2
+issuer= CN = Root CA2
+notBefore=Feb 6 22:38:48 2016 GMT
+notAfter=Feb 7 22:38:48 2116 GMT
+-----BEGIN CERTIFICATE-----
+MIIBaDCCAQ2gAwIBAgIBATAKBggqhkjOPQQDAjATMREwDwYDVQQDDAhSb290IENB
+MjAgFw0xNjAyMDYyMjM4NDhaGA8yMTE2MDIwNzIyMzg0OFowEzERMA8GA1UEAwwI
+Um9vdCBDQTIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATlTxAPKteg+L1LmxMl
+sbAFMxj6/322nR5RRGeF07KZRBFPaFZLgwZ1DuNrwM3wxxNdUyoZ6iAyDmwNf3K1
+42/Uo1AwTjAdBgNVHQ4EFgQUFFv7+que2ySx6ZtqShlPBNmTwBcwHwYDVR0jBBgw
+FoAUFFv7+que2ySx6ZtqShlPBNmTwBcwDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQD
+AgNJADBGAiEAumhPWZ37swl10awM/amX+jv0UlUyJBf8RGA6QMG5bwICIQDbinER
+fEevg+GOsr1P6nNMCAsQd9NwsvTQ+jm+TBArWQ==
+-----END CERTIFICATE-----
+
+# 48
+# Mismatched name "example.org", should fail despite a DANE-TA(2)
+# match for the root CA.
+1 3 62 2
+2 1 1 34474f2fbc39da44dfbd11215bdafadf9507406c04de1f65dbd2a1bc4f2165cc
+subject= CN = example.org
+issuer= CN = CA2
+notBefore=Feb 6 22:39:47 2016 GMT
+notAfter=Feb 7 22:39:47 2116 GMT
+-----BEGIN CERTIFICATE-----
+MIIBkDCCATWgAwIBAgIBAjAKBggqhkjOPQQDAjAOMQwwCgYDVQQDDANDQTIwIBcN
+MTYwMjA2MjIzOTQ3WhgPMjExNjAyMDcyMjM5NDdaMBYxFDASBgNVBAMMC2V4YW1w
+bGUub3JnMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/YCEn0pxClPTvpjioxU4
+ajopRa4j/6XTqxy9zqn1AcMCiVWp6j22B6RpLmKEHoRHQxFzebd2juTXIDq81CID
+z6N6MHgwHQYDVR0OBBYEFOrSA+2YKXa5KR6k0687CZuhai5OMB8GA1UdIwQYMBaA
+FLTY4vqgjcQ01aCcB8AYVbUhEU7VMAkGA1UdEwQCMAAwEwYDVR0lBAwwCgYIKwYB
+BQUHAwEwFgYDVR0RBA8wDYILZXhhbXBsZS5vcmcwCgYIKoZIzj0EAwIDSQAwRgIh
+AKSsLwlidPiSrgda6XWihov4D4KHu6ZX3ZAAZ2uiBAefAiEArCq5WiO3Zeunl0Ct
+PyDiaL1QKbJ7lnqPQCS1o8xn+RI=
+-----END CERTIFICATE-----
+subject= CN = CA2
+issuer= CN = Root CA2
+notBefore=Feb 6 22:39:13 2016 GMT
+notAfter=Feb 7 22:39:13 2116 GMT
+-----BEGIN CERTIFICATE-----
+MIIBYjCCAQigAwIBAgIBAjAKBggqhkjOPQQDAjATMREwDwYDVQQDDAhSb290IENB
+MjAgFw0xNjAyMDYyMjM5MTNaGA8yMTE2MDIwNzIyMzkxM1owDjEMMAoGA1UEAwwD
+Q0EyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYr6zgBxpsxA31IFiGyb6uaGC
+CQdNMyJfDgqCihsU1eOEuauzXO7tydCbjfRmhqQK1EGd254IjcGY+37tZEbvPKNQ
+ME4wHQYDVR0OBBYEFLTY4vqgjcQ01aCcB8AYVbUhEU7VMB8GA1UdIwQYMBaAFBRb
++/qrntsksembakoZTwTZk8AXMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSAAw
+RQIgX2fmMykyiuryf1AeKyc1j8HgmM8u/nyQfJnTCwvYUcECIQC6JHd3ybV9eJQo
+7sfr/jV+rRlZY2iaRv160BWYd82L7g==
+-----END CERTIFICATE-----
+subject= CN = Root CA2
+issuer= CN = Root CA2
+notBefore=Feb 6 22:38:48 2016 GMT
+notAfter=Feb 7 22:38:48 2116 GMT
+-----BEGIN CERTIFICATE-----
+MIIBaDCCAQ2gAwIBAgIBATAKBggqhkjOPQQDAjATMREwDwYDVQQDDAhSb290IENB
+MjAgFw0xNjAyMDYyMjM4NDhaGA8yMTE2MDIwNzIyMzg0OFowEzERMA8GA1UEAwwI
+Um9vdCBDQTIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATlTxAPKteg+L1LmxMl
+sbAFMxj6/322nR5RRGeF07KZRBFPaFZLgwZ1DuNrwM3wxxNdUyoZ6iAyDmwNf3K1
+42/Uo1AwTjAdBgNVHQ4EFgQUFFv7+que2ySx6ZtqShlPBNmTwBcwHwYDVR0jBBgw
+FoAUFFv7+que2ySx6ZtqShlPBNmTwBcwDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQD
+AgNJADBGAiEAumhPWZ37swl10awM/amX+jv0UlUyJBf8RGA6QMG5bwICIQDbinER
+fEevg+GOsr1P6nNMCAsQd9NwsvTQ+jm+TBArWQ==
+-----END CERTIFICATE-----