aboutsummaryrefslogtreecommitdiffstats
path: root/doc/ssl/SSL_CTX_dane_enable.pod
blob: 66eb1b3d8d109eea4cf931be147d48413bb47245 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
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