diff options
author | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2017-07-10 12:09:19 +0200 |
---|---|---|
committer | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2017-07-10 12:09:19 +0200 |
commit | 44c98968838e1724d1ee77f086c4498f2a3f7643 (patch) | |
tree | a3820a9366025b634158c68e9711a2d241d87afa /src/replay.go | |
parent | 4ad62aaa6aa269f08c0fdc9c139e6d5417e21746 (diff) |
Added replay protection
Diffstat (limited to 'src/replay.go')
-rw-r--r-- | src/replay.go | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/replay.go b/src/replay.go new file mode 100644 index 0000000..49c7e08 --- /dev/null +++ b/src/replay.go @@ -0,0 +1,71 @@ +package main + +/* Implementation of RFC6479 + * https://tools.ietf.org/html/rfc6479 + * + * The implementation is not safe for concurrent use! + */ + +const ( + // See: https://golang.org/src/math/big/arith.go + _Wordm = ^uintptr(0) + _WordLogSize = _Wordm>>8&1 + _Wordm>>16&1 + _Wordm>>32&1 + _WordSize = 1 << _WordLogSize +) + +const ( + CounterRedundantBitsLog = _WordLogSize + 3 + CounterRedundantBits = _WordSize * 8 + CounterBitsTotal = 2048 + CounterWindowSize = uint64(CounterBitsTotal - CounterRedundantBits) +) + +const ( + BacktrackWords = CounterBitsTotal / _WordSize +) + +type ReplayFilter struct { + counter uint64 + backtrack [BacktrackWords]uintptr +} + +func (filter *ReplayFilter) Init() { + filter.counter = 0 + filter.backtrack[0] = 0 +} + +func (filter *ReplayFilter) ValidateCounter(counter uint64) bool { + if counter >= RejectAfterMessages { + return false + } + + indexWord := counter >> CounterRedundantBitsLog + + if counter > filter.counter { + + // move window forward + + current := filter.counter >> CounterRedundantBitsLog + diff := minUint64(indexWord-current, BacktrackWords) + for i := uint64(1); i <= diff; i++ { + filter.backtrack[(current+i)%BacktrackWords] = 0 + } + filter.counter = counter + + } else if filter.counter-counter > CounterWindowSize { + + // behind current window + + return false + } + + indexWord %= BacktrackWords + indexBit := counter & uint64(CounterRedundantBits-1) + + // check and set bit + + oldValue := filter.backtrack[indexWord] + newValue := oldValue | (1 << indexBit) + filter.backtrack[indexWord] = newValue + return oldValue != newValue +} |