Refactor cookie to prepare for external callbacks
Also adds flexibility to the verification process.
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 2b06f7e..9300fa7 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1186,36 +1186,51 @@
/*
* Generate cookie for DTLS ClientHello verification
*/
-static int ssl_cookie_generate( ssl_context *ssl )
+static int ssl_cookie_write( void *ctx,
+ unsigned char **p, unsigned char *end,
+ const unsigned char *cli_id, size_t cli_id_len )
{
int ret;
- unsigned char *cookie = ssl->handshake->verify_cookie;
- unsigned char cookie_len;
unsigned char hmac_out[HVR_MD_LEN];
+ md_context_t *hmac_ctx = (md_context_t *) ctx;
- polarssl_free( cookie );
+ if( (size_t)( end - *p ) < HVR_MD_USE )
+ return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
- cookie_len = HVR_MD_LEN;
-
- if( ( cookie = polarssl_malloc( cookie_len ) ) == NULL )
+ if( ( ret = md_hmac_reset( hmac_ctx ) ) != 0 ||
+ ( ret = md_hmac_update( hmac_ctx, cli_id, cli_id_len ) ) != 0 ||
+ ( ret = md_hmac_finish( hmac_ctx, hmac_out ) ) != 0 )
{
- SSL_DEBUG_MSG( 1, ( "malloc (%d bytes) failed\n", cookie_len ) );
- return( POLARSSL_ERR_SSL_MALLOC_FAILED );
- }
-
- if( ( ret = md_hmac_reset( &ssl->hvr_hmac_ctx ) ) != 0 ||
- ( ret = md_hmac_update( &ssl->hvr_hmac_ctx,
- ssl->cli_id, ssl->cli_id_len ) ) != 0 ||
- ( ret = md_hmac_finish( &ssl->hvr_hmac_ctx, hmac_out ) ) != 0 )
- {
- SSL_DEBUG_RET( 1, "md_hmac", ret );
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
}
- memcpy( cookie, hmac_out, HVR_MD_USE );
+ memcpy( *p, hmac_out, HVR_MD_USE );
+ *p += HVR_MD_USE;
- ssl->handshake->verify_cookie = cookie;
- ssl->handshake->verify_cookie_len = cookie_len;
+ return( 0 );
+}
+
+/*
+ * Check a cookie
+ */
+static int ssl_cookie_check( void *ctx,
+ const unsigned char *cookie, size_t cookie_len,
+ const unsigned char *cli_id, size_t cli_id_len )
+{
+ unsigned char ref_cookie[HVR_MD_USE];
+ unsigned char *p = ref_cookie;
+ md_context_t *hmac_ctx = (md_context_t *) ctx;
+
+ if( cookie_len != HVR_MD_USE )
+ return( -1 );
+
+ if( ssl_cookie_write( hmac_ctx,
+ &p, p + sizeof( ref_cookie ),
+ cli_id, cli_id_len ) != 0 )
+ return( -1 );
+
+ if( safer_memcmp( cookie, ref_cookie, sizeof( ref_cookie ) ) != 0 )
+ return( -1 );
return( 0 );
}
@@ -1516,31 +1531,18 @@
buf + cookie_offset + 1, cookie_len );
#if defined(POLARSSL_SSL_DTLS_HELLO_VERIFY)
- /*
- * Generate reference cookie content:
- * - used for verification below,
- * - stored to be sent if verification fails
- */
- if( ( ret = ssl_cookie_generate( ssl ) ) != 0 )
+ if( ssl_cookie_check( &ssl->hvr_hmac_ctx,
+ buf + cookie_offset + 1, cookie_len,
+ ssl->cli_id, ssl->cli_id_len ) != 0 )
{
- SSL_DEBUG_RET( 1, "ssl_cookie_generate", ret );
- return( ret );
+ SSL_DEBUG_MSG( 2, ( "client hello, cookie verification failed" ) );
+ ssl->handshake->verify_cookie_len = 1;
}
-
- /* If the received cookie is OK, no need to send one */
- if( cookie_len == ssl->handshake->verify_cookie_len &&
- safer_memcmp( buf + cookie_offset + 1,
- ssl->handshake->verify_cookie,
- ssl->handshake->verify_cookie_len ) == 0 )
+ else
{
- polarssl_free( ssl->handshake->verify_cookie );
- ssl->handshake->verify_cookie = NULL;
+ SSL_DEBUG_MSG( 2, ( "client hello, cookie verification passed" ) );
ssl->handshake->verify_cookie_len = 0;
}
-
- SSL_DEBUG_MSG( 2, ( "client hello, cookie verification %s",
- ssl->handshake->verify_cookie == NULL ?
- "passed" : "failed" ) );
#else
/* We know we didn't send a cookie, so it should be empty */
if( cookie_len != 0 )
@@ -1549,7 +1551,7 @@
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
- SSL_DEBUG_MSG( 2, ( "cookie verification disabled" ) );
+ SSL_DEBUG_MSG( 2, ( "client hello, cookie verification skipped" ) );
#endif
}
#endif /* POLARSSL_SSL_PROTO_DTLS */
@@ -2053,6 +2055,7 @@
{
int ret;
unsigned char *p = ssl->out_msg + 4;
+ unsigned char *cookie_len_byte;
SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) );
@@ -2069,12 +2072,20 @@
SSL_DEBUG_BUF( 3, "server version", (unsigned char *) p, 2 );
p += 2;
- SSL_DEBUG_BUF( 3, "cookie", ssl->handshake->verify_cookie,
- ssl->handshake->verify_cookie_len );
- *p++ = ssl->handshake->verify_cookie_len;
- memcpy( p, ssl->handshake->verify_cookie,
- ssl->handshake->verify_cookie_len );
- p += ssl->handshake->verify_cookie_len;
+ /* Skip length byte until we know the length */
+ cookie_len_byte = p++;
+
+ if( ( ret = ssl_cookie_write( &ssl->hvr_hmac_ctx,
+ &p, ssl->out_buf + SSL_BUFFER_LEN,
+ ssl->cli_id, ssl->cli_id_len ) ) != 0 )
+ {
+ SSL_DEBUG_RET( 1, "ssl_cookie_generate", ret );
+ return( ret );
+ }
+
+ *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) );
+
+ SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte );
ssl->out_msglen = p - ssl->out_msg;
ssl->out_msgtype = SSL_MSG_HANDSHAKE;
@@ -2107,7 +2118,7 @@
#if defined(POLARSSL_SSL_DTLS_HELLO_VERIFY)
if( ssl->transport == SSL_TRANSPORT_DATAGRAM &&
- ssl->handshake->verify_cookie != NULL )
+ ssl->handshake->verify_cookie_len != 0 )
{
SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) );
SSL_DEBUG_MSG( 2, ( "<= write server hello" ) );