Patchwork Does ESP support 64 bit sequence numbering for authentication hash ?

login
register
mail settings
Submitter Alex Badea
Date Sept. 1, 2009, 12:23 p.m.
Message ID <4A9D1239.8000900@ixiacom.com>
Download mbox | patch
Permalink /patch/32742/
State RFC
Delegated to: David Miller
Headers show

Comments

Alex Badea - Sept. 1, 2009, 12:23 p.m.
On 09/01/2009 03:09 PM, Steffen Klassert wrote:
> On Thu, Jan 15, 2009 at 04:56:44PM +1100, Herbert Xu wrote:
>> Dean Jenkins <djenkins@mvista.com> wrote:
>>> Does ESP support 64 bit sequence numbering for use with the
>>> authentication HMAC ?
>> We don't support 64-bit sequence numbers yet.  If you look at
>> struct xfrm_replay_state which is where we store the sequence
>> number internally you'll find that it uses u32s.
>>
>> Patches for 64-bit support are welcome of course.
>>
> 
> Is there actually anybody working on 64-bit sequence number support?
> If not, I'd start to look at it.

A while ago I implemented a rough version of ESN support. It's against
an ancient 2.6.7 kernel though, and is only superficially tested.

I suppose there's no reason not to publish them here, if only for
historical reasons. My apologies to anyone not interested :)


Alex Badea (6):
      xfrm: move xfrm_replay_{check,advance} to their own source file
      xfrm: introduce XFRM_STATE_ESN flag, and extended replay structure
      xfrm: add generic support for replay protection with Extended
Sequence Numbers
      ipsec: Extended Sequence Numbers support for ESP
      ipsec: Extended Sequence Numbers support for AH
      xfrm: add test harness for Extended Sequence Numbers replay
protection algorithm


Best regards,
Alex
Steffen Klassert - Sept. 1, 2009, 12:42 p.m.
On Tue, Sep 01, 2009 at 03:23:21PM +0300, Alex Badea wrote:
> 
> A while ago I implemented a rough version of ESN support. It's against
> an ancient 2.6.7 kernel though, and is only superficially tested.
> 
> I suppose there's no reason not to publish them here, if only for
> historical reasons. My apologies to anyone not interested :)
> 

I'll have a look whether I can use some parts of it, thanks.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

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

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 <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;
+}
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 <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