^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010 secunet Security Networks AG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <net/xfrm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) u32 seq, seq_hi, bottom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) if (!(x->props.flags & XFRM_STATE_ESN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) seq = ntohl(net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) seq_hi = replay_esn->seq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) bottom = replay_esn->seq - replay_esn->replay_window + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (likely(replay_esn->seq >= replay_esn->replay_window - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /* A. same subspace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (unlikely(seq < bottom))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) seq_hi++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* B. window spans two subspaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (unlikely(seq >= bottom))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) seq_hi--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return seq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) EXPORT_SYMBOL(xfrm_replay_seqhi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void xfrm_replay_notify(struct xfrm_state *x, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct km_event c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* we send notify messages in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * 1. we updated on of the sequence numbers, and the seqno difference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * is at least x->replay_maxdiff, in this case we also update the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * timeout of our timer function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * 2. if x->replay_maxage has elapsed since last update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * and there were changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * The state structure must be locked!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) case XFRM_REPLAY_UPDATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (!x->replay_maxdiff ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ((x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (x->xflags & XFRM_TIME_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) event = XFRM_REPLAY_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case XFRM_REPLAY_TIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (memcmp(&x->replay, &x->preplay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) sizeof(struct xfrm_replay_state)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) x->xflags |= XFRM_TIME_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) c.event = XFRM_MSG_NEWAE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) c.data.aevent = event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) km_state_notify(x, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (x->replay_maxage &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) x->xflags &= ~XFRM_TIME_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct net *net = xs_net(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) XFRM_SKB_CB(skb)->seq.output.hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (unlikely(x->replay.oseq == 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) x->replay.oseq--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) xfrm_audit_state_replay_overflow(x, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) err = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (xfrm_aevent_is_on(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) x->repl->notify(x, XFRM_REPLAY_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static int xfrm_replay_check(struct xfrm_state *x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct sk_buff *skb, __be32 net_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u32 diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u32 seq = ntohl(net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!x->props.replay_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (unlikely(seq == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (likely(seq > x->replay.seq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) diff = x->replay.seq - seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (diff >= x->props.replay_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) x->stats.replay_window++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (x->replay.bitmap & (1U << diff)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) x->stats.replay++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) xfrm_audit_state_replay(x, skb, net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) u32 diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) u32 seq = ntohl(net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (!x->props.replay_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (seq > x->replay.seq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) diff = seq - x->replay.seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (diff < x->props.replay_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) x->replay.bitmap = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) x->replay.seq = seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) diff = x->replay.seq - seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) x->replay.bitmap |= (1U << diff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (xfrm_aevent_is_on(xs_net(x)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) x->repl->notify(x, XFRM_REPLAY_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct net *net = xs_net(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) XFRM_SKB_CB(skb)->seq.output.hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (unlikely(replay_esn->oseq == 0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) replay_esn->oseq--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) xfrm_audit_state_replay_overflow(x, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) err = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (xfrm_aevent_is_on(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) x->repl->notify(x, XFRM_REPLAY_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static int xfrm_replay_check_bmp(struct xfrm_state *x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct sk_buff *skb, __be32 net_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned int bitnr, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u32 pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u32 seq = ntohl(net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u32 diff = replay_esn->seq - seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (!replay_esn->replay_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (unlikely(seq == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (likely(seq > replay_esn->seq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (diff >= replay_esn->replay_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) x->stats.replay_window++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) pos = (replay_esn->seq - 1) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (pos >= diff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) bitnr = (pos - diff) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) bitnr = replay_esn->replay_window - (diff - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) nr = bitnr >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) bitnr = bitnr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (replay_esn->bmp[nr] & (1U << bitnr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) goto err_replay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) err_replay:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) x->stats.replay++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) xfrm_audit_state_replay(x, skb, net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) unsigned int bitnr, nr, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) u32 diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u32 seq = ntohl(net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u32 pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!replay_esn->replay_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) pos = (replay_esn->seq - 1) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (seq > replay_esn->seq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) diff = seq - replay_esn->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (diff < replay_esn->replay_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) for (i = 1; i < diff; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) bitnr = (pos + i) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) nr = bitnr >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) bitnr = bitnr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) replay_esn->bmp[nr] &= ~(1U << bitnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) nr = (replay_esn->replay_window - 1) >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) for (i = 0; i <= nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) replay_esn->bmp[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) bitnr = (pos + diff) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) replay_esn->seq = seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) diff = replay_esn->seq - seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (pos >= diff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) bitnr = (pos - diff) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) bitnr = replay_esn->replay_window - (diff - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) nr = bitnr >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) bitnr = bitnr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) replay_esn->bmp[nr] |= (1U << bitnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (xfrm_aevent_is_on(xs_net(x)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) x->repl->notify(x, XFRM_REPLAY_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct km_event c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* we send notify messages in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * 1. we updated on of the sequence numbers, and the seqno difference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * is at least x->replay_maxdiff, in this case we also update the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * timeout of our timer function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * 2. if x->replay_maxage has elapsed since last update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * and there were changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * The state structure must be locked!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) case XFRM_REPLAY_UPDATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!x->replay_maxdiff ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) ((replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) (replay_esn->oseq - preplay_esn->oseq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) < x->replay_maxdiff))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (x->xflags & XFRM_TIME_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) event = XFRM_REPLAY_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case XFRM_REPLAY_TIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (memcmp(x->replay_esn, x->preplay_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) xfrm_replay_state_esn_len(replay_esn)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) x->xflags |= XFRM_TIME_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) memcpy(x->preplay_esn, x->replay_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) xfrm_replay_state_esn_len(replay_esn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) c.event = XFRM_MSG_NEWAE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) c.data.aevent = event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) km_state_notify(x, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (x->replay_maxage &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) x->xflags &= ~XFRM_TIME_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) u32 seq_diff, oseq_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct km_event c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* we send notify messages in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * 1. we updated on of the sequence numbers, and the seqno difference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * is at least x->replay_maxdiff, in this case we also update the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * timeout of our timer function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * 2. if x->replay_maxage has elapsed since last update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * and there were changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * The state structure must be locked!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) case XFRM_REPLAY_UPDATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (x->replay_maxdiff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (replay_esn->seq_hi == preplay_esn->seq_hi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) seq_diff = replay_esn->seq - preplay_esn->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) seq_diff = ~preplay_esn->seq + replay_esn->seq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) oseq_diff = replay_esn->oseq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) - preplay_esn->oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) oseq_diff = ~preplay_esn->oseq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) + replay_esn->oseq + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (seq_diff >= x->replay_maxdiff ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) oseq_diff >= x->replay_maxdiff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (x->xflags & XFRM_TIME_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) event = XFRM_REPLAY_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case XFRM_REPLAY_TIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (memcmp(x->replay_esn, x->preplay_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) xfrm_replay_state_esn_len(replay_esn)) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) x->xflags |= XFRM_TIME_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) memcpy(x->preplay_esn, x->replay_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) xfrm_replay_state_esn_len(replay_esn));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) c.event = XFRM_MSG_NEWAE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) c.data.aevent = event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) km_state_notify(x, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (x->replay_maxage &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) x->xflags &= ~XFRM_TIME_DEFER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct net *net = xs_net(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) XFRM_SKB_CB(skb)->seq.output.hi = replay_esn->oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (unlikely(replay_esn->oseq == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) XFRM_SKB_CB(skb)->seq.output.hi = ++replay_esn->oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (replay_esn->oseq_hi == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) replay_esn->oseq--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) replay_esn->oseq_hi--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) xfrm_audit_state_replay_overflow(x, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) err = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (xfrm_aevent_is_on(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) x->repl->notify(x, XFRM_REPLAY_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int xfrm_replay_check_esn(struct xfrm_state *x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct sk_buff *skb, __be32 net_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned int bitnr, nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) u32 diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) u32 pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) u32 seq = ntohl(net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) u32 wsize = replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) u32 top = replay_esn->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) u32 bottom = top - wsize + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (!wsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (unlikely(seq == 0 && replay_esn->seq_hi == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) (replay_esn->seq < replay_esn->replay_window - 1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) diff = top - seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (likely(top >= wsize - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /* A. same subspace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (likely(seq > top) || seq < bottom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* B. window spans two subspaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (likely(seq > top && seq < bottom))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (seq >= bottom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) diff = ~seq + top + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (diff >= replay_esn->replay_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) x->stats.replay_window++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) pos = (replay_esn->seq - 1) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (pos >= diff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) bitnr = (pos - diff) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) bitnr = replay_esn->replay_window - (diff - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) nr = bitnr >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) bitnr = bitnr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (replay_esn->bmp[nr] & (1U << bitnr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) goto err_replay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) err_replay:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) x->stats.replay++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) xfrm_audit_state_replay(x, skb, net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static int xfrm_replay_recheck_esn(struct xfrm_state *x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct sk_buff *skb, __be32 net_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) htonl(xfrm_replay_seqhi(x, net_seq)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) x->stats.replay_window++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return xfrm_replay_check_esn(x, skb, net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) unsigned int bitnr, nr, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int wrap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) u32 diff, pos, seq, seq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (!replay_esn->replay_window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) seq = ntohl(net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) pos = (replay_esn->seq - 1) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) seq_hi = xfrm_replay_seqhi(x, net_seq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) wrap = seq_hi - replay_esn->seq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if ((!wrap && seq > replay_esn->seq) || wrap > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (likely(!wrap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) diff = seq - replay_esn->seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) diff = ~replay_esn->seq + seq + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (diff < replay_esn->replay_window) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) for (i = 1; i < diff; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) bitnr = (pos + i) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) nr = bitnr >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) bitnr = bitnr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) replay_esn->bmp[nr] &= ~(1U << bitnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) nr = (replay_esn->replay_window - 1) >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) for (i = 0; i <= nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) replay_esn->bmp[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) bitnr = (pos + diff) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) replay_esn->seq = seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (unlikely(wrap > 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) replay_esn->seq_hi++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) diff = replay_esn->seq - seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (pos >= diff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) bitnr = (pos - diff) % replay_esn->replay_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) bitnr = replay_esn->replay_window - (diff - pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) xfrm_dev_state_advance_esn(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) nr = bitnr >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) bitnr = bitnr & 0x1F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) replay_esn->bmp[nr] |= (1U << bitnr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (xfrm_aevent_is_on(xs_net(x)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) x->repl->notify(x, XFRM_REPLAY_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) #ifdef CONFIG_XFRM_OFFLOAD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static int xfrm_replay_overflow_offload(struct xfrm_state *x, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct net *net = xs_net(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct xfrm_offload *xo = xfrm_offload(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) __u32 oseq = x->replay.oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!xo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return xfrm_replay_overflow(x, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (!skb_is_gso(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) xo->seq.low = oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) xo->seq.low = oseq + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) oseq += skb_shinfo(skb)->gso_segs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) XFRM_SKB_CB(skb)->seq.output.hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) xo->seq.hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (unlikely(oseq < x->replay.oseq) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) xfrm_audit_state_replay_overflow(x, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) err = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) x->replay.oseq = oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (xfrm_aevent_is_on(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) x->repl->notify(x, XFRM_REPLAY_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) static int xfrm_replay_overflow_offload_bmp(struct xfrm_state *x, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) struct xfrm_offload *xo = xfrm_offload(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct net *net = xs_net(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) __u32 oseq = replay_esn->oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (!xo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return xfrm_replay_overflow_bmp(x, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (!skb_is_gso(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) xo->seq.low = oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) xo->seq.low = oseq + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) oseq += skb_shinfo(skb)->gso_segs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) XFRM_SKB_CB(skb)->seq.output.hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) xo->seq.hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (unlikely(oseq < replay_esn->oseq) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) xfrm_audit_state_replay_overflow(x, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) err = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) replay_esn->oseq = oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (xfrm_aevent_is_on(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) x->repl->notify(x, XFRM_REPLAY_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) struct xfrm_offload *xo = xfrm_offload(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) struct net *net = xs_net(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) __u32 oseq = replay_esn->oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) __u32 oseq_hi = replay_esn->oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (!xo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) return xfrm_replay_overflow_esn(x, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (!skb_is_gso(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) xo->seq.low = oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) xo->seq.hi = oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) xo->seq.low = oseq + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) xo->seq.hi = oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) oseq += skb_shinfo(skb)->gso_segs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (unlikely(oseq < replay_esn->oseq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) XFRM_SKB_CB(skb)->seq.output.hi = ++oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) xo->seq.hi = oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) replay_esn->oseq_hi = oseq_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (replay_esn->oseq_hi == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) replay_esn->oseq--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) replay_esn->oseq_hi--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) xfrm_audit_state_replay_overflow(x, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) err = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) replay_esn->oseq = oseq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (xfrm_aevent_is_on(net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) x->repl->notify(x, XFRM_REPLAY_UPDATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static const struct xfrm_replay xfrm_replay_legacy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) .advance = xfrm_replay_advance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) .check = xfrm_replay_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) .recheck = xfrm_replay_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) .notify = xfrm_replay_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) .overflow = xfrm_replay_overflow_offload,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static const struct xfrm_replay xfrm_replay_bmp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) .advance = xfrm_replay_advance_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .check = xfrm_replay_check_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .recheck = xfrm_replay_check_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) .notify = xfrm_replay_notify_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .overflow = xfrm_replay_overflow_offload_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static const struct xfrm_replay xfrm_replay_esn = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .advance = xfrm_replay_advance_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) .check = xfrm_replay_check_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) .recheck = xfrm_replay_recheck_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) .notify = xfrm_replay_notify_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) .overflow = xfrm_replay_overflow_offload_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) static const struct xfrm_replay xfrm_replay_legacy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) .advance = xfrm_replay_advance,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) .check = xfrm_replay_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) .recheck = xfrm_replay_check,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) .notify = xfrm_replay_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) .overflow = xfrm_replay_overflow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static const struct xfrm_replay xfrm_replay_bmp = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) .advance = xfrm_replay_advance_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) .check = xfrm_replay_check_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) .recheck = xfrm_replay_check_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .notify = xfrm_replay_notify_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) .overflow = xfrm_replay_overflow_bmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static const struct xfrm_replay xfrm_replay_esn = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) .advance = xfrm_replay_advance_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) .check = xfrm_replay_check_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) .recheck = xfrm_replay_recheck_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) .notify = xfrm_replay_notify_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) .overflow = xfrm_replay_overflow_esn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) int xfrm_init_replay(struct xfrm_state *x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (replay_esn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (replay_esn->replay_window >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) replay_esn->bmp_len * sizeof(__u32) * 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (x->props.flags & XFRM_STATE_ESN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (replay_esn->replay_window == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) x->repl = &xfrm_replay_esn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) x->repl = &xfrm_replay_bmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) x->repl = &xfrm_replay_legacy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) EXPORT_SYMBOL(xfrm_init_replay);