diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index d4d947471..f0b1ec1bb 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -229,6 +229,9 @@ #define SSL_RENEGOTIATION_DISABLED 0 #define SSL_RENEGOTIATION_ENABLED 1 +#define SSL_ANTI_REPLAY_DISABLED 0 +#define SSL_ANTI_REPLAY_ENABLED 1 + #define SSL_RENEGOTIATION_NOT_ENFORCED -1 #define SSL_RENEGO_MAX_RECORDS_DEFAULT 16 @@ -828,6 +831,7 @@ struct _ssl_context #if defined(POLARSSL_SSL_DTLS_ANTI_REPLAY) uint64_t in_window_top; /*!< last validated record seq_num */ uint64_t in_window; /*!< bitmask for replay detection */ + char anti_replay; /*!< is anti-replay on? */ #endif size_t in_hslen; /*!< current handshake message length, @@ -1246,6 +1250,19 @@ void ssl_set_dtls_cookies( ssl_context *ssl, void *p_cookie ); #endif /* POLARSSL_SSL_DTLS_HELLO_VERIFY */ +#if defined(POLARSSL_SSL_DTLS_ANTI_REPLAY) +/** + * \brief Enable or disable anti-replay protection for DTLS. + * (DTLS only, no effect on TLS.) + * Default: enebled. + * + * \param ssl SSL context + * \param mode SSL_ANTI_REPLAY_ENABLED or SSL_ANTI_REPLAY_DISABLED. + */ +void ssl_set_dtls_anti_replay( ssl_context *ssl, char mode ); +#endif /* POLARSSL_SSL_DTLS_ANTI_REPLAY */ + + /** * \brief Set the session cache callbacks (server-side only) * If not set, no session resuming is done. diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 1a5cb0191..04c199e67 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2733,6 +2733,9 @@ int ssl_dtls_replay_check( ssl_context *ssl ) uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); uint64_t bit; + if( ssl->anti_replay == SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + if( rec_seqnum > ssl->in_window_top ) return( 0 ); @@ -2754,6 +2757,9 @@ void ssl_dtls_replay_update( ssl_context *ssl ) { uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + if( ssl->anti_replay == SSL_ANTI_REPLAY_DISABLED ) + return; + if( rec_seqnum > ssl->in_window_top ) { /* Update window_top and the contents of the window */ @@ -4528,6 +4534,10 @@ int ssl_init( ssl_context *ssl ) ssl->f_cookie_check = ssl_cookie_check_dummy; #endif +#if defined(POLARSSL_SSL_DTLS_ANTI_REPLAY) + ssl->anti_replay = SSL_ANTI_REPLAY_ENABLED; +#endif + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) return( ret ); @@ -4745,6 +4755,13 @@ int ssl_set_transport( ssl_context *ssl, int transport ) return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); } +#if defined(POLARSSL_SSL_DTLS_ANTI_REPLAY) +void ssl_set_dtls_anti_replay( ssl_context *ssl, char mode ) +{ + ssl->anti_replay = mode; +} +#endif + void ssl_set_authmode( ssl_context *ssl, int authmode ) { ssl->authmode = authmode; diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 1707ef05b..7c1a60c3e 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -122,6 +122,7 @@ int main( int argc, char *argv[] ) #define DFL_DHM_FILE NULL #define DFL_TRANSPORT SSL_TRANSPORT_STREAM #define DFL_COOKIES 1 +#define DFL_ANTI_REPLAY -1 #define LONG_RESPONSE "

01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ @@ -184,6 +185,7 @@ struct options const char *dhm_file; /* the file with the DH parameters */ int transport; /* TLS or DTLS? */ int cookies; /* Use cookies for DTLS? -1 to break them */ + int anti_replay; /* Use anti-replay for DTLS? -1 for default */ } opt; static void my_debug( void *ctx, int level, const char *str ) @@ -310,11 +312,18 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len ) #if defined(POLARSSL_SSL_DTLS_HELLO_VERIFY) #define USAGE_COOKIES \ " cookies=0/1/-1 default: 1 (enabled)\n" \ - " 0: disabled, -1: broken\n" + " 0: disabled, -1: library default (broken)\n" #else #define USAGE_COOKIES "" #endif +#if defined(POLARSSL_SSL_DTLS_ANTI_REPLAY) +#define USAGE_ANTI_REPLAY \ + " anti_replay=0/1 default: (library default = enabled)\n" +#else +#define USAGE_ANTI_REPLAY "" +#endif + #define USAGE \ "\n usage: ssl_server2 param=<>...\n" \ "\n acceptable parameters:\n" \ @@ -340,6 +349,7 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len ) USAGE_TICKETS \ USAGE_CACHE \ USAGE_COOKIES \ + USAGE_ANTI_REPLAY \ USAGE_MAX_FRAG_LEN \ USAGE_ALPN \ "\n" \ @@ -740,6 +750,7 @@ int main( int argc, char *argv[] ) opt.dhm_file = DFL_DHM_FILE; opt.transport = DFL_TRANSPORT; opt.cookies = DFL_COOKIES; + opt.anti_replay = DFL_ANTI_REPLAY; for( i = 1; i < argc; i++ ) { @@ -963,6 +974,12 @@ int main( int argc, char *argv[] ) if( opt.cookies < -1 || opt.cookies > 1) goto usage; } + else if( strcmp( p, "anti_replay" ) == 0 ) + { + opt.anti_replay = atoi( q ); + if( opt.anti_replay < 0 || opt.anti_replay > 1) + goto usage; + } else if( strcmp( p, "sni" ) == 0 ) { opt.sni = q; @@ -1400,6 +1417,13 @@ int main( int argc, char *argv[] ) { ; /* Nothing to do */ } + +#if defined(POLARSSL_SSL_DTLS_ANTI_REPLAY) + if( opt.anti_replay != DFL_ANTI_REPLAY ) + { + ssl_set_dtls_anti_replay( &ssl, opt.anti_replay ); + } +#endif } #endif /* POLARSSL_SSL_PROTO_DTLS */ diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 0fce954cc..a145cd7cc 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -2133,6 +2133,18 @@ run_test "DTLS proxy: duplicate every packet" \ -s "Extra-header:" \ -c "HTTP/1.0 200 OK" +run_test "DTLS proxy: duplicate every packet, server anti-replay off" \ + -p "$P_PXY duplicate=1" \ + "$P_SRV dtls=1 debug_level=1 anti_replay=0" \ + "$P_CLI dtls=1 debug_level=1" \ + 0 \ + -c "replayed record" \ + -S "replayed record" \ + -c "discarding invalid record" \ + -s "discarding invalid record" \ + -s "Extra-header:" \ + -c "HTTP/1.0 200 OK" + run_test "DTLS proxy: inject invalid AD record" \ -p "$P_PXY bad_ad=1" \ "$P_SRV dtls=1 debug_level=1" \