Lines Matching +full:xo +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0-only
3 * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
15 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_seqhi()
17 if (!(x->props.flags & XFRM_STATE_ESN)) in xfrm_replay_seqhi()
21 seq_hi = replay_esn->seq_hi; in xfrm_replay_seqhi()
22 bottom = replay_esn->seq - replay_esn->replay_window + 1; in xfrm_replay_seqhi()
24 if (likely(replay_esn->seq >= replay_esn->replay_window - 1)) { in xfrm_replay_seqhi()
31 seq_hi--; in xfrm_replay_seqhi()
45 * 1. we updated on of the sequence numbers, and the seqno difference in xfrm_replay_notify()
46 * is at least x->replay_maxdiff, in this case we also update the in xfrm_replay_notify()
48 * 2. if x->replay_maxage has elapsed since last update, in xfrm_replay_notify()
54 switch (x->repl_mode) { in xfrm_replay_notify()
67 if (!x->replay_maxdiff || in xfrm_replay_notify()
68 ((x->replay.seq - x->preplay.seq < x->replay_maxdiff) && in xfrm_replay_notify()
69 (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))) { in xfrm_replay_notify()
70 if (x->xflags & XFRM_TIME_DEFER) in xfrm_replay_notify()
79 if (memcmp(&x->replay, &x->preplay, in xfrm_replay_notify()
81 x->xflags |= XFRM_TIME_DEFER; in xfrm_replay_notify()
88 memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state)); in xfrm_replay_notify()
93 if (x->replay_maxage && in xfrm_replay_notify()
94 !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) in xfrm_replay_notify()
95 x->xflags &= ~XFRM_TIME_DEFER; in xfrm_replay_notify()
103 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { in __xfrm_replay_overflow()
104 XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq; in __xfrm_replay_overflow()
105 XFRM_SKB_CB(skb)->seq.output.hi = 0; in __xfrm_replay_overflow()
106 if (unlikely(x->replay.oseq == 0) && in __xfrm_replay_overflow()
107 !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) { in __xfrm_replay_overflow()
108 x->replay.oseq--; in __xfrm_replay_overflow()
110 err = -EOVERFLOW; in __xfrm_replay_overflow()
127 if (!x->props.replay_window) in xfrm_replay_check_legacy()
133 if (likely(seq > x->replay.seq)) in xfrm_replay_check_legacy()
136 diff = x->replay.seq - seq; in xfrm_replay_check_legacy()
137 if (diff >= x->props.replay_window) { in xfrm_replay_check_legacy()
138 x->stats.replay_window++; in xfrm_replay_check_legacy()
142 if (x->replay.bitmap & (1U << diff)) { in xfrm_replay_check_legacy()
143 x->stats.replay++; in xfrm_replay_check_legacy()
150 return -EINVAL; in xfrm_replay_check_legacy()
160 switch (x->repl_mode) { in xfrm_replay_advance()
169 if (!x->props.replay_window) in xfrm_replay_advance()
173 if (seq > x->replay.seq) { in xfrm_replay_advance()
174 diff = seq - x->replay.seq; in xfrm_replay_advance()
175 if (diff < x->props.replay_window) in xfrm_replay_advance()
176 x->replay.bitmap = ((x->replay.bitmap) << diff) | 1; in xfrm_replay_advance()
178 x->replay.bitmap = 1; in xfrm_replay_advance()
179 x->replay.seq = seq; in xfrm_replay_advance()
181 diff = x->replay.seq - seq; in xfrm_replay_advance()
182 x->replay.bitmap |= (1U << diff); in xfrm_replay_advance()
192 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_overflow_bmp()
195 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { in xfrm_replay_overflow_bmp()
196 XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq; in xfrm_replay_overflow_bmp()
197 XFRM_SKB_CB(skb)->seq.output.hi = 0; in xfrm_replay_overflow_bmp()
198 if (unlikely(replay_esn->oseq == 0) && in xfrm_replay_overflow_bmp()
199 !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) { in xfrm_replay_overflow_bmp()
200 replay_esn->oseq--; in xfrm_replay_overflow_bmp()
202 err = -EOVERFLOW; in xfrm_replay_overflow_bmp()
217 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_check_bmp()
220 u32 diff = replay_esn->seq - seq; in xfrm_replay_check_bmp()
222 if (!replay_esn->replay_window) in xfrm_replay_check_bmp()
228 if (likely(seq > replay_esn->seq)) in xfrm_replay_check_bmp()
231 if (diff >= replay_esn->replay_window) { in xfrm_replay_check_bmp()
232 x->stats.replay_window++; in xfrm_replay_check_bmp()
236 pos = (replay_esn->seq - 1) % replay_esn->replay_window; in xfrm_replay_check_bmp()
239 bitnr = (pos - diff) % replay_esn->replay_window; in xfrm_replay_check_bmp()
241 bitnr = replay_esn->replay_window - (diff - pos); in xfrm_replay_check_bmp()
245 if (replay_esn->bmp[nr] & (1U << bitnr)) in xfrm_replay_check_bmp()
251 x->stats.replay++; in xfrm_replay_check_bmp()
254 return -EINVAL; in xfrm_replay_check_bmp()
261 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_advance_bmp()
265 if (!replay_esn->replay_window) in xfrm_replay_advance_bmp()
268 pos = (replay_esn->seq - 1) % replay_esn->replay_window; in xfrm_replay_advance_bmp()
270 if (seq > replay_esn->seq) { in xfrm_replay_advance_bmp()
271 diff = seq - replay_esn->seq; in xfrm_replay_advance_bmp()
273 if (diff < replay_esn->replay_window) { in xfrm_replay_advance_bmp()
274 for (i = 1; i < diff; i++) { in xfrm_replay_advance_bmp()
275 bitnr = (pos + i) % replay_esn->replay_window; in xfrm_replay_advance_bmp()
278 replay_esn->bmp[nr] &= ~(1U << bitnr); in xfrm_replay_advance_bmp()
281 nr = (replay_esn->replay_window - 1) >> 5; in xfrm_replay_advance_bmp()
283 replay_esn->bmp[i] = 0; in xfrm_replay_advance_bmp()
286 bitnr = (pos + diff) % replay_esn->replay_window; in xfrm_replay_advance_bmp()
287 replay_esn->seq = seq; in xfrm_replay_advance_bmp()
289 diff = replay_esn->seq - seq; in xfrm_replay_advance_bmp()
292 bitnr = (pos - diff) % replay_esn->replay_window; in xfrm_replay_advance_bmp()
294 bitnr = replay_esn->replay_window - (diff - pos); in xfrm_replay_advance_bmp()
299 replay_esn->bmp[nr] |= (1U << bitnr); in xfrm_replay_advance_bmp()
308 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_notify_bmp()
309 struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn; in xfrm_replay_notify_bmp()
312 * 1. we updated on of the sequence numbers, and the seqno difference in xfrm_replay_notify_bmp()
313 * is at least x->replay_maxdiff, in this case we also update the in xfrm_replay_notify_bmp()
315 * 2. if x->replay_maxage has elapsed since last update, in xfrm_replay_notify_bmp()
323 if (!x->replay_maxdiff || in xfrm_replay_notify_bmp()
324 ((replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) && in xfrm_replay_notify_bmp()
325 (replay_esn->oseq - preplay_esn->oseq in xfrm_replay_notify_bmp()
326 < x->replay_maxdiff))) { in xfrm_replay_notify_bmp()
327 if (x->xflags & XFRM_TIME_DEFER) in xfrm_replay_notify_bmp()
336 if (memcmp(x->replay_esn, x->preplay_esn, in xfrm_replay_notify_bmp()
338 x->xflags |= XFRM_TIME_DEFER; in xfrm_replay_notify_bmp()
345 memcpy(x->preplay_esn, x->replay_esn, in xfrm_replay_notify_bmp()
351 if (x->replay_maxage && in xfrm_replay_notify_bmp()
352 !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) in xfrm_replay_notify_bmp()
353 x->xflags &= ~XFRM_TIME_DEFER; in xfrm_replay_notify_bmp()
360 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_notify_esn()
361 struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn; in xfrm_replay_notify_esn()
364 * 1. we updated on of the sequence numbers, and the seqno difference in xfrm_replay_notify_esn()
365 * is at least x->replay_maxdiff, in this case we also update the in xfrm_replay_notify_esn()
367 * 2. if x->replay_maxage has elapsed since last update, in xfrm_replay_notify_esn()
375 if (x->replay_maxdiff) { in xfrm_replay_notify_esn()
376 if (replay_esn->seq_hi == preplay_esn->seq_hi) in xfrm_replay_notify_esn()
377 seq_diff = replay_esn->seq - preplay_esn->seq; in xfrm_replay_notify_esn()
379 seq_diff = ~preplay_esn->seq + replay_esn->seq in xfrm_replay_notify_esn()
380 + 1; in xfrm_replay_notify_esn()
382 if (replay_esn->oseq_hi == preplay_esn->oseq_hi) in xfrm_replay_notify_esn()
383 oseq_diff = replay_esn->oseq in xfrm_replay_notify_esn()
384 - preplay_esn->oseq; in xfrm_replay_notify_esn()
386 oseq_diff = ~preplay_esn->oseq in xfrm_replay_notify_esn()
387 + replay_esn->oseq + 1; in xfrm_replay_notify_esn()
389 if (seq_diff >= x->replay_maxdiff || in xfrm_replay_notify_esn()
390 oseq_diff >= x->replay_maxdiff) in xfrm_replay_notify_esn()
394 if (x->xflags & XFRM_TIME_DEFER) in xfrm_replay_notify_esn()
402 if (memcmp(x->replay_esn, x->preplay_esn, in xfrm_replay_notify_esn()
404 x->xflags |= XFRM_TIME_DEFER; in xfrm_replay_notify_esn()
411 memcpy(x->preplay_esn, x->replay_esn, in xfrm_replay_notify_esn()
417 if (x->replay_maxage && in xfrm_replay_notify_esn()
418 !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) in xfrm_replay_notify_esn()
419 x->xflags &= ~XFRM_TIME_DEFER; in xfrm_replay_notify_esn()
425 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_overflow_esn()
428 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { in xfrm_replay_overflow_esn()
429 XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq; in xfrm_replay_overflow_esn()
430 XFRM_SKB_CB(skb)->seq.output.hi = replay_esn->oseq_hi; in xfrm_replay_overflow_esn()
432 if (unlikely(replay_esn->oseq == 0)) { in xfrm_replay_overflow_esn()
433 XFRM_SKB_CB(skb)->seq.output.hi = ++replay_esn->oseq_hi; in xfrm_replay_overflow_esn()
435 if (replay_esn->oseq_hi == 0) { in xfrm_replay_overflow_esn()
436 replay_esn->oseq--; in xfrm_replay_overflow_esn()
437 replay_esn->oseq_hi--; in xfrm_replay_overflow_esn()
439 err = -EOVERFLOW; in xfrm_replay_overflow_esn()
456 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_check_esn()
459 u32 wsize = replay_esn->replay_window; in xfrm_replay_check_esn()
460 u32 top = replay_esn->seq; in xfrm_replay_check_esn()
461 u32 bottom = top - wsize + 1; in xfrm_replay_check_esn()
466 if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && in xfrm_replay_check_esn()
467 (replay_esn->seq < replay_esn->replay_window - 1))) in xfrm_replay_check_esn()
470 diff = top - seq; in xfrm_replay_check_esn()
472 if (likely(top >= wsize - 1)) { in xfrm_replay_check_esn()
481 diff = ~seq + top + 1; in xfrm_replay_check_esn()
484 if (diff >= replay_esn->replay_window) { in xfrm_replay_check_esn()
485 x->stats.replay_window++; in xfrm_replay_check_esn()
489 pos = (replay_esn->seq - 1) % replay_esn->replay_window; in xfrm_replay_check_esn()
492 bitnr = (pos - diff) % replay_esn->replay_window; in xfrm_replay_check_esn()
494 bitnr = replay_esn->replay_window - (diff - pos); in xfrm_replay_check_esn()
498 if (replay_esn->bmp[nr] & (1U << bitnr)) in xfrm_replay_check_esn()
504 x->stats.replay++; in xfrm_replay_check_esn()
507 return -EINVAL; in xfrm_replay_check_esn()
513 switch (x->repl_mode) { in xfrm_replay_check()
528 if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi != in xfrm_replay_recheck_esn()
530 x->stats.replay_window++; in xfrm_replay_recheck_esn()
531 return -EINVAL; in xfrm_replay_recheck_esn()
540 switch (x->repl_mode) { in xfrm_replay_recheck()
558 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_advance_esn()
560 if (!replay_esn->replay_window) in xfrm_replay_advance_esn()
564 pos = (replay_esn->seq - 1) % replay_esn->replay_window; in xfrm_replay_advance_esn()
566 wrap = seq_hi - replay_esn->seq_hi; in xfrm_replay_advance_esn()
568 if ((!wrap && seq > replay_esn->seq) || wrap > 0) { in xfrm_replay_advance_esn()
570 diff = seq - replay_esn->seq; in xfrm_replay_advance_esn()
572 diff = ~replay_esn->seq + seq + 1; in xfrm_replay_advance_esn()
574 if (diff < replay_esn->replay_window) { in xfrm_replay_advance_esn()
575 for (i = 1; i < diff; i++) { in xfrm_replay_advance_esn()
576 bitnr = (pos + i) % replay_esn->replay_window; in xfrm_replay_advance_esn()
579 replay_esn->bmp[nr] &= ~(1U << bitnr); in xfrm_replay_advance_esn()
582 nr = (replay_esn->replay_window - 1) >> 5; in xfrm_replay_advance_esn()
584 replay_esn->bmp[i] = 0; in xfrm_replay_advance_esn()
587 bitnr = (pos + diff) % replay_esn->replay_window; in xfrm_replay_advance_esn()
588 replay_esn->seq = seq; in xfrm_replay_advance_esn()
591 replay_esn->seq_hi++; in xfrm_replay_advance_esn()
593 diff = replay_esn->seq - seq; in xfrm_replay_advance_esn()
596 bitnr = (pos - diff) % replay_esn->replay_window; in xfrm_replay_advance_esn()
598 bitnr = replay_esn->replay_window - (diff - pos); in xfrm_replay_advance_esn()
605 replay_esn->bmp[nr] |= (1U << bitnr); in xfrm_replay_advance_esn()
616 struct xfrm_offload *xo = xfrm_offload(skb); in xfrm_replay_overflow_offload() local
617 __u32 oseq = x->replay.oseq; in xfrm_replay_overflow_offload()
619 if (!xo) in xfrm_replay_overflow_offload()
622 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { in xfrm_replay_overflow_offload()
624 XFRM_SKB_CB(skb)->seq.output.low = ++oseq; in xfrm_replay_overflow_offload()
625 xo->seq.low = oseq; in xfrm_replay_overflow_offload()
627 XFRM_SKB_CB(skb)->seq.output.low = oseq + 1; in xfrm_replay_overflow_offload()
628 xo->seq.low = oseq + 1; in xfrm_replay_overflow_offload()
629 oseq += skb_shinfo(skb)->gso_segs; in xfrm_replay_overflow_offload()
632 XFRM_SKB_CB(skb)->seq.output.hi = 0; in xfrm_replay_overflow_offload()
633 xo->seq.hi = 0; in xfrm_replay_overflow_offload()
634 if (unlikely(oseq < x->replay.oseq) && in xfrm_replay_overflow_offload()
635 !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) { in xfrm_replay_overflow_offload()
637 err = -EOVERFLOW; in xfrm_replay_overflow_offload()
642 x->replay.oseq = oseq; in xfrm_replay_overflow_offload()
654 struct xfrm_offload *xo = xfrm_offload(skb); in xfrm_replay_overflow_offload_bmp() local
655 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_overflow_offload_bmp()
657 __u32 oseq = replay_esn->oseq; in xfrm_replay_overflow_offload_bmp()
659 if (!xo) in xfrm_replay_overflow_offload_bmp()
662 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { in xfrm_replay_overflow_offload_bmp()
664 XFRM_SKB_CB(skb)->seq.output.low = ++oseq; in xfrm_replay_overflow_offload_bmp()
665 xo->seq.low = oseq; in xfrm_replay_overflow_offload_bmp()
667 XFRM_SKB_CB(skb)->seq.output.low = oseq + 1; in xfrm_replay_overflow_offload_bmp()
668 xo->seq.low = oseq + 1; in xfrm_replay_overflow_offload_bmp()
669 oseq += skb_shinfo(skb)->gso_segs; in xfrm_replay_overflow_offload_bmp()
672 XFRM_SKB_CB(skb)->seq.output.hi = 0; in xfrm_replay_overflow_offload_bmp()
673 xo->seq.hi = 0; in xfrm_replay_overflow_offload_bmp()
674 if (unlikely(oseq < replay_esn->oseq) && in xfrm_replay_overflow_offload_bmp()
675 !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) { in xfrm_replay_overflow_offload_bmp()
677 err = -EOVERFLOW; in xfrm_replay_overflow_offload_bmp()
681 replay_esn->oseq = oseq; in xfrm_replay_overflow_offload_bmp()
694 struct xfrm_offload *xo = xfrm_offload(skb); in xfrm_replay_overflow_offload_esn() local
695 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_replay_overflow_offload_esn()
697 __u32 oseq = replay_esn->oseq; in xfrm_replay_overflow_offload_esn()
698 __u32 oseq_hi = replay_esn->oseq_hi; in xfrm_replay_overflow_offload_esn()
700 if (!xo) in xfrm_replay_overflow_offload_esn()
703 if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { in xfrm_replay_overflow_offload_esn()
705 XFRM_SKB_CB(skb)->seq.output.low = ++oseq; in xfrm_replay_overflow_offload_esn()
706 XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi; in xfrm_replay_overflow_offload_esn()
707 xo->seq.low = oseq; in xfrm_replay_overflow_offload_esn()
708 xo->seq.hi = oseq_hi; in xfrm_replay_overflow_offload_esn()
710 XFRM_SKB_CB(skb)->seq.output.low = oseq + 1; in xfrm_replay_overflow_offload_esn()
711 XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi; in xfrm_replay_overflow_offload_esn()
712 xo->seq.low = oseq + 1; in xfrm_replay_overflow_offload_esn()
713 xo->seq.hi = oseq_hi; in xfrm_replay_overflow_offload_esn()
714 oseq += skb_shinfo(skb)->gso_segs; in xfrm_replay_overflow_offload_esn()
717 if (unlikely(xo->seq.low < replay_esn->oseq)) { in xfrm_replay_overflow_offload_esn()
718 XFRM_SKB_CB(skb)->seq.output.hi = ++oseq_hi; in xfrm_replay_overflow_offload_esn()
719 xo->seq.hi = oseq_hi; in xfrm_replay_overflow_offload_esn()
720 replay_esn->oseq_hi = oseq_hi; in xfrm_replay_overflow_offload_esn()
721 if (replay_esn->oseq_hi == 0) { in xfrm_replay_overflow_offload_esn()
722 replay_esn->oseq--; in xfrm_replay_overflow_offload_esn()
723 replay_esn->oseq_hi--; in xfrm_replay_overflow_offload_esn()
725 err = -EOVERFLOW; in xfrm_replay_overflow_offload_esn()
731 replay_esn->oseq = oseq; in xfrm_replay_overflow_offload_esn()
742 switch (x->repl_mode) { in xfrm_replay_overflow()
756 switch (x->repl_mode) { in xfrm_replay_overflow()
771 struct xfrm_replay_state_esn *replay_esn = x->replay_esn; in xfrm_init_replay()
774 if (replay_esn->replay_window > in xfrm_init_replay()
775 replay_esn->bmp_len * sizeof(__u32) * 8) { in xfrm_init_replay()
777 return -EINVAL; in xfrm_init_replay()
780 if (x->props.flags & XFRM_STATE_ESN) { in xfrm_init_replay()
781 if (replay_esn->replay_window == 0 && in xfrm_init_replay()
782 (!x->dir || x->dir == XFRM_SA_DIR_IN)) { in xfrm_init_replay()
784 return -EINVAL; in xfrm_init_replay()
786 x->repl_mode = XFRM_REPLAY_MODE_ESN; in xfrm_init_replay()
788 x->repl_mode = XFRM_REPLAY_MODE_BMP; in xfrm_init_replay()
791 x->repl_mode = XFRM_REPLAY_MODE_LEGACY; in xfrm_init_replay()