aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_replay.c
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2012-09-03 20:03:29 -0400
committerDavid S. Miller <davem@davemloft.net>2012-09-04 14:09:45 -0400
commit3b59df46a449ec9975146d71318c4777ad086744 (patch)
tree8ba7e6186ef90c4bffe553504c33f40054704f94 /net/xfrm/xfrm_replay.c
parent37159ef2c1ae1e696b24b260b241209a19f92c60 (diff)
xfrm: Workaround incompatibility of ESN and async crypto
ESN for esp is defined in RFC 4303. This RFC assumes that the sequence number counters are always up to date. However, this is not true if an async crypto algorithm is employed. If the sequence number counters are not up to date on sequence number check, we may incorrectly update the upper 32 bit of the sequence number. This leads to a DOS. We workaround this by comparing the upper sequence number, (used for authentication) with the upper sequence number computed after the async processing. We drop the packet if these numbers are different. To do this, we introduce a recheck function that does this check in the ESN case. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm/xfrm_replay.c')
-rw-r--r--net/xfrm/xfrm_replay.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index 2f6d11d04a2b..3efb07d3eb27 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -420,6 +420,18 @@ err:
420 return -EINVAL; 420 return -EINVAL;
421} 421}
422 422
423static int xfrm_replay_recheck_esn(struct xfrm_state *x,
424 struct sk_buff *skb, __be32 net_seq)
425{
426 if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi !=
427 htonl(xfrm_replay_seqhi(x, net_seq)))) {
428 x->stats.replay_window++;
429 return -EINVAL;
430 }
431
432 return xfrm_replay_check_esn(x, skb, net_seq);
433}
434
423static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) 435static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
424{ 436{
425 unsigned int bitnr, nr, i; 437 unsigned int bitnr, nr, i;
@@ -479,6 +491,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
479static struct xfrm_replay xfrm_replay_legacy = { 491static struct xfrm_replay xfrm_replay_legacy = {
480 .advance = xfrm_replay_advance, 492 .advance = xfrm_replay_advance,
481 .check = xfrm_replay_check, 493 .check = xfrm_replay_check,
494 .recheck = xfrm_replay_check,
482 .notify = xfrm_replay_notify, 495 .notify = xfrm_replay_notify,
483 .overflow = xfrm_replay_overflow, 496 .overflow = xfrm_replay_overflow,
484}; 497};
@@ -486,6 +499,7 @@ static struct xfrm_replay xfrm_replay_legacy = {
486static struct xfrm_replay xfrm_replay_bmp = { 499static struct xfrm_replay xfrm_replay_bmp = {
487 .advance = xfrm_replay_advance_bmp, 500 .advance = xfrm_replay_advance_bmp,
488 .check = xfrm_replay_check_bmp, 501 .check = xfrm_replay_check_bmp,
502 .recheck = xfrm_replay_check_bmp,
489 .notify = xfrm_replay_notify_bmp, 503 .notify = xfrm_replay_notify_bmp,
490 .overflow = xfrm_replay_overflow_bmp, 504 .overflow = xfrm_replay_overflow_bmp,
491}; 505};
@@ -493,6 +507,7 @@ static struct xfrm_replay xfrm_replay_bmp = {
493static struct xfrm_replay xfrm_replay_esn = { 507static struct xfrm_replay xfrm_replay_esn = {
494 .advance = xfrm_replay_advance_esn, 508 .advance = xfrm_replay_advance_esn,
495 .check = xfrm_replay_check_esn, 509 .check = xfrm_replay_check_esn,
510 .recheck = xfrm_replay_recheck_esn,
496 .notify = xfrm_replay_notify_bmp, 511 .notify = xfrm_replay_notify_bmp,
497 .overflow = xfrm_replay_overflow_esn, 512 .overflow = xfrm_replay_overflow_esn,
498}; 513};