diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 3b37867469..6e40c329fe 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -875,6 +875,14 @@ struct _ssl_context const char *alpn_chosen; /*!< negotiated protocol */ #endif + /* + * Client id (IP/port) for DTLS hello verify + */ +#if defined(POLARSSL_SSL_PROTO_DTLS) && defined(POLARSSL_SSL_SRV_C) + unsigned char *cli_id; /*!< transport-level ID of the client */ + size_t cli_id_len; /*!< length of cli_id */ +#endif + /* * Secure renegotiation */ @@ -1058,6 +1066,33 @@ void ssl_set_bio( ssl_context *ssl, int (*f_recv)(void *, unsigned char *, size_t), void *p_recv, int (*f_send)(void *, const unsigned char *, size_t), void *p_send ); +#if defined(POLARSSL_SSL_PROTO_DTLS) && defined(POLARSSL_SSL_SRV_C) +/** + * \brief Set client's transport-level identification info. + * (Only usable on server.) + * + * This is usually the IP address (and port), but could be + * anything identify the client depending on the underlying + * network stack. Used for HelloVerifyRequest with DTLS. + * This is *not* used to route the actual packets. + * + * \warning (TODO-DTLS) May change and even be removed before 2.0.0! + * + * \param ssl SSL context + * \param info Transport-level info identifying the client (eg IP + port) + * \param ilen Length of info in bytes + * + * \note An internal copy is made, so the info buffer can be reused. + * + * \return 0 on success, + * POLARSSL_ERR_SSL_BAD_INPUT_DATA if used on client, + * POLARSSL_ERR_SSL_MALLOC_FAILED if out of memory. + */ +int ssl_set_client_transport_id( ssl_context *ssl, + const unsigned char *info, + size_t ilen ); +#endif /* POLARSSL_SSL_PROTO_DTLS && POLARSSL_SSL_SRV_C */ + /** * \brief Set the session cache callbacks (server-side only) * If not set, no session resuming is done. diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 430f51a84f..eac553f595 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -351,6 +351,26 @@ static int ssl_parse_ticket( ssl_context *ssl, } #endif /* POLARSSL_SSL_SESSION_TICKETS */ +#if defined(POLARSSL_SSL_PROTO_DTLS) +int ssl_set_client_transport_id( ssl_context *ssl, + const unsigned char *info, + size_t ilen ) +{ + if( ssl->endpoint != SSL_IS_SERVER ) + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + + polarssl_free( ssl->cli_id ); + + if( ( ssl->cli_id = polarssl_malloc( ilen ) ) == NULL ) + return( POLARSSL_ERR_SSL_MALLOC_FAILED ); + + memcpy( ssl->cli_id, info, ilen ); + ssl->cli_id_len = ilen; + + return( 0 ); +} +#endif /* POLARSSL_SSL_PROTO_DTLS */ + #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) /* * Wrapper around f_sni, allowing use of ssl_set_own_cert() but diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 27ee058e40..d854199430 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3749,6 +3749,12 @@ int ssl_session_reset( ssl_context *ssl ) ssl->alpn_chosen = NULL; #endif +#if defined(POLARSSL_SSL_PROTO_DTLS) && defined(POLARSSL_SSL_SRV_C) + polarssl_free( ssl->cli_id ); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; +#endif + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) return( ret ); @@ -5033,6 +5039,10 @@ void ssl_free( ssl_context *ssl ) } #endif +#if defined(POLARSSL_SSL_PROTO_DTLS) && defined(POLARSSL_SSL_SRV_C) + polarssl_free( ssl->cli_id ); +#endif + SSL_DEBUG_MSG( 2, ( "<= free" ) ); /* Actually clear after last debug message */