Change Post Handshake auth so that it is opt-in
authorMatt Caswell <matt@openssl.org>
Mon, 13 Aug 2018 14:23:27 +0000 (15:23 +0100)
committerMatt Caswell <matt@openssl.org>
Mon, 20 Aug 2018 14:14:01 +0000 (15:14 +0100)
Having post handshake auth automatically switched on breaks some
applications written for TLSv1.2. This changes things so that an explicit
function call is required for a client to indicate support for
post-handshake auth.

Fixes #6933.

Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6938)

15 files changed:
apps/s_client.c
doc/man1/s_client.pod
doc/man3/SSL_CTX_set_verify.pod
include/openssl/ssl.h
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/statem/extensions_clnt.c
test/handshake_helper.c
test/recipes/70-test_tls13messages.t
test/ssl-tests/26-tls13_client_auth.conf
test/ssl-tests/26-tls13_client_auth.conf.in
test/ssl_test_ctx.c
test/ssl_test_ctx.h
test/sslapitest.c
util/libssl.num

index 8f9ad9ddcfc35e7998f9c850e5d7daf3f2f5cd47..dcaa10cf44ebae4de0d828dcd4508692ad26526a 100644 (file)
@@ -595,7 +595,7 @@ typedef enum OPTION_choice {
     OPT_CT, OPT_NOCT, OPT_CTLOG_FILE,
 #endif
     OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
-    OPT_FORCE_PHA,
+    OPT_ENABLE_PHA,
     OPT_R_ENUM
 } OPTION_CHOICE;
 
@@ -786,7 +786,7 @@ const OPTIONS s_client_options[] = {
 #endif
     {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
     {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"},
-    {"force_pha", OPT_FORCE_PHA, '-', "Force-enable post-handshake-authentication"},
+    {"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"},
     {NULL, OPT_EOF, 0x00, NULL}
 };
 
@@ -975,7 +975,7 @@ int s_client_main(int argc, char **argv)
     int isdtls = 0;
 #endif
     char *psksessf = NULL;
-    int force_pha = 0;
+    int enable_pha = 0;
 
     FD_ZERO(&readfds);
     FD_ZERO(&writefds);
@@ -1492,8 +1492,8 @@ int s_client_main(int argc, char **argv)
         case OPT_EARLY_DATA:
             early_data_file = opt_arg();
             break;
-        case OPT_FORCE_PHA:
-            force_pha = 1;
+        case OPT_ENABLE_PHA:
+            enable_pha = 1;
             break;
         }
     }
@@ -1944,8 +1944,8 @@ int s_client_main(int argc, char **argv)
     if (con == NULL)
         goto end;
 
-    if (force_pha)
-        SSL_force_post_handshake_auth(con);
+    if (enable_pha)
+        SSL_set_post_handshake_auth(con, 1);
 
     if (sess_in != NULL) {
         SSL_SESSION *sess;
index 80152e1ba4c33a2615d264ab14a9d01a975dd711..fa5cb0a92da1c80d48c444446fd8af16c9730fa9 100644 (file)
@@ -134,7 +134,7 @@ B<openssl> B<s_client>
 [B<-ctlogfile>]
 [B<-keylogfile file>]
 [B<-early_data file>]
-[B<-force_pha>]
+[B<-enable_pha>]
 [B<target>]
 
 =head1 DESCRIPTION
@@ -700,10 +700,10 @@ 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>
+=item B<-enable_pha>
 
-For TLSv1.3 only, always send the Post-Handshake Authentication extension,
-whether or not a certificate has been provided via B<-cert>.
+For TLSv1.3 only, send the Post-Handshake Authentication extension. This will
+happen whether or not a certificate has been provided via B<-cert>.
 
 =item B<[target]>
 
index 716554793311efb9fd92b0be8ca5bcb0614d82a3..173f006eb65a4b0c2f3deb32930bcce9ba1c2598 100644 (file)
@@ -7,7 +7,7 @@ SSL_CTX_set_verify, SSL_set_verify,
 SSL_CTX_set_verify_depth, SSL_set_verify_depth,
 SSL_verify_cb,
 SSL_verify_client_post_handshake,
-SSL_force_post_handshake_auth
+SSL_set_post_handshake_auth
 - set peer certificate verification parameters
 
 =head1 SYNOPSIS
@@ -24,7 +24,7 @@ SSL_force_post_handshake_auth
  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);
+ void SSL_set_post_handshake_auth(SSL *ssl, int val);
 
 =head1 DESCRIPTION
 
@@ -48,11 +48,12 @@ verification that shall be allowed for B<ctx>.
 SSL_set_verify_depth() sets the maximum B<depth> for the certificate chain
 verification that shall be allowed for B<ssl>.
 
