X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fstatem%2Fextensions_clnt.c;h=86a1cab9ae81b4b63f459b82c2953ff173a811c8;hp=1bbb2102d7cae1a935ba19e02867a44d65445d6e;hb=add8d0e9e0bb80728f4b89d15573bf2e70596ceb;hpb=e3c0d76bc7848aae01fe9a86720d435b999f3bc1 diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index 1bbb2102d7..86a1cab9ae 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -9,6 +9,7 @@ #include #include "../ssl_locl.h" +#include "internal/cryptlib.h" #include "statem_locl.h" EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, @@ -678,12 +679,41 @@ EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { + const unsigned char *id; + size_t idlen; + SSL_SESSION *psksess = NULL; + const EVP_MD *handmd = NULL; + + if (s->hello_retry_request) + handmd = ssl_handshake_md(s); + + if (s->psk_use_session_cb != NULL + && !s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess)) { + SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, SSL_R_BAD_PSK); + return EXT_RETURN_FAIL; + } + + SSL_SESSION_free(s->psksession); + s->psksession = psksess; + if (psksess != NULL) { + OPENSSL_free(s->psksession_id); + s->psksession_id = OPENSSL_memdup(id, idlen); + if (s->psksession_id == NULL) { + SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR); + return EXT_RETURN_FAIL; + } + s->psksession_id_len = idlen; + } + if (s->early_data_state != SSL_EARLY_DATA_CONNECTING - || s->session->ext.max_early_data == 0) { + || (s->session->ext.max_early_data == 0 + && (psksess == NULL || psksess->ext.max_early_data == 0))) { s->max_early_data = 0; return EXT_RETURN_NOT_SENT; } - s->max_early_data = s->session->ext.max_early_data; + s->max_early_data = s->session->ext.max_early_data != 0 ? + s->session->ext.max_early_data + : psksess->ext.max_early_data; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data) || !WPACKET_start_sub_packet_u16(pkt) @@ -764,12 +794,14 @@ EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt, /* * Take off the size of extension header itself (2 bytes for type and - * 2 bytes for length bytes) + * 2 bytes for length bytes), but ensure that the extension is at least + * 1 byte long so as not to have an empty extension last (WebSphere 7.x, + * 8.x are intolerant of that condition) */ if (hlen >= 4) hlen -= 4; else - hlen = 0; + hlen = 1; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding) || !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) { @@ -790,12 +822,10 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, { #ifndef OPENSSL_NO_TLS1_3 uint32_t now, agesec, agems = 0; - size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen, idlen = 0; + size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen; unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL; - const unsigned char *id = 0; const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL; EXT_RETURN ret = EXT_RETURN_FAIL; - SSL_SESSION *psksess = NULL; int dores = 0; s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY; @@ -811,18 +841,12 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, * so don't add this extension. */ if (s->session->ssl_version != TLS1_3_VERSION - || (s->session->ext.ticklen == 0 && s->psk_use_session_cb == NULL)) + || (s->session->ext.ticklen == 0 && s->psksession == NULL)) return EXT_RETURN_NOT_SENT; if (s->hello_retry_request) handmd = ssl_handshake_md(s); - if (s->psk_use_session_cb != NULL - && !s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess)) { - SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, SSL_R_BAD_PSK); - goto err; - } - if (s->session->ext.ticklen != 0) { /* Get the digest associated with the ciphersuite in the session */ if (s->session->cipher == NULL) { @@ -887,11 +911,11 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, } dopsksess: - if (!dores && psksess == NULL) + if (!dores && s->psksession == NULL) return EXT_RETURN_NOT_SENT; - if (psksess != NULL) { - mdpsk = ssl_md(psksess->cipher->algorithm2); + if (s->psksession != NULL) { + mdpsk = ssl_md(s->psksession->cipher->algorithm2); if (mdpsk == NULL) { /* * Don't recognize this cipher so we can't use the session. @@ -930,8 +954,9 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, } } - if (psksess != NULL) { - if (!WPACKET_sub_memcpy_u16(pkt, id, idlen) + if (s->psksession != NULL) { + if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id, + s->psksession_id_len) || !WPACKET_put_bytes_u32(pkt, 0)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR); goto err; @@ -943,7 +968,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, || !WPACKET_start_sub_packet_u16(pkt) || (dores && !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder)) - || (psksess != NULL + || (s->psksession != NULL && !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder)) || !WPACKET_close(pkt) || !WPACKET_close(pkt) @@ -966,24 +991,20 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, goto err; } - if (psksess != NULL + if (s->psksession != NULL && tls_psk_do_binder(s, mdpsk, msgstart, binderoffset, NULL, - pskbinder, psksess, 1, 1) != 1) { + pskbinder, s->psksession, 1, 1) != 1) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK, ERR_R_INTERNAL_ERROR); goto err; } if (dores) s->session->ext.tick_identity = 0; - SSL_SESSION_free(s->psksession); - s->psksession = psksess; - if (psksess != NULL) + if (s->psksession != NULL) s->psksession->ext.tick_identity = (dores ? 1 : 0); - psksess = NULL; ret = EXT_RETURN_SENT; err: - SSL_SESSION_free(psksess); return ret; #else return 1; @@ -1603,10 +1624,20 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, return 0; } + /* + * If we used the external PSK for sending early_data then s->early_secret + * is already set up, so don't overwrite it. Otherwise we copy the + * early_secret across that we generated earlier. + */ + if ((s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY + && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) + || s->session->ext.max_early_data > 0 + || s->psksession->ext.max_early_data == 0) + memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE); + SSL_SESSION_free(s->session); s->session = s->psksession; s->psksession = NULL; - memcpy(s->early_secret, s->session->early_secret, EVP_MAX_MD_SIZE); s->hit = 1; #endif