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.
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 3825393..df57cb3 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1293,121 +1293,113 @@
}
/*
- * 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;
- 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 ) );
-
- if( ( ret = ssl_flush_output( ssl ) ) != 0 )
+ case SSL_HELLO_REQUEST:
+ ssl->state = SSL_CLIENT_HELLO;
break;
- switch( ssl->state )
- {
- case SSL_HELLO_REQUEST:
- ssl->state = SSL_CLIENT_HELLO;
- break;
-
- /*
- * <== 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 )
+ /*
+ * <== 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 );
}
- SSL_DEBUG_MSG( 2, ( "<= handshake server" ) );
-
return( ret );
}
-
#endif