From b0643d152d9f47f45e344195c43c9eb9a013940d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 14 Oct 2014 18:30:36 +0200 Subject: [PATCH] Add ssl_set_dtls_badmac_limit() --- include/polarssl/check_config.h | 5 +++++ include/polarssl/config.h | 15 +++++++++++++-- include/polarssl/ssl.h | 32 ++++++++++++++++++++++++++++++++ library/ssl_tls.c | 16 ++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/include/polarssl/check_config.h b/include/polarssl/check_config.h index 4f65e17db7..c532db0d65 100644 --- a/include/polarssl/check_config.h +++ b/include/polarssl/check_config.h @@ -277,6 +277,11 @@ #error "POLARSSL_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" #endif +#if defined(POLARSSL_SSL_DTLS_BADMAC_LIMIT) && \ + ( !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_PROTO_DTLS) ) +#error "POLARSSL_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#endif + #if defined(POLARSSL_SSL_SESSION_TICKETS) && defined(POLARSSL_SSL_TLS_C) && \ ( !defined(POLARSSL_AES_C) || !defined(POLARSSL_SHA256_C) || \ !defined(POLARSSL_CIPHER_MODE_CBC) ) diff --git a/include/polarssl/config.h b/include/polarssl/config.h index 2fc1915bed..abc2668236 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -929,7 +929,7 @@ * Enable support for the anti-replay mechanism in DTLS. * * Requires: POLARSSL_SSL_TLS_C - * POLARSSL_POLARSSL_PROTO_DTLS + * POLARSSL_SSL_PROTO_DTLS * * \warning Disabling this is often a security risk! * See ssl_set_dtls_anti_replay() for details. @@ -951,12 +951,23 @@ * \warning Disabling this can ba a security risk! (see above) * * Requires: POLARSSL_SSL_SRV_C - * POLARSSL_POLARSSL_PROTO_DTLS + * POLARSSL_SSL_PROTO_DTLS * * Comment this to disable support for HelloVerifyRequest. */ #define POLARSSL_SSL_DTLS_HELLO_VERIFY +/** + * \def POLARSSL_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See ssl_set_dtls_badmac_limit(). + * + * Requires: POLARSSL_SSL_PROTO_DTLS + */ +#define POLARSSL_SSL_DTLS_BADMAC_LIMIT + /** * \def POLARSSL_SSL_SESSION_TICKETS * diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 5c92d37738..ac6f03fdb3 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -772,6 +772,11 @@ struct _ssl_context uint32_t read_timeout; /*!< timeout for ssl_read in milliseconds */ +#if defined(POLARSSL_SSL_DTLS_BADMAC_LIMIT) + unsigned badmac_limit; /*!< limit of records with a bad MAC */ + unsigned badmac_seen; /*!< records with a bad MAC received */ +#endif + /* * Callbacks (RNG, debug, I/O, verification) */ @@ -1294,6 +1299,33 @@ void ssl_set_dtls_cookies( ssl_context *ssl, void ssl_set_dtls_anti_replay( ssl_context *ssl, char mode ); #endif /* POLARSSL_SSL_DTLS_ANTI_REPLAY */ +#if defined(POLARSSL_SSL_DTLS_BADMAC_LIMIT) +/** + * \brief Set a limit on the number of records with a bad MAC + * before terminating the connection. + * (DTLS only, no effect on TLS.) + * Default: 0 (disabled). + * + * \param ssl SSL context + * \param limit Limit, or 0 to disable. + * + * \note If the limit is N, then the connection is terminated when + * the Nth non-authentic record is seen. + * + * \note Records with an invalid header are not counted, only the + * ones going through the authentication-decryption phase. + * + * \note This is a security trade-off related to the fact that it's + * often relatively easy for an active attacker ot inject UDP + * datagrams. On one hand, setting a low limit here makes it + * easier for such an attacker to forcibly terminated a + * connection. On the other hand, a high limit or no limit + * might make us waste resources checking authentication on + * many bogus packets. + */ +void ssl_set_dtls_badmac_limit( ssl_context *ssl, unsigned limit ); +#endif /* POLARSSL_DTLS_BADMAC_LIMIT */ + #if defined(POLARSSL_SSL_PROTO_DTLS) /** * \brief Set retransmit timeout values for the DTLS handshale. diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 54add8e343..7cb14424db 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3238,6 +3238,15 @@ read_record_header: if( ret == POLARSSL_ERR_SSL_INVALID_RECORD || ret == POLARSSL_ERR_SSL_INVALID_MAC ) { +#if defined(POLARSSL_SSL_DTLS_BADMAC_LIMIT) + if( ssl->badmac_limit != 0 && + ++ssl->badmac_seen >= ssl->badmac_limit ) + { + SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); + return( POLARSSL_ERR_SSL_INVALID_MAC ); + } +#endif + SSL_DEBUG_MSG( 1, ( "discarding invalid record" ) ); goto read_record_header; } @@ -4923,6 +4932,13 @@ void ssl_set_dtls_anti_replay( ssl_context *ssl, char mode ) } #endif +#if defined(POLARSSL_SSL_DTLS_BADMAC_LIMIT) +void ssl_set_dtls_badmac_limit( ssl_context *ssl, unsigned limit ) +{ + ssl->badmac_limit = limit; +} +#endif + #if defined(POLARSSL_SSL_PROTO_DTLS) void ssl_set_handshake_timeout( ssl_context *ssl, uint32_t min, uint32_t max ) {