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