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