-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_set_post_handshake_auth() enables the Post-Handshake Authentication
+extension to be added to the ClientHello such that post-handshake authentication
+can be requested by the server. If B<val> is 0 then the extension is not sent,
+otherwise it is. By default the extension is not sent. 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 CertificateRequest message to be
 sent by a server on the given B<ssl> connection. The SSL_VERIFY_PEER flag must
@@ -341,7 +342,7 @@ L<CRYPTO_get_ex_new_index(3)>
 =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.
+and SSL_set_post_handshake_auth() functions were added in OpenSSL 1.1.1.
 
 =head1 COPYRIGHT
 
index 155d6515e12459a8899fdc2cf625511cbea7b539..b61119cc18dbf6db0b6b4515930df8e0f3156f69 100644 (file)
@@ -1898,7 +1898,7 @@ int SSL_renegotiate_abbreviated(SSL *s);
 __owur int SSL_renegotiate_pending(SSL *s);
 int SSL_shutdown(SSL *s);
 __owur int SSL_verify_client_post_handshake(SSL *s);
-void SSL_force_post_handshake_auth(SSL *s);
+void SSL_set_post_handshake_auth(SSL *s, int val);
 
 __owur const SSL_METHOD *SSL_CTX_get_ssl_method(SSL_CTX *ctx);
 __owur const SSL_METHOD *SSL_get_ssl_method(SSL *s);
index a486356c2ae6cdd3bc2ef8ffeabbe5461ca3a6bf..89570fbe3adf21506b030961593c9a2794588c28 100644 (file)
@@ -5455,9 +5455,9 @@ int SSL_stateless(SSL *s)
     return -1;
 }
 
-void SSL_force_post_handshake_auth(SSL *ssl)
+void SSL_set_post_handshake_auth(SSL *ssl, int val)
 {
-    ssl->pha_forced = 1;
+    ssl->pha_enabled = val;
 }
 
 int SSL_verify_client_post_handshake(SSL *ssl)
index 6d6404ba3d5bd16021c0f4535e1abc2f59c834af..0d981104800a57105935c1adf5a4cae591fd0607 100644 (file)
@@ -1391,7 +1391,7 @@ struct ssl_st {
     int key_update;
     /* Post-handshake authentication state */
     SSL_PHA_STATE post_handshake_auth;
-    int pha_forced;
+    int pha_enabled;
     uint8_t* pha_context;
     size_t pha_context_len;
     int certreqs_sent;
index 86d6189ea1eac0bf4aabd5dc0e850864f24ac918..2d5b60a737c9dc3ca8f076f2d9f209f175647533 100644 (file)
@@ -1193,23 +1193,8 @@ EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
                                                   X509 *x, size_t chainidx)
 {
 #ifndef OPENSSL_NO_TLS1_3
-    if (!s->pha_forced) {
-        int i, n = 0;
-
-        /* check for cert, if present, we can do post-handshake auth */
-        if (s->cert == NULL)
-            return EXT_RETURN_NOT_SENT;
-
-        for (i = 0; i < SSL_PKEY_NUM; i++) {
-            if (s->cert->pkeys[i].x509 != NULL
-                    && s->cert->pkeys[i].privatekey != NULL)
-                n++;
-        }
-
-        /* no identity certificates, so no extension */
-        if (n == 0)
-            return EXT_RETURN_NOT_SENT;
-    }
+    if (!s->pha_enabled)
+        return EXT_RETURN_NOT_SENT;
 
     /* construct extension - 0 length, no contents */
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth)
index c40a0e7c92638e96a4722782254b6399566ec94c..a5b8d8007adb7e5ea0725811d13d00cd84ddd047 100644 (file)
@@ -726,8 +726,8 @@ static void configure_handshake_ssl(SSL *server, SSL *client,
     if (extra->client.servername != SSL_TEST_SERVERNAME_NONE)
         SSL_set_tlsext_host_name(client,
                                  ssl_servername_name(extra->client.servername));
-    if (extra->client.force_pha)
-        SSL_force_post_handshake_auth(client);
+    if (extra->client.enable_pha)
+        SSL_set_post_handshake_auth(client, 1);
 }
 
 /* The status for each connection phase. */
