Add ssl_set_dtls_badmac_limit()
diff --git a/include/polarssl/check_config.h b/include/polarssl/check_config.h
index 4f65e17..c532db0 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 2fc1915..abc2668 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,13 +951,24 @@
  * \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
  *
  * Enable support for RFC 5077 session tickets in SSL.
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 5c92d37..ac6f03f 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -772,6 +772,11 @@
 
     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_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 54add8e..7cb1442 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -3238,6 +3238,15 @@
             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 @@
 }
 #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 )
 {