From 74848811b49191298ca2a62b07328849a3fec4db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 11 Jul 2014 02:43:49 +0200 Subject: [PATCH] Implement HelloVerifyRequest on client --- include/polarssl/ssl.h | 3 ++ library/ssl_cli.c | 97 +++++++++++++++++++++++++++++++++++++++--- library/ssl_tls.c | 4 ++ 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 5ce1878e5..16a6dacd8 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -378,6 +378,7 @@ #define SSL_HS_HELLO_REQUEST 0 #define SSL_HS_CLIENT_HELLO 1 #define SSL_HS_SERVER_HELLO 2 +#define SSL_HS_HELLO_VERIFY_REQUEST 3 #define SSL_HS_NEW_SESSION_TICKET 4 #define SSL_HS_CERTIFICATE 11 #define SSL_HS_SERVER_KEY_EXCHANGE 12 @@ -618,6 +619,8 @@ struct _ssl_handshake_params #endif /* POLARSSL_X509_CRT_PARSE_C */ #if defined(POLARSSL_SSL_PROTO_DTLS) unsigned int msg_seq; /*!< DTLS handshake sequence number */ + unsigned char *verify_cookie; /*!< cookie from HelloVerifyRequest */ + unsigned char verify_cookie_len; /*!< cookie length */ #endif /* diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 9acc1e134..253d74ddc 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -569,9 +569,22 @@ static int ssl_write_client_hello( ssl_context *ssl ) #if defined(POLARSSL_SSL_PROTO_DTLS) if( ssl->transport == SSL_TRANSPORT_DATAGRAM ) { - /* TODO-DTLS: for now, just send an empty cookie, later on must send - * back the cookie from HelloVerifyRequest */ - *p++ = 0; + if( ssl->handshake->verify_cookie == NULL ) + { + SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); + *p++ = 0; + } + else + { + SSL_DEBUG_BUF( 3, "client hello, 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; + } } #endif @@ -893,6 +906,63 @@ static int ssl_parse_alpn_ext( ssl_context *ssl, } #endif /* POLARSSL_SSL_ALPN */ +/* + * Parse HelloVerifyRequest. Only called after verifying the HS type. + */ +#if defined(POLARSSL_SSL_PROTO_DTLS) +static int ssl_parse_hello_verify_request( ssl_context *ssl ) +{ + const unsigned char *p = ssl->in_msg + 4; + int major_ver, minor_ver; + unsigned char cookie_len; + + SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + SSL_DEBUG_BUF( 3, "server version", (unsigned char *) p, 2 ); + ssl_read_version( &major_ver, &minor_ver, ssl->transport, p ); + p += 2; + + if( major_ver != SSL_MAJOR_VERSION_3 || + minor_ver < SSL_MINOR_VERSION_2 || + minor_ver > SSL_MINOR_VERSION_3 ) + { + SSL_DEBUG_MSG( 1, ( "bad server version" ) ); + + ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL, + SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); + } + + cookie_len = *p++; + SSL_DEBUG_BUF( 3, "cookie", (unsigned char *) p, cookie_len ); + + polarssl_free( ssl->handshake->verify_cookie ); + + ssl->handshake->verify_cookie = polarssl_malloc( cookie_len ); + if( ssl->handshake->verify_cookie == NULL ) + { + SSL_DEBUG_MSG( 1, ( "malloc failed (%d bytes)", cookie_len ) ); + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + } + + memcpy( ssl->handshake->verify_cookie, p, cookie_len ); + ssl->handshake->verify_cookie_len = cookie_len; + + ssl->state = SSL_CLIENT_HELLO; + + SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); + + return( 0 ); +} +#endif /* POLARSSL_SSL_PROTO_DTLS */ + static int ssl_parse_server_hello( ssl_context *ssl ) { int ret, i, comp; @@ -944,8 +1014,24 @@ static int ssl_parse_server_hello( ssl_context *ssl ) return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); } - SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", - buf[4], buf[5] ) ); +#if defined(POLARSSL_SSL_PROTO_DTLS) + if( ssl->transport == SSL_TRANSPORT_DATAGRAM ) + { + if( buf[0] == SSL_HS_HELLO_VERIFY_REQUEST ) + { + SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); + SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + return( ssl_parse_hello_verify_request( ssl ) ); + } + else + { + /* We made it through the verification process */ + polarssl_free( ssl->handshake->verify_cookie ); + ssl->handshake->verify_cookie = NULL; + ssl->handshake->verify_cookie_len = 0; + } + } +#endif /* POLARSSL_SSL_PROTO_DTLS */ if( ssl->in_hslen < 42 || buf[0] != SSL_HS_SERVER_HELLO ) @@ -954,6 +1040,7 @@ static int ssl_parse_server_hello( ssl_context *ssl ) return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); } + SSL_DEBUG_BUF( 3, "server hello, version", buf + 4, 2 ); ssl_read_version( &ssl->major_ver, &ssl->minor_ver, ssl->transport, buf + 4 ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 8165963c1..5abf89253 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4854,6 +4854,10 @@ void ssl_handshake_free( ssl_handshake_params *handshake ) } #endif /* POLARSSL_X509_CRT_PARSE_C && POLARSSL_SSL_SERVER_NAME_INDICATION */ +#if defined(POLARSSL_SSL_PROTO_DTLS) + polarssl_free( handshake->verify_cookie ); +#endif + polarssl_zeroize( handshake, sizeof( ssl_handshake_params ) ); }