Commit 428d2459 authored by Petr Vaněk's avatar Petr Vaněk Committed by Steffen Klassert

xfrm: introduce oseq-may-wrap flag

RFC 4303 in section 3.3.3 suggests to disable anti-replay for manually
distributed ICVs in which case the sender does not need to monitor or
reset the counter. However, the sender still increments the counter and
when it reaches the maximum value, the counter rolls over back to zero.

This patch introduces new extra_flag XFRM_SA_XFLAG_OSEQ_MAY_WRAP which
allows sequence number to cycle in outbound packets if set. This flag is
used only in legacy and bmp code, because esn should not be negotiated
if anti-replay is disabled (see note in 3.3.3 section).
Signed-off-by: default avatarPetr Vaněk <pv@excello.cz>
Acked-by: default avatarChristophe Gouault <christophe.gouault@6wind.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 8af7b452
...@@ -387,6 +387,7 @@ struct xfrm_usersa_info { ...@@ -387,6 +387,7 @@ struct xfrm_usersa_info {
}; };
#define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1 #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1
#define XFRM_SA_XFLAG_OSEQ_MAY_WRAP 2
struct xfrm_usersa_id { struct xfrm_usersa_id {
xfrm_address_t daddr; xfrm_address_t daddr;
......
...@@ -89,7 +89,8 @@ static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb) ...@@ -89,7 +89,8 @@ static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq; XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
XFRM_SKB_CB(skb)->seq.output.hi = 0; XFRM_SKB_CB(skb)->seq.output.hi = 0;
if (unlikely(x->replay.oseq == 0)) { if (unlikely(x->replay.oseq == 0) &&
!(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
x->replay.oseq--; x->replay.oseq--;
xfrm_audit_state_replay_overflow(x, skb); xfrm_audit_state_replay_overflow(x, skb);
err = -EOVERFLOW; err = -EOVERFLOW;
...@@ -168,7 +169,8 @@ static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb) ...@@ -168,7 +169,8 @@ static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq; XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
XFRM_SKB_CB(skb)->seq.output.hi = 0; XFRM_SKB_CB(skb)->seq.output.hi = 0;
if (unlikely(replay_esn->oseq == 0)) { if (unlikely(replay_esn->oseq == 0) &&
!(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
replay_esn->oseq--; replay_esn->oseq--;
xfrm_audit_state_replay_overflow(x, skb); xfrm_audit_state_replay_overflow(x, skb);
err = -EOVERFLOW; err = -EOVERFLOW;
...@@ -572,7 +574,8 @@ static int xfrm_replay_overflow_offload(struct xfrm_state *x, struct sk_buff *sk ...@@ -572,7 +574,8 @@ static int xfrm_replay_overflow_offload(struct xfrm_state *x, struct sk_buff *sk
XFRM_SKB_CB(skb)->seq.output.hi = 0; XFRM_SKB_CB(skb)->seq.output.hi = 0;
xo->seq.hi = 0; xo->seq.hi = 0;
if (unlikely(oseq < x->replay.oseq)) { if (unlikely(oseq < x->replay.oseq) &&
!(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
xfrm_audit_state_replay_overflow(x, skb); xfrm_audit_state_replay_overflow(x, skb);
err = -EOVERFLOW; err = -EOVERFLOW;
...@@ -611,7 +614,8 @@ static int xfrm_replay_overflow_offload_bmp(struct xfrm_state *x, struct sk_buff ...@@ -611,7 +614,8 @@ static int xfrm_replay_overflow_offload_bmp(struct xfrm_state *x, struct sk_buff
XFRM_SKB_CB(skb)->seq.output.hi = 0; XFRM_SKB_CB(skb)->seq.output.hi = 0;
xo->seq.hi = 0; xo->seq.hi = 0;
if (unlikely(oseq < replay_esn->oseq)) { if (unlikely(oseq < replay_esn->oseq) &&
!(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
xfrm_audit_state_replay_overflow(x, skb); xfrm_audit_state_replay_overflow(x, skb);
err = -EOVERFLOW; err = -EOVERFLOW;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment