Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
0004  *
0005  * Copyright (C) 2010 secunet Security Networks AG
0006  * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
0007  */
0008 
0009 #include <linux/export.h>
0010 #include <net/xfrm.h>
0011 
0012 u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq)
0013 {
0014     u32 seq, seq_hi, bottom;
0015     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0016 
0017     if (!(x->props.flags & XFRM_STATE_ESN))
0018         return 0;
0019 
0020     seq = ntohl(net_seq);
0021     seq_hi = replay_esn->seq_hi;
0022     bottom = replay_esn->seq - replay_esn->replay_window + 1;
0023 
0024     if (likely(replay_esn->seq >= replay_esn->replay_window - 1)) {
0025         /* A. same subspace */
0026         if (unlikely(seq < bottom))
0027             seq_hi++;
0028     } else {
0029         /* B. window spans two subspaces */
0030         if (unlikely(seq >= bottom))
0031             seq_hi--;
0032     }
0033 
0034     return seq_hi;
0035 }
0036 EXPORT_SYMBOL(xfrm_replay_seqhi);
0037 
0038 static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event);
0039 static void xfrm_replay_notify_esn(struct xfrm_state *x, int event);
0040 
0041 void xfrm_replay_notify(struct xfrm_state *x, int event)
0042 {
0043     struct km_event c;
0044     /* we send notify messages in case
0045      *  1. we updated on of the sequence numbers, and the seqno difference
0046      *     is at least x->replay_maxdiff, in this case we also update the
0047      *     timeout of our timer function
0048      *  2. if x->replay_maxage has elapsed since last update,
0049      *     and there were changes
0050      *
0051      *  The state structure must be locked!
0052      */
0053 
0054     switch (x->repl_mode) {
0055     case XFRM_REPLAY_MODE_LEGACY:
0056         break;
0057     case XFRM_REPLAY_MODE_BMP:
0058         xfrm_replay_notify_bmp(x, event);
0059         return;
0060     case XFRM_REPLAY_MODE_ESN:
0061         xfrm_replay_notify_esn(x, event);
0062         return;
0063     }
0064 
0065     switch (event) {
0066     case XFRM_REPLAY_UPDATE:
0067         if (!x->replay_maxdiff ||
0068             ((x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
0069             (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff))) {
0070             if (x->xflags & XFRM_TIME_DEFER)
0071                 event = XFRM_REPLAY_TIMEOUT;
0072             else
0073                 return;
0074         }
0075 
0076         break;
0077 
0078     case XFRM_REPLAY_TIMEOUT:
0079         if (memcmp(&x->replay, &x->preplay,
0080                sizeof(struct xfrm_replay_state)) == 0) {
0081             x->xflags |= XFRM_TIME_DEFER;
0082             return;
0083         }
0084 
0085         break;
0086     }
0087 
0088     memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
0089     c.event = XFRM_MSG_NEWAE;
0090     c.data.aevent = event;
0091     km_state_notify(x, &c);
0092 
0093     if (x->replay_maxage &&
0094         !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
0095         x->xflags &= ~XFRM_TIME_DEFER;
0096 }
0097 
0098 static int __xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
0099 {
0100     int err = 0;
0101     struct net *net = xs_net(x);
0102 
0103     if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
0104         XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
0105         XFRM_SKB_CB(skb)->seq.output.hi = 0;
0106         if (unlikely(x->replay.oseq == 0) &&
0107             !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
0108             x->replay.oseq--;
0109             xfrm_audit_state_replay_overflow(x, skb);
0110             err = -EOVERFLOW;
0111 
0112             return err;
0113         }
0114         if (xfrm_aevent_is_on(net))
0115             xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
0116     }
0117 
0118     return err;
0119 }
0120 
0121 static int xfrm_replay_check_legacy(struct xfrm_state *x,
0122                     struct sk_buff *skb, __be32 net_seq)
0123 {
0124     u32 diff;
0125     u32 seq = ntohl(net_seq);
0126 
0127     if (!x->props.replay_window)
0128         return 0;
0129 
0130     if (unlikely(seq == 0))
0131         goto err;
0132 
0133     if (likely(seq > x->replay.seq))
0134         return 0;
0135 
0136     diff = x->replay.seq - seq;
0137     if (diff >= x->props.replay_window) {
0138         x->stats.replay_window++;
0139         goto err;
0140     }
0141 
0142     if (x->replay.bitmap & (1U << diff)) {
0143         x->stats.replay++;
0144         goto err;
0145     }
0146     return 0;
0147 
0148 err:
0149     xfrm_audit_state_replay(x, skb, net_seq);
0150     return -EINVAL;
0151 }
0152 
0153 static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq);
0154 static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq);
0155 
0156 void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
0157 {
0158     u32 diff, seq;
0159 
0160     switch (x->repl_mode) {
0161     case XFRM_REPLAY_MODE_LEGACY:
0162         break;
0163     case XFRM_REPLAY_MODE_BMP:
0164         return xfrm_replay_advance_bmp(x, net_seq);
0165     case XFRM_REPLAY_MODE_ESN:
0166         return xfrm_replay_advance_esn(x, net_seq);
0167     }
0168 
0169     if (!x->props.replay_window)
0170         return;
0171 
0172     seq = ntohl(net_seq);
0173     if (seq > x->replay.seq) {
0174         diff = seq - x->replay.seq;
0175         if (diff < x->props.replay_window)
0176             x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;
0177         else
0178             x->replay.bitmap = 1;
0179         x->replay.seq = seq;
0180     } else {
0181         diff = x->replay.seq - seq;
0182         x->replay.bitmap |= (1U << diff);
0183     }
0184 
0185     if (xfrm_aevent_is_on(xs_net(x)))
0186         xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
0187 }
0188 
0189 static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
0190 {
0191     int err = 0;
0192     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0193     struct net *net = xs_net(x);
0194 
0195     if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
0196         XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
0197         XFRM_SKB_CB(skb)->seq.output.hi = 0;
0198         if (unlikely(replay_esn->oseq == 0) &&
0199             !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
0200             replay_esn->oseq--;
0201             xfrm_audit_state_replay_overflow(x, skb);
0202             err = -EOVERFLOW;
0203 
0204             return err;
0205         }
0206         if (xfrm_aevent_is_on(net))
0207             xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
0208     }
0209 
0210     return err;
0211 }
0212 
0213 static int xfrm_replay_check_bmp(struct xfrm_state *x,
0214                  struct sk_buff *skb, __be32 net_seq)
0215 {
0216     unsigned int bitnr, nr;
0217     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0218     u32 pos;
0219     u32 seq = ntohl(net_seq);
0220     u32 diff =  replay_esn->seq - seq;
0221 
0222     if (!replay_esn->replay_window)
0223         return 0;
0224 
0225     if (unlikely(seq == 0))
0226         goto err;
0227 
0228     if (likely(seq > replay_esn->seq))
0229         return 0;
0230 
0231     if (diff >= replay_esn->replay_window) {
0232         x->stats.replay_window++;
0233         goto err;
0234     }
0235 
0236     pos = (replay_esn->seq - 1) % replay_esn->replay_window;
0237 
0238     if (pos >= diff)
0239         bitnr = (pos - diff) % replay_esn->replay_window;
0240     else
0241         bitnr = replay_esn->replay_window - (diff - pos);
0242 
0243     nr = bitnr >> 5;
0244     bitnr = bitnr & 0x1F;
0245     if (replay_esn->bmp[nr] & (1U << bitnr))
0246         goto err_replay;
0247 
0248     return 0;
0249 
0250 err_replay:
0251     x->stats.replay++;
0252 err:
0253     xfrm_audit_state_replay(x, skb, net_seq);
0254     return -EINVAL;
0255 }
0256 
0257 static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq)
0258 {
0259     unsigned int bitnr, nr, i;
0260     u32 diff;
0261     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0262     u32 seq = ntohl(net_seq);
0263     u32 pos;
0264 
0265     if (!replay_esn->replay_window)
0266         return;
0267 
0268     pos = (replay_esn->seq - 1) % replay_esn->replay_window;
0269 
0270     if (seq > replay_esn->seq) {
0271         diff = seq - replay_esn->seq;
0272 
0273         if (diff < replay_esn->replay_window) {
0274             for (i = 1; i < diff; i++) {
0275                 bitnr = (pos + i) % replay_esn->replay_window;
0276                 nr = bitnr >> 5;
0277                 bitnr = bitnr & 0x1F;
0278                 replay_esn->bmp[nr] &=  ~(1U << bitnr);
0279             }
0280         } else {
0281             nr = (replay_esn->replay_window - 1) >> 5;
0282             for (i = 0; i <= nr; i++)
0283                 replay_esn->bmp[i] = 0;
0284         }
0285 
0286         bitnr = (pos + diff) % replay_esn->replay_window;
0287         replay_esn->seq = seq;
0288     } else {
0289         diff = replay_esn->seq - seq;
0290 
0291         if (pos >= diff)
0292             bitnr = (pos - diff) % replay_esn->replay_window;
0293         else
0294             bitnr = replay_esn->replay_window - (diff - pos);
0295     }
0296 
0297     nr = bitnr >> 5;
0298     bitnr = bitnr & 0x1F;
0299     replay_esn->bmp[nr] |= (1U << bitnr);
0300 
0301     if (xfrm_aevent_is_on(xs_net(x)))
0302         xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
0303 }
0304 
0305 static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
0306 {
0307     struct km_event c;
0308     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0309     struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
0310 
0311     /* we send notify messages in case
0312      *  1. we updated on of the sequence numbers, and the seqno difference
0313      *     is at least x->replay_maxdiff, in this case we also update the
0314      *     timeout of our timer function
0315      *  2. if x->replay_maxage has elapsed since last update,
0316      *     and there were changes
0317      *
0318      *  The state structure must be locked!
0319      */
0320 
0321     switch (event) {
0322     case XFRM_REPLAY_UPDATE:
0323         if (!x->replay_maxdiff ||
0324             ((replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
0325             (replay_esn->oseq - preplay_esn->oseq
0326              < x->replay_maxdiff))) {
0327             if (x->xflags & XFRM_TIME_DEFER)
0328                 event = XFRM_REPLAY_TIMEOUT;
0329             else
0330                 return;
0331         }
0332 
0333         break;
0334 
0335     case XFRM_REPLAY_TIMEOUT:
0336         if (memcmp(x->replay_esn, x->preplay_esn,
0337                xfrm_replay_state_esn_len(replay_esn)) == 0) {
0338             x->xflags |= XFRM_TIME_DEFER;
0339             return;
0340         }
0341 
0342         break;
0343     }
0344 
0345     memcpy(x->preplay_esn, x->replay_esn,
0346            xfrm_replay_state_esn_len(replay_esn));
0347     c.event = XFRM_MSG_NEWAE;
0348     c.data.aevent = event;
0349     km_state_notify(x, &c);
0350 
0351     if (x->replay_maxage &&
0352         !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
0353         x->xflags &= ~XFRM_TIME_DEFER;
0354 }
0355 
0356 static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
0357 {
0358     u32 seq_diff, oseq_diff;
0359     struct km_event c;
0360     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0361     struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
0362 
0363     /* we send notify messages in case
0364      *  1. we updated on of the sequence numbers, and the seqno difference
0365      *     is at least x->replay_maxdiff, in this case we also update the
0366      *     timeout of our timer function
0367      *  2. if x->replay_maxage has elapsed since last update,
0368      *     and there were changes
0369      *
0370      *  The state structure must be locked!
0371      */
0372 
0373     switch (event) {
0374     case XFRM_REPLAY_UPDATE:
0375         if (x->replay_maxdiff) {
0376             if (replay_esn->seq_hi == preplay_esn->seq_hi)
0377                 seq_diff = replay_esn->seq - preplay_esn->seq;
0378             else
0379                 seq_diff = ~preplay_esn->seq + replay_esn->seq
0380                        + 1;
0381 
0382             if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
0383                 oseq_diff = replay_esn->oseq
0384                         - preplay_esn->oseq;
0385             else
0386                 oseq_diff = ~preplay_esn->oseq
0387                         + replay_esn->oseq + 1;
0388 
0389             if (seq_diff >= x->replay_maxdiff ||
0390                 oseq_diff >= x->replay_maxdiff)
0391                 break;
0392         }
0393 
0394         if (x->xflags & XFRM_TIME_DEFER)
0395             event = XFRM_REPLAY_TIMEOUT;
0396         else
0397             return;
0398 
0399         break;
0400 
0401     case XFRM_REPLAY_TIMEOUT:
0402         if (memcmp(x->replay_esn, x->preplay_esn,
0403                xfrm_replay_state_esn_len(replay_esn)) == 0) {
0404             x->xflags |= XFRM_TIME_DEFER;
0405             return;
0406         }
0407 
0408         break;
0409     }
0410 
0411     memcpy(x->preplay_esn, x->replay_esn,
0412            xfrm_replay_state_esn_len(replay_esn));
0413     c.event = XFRM_MSG_NEWAE;
0414     c.data.aevent = event;
0415     km_state_notify(x, &c);
0416 
0417     if (x->replay_maxage &&
0418         !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
0419         x->xflags &= ~XFRM_TIME_DEFER;
0420 }
0421 
0422 static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
0423 {
0424     int err = 0;
0425     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0426     struct net *net = xs_net(x);
0427 
0428     if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
0429         XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
0430         XFRM_SKB_CB(skb)->seq.output.hi = replay_esn->oseq_hi;
0431 
0432         if (unlikely(replay_esn->oseq == 0)) {
0433             XFRM_SKB_CB(skb)->seq.output.hi = ++replay_esn->oseq_hi;
0434 
0435             if (replay_esn->oseq_hi == 0) {
0436                 replay_esn->oseq--;
0437                 replay_esn->oseq_hi--;
0438                 xfrm_audit_state_replay_overflow(x, skb);
0439                 err = -EOVERFLOW;
0440 
0441                 return err;
0442             }
0443         }
0444         if (xfrm_aevent_is_on(net))
0445             xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
0446     }
0447 
0448     return err;
0449 }
0450 
0451 static int xfrm_replay_check_esn(struct xfrm_state *x,
0452                  struct sk_buff *skb, __be32 net_seq)
0453 {
0454     unsigned int bitnr, nr;
0455     u32 diff;
0456     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0457     u32 pos;
0458     u32 seq = ntohl(net_seq);
0459     u32 wsize = replay_esn->replay_window;
0460     u32 top = replay_esn->seq;
0461     u32 bottom = top - wsize + 1;
0462 
0463     if (!wsize)
0464         return 0;
0465 
0466     if (unlikely(seq == 0 && replay_esn->seq_hi == 0 &&
0467              (replay_esn->seq < replay_esn->replay_window - 1)))
0468         goto err;
0469 
0470     diff = top - seq;
0471 
0472     if (likely(top >= wsize - 1)) {
0473         /* A. same subspace */
0474         if (likely(seq > top) || seq < bottom)
0475             return 0;
0476     } else {
0477         /* B. window spans two subspaces */
0478         if (likely(seq > top && seq < bottom))
0479             return 0;
0480         if (seq >= bottom)
0481             diff = ~seq + top + 1;
0482     }
0483 
0484     if (diff >= replay_esn->replay_window) {
0485         x->stats.replay_window++;
0486         goto err;
0487     }
0488 
0489     pos = (replay_esn->seq - 1) % replay_esn->replay_window;
0490 
0491     if (pos >= diff)
0492         bitnr = (pos - diff) % replay_esn->replay_window;
0493     else
0494         bitnr = replay_esn->replay_window - (diff - pos);
0495 
0496     nr = bitnr >> 5;
0497     bitnr = bitnr & 0x1F;
0498     if (replay_esn->bmp[nr] & (1U << bitnr))
0499         goto err_replay;
0500 
0501     return 0;
0502 
0503 err_replay:
0504     x->stats.replay++;
0505 err:
0506     xfrm_audit_state_replay(x, skb, net_seq);
0507     return -EINVAL;
0508 }
0509 
0510 int xfrm_replay_check(struct xfrm_state *x,
0511               struct sk_buff *skb, __be32 net_seq)
0512 {
0513     switch (x->repl_mode) {
0514     case XFRM_REPLAY_MODE_LEGACY:
0515         break;
0516     case XFRM_REPLAY_MODE_BMP:
0517         return xfrm_replay_check_bmp(x, skb, net_seq);
0518     case XFRM_REPLAY_MODE_ESN:
0519         return xfrm_replay_check_esn(x, skb, net_seq);
0520     }
0521 
0522     return xfrm_replay_check_legacy(x, skb, net_seq);
0523 }
0524 
0525 static int xfrm_replay_recheck_esn(struct xfrm_state *x,
0526                    struct sk_buff *skb, __be32 net_seq)
0527 {
0528     if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi !=
0529              htonl(xfrm_replay_seqhi(x, net_seq)))) {
0530             x->stats.replay_window++;
0531             return -EINVAL;
0532     }
0533 
0534     return xfrm_replay_check_esn(x, skb, net_seq);
0535 }
0536 
0537 int xfrm_replay_recheck(struct xfrm_state *x,
0538             struct sk_buff *skb, __be32 net_seq)
0539 {
0540     switch (x->repl_mode) {
0541     case XFRM_REPLAY_MODE_LEGACY:
0542         break;
0543     case XFRM_REPLAY_MODE_BMP:
0544         /* no special recheck treatment */
0545         return xfrm_replay_check_bmp(x, skb, net_seq);
0546     case XFRM_REPLAY_MODE_ESN:
0547         return xfrm_replay_recheck_esn(x, skb, net_seq);
0548     }
0549 
0550     return xfrm_replay_check_legacy(x, skb, net_seq);
0551 }
0552 
0553 static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
0554 {
0555     unsigned int bitnr, nr, i;
0556     int wrap;
0557     u32 diff, pos, seq, seq_hi;
0558     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0559 
0560     if (!replay_esn->replay_window)
0561         return;
0562 
0563     seq = ntohl(net_seq);
0564     pos = (replay_esn->seq - 1) % replay_esn->replay_window;
0565     seq_hi = xfrm_replay_seqhi(x, net_seq);
0566     wrap = seq_hi - replay_esn->seq_hi;
0567 
0568     if ((!wrap && seq > replay_esn->seq) || wrap > 0) {
0569         if (likely(!wrap))
0570             diff = seq - replay_esn->seq;
0571         else
0572             diff = ~replay_esn->seq + seq + 1;
0573 
0574         if (diff < replay_esn->replay_window) {
0575             for (i = 1; i < diff; i++) {
0576                 bitnr = (pos + i) % replay_esn->replay_window;
0577                 nr = bitnr >> 5;
0578                 bitnr = bitnr & 0x1F;
0579                 replay_esn->bmp[nr] &=  ~(1U << bitnr);
0580             }
0581         } else {
0582             nr = (replay_esn->replay_window - 1) >> 5;
0583             for (i = 0; i <= nr; i++)
0584                 replay_esn->bmp[i] = 0;
0585         }
0586 
0587         bitnr = (pos + diff) % replay_esn->replay_window;
0588         replay_esn->seq = seq;
0589 
0590         if (unlikely(wrap > 0))
0591             replay_esn->seq_hi++;
0592     } else {
0593         diff = replay_esn->seq - seq;
0594 
0595         if (pos >= diff)
0596             bitnr = (pos - diff) % replay_esn->replay_window;
0597         else
0598             bitnr = replay_esn->replay_window - (diff - pos);
0599     }
0600 
0601     xfrm_dev_state_advance_esn(x);
0602 
0603     nr = bitnr >> 5;
0604     bitnr = bitnr & 0x1F;
0605     replay_esn->bmp[nr] |= (1U << bitnr);
0606 
0607     if (xfrm_aevent_is_on(xs_net(x)))
0608         xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
0609 }
0610 
0611 #ifdef CONFIG_XFRM_OFFLOAD
0612 static int xfrm_replay_overflow_offload(struct xfrm_state *x, struct sk_buff *skb)
0613 {
0614     int err = 0;
0615     struct net *net = xs_net(x);
0616     struct xfrm_offload *xo = xfrm_offload(skb);
0617     __u32 oseq = x->replay.oseq;
0618 
0619     if (!xo)
0620         return __xfrm_replay_overflow(x, skb);
0621 
0622     if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
0623         if (!skb_is_gso(skb)) {
0624             XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
0625             xo->seq.low = oseq;
0626         } else {
0627             XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
0628             xo->seq.low = oseq + 1;
0629             oseq += skb_shinfo(skb)->gso_segs;
0630         }
0631 
0632         XFRM_SKB_CB(skb)->seq.output.hi = 0;
0633         xo->seq.hi = 0;
0634         if (unlikely(oseq < x->replay.oseq) &&
0635             !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
0636             xfrm_audit_state_replay_overflow(x, skb);
0637             err = -EOVERFLOW;
0638 
0639             return err;
0640         }
0641 
0642         x->replay.oseq = oseq;
0643 
0644         if (xfrm_aevent_is_on(net))
0645             xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
0646     }
0647 
0648     return err;
0649 }
0650 
0651 static int xfrm_replay_overflow_offload_bmp(struct xfrm_state *x, struct sk_buff *skb)
0652 {
0653     int err = 0;
0654     struct xfrm_offload *xo = xfrm_offload(skb);
0655     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0656     struct net *net = xs_net(x);
0657     __u32 oseq = replay_esn->oseq;
0658 
0659     if (!xo)
0660         return xfrm_replay_overflow_bmp(x, skb);
0661 
0662     if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
0663         if (!skb_is_gso(skb)) {
0664             XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
0665             xo->seq.low = oseq;
0666         } else {
0667             XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
0668             xo->seq.low = oseq + 1;
0669             oseq += skb_shinfo(skb)->gso_segs;
0670         }
0671 
0672         XFRM_SKB_CB(skb)->seq.output.hi = 0;
0673         xo->seq.hi = 0;
0674         if (unlikely(oseq < replay_esn->oseq) &&
0675             !(x->props.extra_flags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP)) {
0676             xfrm_audit_state_replay_overflow(x, skb);
0677             err = -EOVERFLOW;
0678 
0679             return err;
0680         } else {
0681             replay_esn->oseq = oseq;
0682         }
0683 
0684         if (xfrm_aevent_is_on(net))
0685             xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
0686     }
0687 
0688     return err;
0689 }
0690 
0691 static int xfrm_replay_overflow_offload_esn(struct xfrm_state *x, struct sk_buff *skb)
0692 {
0693     int err = 0;
0694     struct xfrm_offload *xo = xfrm_offload(skb);
0695     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0696     struct net *net = xs_net(x);
0697     __u32 oseq = replay_esn->oseq;
0698     __u32 oseq_hi = replay_esn->oseq_hi;
0699 
0700     if (!xo)
0701         return xfrm_replay_overflow_esn(x, skb);
0702 
0703     if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
0704         if (!skb_is_gso(skb)) {
0705             XFRM_SKB_CB(skb)->seq.output.low = ++oseq;
0706             XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
0707             xo->seq.low = oseq;
0708             xo->seq.hi = oseq_hi;
0709         } else {
0710             XFRM_SKB_CB(skb)->seq.output.low = oseq + 1;
0711             XFRM_SKB_CB(skb)->seq.output.hi = oseq_hi;
0712             xo->seq.low = oseq + 1;
0713             xo->seq.hi = oseq_hi;
0714             oseq += skb_shinfo(skb)->gso_segs;
0715         }
0716 
0717         if (unlikely(oseq < replay_esn->oseq)) {
0718             XFRM_SKB_CB(skb)->seq.output.hi = ++oseq_hi;
0719             xo->seq.hi = oseq_hi;
0720             replay_esn->oseq_hi = oseq_hi;
0721             if (replay_esn->oseq_hi == 0) {
0722                 replay_esn->oseq--;
0723                 replay_esn->oseq_hi--;
0724                 xfrm_audit_state_replay_overflow(x, skb);
0725                 err = -EOVERFLOW;
0726 
0727                 return err;
0728             }
0729         }
0730 
0731         replay_esn->oseq = oseq;
0732 
0733         if (xfrm_aevent_is_on(net))
0734             xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
0735     }
0736 
0737     return err;
0738 }
0739 
0740 int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
0741 {
0742     switch (x->repl_mode) {
0743     case XFRM_REPLAY_MODE_LEGACY:
0744         break;
0745     case XFRM_REPLAY_MODE_BMP:
0746         return xfrm_replay_overflow_offload_bmp(x, skb);
0747     case XFRM_REPLAY_MODE_ESN:
0748         return xfrm_replay_overflow_offload_esn(x, skb);
0749     }
0750 
0751     return xfrm_replay_overflow_offload(x, skb);
0752 }
0753 #else
0754 int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
0755 {
0756     switch (x->repl_mode) {
0757     case XFRM_REPLAY_MODE_LEGACY:
0758         break;
0759     case XFRM_REPLAY_MODE_BMP:
0760         return xfrm_replay_overflow_bmp(x, skb);
0761     case XFRM_REPLAY_MODE_ESN:
0762         return xfrm_replay_overflow_esn(x, skb);
0763     }
0764 
0765     return __xfrm_replay_overflow(x, skb);
0766 }
0767 #endif
0768 
0769 int xfrm_init_replay(struct xfrm_state *x)
0770 {
0771     struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
0772 
0773     if (replay_esn) {
0774         if (replay_esn->replay_window >
0775             replay_esn->bmp_len * sizeof(__u32) * 8)
0776             return -EINVAL;
0777 
0778         if (x->props.flags & XFRM_STATE_ESN) {
0779             if (replay_esn->replay_window == 0)
0780                 return -EINVAL;
0781             x->repl_mode = XFRM_REPLAY_MODE_ESN;
0782         } else {
0783             x->repl_mode = XFRM_REPLAY_MODE_BMP;
0784         }
0785     } else {
0786         x->repl_mode = XFRM_REPLAY_MODE_LEGACY;
0787     }
0788 
0789     return 0;
0790 }
0791 EXPORT_SYMBOL(xfrm_init_replay);