Add functions for replay protection
This commit is contained in:
parent
ea22ce577e
commit
7a7e140d4e
3 changed files with 103 additions and 0 deletions
|
@ -913,6 +913,15 @@
|
|||
*/
|
||||
#define POLARSSL_SSL_PROTO_DTLS
|
||||
|
||||
/**
|
||||
* \def POLARSSL_SSL_DTLS_ANTI_REPLAY
|
||||
*
|
||||
* Enable support for the anti-replay mechanism in DTLS.
|
||||
*
|
||||
* Comment this to disable anti-replay in DTLS.
|
||||
*/
|
||||
#define POLARSSL_SSL_DTLS_ANTI_REPLAY
|
||||
|
||||
/**
|
||||
* \def POLARSSL_SSL_ALPN
|
||||
*
|
||||
|
|
|
@ -822,6 +822,10 @@ struct _ssl_context
|
|||
size_t next_record_offset; /*!< offset of the next record in datagram
|
||||
(equal to in_left if none) */
|
||||
#endif
|
||||
#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 */
|
||||
#endif
|
||||
|
||||
size_t in_hslen; /*!< current handshake message length,
|
||||
including the handshake header */
|
||||
|
@ -2043,6 +2047,12 @@ void ssl_recv_flight_completed( ssl_context *ssl );
|
|||
int ssl_resend( ssl_context *ssl );
|
||||
#endif
|
||||
|
||||
/* Visible for testing purposes only */
|
||||
#if defined(POLARSSL_SSL_DTLS_ANTI_REPLAY)
|
||||
int ssl_dtls_replay_check( ssl_context *ssl );
|
||||
void ssl_dtls_replay_update( ssl_context *ssl );
|
||||
#endif
|
||||
|
||||
/* constant-time buffer comparison */
|
||||
static inline int safer_memcmp( const void *a, const void *b, size_t n )
|
||||
{
|
||||
|
|
|
@ -2694,6 +2694,90 @@ static int ssl_prepare_handshake_record( ssl_context *ssl )
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* DTLS anti-replay: RFC 6347 4.1.2.6
|
||||
*
|
||||
* - in_window_top is the highest record sequence number seen
|
||||
* - the lsb of in_window is set iff in_window_top - 1 has been seen
|
||||
* ...
|
||||
* the msb of in_window is set iff in_window_top - 64 has been seen
|
||||
*/
|
||||
#if defined(POLARSSL_SSL_DTLS_ANTI_REPLAY)
|
||||
static void ssl_dtls_replay_reset( ssl_context *ssl )
|
||||
{
|
||||
ssl->in_window_top = 0;
|
||||
ssl->in_window = 0;
|
||||
}
|
||||
|
||||
static inline uint64_t ssl_load_six_bytes( unsigned char *buf )
|
||||
{
|
||||
return( ( (uint64_t) buf[0] << 40 ) |
|
||||
( (uint64_t) buf[1] << 32 ) |
|
||||
( (uint64_t) buf[2] << 24 ) |
|
||||
( (uint64_t) buf[3] << 16 ) |
|
||||
( (uint64_t) buf[4] << 8 ) |
|
||||
( (uint64_t) buf[5] ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if sequence number is acceptable, -1 otherwise
|
||||
*/
|
||||
int ssl_dtls_replay_check( ssl_context *ssl )
|
||||
{
|
||||
uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
|
||||
uint64_t bit;
|
||||
|
||||
if( rec_seqnum > ssl->in_window_top )
|
||||
return( 0 );
|
||||
|
||||
if( rec_seqnum == ssl->in_window_top )
|
||||
return( -1 );
|
||||
|
||||
bit = ssl->in_window_top - rec_seqnum - 1;
|
||||
|
||||
if( bit >= 64 )
|
||||
return( -1 );
|
||||
|
||||
if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Update replay window on new validated record
|
||||
*/
|
||||
void ssl_dtls_replay_update( ssl_context *ssl )
|
||||
{
|
||||
uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
|
||||
|
||||
if( rec_seqnum > ssl->in_window_top )
|
||||
{
|
||||
/* Update window_top and the contents of the window */
|
||||
uint64_t shift = rec_seqnum - ssl->in_window_top;
|
||||
|
||||
if( shift >= 64 )
|
||||
ssl->in_window = 0;
|
||||
else
|
||||
ssl->in_window <<= shift;
|
||||
|
||||
ssl->in_window_top = rec_seqnum;
|
||||
}
|
||||
else if( rec_seqnum == ssl->in_window_top )
|
||||
{
|
||||
; /* Can't happen, but anyway, nothing to do if it happened */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Mark that number as seen in the current window */
|
||||
uint64_t bit = ssl->in_window_top - rec_seqnum - 1;
|
||||
|
||||
if( bit < 64 ) /* Always true, but be extra sure */
|
||||
ssl->in_window |= (uint64_t) 1 << bit;
|
||||
}
|
||||
}
|
||||
#endif /* POLARSSL_SSL_DTLS_ANTI_REPLAY */
|
||||
|
||||
/*
|
||||
* ContentType type;
|
||||
* ProtocolVersion version;
|
||||
|
|
Loading…
Reference in a new issue