Implement Maximum Fragment Length TLS extension.

Based on patch from Tomasz Moń:
https://groups.google.com/forum/#!topic/mailing.openssl.dev/fQxXvCg1uQY

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
(Merged from https://github.com/openssl/openssl/pull/1008)
This commit is contained in:
FdaSilvaYY 2017-11-05 17:46:48 +01:00 committed by Bernd Edlinger
parent b82acc3c1a
commit cf72c75792
32 changed files with 860 additions and 36 deletions

View file

@ -9,6 +9,11 @@
Changes between 1.1.0f and 1.1.1 [xx XXX xxxx] Changes between 1.1.0f and 1.1.1 [xx XXX xxxx]
*) Add 'Maximum Fragment Length' TLS extension negotiation and support
as documented in RFC6066.
Based on a patch from Tomasz Moń
[Filipe Raimundo da Silva]
*) Add SM4 implemented according to GB/T 32907-2016. *) Add SM4 implemented according to GB/T 32907-2016.
[ Jack Lloyd <jack.lloyd@ribose.com>, [ Jack Lloyd <jack.lloyd@ribose.com>,
Ronald Tse <ronald.tse@ribose.com>, Ronald Tse <ronald.tse@ribose.com>,

View file

@ -590,8 +590,8 @@ typedef enum OPTION_choice {
OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN, OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN,
OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME, OPT_NOSERVERNAME, OPT_ASYNC, OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME, OPT_NOSERVERNAME, OPT_ASYNC,
OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_PROTOHOST, OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_PROTOHOST,
OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF, OPT_MAXFRAGLEN, OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES,
OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE, OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE,
OPT_V_ENUM, OPT_V_ENUM,
OPT_X_ENUM, OPT_X_ENUM,
OPT_S_ENUM, OPT_S_ENUM,
@ -665,6 +665,8 @@ const OPTIONS s_client_options[] = {
"Export keying material using label"}, "Export keying material using label"},
{"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p', {"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
"Export len bytes of keying material (default 20)"}, "Export len bytes of keying material (default 20)"},
{"maxfraglen", OPT_MAXFRAGLEN, 'p',
"Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"},
{"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"}, {"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"},
{"name", OPT_PROTOHOST, 's', {"name", OPT_PROTOHOST, 's',
"Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""}, "Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""},
@ -942,6 +944,7 @@ int s_client_main(int argc, char **argv)
unsigned int split_send_fragment = 0, max_pipelines = 0; unsigned int split_send_fragment = 0, max_pipelines = 0;
enum { use_inet, use_unix, use_unknown } connect_type = use_unknown; enum { use_inet, use_unix, use_unknown } connect_type = use_unknown;
int count4or6 = 0; int count4or6 = 0;
uint8_t maxfraglen = 0;
int c_nbio = 0, c_msg = 0, c_ign_eof = 0, c_brief = 0; int c_nbio = 0, c_msg = 0, c_ign_eof = 0, c_brief = 0;
int c_tlsextdebug = 0; int c_tlsextdebug = 0;
#ifndef OPENSSL_NO_OCSP #ifndef OPENSSL_NO_OCSP
@ -1424,6 +1427,28 @@ int s_client_main(int argc, char **argv)
case OPT_ASYNC: case OPT_ASYNC:
async = 1; async = 1;
break; break;
case OPT_MAXFRAGLEN:
len = atoi(opt_arg());
switch (len) {
case 512:
maxfraglen = TLSEXT_max_fragment_length_512;
break;
case 1024:
maxfraglen = TLSEXT_max_fragment_length_1024;
break;
case 2048:
maxfraglen = TLSEXT_max_fragment_length_2048;
break;
case 4096:
maxfraglen = TLSEXT_max_fragment_length_4096;
break;
default:
BIO_printf(bio_err,
"%s: Max Fragment Len %u is out of permitted values",
prog, len);
goto opthelp;
}
break;
case OPT_MAX_SEND_FRAG: case OPT_MAX_SEND_FRAG:
max_send_fragment = atoi(opt_arg()); max_send_fragment = atoi(opt_arg());
break; break;
@ -1677,6 +1702,14 @@ int s_client_main(int argc, char **argv)
SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len); SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len);
} }
if (maxfraglen > 0
&& !SSL_CTX_set_tlsext_max_fragment_length(ctx, maxfraglen)) {
BIO_printf(bio_err,
"%s: Max Fragment Length code %u is out of permitted values"
"\n", prog, maxfraglen);
goto end;
}
if (!config_ctx(cctx, ssl_args, ctx)) if (!config_ctx(cctx, ssl_args, ctx))
goto end; goto end;

View file

@ -1063,6 +1063,8 @@ SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE:290:SSL_CTX_set_client_cert_engine
SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK:396:SSL_CTX_set_ct_validation_callback SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK:396:SSL_CTX_set_ct_validation_callback
SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT:219:SSL_CTX_set_session_id_context SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT:219:SSL_CTX_set_session_id_context
SSL_F_SSL_CTX_SET_SSL_VERSION:170:SSL_CTX_set_ssl_version SSL_F_SSL_CTX_SET_SSL_VERSION:170:SSL_CTX_set_ssl_version
SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH:551:\
SSL_CTX_set_tlsext_max_fragment_length
SSL_F_SSL_CTX_USE_CERTIFICATE:171:SSL_CTX_use_certificate SSL_F_SSL_CTX_USE_CERTIFICATE:171:SSL_CTX_use_certificate
SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1:172:SSL_CTX_use_certificate_ASN1 SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1:172:SSL_CTX_use_certificate_ASN1
SSL_F_SSL_CTX_USE_CERTIFICATE_FILE:173:SSL_CTX_use_certificate_file SSL_F_SSL_CTX_USE_CERTIFICATE_FILE:173:SSL_CTX_use_certificate_file
@ -1126,6 +1128,7 @@ SSL_F_SSL_SET_RFD:194:SSL_set_rfd
SSL_F_SSL_SET_SESSION:195:SSL_set_session SSL_F_SSL_SET_SESSION:195:SSL_set_session
SSL_F_SSL_SET_SESSION_ID_CONTEXT:218:SSL_set_session_id_context SSL_F_SSL_SET_SESSION_ID_CONTEXT:218:SSL_set_session_id_context
SSL_F_SSL_SET_SESSION_TICKET_EXT:294:SSL_set_session_ticket_ext SSL_F_SSL_SET_SESSION_TICKET_EXT:294:SSL_set_session_ticket_ext
SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH:550:SSL_set_tlsext_max_fragment_length
SSL_F_SSL_SET_WFD:196:SSL_set_wfd SSL_F_SSL_SET_WFD:196:SSL_set_wfd
SSL_F_SSL_SHUTDOWN:224:SSL_shutdown SSL_F_SSL_SHUTDOWN:224:SSL_shutdown
SSL_F_SSL_SRP_CTX_INIT:313:SSL_SRP_CTX_init SSL_F_SSL_SRP_CTX_INIT:313:SSL_SRP_CTX_init
@ -1192,6 +1195,7 @@ SSL_F_TLS_CONSTRUCT_CTOS_ETM:469:tls_construct_ctos_etm
SSL_F_TLS_CONSTRUCT_CTOS_HELLO:356:* SSL_F_TLS_CONSTRUCT_CTOS_HELLO:356:*
SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE:357:* SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE:357:*
SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE:470:tls_construct_ctos_key_share SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE:470:tls_construct_ctos_key_share
SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN:549:tls_construct_ctos_maxfragmentlen
SSL_F_TLS_CONSTRUCT_CTOS_NPN:471:tls_construct_ctos_npn SSL_F_TLS_CONSTRUCT_CTOS_NPN:471:tls_construct_ctos_npn
SSL_F_TLS_CONSTRUCT_CTOS_PADDING:472:tls_construct_ctos_padding SSL_F_TLS_CONSTRUCT_CTOS_PADDING:472:tls_construct_ctos_padding
SSL_F_TLS_CONSTRUCT_CTOS_PSK:501:tls_construct_ctos_psk SSL_F_TLS_CONSTRUCT_CTOS_PSK:501:tls_construct_ctos_psk
@ -1233,6 +1237,7 @@ SSL_F_TLS_CONSTRUCT_STOC_ETM:455:tls_construct_stoc_etm
SSL_F_TLS_CONSTRUCT_STOC_HELLO:376:* SSL_F_TLS_CONSTRUCT_STOC_HELLO:376:*
SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE:377:* SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE:377:*
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE:456:tls_construct_stoc_key_share SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE:456:tls_construct_stoc_key_share
SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN:548:tls_construct_stoc_maxfragmentlen
SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG:457:tls_construct_stoc_next_proto_neg SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG:457:tls_construct_stoc_next_proto_neg
SSL_F_TLS_CONSTRUCT_STOC_PSK:504:tls_construct_stoc_psk SSL_F_TLS_CONSTRUCT_STOC_PSK:504:tls_construct_stoc_psk
SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE:458:tls_construct_stoc_renegotiate SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE:458:tls_construct_stoc_renegotiate
@ -2443,6 +2448,8 @@ SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES:362:srtp could not allocate profiles
SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG:363:\ SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG:363:\
srtp protection profile list too long srtp protection profile list too long
SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE:364:srtp unknown protection profile SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE:364:srtp unknown protection profile
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH:232:\
ssl3 ext invalid max fragment length
SSL_R_SSL3_EXT_INVALID_SERVERNAME:319:ssl3 ext invalid servername SSL_R_SSL3_EXT_INVALID_SERVERNAME:319:ssl3 ext invalid servername
SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE:320:ssl3 ext invalid servername type SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE:320:ssl3 ext invalid servername type
SSL_R_SSL3_SESSION_ID_TOO_LONG:300:ssl3 session id too long SSL_R_SSL3_SESSION_ID_TOO_LONG:300:ssl3 session id too long

