mirror of https://github.com/openssl/openssl.git
Fix handling of max_fragment_length extension for PSK
A psk session was assumed to be a resumption which failed a check when parsing the max_fragment_length extension hello from the client. Relevant code from PR#18130 which was a suggested fix to the issue was cherry-picked. Fixes #18121 Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Viktor Dukhovni <viktor@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/24513)
This commit is contained in:
parent
6a3579e190
commit
fa49560451
|
@ -231,6 +231,8 @@ extern "C" {
|
||||||
# define TLSEXT_max_fragment_length_1024 2
|
# define TLSEXT_max_fragment_length_1024 2
|
||||||
# define TLSEXT_max_fragment_length_2048 3
|
# define TLSEXT_max_fragment_length_2048 3
|
||||||
# define TLSEXT_max_fragment_length_4096 4
|
# define TLSEXT_max_fragment_length_4096 4
|
||||||
|
/* OpenSSL value for unset maximum fragment length extension */
|
||||||
|
# define TLSEXT_max_fragment_length_UNSPECIFIED 255
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TLS Certificate Type (for RFC7250)
|
* TLS Certificate Type (for RFC7250)
|
||||||
|
|
|
@ -109,6 +109,7 @@ SSL_SESSION *SSL_SESSION_new(void)
|
||||||
if (ss == NULL)
|
if (ss == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
ss->ext.max_fragment_len_mode = TLSEXT_max_fragment_length_UNSPECIFIED;
|
||||||
ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
|
ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
|
||||||
/* 5 minute timeout by default */
|
/* 5 minute timeout by default */
|
||||||
ss->timeout = ossl_seconds2time(60 * 5 + 4);
|
ss->timeout = ossl_seconds2time(60 * 5 + 4);
|
||||||
|
|
|
@ -1741,15 +1741,9 @@ static int final_early_data(SSL_CONNECTION *s, unsigned int context, int sent)
|
||||||
static int final_maxfragmentlen(SSL_CONNECTION *s, unsigned int context,
|
static int final_maxfragmentlen(SSL_CONNECTION *s, unsigned int context,
|
||||||
int sent)
|
int sent)
|
||||||
{
|
{
|
||||||
/*
|
/* MaxFragmentLength defaults to disabled */
|
||||||
* Session resumption on server-side with MFL extension active
|
if (s->session->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_UNSPECIFIED)
|
||||||
* BUT MFL extension packet was not resent (i.e. sent == 0)
|
s->session->ext.max_fragment_len_mode = TLSEXT_max_fragment_length_DISABLED;
|
||||||
*/
|
|
||||||
if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
|
|
||||||
&& !sent ) {
|
|
||||||
SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_R_BAD_EXTENSION);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)) {
|
if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)) {
|
||||||
s->rlayer.rrlmethod->set_max_frag_len(s->rlayer.rrl,
|
s->rlayer.rrlmethod->set_max_frag_len(s->rlayer.rrl,
|
||||||
|
|
|
@ -192,21 +192,26 @@ int tls_parse_ctos_maxfragmentlen(SSL_CONNECTION *s, PACKET *pkt,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RFC 6066: The negotiated length applies for the duration of the session
|
* When doing a full handshake or a renegotiation max_fragment_len_mode will
|
||||||
|
* be TLSEXT_max_fragment_length_UNSPECIFIED
|
||||||
|
*
|
||||||
|
* In case of a resumption max_fragment_len_mode will be one of
|
||||||
|
* TLSEXT_max_fragment_length_DISABLED, TLSEXT_max_fragment_length_512,
|
||||||
|
* TLSEXT_max_fragment_length_1024, TLSEXT_max_fragment_length_2048.
|
||||||
|
* TLSEXT_max_fragment_length_4096
|
||||||
|
*
|
||||||
|
* RFC 6066: The negotiated length applies for the duration of the session
|
||||||
* including session resumptions.
|
* including session resumptions.
|
||||||
* We should receive the same code as in resumed session !
|
*
|
||||||
|
* So we only set the value in case it is unspecified.
|
||||||
*/
|
*/
|
||||||
if (s->hit && s->session->ext.max_fragment_len_mode != value) {
|
if (s->session->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_UNSPECIFIED)
|
||||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
/*
|
||||||
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
|
* Store it in session, so it'll become binding for us
|
||||||
return 0;
|
* and we'll include it in a next Server Hello.
|
||||||
}
|
*/
|
||||||
|
s->session->ext.max_fragment_len_mode = value;
|
||||||
|
|
||||||
/*
|
|
||||||
* Store it in session, so it'll become binding for us
|
|
||||||
* and we'll include it in a next Server Hello.
|
|
||||||
*/
|
|
||||||
s->session->ext.max_fragment_len_mode = value;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3930,6 +3930,8 @@ int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode)
|
||||||
|
|
||||||
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session)
|
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session)
|
||||||
{
|
{
|
||||||
|
if (session->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_UNSPECIFIED)
|
||||||
|
return TLSEXT_max_fragment_length_DISABLED;
|
||||||
return session->ext.max_fragment_len_mode;
|
return session->ext.max_fragment_len_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue