Implement anti-replay algorithm with ESN support
As RFC 4304 describes there is anti-replay algorithm responsibility to provide appropriate value of Extended Sequence Number. This patch introduces anti-replay algorithm with ESN support based on RFC 4304, however to avoid performance regressions window implementation was based on RFC 6479, which was already implemented in FreeBSD. To keep things clean and improve code readability, implementation of window is kept in seperate functions. Submitted by: Grzegorz Jaszczyk <jaz@semihalf.com> Patryk Duda <pdk@semihalf.com> Reviewed by: jhb Differential revision: https://reviews.freebsd.org/D22367 Obtained from: Semihalf Sponsored by: Stormshield
This commit is contained in:
parent
1c34dcb532
commit
8b7f39947c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=366757
@ -1173,6 +1173,66 @@ ipsec_hdrsiz_inpcb(struct inpcb *inp)
|
|||||||
return (sz);
|
return (sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define IPSEC_BITMAP_INDEX_MASK(w) (w - 1)
|
||||||
|
#define IPSEC_REDUNDANT_BIT_SHIFTS 5
|
||||||
|
#define IPSEC_REDUNDANT_BITS (1 << IPSEC_REDUNDANT_BIT_SHIFTS)
|
||||||
|
#define IPSEC_BITMAP_LOC_MASK (IPSEC_REDUNDANT_BITS - 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions below are responsible for checking and updating bitmap.
|
||||||
|
* These are used to separate ipsec_chkreplay() and ipsec_updatereplay()
|
||||||
|
* from window implementation
|
||||||
|
*
|
||||||
|
* Based on RFC 6479. Blocks are 32 bits unsigned integers
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
check_window(const struct secreplay *replay, uint64_t seq)
|
||||||
|
{
|
||||||
|
int index, bit_location;
|
||||||
|
|
||||||
|
bit_location = seq & IPSEC_BITMAP_LOC_MASK;
|
||||||
|
index = (seq >> IPSEC_REDUNDANT_BIT_SHIFTS)
|
||||||
|
& IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size);
|
||||||
|
|
||||||
|
/* This packet already seen? */
|
||||||
|
return ((replay->bitmap)[index] & (1 << bit_location));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
advance_window(const struct secreplay *replay, uint64_t seq)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint64_t index, index_cur, diff;
|
||||||
|
|
||||||
|
index_cur = replay->last >> IPSEC_REDUNDANT_BIT_SHIFTS;
|
||||||
|
index = seq >> IPSEC_REDUNDANT_BIT_SHIFTS;
|
||||||
|
diff = index - index_cur;
|
||||||
|
|
||||||
|
if (diff > replay->bitmap_size) {
|
||||||
|
/* something unusual in this case */
|
||||||
|
diff = replay->bitmap_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < diff; i++) {
|
||||||
|
replay->bitmap[(i + index_cur + 1)
|
||||||
|
& IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size)] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_window(const struct secreplay *replay, uint64_t seq)
|
||||||
|
{
|
||||||
|
int index, bit_location;
|
||||||
|
|
||||||
|
bit_location = seq & IPSEC_BITMAP_LOC_MASK;
|
||||||
|
index = (seq >> IPSEC_REDUNDANT_BIT_SHIFTS)
|
||||||
|
& IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size);
|
||||||
|
|
||||||
|
replay->bitmap[index] |= (1 << bit_location);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the variable replay window.
|
* Check the variable replay window.
|
||||||
* ipsec_chkreplay() performs replay check before ICV verification.
|
* ipsec_chkreplay() performs replay check before ICV verification.
|
||||||
@ -1181,20 +1241,17 @@ ipsec_hdrsiz_inpcb(struct inpcb *inp)
|
|||||||
* beforehand).
|
* beforehand).
|
||||||
* 0 (zero) is returned if packet disallowed, 1 if packet permitted.
|
* 0 (zero) is returned if packet disallowed, 1 if packet permitted.
|
||||||
*
|
*
|
||||||
* Based on RFC 6479. Blocks are 32 bits unsigned integers
|
* Based on RFC 4303
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define IPSEC_BITMAP_INDEX_MASK(w) (w - 1)
|
|
||||||
#define IPSEC_REDUNDANT_BIT_SHIFTS 5
|
|
||||||
#define IPSEC_REDUNDANT_BITS (1 << IPSEC_REDUNDANT_BIT_SHIFTS)
|
|
||||||
#define IPSEC_BITMAP_LOC_MASK (IPSEC_REDUNDANT_BITS - 1)
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ipsec_chkreplay(uint32_t seq, struct secasvar *sav)
|
ipsec_chkreplay(uint32_t seq, uint32_t *seqhigh, struct secasvar *sav)
|
||||||
{
|
{
|
||||||
const struct secreplay *replay;
|
char buf[128];
|
||||||
uint32_t wsizeb; /* Constant: window size. */
|
struct secreplay *replay;
|
||||||
int index, bit_location;
|
uint32_t window;
|
||||||
|
uint32_t tl, th, bl;
|
||||||
|
uint32_t seqh;
|
||||||
|
|
||||||
IPSEC_ASSERT(sav != NULL, ("Null SA"));
|
IPSEC_ASSERT(sav != NULL, ("Null SA"));
|
||||||
IPSEC_ASSERT(sav->replay != NULL, ("Null replay state"));
|
IPSEC_ASSERT(sav->replay != NULL, ("Null replay state"));
|
||||||
@ -1205,36 +1262,96 @@ ipsec_chkreplay(uint32_t seq, struct secasvar *sav)
|
|||||||
if (replay->wsize == 0)
|
if (replay->wsize == 0)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
/* Constant. */
|
/* Zero sequence number is not allowed. */
|
||||||
wsizeb = replay->wsize << 3;
|
if (seq == 0 && replay->last == 0)
|
||||||
|
|
||||||
/* Sequence number of 0 is invalid. */
|
|
||||||
if (seq == 0)
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
/* First time is always okay. */
|
window = replay->wsize << 3; /* Size of window */
|
||||||
if (replay->count == 0)
|
tl = (uint32_t)replay->last; /* Top of window, lower part */
|
||||||
return (1);
|
th = (uint32_t)(replay->last >> 32); /* Top of window, high part */
|
||||||
|
bl = tl - window + 1; /* Bottom of window, lower part */
|
||||||
|
|
||||||
/* Larger sequences are okay. */
|
/*
|
||||||
if (seq > replay->lastseq)
|
* We keep the high part intact when:
|
||||||
return (1);
|
* 1) the seq is within [bl, 0xffffffff] and the whole window is
|
||||||
|
* within one subspace;
|
||||||
/* Over range to check, i.e. too old or wrapped. */
|
* 2) the seq is within [0, bl) and window spans two subspaces.
|
||||||
if (replay->lastseq - seq >= wsizeb)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
/* The sequence is inside the sliding window
|
|
||||||
* now check the bit in the bitmap
|
|
||||||
* bit location only depends on the sequence number
|
|
||||||
*/
|
*/
|
||||||
bit_location = seq & IPSEC_BITMAP_LOC_MASK;
|
if ((tl >= window - 1 && seq >= bl) ||
|
||||||
index = (seq >> IPSEC_REDUNDANT_BIT_SHIFTS)
|
(tl < window - 1 && seq < bl)) {
|
||||||
& IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size);
|
*seqhigh = th;
|
||||||
|
if (seq <= tl) {
|
||||||
/* This packet already seen? */
|
/* Sequence number inside window - check against replay */
|
||||||
if ((replay->bitmap)[index] & (1 << bit_location))
|
if (check_window(replay, seq))
|
||||||
return (0);
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sequence number above top of window or not found in bitmap */
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If ESN is not enabled and packet with highest sequence number
|
||||||
|
* was received we should report overflow
|
||||||
|
*/
|
||||||
|
if (tl == 0xffffffff && !(sav->flags & SADB_X_SAFLAGS_ESN)) {
|
||||||
|
/* Set overflow flag. */
|
||||||
|
replay->overflow++;
|
||||||
|
|
||||||
|
if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
|
||||||
|
if (sav->sah->saidx.proto == IPPROTO_ESP)
|
||||||
|
ESPSTAT_INC(esps_wrap);
|
||||||
|
else if (sav->sah->saidx.proto == IPPROTO_AH)
|
||||||
|
AHSTAT_INC(ahs_wrap);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ipseclog((LOG_WARNING, "%s: replay counter made %d cycle. %s\n",
|
||||||
|
__func__, replay->overflow,
|
||||||
|
ipsec_sa2str(sav, buf, sizeof(buf))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Seq is within [bl, 0xffffffff] and bl is within
|
||||||
|
* [0xffffffff-window, 0xffffffff]. This means we got a seq
|
||||||
|
* which is within our replay window, but in the previous
|
||||||
|
* subspace.
|
||||||
|
*/
|
||||||
|
if (tl < window - 1 && seq >= bl) {
|
||||||
|
if (th == 0)
|
||||||
|
return (0);
|
||||||
|
*seqhigh = th - 1;
|
||||||
|
seqh = th - 1;
|
||||||
|
if (check_window(replay, seq))
|
||||||
|
return (0);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Seq is within [0, bl) but the whole window is within one subspace.
|
||||||
|
* This means that seq has wrapped and is in next subspace
|
||||||
|
*/
|
||||||
|
*seqhigh = th + 1;
|
||||||
|
seqh = th + 1;
|
||||||
|
|
||||||
|
/* Don't let high part wrap. */
|
||||||
|
if (seqh == 0) {
|
||||||
|
/* Set overflow flag. */
|
||||||
|
replay->overflow++;
|
||||||
|
|
||||||
|
if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
|
||||||
|
if (sav->sah->saidx.proto == IPPROTO_ESP)
|
||||||
|
ESPSTAT_INC(esps_wrap);
|
||||||
|
else if (sav->sah->saidx.proto == IPPROTO_AH)
|
||||||
|
AHSTAT_INC(ahs_wrap);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ipseclog((LOG_WARNING, "%s: replay counter made %d cycle. %s\n",
|
||||||
|
__func__, replay->overflow,
|
||||||
|
ipsec_sa2str(sav, buf, sizeof(buf))));
|
||||||
|
}
|
||||||
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1246,84 +1363,90 @@ ipsec_chkreplay(uint32_t seq, struct secasvar *sav)
|
|||||||
int
|
int
|
||||||
ipsec_updatereplay(uint32_t seq, struct secasvar *sav)
|
ipsec_updatereplay(uint32_t seq, struct secasvar *sav)
|
||||||
{
|
{
|
||||||
char buf[128];
|
|
||||||
struct secreplay *replay;
|
struct secreplay *replay;
|
||||||
uint32_t wsizeb; /* Constant: window size. */
|
uint32_t window;
|
||||||
int diff, index, bit_location;
|
uint32_t tl, th, bl;
|
||||||
|
uint32_t seqh;
|
||||||
|
|
||||||
IPSEC_ASSERT(sav != NULL, ("Null SA"));
|
IPSEC_ASSERT(sav != NULL, ("Null SA"));
|
||||||
IPSEC_ASSERT(sav->replay != NULL, ("Null replay state"));
|
IPSEC_ASSERT(sav->replay != NULL, ("Null replay state"));
|
||||||
|
|
||||||
replay = sav->replay;
|
replay = sav->replay;
|
||||||
|
|
||||||
|
/* No need to check replay if disabled. */
|
||||||
if (replay->wsize == 0)
|
if (replay->wsize == 0)
|
||||||
goto ok; /* No need to check replay. */
|
return (0);
|
||||||
|
|
||||||
/* Constant. */
|
/* Zero sequence number is not allowed. */
|
||||||
wsizeb = replay->wsize << 3;
|
if (seq == 0 && replay->last == 0)
|
||||||
|
|
||||||
/* Sequence number of 0 is invalid. */
|
|
||||||
if (seq == 0)
|
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
/* The packet is too old, no need to update */
|
window = replay->wsize << 3; /* Size of window */
|
||||||
if (wsizeb + seq < replay->lastseq)
|
tl = (uint32_t)replay->last; /* Top of window, lower part */
|
||||||
goto ok;
|
th = (uint32_t)(replay->last >> 32); /* Top of window, high part */
|
||||||
|
bl = tl - window + 1; /* Bottom of window, lower part */
|
||||||
|
|
||||||
/* Now update the bit */
|
/*
|
||||||
index = (seq >> IPSEC_REDUNDANT_BIT_SHIFTS);
|
* We keep the high part intact when:
|
||||||
|
* 1) the seq is within [bl, 0xffffffff] and the whole window is
|
||||||
/* First check if the sequence number is in the range */
|
* within one subspace;
|
||||||
if (seq > replay->lastseq) {
|
* 2) the seq is within [0, bl) and window spans two subspaces.
|
||||||
int id;
|
*/
|
||||||
int index_cur = replay->lastseq >> IPSEC_REDUNDANT_BIT_SHIFTS;
|
if ((tl >= window - 1 && seq >= bl) ||
|
||||||
|
(tl < window - 1 && seq < bl)) {
|
||||||
diff = index - index_cur;
|
seqh = th;
|
||||||
if (diff > replay->bitmap_size) {
|
if (seq <= tl) {
|
||||||
/* something unusual in this case */
|
/* Sequence number inside window - check against replay */
|
||||||
diff = replay->bitmap_size;
|
if (check_window(replay, seq))
|
||||||
|
return (1);
|
||||||
|
set_window(replay, seq);
|
||||||
|
} else {
|
||||||
|
advance_window(replay, ((uint64_t)seqh << 32) | seq);
|
||||||
|
set_window(replay, seq);
|
||||||
|
replay->last = ((uint64_t)seqh << 32) | seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (id = 0; id < diff; ++id) {
|
/* Sequence number above top of window or not found in bitmap */
|
||||||
replay->bitmap[(id + index_cur + 1)
|
replay->count++;
|
||||||
& IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size)] = 0;
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
replay->lastseq = seq;
|
if (!(sav->flags & SADB_X_SAFLAGS_ESN))
|
||||||
}
|
|
||||||
|
|
||||||
index &= IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size);
|
|
||||||
bit_location = seq & IPSEC_BITMAP_LOC_MASK;
|
|
||||||
|
|
||||||
/* this packet has already been received */
|
|
||||||
if (replay->bitmap[index] & (1 << bit_location))
|
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
replay->bitmap[index] |= (1 << bit_location);
|
/*
|
||||||
|
* Seq is within [bl, 0xffffffff] and bl is within
|
||||||
ok:
|
* [0xffffffff-window, 0xffffffff]. This means we got a seq
|
||||||
if (replay->count == ~0) {
|
* which is within our replay window, but in the previous
|
||||||
/* Set overflow flag. */
|
* subspace.
|
||||||
replay->overflow++;
|
*/
|
||||||
|
if (tl < window - 1 && seq >= bl) {
|
||||||
/* Don't increment, no more packets accepted. */
|
if (th == 0)
|
||||||
if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
|
|
||||||
if (sav->sah->saidx.proto == IPPROTO_AH)
|
|
||||||
AHSTAT_INC(ahs_wrap);
|
|
||||||
else if (sav->sah->saidx.proto == IPPROTO_ESP)
|
|
||||||
ESPSTAT_INC(esps_wrap);
|
|
||||||
return (1);
|
return (1);
|
||||||
|
if (check_window(replay, seq))
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
set_window(replay, seq);
|
||||||
|
replay->count++;
|
||||||
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ipseclog((LOG_WARNING, "%s: replay counter made %d cycle. %s\n",
|
/*
|
||||||
__func__, replay->overflow,
|
* Seq is within [0, bl) but the whole window is within one subspace.
|
||||||
ipsec_sa2str(sav, buf, sizeof(buf))));
|
* This means that seq has wrapped and is in next subspace
|
||||||
}
|
*/
|
||||||
|
seqh = th + 1;
|
||||||
|
|
||||||
|
/* Don't let high part wrap. */
|
||||||
|
if (seqh == 0)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
advance_window(replay, ((uint64_t)seqh << 32) | seq);
|
||||||
|
set_window(replay, seq);
|
||||||
|
replay->last = ((uint64_t)seqh << 32) | seq;
|
||||||
replay->count++;
|
replay->count++;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ipsec_updateid(struct secasvar *sav, crypto_session_t *new,
|
ipsec_updateid(struct secasvar *sav, crypto_session_t *new,
|
||||||
crypto_session_t *old)
|
crypto_session_t *old)
|
||||||
|
@ -325,7 +325,7 @@ int udp_ipsec_output(struct mbuf *, struct secasvar *);
|
|||||||
int udp_ipsec_input(struct mbuf *, int, int);
|
int udp_ipsec_input(struct mbuf *, int, int);
|
||||||
int udp_ipsec_pcbctl(struct inpcb *, struct sockopt *);
|
int udp_ipsec_pcbctl(struct inpcb *, struct sockopt *);
|
||||||
|
|
||||||
int ipsec_chkreplay(uint32_t, struct secasvar *);
|
int ipsec_chkreplay(uint32_t, uint32_t *, struct secasvar *);
|
||||||
int ipsec_updatereplay(uint32_t, struct secasvar *);
|
int ipsec_updatereplay(uint32_t, struct secasvar *);
|
||||||
int ipsec_updateid(struct secasvar *, crypto_session_t *, crypto_session_t *);
|
int ipsec_updateid(struct secasvar *, crypto_session_t *, crypto_session_t *);
|
||||||
int ipsec_initialized(void);
|
int ipsec_initialized(void);
|
||||||
|
@ -809,8 +809,8 @@ kdebug_secreplay(struct secreplay *rpl)
|
|||||||
int len, l;
|
int len, l;
|
||||||
|
|
||||||
IPSEC_ASSERT(rpl != NULL, ("null rpl"));
|
IPSEC_ASSERT(rpl != NULL, ("null rpl"));
|
||||||
printf(" secreplay{ count=%u bitmap_size=%u wsize=%u seq=%u lastseq=%u",
|
printf(" secreplay{ count=%lu bitmap_size=%u wsize=%u last=%lu",
|
||||||
rpl->count, rpl->bitmap_size, rpl->wsize, rpl->seq, rpl->lastseq);
|
rpl->count, rpl->bitmap_size, rpl->wsize, rpl->last);
|
||||||
|
|
||||||
if (rpl->bitmap == NULL) {
|
if (rpl->bitmap == NULL) {
|
||||||
printf(" }\n");
|
printf(" }\n");
|
||||||
|
@ -202,10 +202,9 @@ struct secasvar {
|
|||||||
* (c) read only except during creation / free
|
* (c) read only except during creation / free
|
||||||
*/
|
*/
|
||||||
struct secreplay {
|
struct secreplay {
|
||||||
u_int32_t count; /* (m) */
|
u_int64_t count; /* (m) */
|
||||||
u_int wsize; /* (c) window size, i.g. 4 bytes */
|
u_int wsize; /* (c) window size, i.g. 4 bytes */
|
||||||
u_int32_t seq; /* (m) used by sender */
|
u_int64_t last; /* (m) used by receiver */
|
||||||
u_int32_t lastseq; /* (m) used by receiver */
|
|
||||||
u_int32_t *bitmap; /* (m) used by receiver */
|
u_int32_t *bitmap; /* (m) used by receiver */
|
||||||
u_int bitmap_size; /* (c) size of the bitmap array */
|
u_int bitmap_size; /* (c) size of the bitmap array */
|
||||||
int overflow; /* (m) overflow flag */
|
int overflow; /* (m) overflow flag */
|
||||||
|
@ -534,6 +534,7 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
|||||||
struct newah *ah;
|
struct newah *ah;
|
||||||
crypto_session_t cryptoid;
|
crypto_session_t cryptoid;
|
||||||
int hl, rplen, authsize, ahsize, error;
|
int hl, rplen, authsize, ahsize, error;
|
||||||
|
uint32_t seqh;
|
||||||
|
|
||||||
IPSEC_ASSERT(sav != NULL, ("null SA"));
|
IPSEC_ASSERT(sav != NULL, ("null SA"));
|
||||||
IPSEC_ASSERT(sav->key_auth != NULL, ("null authentication key"));
|
IPSEC_ASSERT(sav->key_auth != NULL, ("null authentication key"));
|
||||||
@ -557,7 +558,7 @@ ah_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
|||||||
/* Check replay window, if applicable. */
|
/* Check replay window, if applicable. */
|
||||||
SECASVAR_LOCK(sav);
|
SECASVAR_LOCK(sav);
|
||||||
if (sav->replay != NULL && sav->replay->wsize != 0 &&
|
if (sav->replay != NULL && sav->replay->wsize != 0 &&
|
||||||
ipsec_chkreplay(ntohl(ah->ah_seq), sav) == 0) {
|
ipsec_chkreplay(ntohl(ah->ah_seq), &seqh, sav) == 0) {
|
||||||
SECASVAR_UNLOCK(sav);
|
SECASVAR_UNLOCK(sav);
|
||||||
AHSTAT_INC(ahs_replay);
|
AHSTAT_INC(ahs_replay);
|
||||||
DPRINTF(("%s: packet replay failure: %s\n", __func__,
|
DPRINTF(("%s: packet replay failure: %s\n", __func__,
|
||||||
@ -925,7 +926,9 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
|
|||||||
/* Insert packet replay counter, as requested. */
|
/* Insert packet replay counter, as requested. */
|
||||||
SECASVAR_LOCK(sav);
|
SECASVAR_LOCK(sav);
|
||||||
if (sav->replay) {
|
if (sav->replay) {
|
||||||
if (sav->replay->count == ~0 &&
|
if ((sav->replay->count == ~0 ||
|
||||||
|
(!(sav->flags & SADB_X_SAFLAGS_ESN) &&
|
||||||
|
((uint32_t)sav->replay->count) == ~0)) &&
|
||||||
(sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
|
(sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
|
||||||
SECASVAR_UNLOCK(sav);
|
SECASVAR_UNLOCK(sav);
|
||||||
DPRINTF(("%s: replay counter wrapped for SA %s/%08lx\n",
|
DPRINTF(("%s: replay counter wrapped for SA %s/%08lx\n",
|
||||||
@ -940,7 +943,7 @@ ah_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
|
|||||||
if (!V_ipsec_replay)
|
if (!V_ipsec_replay)
|
||||||
#endif
|
#endif
|
||||||
sav->replay->count++;
|
sav->replay->count++;
|
||||||
ah->ah_seq = htonl(sav->replay->count);
|
ah->ah_seq = htonl((uint32_t)sav->replay->count);
|
||||||
}
|
}
|
||||||
cryptoid = sav->tdb_cryptoid;
|
cryptoid = sav->tdb_cryptoid;
|
||||||
SECASVAR_UNLOCK(sav);
|
SECASVAR_UNLOCK(sav);
|
||||||
|
@ -262,6 +262,7 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
|||||||
uint8_t *ivp;
|
uint8_t *ivp;
|
||||||
crypto_session_t cryptoid;
|
crypto_session_t cryptoid;
|
||||||
int alen, error, hlen, plen;
|
int alen, error, hlen, plen;
|
||||||
|
uint32_t seqh;
|
||||||
|
|
||||||
IPSEC_ASSERT(sav != NULL, ("null SA"));
|
IPSEC_ASSERT(sav != NULL, ("null SA"));
|
||||||
IPSEC_ASSERT(sav->tdb_encalgxform != NULL, ("null encoding xform"));
|
IPSEC_ASSERT(sav->tdb_encalgxform != NULL, ("null encoding xform"));
|
||||||
@ -320,7 +321,7 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
|
|||||||
*/
|
*/
|
||||||
SECASVAR_LOCK(sav);
|
SECASVAR_LOCK(sav);
|
||||||
if (esph != NULL && sav->replay != NULL && sav->replay->wsize != 0) {
|
if (esph != NULL && sav->replay != NULL && sav->replay->wsize != 0) {
|
||||||
if (ipsec_chkreplay(ntohl(esp->esp_seq), sav) == 0) {
|
if (ipsec_chkreplay(ntohl(esp->esp_seq), &seqh, sav) == 0) {
|
||||||
SECASVAR_UNLOCK(sav);
|
SECASVAR_UNLOCK(sav);
|
||||||
DPRINTF(("%s: packet replay check for %s\n", __func__,
|
DPRINTF(("%s: packet replay check for %s\n", __func__,
|
||||||
ipsec_sa2str(sav, buf, sizeof(buf))));
|
ipsec_sa2str(sav, buf, sizeof(buf))));
|
||||||
@ -740,7 +741,7 @@ esp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
|
|||||||
if (!V_ipsec_replay)
|
if (!V_ipsec_replay)
|
||||||
#endif
|
#endif
|
||||||
sav->replay->count++;
|
sav->replay->count++;
|
||||||
replay = htonl(sav->replay->count);
|
replay = htonl((uint32_t)sav->replay->count);
|
||||||
|
|
||||||
bcopy((caddr_t) &replay, mtod(mo, caddr_t) + roff +
|
bcopy((caddr_t) &replay, mtod(mo, caddr_t) + roff +
|
||||||
sizeof(uint32_t), sizeof(uint32_t));
|
sizeof(uint32_t), sizeof(uint32_t));
|
||||||
|
Loading…
Reference in New Issue
Block a user