View file

@ -5,8 +5,10 @@
SSL_CTX_set_max_send_fragment, SSL_set_max_send_fragment, SSL_CTX_set_max_send_fragment, SSL_set_max_send_fragment,
SSL_CTX_set_split_send_fragment, SSL_set_split_send_fragment, SSL_CTX_set_split_send_fragment, SSL_set_split_send_fragment,
SSL_CTX_set_max_pipelines, SSL_set_max_pipelines, SSL_CTX_set_max_pipelines, SSL_set_max_pipelines,
SSL_CTX_set_default_read_buffer_len, SSL_set_default_read_buffer_len - Control SSL_CTX_set_default_read_buffer_len, SSL_set_default_read_buffer_len,
fragment sizes and pipelining operations SSL_CTX_set_tlsext_max_fragment_length,
SSL_set_tlsext_max_fragment_length,
SSL_SESSION_get_max_fragment_length - Control fragment size settings and pipelining operations
=head1 SYNOPSIS =head1 SYNOPSIS
@ -24,6 +26,10 @@ fragment sizes and pipelining operations
void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len); void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
void SSL_set_default_read_buffer_len(SSL *s, size_t len); void SSL_set_default_read_buffer_len(SSL *s, size_t len);
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode);
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode);
uint8_t SSL_SESSION_get_max_fragment_length(SSL_SESSION *session);
=head1 DESCRIPTION =head1 DESCRIPTION
Some engines are able to process multiple simultaneous crypto operations. This Some engines are able to process multiple simultaneous crypto operations. This
@ -99,15 +105,62 @@ greater than the default that would have been used anyway. The normal default
value depends on a number of factors but it will be at least value depends on a number of factors but it will be at least
SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD (16704) bytes. SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD (16704) bytes.
SSL_CTX_set_tlsext_max_fragment_length() sets the default maximum fragment
length negotiation mode via value B<mode> to B<ctx>.
This setting affects only SSL instances created after this function is called.
It affects the client-side as only its side may initiate this extension use.
SSL_set_tlsext_max_fragment_length() sets the maximum fragment length
negotiation mode via value B<mode> to B<ssl>.
This setting will be used during a handshake when extensions are exchanged
between client and server.
So it only affects SSL sessions created after this function is called.
It affects the client-side as only its side may initiate this extension use.
SSL_SESSION_get_max_fragment_length() gets the maximum fragment length
negotiated in B<session>.
=head1 RETURN VALUES =head1 RETURN VALUES
All non-void functions return 1 on success and 0 on failure. All non-void functions return 1 on success and 0 on failure.
=head1 NOTES =head1 NOTES
With the exception of SSL_CTX_set_default_read_buffer_len() and The Maximum Fragment Length extension support is optional on the server side.
SSL_set_default_read_buffer_len() all these functions are implemented using If the server does not support this extension then
macros. SSL_SESSION_get_max_fragment_length() will return:
TLSEXT_max_fragment_length_DISABLED.
The following modes are available:
=over 4
=item TLSEXT_max_fragment_length_DISABLED
Disables Maximum Fragment Length Negotiation (default).
=item TLSEXT_max_fragment_length_512
Sets Maximum Fragment Length to 512 bytes.
=item TLSEXT_max_fragment_length_1024
Sets Maximum Fragment Length to 1024.
=item TLSEXT_max_fragment_length_2048
Sets Maximum Fragment Length to 2048.
=item TLSEXT_max_fragment_length_4096
Sets Maximum Fragment Length to 4096.
=back
With the exception of SSL_CTX_set_default_read_buffer_len()
SSL_set_default_read_buffer_len(), SSL_CTX_set_tlsext_max_fragment_length(),
SSL_set_tlsext_max_fragment_length() and SSL_SESSION_get_max_fragment_length()
all these functions are implemented using macros.
=head1 HISTORY =head1 HISTORY
@ -116,13 +169,16 @@ SSL_CTX_set_split_send_fragment(), SSL_set_split_send_fragment(),
SSL_CTX_set_default_read_buffer_len() and SSL_set_default_read_buffer_len() SSL_CTX_set_default_read_buffer_len() and SSL_set_default_read_buffer_len()
functions were added in OpenSSL 1.1.0. functions were added in OpenSSL 1.1.0.
SSL_CTX_set_tlsext_max_fragment_length(), SSL_set_tlsext_max_fragment_length()
and SSL_SESSION_get_max_fragment_length() were added in OpenSSL 1.1.1.
=head1 SEE ALSO =head1 SEE ALSO
L<SSL_CTX_set_read_ahead(3)>, L<SSL_pending(3)> L<SSL_CTX_set_read_ahead(3)>, L<SSL_pending(3)>
=head1 COPYRIGHT =head1 COPYRIGHT
Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy this file except in compliance with the License. You can obtain a copy

View file

@ -1915,10 +1915,11 @@ __owur size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
size_t outlen); size_t outlen);
__owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, __owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
size_t outlen); size_t outlen);
__owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *ssl, __owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *sess,
unsigned char *out, size_t outlen); unsigned char *out, size_t outlen);
__owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess, __owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess,
const unsigned char *in, size_t len); const unsigned char *in, size_t len);
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *sess);
#define SSL_get_ex_new_index(l, p, newf, dupf, freef) \ #define SSL_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef) CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef)

View file

