• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
xfrm_replay_seqhi(struct xfrm_state * x,__be32 net_seq)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 
xfrm_replay_notify(struct xfrm_state * x,int event)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 
__xfrm_replay_overflow(struct xfrm_state * x,struct sk_buff * skb)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 
xfrm_replay_check_legacy(struct xfrm_state * x,struct sk_buff * skb,__be32 net_seq)121 static int xfrm_replay_check_legacy(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 
xfrm_replay_advance(struct xfrm_state * x,__be32 net_seq)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 
xfrm_replay_overflow_bmp(struct xfrm_state * x,struct sk_buff * skb)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 
xfrm_replay_check_bmp(struct xfrm_state * x,struct sk_buff * skb,__be32 net_seq)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 
xfrm_replay_advance_bmp(struct xfrm_state * x,__be32 net_seq)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 
xfrm_replay_notify_bmp(struct xfrm_state * x,int event)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 
xfrm_replay_notify_esn(struct xfrm_state * x,int event)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 
xfrm_replay_overflow_esn(struct xfrm_state * x,struct sk_buff * skb)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 
xfrm_replay_check_esn(struct xfrm_state * x,struct sk_buff * skb,__be32 net_seq)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 
xfrm_replay_check(struct xfrm_state * x,struct sk_buff * skb,__be32 net_seq)510 int xfrm_replay_check(struct xfrm_state *x,
511 		      struct sk_buff *skb, __be32 net_seq)
512 {
513 	switch (x->repl_mode) {
514 	case XFRM_REPLAY_MODE_LEGACY:
515 		break;
516 	case XFRM_REPLAY_MODE_BMP:
517 		return xfrm_replay_check_bmp(x, skb, net_seq);
518 	case XFRM_REPLAY_MODE_ESN:
519 		return xfrm_replay_check_esn(x, skb, net_seq);
520 	}
521 
522 	return xfrm_replay_check_legacy(x, skb, net_seq);
523 }
524 
xfrm_replay_recheck_esn(struct xfrm_state * x,struct sk_buff * skb,__be32 net_seq)525 static int xfrm_replay_recheck_esn(struct xfrm_state *x,
526 				   struct sk_buff *skb, __be32 net_seq)
527 {
528 	if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi !=
529 		     htonl(xfrm_replay_seqhi(x, net_seq)))) {
530 			x->stats.replay_window++;
531 			return -EINVAL;
532 	}
533 
534 	return xfrm_replay_check_esn(x, skb, net_seq);
535 }
536 
xfrm_replay_recheck(struct xfrm_state * x,struct sk_buff * skb,__be32 net_seq)537 int xfrm_replay_recheck(struct xfrm_state *x,
538 			struct sk_buff *skb, __be32 net_seq)
539 {
540 	switch (x->repl_mode) {
541 	case XFRM_REPLAY_MODE_LEGACY:
542 		break;
543 	case XFRM_REPLAY_MODE_BMP:
544 		/* no special recheck treatment */
545 		return xfrm_replay_check_bmp(x, skb, net_seq);
546 	case XFRM_REPLAY_MODE_ESN:
547 		return xfrm_replay_recheck_esn(x, skb, net_seq);
548 	}
549 
550 	return xfrm_replay_check_legacy(x, skb, net_seq);
551 }
552 
xfrm_replay_advance_esn(struct xfrm_state * x,__be32 net_seq)553 static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
554 {
555 	unsigned int bitnr, nr, i;
556 	int wrap;
557 	u32 diff, pos, seq, seq_hi;
558 	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
559 
560 	if (!replay_esn->replay_window)
561 		return;
562 
563 	seq = ntohl(net_seq);
564 	pos = (replay_esn->seq - 1) % replay_esn->replay_window;
565 	seq_hi = xfrm_replay_seqhi(x, net_seq);
566 	wrap = seq_hi - replay_esn->seq_hi;
567 
568 	if ((!wrap && seq > replay_esn->seq) || wrap > 0) {
569 		if (likely(!wrap))
570 			diff = seq - replay_esn->seq;
571 		else
572 			diff = ~replay_esn->seq + seq + 1;
573 
574 		if (diff < replay_esn->replay_window) {
575 			for (i = 1; i < diff; i++) {
576 				bitnr = (pos + i) % replay_esn->replay_window;
577 				nr = bitnr >> 5;
578 				bitnr = bitnr & 0x1F;
579 				replay_esn->bmp[nr] &=  ~(1U << bitnr);
580 			}
581 		} else {
582 			nr = (replay_esn->replay_window - 1) >> 5;
583 			for (i = 0; i <= nr; i++)
584 				replay_esn->bmp[i] = 0;
585 		}
586 
587 		bitnr = (pos + diff) % replay_esn->replay_window;
588 		replay_esn->seq = seq;
589 
590 		if (unlikely(wrap > 0))
591 			replay_esn->seq_hi++;
592 	} else {
593 		diff = replay_esn->seq - seq;
594 
595 		if (pos >= diff)
596 			bitnr = (pos - diff) % replay_esn->replay_window;
597 		else
598 			bitnr = replay_esn->replay_window - (diff - pos);
599 	}
600 
601 	xfrm_dev_state_advance_esn(x);
602 
603 	nr = bitnr >> 5;
604 	bitnr = bitnr & 0x1F;
605 	replay_esn->bmp[nr] |= (1U << bitnr);
606 
607 	if (xfrm_aevent_is_on(xs_net(x)))
608 		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
609 }
610 
611 #ifdef CONFIG_XFRM_OFFLOAD
xfrm_replay_overflow_offload(struct xfrm_state * x,struct sk_buff * skb)612 static int xfrm_replay_overflow_offload(struct xfrm_state *x, struct sk_buff *skb)
613 {
614 	int err = 0;
615 	struct net *net = xs_net(x);
616 	struct xfrm_offload *xo = xfrm_offload(skb);
617 	__u32 oseq = x->replay.oseq;
618 
619 	if (!xo)
620 		return __xfrm_replay_overflow(x, skb);
621 
622 	if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
623 		if (!skb_is_gso(skb)) {
624 			XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
625 			xo->seq.low = oseq;
626 		} else {
627 			XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
628 			xo->seq.low = oseq + 1;
629 			oseq += skb_shinfo(skb)->gso_segs;
630 		}
631 
632 		XFRM_SKB_CB(skb)->seq.output.hi = 0;
633 		xo->seq.hi = 0;
634 		if (unlikely(oseq < x->replay.oseq) &&
635 		    !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
636 			xfrm_audit_state_replay_overflow(x, skb);
637 			err = -EOVERFLOW;
638 
639 			return err;
640 		}
641 
642 		x->replay.oseq = oseq;
643 
644 		if (xfrm_aevent_is_on(net))
645 			xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
646 	}
647 
648 	return err;
649 }
650 
xfrm_replay_overflow_offload_bmp(struct xfrm_state * x,struct sk_buff * skb)651 static int xfrm_replay_overflow_offload_bmp(struct xfrm_state *x, struct sk_buff *skb)
652 {
653 	int err = 0;
654 	struct xfrm_offload *xo = xfrm_offload(skb);
655 	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
656 	struct net *net = xs_net(x);
657 	__u32 oseq = replay_esn->oseq;
658 
659 	if (!xo)
660 		return xfrm_replay_overflow_bmp(x, skb);
661 
662 	if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
663 		if (!skb_is_gso(skb)) {
664 			XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
665 			xo->seq.low = oseq;
666 		} else {
667 			XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
668 			xo->seq.low = oseq + 1;
669 			oseq += skb_shinfo(skb)->gso_segs;
670 		}
671 
672 		XFRM_SKB_CB(skb)->seq.output.hi = 0;
673 		xo->seq.hi = 0;
674 		if (unlikely(oseq < replay_esn->oseq) &&
675 		    !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
676 			xfrm_audit_state_replay_overflow(x, skb);
677 			err = -EOVERFLOW;
678 
679 			return err;
680 		} else {
681 			replay_esn->oseq = oseq;
682 		}
683 
684 		if (xfrm_aevent_is_on(net))
685 			xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
686 	}
687 
688 	return err;
689 }
690 
xfrm_replay_overflow_offload_esn(struct xfrm_state * x,struct sk_buff * skb)691 static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff *skb)
692 {
693 	int err = 0;
694 	struct xfrm_offload *xo = xfrm_offload(skb);
695 	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
696 	struct net *net = xs_net(x);
697 	__u32 oseq = replay_esn->oseq;
698 	__u32 oseq_hi = replay_esn->oseq_hi;
699 
700 	if (!xo)
701 		return xfrm_replay_overflow_esn(x, skb);
702 
703 	if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
704 		if (!skb_is_gso(skb)) {
705 			XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
706 			XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
707 			xo->seq.low = oseq;
708 			xo->seq.hi = oseq_hi;
709 		} else {
710 			XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
711 			XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
712 			xo->seq.low = oseq + 1;
713 			xo->seq.hi = oseq_hi;
714 			oseq += skb_shinfo(skb)->gso_segs;
715 		}
716 
717 		if (unlikely(xo->seq.low < replay_esn->oseq)) {
718 			XFRM_SKB_CB(skb)->seq.output.hi = ++oseq_hi;
719 			xo->seq.hi = oseq_hi;
720 			replay_esn->oseq_hi = oseq_hi;
721 			if (replay_esn->oseq_hi == 0) {
722 				replay_esn->oseq--;
723 				replay_esn->oseq_hi--;
724 				xfrm_audit_state_replay_overflow(x, skb);
725 				err = -EOVERFLOW;
726 
727 				return err;
728 			}
729 		}
730 
731 		replay_esn->oseq = oseq;
732 
733 		if (xfrm_aevent_is_on(net))
734 			xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
735 	}
736 
737 	return err;
738 }
739 
xfrm_replay_overflow(struct xfrm_state * x,struct sk_buff * skb)740 int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
741 {
742 	switch (x->repl_mode) {
743 	case XFRM_REPLAY_MODE_LEGACY:
744 		break;
745 	case XFRM_REPLAY_MODE_BMP:
746 		return xfrm_replay_overflow_offload_bmp(x, skb);
747 	case XFRM_REPLAY_MODE_ESN:
748 		return xfrm_replay_overflow_offload_esn(x, skb);
749 	}
750 
751 	return xfrm_replay_overflow_offload(x, skb);
752 }
753 #else
xfrm_replay_overflow(struct xfrm_state * x,struct sk_buff * skb)754 int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
755 {
756 	switch (x->repl_mode) {
757 	case XFRM_REPLAY_MODE_LEGACY:
758 		break;
759 	case XFRM_REPLAY_MODE_BMP:
760 		return xfrm_replay_overflow_bmp(x, skb);
761 	case XFRM_REPLAY_MODE_ESN:
762 		return xfrm_replay_overflow_esn(x, skb);
763 	}
764 
765 	return __xfrm_replay_overflow(x, skb);
766 }
767 #endif
768 
xfrm_init_replay(struct xfrm_state * x)769 int xfrm_init_replay(struct xfrm_state *x)
770 {
771 	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
772 
773 	if (replay_esn) {
774 		if (replay_esn->replay_window >
775 		    replay_esn->bmp_len * sizeof(__u32) * 8)
776 			return -EINVAL;
777 
778 		if (x->props.flags & XFRM_STATE_ESN) {
779 			if (replay_esn->replay_window == 0)
780 				return -EINVAL;
781 			x->repl_mode = XFRM_REPLAY_MODE_ESN;
782 		} else {
783 			x->repl_mode = XFRM_REPLAY_MODE_BMP;
784 		}
785 	} else {
786 		x->repl_mode = XFRM_REPLAY_MODE_LEGACY;
787 	}
788 
789 	return 0;
790 }
791 EXPORT_SYMBOL(xfrm_init_replay);
792