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