mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-25 17:05:42 +01:00
Added ssl_handshake_step() to allow single stepping the handshake
process Single stepping the handshake process allows for better support of non-blocking network stacks and for getting information from specific handshake messages if wanted.
This commit is contained in:
parent
9c94cddeae
commit
1961b709d8
@ -1,6 +1,9 @@
|
|||||||
PolarSSL ChangeLog
|
PolarSSL ChangeLog
|
||||||
|
|
||||||
= Version Master
|
= Version Master
|
||||||
|
Changes
|
||||||
|
* Added ssl_handshake_step() to allow single stepping the handshake process
|
||||||
|
|
||||||
Bugfix
|
Bugfix
|
||||||
* Memory leak when using RSA_PKCS_V21 operations fixed
|
* Memory leak when using RSA_PKCS_V21 operations fixed
|
||||||
* Handle future version properly in ssl_write_certificate_request()
|
* Handle future version properly in ssl_write_certificate_request()
|
||||||
|
@ -970,6 +970,20 @@ const x509_cert *ssl_get_peer_cert( const ssl_context *ssl );
|
|||||||
*/
|
*/
|
||||||
int ssl_handshake( ssl_context *ssl );
|
int ssl_handshake( ssl_context *ssl );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Perform a single step of the SSL handshake
|
||||||
|
*
|
||||||
|
* Note: the state of the context (ssl->state) will be at
|
||||||
|
* the following state after execution of this function.
|
||||||
|
* Do not call this function if state is SSL_HANDSHAKE_OVER.
|
||||||
|
*
|
||||||
|
* \param ssl SSL context
|
||||||
|
*
|
||||||
|
* \return 0 if successful, POLARSSL_ERR_NET_WANT_READ,
|
||||||
|
* POLARSSL_ERR_NET_WANT_WRITE, or a specific SSL error code.
|
||||||
|
*/
|
||||||
|
int ssl_handshake_step( ssl_context *ssl );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Perform an SSL renegotiation on the running connection
|
* \brief Perform an SSL renegotiation on the running connection
|
||||||
*
|
*
|
||||||
@ -1061,8 +1075,8 @@ void ssl_handshake_free( ssl_handshake_params *handshake );
|
|||||||
/*
|
/*
|
||||||
* Internal functions (do not call directly)
|
* Internal functions (do not call directly)
|
||||||
*/
|
*/
|
||||||
int ssl_handshake_client( ssl_context *ssl );
|
int ssl_handshake_client_step( ssl_context *ssl );
|
||||||
int ssl_handshake_server( ssl_context *ssl );
|
int ssl_handshake_server_step( ssl_context *ssl );
|
||||||
void ssl_handshake_wrapup( ssl_context *ssl );
|
void ssl_handshake_wrapup( ssl_context *ssl );
|
||||||
|
|
||||||
int ssl_send_fatal_handshake_failure( ssl_context *ssl );
|
int ssl_send_fatal_handshake_failure( ssl_context *ssl );
|
||||||
|
@ -1274,121 +1274,113 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SSL handshake -- client side
|
* SSL handshake -- client side -- single step
|
||||||
*/
|
*/
|
||||||
int ssl_handshake_client( ssl_context *ssl )
|
int ssl_handshake_client_step( ssl_context *ssl )
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 2, ( "=> handshake client" ) );
|
if( ssl->state == SSL_HANDSHAKE_OVER )
|
||||||
|
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
||||||
|
|
||||||
while( ssl->state != SSL_HANDSHAKE_OVER )
|
SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
|
||||||
|
|
||||||
|
if( ( ret = ssl_flush_output( ssl ) ) != 0 )
|
||||||
|
return( ret );
|
||||||
|
|
||||||
|
switch( ssl->state )
|
||||||
{
|
{
|
||||||
SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
|
case SSL_HELLO_REQUEST:
|
||||||
|
ssl->state = SSL_CLIENT_HELLO;
|
||||||
if( ( ret = ssl_flush_output( ssl ) ) != 0 )
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch( ssl->state )
|
/*
|
||||||
{
|
* ==> ClientHello
|
||||||
case SSL_HELLO_REQUEST:
|
*/
|
||||||
ssl->state = SSL_CLIENT_HELLO;
|
case SSL_CLIENT_HELLO:
|
||||||
break;
|
ret = ssl_write_client_hello( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ==> ClientHello
|
* <== ServerHello
|
||||||
*/
|
* Certificate
|
||||||
case SSL_CLIENT_HELLO:
|
* ( ServerKeyExchange )
|
||||||
ret = ssl_write_client_hello( ssl );
|
* ( CertificateRequest )
|
||||||
break;
|
* ServerHelloDone
|
||||||
|
*/
|
||||||
|
case SSL_SERVER_HELLO:
|
||||||
|
ret = ssl_parse_server_hello( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
/*
|
case SSL_SERVER_CERTIFICATE:
|
||||||
* <== ServerHello
|
ret = ssl_parse_certificate( ssl );
|
||||||
* Certificate
|
break;
|
||||||
* ( ServerKeyExchange )
|
|
||||||
* ( CertificateRequest )
|
|
||||||
* ServerHelloDone
|
|
||||||
*/
|
|
||||||
case SSL_SERVER_HELLO:
|
|
||||||
ret = ssl_parse_server_hello( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_SERVER_CERTIFICATE:
|
case SSL_SERVER_KEY_EXCHANGE:
|
||||||
ret = ssl_parse_certificate( ssl );
|
ret = ssl_parse_server_key_exchange( ssl );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSL_SERVER_KEY_EXCHANGE:
|
case SSL_CERTIFICATE_REQUEST:
|
||||||
ret = ssl_parse_server_key_exchange( ssl );
|
ret = ssl_parse_certificate_request( ssl );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSL_CERTIFICATE_REQUEST:
|
case SSL_SERVER_HELLO_DONE:
|
||||||
ret = ssl_parse_certificate_request( ssl );
|
ret = ssl_parse_server_hello_done( ssl );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSL_SERVER_HELLO_DONE:
|
/*
|
||||||
ret = ssl_parse_server_hello_done( ssl );
|
* ==> ( Certificate/Alert )
|
||||||
break;
|
* ClientKeyExchange
|
||||||
|
* ( CertificateVerify )
|
||||||
|
* ChangeCipherSpec
|
||||||
|
* Finished
|
||||||
|
*/
|
||||||
|
case SSL_CLIENT_CERTIFICATE:
|
||||||
|
ret = ssl_write_certificate( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
/*
|
case SSL_CLIENT_KEY_EXCHANGE:
|
||||||
* ==> ( Certificate/Alert )
|
ret = ssl_write_client_key_exchange( ssl );
|
||||||
* ClientKeyExchange
|
break;
|
||||||
* ( CertificateVerify )
|
|
||||||
* ChangeCipherSpec
|
|
||||||
* Finished
|
|
||||||
*/
|
|
||||||
case SSL_CLIENT_CERTIFICATE:
|
|
||||||
ret = ssl_write_certificate( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_CLIENT_KEY_EXCHANGE:
|
case SSL_CERTIFICATE_VERIFY:
|
||||||
ret = ssl_write_client_key_exchange( ssl );
|
ret = ssl_write_certificate_verify( ssl );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSL_CERTIFICATE_VERIFY:
|
case SSL_CLIENT_CHANGE_CIPHER_SPEC:
|
||||||
ret = ssl_write_certificate_verify( ssl );
|
ret = ssl_write_change_cipher_spec( ssl );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSL_CLIENT_CHANGE_CIPHER_SPEC:
|
case SSL_CLIENT_FINISHED:
|
||||||
ret = ssl_write_change_cipher_spec( ssl );
|
ret = ssl_write_finished( ssl );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSL_CLIENT_FINISHED:
|
/*
|
||||||
ret = ssl_write_finished( ssl );
|
* <== ChangeCipherSpec
|
||||||
break;
|
* Finished
|
||||||
|
*/
|
||||||
|
case SSL_SERVER_CHANGE_CIPHER_SPEC:
|
||||||
|
ret = ssl_parse_change_cipher_spec( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
/*
|
case SSL_SERVER_FINISHED:
|
||||||
* <== ChangeCipherSpec
|
ret = ssl_parse_finished( ssl );
|
||||||
* Finished
|
break;
|
||||||
*/
|
|
||||||
case SSL_SERVER_CHANGE_CIPHER_SPEC:
|
|
||||||
ret = ssl_parse_change_cipher_spec( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_SERVER_FINISHED:
|
case SSL_FLUSH_BUFFERS:
|
||||||
ret = ssl_parse_finished( ssl );
|
SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
|
||||||
break;
|
ssl->state = SSL_HANDSHAKE_WRAPUP;
|
||||||
|
break;
|
||||||
|
|
||||||
case SSL_FLUSH_BUFFERS:
|
case SSL_HANDSHAKE_WRAPUP:
|
||||||
SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
|
ssl_handshake_wrapup( ssl );
|
||||||
ssl->state = SSL_HANDSHAKE_WRAPUP;
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_HANDSHAKE_WRAPUP:
|
default:
|
||||||
ssl_handshake_wrapup( ssl );
|
SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
|
||||||
break;
|
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
||||||
|
}
|
||||||
default:
|
|
||||||
SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
|
|
||||||
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ret != 0 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 2, ( "<= handshake client" ) );
|
|
||||||
|
|
||||||
return( ret );
|
return( ret );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1293,121 +1293,113 @@ static int ssl_parse_certificate_verify( ssl_context *ssl )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SSL handshake -- server side
|
* SSL handshake -- server side -- single step
|
||||||
*/
|
*/
|
||||||
int ssl_handshake_server( ssl_context *ssl )
|
int ssl_handshake_server_step( ssl_context *ssl )
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 2, ( "=> handshake server" ) );
|
if( ssl->state == SSL_HANDSHAKE_OVER )
|
||||||
|
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
||||||
|
|
||||||
while( ssl->state != SSL_HANDSHAKE_OVER )
|
SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
|
||||||
|
|
||||||
|
if( ( ret = ssl_flush_output( ssl ) ) != 0 )
|
||||||
|
return( ret );
|
||||||
|
|
||||||
|
switch( ssl->state )
|
||||||
{
|
{
|
||||||
SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );
|
case SSL_HELLO_REQUEST:
|
||||||
|
ssl->state = SSL_CLIENT_HELLO;
|
||||||
if( ( ret = ssl_flush_output( ssl ) ) != 0 )
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch( ssl->state )
|
/*
|
||||||
{
|
* <== ClientHello
|
||||||
case SSL_HELLO_REQUEST:
|
*/
|
||||||
ssl->state = SSL_CLIENT_HELLO;
|
case SSL_CLIENT_HELLO:
|
||||||
break;
|
ret = ssl_parse_client_hello( ssl );
|
||||||
|
|
||||||
/*
|
|
||||||
* <== ClientHello
|
|
||||||
*/
|
|
||||||
case SSL_CLIENT_HELLO:
|
|
||||||
ret = ssl_parse_client_hello( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ==> ServerHello
|
|
||||||
* Certificate
|
|
||||||
* ( ServerKeyExchange )
|
|
||||||
* ( CertificateRequest )
|
|
||||||
* ServerHelloDone
|
|
||||||
*/
|
|
||||||
case SSL_SERVER_HELLO:
|
|
||||||
ret = ssl_write_server_hello( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_SERVER_CERTIFICATE:
|
|
||||||
ret = ssl_write_certificate( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_SERVER_KEY_EXCHANGE:
|
|
||||||
ret = ssl_write_server_key_exchange( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_CERTIFICATE_REQUEST:
|
|
||||||
ret = ssl_write_certificate_request( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_SERVER_HELLO_DONE:
|
|
||||||
ret = ssl_write_server_hello_done( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* <== ( Certificate/Alert )
|
|
||||||
* ClientKeyExchange
|
|
||||||
* ( CertificateVerify )
|
|
||||||
* ChangeCipherSpec
|
|
||||||
* Finished
|
|
||||||
*/
|
|
||||||
case SSL_CLIENT_CERTIFICATE:
|
|
||||||
ret = ssl_parse_certificate( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_CLIENT_KEY_EXCHANGE:
|
|
||||||
ret = ssl_parse_client_key_exchange( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_CERTIFICATE_VERIFY:
|
|
||||||
ret = ssl_parse_certificate_verify( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_CLIENT_CHANGE_CIPHER_SPEC:
|
|
||||||
ret = ssl_parse_change_cipher_spec( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_CLIENT_FINISHED:
|
|
||||||
ret = ssl_parse_finished( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ==> ChangeCipherSpec
|
|
||||||
* Finished
|
|
||||||
*/
|
|
||||||
case SSL_SERVER_CHANGE_CIPHER_SPEC:
|
|
||||||
ret = ssl_write_change_cipher_spec( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_SERVER_FINISHED:
|
|
||||||
ret = ssl_write_finished( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_FLUSH_BUFFERS:
|
|
||||||
SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
|
|
||||||
ssl->state = SSL_HANDSHAKE_WRAPUP;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSL_HANDSHAKE_WRAPUP:
|
|
||||||
ssl_handshake_wrapup( ssl );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
|
|
||||||
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ret != 0 )
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ==> ServerHello
|
||||||
|
* Certificate
|
||||||
|
* ( ServerKeyExchange )
|
||||||
|
* ( CertificateRequest )
|
||||||
|
* ServerHelloDone
|
||||||
|
*/
|
||||||
|
case SSL_SERVER_HELLO:
|
||||||
|
ret = ssl_write_server_hello( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_SERVER_CERTIFICATE:
|
||||||
|
ret = ssl_write_certificate( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_SERVER_KEY_EXCHANGE:
|
||||||
|
ret = ssl_write_server_key_exchange( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CERTIFICATE_REQUEST:
|
||||||
|
ret = ssl_write_certificate_request( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_SERVER_HELLO_DONE:
|
||||||
|
ret = ssl_write_server_hello_done( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <== ( Certificate/Alert )
|
||||||
|
* ClientKeyExchange
|
||||||
|
* ( CertificateVerify )
|
||||||
|
* ChangeCipherSpec
|
||||||
|
* Finished
|
||||||
|
*/
|
||||||
|
case SSL_CLIENT_CERTIFICATE:
|
||||||
|
ret = ssl_parse_certificate( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CLIENT_KEY_EXCHANGE:
|
||||||
|
ret = ssl_parse_client_key_exchange( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CERTIFICATE_VERIFY:
|
||||||
|
ret = ssl_parse_certificate_verify( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CLIENT_CHANGE_CIPHER_SPEC:
|
||||||
|
ret = ssl_parse_change_cipher_spec( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CLIENT_FINISHED:
|
||||||
|
ret = ssl_parse_finished( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ==> ChangeCipherSpec
|
||||||
|
* Finished
|
||||||
|
*/
|
||||||
|
case SSL_SERVER_CHANGE_CIPHER_SPEC:
|
||||||
|
ret = ssl_write_change_cipher_spec( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_SERVER_FINISHED:
|
||||||
|
ret = ssl_write_finished( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_FLUSH_BUFFERS:
|
||||||
|
SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
|
||||||
|
ssl->state = SSL_HANDSHAKE_WRAPUP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_HANDSHAKE_WRAPUP:
|
||||||
|
ssl_handshake_wrapup( ssl );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );
|
||||||
|
return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 2, ( "<= handshake server" ) );
|
|
||||||
|
|
||||||
return( ret );
|
return( ret );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3513,24 +3513,42 @@ const int ssl_default_ciphersuites[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform the SSL handshake
|
* Perform a single step of the SSL handshake
|
||||||
*/
|
*/
|
||||||
int ssl_handshake( ssl_context *ssl )
|
int ssl_handshake_step( ssl_context *ssl )
|
||||||
{
|
{
|
||||||
int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
|
int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
|
|
||||||
|
|
||||||
#if defined(POLARSSL_SSL_CLI_C)
|
#if defined(POLARSSL_SSL_CLI_C)
|
||||||
if( ssl->endpoint == SSL_IS_CLIENT )
|
if( ssl->endpoint == SSL_IS_CLIENT )
|
||||||
ret = ssl_handshake_client( ssl );
|
ret = ssl_handshake_client_step( ssl );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(POLARSSL_SSL_SRV_C)
|
#if defined(POLARSSL_SSL_SRV_C)
|
||||||
if( ssl->endpoint == SSL_IS_SERVER )
|
if( ssl->endpoint == SSL_IS_SERVER )
|
||||||
ret = ssl_handshake_server( ssl );
|
ret = ssl_handshake_server_step( ssl );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform the SSL handshake
|
||||||
|
*/
|
||||||
|
int ssl_handshake( ssl_context *ssl )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
|
||||||
|
|
||||||
|
while( ssl->state != SSL_HANDSHAKE_OVER )
|
||||||
|
{
|
||||||
|
ret = ssl_handshake_step( ssl );
|
||||||
|
|
||||||
|
if( ret != 0 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
SSL_DEBUG_MSG( 2, ( "<= handshake" ) );
|
SSL_DEBUG_MSG( 2, ( "<= handshake" ) );
|
||||||
|
|
||||||
return( ret );
|
return( ret );
|
||||||
|
Loading…
Reference in New Issue
Block a user