From 9d75dce3e1f94be6006500089491cb3284f70d06 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Mon, 18 Dec 2017 16:52:28 -0500 Subject: Add TLSv1.3 post-handshake authentication (PHA) Add SSL_verify_client_post_handshake() for servers to initiate PHA Add SSL_force_post_handshake_auth() for clients that don't have certificates initially configured, but use a certificate callback. Update SSL_CTX_set_verify()/SSL_set_verify() mode: * Add SSL_VERIFY_POST_HANDSHAKE to postpone client authentication until after the initial handshake. * Update SSL_VERIFY_CLIENT_ONCE now only sends out one CertRequest regardless of when the certificate authentication takes place; either initial handshake, re-negotiation, or post-handshake authentication. Add 'RequestPostHandshake' and 'RequirePostHandshake' SSL_CONF options that add the SSL_VERIFY_POST_HANDSHAKE to the 'Request' and 'Require' options Add support to s_client: * Enabled automatically when cert is configured * Can be forced enabled via -force_pha Add support to s_server: * Use 'c' to invoke PHA in s_server * Remove some dead code Update documentation Update unit tests: * Illegal use of PHA extension * TLSv1.3 certificate tests DTLS and TLS behave ever-so-slightly differently. So, when DTLS1.3 is implemented, it's PHA support state machine may need to be different. Add a TODO and a #error Update handshake context to deal with PHA. The handshake context for TLSv1.3 post-handshake auth is up through the ClientFinish message, plus the CertificateRequest message. Subsequent Certificate, CertificateVerify, and Finish messages are based on this handshake context (not the Certificate message per se, but it's included after the hash). KeyUpdate, NewSessionTicket, and prior Certificate Request messages are not included in post-handshake authentication. After the ClientFinished message is processed, save off the digest state for future post-handshake authentication. When post-handshake auth occurs, copy over the saved handshake context into the "main" handshake digest. This effectively discards the any KeyUpdate or NewSessionTicket messages and any prior post-handshake authentication. This, of course, assumes that the ID-22 did not mean to include any previous post-handshake authentication into the new handshake transcript. This is implied by section 4.4.1 that lists messages only up to the first ClientFinished. Reviewed-by: Ben Kaduk Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/4964) --- doc/man1/s_client.pod | 6 ++++ doc/man3/SSL_CONF_cmd.pod | 12 ++++++++ doc/man3/SSL_CTX_set_verify.pod | 67 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 78 insertions(+), 7 deletions(-) (limited to 'doc') diff --git a/doc/man1/s_client.pod b/doc/man1/s_client.pod index 1d9dd39656..4f0f01c3db 100644 --- a/doc/man1/s_client.pod +++ b/doc/man1/s_client.pod @@ -118,6 +118,7 @@ B B [B<-ctlogfile>] [B<-keylogfile file>] [B<-early_data file>] +[B<-force_pha>] [B] =head1 DESCRIPTION @@ -621,6 +622,11 @@ Reads the contents of the specified file and attempts to send it as early data to the server. This will only work with resumed sessions that support early data and when the server accepts the early data. +=item B<-force_pha> + +For TLSv1.3 only, always send the Post-Handshake Authentication extension, +whether or not a certificate has been provided via B<-cert>. + =item B<[target]> Rather than providing B<-connect>, the target hostname and optional port may diff --git a/doc/man3/SSL_CONF_cmd.pod b/doc/man3/SSL_CONF_cmd.pod index 06b98bd416..27317e0652 100644 --- a/doc/man3/SSL_CONF_cmd.pod +++ b/doc/man3/SSL_CONF_cmd.pod @@ -435,6 +435,18 @@ occurs if the client does not present a certificate. Servers only. B requests a certificate from a client only on the initial connection: not when renegotiating. Servers only. +B configures the connection to support requests but does +not require a certificate from the client post-handshake. A certificate will +not be requested during the initial handshake. The server application must +provide a mechanism to request a certificate post-handshake. Servers only. +TLSv1.3 only. + +B configures the connection to support requests and +requires a certificate from the client post-handshake: an error occurs if the +client does not present a certificate. A certificate will not be requested +during the initial handshake. The server application must provide a mechanism +to request a certificate post-handshake. Servers only. TLSv1.3 only. + =item B, B A file or directory of certificates in PEM format whose names are used as the diff --git a/doc/man3/SSL_CTX_set_verify.pod b/doc/man3/SSL_CTX_set_verify.pod index 9e634dd91d..c9b4daf42a 100644 --- a/doc/man3/SSL_CTX_set_verify.pod +++ b/doc/man3/SSL_CTX_set_verify.pod @@ -5,7 +5,9 @@ SSL_get_ex_data_X509_STORE_CTX_idx, SSL_CTX_set_verify, SSL_set_verify, SSL_CTX_set_verify_depth, SSL_set_verify_depth, -SSL_verify_cb +SSL_verify_cb, +SSL_verify_client_post_handshake, +SSL_force_post_handshake_auth - set peer certificate verification parameters =head1 SYNOPSIS @@ -15,11 +17,14 @@ SSL_verify_cb typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx); void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb verify_callback); - void SSL_set_verify(SSL *s, int mode, SSL_verify_cb verify_callback); + void SSL_set_verify(SSL *ssl, int mode, SSL_verify_cb verify_callback); SSL_get_ex_data_X509_STORE_CTX_idx(void); void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); - void SSL_set_verify_depth(SSL *s, int depth); + void SSL_set_verify_depth(SSL *ssl, int depth); + + int SSL_verify_client_post_handshake(SSL *ssl); + void SSL_force_post_handshake_auth(SSL *ssl); =head1 DESCRIPTION @@ -43,6 +48,16 @@ verification that shall be allowed for B. SSL_set_verify_depth() sets the maximum B for the certificate chain verification that shall be allowed for B. +SSL_force_post_handshake_auth() forces the Post-Handshake Authentication +extension to be added to the ClientHello regardless of certificate configuration +at the time of the initial handshake, such that post-handshake authentication +can be requested by the server. A certificate callback will need to be set via +SSL_CTX_set_client_cert_cb() if no certificate is provided at initialization. + +SSL_verify_client_post_handshake() causes a Certificate Request message to be +sent by a server on the given B connection. The SSL_VERIFY_PEER flag must +be set, the SSL_VERIFY_POST_HANDSHAKE flag is optional. + =head1 NOTES The verification of certificates can be controlled by a set of logically @@ -69,7 +84,8 @@ fails, the TLS/SSL handshake is immediately terminated with an alert message containing the reason for the verification failure. The behaviour can be controlled by the additional -SSL_VERIFY_FAIL_IF_NO_PEER_CERT and SSL_VERIFY_CLIENT_ONCE flags. +SSL_VERIFY_FAIL_IF_NO_PEER_CERT, SSL_VERIFY_CLIENT_ONCE and +SSL_VERIFY_POST_HANDSHAKE flags. B the server certificate is verified. If the verification process fails, the TLS/SSL handshake is @@ -87,9 +103,22 @@ B ignored =item SSL_VERIFY_CLIENT_ONCE -B only request a client certificate on the initial TLS/SSL -handshake. Do not ask for a client certificate again in case of a -renegotiation. This flag must be used together with SSL_VERIFY_PEER. +B only request a client certificate once during the +connection. Do not ask for a client certificate again during +renegotiation or post-authentication if a certificate was requested +during the initial handshake. This flag must be used together with +SSL_VERIFY_PEER. + +B ignored + +=item SSL_VERIFY_POST_HANDSHAKE + +B the server will not send a client certificate request +during the initial handshake, but will send the request via +SSL_verify_client_post_handshake(). This allows the SSL_CTX or SSL +to be configured for post-handshake peer verification before the +handshake occurs. This flag must be used together with +SSL_VERIFY_PEER. TLSv1.3 only; no effect on pre-TLSv1.3 connections. B ignored @@ -154,6 +183,20 @@ Its return value is identical to B, so that any verification failure will lead to a termination of the TLS/SSL handshake with an alert message, if SSL_VERIFY_PEER is set. +After calling SSL_force_post_handshake_auth(), the client will need to add a +certificate to its configuration before it can successfully authenticate. This +must be called before SSL_connect(). + +SSL_verify_client_post_handshake() requires that verify flags have been +previously set, and that a client sent the post-handshake authentication +extension. When the client returns a certificate the verify callback will be +invoked. A write operation must take place for the Certificate Request to be +sent to the client, this can be done with SSL_do_handshake() or SSL_write_ex(). +Only one certificate request may be outstanding at any time. + +When post-handshake authentication occurs, a refreshed B +message is sent to the client. + =head1 BUGS In client mode, it is not checked whether the SSL_VERIFY_PEER flag @@ -165,6 +208,10 @@ required. The SSL*_set_verify*() functions do not provide diagnostic information. +The SSL_verify_client_post_handshake() function returns 1 if the request +succeeded, and 0 if the request failed. The error stack can be examined +to determine the failure reason. + =head1 EXAMPLES The following code sequence realizes an example B function @@ -288,8 +335,14 @@ L, L, L, L, +L, L +=head1 HISTORY + +The SSL_VERIFY_POST_HANDSHAKE option, and the SSL_verify_client_post_handshake() +and SSL_force_post_handshake_auth() functions were added in OpenSSL 1.1.1. + =head1 COPYRIGHT Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. -- cgit v1.2.3