From 813d3e12e5f207d037bb1570a35519da77227f0e Mon Sep 17 00:00:00 2001
From: Alex Badea <abadea@ixiacom.com>
Date: Mon, 29 Jun 2009 12:29:25 +0300
Subject: [PATCH] xfrm: add test harness for Extended Sequence Numbers replay protection algorithm
---
test/esn/SConstruct | 15 +++
test/esn/harness.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++++++
test/esn/harness.h | 37 ++++++++
3 files changed, 309 insertions(+), 0 deletions(-)
create mode 100644 test/esn/SConstruct
create mode 100644 test/esn/harness.c
create mode 100644 test/esn/harness.h
new file mode 100644
@@ -0,0 +1,15 @@
+env = Environment(
+ CCFLAGS = ['-g', '-Wall', '-Werror', '--include=harness.h'],
+ LINKFLAGS = ['-g'],
+ CPPPATH = ['.', '../../src/include'],
+)
+
+env.Append(
+ CCFLAGS = ['-fprofile-arcs', '-ftest-coverage'],
+ LINKFLAGS = ['-fprofile-arcs', '-ftest-coverage'],
+)
+
+env.Program('test-esn', [
+ 'harness.c',
+ '../../src/net/xfrm/xfrm_replay.c',
+])
new file mode 100644
@@ -0,0 +1,257 @@
+#include "harness.h"
+#include <string.h>
+
+static void print_bitmap(struct xfrm_state *x)
+{
+ unsigned k;
+ u32 bm = x->replay.bitmap;
+
+ printk("bitmap: %u [", x->replay.seq - x->props.replay_window + 1);
+ bm <<= 32 - x->props.replay_window;
+ for (k = 0; k < x->props.replay_window; k++) {
+ if (k && !(k % 4))
+ printk(" ");
+ printk("%c", (bm & (1 << 31)) ? '1' : '-');
+ bm <<= 1;
+ }
+ printk("] %u\n", x->replay.seq);
+}
+
+static int do_replay(struct xfrm_state *x, u64 seq64, unsigned should_fail)
+{
+ printk("\ntest: #%llu (%llu / %llu)\n",
+ seq64,
+ seq64 >> 32,
+ seq64 & 0xffffffff);
+ print_bitmap(x);
+ printk("w=%u bottom=%u top(replay.seq)=%u|%u\n",
+ x->props.replay_window,
+ x->replay.seq - x->props.replay_window + 1,
+ x->replay_ext.seq_hi,
+ x->replay.seq);
+
+ u32 seq = htonl(seq64 & 0xffffffff);
+ if (xfrm_replay_check(x, seq)) {
+ printk("### replay check failed\n");
+ if (!should_fail)
+ BUG();
+ return -1;
+ }
+
+ if (x->props.flags & XFRM_STATE_ESN) {
+ u32 seq_hi = xfrm_replay_seqhi(x, seq);
+ printk("seq_hi=%u\n", seq_hi);
+ if (seq_hi != (seq64 >> 32)) {
+ /* this is equivalent to the integrity check */
+ printk("### seq_hi check failed (expected %llu)\n", seq64 >> 32);
+ if (!should_fail)
+ BUG();
+ return -1;
+ }
+ }
+
+ if (should_fail) {
+ printk("### replay check didn't fail -- and should have\n");
+ BUG();
+ }
+
+ xfrm_replay_advance(x, seq);
+ return 0;
+}
+
+static inline int test_replay_pass(struct xfrm_state *x, u64 seq64)
+{
+ return do_replay(x, seq64, 0);
+}
+
+static inline int test_replay_fail(struct xfrm_state *x, u64 seq64)
+{
+ return do_replay(x, seq64, 1);
+}
+
+static void init_state(struct xfrm_state *x)
+{
+ memset(x, 0, sizeof(struct xfrm_state));
+ x->props.replay_window = 8;
+}
+
+static void init_state_esn(struct xfrm_state *x)
+{
+ init_state(x);
+ x->props.flags |= XFRM_STATE_ESN;
+}
+
+static void banner(const char *text)
+{
+ printk("\n\n================================================================\n");
+ printk("===== %s\n\n", text);
+
+}
+
+static void sep(void)
+{
+ printk("\n\n-----\n\n");
+}
+
+static void test_0(void)
+{
+ struct xfrm_state st, *x = &st;
+
+ banner("seq == 0");
+ init_state_esn(x);
+ test_replay_fail(x, 0);
+ test_replay_pass(x, 1);
+ test_replay_fail(x, 0);
+ test_replay_pass(x, 128);
+ test_replay_fail(x, 0);
+ test_replay_pass(x, (1ULL << 32) - 20);
+ test_replay_fail(x, 0);
+ test_replay_pass(x, (1ULL << 32));
+ test_replay_pass(x, (1ULL << 32) + 20);
+}
+
+static void test_1(void)
+{
+ struct xfrm_state st, *x = &st;
+ unsigned k;
+ u64 seq64 = 1;
+
+ banner("linear sequence, wrapping");
+ init_state_esn(x);
+
+ seq64 = 1;
+ for (k = 1; k < 5; k++)
+ test_replay_pass(x, seq64++);
+ sep();
+ seq64 = 0xfffffff0;
+ for (k = 0; k < 16; k++)
+ test_replay_pass(x, seq64++);
+ sep();
+ for (k = 0; k < 10; k++)
+ test_replay_pass(x, seq64++);
+}
+
+static void test_2(void)
+{
+ struct xfrm_state st, *x = &st;
+ unsigned k;
+ u64 seq64 = 1;
+
+ banner("short sequence with a few replays");
+ init_state_esn(x);
+
+ for (k = 0; k < 64; k++)
+ test_replay_pass(x, seq64++);
+ /* out-of-window */
+ test_replay_fail(x, 1);
+ test_replay_fail(x, 2);
+ test_replay_fail(x, 3);
+ /* in-window */
+ test_replay_fail(x, 60);
+ test_replay_fail(x, 63);
+
+ test_replay_pass(x, seq64++);
+}
+
+static void test_3(void)
+{
+ struct xfrm_state st, *x = &st;
+
+ banner("swiss cheese");
+ init_state_esn(x);
+
+ test_replay_pass(x, 3);
+ test_replay_pass(x, 9);
+ test_replay_pass(x, 5);
+ test_replay_fail(x, 5); /* replayed */
+ test_replay_pass(x, 16);
+ test_replay_fail(x, 4); /* out of window */
+ test_replay_pass(x, 10);
+}
+
+static void test_4(void)
+{
+ struct xfrm_state st, *x = &st;
+ u64 edge = (1ULL << 32);
+
+ banner("swiss cheese with wrapping");
+ init_state_esn(x);
+
+ test_replay_pass(x, 1);
+ test_replay_pass(x, 128);
+ test_replay_pass(x, edge + 2);
+ test_replay_pass(x, edge - 2);
+ test_replay_pass(x, edge);
+ test_replay_pass(x, edge + 3);
+ test_replay_pass(x, edge + 1);
+
+ test_replay_fail(x, edge + 1);
+ test_replay_fail(x, edge);
+ test_replay_fail(x, edge - 2);
+ test_replay_pass(x, edge - 1);
+}
+
+static void test_5(void)
+{
+ struct xfrm_state st, *x = &st;
+ unsigned k;
+ u64 seq64 = 1;
+
+ banner("sparse");
+ init_state_esn(x);
+
+ for (k = 1; k < 10; k++) {
+ seq64 += 2149536563U; /* random prime */
+ test_replay_pass(x, seq64);
+ }
+}
+
+static void test_plain_1(void)
+{
+ struct xfrm_state st, *x = &st;
+ unsigned k;
+ u64 seq64 = 1;
+
+ banner("non-ESN in-sequence");
+ init_state(x);
+
+ for (k = 1; k < 10; k++)
+ test_replay_pass(x, seq64++);
+ for (k = 1; k < 3; k++)
+ test_replay_pass(x, seq64 += 13);
+ for (k = 1; k < 3; k++)
+ test_replay_pass(x, seq64 += 5);
+}
+
+static void test_plain_2(void)
+{
+ struct xfrm_state st, *x = &st;
+
+ banner("non-ESN replay check");
+ init_state(x);
+
+ test_replay_fail(x, 0); /* seq == 0 */
+ test_replay_pass(x, 3);
+ test_replay_pass(x, 9);
+ test_replay_pass(x, 5);
+ test_replay_fail(x, 5); /* replayed */
+ test_replay_pass(x, 16);
+ test_replay_fail(x, 4); /* out of window */
+ test_replay_pass(x, 10);
+}
+
+int main(int argc, char *argv[])
+{
+ test_0();
+ test_1();
+ test_2();
+ test_3();
+ test_4();
+ test_5();
+ test_plain_1();
+ test_plain_2();
+
+ sep();
+ printk("all done.\n");
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,37 @@
+#ifndef _HARNESS_H
+#define _HARNESS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <linux/xfrm.h>
+
+#define printk printf
+#define likely(x) x
+#define unlikely(x) x
+#define BUG() abort()
+#define _NET_XFRM_H
+
+typedef u_int8_t u8;
+typedef u_int32_t u32;
+typedef u_int64_t u64;
+
+struct xfrm_state {
+ struct {
+ u8 flags;
+ u8 replay_window;
+ } props;
+ struct xfrm_replay_state replay;
+ struct xfrm_replay_state_ext replay_ext;
+ struct xfrm_stats stats;
+};
+
+#define XFRM_STATE_ESN 64
+
+extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
+extern u32 xfrm_replay_seqhi(struct xfrm_state *x, u32 seq);
+extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
+
+#endif
--
1.5.4.3