The branch OpenSSL_1_1_1-stable has been updated via b743b16113ca0e30c383191c804de37dbfc4f12e (commit) via df1fd3c986f5a58b6dc87d2c4bb565a8f1e688fa (commit) via 5d88a9c62c81e38918becae96a842986e2e0940e (commit) via 1ab7b9991ba00a1423ec6c5898a70e11d1337cfb (commit) from a812f8fc8f3c9ba30e5ecd2c168cca0613f15dcd (commit)
- Log ----------------------------------------------------------------- commit b743b16113ca0e30c383191c804de37dbfc4f12e Author: Benjamin Kaduk <bka...@akamai.com> Date: Mon Mar 29 23:05:22 2021 -0700 Update expected results for tls13kexmodes tests One of the scenarios constructed in these tests was erroneously producing successful handshakes until the previous commits, but should have been failing. Update our expected behavior to match the specification requirements, and adjust the commentary slightly for a test case relevant for the other preceding commit. Reviewed-by: Tomas Mraz <to...@openssl.org> (cherry picked from commit 80c25611abd7067815943187f36f5e1879201678) (Merged from https://github.com/openssl/openssl/pull/15255) commit df1fd3c986f5a58b6dc87d2c4bb565a8f1e688fa Author: Benjamin Kaduk <bka...@akamai.com> Date: Mon Mar 29 21:27:49 2021 -0700 Don't send key_share for PSK-only key exchange TLS 1.3 allows for the "psk_ke" and "psk_dhe_ke" key-exchange modes. Only the latter mode introduces a new ephemeral (Diffie-Hellman) key exchange, with the PSK being the only key material used in the former case. It's a compliance requirement of RFC 8446 that the server MUST NOT send a KeyShareEntry when using the "psk_ke" mode, but prior to this commit we would send a key-share based solely on whether the client sent one. This bug goes unnoticed in our internal test suite since openssl communicating with openssl can never negotiate the PSK-only key-exchange mode. However, we should still be compliant with the spec, so check whether the DHE mode was offered and don't send a key-share if it wasn't. Reviewed-by: Tomas Mraz <to...@openssl.org> (cherry picked from commit e776858bce32d473bd7a69c616ad7f6c2f979dfc) (Merged from https://github.com/openssl/openssl/pull/15255) commit 5d88a9c62c81e38918becae96a842986e2e0940e Author: Benjamin Kaduk <bka...@akamai.com> Date: Mon Mar 29 23:08:10 2021 -0700 make update Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15255) commit 1ab7b9991ba00a1423ec6c5898a70e11d1337cfb Author: Benjamin Kaduk <bka...@akamai.com> Date: Mon Mar 29 23:03:49 2021 -0700 Improve RFC 8446 PSK key exchange mode compliance It's a MUST-level requirement that if the client sends a pre_shared_key extension not accompanied by a psk_key_exchange_modes extension, the server must abort the handshake. Prior to this commit the server would continue on. Reviewed-by: Tomas Mraz <to...@openssl.org> (cherry picked from commit efe0f315354b020213097885c79ce856a2f5ac68) (Merged from https://github.com/openssl/openssl/pull/15255) ----------------------------------------------------------------------- Summary of changes: crypto/err/openssl.txt | 2 ++ include/openssl/sslerr.h | 2 ++ ssl/ssl_err.c | 3 +++ ssl/statem/extensions.c | 19 ++++++++++++++++++- ssl/statem/extensions_srvr.c | 7 +++++++ test/recipes/70-test_tls13kexmodes.t | 12 +++++------- 6 files changed, 37 insertions(+), 8 deletions(-) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index e0e60ffa38..017a9a6652 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -1160,6 +1160,7 @@ SSL_F_FINAL_EC_PT_FORMATS:485:final_ec_pt_formats SSL_F_FINAL_EMS:486:final_ems SSL_F_FINAL_KEY_SHARE:503:final_key_share SSL_F_FINAL_MAXFRAGMENTLEN:557:final_maxfragmentlen +SSL_F_FINAL_PSK:639:final_psk SSL_F_FINAL_RENEGOTIATE:483:final_renegotiate SSL_F_FINAL_SERVER_NAME:558:final_server_name SSL_F_FINAL_SIG_ALGS:497:final_sig_algs @@ -2741,6 +2742,7 @@ SSL_R_MISSING_DSA_SIGNING_CERT:165:missing dsa signing cert SSL_R_MISSING_ECDSA_SIGNING_CERT:381:missing ecdsa signing cert SSL_R_MISSING_FATAL:256:missing fatal SSL_R_MISSING_PARAMETERS:290:missing parameters +SSL_R_MISSING_PSK_KEX_MODES_EXTENSION:310:missing psk kex modes extension SSL_R_MISSING_RSA_CERTIFICATE:168:missing rsa certificate SSL_R_MISSING_RSA_ENCRYPTING_CERT:169:missing rsa encrypting cert SSL_R_MISSING_RSA_SIGNING_CERT:170:missing rsa signing cert diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h index 9060fd1b75..701d61c6e9 100644 --- a/include/openssl/sslerr.h +++ b/include/openssl/sslerr.h @@ -70,6 +70,7 @@ int ERR_load_SSL_strings(void); # define SSL_F_FINAL_EMS 486 # define SSL_F_FINAL_KEY_SHARE 503 # define SSL_F_FINAL_MAXFRAGMENTLEN 557 +# define SSL_F_FINAL_PSK 639 # define SSL_F_FINAL_RENEGOTIATE 483 # define SSL_F_FINAL_SERVER_NAME 558 # define SSL_F_FINAL_SIG_ALGS 497 @@ -592,6 +593,7 @@ int ERR_load_SSL_strings(void); # define SSL_R_MISSING_ECDSA_SIGNING_CERT 381 # define SSL_R_MISSING_FATAL 256 # define SSL_R_MISSING_PARAMETERS 290 +# define SSL_R_MISSING_PSK_KEX_MODES_EXTENSION 310 # define SSL_R_MISSING_RSA_CERTIFICATE 168 # define SSL_R_MISSING_RSA_ENCRYPTING_CERT 169 # define SSL_R_MISSING_RSA_SIGNING_CERT 170 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index d0c69821b5..324f2ccbb0 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -85,6 +85,7 @@ static const ERR_STRING_DATA SSL_str_functs[] = { {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_KEY_SHARE, 0), "final_key_share"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_MAXFRAGMENTLEN, 0), "final_maxfragmentlen"}, + {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_PSK, 0), "final_psk"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_RENEGOTIATE, 0), "final_renegotiate"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SERVER_NAME, 0), "final_server_name"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_FINAL_SIG_ALGS, 0), "final_sig_algs"}, @@ -948,6 +949,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = { "missing ecdsa signing cert"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_FATAL), "missing fatal"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_PARAMETERS), "missing parameters"}, + {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_PSK_KEX_MODES_EXTENSION), + "missing psk kex modes extension"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_CERTIFICATE), "missing rsa certificate"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_RSA_ENCRYPTING_CERT), diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index e1a3b1db67..07803537ba 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -56,6 +56,7 @@ static int final_sig_algs(SSL *s, unsigned int context, int sent); static int final_early_data(SSL *s, unsigned int context, int sent); static int final_maxfragmentlen(SSL *s, unsigned int context, int sent); static int init_post_handshake_auth(SSL *s, unsigned int context); +static int final_psk(SSL *s, unsigned int context, int sent); /* Structure to define a built-in extension */ typedef struct extensions_definition_st { @@ -389,7 +390,7 @@ static const EXTENSION_DEFINITION ext_defs[] = { SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY, NULL, tls_parse_ctos_psk, tls_parse_stoc_psk, tls_construct_stoc_psk, - tls_construct_ctos_psk, NULL + tls_construct_ctos_psk, final_psk } }; @@ -1718,3 +1719,19 @@ static int init_post_handshake_auth(SSL *s, unsigned int context) return 1; } + +/* + * If clients offer "pre_shared_key" without a "psk_key_exchange_modes" + * extension, servers MUST abort the handshake. + */ +static int final_psk(SSL *s, unsigned int context, int sent) +{ + if (s->server && sent && s->clienthello != NULL + && !s->clienthello->pre_proc_exts[TLSEXT_IDX_psk_kex_modes].present) { + SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_PSK, + SSL_R_MISSING_PSK_KEX_MODES_EXTENSION); + return 0; + } + + return 1; +} diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index 3c7395c0eb..90e8bce19b 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -1714,6 +1714,13 @@ EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt, } return EXT_RETURN_NOT_SENT; } + if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) { + /* + * PSK ('hit') and explicitly not doing DHE (if the client sent the + * DHE option we always take it); don't send key share. + */ + return EXT_RETURN_NOT_SENT; + } if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) || !WPACKET_start_sub_packet_u16(pkt) diff --git a/test/recipes/70-test_tls13kexmodes.t b/test/recipes/70-test_tls13kexmodes.t index 98989b4703..e8ab25f190 100644 --- a/test/recipes/70-test_tls13kexmodes.t +++ b/test/recipes/70-test_tls13kexmodes.t @@ -195,17 +195,14 @@ $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; plan tests => 11; ok(TLSProxy::Message->success(), "Initial connection"); -#Test 2: Attempt a resume with no kex modes extension. Should not resume +#Test 2: Attempt a resume with no kex modes extension. Should fail (server +# MUST abort handshake with pre_shared key and no psk_kex_modes) $proxy->clear(); $proxy->clientflags("-sess_in ".$session); my $testtype = DELETE_EXTENSION; $proxy->filter(\&modify_kex_modes_filter); $proxy->start(); -checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE, - checkhandshake::DEFAULT_EXTENSIONS - | checkhandshake::KEY_SHARE_SRV_EXTENSION - | checkhandshake::PSK_CLI_EXTENSION, - "Resume with no kex modes"); +ok(TLSProxy::Message->fail(), "Resume with no kex modes"); #Test 3: Attempt a resume with empty kex modes extension. Should fail (empty # extension is invalid) @@ -243,6 +240,7 @@ checkhandshake($proxy, checkhandshake::RESUME_HANDSHAKE, "Resume with non-dhe kex mode"); #Test 6: Attempt a resume with only unrecognised kex modes. Should not resume +# but rather fall back to full handshake $proxy->clear(); $proxy->clientflags("-sess_in ".$session); $testtype = UNKNOWN_KEX_MODES; @@ -252,7 +250,7 @@ checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE, | checkhandshake::PSK_KEX_MODES_EXTENSION | checkhandshake::KEY_SHARE_SRV_EXTENSION | checkhandshake::PSK_CLI_EXTENSION, - "Resume with empty kex modes"); + "Resume with unrecognized kex mode"); #Test 7: Attempt a resume with both non-dhe and dhe kex mode. Should resume with # a key_share