Merge tag 'tegra-for-5.14-rc3-arm64-dt' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / net / xfrm / xfrm_replay.c
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_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
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 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
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
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
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
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
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
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(oseq < 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
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
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
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);