@ -129,6 +129,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK 396 # define SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK 396
# define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219 # define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219
# define SSL_F_SSL_CTX_SET_SSL_VERSION 170 # define SSL_F_SSL_CTX_SET_SSL_VERSION 170
# define SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH 551
# define SSL_F_SSL_CTX_USE_CERTIFICATE 171 # define SSL_F_SSL_CTX_USE_CERTIFICATE 171
# define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172 # define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172
# define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173 # define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173
@ -192,6 +193,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_SSL_SET_SESSION 195 # define SSL_F_SSL_SET_SESSION 195
# define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218 # define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218
# define SSL_F_SSL_SET_SESSION_TICKET_EXT 294 # define SSL_F_SSL_SET_SESSION_TICKET_EXT 294
# define SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH 550
# define SSL_F_SSL_SET_WFD 196 # define SSL_F_SSL_SET_WFD 196
# define SSL_F_SSL_SHUTDOWN 224 # define SSL_F_SSL_SHUTDOWN 224
# define SSL_F_SSL_SRP_CTX_INIT 313 # define SSL_F_SSL_SRP_CTX_INIT 313
@ -257,6 +259,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_TLS_CONSTRUCT_CTOS_HELLO 356 # define SSL_F_TLS_CONSTRUCT_CTOS_HELLO 356
# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE 357 # define SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE 357
# define SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE 470 # define SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE 470
# define SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN 549
# define SSL_F_TLS_CONSTRUCT_CTOS_NPN 471 # define SSL_F_TLS_CONSTRUCT_CTOS_NPN 471
# define SSL_F_TLS_CONSTRUCT_CTOS_PADDING 472 # define SSL_F_TLS_CONSTRUCT_CTOS_PADDING 472
# define SSL_F_TLS_CONSTRUCT_CTOS_PSK 501 # define SSL_F_TLS_CONSTRUCT_CTOS_PSK 501
@ -296,6 +299,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_TLS_CONSTRUCT_STOC_HELLO 376 # define SSL_F_TLS_CONSTRUCT_STOC_HELLO 376
# define SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE 377 # define SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE 377
# define SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE 456 # define SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE 456
# define SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN 548
# define SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG 457 # define SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG 457
# define SSL_F_TLS_CONSTRUCT_STOC_PSK 504 # define SSL_F_TLS_CONSTRUCT_STOC_PSK 504
# define SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE 458 # define SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE 458
@ -551,6 +555,7 @@ int ERR_load_SSL_strings(void);
# define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 362 # define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 362
# define SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG 363 # define SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG 363
# define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE 364 # define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE 364
# define SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH 232
# define SSL_R_SSL3_EXT_INVALID_SERVERNAME 319 # define SSL_R_SSL3_EXT_INVALID_SERVERNAME 319
# define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 320 # define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 320
# define SSL_R_SSL3_SESSION_ID_TOO_LONG 300 # define SSL_R_SSL3_SESSION_ID_TOO_LONG 300

View file

@ -203,6 +203,17 @@ extern "C" {
# define TLSEXT_curve_P_256 23 # define TLSEXT_curve_P_256 23
# define TLSEXT_curve_P_384 24 # define TLSEXT_curve_P_384 24
/* OpenSSL value to disable maximum fragment length extension */
# define TLSEXT_max_fragment_length_DISABLED 0
/* Allowed values for max fragment length extension */
# define TLSEXT_max_fragment_length_512 1
# define TLSEXT_max_fragment_length_1024 2
# define TLSEXT_max_fragment_length_2048 3
# define TLSEXT_max_fragment_length_4096 4
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode);
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode);
# define TLSEXT_MAXLEN_host_name 255 # define TLSEXT_MAXLEN_host_name 255
__owur const char *SSL_get_servername(const SSL *s, const int type); __owur const char *SSL_get_servername(const SSL *s, const int type);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved.
* *
* Licensed under the OpenSSL license (the "License"). You may not use * Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy * this file except in compliance with the License. You can obtain a copy
@ -774,7 +774,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
if (len == 0 && !create_empty_fragment) if (len == 0 && !create_empty_fragment)
return 0; return 0;
if (len > s->max_send_fragment) { if (len > ssl_get_max_send_fragment(s)) {
SSLerr(SSL_F_DO_DTLS1_WRITE, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE); SSLerr(SSL_F_DO_DTLS1_WRITE, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
return 0; return 0;
} }

View file

@ -334,9 +334,9 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
{ {
const unsigned char *buf = buf_; const unsigned char *buf = buf_;
size_t tot; size_t tot;
size_t n, split_send_fragment, maxpipes; size_t n, max_send_fragment, split_send_fragment, maxpipes;
#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK #if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
size_t max_send_fragment, nw; size_t nw;
#endif #endif
SSL3_BUFFER *wb = &s->rlayer.wbuf[0]; SSL3_BUFFER *wb = &s->rlayer.wbuf[0];
int i; int i;
@ -403,7 +403,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
* compromise is considered worthy. * compromise is considered worthy.
*/ */
if (type == SSL3_RT_APPLICATION_DATA && if (type == SSL3_RT_APPLICATION_DATA &&
len >= 4 * (max_send_fragment = s->max_send_fragment) && len >= 4 * (max_send_fragment = ssl_get_max_send_fragment(s)) &&
s->compress == NULL && s->msg_callback == NULL && s->compress == NULL && s->msg_callback == NULL &&
!SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) && !SSL_WRITE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) & EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_write_ctx)) &
@ -523,7 +523,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
tot += tmpwrit; tot += tmpwrit;
} }
} else } else
#endif #endif /* !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK */
if (tot == len) { /* done? */ if (tot == len) { /* done? */
if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s))
ssl3_release_write_buffer(s); ssl3_release_write_buffer(s);
@ -534,7 +534,8 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
n = (len - tot); n = (len - tot);
split_send_fragment = s->split_send_fragment; max_send_fragment = ssl_get_max_send_fragment(s);
split_send_fragment = ssl_get_split_send_fragment(s);
/* /*
* If max_pipelines is 0 then this means "undefined" and we default to * If max_pipelines is 0 then this means "undefined" and we default to
* 1 pipeline. Similarly if the cipher does not support pipelined * 1 pipeline. Similarly if the cipher does not support pipelined
@ -556,10 +557,10 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
& EVP_CIPH_FLAG_PIPELINE) & EVP_CIPH_FLAG_PIPELINE)
|| !SSL_USE_EXPLICIT_IV(s)) || !SSL_USE_EXPLICIT_IV(s))
maxpipes = 1; maxpipes = 1;
if (s->max_send_fragment == 0 || split_send_fragment > s->max_send_fragment if (max_send_fragment == 0 || split_send_fragment == 0
|| split_send_fragment == 0) { || split_send_fragment > max_send_fragment) {
/* /*
* We should have prevented this when we set the split and max send * We should have prevented this when we set/get the split and max send
* fragments so we shouldn't get here * fragments so we shouldn't get here
*/ */
SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_SSL3_WRITE_BYTES, ERR_R_INTERNAL_ERROR);
@ -577,13 +578,13 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, size_t len,
if (numpipes > maxpipes) if (numpipes > maxpipes)
numpipes = maxpipes; numpipes = maxpipes;
if (n / numpipes >= s->max_send_fragment) { if (n / numpipes >= max_send_fragment) {
/* /*
* We have enough data to completely fill all available * We have enough data to completely fill all available
* pipelines * pipelines
*/ */
for (j = 0; j < numpipes; j++) { for (j = 0; j < numpipes; j++) {
pipelens[j] = s->max_send_fragment; pipelens[j] = max_send_fragment;
} }
} else { } else {
/* We can partially fill all available pipelines */ /* We can partially fill all available pipelines */
@ -854,7 +855,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
} }
if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) { if (SSL_TREAT_AS_TLS13(s) && s->enc_write_ctx != NULL) {
size_t rlen; size_t rlen, max_send_fragment;
if (!WPACKET_put_bytes_u8(thispkt, type)) { if (!WPACKET_put_bytes_u8(thispkt, type)) {
SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
@ -863,10 +864,11 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
SSL3_RECORD_add_length(thiswr, 1); SSL3_RECORD_add_length(thiswr, 1);
/* Add TLS1.3 padding */ /* Add TLS1.3 padding */
max_send_fragment = ssl_get_max_send_fragment(s);
rlen = SSL3_RECORD_get_length(thiswr); rlen = SSL3_RECORD_get_length(thiswr);
if (rlen < SSL3_RT_MAX_PLAIN_LENGTH) { if (rlen < max_send_fragment) {
size_t padding = 0; size_t padding = 0;
size_t max_padding = SSL3_RT_MAX_PLAIN_LENGTH - rlen; size_t max_padding = max_send_fragment - rlen;
if (s->record_padding_cb != NULL) { if (s->record_padding_cb != NULL) {
padding = s->record_padding_cb(s, type, rlen, s->record_padding_arg); padding = s->record_padding_cb(s, type, rlen, s->record_padding_arg);
} else if (s->block_padding > 0) { } else if (s->block_padding > 0) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
* *
* Licensed under the OpenSSL license (the "License"). You may not use * Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy * this file except in compliance with the License. You can obtain a copy
@ -93,7 +93,7 @@ int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1);
#endif #endif
len = s->max_send_fragment len = ssl_get_max_send_fragment(s)
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align;
#ifndef OPENSSL_NO_COMP #ifndef OPENSSL_NO_COMP
if (ssl_allow_compression(s)) if (ssl_allow_compression(s))
@ -107,6 +107,11 @@ int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len)
for (currpipe = 0; currpipe < numwpipes; currpipe++) { for (currpipe = 0; currpipe < numwpipes; currpipe++) {
SSL3_BUFFER *thiswb = &wb[currpipe]; SSL3_BUFFER *thiswb = &wb[currpipe];
if (thiswb->buf != NULL && thiswb->len != len) {
OPENSSL_free(thiswb->buf);
thiswb->buf = NULL; /* force reallocation */
}
if (thiswb->buf == NULL) { if (thiswb->buf == NULL) {
p = OPENSSL_malloc(len); p = OPENSSL_malloc(len);
if (p == NULL) { if (p == NULL) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
* *
* Licensed under the OpenSSL license (the "License"). You may not use * Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy * this file except in compliance with the License. You can obtain a copy
@ -685,6 +685,14 @@ int ssl3_get_record(SSL *s)
goto f_err; goto f_err;
} }
/* If received packet overflows current Max Fragment Length setting */
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& thisrr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) {
al = SSL_AD_RECORD_OVERFLOW;
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_DATA_LENGTH_TOO_LONG);
goto f_err;
}
thisrr->off = 0; thisrr->off = 0;
/*- /*-
* So at this point the following is true * So at this point the following is true
@ -1823,6 +1831,15 @@ int dtls1_get_record(SSL *s)
goto again; goto again;
} }
/* If received packet overflows own-client Max Fragment Length setting */
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& rr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) {
/* record too long, silently discard it */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
goto again;
}
/* now s->rlayer.rstate == SSL_ST_READ_BODY */ /* now s->rlayer.rstate == SSL_ST_READ_BODY */
} }

View file

@ -42,6 +42,7 @@ typedef struct {
uint32_t max_early_data; uint32_t max_early_data;
ASN1_OCTET_STRING *alpn_selected; ASN1_OCTET_STRING *alpn_selected;
ASN1_OCTET_STRING *tick_nonce; ASN1_OCTET_STRING *tick_nonce;
uint32_t tlsext_max_fragment_len_mode;
} SSL_SESSION_ASN1; } SSL_SESSION_ASN1;
ASN1_SEQUENCE(SSL_SESSION_ASN1) = { ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
@ -71,7 +72,8 @@ ASN1_SEQUENCE(SSL_SESSION_ASN1) = {
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_tick_age_add, ZUINT32, 14), ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_tick_age_add, ZUINT32, 14),
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_early_data, ZUINT32, 15), ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, max_early_data, ZUINT32, 15),
ASN1_EXP_OPT(SSL_SESSION_ASN1, alpn_selected, ASN1_OCTET_STRING, 16), ASN1_EXP_OPT(SSL_SESSION_ASN1, alpn_selected, ASN1_OCTET_STRING, 16),
ASN1_EXP_OPT(SSL_SESSION_ASN1, tick_nonce, ASN1_OCTET_STRING, 17) ASN1_EXP_OPT(SSL_SESSION_ASN1, tick_nonce, ASN1_OCTET_STRING, 17),
ASN1_EXP_OPT_EMBED(SSL_SESSION_ASN1, tlsext_max_fragment_len_mode, ZUINT32, 18)
} static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1) } static_ASN1_SEQUENCE_END(SSL_SESSION_ASN1)
IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1) IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(SSL_SESSION_ASN1)
@ -196,6 +198,8 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
ssl_session_oinit(&as.tick_nonce, &tick_nonce, ssl_session_oinit(&as.tick_nonce, &tick_nonce,
in->ext.tick_nonce, in->ext.tick_nonce_len); in->ext.tick_nonce, in->ext.tick_nonce_len);
as.tlsext_max_fragment_len_mode = in->ext.max_fragment_len_mode;
return i2d_SSL_SESSION_ASN1(&as, pp); return i2d_SSL_SESSION_ASN1(&as, pp);
} }
@ -370,6 +374,8 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
ret->ext.tick_nonce_len = 0; ret->ext.tick_nonce_len = 0;
} }
ret->ext.max_fragment_len_mode = as->tlsext_max_fragment_len_mode;
M_ASN1_free_of(as, SSL_SESSION_ASN1); M_ASN1_free_of(as, SSL_SESSION_ASN1);
if ((a != NULL) && (*a == NULL)) if ((a != NULL) && (*a == NULL))