index 35f36b6c33255f099060dc43f48247a7fe27bb43..be6a2db5d68b872ae1e0196b1623431a064f5531 100644 (file)
@@ -214,7 +214,7 @@ SKIP: {
 
 #Test 6: A client auth handshake
 $proxy->clear();
-$proxy->clientflags("-cert ".srctop_file("apps", "server.pem"));
+$proxy->clientflags("-enable_pha -cert ".srctop_file("apps", "server.pem"));
 $proxy->serverflags("-Verify 5");
 $proxy->start();
 checkhandshake($proxy, checkhandshake::CLIENT_AUTH_HANDSHAKE,
index 55361dde73dbf708426a15854604f0535d8572ec..9c42391906a7888ae7ad45b28e34868ec574c55b 100644 (file)
@@ -299,6 +299,10 @@ ExpectedClientSignHash = SHA256
 ExpectedClientSignType = RSA-PSS
 ExpectedResult = Success
 HandshakeMode = PostHandshakeAuth
+client = 8-client-auth-TLSv1.3-require-post-handshake-client-extra
+
+[8-client-auth-TLSv1.3-require-post-handshake-client-extra]
+EnablePHA = Yes
 
 
 # ===========================================================
@@ -337,6 +341,10 @@ ExpectedClientSignHash = SHA256
 ExpectedClientSignType = RSA-PSS
 ExpectedResult = Success
 HandshakeMode = PostHandshakeAuth
+client = 9-client-auth-TLSv1.3-require-non-empty-names-post-handshake-client-extra
+
+[9-client-auth-TLSv1.3-require-non-empty-names-post-handshake-client-extra]
+EnablePHA = Yes
 
 
 # ===========================================================
@@ -369,6 +377,10 @@ VerifyMode = Peer
 ExpectedResult = ServerFail
 ExpectedServerAlert = UnknownCA
 HandshakeMode = PostHandshakeAuth
+client = 10-client-auth-TLSv1.3-noroot-post-handshake-client-extra
+
+[10-client-auth-TLSv1.3-noroot-post-handshake-client-extra]
+EnablePHA = Yes
 
 
 # ===========================================================
@@ -401,7 +413,7 @@ HandshakeMode = PostHandshakeAuth
 client = 11-client-auth-TLSv1.3-request-force-client-post-handshake-client-extra
 
 [11-client-auth-TLSv1.3-request-force-client-post-handshake-client-extra]
-ForcePHA = Yes
+EnablePHA = Yes
 
 
 # ===========================================================
@@ -471,6 +483,6 @@ client = 13-client-auth-TLSv1.3-request-force-both-post-handshake-client-extra
 ForcePHA = Yes
 
 [13-client-auth-TLSv1.3-request-force-both-post-handshake-client-extra]
-ForcePHA = Yes
+EnablePHA = Yes
 
 
index e53cda2304e4fb80212eff9a0c8ad2dbcffcbfee..018dd825be0cc54b3e4a62dc4a7d21a02f30b6ae 100644 (file)
@@ -176,6 +176,9 @@ our @tests = (
             "MaxProtocol" => "TLSv1.3",
             "Certificate" => test_pem("ee-client-chain.pem"),
             "PrivateKey" => test_pem("ee-key.pem"),
+            extra => {
+                "EnablePHA" => "Yes",
+            },
         },
         test => {
             "ExpectedResult" => "Success",
@@ -201,6 +204,9 @@ our @tests = (
             "MaxProtocol" => "TLSv1.3",
             "Certificate" => test_pem("ee-client-chain.pem"),
             "PrivateKey" => test_pem("ee-key.pem"),
+            extra => {
+                "EnablePHA" => "Yes",
+            },
         },
         test => {
             "ExpectedResult" => "Success",
@@ -223,6 +229,9 @@ our @tests = (
             "MaxProtocol" => "TLSv1.3",
             "Certificate" => test_pem("ee-client-chain.pem"),
             "PrivateKey" => test_pem("ee-key.pem"),
+            extra => {
+                "EnablePHA" => "Yes",
+            },
         },
         test => {
             "ExpectedResult" => "ServerFail",
@@ -240,9 +249,9 @@ our @tests = (
         client => {
             "MinProtocol" => "TLSv1.3",
             "MaxProtocol" => "TLSv1.3",
-           extra => {
-               "ForcePHA" => "Yes",
-           },
+            extra => {
+                "EnablePHA" => "Yes",
+            },
         },
         test => {
             "ExpectedResult" => "Success",
@@ -255,9 +264,9 @@ our @tests = (
             "MinProtocol" => "TLSv1.3",
             "MaxProtocol" => "TLSv1.3",
             "VerifyMode" => "RequestPostHandshake",
-           extra => {
-               "ForcePHA" => "Yes",
-           },
+            extra => {
+                "ForcePHA" => "Yes",
+            },
         },
         client => {
             "MinProtocol" => "TLSv1.3",
@@ -274,16 +283,16 @@ our @tests = (
             "MinProtocol" => "TLSv1.3",
             "MaxProtocol" => "TLSv1.3",
             "VerifyMode" => "RequestPostHandshake",
-           extra => {
-               "ForcePHA" => "Yes",
-           },
+            extra => {
+                "ForcePHA" => "Yes",
+            },
         },
         client => {
             "MinProtocol" => "TLSv1.3",
             "MaxProtocol" => "TLSv1.3",
-           extra => {
-               "ForcePHA" => "Yes",
-           },
+            extra => {
+                "EnablePHA" => "Yes",
+            },
         },
         test => {
             "ExpectedResult" => "Success",
index cb4b8606e2accf44404a32b131f1bf09132d79fe..753338530daaa00286f7af3a6a06cc5910c6c676 100644 (file)
@@ -629,9 +629,9 @@ __owur static int parse_expected_client_ca_names(SSL_TEST_CTX *test_ctx,
 
 IMPLEMENT_SSL_TEST_STRING_OPTION(SSL_TEST_CTX, test, expected_cipher)
 
-/* Client and Server ForcePHA */
+/* Client and Server PHA */
 
-IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CLIENT_CONF, client, force_pha)
+IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CLIENT_CONF, client, enable_pha)
 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, force_pha)
 
 /* Known test options and their corresponding parse methods. */
@@ -689,7 +689,7 @@ static const ssl_test_client_option ssl_test_client_options[] = {
     { "SRPUser", &parse_client_srp_user },
     { "SRPPassword", &parse_client_srp_password },
     { "MaxFragmentLenExt", &parse_max_fragment_len_mode },
-    { "ForcePHA", &parse_client_force_pha },
+    { "EnablePHA", &parse_client_enable_pha },
 };
 
 /* Nested server options. */
index e26c207657b878109e28c4dce2dbf2d0da348abd..86d227d86550cf0764838b9899d655147c8706af 100644 (file)
@@ -108,8 +108,8 @@ typedef struct {
     char *reneg_ciphers;
     char *srp_user;
     char *srp_password;
-    /* Forced PHA */
-    int force_pha;
+    /* PHA enabled */
+    int enable_pha;
 } SSL_TEST_CLIENT_CONF;
 
 typedef struct {
index c65bf59ffd070bff227e9d83ccdce34be018ff81..81761f2f654e3163585520789ac28ca1e00f654c 100644 (file)
@@ -1270,7 +1270,7 @@ static int check_resumption(int idx, SSL_CTX *sctx, SSL_CTX *cctx, int succ)
                 || !TEST_true(SSL_set_session(clientssl, sesscache[i])))
             goto end;
 
-        SSL_force_post_handshake_auth(clientssl);
+        SSL_set_post_handshake_auth(clientssl, 1);
 
         if (!TEST_true(create_ssl_connection(serverssl, clientssl,
                                                     SSL_ERROR_NONE)))
@@ -1377,7 +1377,7 @@ static int test_tickets(int stateful, int idx)
                                           &clientssl, NULL, NULL)))
         goto end;
 
-    SSL_force_post_handshake_auth(clientssl);
+    SSL_set_post_handshake_auth(clientssl, 1);
 
     if (!TEST_true(create_ssl_connection(serverssl, clientssl,
                                                 SSL_ERROR_NONE))
@@ -4336,7 +4336,7 @@ static int test_pha_key_update(void)
                                       NULL, NULL)))
         goto end;
 
-    SSL_force_post_handshake_auth(clientssl);
+    SSL_set_post_handshake_auth(clientssl, 1);
 
     if (!TEST_true(create_ssl_connection(serverssl, clientssl,
                                          SSL_ERROR_NONE)))
index 9b6d2661447e96c34debad8a83a38df6cb28ae2e..521637f098428d5584884e2ffa340a1f111bcc9b 100644 (file)
@@ -475,7 +475,7 @@ SSL_set_tlsext_max_fragment_length      475 1_1_1   EXIST::FUNCTION:
 SSL_SESSION_get_max_fragment_length     476    1_1_1   EXIST::FUNCTION:
 SSL_stateless                           477    1_1_1   EXIST::FUNCTION:
 SSL_verify_client_post_handshake        478    1_1_1   EXIST::FUNCTION:
-SSL_force_post_handshake_auth           479    1_1_1   EXIST::FUNCTION:
+SSL_set_post_handshake_auth             479    1_1_1   EXIST::FUNCTION:
 SSL_export_keying_material_early        480    1_1_1   EXIST::FUNCTION:
 SSL_CTX_use_cert_and_key                481    1_1_1   EXIST::FUNCTION:
 SSL_use_cert_and_key                    482    1_1_1   EXIST::FUNCTION: