mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-12-23 17:55:37 +00:00
Merge branch 'maximum-fragment-length' into development
This commit is contained in:
commit
a7eaba5ef9
|
@ -117,6 +117,15 @@
|
||||||
#define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */
|
#define SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */
|
||||||
#define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */
|
#define SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */
|
||||||
|
|
||||||
|
/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c
|
||||||
|
* NONE must be zero so that memset()ing structure to zero works */
|
||||||
|
#define SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */
|
||||||
|
#define SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */
|
||||||
|
#define SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */
|
||||||
|
#define SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */
|
||||||
|
#define SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */
|
||||||
|
#define SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */
|
||||||
|
|
||||||
#define SSL_IS_CLIENT 0
|
#define SSL_IS_CLIENT 0
|
||||||
#define SSL_IS_SERVER 1
|
#define SSL_IS_SERVER 1
|
||||||
#define SSL_COMPRESS_NULL 0
|
#define SSL_COMPRESS_NULL 0
|
||||||
|
@ -240,6 +249,8 @@
|
||||||
#define TLS_EXT_SERVERNAME 0
|
#define TLS_EXT_SERVERNAME 0
|
||||||
#define TLS_EXT_SERVERNAME_HOSTNAME 0
|
#define TLS_EXT_SERVERNAME_HOSTNAME 0
|
||||||
|
|
||||||
|
#define TLS_EXT_MAX_FRAGMENT_LENGTH 1
|
||||||
|
|
||||||
#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10
|
#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10
|
||||||
#define TLS_EXT_SUPPORTED_POINT_FORMATS 11
|
#define TLS_EXT_SUPPORTED_POINT_FORMATS 11
|
||||||
|
|
||||||
|
@ -320,6 +331,8 @@ struct _ssl_session
|
||||||
#if defined(POLARSSL_X509_PARSE_C)
|
#if defined(POLARSSL_X509_PARSE_C)
|
||||||
x509_cert *peer_cert; /*!< peer X.509 cert chain */
|
x509_cert *peer_cert; /*!< peer X.509 cert chain */
|
||||||
#endif /* POLARSSL_X509_PARSE_C */
|
#endif /* POLARSSL_X509_PARSE_C */
|
||||||
|
|
||||||
|
unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -498,6 +511,8 @@ struct _ssl_context
|
||||||
size_t out_msglen; /*!< record header: message length */
|
size_t out_msglen; /*!< record header: message length */
|
||||||
size_t out_left; /*!< amount of data not yet written */
|
size_t out_left; /*!< amount of data not yet written */
|
||||||
|
|
||||||
|
unsigned char mfl_code; /*!< MaxFragmentLength chosen by us */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PKI layer
|
* PKI layer
|
||||||
*/
|
*/
|
||||||
|
@ -944,6 +959,23 @@ void ssl_set_max_version( ssl_context *ssl, int major, int minor );
|
||||||
*/
|
*/
|
||||||
void ssl_set_min_version( ssl_context *ssl, int major, int minor );
|
void ssl_set_min_version( ssl_context *ssl, int major, int minor );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set the maximum fragment length to emit and/or negotiate
|
||||||
|
* (Default: SSL_MAX_CONTENT_LEN, usually 2^14 bytes)
|
||||||
|
* (Server: set maximum fragment length to emit,
|
||||||
|
* usually negotiated by the client during handshake
|
||||||
|
* (Client: set maximum fragment length to emit *and*
|
||||||
|
* negotiate with the server during handshake)
|
||||||
|
*
|
||||||
|
* \param ssl SSL context
|
||||||
|
* \param mfl Code for maximum fragment length (allowed values:
|
||||||
|
* SSL_MAX_FRAG_LEN_512, SSL_MAX_FRAG_LEN_1024,
|
||||||
|
* SSL_MAX_FRAG_LEN_2048, SSL_MAX_FRAG_LEN_4096)
|
||||||
|
*
|
||||||
|
* \return O if successful or POLARSSL_ERR_SSL_BAD_INPUT_DATA
|
||||||
|
*/
|
||||||
|
int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Enable / Disable renegotiation support for connection when
|
* \brief Enable / Disable renegotiation support for connection when
|
||||||
* initiated by peer
|
* initiated by peer
|
||||||
|
|
|
@ -269,6 +269,30 @@ static void ssl_write_supported_point_formats_ext( ssl_context *ssl,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void ssl_write_max_fragment_length_ext( ssl_context *ssl,
|
||||||
|
unsigned char *buf,
|
||||||
|
size_t *olen )
|
||||||
|
{
|
||||||
|
unsigned char *p = buf;
|
||||||
|
|
||||||
|
if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE ) {
|
||||||
|
*olen = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) );
|
||||||
|
|
||||||
|
*p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
|
||||||
|
*p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF );
|
||||||
|
|
||||||
|
*p++ = 0x00;
|
||||||
|
*p++ = 1;
|
||||||
|
|
||||||
|
*p++ = ssl->mfl_code;
|
||||||
|
|
||||||
|
*olen = 5;
|
||||||
|
}
|
||||||
|
|
||||||
static int ssl_write_client_hello( ssl_context *ssl )
|
static int ssl_write_client_hello( ssl_context *ssl )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -436,6 +460,9 @@ static int ssl_write_client_hello( ssl_context *ssl )
|
||||||
ext_len += olen;
|
ext_len += olen;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
|
||||||
|
ext_len += olen;
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
|
SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d",
|
||||||
ext_len ) );
|
ext_len ) );
|
||||||
|
|
||||||
|
@ -461,7 +488,7 @@ static int ssl_write_client_hello( ssl_context *ssl )
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ssl_parse_renegotiation_info( ssl_context *ssl,
|
static int ssl_parse_renegotiation_info( ssl_context *ssl,
|
||||||
unsigned char *buf,
|
const unsigned char *buf,
|
||||||
size_t len )
|
size_t len )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -499,6 +526,23 @@ static int ssl_parse_renegotiation_info( ssl_context *ssl,
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
static int ssl_parse_max_fragment_length_ext( ssl_context *ssl,
|
||||||
|
const unsigned char *buf,
|
||||||
|
size_t len )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* server should use the extension only if we did,
|
||||||
|
* and if so the server's value should match ours (and len is always 1)
|
||||||
|
*/
|
||||||
|
if( ssl->mfl_code == SSL_MAX_FRAG_LEN_NONE ||
|
||||||
|
len != 1 ||
|
||||||
|
buf[0] != ssl->mfl_code )
|
||||||
|
{
|
||||||
|
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
static int ssl_parse_server_hello( ssl_context *ssl )
|
static int ssl_parse_server_hello( ssl_context *ssl )
|
||||||
{
|
{
|
||||||
|
@ -690,6 +734,8 @@ static int ssl_parse_server_hello( ssl_context *ssl )
|
||||||
|
|
||||||
ext = buf + 44 + n;
|
ext = buf + 44 + n;
|
||||||
|
|
||||||
|
SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) );
|
||||||
|
|
||||||
while( ext_len )
|
while( ext_len )
|
||||||
{
|
{
|
||||||
unsigned int ext_id = ( ( ext[0] << 8 )
|
unsigned int ext_id = ( ( ext[0] << 8 )
|
||||||
|
@ -714,6 +760,17 @@ static int ssl_parse_server_hello( ssl_context *ssl )
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TLS_EXT_MAX_FRAGMENT_LENGTH:
|
||||||
|
SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) );
|
||||||
|
|
||||||
|
if( ( ret = ssl_parse_max_fragment_length_ext( ssl,
|
||||||
|
ext + 4, ext_size ) ) != 0 )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
|
SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
|
||||||
ext_id ) );
|
ext_id ) );
|
||||||
|
|
|
@ -291,6 +291,21 @@ static int ssl_parse_supported_point_formats( ssl_context *ssl,
|
||||||
}
|
}
|
||||||
#endif /* POLARSSL_ECP_C */
|
#endif /* POLARSSL_ECP_C */
|
||||||
|
|
||||||
|
static int ssl_parse_max_fragment_length_ext( ssl_context *ssl,
|
||||||
|
const unsigned char *buf,
|
||||||
|
size_t len )
|
||||||
|
{
|
||||||
|
if( len != 1 || buf[0] >= SSL_MAX_FRAG_LEN_INVALID )
|
||||||
|
{
|
||||||
|
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
||||||
|
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl->session_negotiate->mfl_code = buf[0];
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
|
#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
|
||||||
static int ssl_parse_client_hello_v2( ssl_context *ssl )
|
static int ssl_parse_client_hello_v2( ssl_context *ssl )
|
||||||
{
|
{
|
||||||
|
@ -825,6 +840,14 @@ static int ssl_parse_client_hello( ssl_context *ssl )
|
||||||
break;
|
break;
|
||||||
#endif /* POLARSSL_ECP_C */
|
#endif /* POLARSSL_ECP_C */
|
||||||
|
|
||||||
|
case TLS_EXT_MAX_FRAGMENT_LENGTH:
|
||||||
|
SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) );
|
||||||
|
|
||||||
|
ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size );
|
||||||
|
if( ret != 0 )
|
||||||
|
return( ret );
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
|
SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
|
||||||
ext_id ) );
|
ext_id ) );
|
||||||
|
@ -934,13 +957,67 @@ have_ciphersuite:
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ssl_write_renegotiation_ext( ssl_context *ssl,
|
||||||
|
unsigned char *buf,
|
||||||
|
size_t *olen )
|
||||||
|
{
|
||||||
|
unsigned char *p = buf;
|
||||||
|
|
||||||
|
if( ssl->secure_renegotiation != SSL_SECURE_RENEGOTIATION )
|
||||||
|
{
|
||||||
|
*olen = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) );
|
||||||
|
|
||||||
|
*p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
|
||||||
|
*p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF );
|
||||||
|
|
||||||
|
*p++ = 0x00;
|
||||||
|
*p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF;
|
||||||
|
*p++ = ssl->verify_data_len * 2 & 0xFF;
|
||||||
|
|
||||||
|
memcpy( p, ssl->peer_verify_data, ssl->verify_data_len );
|
||||||
|
p += ssl->verify_data_len;
|
||||||
|
memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
|
||||||
|
p += ssl->verify_data_len;
|
||||||
|
|
||||||
|
*olen = 5 + ssl->verify_data_len * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ssl_write_max_fragment_length_ext( ssl_context *ssl,
|
||||||
|
unsigned char *buf,
|
||||||
|
size_t *olen )
|
||||||
|
{
|
||||||
|
unsigned char *p = buf;
|
||||||
|
|
||||||
|
if( ssl->session_negotiate->mfl_code == SSL_MAX_FRAG_LEN_NONE )
|
||||||
|
{
|
||||||
|
*olen = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) );
|
||||||
|
|
||||||
|
*p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF );
|
||||||
|
*p++ = (unsigned char)( ( TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF );
|
||||||
|
|
||||||
|
*p++ = 0x00;
|
||||||
|
*p++ = 1;
|
||||||
|
|
||||||
|
*p++ = ssl->session_negotiate->mfl_code;
|
||||||
|
|
||||||
|
*olen = 5;
|
||||||
|
}
|
||||||
|
|
||||||
static int ssl_write_server_hello( ssl_context *ssl )
|
static int ssl_write_server_hello( ssl_context *ssl )
|
||||||
{
|
{
|
||||||
#if defined(POLARSSL_HAVE_TIME)
|
#if defined(POLARSSL_HAVE_TIME)
|
||||||
time_t t;
|
time_t t;
|
||||||
#endif
|
#endif
|
||||||
int ret, n;
|
int ret, n;
|
||||||
size_t ext_len = 0;
|
size_t olen, ext_len = 0;
|
||||||
unsigned char *buf, *p;
|
unsigned char *buf, *p;
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
|
SSL_DEBUG_MSG( 2, ( "=> write server hello" ) );
|
||||||
|
@ -986,10 +1063,12 @@ static int ssl_write_server_hello( ssl_context *ssl )
|
||||||
SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
|
SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 38 . 38 session id length
|
* 38 . 38 session id length
|
||||||
* 39 . 38+n session id
|
* 39 . 38+n session id
|
||||||
* 39+n . 40+n chosen ciphersuite
|
* 39+n . 40+n chosen ciphersuite
|
||||||
* 41+n . 41+n chosen compression alg.
|
* 41+n . 41+n chosen compression alg.
|
||||||
|
* 42+n . 43+n extensions length
|
||||||
|
* 44+n . 43+n+m extensions
|
||||||
*/
|
*/
|
||||||
ssl->session_negotiate->length = n = 32;
|
ssl->session_negotiate->length = n = 32;
|
||||||
*p++ = (unsigned char) ssl->session_negotiate->length;
|
*p++ = (unsigned char) ssl->session_negotiate->length;
|
||||||
|
@ -1040,34 +1119,20 @@ static int ssl_write_server_hello( ssl_context *ssl )
|
||||||
SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d",
|
SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d",
|
||||||
ssl->session_negotiate->compression ) );
|
ssl->session_negotiate->compression ) );
|
||||||
|
|
||||||
if( ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION )
|
/*
|
||||||
{
|
* First write extensions, then the total length
|
||||||
SSL_DEBUG_MSG( 3, ( "server hello, prepping for secure renegotiation extension" ) );
|
*/
|
||||||
ext_len += 5 + ssl->verify_data_len * 2;
|
ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen );
|
||||||
|
ext_len += olen;
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d",
|
ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen );
|
||||||
ext_len ) );
|
ext_len += olen;
|
||||||
|
|
||||||
*p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
|
SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) );
|
||||||
*p++ = (unsigned char)( ( ext_len ) & 0xFF );
|
|
||||||
|
|
||||||
/*
|
*p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
|
||||||
* Secure renegotiation
|
*p++ = (unsigned char)( ( ext_len ) & 0xFF );
|
||||||
*/
|
p += ext_len;
|
||||||
SSL_DEBUG_MSG( 3, ( "client hello, secure renegotiation extension" ) );
|
|
||||||
|
|
||||||
*p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF );
|
|
||||||
*p++ = (unsigned char)( ( TLS_EXT_RENEGOTIATION_INFO ) & 0xFF );
|
|
||||||
|
|
||||||
*p++ = 0x00;
|
|
||||||
*p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF;
|
|
||||||
*p++ = ssl->verify_data_len * 2 & 0xFF;
|
|
||||||
|
|
||||||
memcpy( p, ssl->peer_verify_data, ssl->verify_data_len );
|
|
||||||
p += ssl->verify_data_len;
|
|
||||||
memcpy( p, ssl->own_verify_data, ssl->verify_data_len );
|
|
||||||
p += ssl->verify_data_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssl->out_msglen = p - buf;
|
ssl->out_msglen = p - buf;
|
||||||
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
|
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
|
||||||
|
|
|
@ -59,6 +59,23 @@
|
||||||
#define strcasecmp _stricmp
|
#define strcasecmp _stricmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert max_fragment_length codes to length.
|
||||||
|
* RFC 6066 says:
|
||||||
|
* enum{
|
||||||
|
* 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255)
|
||||||
|
* } MaxFragmentLength;
|
||||||
|
* and we add 0 -> extension unused
|
||||||
|
*/
|
||||||
|
static unsigned int mfl_code_to_length[SSL_MAX_FRAG_LEN_INVALID] =
|
||||||
|
{
|
||||||
|
SSL_MAX_CONTENT_LEN, /* SSL_MAX_FRAG_LEN_NONE */
|
||||||
|
512, /* SSL_MAX_FRAG_LEN_512 */
|
||||||
|
1024, /* SSL_MAX_FRAG_LEN_1024 */
|
||||||
|
2048, /* SSL_MAX_FRAG_LEN_2048 */
|
||||||
|
4096, /* SSL_MAX_FRAG_LEN_4096 */
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
|
#if defined(POLARSSL_SSL_HW_RECORD_ACCEL)
|
||||||
int (*ssl_hw_record_init)(ssl_context *ssl,
|
int (*ssl_hw_record_init)(ssl_context *ssl,
|
||||||
const unsigned char *key_enc, const unsigned char *key_dec,
|
const unsigned char *key_enc, const unsigned char *key_dec,
|
||||||
|
@ -3111,6 +3128,19 @@ void ssl_set_min_version( ssl_context *ssl, int major, int minor )
|
||||||
ssl->min_minor_ver = minor;
|
ssl->min_minor_ver = minor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code )
|
||||||
|
{
|
||||||
|
if( mfl_code >= sizeof( mfl_code_to_length ) ||
|
||||||
|
mfl_code_to_length[mfl_code] > SSL_MAX_CONTENT_LEN )
|
||||||
|
{
|
||||||
|
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
||||||
|
}
|
||||||
|
|
||||||
|
ssl->mfl_code = mfl_code;
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
void ssl_set_renegotiation( ssl_context *ssl, int renegotiation )
|
void ssl_set_renegotiation( ssl_context *ssl, int renegotiation )
|
||||||
{
|
{
|
||||||
ssl->disable_renegotiation = renegotiation;
|
ssl->disable_renegotiation = renegotiation;
|
||||||
|
@ -3372,6 +3402,7 @@ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
unsigned int max_len;
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 2, ( "=> write" ) );
|
SSL_DEBUG_MSG( 2, ( "=> write" ) );
|
||||||
|
|
||||||
|
@ -3384,8 +3415,21 @@ int ssl_write( ssl_context *ssl, const unsigned char *buf, size_t len )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n = ( len < SSL_MAX_CONTENT_LEN )
|
/*
|
||||||
? len : SSL_MAX_CONTENT_LEN;
|
* Assume mfl_code is correct since it was checked when set
|
||||||
|
*/
|
||||||
|
max_len = mfl_code_to_length[ssl->mfl_code];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if a smaller max length was negociated
|
||||||
|
*/
|
||||||
|
if( ssl->session_out != NULL &&
|
||||||
|
mfl_code_to_length[ssl->session_out->mfl_code] < max_len )
|
||||||
|
{
|
||||||
|
max_len = mfl_code_to_length[ssl->session_out->mfl_code];
|
||||||
|
}
|
||||||
|
|
||||||
|
n = ( len < max_len) ? len : max_len;
|
||||||
|
|
||||||
if( ssl->out_left != 0 )
|
if( ssl->out_left != 0 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,8 +57,20 @@
|
||||||
#define DFL_MIN_VERSION -1
|
#define DFL_MIN_VERSION -1
|
||||||
#define DFL_MAX_VERSION -1
|
#define DFL_MAX_VERSION -1
|
||||||
#define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL
|
#define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL
|
||||||
|
#define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE
|
||||||
|
|
||||||
#define GET_REQUEST "GET %s HTTP/1.0\r\n\r\n"
|
#define LONG_HEADER "User-agent: blah-blah-blah-blah-blah-blah-blah-blah-" \
|
||||||
|
"-01--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \
|
||||||
|
"-02--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \
|
||||||
|
"-03--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \
|
||||||
|
"-04--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \
|
||||||
|
"-05--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \
|
||||||
|
"-06--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-" \
|
||||||
|
"-07--blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-END\r\n"
|
||||||
|
|
||||||
|
/* Uncomment LONG_HEADER in the definition of GET_REQUEST to test sending
|
||||||
|
* longer paquets (for fragmentation purposes) */
|
||||||
|
#define GET_REQUEST "GET %s HTTP/1.0\r\n" /* LONG_HEADER */ "\r\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* global options
|
* global options
|
||||||
|
@ -81,6 +93,7 @@ struct options
|
||||||
int min_version; /* minimum protocol version accepted */
|
int min_version; /* minimum protocol version accepted */
|
||||||
int max_version; /* maximum protocol version accepted */
|
int max_version; /* maximum protocol version accepted */
|
||||||
int auth_mode; /* verify mode for connection */
|
int auth_mode; /* verify mode for connection */
|
||||||
|
unsigned char mfl_code; /* code for maximum fragment length */
|
||||||
} opt;
|
} opt;
|
||||||
|
|
||||||
static void my_debug( void *ctx, int level, const char *str )
|
static void my_debug( void *ctx, int level, const char *str )
|
||||||
|
@ -176,6 +189,8 @@ static int my_verify( void *data, x509_cert *crt, int depth, int *flags )
|
||||||
" options: ssl3, tls1, tls1_1, tls1_2\n" \
|
" options: ssl3, tls1, tls1_1, tls1_2\n" \
|
||||||
" auth_mode=%%s default: \"optional\"\n" \
|
" auth_mode=%%s default: \"optional\"\n" \
|
||||||
" options: none, optional, required\n" \
|
" options: none, optional, required\n" \
|
||||||
|
" max_frag_len=%%d default: 16384 (tls default)" \
|
||||||
|
" options: 512, 1024, 2048, 4096" \
|
||||||
USAGE_PSK \
|
USAGE_PSK \
|
||||||
"\n" \
|
"\n" \
|
||||||
" force_ciphersuite=<name> default: all enabled\n"\
|
" force_ciphersuite=<name> default: all enabled\n"\
|
||||||
|
@ -197,7 +212,7 @@ int main( int argc, char *argv[] )
|
||||||
#else
|
#else
|
||||||
int main( int argc, char *argv[] )
|
int main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
int ret = 0, len, server_fd, i;
|
int ret = 0, len, server_fd, i, written, frags;
|
||||||
unsigned char buf[1024];
|
unsigned char buf[1024];
|
||||||
#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
|
#if defined(POLARSSL_KEY_EXCHANGE_PSK_ENABLED)
|
||||||
unsigned char psk[256];
|
unsigned char psk[256];
|
||||||
|
@ -265,6 +280,7 @@ int main( int argc, char *argv[] )
|
||||||
opt.min_version = DFL_MIN_VERSION;
|
opt.min_version = DFL_MIN_VERSION;
|
||||||
opt.max_version = DFL_MAX_VERSION;
|
opt.max_version = DFL_MAX_VERSION;
|
||||||
opt.auth_mode = DFL_AUTH_MODE;
|
opt.auth_mode = DFL_AUTH_MODE;
|
||||||
|
opt.mfl_code = DFL_MFL_CODE;
|
||||||
|
|
||||||
for( i = 1; i < argc; i++ )
|
for( i = 1; i < argc; i++ )
|
||||||
{
|
{
|
||||||
|
@ -387,6 +403,19 @@ int main( int argc, char *argv[] )
|
||||||
else
|
else
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
|
else if( strcmp( p, "max_frag_len" ) == 0 )
|
||||||
|
{
|
||||||
|
if( strcmp( q, "512" ) == 0 )
|
||||||
|
opt.mfl_code = SSL_MAX_FRAG_LEN_512;
|
||||||
|
else if( strcmp( q, "1024" ) == 0 )
|
||||||
|
opt.mfl_code = SSL_MAX_FRAG_LEN_1024;
|
||||||
|
else if( strcmp( q, "2048" ) == 0 )
|
||||||
|
opt.mfl_code = SSL_MAX_FRAG_LEN_2048;
|
||||||
|
else if( strcmp( q, "4096" ) == 0 )
|
||||||
|
opt.mfl_code = SSL_MAX_FRAG_LEN_4096;
|
||||||
|
else
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
|
@ -592,6 +621,8 @@ int main( int argc, char *argv[] )
|
||||||
ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
|
ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
|
||||||
ssl_set_authmode( &ssl, opt.auth_mode );
|
ssl_set_authmode( &ssl, opt.auth_mode );
|
||||||
|
|
||||||
|
ssl_set_max_frag_len( &ssl, opt.mfl_code );
|
||||||
|
|
||||||
ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
|
ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
|
||||||
ssl_set_dbg( &ssl, my_debug, stdout );
|
ssl_set_dbg( &ssl, my_debug, stdout );
|
||||||
ssl_set_bio( &ssl, net_recv, &server_fd,
|
ssl_set_bio( &ssl, net_recv, &server_fd,
|
||||||
|
@ -682,17 +713,20 @@ int main( int argc, char *argv[] )
|
||||||
|
|
||||||
len = sprintf( (char *) buf, GET_REQUEST, opt.request_page );
|
len = sprintf( (char *) buf, GET_REQUEST, opt.request_page );
|
||||||
|
|
||||||
while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
|
for( written = 0, frags = 0; written < len; written += ret, frags++ )
|
||||||
{
|
{
|
||||||
if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
|
while( ( ret = ssl_write( &ssl, buf + written, len - written ) ) <= 0 )
|
||||||
{
|
{
|
||||||
printf( " failed\n ! ssl_write returned -0x%x\n\n", -ret );
|
if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
|
||||||
goto exit;
|
{
|
||||||
|
printf( " failed\n ! ssl_write returned -0x%x\n\n", -ret );
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
len = ret;
|
buf[written] = '\0';
|
||||||
printf( " %d bytes written\n\n%s", len, (char *) buf );
|
printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 7. Read the HTTP response
|
* 7. Read the HTTP response
|
||||||
|
|
|
@ -68,11 +68,22 @@
|
||||||
#define DFL_MIN_VERSION -1
|
#define DFL_MIN_VERSION -1
|
||||||
#define DFL_MAX_VERSION -1
|
#define DFL_MAX_VERSION -1
|
||||||
#define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL
|
#define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL
|
||||||
|
#define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE
|
||||||
|
|
||||||
|
#define LONG_RESPONSE "<p>01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
|
||||||
|
"02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
|
||||||
|
"03-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
|
||||||
|
"04-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
|
||||||
|
"05-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
|
||||||
|
"06-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
|
||||||
|
"07-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah</p>\r\n"
|
||||||
|
|
||||||
|
/* Uncomment LONG_RESPONSE at the end of HTTP_RESPONSE to test sending longer
|
||||||
|
* packets (for fragmentation purposes) */
|
||||||
#define HTTP_RESPONSE \
|
#define HTTP_RESPONSE \
|
||||||
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
|
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
|
||||||
"<h2>PolarSSL Test Server</h2>\r\n" \
|
"<h2>PolarSSL Test Server</h2>\r\n" \
|
||||||
"<p>Successful connection using: %s</p>\r\n"
|
"<p>Successful connection using: %s</p>\r\n" // LONG_RESPONSE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* global options
|
* global options
|
||||||
|
@ -93,6 +104,7 @@ struct options
|
||||||
int min_version; /* minimum protocol version accepted */
|
int min_version; /* minimum protocol version accepted */
|
||||||
int max_version; /* maximum protocol version accepted */
|
int max_version; /* maximum protocol version accepted */
|
||||||
int auth_mode; /* verify mode for connection */
|
int auth_mode; /* verify mode for connection */
|
||||||
|
unsigned char mfl_code; /* code for maximum fragment length */
|
||||||
} opt;
|
} opt;
|
||||||
|
|
||||||
static void my_debug( void *ctx, int level, const char *str )
|
static void my_debug( void *ctx, int level, const char *str )
|
||||||
|
@ -147,6 +159,8 @@ static void my_debug( void *ctx, int level, const char *str )
|
||||||
" options: ssl3, tls1, tls1_1, tls1_2\n" \
|
" options: ssl3, tls1, tls1_1, tls1_2\n" \
|
||||||
" auth_mode=%%s default: \"optional\"\n" \
|
" auth_mode=%%s default: \"optional\"\n" \
|
||||||
" options: none, optional, required\n" \
|
" options: none, optional, required\n" \
|
||||||
|
" max_frag_len=%%d default: 16384 (tls default)" \
|
||||||
|
" options: 512, 1024, 2048, 4096" \
|
||||||
USAGE_PSK \
|
USAGE_PSK \
|
||||||
"\n" \
|
"\n" \
|
||||||
" force_ciphersuite=<name> default: all enabled\n"\
|
" force_ciphersuite=<name> default: all enabled\n"\
|
||||||
|
@ -168,7 +182,7 @@ int main( int argc, char *argv[] )
|
||||||
#else
|
#else
|
||||||
int main( int argc, char *argv[] )
|
int main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
int ret = 0, len;
|
int ret = 0, len, written, frags;
|
||||||
int listen_fd;
|
int listen_fd;
|
||||||
int client_fd = -1;
|
int client_fd = -1;
|
||||||
unsigned char buf[1024];
|
unsigned char buf[1024];
|
||||||
|
@ -250,6 +264,7 @@ int main( int argc, char *argv[] )
|
||||||
opt.min_version = DFL_MIN_VERSION;
|
opt.min_version = DFL_MIN_VERSION;
|
||||||
opt.max_version = DFL_MAX_VERSION;
|
opt.max_version = DFL_MAX_VERSION;
|
||||||
opt.auth_mode = DFL_AUTH_MODE;
|
opt.auth_mode = DFL_AUTH_MODE;
|
||||||
|
opt.mfl_code = DFL_MFL_CODE;
|
||||||
|
|
||||||
for( i = 1; i < argc; i++ )
|
for( i = 1; i < argc; i++ )
|
||||||
{
|
{
|
||||||
|
@ -368,6 +383,19 @@ int main( int argc, char *argv[] )
|
||||||
else
|
else
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
|
else if( strcmp( p, "max_frag_len" ) == 0 )
|
||||||
|
{
|
||||||
|
if( strcmp( q, "512" ) == 0 )
|
||||||
|
opt.mfl_code = SSL_MAX_FRAG_LEN_512;
|
||||||
|
else if( strcmp( q, "1024" ) == 0 )
|
||||||
|
opt.mfl_code = SSL_MAX_FRAG_LEN_1024;
|
||||||
|
else if( strcmp( q, "2048" ) == 0 )
|
||||||
|
opt.mfl_code = SSL_MAX_FRAG_LEN_2048;
|
||||||
|
else if( strcmp( q, "4096" ) == 0 )
|
||||||
|
opt.mfl_code = SSL_MAX_FRAG_LEN_4096;
|
||||||
|
else
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
|
@ -562,6 +590,8 @@ int main( int argc, char *argv[] )
|
||||||
ssl_set_endpoint( &ssl, SSL_IS_SERVER );
|
ssl_set_endpoint( &ssl, SSL_IS_SERVER );
|
||||||
ssl_set_authmode( &ssl, opt.auth_mode );
|
ssl_set_authmode( &ssl, opt.auth_mode );
|
||||||
|
|
||||||
|
ssl_set_max_frag_len( &ssl, opt.mfl_code );
|
||||||
|
|
||||||
ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
|
ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
|
||||||
ssl_set_dbg( &ssl, my_debug, stdout );
|
ssl_set_dbg( &ssl, my_debug, stdout );
|
||||||
|
|
||||||
|
@ -748,7 +778,7 @@ reset:
|
||||||
}
|
}
|
||||||
|
|
||||||
len = ret;
|
len = ret;
|
||||||
printf( " %d bytes read\n\n%s", len, (char *) buf );
|
printf( " %d bytes read\n\n%s\n", len, (char *) buf );
|
||||||
|
|
||||||
if( memcmp( buf, "SERVERQUIT", 10 ) == 0 )
|
if( memcmp( buf, "SERVERQUIT", 10 ) == 0 )
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -767,23 +797,26 @@ reset:
|
||||||
len = sprintf( (char *) buf, HTTP_RESPONSE,
|
len = sprintf( (char *) buf, HTTP_RESPONSE,
|
||||||
ssl_get_ciphersuite( &ssl ) );
|
ssl_get_ciphersuite( &ssl ) );
|
||||||
|
|
||||||
while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
|
for( written = 0, frags = 0; written < len; written += ret, frags++ )
|
||||||
{
|
{
|
||||||
if( ret == POLARSSL_ERR_NET_CONN_RESET )
|
while( ( ret = ssl_write( &ssl, buf + written, len - written ) ) <= 0 )
|
||||||
{
|
{
|
||||||
printf( " failed\n ! peer closed the connection\n\n" );
|
if( ret == POLARSSL_ERR_NET_CONN_RESET )
|
||||||
goto reset;
|
{
|
||||||
}
|
printf( " failed\n ! peer closed the connection\n\n" );
|
||||||
|
goto reset;
|
||||||
|
}
|
||||||
|
|
||||||
if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
|
if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
|
||||||
{
|
{
|
||||||
printf( " failed\n ! ssl_write returned %d\n\n", ret );
|
printf( " failed\n ! ssl_write returned %d\n\n", ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
len = ret;
|
buf[written] = '\0';
|
||||||
printf( " %d bytes written\n\n%s\n", len, (char *) buf );
|
printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf );
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto reset;
|
goto reset;
|
||||||
|
|
Loading…
Reference in a new issue