View file

@ -176,6 +176,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
"SSL_CTX_set_session_id_context"}, "SSL_CTX_set_session_id_context"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_SSL_VERSION, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_SSL_VERSION, 0),
"SSL_CTX_set_ssl_version"}, "SSL_CTX_set_ssl_version"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH, 0),
"SSL_CTX_set_tlsext_max_fragment_length"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE, 0),
"SSL_CTX_use_certificate"}, "SSL_CTX_use_certificate"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1, 0),
@ -268,6 +270,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
"SSL_set_session_id_context"}, "SSL_set_session_id_context"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION_TICKET_EXT, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_SESSION_TICKET_EXT, 0),
"SSL_set_session_ticket_ext"}, "SSL_set_session_ticket_ext"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH, 0),
"SSL_set_tlsext_max_fragment_length"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_WFD, 0), "SSL_set_wfd"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SET_WFD, 0), "SSL_set_wfd"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SHUTDOWN, 0), "SSL_shutdown"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SHUTDOWN, 0), "SSL_shutdown"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SRP_CTX_INIT, 0), "SSL_SRP_CTX_init"}, {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SRP_CTX_INIT, 0), "SSL_SRP_CTX_init"},
@ -377,6 +381,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE, 0), ""}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_KEY_EXCHANGE, 0), ""},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, 0),
"tls_construct_ctos_key_share"}, "tls_construct_ctos_key_share"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, 0),
"tls_construct_ctos_maxfragmentlen"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_NPN, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_NPN, 0),
"tls_construct_ctos_npn"}, "tls_construct_ctos_npn"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PADDING, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_CTOS_PADDING, 0),
@ -448,6 +454,8 @@ static const ERR_STRING_DATA SSL_str_functs[] = {
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE, 0), ""}, {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_KEY_EXCHANGE, 0), ""},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, 0),
"tls_construct_stoc_key_share"}, "tls_construct_stoc_key_share"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, 0),
"tls_construct_stoc_maxfragmentlen"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG, 0),
"tls_construct_stoc_next_proto_neg"}, "tls_construct_stoc_next_proto_neg"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_PSK, 0), {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_CONSTRUCT_STOC_PSK, 0),
@ -882,6 +890,8 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"srtp protection profile list too long"}, "srtp protection profile list too long"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE), {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE),
"srtp unknown protection profile"}, "srtp unknown protection profile"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH),
"ssl3 ext invalid max fragment length"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_SERVERNAME), {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_SERVERNAME),
"ssl3 ext invalid servername"}, "ssl3 ext invalid servername"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE), {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),

View file

@ -688,6 +688,8 @@ SSL *SSL_new(SSL_CTX *ctx)
goto err; goto err;
X509_VERIFY_PARAM_inherit(s->param, ctx->param); X509_VERIFY_PARAM_inherit(s->param, ctx->param);
s->quiet_shutdown = ctx->quiet_shutdown; s->quiet_shutdown = ctx->quiet_shutdown;
s->ext.max_fragment_len_mode = ctx->ext.max_fragment_len_mode;
s->max_send_fragment = ctx->max_send_fragment; s->max_send_fragment = ctx->max_send_fragment;
s->split_send_fragment = ctx->split_send_fragment; s->split_send_fragment = ctx->split_send_fragment;
s->max_pipelines = ctx->max_pipelines; s->max_pipelines = ctx->max_pipelines;
@ -5160,3 +5162,28 @@ int ssl_randbytes(SSL *s, unsigned char *rnd, size_t size)
} }
return RAND_bytes(rnd, (int)size); return RAND_bytes(rnd, (int)size);
} }
__owur unsigned int ssl_get_max_send_fragment(const SSL *ssl)
{
/* Return any active Max Fragment Len extension */
if (ssl->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session))
return GET_MAX_FRAGMENT_LENGTH(ssl->session);
/* return current SSL connection setting */
return ssl->max_send_fragment;
}
__owur unsigned int ssl_get_split_send_fragment(const SSL *ssl)
{
/* Return a value regarding an active Max Fragment Len extension */
if (ssl->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session)
&& ssl->split_send_fragment > GET_MAX_FRAGMENT_LENGTH(ssl->session))
return GET_MAX_FRAGMENT_LENGTH(ssl->session);
/* else limit |split_send_fragment| to current |max_send_fragment| */
if (ssl->split_send_fragment > ssl->max_send_fragment)
return ssl->max_send_fragment;
/* return current SSL connection setting */
return ssl->split_send_fragment;
}

