openssl/doc/ssl/SSL_CTX_dane_enable.pod
Viktor Dukhovni c0a445a9f2 Suppress DANE TLSA reflection when verification fails
As documented both SSL_get0_dane_authority() and SSL_get0_dane_tlsa()
are expected to return a negative match depth and nothing else when
verification fails.  However, this only happened when verification
failed during chain construction.  Errors in verification of the
constructed chain did not have the intended effect on these functions.

This commit updates the functions to check for verify_result ==
X509_V_OK, and no longer erases any accumulated match information
when chain construction fails.  Sophisticated developers can, with
care, use SSL_set_verify_result(ssl, X509_V_OK) to "peek" at TLSA
info even when verification fail.  They must of course first check
and save the real error, and restore the original error as quickly
as possible.  Hiding by default seems to be the safer interface.

Introduced X509_V_ERR_DANE_NO_MATCH code to signal failure to find
matching TLSA records.  Previously reported via X509_V_ERR_CERT_UNTRUSTED.

This also changes the "-brief" output from s_client to include
verification results and TLSA match information.

Mentioned session resumption in code example in SSL_CTX_dane_enable(3).
Also mentioned that depths returned are relative to the verified chain
which is now available via SSL_get0_verified_chain(3).

Added a few more test-cases to danetest, that exercise the new
code.

Resolved thread safety issue in use of static buffer in
X509_verify_cert_error_string().

Fixed long-stating issue in apps/s_cb.c which always sets verify_error
to either X509_V_OK or "chain to long", code elsewhere (e.g.
s_time.c), seems to expect the actual error.  [ The new chain
construction code is expected to correctly generate "chain
too long" errors, so at some point we need to drop the
work-arounds, once SSL_set_verify_depth() is also fixed to
propagate the depth to X509_STORE_CTX reliably. ]

Reviewed-by: Rich Salz <rsalz@openssl.org>
2016-02-08 14:46:09 -05:00

301 lines
12 KiB
Plaintext

=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 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() must be called before the SSL handshake is initiated with
L<SSL_connect(3)> if (and only if) you want 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.
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>.
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 appropriate */
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);
}
/*
* 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_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;
int depth = SSL_get0_dane_authority(ssl, NULL, &mspki);
if (depth >= 0) {
(void) SSL_get0_dane_tlsa(ssl, &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<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<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)>
=head1 HISTORY
These functions were first added to OpenSSL 1.1.0.
=cut