From 0c00a4306d5ee93aa63ee0f9e5eda3d5fc2bccb2 Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Fri, 9 Apr 2021 23:05:49 +0100 Subject: [PATCH 1/5] added repeat interface --- proxy/repeats.go | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 proxy/repeats.go diff --git a/proxy/repeats.go b/proxy/repeats.go new file mode 100644 index 0000000..a527648 --- /dev/null +++ b/proxy/repeats.go @@ -0,0 +1,9 @@ +package proxy + +type RepeatGenerator interface { + Generate() []byte +} + +type RepeatVerifier interface { + Verify(in []byte) error +} From ad590808c01677aa21c33fde9c095ea4bb32f3ea Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Fri, 9 Apr 2021 23:14:47 +0100 Subject: [PATCH 2/5] Removed repeat interfaces Instead focus on allowing multiple MACs. --- proxy/repeats.go | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 proxy/repeats.go diff --git a/proxy/repeats.go b/proxy/repeats.go deleted file mode 100644 index a527648..0000000 --- a/proxy/repeats.go +++ /dev/null @@ -1,9 +0,0 @@ -package proxy - -type RepeatGenerator interface { - Generate() []byte -} - -type RepeatVerifier interface { - Verify(in []byte) error -} From 96acf67f6cd0f28193ed3f993e1a707a61dd79f9 Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Thu, 13 May 2021 18:15:43 +0100 Subject: [PATCH 3/5] replay protection --- replay/replay.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 replay/replay.go diff --git a/replay/replay.go b/replay/replay.go new file mode 100644 index 0000000..9ad37be --- /dev/null +++ b/replay/replay.go @@ -0,0 +1,78 @@ +package replay + +import ( + "encoding/binary" + "errors" + "math/rand" + "sync" + "sync/atomic" +) + +var ErrReplayedPacket = errors.New("replayed packet") + +const ( + BlockBits = 64 + NumBlocks = 128 + WindowSize = (NumBlocks - 1) * BlockBits +) + +type AntiReplay struct { + // for outbound packets + next uint64 + + // for inbound packets + mu sync.Mutex + last uint64 + circle [1 << 7]uint64 +} + +func NewAntiReplay() *AntiReplay { + return &AntiReplay{next: rand.Uint64()} +} + +func (a *AntiReplay) CodeLength() int { + return 8 +} + +func (a *AntiReplay) Generate([]byte) (out []byte) { + out = make([]byte, a.CodeLength()) + + s := atomic.AddUint64(&a.next, 1) + binary.LittleEndian.PutUint64(out, s) + + return +} + +func (a *AntiReplay) Verify(_, sum []byte) error { + a.mu.Lock() + defer a.mu.Unlock() + + s := binary.LittleEndian.Uint64(sum) + + indexBlock := s >> 6 + if s > a.last { + current := a.last >> 6 + diff := indexBlock - current + if diff > NumBlocks { + diff = NumBlocks // number so far away the whole ring is fresh + } + for i := current; i <= current+diff; i++ { + a.circle[i&(NumBlocks-1)] = 0 // clear the ones skipped over + } + a.last = s + } else if a.last-s > WindowSize { + return ErrReplayedPacket + } + + indexBlock &= NumBlocks - 1 + indexBit := s & (BlockBits - 1) + + prev := a.circle[indexBlock] + a.circle[indexBlock] = prev | 1< Date: Thu, 13 May 2021 18:28:05 +0100 Subject: [PATCH 4/5] anti-replay tests --- replay/replay.go | 2 +- replay/replay_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 replay/replay_test.go diff --git a/replay/replay.go b/replay/replay.go index 9ad37be..c6cf4f7 100644 --- a/replay/replay.go +++ b/replay/replay.go @@ -23,7 +23,7 @@ type AntiReplay struct { // for inbound packets mu sync.Mutex last uint64 - circle [1 << 7]uint64 + circle [NumBlocks]uint64 } func NewAntiReplay() *AntiReplay { diff --git a/replay/replay_test.go b/replay/replay_test.go new file mode 100644 index 0000000..0254d5c --- /dev/null +++ b/replay/replay_test.go @@ -0,0 +1,77 @@ +package replay + +import ( + "encoding/binary" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "math/rand" + "testing" +) + +func TestAntiReplay_Verify(t *testing.T) { + t.Run("NoReplays", func(t *testing.T) { + // ASSIGN + r := NewAntiReplay() + + start := rand.Uint64() + sum := make([]byte, 8) + + // ACT + ASSERT + for i := start; i < start+128; i++ { + // ACT + binary.LittleEndian.PutUint64(sum, i) + err := r.Verify(nil, sum) + + // ASSERT + require.Nil(t, err) + } + }) + + t.Run("ImmediateReplay", func(t *testing.T) { + // ASSIGN + r := NewAntiReplay() + + start := rand.Uint64() + sum := make([]byte, 8) + + // ACT + binary.LittleEndian.PutUint64(sum, start) + + err1 := r.Verify(nil, sum) + err2 := r.Verify(nil, sum) + + // ASSERT + require.Nil(t, err1) + require.Equal(t, ErrReplayedPacket, err2) + }) + + t.Run("RandomReplays", func(t *testing.T) { + // ASSIGN + r := NewAntiReplay() + + start := rand.Uint64() + sum := make([]byte, 8) + + random := make([]byte, 512/8) + rand.Read(random) + + // ACT + ASSERT + for i := 0; i < 512; i++ { + // ACT + replay := (random[i/8] & (1 << (i % 8)) > 0) && i != 0 + if !replay { + start++ + } + + binary.LittleEndian.PutUint64(sum, start) + err := r.Verify(nil, sum) + + // ASSERT + if replay { + assert.Equal(t, ErrReplayedPacket, err) + } else { + assert.Nil(t, err) + } + } + }) +} From 530ad9e929697a137468cd74f93da0d0e12e6607 Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Thu, 13 May 2021 18:30:48 +0100 Subject: [PATCH 5/5] formatting --- replay/replay_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/replay/replay_test.go b/replay/replay_test.go index 0254d5c..2ab3b4e 100644 --- a/replay/replay_test.go +++ b/replay/replay_test.go @@ -58,7 +58,7 @@ func TestAntiReplay_Verify(t *testing.T) { // ACT + ASSERT for i := 0; i < 512; i++ { // ACT - replay := (random[i/8] & (1 << (i % 8)) > 0) && i != 0 + replay := (random[i/8]&(1<<(i%8)) > 0) && i != 0 if !replay { start++ }