View file

@ -357,6 +357,14 @@
# define SSL_CLIENT_USE_SIGALGS(s) \ # define SSL_CLIENT_USE_SIGALGS(s) \
SSL_CLIENT_USE_TLS1_2_CIPHERS(s) SSL_CLIENT_USE_TLS1_2_CIPHERS(s)
# define IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value) \
(((value) >= TLSEXT_max_fragment_length_512) && \
((value) <= TLSEXT_max_fragment_length_4096))
# define USE_MAX_FRAGMENT_LENGTH_EXT(session) \
IS_MAX_FRAGMENT_LENGTH_EXT_VALID(session->ext.max_fragment_len_mode)
# define GET_MAX_FRAGMENT_LENGTH(session) \
(512U << (session->ext.max_fragment_len_mode - 1))
# define SSL_READ_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_READ) # define SSL_READ_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_READ)
# define SSL_WRITE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE) # define SSL_WRITE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE)
@ -558,6 +566,13 @@ struct ssl_session_st {
/* The ALPN protocol selected for this session */ /* The ALPN protocol selected for this session */
unsigned char *alpn_selected; unsigned char *alpn_selected;
size_t alpn_selected_len; size_t alpn_selected_len;
/*
* Maximum Fragment Length as per RFC 4366.
* If this value does not contain RFC 4366 allowed values (1-4) then
* either the Maximum Fragment Length Negotiation failed or was not
* performed at all.
*/
uint8_t max_fragment_len_mode;
} ext; } ext;
# ifndef OPENSSL_NO_SRP # ifndef OPENSSL_NO_SRP
char *srp_username; char *srp_username;
@ -669,6 +684,7 @@ typedef struct {
typedef enum tlsext_index_en { typedef enum tlsext_index_en {
TLSEXT_IDX_renegotiate, TLSEXT_IDX_renegotiate,
TLSEXT_IDX_server_name, TLSEXT_IDX_server_name,
TLSEXT_IDX_max_fragment_length,
TLSEXT_IDX_srp, TLSEXT_IDX_srp,
TLSEXT_IDX_ec_point_formats, TLSEXT_IDX_ec_point_formats,
TLSEXT_IDX_supported_groups, TLSEXT_IDX_supported_groups,
@ -895,6 +911,8 @@ struct ssl_ctx_st {
void *status_arg; void *status_arg;
/* ext status type used for CSR extension (OCSP Stapling) */ /* ext status type used for CSR extension (OCSP Stapling) */
int status_type; int status_type;
/* RFC 4366 Maximum Fragment Length Negotiation */
uint8_t max_fragment_len_mode;
# ifndef OPENSSL_NO_EC # ifndef OPENSSL_NO_EC
/* EC extension values inherited by SSL structure */ /* EC extension values inherited by SSL structure */
@ -1244,6 +1262,16 @@ struct ssl_st {
/* May be sent by a server in HRR. Must be echoed back in ClientHello */ /* May be sent by a server in HRR. Must be echoed back in ClientHello */
unsigned char *tls13_cookie; unsigned char *tls13_cookie;
size_t tls13_cookie_len; size_t tls13_cookie_len;
/*
* Maximum Fragment Length as per RFC 4366.
* If this member contains one of the allowed values (1-4)
* then we should include Maximum Fragment Length Negotiation
* extension in Client Hello.
* Please note that value of this member does not have direct
* effect. The actual (binding) value is stored in SSL_SESSION,
* as this extension is optional on server side.
*/
uint8_t max_fragment_len_mode;
} ext; } ext;
/* /*
@ -2175,6 +2203,8 @@ __owur EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm);
__owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, __owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey,
int genmaster); int genmaster);
__owur EVP_PKEY *ssl_dh_to_pkey(DH *dh); __owur EVP_PKEY *ssl_dh_to_pkey(DH *dh);
__owur unsigned int ssl_get_max_send_fragment(const SSL *ssl);
__owur unsigned int ssl_get_split_send_fragment(const SSL *ssl);
__owur const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id); __owur const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id);
__owur const SSL_CIPHER *ssl3_get_cipher_by_std_name(const char *stdname); __owur const SSL_CIPHER *ssl3_get_cipher_by_std_name(const char *stdname);

View file

@ -55,6 +55,7 @@ static int init_srtp(SSL *s, unsigned int context);
#endif #endif
static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al); static int final_sig_algs(SSL *s, unsigned int context, int sent, int *al);
static int final_early_data(SSL *s, unsigned int context, int sent, int *al); static int final_early_data(SSL *s, unsigned int context, int sent, int *al);
static int final_maxfragmentlen(SSL *s, unsigned int context, int sent, int *al);
/* Structure to define a built-in extension */ /* Structure to define a built-in extension */
typedef struct extensions_definition_st { typedef struct extensions_definition_st {
@ -135,6 +136,14 @@ static const EXTENSION_DEFINITION ext_defs[] = {
tls_construct_stoc_server_name, tls_construct_ctos_server_name, tls_construct_stoc_server_name, tls_construct_ctos_server_name,
final_server_name final_server_name
}, },
{
TLSEXT_TYPE_max_fragment_length,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
NULL, tls_parse_ctos_maxfragmentlen, tls_parse_stoc_maxfragmentlen,
tls_construct_stoc_maxfragmentlen, tls_construct_ctos_maxfragmentlen,
final_maxfragmentlen
},
#ifndef OPENSSL_NO_SRP #ifndef OPENSSL_NO_SRP
{ {
TLSEXT_TYPE_srp, TLSEXT_TYPE_srp,
@ -1475,3 +1484,25 @@ static int final_early_data(SSL *s, unsigned int context, int sent, int *al)
return 1; return 1;
} }
static int final_maxfragmentlen(SSL *ssl, unsigned int context, int sent, int *al)
{
/*
* Session resumption on server-side with MFL extension active
* BUT MFL extension packet was not resent (i.e. sent == 0)
*/
if (ssl->server && ssl->hit && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session)
&& !sent ) {
*al = SSL_AD_MISSING_EXTENSION;
return 0;
}
/* Current SSL buffer is lower than requested MFL */
if (ssl->session && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session)
&& ssl->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(ssl->session))
/* trigger a larger buffer reallocation */
if (!ssl3_setup_buffers(ssl))
return 0;
return 1;
}

View file

@ -57,6 +57,31 @@ EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt,
return EXT_RETURN_SENT; return EXT_RETURN_SENT;
} }
/* Push a Max Fragment Len extension into ClientHello */
EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx, int *al)
{
if (s->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_DISABLED)
return EXT_RETURN_NOT_SENT;
/* Add Max Fragment Length extension if client enabled it. */
/*-
* 4 bytes for this extension type and extension length
* 1 byte for the Max Fragment Length code value.
*/
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
/* Sub-packet for Max Fragment Length extension (1 byte) */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode)
|| !WPACKET_close(pkt)) {
SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_SRP #ifndef OPENSSL_NO_SRP
EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al) X509 *x, size_t chainidx, int *al)
@ -1115,6 +1140,43 @@ int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
return 1; return 1;
} }
/* Parse the server's max fragment len extension packet */
int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al)
{
unsigned int value;
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
/* |value| should contains a valid max-fragment-length code. */
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
*al = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
/* Must be the same value as client-configured one who was sent to server */
/*-
* RFC 6066: if a client receives a maximum fragment length negotiation
* response that differs from the length it requested, ...
* It must abort with SSL_AD_ILLEGAL_PARAMETER alert
*/
if (value != s->ext.max_fragment_len_mode) {
*al = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
/*
* Maximum Fragment Length Negotiation succeeded.
* The negotiated Maximum Fragment Length is binding now.
*/
s->session->ext.max_fragment_len_mode = value;
return 1;
}
int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context, int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al) X509 *x, size_t chainidx, int *al)
{ {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved.
* *
* Licensed under the OpenSSL license (the "License"). You may not use * Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy * this file except in compliance with the License. You can obtain a copy
@ -489,6 +489,7 @@ int SSL_extension_supported(unsigned int ext_type)
#endif #endif
case TLSEXT_TYPE_padding: case TLSEXT_TYPE_padding:
case TLSEXT_TYPE_renegotiate: case TLSEXT_TYPE_renegotiate:
case TLSEXT_TYPE_max_fragment_length:
case TLSEXT_TYPE_server_name: case TLSEXT_TYPE_server_name:
case TLSEXT_TYPE_session_ticket: case TLSEXT_TYPE_session_ticket:
case TLSEXT_TYPE_signature_algorithms: case TLSEXT_TYPE_signature_algorithms:

View file

@ -139,6 +139,40 @@ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
return 1; return 1;
} }
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al)
{
unsigned int value;
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
/* Received |value| should be a valid max-fragment-length code. */
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
*al = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
/*
* RFC 6066: The negotiated length applies for the duration of the session
* including session resumptions.
* We should receive the same code as in resumed session !
*/
if (s->hit && s->session->ext.max_fragment_len_mode != value) {
*al = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
/*
* 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;
}
#ifndef OPENSSL_NO_SRP #ifndef OPENSSL_NO_SRP
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx, int *al) size_t chainidx, int *al)
@ -844,6 +878,29 @@ EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
return EXT_RETURN_SENT; return EXT_RETURN_SENT;
} }
/* Add/include the server's max fragment len extension into ServerHello */
EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx, int *al)
{
if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
return EXT_RETURN_NOT_SENT;
/*-
* 4 bytes for this extension type and extension length
* 1 byte for the Max Fragment Length code value.
*/
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode)
|| !WPACKET_close(pkt)) {
SSLerr(SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x, unsigned int context, X509 *x,

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
* *
* Licensed under the OpenSSL license (the "License"). You may not use * Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy * this file except in compliance with the License. You can obtain a copy
@ -187,6 +187,8 @@ int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al); X509 *x, size_t chainidx, int *al);
int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context, int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al); X509 *x, size_t chainidx, int *al);
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al);
#ifndef OPENSSL_NO_SRP #ifndef OPENSSL_NO_SRP
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x, int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx, int *al); size_t chainidx, int *al);
@ -237,6 +239,9 @@ EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt, EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x, unsigned int context, X509 *x,
size_t chainidx, int *al); size_t chainidx, int *al);
EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx, int *al);
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x, unsigned int context, X509 *x,
@ -287,6 +292,8 @@ EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, unsigned int con
X509 *x, size_t chainidx, int *al); X509 *x, size_t chainidx, int *al);
EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt, unsigned int context, EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al); X509 *x, size_t chainidx, int *al);
EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al);
#ifndef OPENSSL_NO_SRP #ifndef OPENSSL_NO_SRP
EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, X509 *x,
size_t chainidx, int *al); size_t chainidx, int *al);
@ -353,6 +360,8 @@ int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al); X509 *x, size_t chainidx, int *al);
int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context, int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al); X509 *x, size_t chainidx, int *al);
int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al);
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx, int *al); X509 *x, size_t chainidx, int *al);

