Change Post Handshake auth so that it is opt-in
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)
diff --git a/apps/s_client.c b/apps/s_client.c
index 8f9ad9d..dcaa10c 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -595,7 +595,7 @@
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 @@
#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 isdtls = 0;
#endif
char *psksessf = NULL;
- int force_pha = 0;
+ int enable_pha = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
@@ -1492,8 +1492,8 @@
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 @@
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;
diff --git a/doc/man1/s_client.pod b/doc/man1/s_client.pod
index 80152e1..fa5cb0a 100644
--- a/doc/man1/s_client.pod
+++ b/doc/man1/s_client.pod
@@ -134,7 +134,7 @@
[B<-ctlogfile>]
[B<-keylogfile file>]
[B<-early_data file>]
-[B<-force_pha>]
+[B<-enable_pha>]
[B<target>]
=head1 DESCRIPTION
@@ -700,10 +700,10 @@
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]>
diff --git a/doc/man3/SSL_CTX_set_verify.pod b/doc/man3/SSL_CTX_set_verify.pod
index 7165547..173f006 100644
--- a/doc/man3/SSL_CTX_set_verify.pod
+++ b/doc/man3/SSL_CTX_set_verify.pod
@@ -7,7 +7,7 @@
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 @@
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 @@
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 @@
=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
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 155d651..b61119c 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1898,7 +1898,7 @@
__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);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index a486356..89570fb 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -5455,9 +5455,9 @@
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)
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 6d6404b..0d98110 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1391,7 +1391,7 @@
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;
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index 86d6189..2d5b60a 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -1193,23 +1193,8 @@
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)
diff --git a/test/handshake_helper.c b/test/handshake_helper.c
index c40a0e7..a5b8d80 100644
--- a/test/handshake_helper.c
+++ b/test/handshake_helper.c
@@ -726,8 +726,8 @@
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. */
diff --git a/test/recipes/70-test_tls13messages.t b/test/recipes/70-test_tls13messages.t
index 35f36b6..be6a2db 100644
--- a/test/recipes/70-test_tls13messages.t
+++ b/test/recipes/70-test_tls13messages.t
@@ -214,7 +214,7 @@
#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,
diff --git a/test/ssl-tests/26-tls13_client_auth.conf b/test/ssl-tests/26-tls13_client_auth.conf
index 55361dd..9c42391 100644
--- a/test/ssl-tests/26-tls13_client_auth.conf
+++ b/test/ssl-tests/26-tls13_client_auth.conf
@@ -299,6 +299,10 @@
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 @@
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 @@
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 @@
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 @@
ForcePHA = Yes
[13-client-auth-TLSv1.3-request-force-both-post-handshake-client-extra]
-ForcePHA = Yes
+EnablePHA = Yes
diff --git a/test/ssl-tests/26-tls13_client_auth.conf.in b/test/ssl-tests/26-tls13_client_auth.conf.in
index e53cda2..018dd82 100644
--- a/test/ssl-tests/26-tls13_client_auth.conf.in
+++ b/test/ssl-tests/26-tls13_client_auth.conf.in
@@ -176,6 +176,9 @@
"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 @@
"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 @@
"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 @@
client => {
"MinProtocol" => "TLSv1.3",
"MaxProtocol" => "TLSv1.3",
- extra => {
- "ForcePHA" => "Yes",
- },
+ extra => {
+ "EnablePHA" => "Yes",
+ },
},
test => {
"ExpectedResult" => "Success",
@@ -255,9 +264,9 @@
"MinProtocol" => "TLSv1.3",
"MaxProtocol" => "TLSv1.3",
"VerifyMode" => "RequestPostHandshake",
- extra => {
- "ForcePHA" => "Yes",
- },
+ extra => {
+ "ForcePHA" => "Yes",
+ },
},
client => {
"MinProtocol" => "TLSv1.3",
@@ -274,16 +283,16 @@
"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",
diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c
index cb4b860..7533385 100644
--- a/test/ssl_test_ctx.c
+++ b/test/ssl_test_ctx.c
@@ -629,9 +629,9 @@
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 @@
{ "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. */
diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h
index e26c207..86d227d 100644
--- a/test/ssl_test_ctx.h
+++ b/test/ssl_test_ctx.h
@@ -108,8 +108,8 @@
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 {
diff --git a/test/sslapitest.c b/test/sslapitest.c
index c65bf59..81761f2 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -1270,7 +1270,7 @@
|| !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 @@
&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 @@
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)))
diff --git a/util/libssl.num b/util/libssl.num
index 9b6d266..521637f 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -475,7 +475,7 @@
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: