diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2018-05-23 02:32:02 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2018-05-23 03:58:27 +0200 |
commit | 5a2228a5c910ada948677f1dd3fcc59f74e5cb20 (patch) | |
tree | bafb31cbcc18221e2299f8fef21d9c2f4471f706 /replay/replay.go | |
parent | 0a63188afab1dd49380f916963307f9b2efdcac1 (diff) |
Move replay into subpackage
Diffstat (limited to 'replay/replay.go')
-rw-r--r-- | replay/replay.go | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/replay/replay.go b/replay/replay.go new file mode 100644 index 0000000..993ff58 --- /dev/null +++ b/replay/replay.go @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. + * Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>. + */ + +package replay + +/* 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 +) + +func minUint64(a uint64, b uint64) uint64 { + if a > b { + return b + } + return a +} + +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, limit uint64) bool { + if counter >= limit { + 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 +} |