View file

@ -2406,3 +2406,34 @@ int tls_choose_sigalg(SSL *s, int *al)
s->s3->tmp.sigalg = lu; s->s3->tmp.sigalg = lu;
return 1; return 1;
} }
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode)
{
if (mode != TLSEXT_max_fragment_length_DISABLED
&& !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
SSLerr(SSL_F_SSL_CTX_SET_TLSEXT_MAX_FRAGMENT_LENGTH,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
ctx->ext.max_fragment_len_mode = mode;
return 1;
}
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode)
{
if (mode != TLSEXT_max_fragment_length_DISABLED
&& !IS_MAX_FRAGMENT_LENGTH_EXT_VALID(mode)) {
SSLerr(SSL_F_SSL_SET_TLSEXT_MAX_FRAGMENT_LENGTH,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
ssl->ext.max_fragment_len_mode = mode;
return 1;
}
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session)
{
return session->ext.max_fragment_len_mode;
}

View file

@ -490,6 +490,17 @@ static int configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx,
break; break;
} }
switch (extra->client.max_fragment_len_mode) {
case TLSEXT_max_fragment_length_512:
case TLSEXT_max_fragment_length_1024:
case TLSEXT_max_fragment_length_2048:
case TLSEXT_max_fragment_length_4096:
case TLSEXT_max_fragment_length_DISABLED:
TEST_true(SSL_CTX_set_tlsext_max_fragment_length(
client_ctx, extra->client.max_fragment_len_mode));
break;
}
/* /*
* Link the two contexts for SNI purposes. * Link the two contexts for SNI purposes.
* Also do ClientHello callbacks here, as setting both ClientHello and SNI * Also do ClientHello callbacks here, as setting both ClientHello and SNI

View file

@ -1,5 +1,5 @@
#! /usr/bin/env perl #! /usr/bin/env perl
# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. # Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
# #
# Licensed under the OpenSSL license (the "License"). You may not use # Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy # this file except in compliance with the License. You can obtain a copy
@ -81,7 +81,7 @@ my %skip = (
# We could run some of these tests without TLS 1.2 if we had a per-test # We could run some of these tests without TLS 1.2 if we had a per-test
# disable instruction but that's a bizarre configuration not worth # disable instruction but that's a bizarre configuration not worth
# special-casing for. # special-casing for.
# We should review this once we have TLS 1.3. # TODO(TLS 1.3): We should review this once we have TLS 1.3.
"13-fragmentation.conf" => disabled("tls1_2"), "13-fragmentation.conf" => disabled("tls1_2"),
"14-curves.conf" => disabled("tls1_2") || $no_ec || $no_ec2m, "14-curves.conf" => disabled("tls1_2") || $no_ec || $no_ec2m,
"15-certstatus.conf" => $no_tls || $no_ocsp, "15-certstatus.conf" => $no_tls || $no_ocsp,

View file

@ -1,6 +1,6 @@
# Generated with generate_ssl_tests.pl # Generated with generate_ssl_tests.pl
num_tests = 16 num_tests = 22
test-0 = 0-one-fragment-minus-app-data test-0 = 0-one-fragment-minus-app-data
test-1 = 1-one-fragment-app-data test-1 = 1-one-fragment-app-data
@ -18,6 +18,12 @@ test-12 = 12-large-app-data-aes-sha1-multibuffer-odd-fragment
test-13 = 13-large-app-data-aes-sha2-multibuffer-odd-fragment test-13 = 13-large-app-data-aes-sha2-multibuffer-odd-fragment
test-14 = 14-small-app-data-aes-sha1-multibuffer test-14 = 14-small-app-data-aes-sha1-multibuffer
test-15 = 15-small-app-data-aes-sha2-multibuffer test-15 = 15-small-app-data-aes-sha2-multibuffer
test-16 = 16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled
test-17 = 17-Maximum Fragment Len extension equal FragmentSize to 2048
test-18 = 18-Maximum Fragment Len extension 512 lower than FragmentSize 1024
test-19 = 19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024
test-20 = 20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048
test-21 = 21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024
# =========================================================== # ===========================================================
[0-one-fragment-minus-app-data] [0-one-fragment-minus-app-data]
@ -401,3 +407,171 @@ ApplicationData = 4096
MaxFragmentSize = 4096 MaxFragmentSize = 4096
# ===========================================================
[16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled]
ssl_conf = 16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled-ssl
[16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled-ssl]
server = 16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled-server
client = 16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled-client
[16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled-client]
CipherString = DEFAULT
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-16]
ApplicationData = 3072
MaxFragmentSize = 16384
client = 16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled-client-extra
[16-Maximum Fragment Len extension set to 1024 w. FragmentSize disabled-client-extra]
MaxFragmentLenExt = 1024
# ===========================================================
[17-Maximum Fragment Len extension equal FragmentSize to 2048]
ssl_conf = 17-Maximum Fragment Len extension equal FragmentSize to 2048-ssl
[17-Maximum Fragment Len extension equal FragmentSize to 2048-ssl]
server = 17-Maximum Fragment Len extension equal FragmentSize to 2048-server
client = 17-Maximum Fragment Len extension equal FragmentSize to 2048-client
[17-Maximum Fragment Len extension equal FragmentSize to 2048-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[17-Maximum Fragment Len extension equal FragmentSize to 2048-client]
CipherString = DEFAULT
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-17]
ApplicationData = 3072
MaxFragmentSize = 2048
client = 17-Maximum Fragment Len extension equal FragmentSize to 2048-client-extra
[17-Maximum Fragment Len extension equal FragmentSize to 2048-client-extra]
MaxFragmentLenExt = 2048
# ===========================================================
[18-Maximum Fragment Len extension 512 lower than FragmentSize 1024]
ssl_conf = 18-Maximum Fragment Len extension 512 lower than FragmentSize 1024-ssl
[18-Maximum Fragment Len extension 512 lower than FragmentSize 1024-ssl]
server = 18-Maximum Fragment Len extension 512 lower than FragmentSize 1024-server
client = 18-Maximum Fragment Len extension 512 lower than FragmentSize 1024-client
[18-Maximum Fragment Len extension 512 lower than FragmentSize 1024-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[18-Maximum Fragment Len extension 512 lower than FragmentSize 1024-client]
CipherString = DEFAULT
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-18]
ApplicationData = 3072
MaxFragmentSize = 1024
client = 18-Maximum Fragment Len extension 512 lower than FragmentSize 1024-client-extra
[18-Maximum Fragment Len extension 512 lower than FragmentSize 1024-client-extra]
MaxFragmentLenExt = 512
# ===========================================================
[19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024]
ssl_conf = 19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024-ssl
[19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024-ssl]
server = 19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024-server
client = 19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024-client
[19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024-client]
CipherString = DEFAULT
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-19]
ApplicationData = 3072
MaxFragmentSize = 1024
client = 19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024-client-extra
[19-Maximum Fragment Len extension 1024 lower than FragmentSize 1024-client-extra]
MaxFragmentLenExt = 2048
# ===========================================================
[20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048]
ssl_conf = 20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048-ssl
[20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048-ssl]
server = 20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048-server
client = 20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048-client
[20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048-client]
CipherString = DEFAULT
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-20]
ApplicationData = 8196
MaxFragmentSize = 2048
client = 20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048-client-extra
[20-Maximum Fragment Len extension 4096 greater than FragmentSize 2048-client-extra]
MaxFragmentLenExt = 4096
# ===========================================================
[21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024]
ssl_conf = 21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024-ssl
[21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024-ssl]
server = 21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024-server
client = 21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024-client
[21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
[21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024-client]
CipherString = DEFAULT
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
VerifyMode = Peer
[test-21]
ApplicationData = 3072
MaxFragmentSize = 1024
client = 21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024-client-extra
[21-Maximum Fragment Len extension 2048 greater than FragmentSize 1024-client-extra]
MaxFragmentLenExt = 2048

View file

@ -1,5 +1,5 @@
# -*- mode: perl; -*- # -*- mode: perl; -*-
# Copyright 2016-2016 The OpenSSL Project Authors. All Rights Reserved. # Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
# #
# Licensed under the OpenSSL license (the "License"). You may not use # Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy # this file except in compliance with the License. You can obtain a copy
@ -7,7 +7,7 @@
# https://www.openssl.org/source/license.html # https://www.openssl.org/source/license.html
## Test version negotiation ## Test packet fragmentation
use strict; use strict;
use warnings; use warnings;
@ -184,4 +184,85 @@ our @tests = (
MaxFragmentSize => 4 * 1024, MaxFragmentSize => 4 * 1024,
} }
}, },
############################################
# Default (Max) Fragment Size is 512.
# Default Application data size is 256.
{
name => "Maximum Fragment Len extension set to 1024 w. FragmentSize disabled",
server => { },
client => {
extra => {
MaxFragmentLenExt => 1024,
},
},
test => {
ApplicationData => 3072,
MaxFragmentSize => 16384,
}
},
{
name => "Maximum Fragment Len extension equal FragmentSize to 2048",
server => { },
client => {
extra => {
MaxFragmentLenExt => 2048,
},
},
test => {
ApplicationData => 3072,
MaxFragmentSize => 2048,
}
},
{
name => "Maximum Fragment Len extension 512 lower than FragmentSize 1024",
server => { },
client => {
extra => {
MaxFragmentLenExt => 512,
},
},
test => {
ApplicationData => 3072,
MaxFragmentSize => 1024,
}
},
{
name => "Maximum Fragment Len extension 1024 lower than FragmentSize 1024",
server => { },
client => {
extra => {
MaxFragmentLenExt => 2048,
},
},
test => {
ApplicationData => 3072,
MaxFragmentSize => 1024,
}
},
{
name => "Maximum Fragment Len extension 4096 greater than FragmentSize 2048",
server => { },
client => {
extra => {
MaxFragmentLenExt => 4096,
},
},
test => {
ApplicationData => 8196,
MaxFragmentSize => 2048,
}
},
{
name => "Maximum Fragment Len extension 2048 greater than FragmentSize 1024",
server => { },
client => {
extra => {
MaxFragmentLenExt => 2048,
},
},
test => {
ApplicationData => 3072,
MaxFragmentSize => 1024,
}
},
); );

View file

@ -472,6 +472,34 @@ IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, app_data_size)
IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, max_fragment_size) IMPLEMENT_SSL_TEST_INT_OPTION(SSL_TEST_CTX, test, max_fragment_size)
/* Maximum-Fragment-Length TLS extension mode */
static const test_enum ssl_max_fragment_len_mode[] = {
{"None", TLSEXT_max_fragment_length_DISABLED},
{ "512", TLSEXT_max_fragment_length_512},
{"1024", TLSEXT_max_fragment_length_1024},
{"2048", TLSEXT_max_fragment_length_2048},
{"4096", TLSEXT_max_fragment_length_4096}
};
__owur static int parse_max_fragment_len_mode(SSL_TEST_CLIENT_CONF *client_conf,
const char *value)
{
int ret_value;
if (!parse_enum(ssl_max_fragment_len_mode,
OSSL_NELEM(ssl_max_fragment_len_mode), &ret_value, value)) {
return 0;
}
client_conf->max_fragment_len_mode = ret_value;
return 1;
}
const char *ssl_max_fragment_len_name(int MFL_mode)
{
return enum_name(ssl_max_fragment_len_mode,
OSSL_NELEM(ssl_max_fragment_len_mode), MFL_mode);
}
/* Expected key and signature types */ /* Expected key and signature types */
@ -639,6 +667,7 @@ static const ssl_test_client_option ssl_test_client_options[] = {
{ "RenegotiateCiphers", &parse_client_reneg_ciphers}, { "RenegotiateCiphers", &parse_client_reneg_ciphers},
{ "SRPUser", &parse_client_srp_user }, { "SRPUser", &parse_client_srp_user },
{ "SRPPassword", &parse_client_srp_password }, { "SRPPassword", &parse_client_srp_password },
{ "MaxFragmentLenExt", &parse_max_fragment_len_mode },
}; };
/* Nested server options. */ /* Nested server options. */

