The branch master has been updated via 532f95783e2bff4d7f4e8086297ed8e0b25561f7 (commit) via 4a192c77b7bf794a9283a8e7fb4f7bee0d7bff56 (commit) via f3d40db1b947f546541b815a0363de3120c16506 (commit) via e73c6eaeff82615d20845692c5c72ba9dfa895f5 (commit) from a7fb4fa1708c65c0932133dca64a53d0237312e3 (commit)
- Log ----------------------------------------------------------------- commit 532f95783e2bff4d7f4e8086297ed8e0b25561f7 Author: Matt Caswell <m...@openssl.org> Date: Thu Mar 8 13:45:22 2018 +0000 Test the new PSK behaviour Reviewed-by: Rich Salz <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5554) commit 4a192c77b7bf794a9283a8e7fb4f7bee0d7bff56 Author: Matt Caswell <m...@openssl.org> Date: Thu Mar 8 08:20:23 2018 +0000 Update documentation for the new PSK behaviour Reviewed-by: Rich Salz <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5554) commit f3d40db1b947f546541b815a0363de3120c16506 Author: Matt Caswell <m...@openssl.org> Date: Tue Mar 6 16:41:51 2018 +0000 Fallback on old style PSK callbacks if the new style ones aren't present Reviewed-by: Rich Salz <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5554) commit e73c6eaeff82615d20845692c5c72ba9dfa895f5 Author: Matt Caswell <m...@openssl.org> Date: Tue Mar 6 14:12:10 2018 +0000 Tolerate TLSv1.3 PSKs that are a different size to the hash size We also default to SHA256 as per the spec if we do not have an explicit digest defined. Reviewed-by: Rich Salz <rs...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5554) ----------------------------------------------------------------------- Summary of changes: apps/s_client.c | 16 +-- apps/s_server.c | 10 +- doc/man3/SSL_CTX_set_psk_client_callback.pod | 66 +++++----- doc/man3/SSL_CTX_use_psk_identity_hint.pod | 70 ++++++----- ssl/statem/extensions.c | 12 +- ssl/statem/extensions_clnt.c | 53 +++++++++ ssl/statem/extensions_srvr.c | 56 ++++++++- test/sslapitest.c | 172 ++++++++++++++++++++++++--- 8 files changed, 351 insertions(+), 104 deletions(-) diff --git a/apps/s_client.c b/apps/s_client.c index a319d21..1ed853d 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -197,19 +197,13 @@ static int psk_use_session_cb(SSL *s, const EVP_MD *md, return 0; } - if (key_len == EVP_MD_size(EVP_sha256())) - cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); - else if (key_len == EVP_MD_size(EVP_sha384())) - cipher = SSL_CIPHER_find(s, tls13_aes256gcmsha384_id); - + /* We default to SHA-256 */ + cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); if (cipher == NULL) { - /* Doesn't look like a suitable TLSv1.3 key. Ignore it */ - OPENSSL_free(key); - *id = NULL; - *idlen = 0; - *sess = NULL; - return 1; + BIO_printf(bio_err, "Error finding suitable ciphersuite\n"); + return 0; } + usesess = SSL_SESSION_new(); if (usesess == NULL || !SSL_SESSION_set1_master_key(usesess, key, key_len) diff --git a/apps/s_server.c b/apps/s_server.c index ff9ee5a..bc1d1e5 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -208,14 +208,10 @@ static int psk_find_session_cb(SSL *ssl, const unsigned char *identity, return 0; } - if (key_len == EVP_MD_size(EVP_sha256())) - cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id); - else if (key_len == EVP_MD_size(EVP_sha384())) - cipher = SSL_CIPHER_find(ssl, tls13_aes256gcmsha384_id); - + /* We default to SHA256 */ + cipher = SSL_CIPHER_find(ssl, tls13_aes128gcmsha256_id); if (cipher == NULL) { - /* Doesn't look like a suitable TLSv1.3 key. Ignore it */ - OPENSSL_free(key); + BIO_printf(bio_err, "Error finding suitable ciphersuite\n"); return 0; } diff --git a/doc/man3/SSL_CTX_set_psk_client_callback.pod b/doc/man3/SSL_CTX_set_psk_client_callback.pod index e771072..5350d79 100644 --- a/doc/man3/SSL_CTX_set_psk_client_callback.pod +++ b/doc/man3/SSL_CTX_set_psk_client_callback.pod @@ -14,48 +14,33 @@ SSL_set_psk_use_session_callback #include <openssl/ssl.h> - typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl, - const char *hint, - char *identity, - unsigned int max_identity_len, - unsigned char *psk, - unsigned int max_psk_len); typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md, const unsigned char **id, size_t *idlen, SSL_SESSION **sess); - void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb); - void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb); void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx, SSL_psk_use_session_cb_func cb); void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb); -=head1 DESCRIPTION -TLSv1.3 Pre-Shared Keys (PSKs) and PSKs for TLSv1.2 and below are not -compatible. + typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl, + const char *hint, + char *identity, + unsigned int max_identity_len, + unsigned char *psk, + unsigned int max_psk_len); -A client application wishing to use PSK ciphersuites for TLSv1.2 and below must -provide a callback function. This function will be called when the client is -sending the ClientKeyExchange message to the server. + void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb); + void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb); -The purpose of the callback function is to select the PSK identity and -the pre-shared key to use during the connection setup phase. -The callback is set using functions SSL_CTX_set_psk_client_callback() -or SSL_set_psk_client_callback(). The callback function is given the -connection in parameter B<ssl>, a B<NULL>-terminated PSK identity hint -sent by the server in parameter B<hint>, a buffer B<identity> of -length B<max_identity_len> bytes where the resulting -B<NULL>-terminated identity is to be stored, and a buffer B<psk> of -length B<max_psk_len> bytes where the resulting pre-shared key is to -be stored. +=head1 DESCRIPTION -A client application wishing to use TLSv1.3 PSKs must set a different callback -using either SSL_CTX_set_psk_use_session_callback() or -SSL_set_psk_use_session_callback() as appropriate. +A client application wishing to use TLSv1.3 PSKs should use either +SSL_CTX_set_psk_use_session_callback() or SSL_set_psk_use_session_callback() as +appropriate. These functions cannot be used for TLSv1.2 and below PSKs. The callback function is given a pointer to the SSL connection in B<ssl>. @@ -113,6 +98,33 @@ case no PSK will be sent to the server but the handshake will continue. To do this the callback should return successfully and ensure that B<*sess> is NULL. The contents of B<*id> and B<*idlen> will be ignored. +A client application wishing to use PSK ciphersuites for TLSv1.2 and below must +provide a different callback function. This function will be called when the +client is sending the ClientKeyExchange message to the server. + +The purpose of the callback function is to select the PSK identity and +the pre-shared key to use during the connection setup phase. + +The callback is set using functions SSL_CTX_set_psk_client_callback() +or SSL_set_psk_client_callback(). The callback function is given the +connection in parameter B<ssl>, a B<NULL>-terminated PSK identity hint +sent by the server in parameter B<hint>, a buffer B<identity> of +length B<max_identity_len> bytes where the resulting +B<NUL>-terminated identity is to be stored, and a buffer B<psk> of +length B<max_psk_len> bytes where the resulting pre-shared key is to +be stored. + +The callback for use in TLSv1.2 will also work in TLSv1.3 although it is +recommended to use SSL_CTX_set_psk_use_session_callback() +or SSL_set_psk_use_session_callback() for this purpose instead. If TLSv1.3 has +been negotiated then OpenSSL will first check to see if a callback has been set +via SSL_CTX_set_psk_use_session_callback() or SSL_set_psk_use_session_callback() +and it will use that in preference. If no such callback is present then it will +check to see if a callback has been set via SSL_CTX_set_psk_client_callback() or +SSL_set_psk_client_callback() and use that. In this case the B<hint> value will +always be NULL and the handshake digest will default to SHA-256 for any returned +PSK. + =head1 NOTES Note that parameter B<hint> given to the callback may be B<NULL>. diff --git a/doc/man3/SSL_CTX_use_psk_identity_hint.pod b/doc/man3/SSL_CTX_use_psk_identity_hint.pod index d41c0cc..2f4773d 100644 --- a/doc/man3/SSL_CTX_use_psk_identity_hint.pod +++ b/doc/man3/SSL_CTX_use_psk_identity_hint.pod @@ -16,30 +16,44 @@ SSL_set_psk_find_session_callback #include <openssl/ssl.h> - typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl, - const char *identity, - unsigned char *psk, - unsigned int max_psk_len); - typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl, const unsigned char *identity, size_t identity_len, SSL_SESSION **sess); + + void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx, + SSL_psk_find_session_cb_func cb); + void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb); + + typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl, + const char *identity, + unsigned char *psk, + unsigned int max_psk_len); + int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint); int SSL_use_psk_identity_hint(SSL *ssl, const char *hint); void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb); void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb); - void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx, - SSL_psk_find_session_cb_func cb); - void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb); - =head1 DESCRIPTION -TLSv1.3 Pre-Shared Keys (PSKs) and PSKs for TLSv1.2 and below are not -compatible. +A client application wishing to use TLSv1.3 PSKs should set a callback +using either SSL_CTX_set_psk_use_session_callback() or +SSL_set_psk_use_session_callback() as appropriate. + +The callback function is given a pointer to the SSL connection in B<ssl> and +an identity in B<identity> of length B<identity_len>. The callback function +should identify an SSL_SESSION object that provides the PSK details and store it +in B<*sess>. The SSL_SESSION object should, as a minimum, set the master key, +the ciphersuite and the protocol version. See +L<SSL_CTX_set_psk_use_session_callback(3)> for details. + +It is also possible for the callback to succeed but not supply a PSK. In this +case no PSK will be used but the handshake will continue. To do this the +callback should return successfully and ensure that B<*sess> is +NULL. Identity hints are not relevant for TLSv1.3. A server application wishing to use PSK ciphersuites for TLSv1.2 and below may call SSL_CTX_use_psk_identity_hint() @@ -51,31 +65,25 @@ B<NULL> the current hint from B<ctx> or B<ssl> is deleted. In the case where PSK identity hint is B<NULL>, the server does not send the ServerKeyExchange message to the client. -A server application for TLSv1.2 and below must provide a callback function -which is called when the server receives the ClientKeyExchange message from the -client. The purpose of the callback function is to validate the -received PSK identity and to fetch the pre-shared key used during the -connection setup phase. The callback is set using the functions +A server application wishing to use PSKs for TLSv1.2 and below must provide a +callback function which is called when the server receives the +ClientKeyExchange message from the client. The purpose of the callback function +is to validate the received PSK identity and to fetch the pre-shared key used +during the connection setup phase. The callback is set using the functions SSL_CTX_set_psk_server_callback() or SSL_set_psk_server_callback(). The callback function is given the connection in parameter B<ssl>, B<NUL>-terminated PSK identity sent by the client in parameter B<identity>, and a buffer B<psk> of length B<max_psk_len> bytes where the pre-shared key is to be stored. -A client application wishing to use TLSv1.3 PSKs must set a different callback -using either SSL_CTX_set_psk_use_session_callback() or -SSL_set_psk_use_session_callback() as appropriate. - -The callback function is given a pointer to the SSL connection in B<ssl> and -an identity in B<identity> of length B<identity_len>. The callback function -should identify an SSL_SESSION object that provides the PSK details and store it -in B<*sess>. The SSL_SESSION object should, as a minimum, set the master key, -the ciphersuite and the protocol version. See -L<SSL_CTX_set_psk_use_session_callback(3)> for details. - -It is also possible for the callback to succeed but not supply a PSK. In this -case no PSK will be used but the handshake will continue. To do this the -callback should return successfully and ensure that B<*sess> is -NULL. +The callback for use in TLSv1.2 will also work in TLSv1.3 although it is +recommended to use SSL_CTX_set_psk_find_session_callback() +or SSL_set_psk_find_session_callback() for this purpose instead. If TLSv1.3 has +been negotiated then OpenSSL will first check to see if a callback has been set +via SSL_CTX_set_psk_find_session_callback() or SSL_set_psk_find_session_callback() +and it will use that in preference. If no such callback is present then it will +check to see if a callback has been set via SSL_CTX_set_psk_server_callback() or +SSL_set_psk_server_callback() and use that. In this case the handshake digest +will default to SHA-256 for any returned PSK. =head1 NOTES diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index 6e3f8d1..8a8e524 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -1426,7 +1426,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, const char external_label[] = "ext binder"; const char nonce_label[] = "resumption"; const char *label; - size_t bindersize, labelsize, hashsize = EVP_MD_size(md); + size_t bindersize, labelsize, psklen, hashsize = EVP_MD_size(md); int ret = -1; int usepskfored = 0; @@ -1444,16 +1444,12 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, labelsize = sizeof(resumption_label) - 1; } - if (sess->master_key_length != hashsize) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER, - SSL_R_BAD_PSK); - goto err; - } - if (external) { psk = sess->master_key; + psklen = sess->master_key_length; } else { psk = tmppsk; + psklen = hashsize; if (!tls13_hkdf_expand(s, md, sess->master_key, (const unsigned char *)nonce_label, sizeof(nonce_label) - 1, sess->ext.tick_nonce, @@ -1475,7 +1471,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart, early_secret = (unsigned char *)s->early_secret; else early_secret = (unsigned char *)sess->early_secret; - if (!tls13_generate_secret(s, md, NULL, psk, hashsize, early_secret)) { + if (!tls13_generate_secret(s, md, NULL, psk, psklen, early_secret)) { /* SSLfatal() already called */ goto err; } diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index fa6c65b..9bf2d1c 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -744,6 +744,7 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { + char identity[PSK_MAX_IDENTITY_LEN + 1]; const unsigned char *id = NULL; size_t idlen = 0; SSL_SESSION *psksess = NULL; @@ -763,6 +764,58 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, return EXT_RETURN_FAIL; } + if (psksess == NULL && s->psk_client_callback != NULL) { + unsigned char psk[PSK_MAX_PSK_LEN]; + size_t psklen = 0; + + memset(identity, 0, sizeof(identity)); + psklen = s->psk_client_callback(s, NULL, identity, sizeof(identity) - 1, + psk, sizeof(psk)); + + if (psklen > PSK_MAX_PSK_LEN) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } else if (psklen > 0) { + const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 }; + const SSL_CIPHER *cipher; + + idlen = strlen(identity); + if (idlen > PSK_MAX_IDENTITY_LEN) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + id = (unsigned char *)identity; + + /* + * We found a PSK using an old style callback. We don't know + * the digest so we default to SHA256 as per the TLSv1.3 spec + */ + cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); + if (cipher == NULL) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + + psksess = SSL_SESSION_new(); + if (psksess == NULL + || !SSL_SESSION_set1_master_key(psksess, psk, psklen) + || !SSL_SESSION_set_cipher(psksess, cipher) + || !SSL_SESSION_set_protocol_version(psksess, TLS1_3_VERSION)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, + ERR_R_INTERNAL_ERROR); + OPENSSL_cleanse(psk, psklen); + return EXT_RETURN_FAIL; + } + OPENSSL_cleanse(psk, psklen); + } + } + SSL_SESSION_free(s->psksession); s->psksession = psksess; if (psksess != NULL) { diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index d1be32c..bcabb85 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -1028,6 +1028,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, for (id = 0; PACKET_remaining(&identities) != 0; id++) { PACKET identity; unsigned long ticket_agel; + size_t idlen; if (!PACKET_get_length_prefixed_2(&identities, &identity) || !PACKET_get_net_4(&identities, &ticket_agel)) { @@ -1036,15 +1037,66 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, return 0; } + idlen = PACKET_remaining(&identity); if (s->psk_find_session_cb != NULL - && !s->psk_find_session_cb(s, PACKET_data(&identity), - PACKET_remaining(&identity), + && !s->psk_find_session_cb(s, PACKET_data(&identity), idlen, &sess)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION); return 0; } + if(sess == NULL + && s->psk_server_callback != NULL + && idlen <= PSK_MAX_IDENTITY_LEN) { + char *pskid = NULL; + unsigned char pskdata[PSK_MAX_PSK_LEN]; + unsigned int pskdatalen; + + if (!PACKET_strndup(&identity, &pskid)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return 0; + } + pskdatalen = s->psk_server_callback(s, pskid, pskdata, + sizeof(pskdata)); + OPENSSL_free(pskid); + if (pskdatalen > PSK_MAX_PSK_LEN) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return 0; + } else if (pskdatalen > 0) { + const SSL_CIPHER *cipher; + const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 }; + + /* + * We found a PSK using an old style callback. We don't know + * the digest so we default to SHA256 as per the TLSv1.3 spec + */ + cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id); + if (cipher == NULL) { + OPENSSL_cleanse(pskdata, pskdatalen); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + return 0; + } + + sess = SSL_SESSION_new(); + if (sess == NULL + || !SSL_SESSION_set1_master_key(sess, pskdata, + pskdatalen) + || !SSL_SESSION_set_cipher(sess, cipher) + || !SSL_SESSION_set_protocol_version(sess, + TLS1_3_VERSION)) { + OPENSSL_cleanse(pskdata, pskdatalen); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK, + ERR_R_INTERNAL_ERROR); + goto err; + } + OPENSSL_cleanse(pskdata, pskdatalen); + } + } + if (sess != NULL) { /* We found a PSK */ SSL_SESSION *sesstmp = ssl_session_dup(sess, 0); diff --git a/test/sslapitest.c b/test/sslapitest.c index ce24fad..c183ca8 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -1415,6 +1415,8 @@ static const char *srvid; static int use_session_cb_cnt = 0; static int find_session_cb_cnt = 0; +static int psk_client_cb_cnt = 0; +static int psk_server_cb_cnt = 0; static int use_session_cb(SSL *ssl, const EVP_MD *md, const unsigned char **id, size_t *idlen, SSL_SESSION **sess) @@ -1447,6 +1449,34 @@ static int use_session_cb(SSL *ssl, const EVP_MD *md, const unsigned char **id, return 1; } +static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *id, + unsigned int max_id_len, + unsigned char *psk, + unsigned int max_psk_len) +{ + unsigned int psklen = 0; + + psk_client_cb_cnt++; + + if (strlen(pskid) + 1 > max_id_len) + return 0; + + /* We should only ever be called a maximum of twice per connection */ + if (psk_client_cb_cnt > 2) + return 0; + + if (clientpsk == NULL) + return 0; + + /* We'll reuse the PSK we set up for TLSv1.3 */ + if (SSL_SESSION_get_master_key(clientpsk, NULL, 0) > max_psk_len) + return 0; + psklen = SSL_SESSION_get_master_key(clientpsk, psk, max_psk_len); + strncpy(id, pskid, max_id_len); + + return psklen; +} + static int find_session_cb(SSL *ssl, const unsigned char *identity, size_t identity_len, SSL_SESSION **sess) { @@ -1473,6 +1503,33 @@ static int find_session_cb(SSL *ssl, const unsigned char *identity, return 1; } +static unsigned int psk_server_cb(SSL *ssl, const char *identity, + unsigned char *psk, unsigned int max_psk_len) +{ + unsigned int psklen = 0; + + psk_server_cb_cnt++; + + /* We should only ever be called a maximum of twice per connection */ + if (find_session_cb_cnt > 2) + return 0; + + if (serverpsk == NULL) + return 0; + + /* Identity should match that set by the client */ + if (strcmp(srvid, identity) != 0) { + return 0; + } + + /* We'll reuse the PSK we set up for TLSv1.3 */ + if (SSL_SESSION_get_master_key(serverpsk, NULL, 0) > max_psk_len) + return 0; + psklen = SSL_SESSION_get_master_key(serverpsk, psk, max_psk_len); + + return psklen; +} + #define MSG1 "Hello" #define MSG2 "World." #define MSG3 "This" @@ -1482,6 +1539,7 @@ static int find_session_cb(SSL *ssl, const unsigned char *identity, #define MSG7 "message." #define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02") +#define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01") /* * Helper method to setup objects for early data test. Caller frees objects on @@ -2440,7 +2498,7 @@ static int test_ciphersuite_change(void) return testresult; } -static int test_tls13_psk(void) +static int test_tls13_psk(int idx) { SSL_CTX *sctx = NULL, *cctx = NULL; SSL *serverssl = NULL, *clientssl = NULL; @@ -2458,11 +2516,31 @@ static int test_tls13_psk(void) &cctx, cert, privkey))) goto end; - SSL_CTX_set_psk_use_session_callback(cctx, use_session_cb); - SSL_CTX_set_psk_find_session_callback(sctx, find_session_cb); + /* + * We use a ciphersuite with SHA256 to ease testing old style PSK callbacks + * which will always default to SHA256 + */ + if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "TLS13-AES-128-GCM-SHA256"))) + goto end; + + /* + * Test 0: New style callbacks only + * Test 1: New and old style callbacks (only the new ones should be used) + * Test 2: Old style callbacks only + */ + if (idx == 0 || idx == 1) { + SSL_CTX_set_psk_use_session_callback(cctx, use_session_cb); + SSL_CTX_set_psk_find_session_callback(sctx, find_session_cb); + } + if (idx == 1 || idx == 2) { + SSL_CTX_set_psk_client_callback(cctx, psk_client_cb); + SSL_CTX_set_psk_server_callback(sctx, psk_server_cb); + } srvid = pskid; use_session_cb_cnt = 0; find_session_cb_cnt = 0; + psk_client_cb_cnt = 0; + psk_server_cb_cnt = 0; /* Check we can create a connection if callback decides not to send a PSK */ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, @@ -2470,21 +2548,37 @@ static int test_tls13_psk(void) || !TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) || !TEST_false(SSL_session_reused(clientssl)) - || !TEST_false(SSL_session_reused(serverssl)) - || !TEST_true(use_session_cb_cnt == 1) - || !TEST_true(find_session_cb_cnt == 0)) + || !TEST_false(SSL_session_reused(serverssl))) goto end; + if (idx == 0 || idx == 1) { + if (!TEST_true(use_session_cb_cnt == 1) + || !TEST_true(find_session_cb_cnt == 0) + /* + * If no old style callback then below should be 0 + * otherwise 1 + */ + || !TEST_true(psk_client_cb_cnt == idx) + || !TEST_true(psk_server_cb_cnt == 0)) + goto end; + } else { + if (!TEST_true(use_session_cb_cnt == 0) + || !TEST_true(find_session_cb_cnt == 0) + || !TEST_true(psk_client_cb_cnt == 1) + || !TEST_true(psk_server_cb_cnt == 0)) + goto end; + } + shutdown_ssl_connection(serverssl, clientssl); serverssl = clientssl = NULL; - use_session_cb_cnt = 0; + use_session_cb_cnt = psk_client_cb_cnt = 0; if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL))) goto end; /* Create the PSK */ - cipher = SSL_CIPHER_find(clientssl, TLS13_AES_256_GCM_SHA384_BYTES); + cipher = SSL_CIPHER_find(clientssl, TLS13_AES_128_GCM_SHA256_BYTES); clientpsk = SSL_SESSION_new(); if (!TEST_ptr(clientpsk) || !TEST_ptr(cipher) @@ -2500,14 +2594,27 @@ static int test_tls13_psk(void) /* Check we can create a connection and the PSK is used */ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) || !TEST_true(SSL_session_reused(clientssl)) - || !TEST_true(SSL_session_reused(serverssl)) - || !TEST_true(use_session_cb_cnt == 1) - || !TEST_true(find_session_cb_cnt == 1)) + || !TEST_true(SSL_session_reused(serverssl))) goto end; + if (idx == 0 || idx == 1) { + if (!TEST_true(use_session_cb_cnt == 1) + || !TEST_true(find_session_cb_cnt == 1) + || !TEST_true(psk_client_cb_cnt == 0) + || !TEST_true(psk_server_cb_cnt == 0)) + goto end; + } else { + if (!TEST_true(use_session_cb_cnt == 0) + || !TEST_true(find_session_cb_cnt == 0) + || !TEST_true(psk_client_cb_cnt == 1) + || !TEST_true(psk_server_cb_cnt == 1)) + goto end; + } + shutdown_ssl_connection(serverssl, clientssl); serverssl = clientssl = NULL; use_session_cb_cnt = find_session_cb_cnt = 0; + psk_client_cb_cnt = psk_server_cb_cnt = 0; if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL))) @@ -2523,14 +2630,27 @@ static int test_tls13_psk(void) */ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) || !TEST_true(SSL_session_reused(clientssl)) - || !TEST_true(SSL_session_reused(serverssl)) - || !TEST_true(use_session_cb_cnt == 2) - || !TEST_true(find_session_cb_cnt == 2)) + || !TEST_true(SSL_session_reused(serverssl))) goto end; + if (idx == 0 || idx == 1) { + if (!TEST_true(use_session_cb_cnt == 2) + || !TEST_true(find_session_cb_cnt == 2) + || !TEST_true(psk_client_cb_cnt == 0) + || !TEST_true(psk_server_cb_cnt == 0)) + goto end; + } else { + if (!TEST_true(use_session_cb_cnt == 0) + || !TEST_true(find_session_cb_cnt == 0) + || !TEST_true(psk_client_cb_cnt == 2) + || !TEST_true(psk_server_cb_cnt == 2)) + goto end; + } + shutdown_ssl_connection(serverssl, clientssl); serverssl = clientssl = NULL; use_session_cb_cnt = find_session_cb_cnt = 0; + psk_client_cb_cnt = psk_server_cb_cnt = 0; /* * Check that if the server rejects the PSK we can still connect, but with @@ -2542,11 +2662,27 @@ static int test_tls13_psk(void) || !TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) || !TEST_false(SSL_session_reused(clientssl)) - || !TEST_false(SSL_session_reused(serverssl)) - || !TEST_true(use_session_cb_cnt == 1) - || !TEST_true(find_session_cb_cnt == 1)) + || !TEST_false(SSL_session_reused(serverssl))) goto end; + if (idx == 0 || idx == 1) { + if (!TEST_true(use_session_cb_cnt == 1) + || !TEST_true(find_session_cb_cnt == 1) + || !TEST_true(psk_client_cb_cnt == 0) + /* + * If no old style callback then below should be 0 + * otherwise 1 + */ + || !TEST_true(psk_server_cb_cnt == idx)) + goto end; + } else { + if (!TEST_true(use_session_cb_cnt == 0) + || !TEST_true(find_session_cb_cnt == 0) + || !TEST_true(psk_client_cb_cnt == 1) + || !TEST_true(psk_server_cb_cnt == 1)) + goto end; + } + shutdown_ssl_connection(serverssl, clientssl); serverssl = clientssl = NULL; testresult = 1; @@ -3506,7 +3642,7 @@ int setup_tests(void) #endif #ifndef OPENSSL_NO_TLS1_3 ADD_TEST(test_ciphersuite_change); - ADD_TEST(test_tls13_psk); + ADD_ALL_TESTS(test_tls13_psk, 3); ADD_ALL_TESTS(test_custom_exts, 5); ADD_TEST(test_stateless); ADD_TEST(test_pha_key_update); _____ openssl-commits mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-commits