1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-29 11:41:15 +03:00

Merge branch 'mbedtls_ssl_get_key_exchange_md_ssl_tls-return_hashlen' into tls_async_server-2.9

Conflict resolution:
* ChangeLog: put the new entry from my branch in the proper place.
* include/mbedtls/error.h: counted high-level module error codes again.
* include/mbedtls/ssl.h: picked different numeric codes for the
  concurrently added errors; made the new error a full sentence per
  current standards.
* library/error.c: ran scripts/generate_errors.pl.
* library/ssl_srv.c:
    * ssl_prepare_server_key_exchange "DHE key exchanges": the conflict
      was due to style corrections in development
      (4cb1f4d49c) which I merged with
      my refactoring.
    * ssl_prepare_server_key_exchange "For key exchanges involving the
      server signing", first case, variable declarations: merged line
      by line:
        * dig_signed_len: added in async
        * signature_len: removed in async
        * hashlen: type changed to size_t in development
        * hash: size changed to MBEDTLS_MD_MAX_SIZE in async
        * ret: added in async
    * ssl_prepare_server_key_exchange "For key exchanges involving the
      server signing", first cae comment: the conflict was due to style
      corrections in development (4cb1f4d49c)
      which I merged with my comment changes made as part of refactoring
      the function.
    * ssl_prepare_server_key_exchange "Compute the hash to be signed" if
      `md_alg != MBEDTLS_MD_NONE`: conflict between
      ebd652fe2d
      "ssl_write_server_key_exchange: calculate hashlen explicitly" and
      46f5a3e9b4 "Check return codes from
      MD in ssl code". I took the code from commit
      ca1d742904 made on top of development
      which makes mbedtls_ssl_get_key_exchange_md_ssl_tls return the
      hash length.
* programs/ssl/ssl_server2.c: multiple conflicts between the introduction
  of MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS and new auxiliary functions and
  definitions for async support, and the introduction of idle().
    * definitions before main: concurrent additions, kept both.
    * main, just after `handshake:`: in the loop around
      mbedtls_ssl_handshake(), merge the addition of support for
      MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS and SSL_ASYNC_INJECT_ERROR_CANCEL
      with the addition of the idle() call.
    * main, if `opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM`: take the
      code from development and add a check for
      MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS.
    * main, loop around mbedtls_ssl_read() in the datagram case:
      take the code from development and add a check for
      MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS; revert to a do...while loop.
    * main, loop around mbedtls_ssl_write() in the datagram case:
      take the code from development and add a check for
      MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS; revert to a do...while loop.
This commit is contained in:
Gilles Peskine
2018-04-24 12:18:19 +02:00
345 changed files with 17923 additions and 5548 deletions

View File