View file

@ -97,6 +97,8 @@ typedef struct {
ssl_verify_callback_t verify_callback; ssl_verify_callback_t verify_callback;
/* One of a number of predefined server names use by the client */ /* One of a number of predefined server names use by the client */
ssl_servername_t servername; ssl_servername_t servername;
/* Maximum Fragment Length extension mode */
int max_fragment_len_mode;
/* Supported NPN and ALPN protocols. A comma-separated list. */ /* Supported NPN and ALPN protocols. A comma-separated list. */
char *npn_protocols; char *npn_protocols;
char *alpn_protocols; char *alpn_protocols;
@ -223,6 +225,7 @@ const char *ssl_test_method_name(ssl_test_method_t method);
const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode); const char *ssl_handshake_mode_name(ssl_handshake_mode_t mode);
const char *ssl_ct_validation_name(ssl_ct_validation_t mode); const char *ssl_ct_validation_name(ssl_ct_validation_t mode);
const char *ssl_certstatus_name(ssl_cert_status_t cert_status); const char *ssl_certstatus_name(ssl_cert_status_t cert_status);
const char *ssl_max_fragment_len_name(int MFL_mode);
/* /*
* Load the test case context from |conf|. * Load the test case context from |conf|.

View file

@ -40,7 +40,9 @@ static int clientconf_eq(SSL_TEST_CLIENT_CONF *conf1,
|| !TEST_int_eq(conf1->servername, conf2->servername) || !TEST_int_eq(conf1->servername, conf2->servername)
|| !TEST_str_eq(conf1->npn_protocols, conf2->npn_protocols) || !TEST_str_eq(conf1->npn_protocols, conf2->npn_protocols)
|| !TEST_str_eq(conf1->alpn_protocols, conf2->alpn_protocols) || !TEST_str_eq(conf1->alpn_protocols, conf2->alpn_protocols)
|| !TEST_int_eq(conf1->ct_validation, conf2->ct_validation)) || !TEST_int_eq(conf1->ct_validation, conf2->ct_validation)
|| !TEST_int_eq(conf1->max_fragment_len_mode,
conf2->max_fragment_len_mode))
return 0; return 0;
return 1; return 1;
} }
@ -178,6 +180,7 @@ static int test_good_configuration(void)
OPENSSL_strdup("foo,bar"); OPENSSL_strdup("foo,bar");
if (!TEST_ptr(fixture->expected_ctx->extra.client.npn_protocols)) if (!TEST_ptr(fixture->expected_ctx->extra.client.npn_protocols))
goto err; goto err;
fixture->expected_ctx->extra.client.max_fragment_len_mode = 0;
fixture->expected_ctx->extra.server.servername_callback = fixture->expected_ctx->extra.server.servername_callback =
SSL_TEST_SERVERNAME_IGNORE_MISMATCH; SSL_TEST_SERVERNAME_IGNORE_MISMATCH;
@ -215,6 +218,7 @@ static const char *bad_configurations[] = {
"ssltest_unknown_handshake_mode", "ssltest_unknown_handshake_mode",
"ssltest_unknown_resumption_expected", "ssltest_unknown_resumption_expected",
"ssltest_unknown_ct_validation", "ssltest_unknown_ct_validation",
"ssltest_invalid_max_fragment_len",
}; };
static int test_bad_configuration(int idx) static int test_bad_configuration(int idx)

View file

@ -92,3 +92,6 @@ client = ssltest_unknown_ct_validation_client
[ssltest_unknown_ct_validation_client] [ssltest_unknown_ct_validation_client]
CTCallback = Foo CTCallback = Foo
[ssltest_invalid_max_fragment_len]
MaxFragmentLenExt = 421

View file

@ -40,6 +40,7 @@ static X509 *ocspcert = NULL;
#endif #endif
#define NUM_EXTRA_CERTS 40 #define NUM_EXTRA_CERTS 40
#define CLIENT_VERSION_LEN 2
/* /*
* This structure is used to validate that the correct number of log messages * This structure is used to validate that the correct number of log messages
@ -3108,6 +3109,113 @@ static int test_ssl_clear(int idx)
return testresult; return testresult;
} }
/* Parse CH and retrieve any MFL extension value if present */
static int get_MFL_from_client_hello(BIO *bio, int *mfl_codemfl_code)
{
long len;
unsigned char *data;
PACKET pkt = {0}, pkt2 = {0}, pkt3 = {0};
unsigned int MFL_code = 0, type = 0;
if (!TEST_uint_gt( len = BIO_get_mem_data( bio, (char **) &data ), 0 ) )
goto end;
if (!TEST_true( PACKET_buf_init( &pkt, data, len ) )
/* Skip the record header */
|| !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH)
/* Skip the handshake message header */
|| !TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH))
/* Skip client version and random */
|| !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN
+ SSL3_RANDOM_SIZE))
/* Skip session id */
|| !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
/* Skip ciphers */
|| !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2))
/* Skip compression */
|| !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
/* Extensions len */
|| !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2)))
goto end;
/* Loop through all extensions */
while (PACKET_remaining(&pkt2)) {
if (!TEST_true(PACKET_get_net_2(&pkt2, &type))
|| !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3)))
goto end;
if (type == TLSEXT_TYPE_max_fragment_length) {
if (!TEST_uint_ne(PACKET_remaining(&pkt3), 0)
|| !TEST_true(PACKET_get_1(&pkt3, &MFL_code)))
goto end;
*mfl_codemfl_code = MFL_code;
return 1;
}
}
end:
return 0;
}
/* Maximum-Fragment-Length TLS extension mode to test */
static const unsigned char max_fragment_len_test[] = {
TLSEXT_max_fragment_length_512,
TLSEXT_max_fragment_length_1024,
TLSEXT_max_fragment_length_2048,
TLSEXT_max_fragment_length_4096
};
static int test_max_fragment_len_ext(int idx_tst)
{
SSL_CTX *ctx;
SSL *con = NULL;
int testresult = 0, MFL_mode = 0;
BIO *rbio, *wbio;
ctx = SSL_CTX_new(TLS_method());
if (!TEST_ptr(ctx))
goto end;
if (!TEST_true(SSL_CTX_set_tlsext_max_fragment_length(
ctx, max_fragment_len_test[idx_tst])))
goto end;
con = SSL_new(ctx);
if (!TEST_ptr(con))
goto end;
rbio = BIO_new(BIO_s_mem());
wbio = BIO_new(BIO_s_mem());
if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
BIO_free(rbio);
BIO_free(wbio);
goto end;
}
SSL_set_bio(con, rbio, wbio);
SSL_set_connect_state(con);
if (!TEST_int_le(SSL_connect(con), 0)) {
/* This shouldn't succeed because we don't have a server! */
goto end;
}
if (!TEST_true(get_MFL_from_client_hello(wbio, &MFL_mode)))
/* no MFL in client hello */
goto end;
if (!TEST_true(max_fragment_len_test[idx_tst] == MFL_mode))
goto end;
testresult = 1;
end:
SSL_free(con);
SSL_CTX_free(ctx);
return testresult;
}
int setup_tests(void) int setup_tests(void)
{ {
if (!TEST_ptr(cert = test_get_argument(0)) if (!TEST_ptr(cert = test_get_argument(0))
@ -3159,6 +3267,7 @@ int setup_tests(void)
ADD_ALL_TESTS(test_serverinfo, 8); ADD_ALL_TESTS(test_serverinfo, 8);
ADD_ALL_TESTS(test_export_key_mat, 4); ADD_ALL_TESTS(test_export_key_mat, 4);
ADD_ALL_TESTS(test_ssl_clear, 2); ADD_ALL_TESTS(test_ssl_clear, 2);
ADD_ALL_TESTS(test_max_fragment_len_ext, OSSL_NELEM(max_fragment_len_test));
return 1; return 1;
} }

View file

@ -470,3 +470,6 @@ SSL_SESSION_set1_alpn_selected 470 1_1_1 EXIST::FUNCTION:
SSL_SESSION_set1_hostname 471 1_1_1 EXIST::FUNCTION: SSL_SESSION_set1_hostname 471 1_1_1 EXIST::FUNCTION:
SSL_SESSION_get0_alpn_selected 472 1_1_1 EXIST::FUNCTION: SSL_SESSION_get0_alpn_selected 472 1_1_1 EXIST::FUNCTION:
DTLS_set_timer_cb 473 1_1_1 EXIST::FUNCTION: DTLS_set_timer_cb 473 1_1_1 EXIST::FUNCTION:
SSL_CTX_set_tlsext_max_fragment_length 474 1_1_1 EXIST::FUNCTION:
SSL_set_tlsext_max_fragment_length 475 1_1_1 EXIST::FUNCTION:
SSL_SESSION_get_max_fragment_length 476 1_1_1 EXIST::FUNCTION:

View file

@ -63,6 +63,7 @@ my %message_type = (
use constant { use constant {
EXT_SERVER_NAME => 0, EXT_SERVER_NAME => 0,
EXT_MAX_FRAGMENT_LENGTH => 1,
EXT_STATUS_REQUEST => 5, EXT_STATUS_REQUEST => 5,
EXT_SUPPORTED_GROUPS => 10, EXT_SUPPORTED_GROUPS => 10,
EXT_EC_POINT_FORMATS => 11, EXT_EC_POINT_FORMATS => 11,