>From 813d3e12e5f207d037bb1570a35519da77227f0e Mon Sep 17 00:00:00 2001 From: Alex Badea 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 diff --git a/test/esn/SConstruct b/test/esn/SConstruct new file mode 100644 index 0000000..55177a4 --- /dev/null +++ b/test/esn/SConstruct @@ -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', +]) diff --git a/test/esn/harness.c b/test/esn/harness.c new file mode 100644 index 0000000..d026023 --- /dev/null +++ b/test/esn/harness.c @@ -0,0 +1,257 @@ +#include "harness.h" +#include + +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; +} diff --git a/test/esn/harness.h b/test/esn/harness.h new file mode 100644 index 0000000..1e4277b --- /dev/null +++ b/test/esn/harness.h @@ -0,0 +1,37 @@ +#ifndef _HARNESS_H +#define _HARNESS_H + +#include +#include +#include +#include +#include +#include + +#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