feat: Waku v2 bridge

Issue #12610
This commit is contained in:
Michal Iskierko
2023-11-12 13:29:38 +01:00
parent 56e7bd01ca
commit 6d31343205
6716 changed files with 1982502 additions and 5891 deletions

View File

@@ -0,0 +1,78 @@
package replaydetector
import (
"fmt"
)
// fixedBigInt is the fix-sized multi-word integer.
type fixedBigInt struct {
bits []uint64
n uint
msbMask uint64
}
// newFixedBigInt creates a new fix-sized multi-word int.
func newFixedBigInt(n uint) *fixedBigInt {
chunkSize := (n + 63) / 64
if chunkSize == 0 {
chunkSize = 1
}
return &fixedBigInt{
bits: make([]uint64, chunkSize),
n: n,
msbMask: (1 << (64 - n%64)) - 1,
}
}
// Lsh is the left shift operation.
func (s *fixedBigInt) Lsh(n uint) {
if n == 0 {
return
}
nChunk := int(n / 64)
nN := n % 64
for i := len(s.bits) - 1; i >= 0; i-- {
var carry uint64
if i-nChunk >= 0 {
carry = s.bits[i-nChunk] << nN
if i-nChunk-1 >= 0 {
carry |= s.bits[i-nChunk-1] >> (64 - nN)
}
}
s.bits[i] = (s.bits[i] << n) | carry
}
s.bits[len(s.bits)-1] &= s.msbMask
}
// Bit returns i-th bit of the fixedBigInt.
func (s *fixedBigInt) Bit(i uint) uint {
if i >= s.n {
return 0
}
chunk := i / 64
pos := i % 64
if s.bits[chunk]&(1<<pos) != 0 {
return 1
}
return 0
}
// SetBit sets i-th bit to 1.
func (s *fixedBigInt) SetBit(i uint) {
if i >= s.n {
return
}
chunk := i / 64
pos := i % 64
s.bits[chunk] |= 1 << pos
}
// String returns string representation of fixedBigInt.
func (s *fixedBigInt) String() string {
var out string
for i := len(s.bits) - 1; i >= 0; i-- {
out += fmt.Sprintf("%016X", s.bits[i])
}
return out
}

View File

@@ -0,0 +1,116 @@
// Package replaydetector provides packet replay detection algorithm.
package replaydetector
// ReplayDetector is the interface of sequence replay detector.
type ReplayDetector interface {
// Check returns true if given sequence number is not replayed.
// Call accept() to mark the packet is received properly.
Check(seq uint64) (accept func(), ok bool)
}
type slidingWindowDetector struct {
latestSeq uint64
maxSeq uint64
windowSize uint
mask *fixedBigInt
}
// New creates ReplayDetector.
// Created ReplayDetector doesn't allow wrapping.
// It can handle monotonically increasing sequence number up to
// full 64bit number. It is suitable for DTLS replay protection.
func New(windowSize uint, maxSeq uint64) ReplayDetector {
return &slidingWindowDetector{
maxSeq: maxSeq,
windowSize: windowSize,
mask: newFixedBigInt(windowSize),
}
}
func (d *slidingWindowDetector) Check(seq uint64) (accept func(), ok bool) {
if seq > d.maxSeq {
// Exceeded upper limit.
return func() {}, false
}
if seq <= d.latestSeq {
if d.latestSeq >= uint64(d.windowSize)+seq {
return func() {}, false
}
if d.mask.Bit(uint(d.latestSeq-seq)) != 0 {
// The sequence number is duplicated.
return func() {}, false
}
}
return func() {
if seq > d.latestSeq {
// Update the head of the window.
d.mask.Lsh(uint(seq - d.latestSeq))
d.latestSeq = seq
}
diff := (d.latestSeq - seq) % d.maxSeq
d.mask.SetBit(uint(diff))
}, true
}
// WithWrap creates ReplayDetector allowing sequence wrapping.
// This is suitable for short bitwidth counter like SRTP and SRTCP.
func WithWrap(windowSize uint, maxSeq uint64) ReplayDetector {
return &wrappedSlidingWindowDetector{
maxSeq: maxSeq,
windowSize: windowSize,
mask: newFixedBigInt(windowSize),
}
}
type wrappedSlidingWindowDetector struct {
latestSeq uint64
maxSeq uint64
windowSize uint
mask *fixedBigInt
init bool
}
func (d *wrappedSlidingWindowDetector) Check(seq uint64) (accept func(), ok bool) {
if seq > d.maxSeq {
// Exceeded upper limit.
return func() {}, false
}
if !d.init {
if seq != 0 {
d.latestSeq = seq - 1
} else {
d.latestSeq = d.maxSeq
}
d.init = true
}
diff := int64(d.latestSeq) - int64(seq)
// Wrap the number.
if diff > int64(d.maxSeq)/2 {
diff -= int64(d.maxSeq + 1)
} else if diff <= -int64(d.maxSeq)/2 {
diff += int64(d.maxSeq + 1)
}
if diff >= int64(d.windowSize) {
// Too old.
return func() {}, false
}
if diff >= 0 {
if d.mask.Bit(uint(diff)) != 0 {
// The sequence number is duplicated.
return func() {}, false
}
}
return func() {
if diff < 0 {
// Update the head of the window.
d.mask.Lsh(uint(-diff))
d.latestSeq = seq
}
d.mask.SetBit(uint(d.latestSeq - seq))
}, true
}