2 * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
4 * Copyright (C) 2010 secunet Security Networks AG
5 * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <linux/export.h>
24 u32
xfrm_replay_seqhi(struct xfrm_state
*x
, __be32 net_seq
)
26 u32 seq
, seq_hi
, bottom
;
27 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
29 if (!(x
->props
.flags
& XFRM_STATE_ESN
))
33 seq_hi
= replay_esn
->seq_hi
;
34 bottom
= replay_esn
->seq
- replay_esn
->replay_window
+ 1;
36 if (likely(replay_esn
->seq
>= replay_esn
->replay_window
- 1)) {
37 /* A. same subspace */
38 if (unlikely(seq
< bottom
))
41 /* B. window spans two subspaces */
42 if (unlikely(seq
>= bottom
))
49 static void xfrm_replay_notify(struct xfrm_state
*x
, int event
)
52 /* we send notify messages in case
53 * 1. we updated on of the sequence numbers, and the seqno difference
54 * is at least x->replay_maxdiff, in this case we also update the
55 * timeout of our timer function
56 * 2. if x->replay_maxage has elapsed since last update,
57 * and there were changes
59 * The state structure must be locked!
63 case XFRM_REPLAY_UPDATE
:
64 if (!x
->replay_maxdiff
||
65 ((x
->replay
.seq
- x
->preplay
.seq
< x
->replay_maxdiff
) &&
66 (x
->replay
.oseq
- x
->preplay
.oseq
< x
->replay_maxdiff
))) {
67 if (x
->xflags
& XFRM_TIME_DEFER
)
68 event
= XFRM_REPLAY_TIMEOUT
;
75 case XFRM_REPLAY_TIMEOUT
:
76 if (memcmp(&x
->replay
, &x
->preplay
,
77 sizeof(struct xfrm_replay_state
)) == 0) {
78 x
->xflags
|= XFRM_TIME_DEFER
;
85 memcpy(&x
->preplay
, &x
->replay
, sizeof(struct xfrm_replay_state
));
86 c
.event
= XFRM_MSG_NEWAE
;
87 c
.data
.aevent
= event
;
88 km_state_notify(x
, &c
);
90 if (x
->replay_maxage
&&
91 !mod_timer(&x
->rtimer
, jiffies
+ x
->replay_maxage
))
92 x
->xflags
&= ~XFRM_TIME_DEFER
;
95 static int xfrm_replay_overflow(struct xfrm_state
*x
, struct sk_buff
*skb
)
98 struct net
*net
= xs_net(x
);
100 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
101 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++x
->replay
.oseq
;
102 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
103 if (unlikely(x
->replay
.oseq
== 0)) {
105 xfrm_audit_state_replay_overflow(x
, skb
);
110 if (xfrm_aevent_is_on(net
))
111 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
117 static int xfrm_replay_check(struct xfrm_state
*x
,
118 struct sk_buff
*skb
, __be32 net_seq
)
121 u32 seq
= ntohl(net_seq
);
123 if (!x
->props
.replay_window
)
126 if (unlikely(seq
== 0))
129 if (likely(seq
> x
->replay
.seq
))
132 diff
= x
->replay
.seq
- seq
;
133 if (diff
>= x
->props
.replay_window
) {
134 x
->stats
.replay_window
++;
138 if (x
->replay
.bitmap
& (1U << diff
)) {
145 xfrm_audit_state_replay(x
, skb
, net_seq
);
149 static void xfrm_replay_advance(struct xfrm_state
*x
, __be32 net_seq
)
152 u32 seq
= ntohl(net_seq
);
154 if (!x
->props
.replay_window
)
157 if (seq
> x
->replay
.seq
) {
158 diff
= seq
- x
->replay
.seq
;
159 if (diff
< x
->props
.replay_window
)
160 x
->replay
.bitmap
= ((x
->replay
.bitmap
) << diff
) | 1;
162 x
->replay
.bitmap
= 1;
165 diff
= x
->replay
.seq
- seq
;
166 x
->replay
.bitmap
|= (1U << diff
);
169 if (xfrm_aevent_is_on(xs_net(x
)))
170 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
173 static int xfrm_replay_overflow_bmp(struct xfrm_state
*x
, struct sk_buff
*skb
)
176 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
177 struct net
*net
= xs_net(x
);
179 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
180 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++replay_esn
->oseq
;
181 XFRM_SKB_CB(skb
)->seq
.output
.hi
= 0;
182 if (unlikely(replay_esn
->oseq
== 0)) {
184 xfrm_audit_state_replay_overflow(x
, skb
);
189 if (xfrm_aevent_is_on(net
))
190 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
196 static int xfrm_replay_check_bmp(struct xfrm_state
*x
,
197 struct sk_buff
*skb
, __be32 net_seq
)
199 unsigned int bitnr
, nr
;
200 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
202 u32 seq
= ntohl(net_seq
);
203 u32 diff
= replay_esn
->seq
- seq
;
205 if (!replay_esn
->replay_window
)
208 if (unlikely(seq
== 0))
211 if (likely(seq
> replay_esn
->seq
))
214 if (diff
>= replay_esn
->replay_window
) {
215 x
->stats
.replay_window
++;
219 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
222 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
224 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
227 bitnr
= bitnr
& 0x1F;
228 if (replay_esn
->bmp
[nr
] & (1U << bitnr
))
236 xfrm_audit_state_replay(x
, skb
, net_seq
);
240 static void xfrm_replay_advance_bmp(struct xfrm_state
*x
, __be32 net_seq
)
242 unsigned int bitnr
, nr
, i
;
244 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
245 u32 seq
= ntohl(net_seq
);
248 if (!replay_esn
->replay_window
)
251 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
253 if (seq
> replay_esn
->seq
) {
254 diff
= seq
- replay_esn
->seq
;
256 if (diff
< replay_esn
->replay_window
) {
257 for (i
= 1; i
< diff
; i
++) {
258 bitnr
= (pos
+ i
) % replay_esn
->replay_window
;
260 bitnr
= bitnr
& 0x1F;
261 replay_esn
->bmp
[nr
] &= ~(1U << bitnr
);
264 nr
= (replay_esn
->replay_window
- 1) >> 5;
265 for (i
= 0; i
<= nr
; i
++)
266 replay_esn
->bmp
[i
] = 0;
269 bitnr
= (pos
+ diff
) % replay_esn
->replay_window
;
270 replay_esn
->seq
= seq
;
272 diff
= replay_esn
->seq
- seq
;
275 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
277 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
281 bitnr
= bitnr
& 0x1F;
282 replay_esn
->bmp
[nr
] |= (1U << bitnr
);
284 if (xfrm_aevent_is_on(xs_net(x
)))
285 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
288 static void xfrm_replay_notify_bmp(struct xfrm_state
*x
, int event
)
291 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
292 struct xfrm_replay_state_esn
*preplay_esn
= x
->preplay_esn
;
294 /* we send notify messages in case
295 * 1. we updated on of the sequence numbers, and the seqno difference
296 * is at least x->replay_maxdiff, in this case we also update the
297 * timeout of our timer function
298 * 2. if x->replay_maxage has elapsed since last update,
299 * and there were changes
301 * The state structure must be locked!
305 case XFRM_REPLAY_UPDATE
:
306 if (!x
->replay_maxdiff
||
307 ((replay_esn
->seq
- preplay_esn
->seq
< x
->replay_maxdiff
) &&
308 (replay_esn
->oseq
- preplay_esn
->oseq
309 < x
->replay_maxdiff
))) {
310 if (x
->xflags
& XFRM_TIME_DEFER
)
311 event
= XFRM_REPLAY_TIMEOUT
;
318 case XFRM_REPLAY_TIMEOUT
:
319 if (memcmp(x
->replay_esn
, x
->preplay_esn
,
320 xfrm_replay_state_esn_len(replay_esn
)) == 0) {
321 x
->xflags
|= XFRM_TIME_DEFER
;
328 memcpy(x
->preplay_esn
, x
->replay_esn
,
329 xfrm_replay_state_esn_len(replay_esn
));
330 c
.event
= XFRM_MSG_NEWAE
;
331 c
.data
.aevent
= event
;
332 km_state_notify(x
, &c
);
334 if (x
->replay_maxage
&&
335 !mod_timer(&x
->rtimer
, jiffies
+ x
->replay_maxage
))
336 x
->xflags
&= ~XFRM_TIME_DEFER
;
339 static void xfrm_replay_notify_esn(struct xfrm_state
*x
, int event
)
341 u32 seq_diff
, oseq_diff
;
343 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
344 struct xfrm_replay_state_esn
*preplay_esn
= x
->preplay_esn
;
346 /* we send notify messages in case
347 * 1. we updated on of the sequence numbers, and the seqno difference
348 * is at least x->replay_maxdiff, in this case we also update the
349 * timeout of our timer function
350 * 2. if x->replay_maxage has elapsed since last update,
351 * and there were changes
353 * The state structure must be locked!
357 case XFRM_REPLAY_UPDATE
:
358 if (x
->replay_maxdiff
) {
359 if (replay_esn
->seq_hi
== preplay_esn
->seq_hi
)
360 seq_diff
= replay_esn
->seq
- preplay_esn
->seq
;
362 seq_diff
= ~preplay_esn
->seq
+ replay_esn
->seq
365 if (replay_esn
->oseq_hi
== preplay_esn
->oseq_hi
)
366 oseq_diff
= replay_esn
->oseq
369 oseq_diff
= ~preplay_esn
->oseq
370 + replay_esn
->oseq
+ 1;
372 if (seq_diff
>= x
->replay_maxdiff
||
373 oseq_diff
>= x
->replay_maxdiff
)
377 if (x
->xflags
& XFRM_TIME_DEFER
)
378 event
= XFRM_REPLAY_TIMEOUT
;
384 case XFRM_REPLAY_TIMEOUT
:
385 if (memcmp(x
->replay_esn
, x
->preplay_esn
,
386 xfrm_replay_state_esn_len(replay_esn
)) == 0) {
387 x
->xflags
|= XFRM_TIME_DEFER
;
394 memcpy(x
->preplay_esn
, x
->replay_esn
,
395 xfrm_replay_state_esn_len(replay_esn
));
396 c
.event
= XFRM_MSG_NEWAE
;
397 c
.data
.aevent
= event
;
398 km_state_notify(x
, &c
);
400 if (x
->replay_maxage
&&
401 !mod_timer(&x
->rtimer
, jiffies
+ x
->replay_maxage
))
402 x
->xflags
&= ~XFRM_TIME_DEFER
;
405 static int xfrm_replay_overflow_esn(struct xfrm_state
*x
, struct sk_buff
*skb
)
408 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
409 struct net
*net
= xs_net(x
);
411 if (x
->type
->flags
& XFRM_TYPE_REPLAY_PROT
) {
412 XFRM_SKB_CB(skb
)->seq
.output
.low
= ++replay_esn
->oseq
;
413 XFRM_SKB_CB(skb
)->seq
.output
.hi
= replay_esn
->oseq_hi
;
415 if (unlikely(replay_esn
->oseq
== 0)) {
416 XFRM_SKB_CB(skb
)->seq
.output
.hi
= ++replay_esn
->oseq_hi
;
418 if (replay_esn
->oseq_hi
== 0) {
420 replay_esn
->oseq_hi
--;
421 xfrm_audit_state_replay_overflow(x
, skb
);
427 if (xfrm_aevent_is_on(net
))
428 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
434 static int xfrm_replay_check_esn(struct xfrm_state
*x
,
435 struct sk_buff
*skb
, __be32 net_seq
)
437 unsigned int bitnr
, nr
;
439 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
441 u32 seq
= ntohl(net_seq
);
442 u32 wsize
= replay_esn
->replay_window
;
443 u32 top
= replay_esn
->seq
;
444 u32 bottom
= top
- wsize
+ 1;
449 if (unlikely(seq
== 0 && replay_esn
->seq_hi
== 0 &&
450 (replay_esn
->seq
< replay_esn
->replay_window
- 1)))
455 if (likely(top
>= wsize
- 1)) {
456 /* A. same subspace */
457 if (likely(seq
> top
) || seq
< bottom
)
460 /* B. window spans two subspaces */
461 if (likely(seq
> top
&& seq
< bottom
))
464 diff
= ~seq
+ top
+ 1;
467 if (diff
>= replay_esn
->replay_window
) {
468 x
->stats
.replay_window
++;
472 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
475 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
477 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
480 bitnr
= bitnr
& 0x1F;
481 if (replay_esn
->bmp
[nr
] & (1U << bitnr
))
489 xfrm_audit_state_replay(x
, skb
, net_seq
);
493 static int xfrm_replay_recheck_esn(struct xfrm_state
*x
,
494 struct sk_buff
*skb
, __be32 net_seq
)
496 if (unlikely(XFRM_SKB_CB(skb
)->seq
.input
.hi
!=
497 htonl(xfrm_replay_seqhi(x
, net_seq
)))) {
498 x
->stats
.replay_window
++;
502 return xfrm_replay_check_esn(x
, skb
, net_seq
);
505 static void xfrm_replay_advance_esn(struct xfrm_state
*x
, __be32 net_seq
)
507 unsigned int bitnr
, nr
, i
;
509 u32 diff
, pos
, seq
, seq_hi
;
510 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
512 if (!replay_esn
->replay_window
)
515 seq
= ntohl(net_seq
);
516 pos
= (replay_esn
->seq
- 1) % replay_esn
->replay_window
;
517 seq_hi
= xfrm_replay_seqhi(x
, net_seq
);
518 wrap
= seq_hi
- replay_esn
->seq_hi
;
520 if ((!wrap
&& seq
> replay_esn
->seq
) || wrap
> 0) {
522 diff
= seq
- replay_esn
->seq
;
524 diff
= ~replay_esn
->seq
+ seq
+ 1;
526 if (diff
< replay_esn
->replay_window
) {
527 for (i
= 1; i
< diff
; i
++) {
528 bitnr
= (pos
+ i
) % replay_esn
->replay_window
;
530 bitnr
= bitnr
& 0x1F;
531 replay_esn
->bmp
[nr
] &= ~(1U << bitnr
);
534 nr
= (replay_esn
->replay_window
- 1) >> 5;
535 for (i
= 0; i
<= nr
; i
++)
536 replay_esn
->bmp
[i
] = 0;
539 bitnr
= (pos
+ diff
) % replay_esn
->replay_window
;
540 replay_esn
->seq
= seq
;
542 if (unlikely(wrap
> 0))
543 replay_esn
->seq_hi
++;
545 diff
= replay_esn
->seq
- seq
;
548 bitnr
= (pos
- diff
) % replay_esn
->replay_window
;
550 bitnr
= replay_esn
->replay_window
- (diff
- pos
);
554 bitnr
= bitnr
& 0x1F;
555 replay_esn
->bmp
[nr
] |= (1U << bitnr
);
557 if (xfrm_aevent_is_on(xs_net(x
)))
558 x
->repl
->notify(x
, XFRM_REPLAY_UPDATE
);
561 static struct xfrm_replay xfrm_replay_legacy
= {
562 .advance
= xfrm_replay_advance
,
563 .check
= xfrm_replay_check
,
564 .recheck
= xfrm_replay_check
,
565 .notify
= xfrm_replay_notify
,
566 .overflow
= xfrm_replay_overflow
,
569 static struct xfrm_replay xfrm_replay_bmp
= {
570 .advance
= xfrm_replay_advance_bmp
,
571 .check
= xfrm_replay_check_bmp
,
572 .recheck
= xfrm_replay_check_bmp
,
573 .notify
= xfrm_replay_notify_bmp
,
574 .overflow
= xfrm_replay_overflow_bmp
,
577 static struct xfrm_replay xfrm_replay_esn
= {
578 .advance
= xfrm_replay_advance_esn
,
579 .check
= xfrm_replay_check_esn
,
580 .recheck
= xfrm_replay_recheck_esn
,
581 .notify
= xfrm_replay_notify_esn
,
582 .overflow
= xfrm_replay_overflow_esn
,
585 int xfrm_init_replay(struct xfrm_state
*x
)
587 struct xfrm_replay_state_esn
*replay_esn
= x
->replay_esn
;
590 if (replay_esn
->replay_window
>
591 replay_esn
->bmp_len
* sizeof(__u32
) * 8)
594 if (x
->props
.flags
& XFRM_STATE_ESN
) {
595 if (replay_esn
->replay_window
== 0)
597 x
->repl
= &xfrm_replay_esn
;
599 x
->repl
= &xfrm_replay_bmp
;
601 x
->repl
= &xfrm_replay_legacy
;
605 EXPORT_SYMBOL(xfrm_init_replay
);