@ -101,6 +101,7 @@ int main( void )
#define DFL_SERVER_PORT "4433"
#define DFL_DEBUG_LEVEL 0
#define DFL_NBIO 0
#define DFL_EVENT 0
#define DFL_READ_TIMEOUT 0
#define DFL_CA_FILE ""
#define DFL_CA_PATH ""
@ -347,6 +348,8 @@ int main( void )
" debug_level=%%d default: 0 (disabled)\n" \
" nbio=%%d default: 0 (blocking I/O)\n" \
" options: 1 (non-blocking), 2 (added delays)\n" \
" event=%%d default: 0 (loop)\n" \
" options: 1 (level-triggered, implies nbio=1),\n" \
" read_timeout=%%d default: 0 ms (no timeout)\n" \
"\n" \
USAGE_DTLS \
@ -416,6 +419,7 @@ struct options
const char *server_port; /* port on which the ssl service runs */
int debug_level; /* level of debugging */
int nbio; /* should I/O be blocking? */
int event; /* loop or event-driven IO? level or edge triggered? */
uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */
const char *ca_file; /* the file with the CA certificate(s) */
const char *ca_path; /* the path with the CA certificate(s) reside */
@ -1041,6 +1045,56 @@ static void ssl_async_cancel( void *connection_ctx_arg,
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE_C */
/*
* Wait for an event from the underlying transport or the timer
* (Used in event-driven IO mode).
*/
#if !defined(MBEDTLS_TIMING_C)
int idle( mbedtls_net_context *fd,
int idle_reason )
#else
int idle( mbedtls_net_context *fd,
mbedtls_timing_delay_context *timer,
int idle_reason )
#endif
{
int ret;
int poll_type = 0;
if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
poll_type = MBEDTLS_NET_POLL_WRITE;
else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
poll_type = MBEDTLS_NET_POLL_READ;
#if !defined(MBEDTLS_TIMING_C)
else
return( 0 );
#endif
while( 1 )
{
/* Check if timer has expired */
#if defined(MBEDTLS_TIMING_C)
if( timer != NULL &&
mbedtls_timing_get_delay( timer ) == 2 )
{
break;
}
#endif /* MBEDTLS_TIMING_C */
/* Check if underlying transport became available */
if( poll_type != 0 )
{
ret = mbedtls_net_poll( fd, poll_type, 0 );
if( ret < 0 )
return( ret );
if( ret == poll_type )
break;
}
}
return( 0 );
}
int main( int argc, char *argv[] )
{
int ret = 0, len, written, frags, exchanges_left;
@ -1176,6 +1230,7 @@ int main( int argc, char *argv[] )
opt.server_addr = DFL_SERVER_ADDR;
opt.server_port = DFL_SERVER_PORT;
opt.debug_level = DFL_DEBUG_LEVEL;
opt.event = DFL_EVENT;
opt.nbio = DFL_NBIO;
opt.read_timeout = DFL_READ_TIMEOUT;
opt.ca_file = DFL_CA_FILE;
@ -1258,6 +1313,12 @@ int main( int argc, char *argv[] )
if( opt.nbio < 0 || opt.nbio > 2 )
goto usage;
}
else if( strcmp( p, "event" ) == 0 )
{
opt.event = atoi( q );
if( opt.event < 0 || opt.event > 2 )
goto usage;
}
else if( strcmp( p, "read_timeout" ) == 0 )
opt.read_timeout = atoi( q );
else if( strcmp( p, "ca_file" ) == 0 )
@ -1318,16 +1379,23 @@ int main( int argc, char *argv[] )
opt.version_suites = q;
else if( strcmp( p, "renegotiation" ) == 0 )
{
opt.renegotiation = (atoi( q )) ? MBEDTLS_SSL_RENEGOTIATION_ENABLED :
MBEDTLS_SSL_RENEGOTIATION_DISABLED;
opt.renegotiation = (atoi( q )) ?
MBEDTLS_SSL_RENEGOTIATION_ENABLED :
MBEDTLS_SSL_RENEGOTIATION_DISABLED;
}
else if( strcmp( p, "allow_legacy" ) == 0 )
{
switch( atoi( q ) )
{
case -1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE; break;
case 0: opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; break;
case 1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION; break;
case -1:
opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE;
break;
case 0:
opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION;
break;
case 1:
opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION;
break;
default: goto usage;
}
}
@ -1484,8 +1552,12 @@ int main( int argc, char *argv[] )
{
switch( atoi( q ) )
{
case 0: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED; break;
case 1: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; break;
case 0:
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED;
break;
case 1:
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
break;
default: goto usage;
}
}
@ -1558,6 +1630,15 @@ int main( int argc, char *argv[] )
goto usage;
}
/* Event-driven IO is incompatible with the above custom
* receive and send functions, as the polling builds on
* refers to the underlying net_context. */
if( opt.event == 1 && opt.nbio != 1 )
{
mbedtls_printf( "Warning: event-driven IO mandates nbio=1 - overwrite\n" );
opt.nbio = 1;
}
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold( opt.debug_level );
#endif
@ -1565,19 +1646,20 @@ int main( int argc, char *argv[] )
if( opt.force_ciphersuite[0] > 0 )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
ciphersuite_info =
mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
if( opt.max_version != -1 &&
ciphersuite_info->min_minor_ver > opt.max_version )
{
mbedtls_printf("forced ciphersuite not allowed with this protocol version\n");
mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" );
ret = 2;
goto usage;
}
if( opt.min_version != -1 &&
ciphersuite_info->max_minor_ver < opt.min_version )
{
mbedtls_printf("forced ciphersuite not allowed with this protocol version\n");
mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" );
ret = 2;
goto usage;
}
@ -1756,11 +1838,12 @@ int main( int argc, char *argv[] )
fflush( stdout );
mbedtls_entropy_init( &entropy );
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers,
strlen( pers ) ) ) != 0 )
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
&entropy, (const unsigned char *) pers,
strlen( pers ) ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret );
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n",
-ret );
goto exit;
}
@ -1857,7 +1940,7 @@ int main( int argc, char *argv[] )
if( ( ret = mbedtls_pk_parse_keyfile( &pkey2, opt.key_file2, "" ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile(2) returned -0x%x\n\n",
-ret );
-ret );
goto exit;
}
}
@ -1875,8 +1958,7 @@ int main( int argc, char *argv[] )
strcmp( opt.key_file2, "none" ) != 0 )
{
#if !defined(MBEDTLS_CERTS_C)
mbedtls_printf( "Not certificated or key provided, and \n"
"MBEDTLS_CERTS_C not defined!\n" );
mbedtls_printf( "Not certificated or key provided, and \nMBEDTLS_CERTS_C not defined!\n" );
goto exit;
#else
#if defined(MBEDTLS_RSA_C)
@ -1884,14 +1966,16 @@ int main( int argc, char *argv[] )
(const unsigned char *) mbedtls_test_srv_crt_rsa,
mbedtls_test_srv_crt_rsa_len ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n",
-ret );
goto exit;
}
if( ( ret = mbedtls_pk_parse_key( &pkey,
(const unsigned char *) mbedtls_test_srv_key_rsa,
mbedtls_test_srv_key_rsa_len, NULL, 0 ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", -ret );
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n",
-ret );
goto exit;
}
key_cert_init = 2;
@ -1901,14 +1985,16 @@ int main( int argc, char *argv[] )
(const unsigned char *) mbedtls_test_srv_crt_ec,
mbedtls_test_srv_crt_ec_len ) ) != 0 )
{
mbedtls_printf( " failed\n ! x509_crt_parse2 returned -0x%x\n\n", -ret );
mbedtls_printf( " failed\n ! x509_crt_parse2 returned -0x%x\n\n",
-ret );
goto exit;
}
if( ( ret = mbedtls_pk_parse_key( &pkey2,
(const unsigned char *) mbedtls_test_srv_key_ec,
mbedtls_test_srv_key_ec_len, NULL, 0 ) ) != 0 )
{
mbedtls_printf( " failed\n ! pk_parse_key2 returned -0x%x\n\n", -ret );
mbedtls_printf( " failed\n ! pk_parse_key2 returned -0x%x\n\n",
-ret );
goto exit;
}
key_cert_init2 = 2;
@ -2303,8 +2389,10 @@ reset:
#if !defined(_WIN32)
if( received_sigterm )
{
mbedtls_printf( " interrupted by SIGTERM\n" );
ret = 0;
mbedtls_printf( " interrupted by SIGTERM (not in net_accept())\n" );
if( ret == MBEDTLS_ERR_NET_INVALID_CONTEXT )
ret = 0;
goto exit;
}
#endif
@ -2340,8 +2428,10 @@ reset:
#if !defined(_WIN32)
if( received_sigterm )
{
mbedtls_printf( " interrupted by signal\n" );
ret = 0;
mbedtls_printf( " interrupted by SIGTERM (in net_accept())\n" );
if( ret == MBEDTLS_ERR_NET_ACCEPT_FAILED )
ret = 0;
goto exit;
}
#endif
@ -2368,8 +2458,8 @@ reset:
if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl,
client_ip, cliip_len ) ) != 0 )
{
mbedtls_printf( " failed\n ! "
"mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", -ret );
mbedtls_printf( " failed\n ! mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n",
-ret );
goto exit;
}
}
@ -2397,9 +2487,8 @@ handshake:
mbedtls_printf( " . Performing the SSL/TLS handshake..." );
fflush( stdout );
do
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
{
ret = mbedtls_ssl_handshake( &ssl );
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE_C)
if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS &&
ssl_async_keys.inject_error == SSL_ASYNC_INJECT_ERROR_CANCEL )
@ -2408,10 +2497,24 @@ handshake:
break;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE_C */
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
break;
/* For event-driven IO, wait for socket to become available */
if( opt.event == 1 /* level triggered IO */ )
{
#if defined(MBEDTLS_TIMING_C)
ret = idle( &client_fd, &timer, ret );
#else
ret = idle( &client_fd, ret );
#endif
if( ret != 0 )
goto reset;
}
}
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
{
@ -2523,7 +2626,18 @@ data_exchange:
if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
{
if( opt.event == 1 /* level triggered IO */ )
{
#if defined(MBEDTLS_TIMING_C)
idle( &client_fd, &timer, ret );
#else
idle( &client_fd, ret );
#endif
}
continue;
}
if( ret <= 0 )
{
@ -2611,7 +2725,37 @@ data_exchange:
len = sizeof( buf ) - 1;
memset( buf, 0, sizeof( buf ) );
do ret = mbedtls_ssl_read( &ssl, buf, len );
do
{
/* Without the call to `mbedtls_ssl_check_pending`, it might
* happen that the client sends application data in the same
* datagram as the Finished message concluding the handshake.
* In this case, the application data would be ready to be
* processed while the underlying transport wouldn't signal
* any further incoming data.
*
* See the test 'Event-driven I/O: session-id resume, UDP packing'
* in tests/ssl-opt.sh.
*/
/* For event-driven IO, wait for socket to become available */
if( mbedtls_ssl_check_pending( &ssl ) == 0 &&
opt.event == 1 /* level triggered IO */ )
{
#if defined(MBEDTLS_TIMING_C)
idle( &client_fd, &timer, MBEDTLS_ERR_SSL_WANT_READ );
#else
idle( &client_fd, MBEDTLS_ERR_SSL_WANT_READ );
#endif
}
ret = mbedtls_ssl_read( &ssl, buf, len );
/* Note that even if `mbedtls_ssl_check_pending` returns true,
* it can happen that the subsequent call to `mbedtls_ssl_read`
* returns `MBEDTLS_ERR_SSL_WANT_READ`, because the pending messages
* might be discarded (e.g. because they are retransmissions). */
}
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
@ -2656,6 +2800,16 @@ data_exchange:
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret );
goto reset;
}
/* For event-driven IO, wait for socket to become available */
if( opt.event == 1 /* level triggered IO */ )
{
#if defined(MBEDTLS_TIMING_C)
idle( &client_fd, &timer, ret );
#else
idle( &client_fd, ret );
#endif
}
}
mbedtls_printf( " ok\n" );
@ -2691,15 +2845,40 @@ data_exchange:
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
goto reset;
}
/* For event-driven IO, wait for socket to become available */
if( opt.event == 1 /* level triggered IO */ )
{
#if defined(MBEDTLS_TIMING_C)
idle( &client_fd, &timer, ret );
#else
idle( &client_fd, ret );
#endif
}
}
}
}
else /* Not stream, so datagram */
{
do ret = mbedtls_ssl_write( &ssl, buf, len );
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
while( 1 )
{
ret = mbedtls_ssl_write( &ssl, buf, len );
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
break;
/* For event-driven IO, wait for socket to become available */
if( opt.event == 1 /* level triggered IO */ )
{
#if defined(MBEDTLS_TIMING_C)
idle( &client_fd, &timer, ret );
#else
idle( &client_fd, ret );
#endif
}
}
if( ret < 0 )
{