diff options
author | Matt Caswell <matt@openssl.org> | 2018-03-06 16:41:51 +0000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2018-03-09 11:22:23 +0000 |
commit | f3d40db1b947f546541b815a0363de3120c16506 (patch) | |
tree | dcc421ae5ca2151cada49bacdf143f12ed775455 /ssl/statem/extensions_clnt.c | |
parent | e73c6eaeff82615d20845692c5c72ba9dfa895f5 (diff) |
Fallback on old style PSK callbacks if the new style ones aren't present
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5554)
Diffstat (limited to 'ssl/statem/extensions_clnt.c')
-rw-r--r-- | ssl/statem/extensions_clnt.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index fa6c65b266..9bf2d1cb38 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) { |