Clear cryptographic state when interface down
Attempts to clear the cryptographic state for every peer when the device goes down.
This commit is contained in:
parent
029410b118
commit
4f97b52ea6
|
@ -88,28 +88,6 @@ func unsafeRemovePeer(device *Device, peer *Peer, key NoisePublicKey) {
|
||||||
device.routing.table.RemovePeer(peer)
|
device.routing.table.RemovePeer(peer)
|
||||||
peer.Stop()
|
peer.Stop()
|
||||||
|
|
||||||
// clean index table
|
|
||||||
|
|
||||||
kp := &peer.keyPairs
|
|
||||||
kp.mutex.Lock()
|
|
||||||
|
|
||||||
if kp.previous != nil {
|
|
||||||
device.indices.Delete(kp.previous.localIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
if kp.current != nil {
|
|
||||||
device.indices.Delete(kp.current.localIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
if kp.next != nil {
|
|
||||||
device.indices.Delete(kp.next.localIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
kp.previous = nil
|
|
||||||
kp.current = nil
|
|
||||||
kp.next = nil
|
|
||||||
kp.mutex.Unlock()
|
|
||||||
|
|
||||||
// remove from peer map
|
// remove from peer map
|
||||||
|
|
||||||
delete(device.peers.keyMap, key)
|
delete(device.peers.keyMap, key)
|
||||||
|
|
|
@ -38,5 +38,7 @@ func (kp *KeyPairs) Current() *KeyPair {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (device *Device) DeleteKeyPair(key *KeyPair) {
|
func (device *Device) DeleteKeyPair(key *KeyPair) {
|
||||||
|
if key != nil {
|
||||||
device.indices.Delete(key.localIndex)
|
device.indices.Delete(key.localIndex)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -121,6 +121,15 @@ func mixHash(dst *[blake2s.Size]byte, h *[blake2s.Size]byte, data []byte) {
|
||||||
hsh.Reset()
|
hsh.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handshake) Clear() {
|
||||||
|
setZero(h.localEphemeral[:])
|
||||||
|
setZero(h.remoteEphemeral[:])
|
||||||
|
setZero(h.chainKey[:])
|
||||||
|
setZero(h.hash[:])
|
||||||
|
h.localIndex = 0
|
||||||
|
h.state = HandshakeZeroed
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handshake) mixHash(data []byte) {
|
func (h *Handshake) mixHash(data []byte) {
|
||||||
mixHash(&h.hash, &h.hash, data)
|
mixHash(&h.hash, &h.hash, data)
|
||||||
}
|
}
|
||||||
|
@ -138,8 +147,8 @@ func init() {
|
||||||
|
|
||||||
func (device *Device) CreateMessageInitiation(peer *Peer) (*MessageInitiation, error) {
|
func (device *Device) CreateMessageInitiation(peer *Peer) (*MessageInitiation, error) {
|
||||||
|
|
||||||
device.noise.mutex.Lock()
|
device.noise.mutex.RLock()
|
||||||
defer device.noise.mutex.Unlock()
|
defer device.noise.mutex.RUnlock()
|
||||||
|
|
||||||
handshake := &peer.handshake
|
handshake := &peer.handshake
|
||||||
handshake.mutex.Lock()
|
handshake.mutex.Lock()
|
||||||
|
@ -393,7 +402,7 @@ func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
|
||||||
|
|
||||||
ok := func() bool {
|
ok := func() bool {
|
||||||
|
|
||||||
// read lock handshake
|
// lock handshake state
|
||||||
|
|
||||||
handshake.mutex.RLock()
|
handshake.mutex.RLock()
|
||||||
defer handshake.mutex.RUnlock()
|
defer handshake.mutex.RUnlock()
|
||||||
|
@ -402,6 +411,11 @@ func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lock private key for reading
|
||||||
|
|
||||||
|
device.noise.mutex.RLock()
|
||||||
|
defer device.noise.mutex.RUnlock()
|
||||||
|
|
||||||
// finish 3-way DH
|
// finish 3-way DH
|
||||||
|
|
||||||
mixHash(&hash, &handshake.hash, msg.Ephemeral[:])
|
mixHash(&hash, &handshake.hash, msg.Ephemeral[:])
|
||||||
|
@ -432,7 +446,7 @@ func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
|
||||||
)
|
)
|
||||||
mixHash(&hash, &hash, tau[:])
|
mixHash(&hash, &hash, tau[:])
|
||||||
|
|
||||||
// authenticate
|
// authenticate transcript
|
||||||
|
|
||||||
aead, _ := chacha20poly1305.New(key[:])
|
aead, _ := chacha20poly1305.New(key[:])
|
||||||
_, err := aead.Open(nil, ZeroNonce[:], msg.Empty[:], hash[:])
|
_, err := aead.Open(nil, ZeroNonce[:], msg.Empty[:], hash[:])
|
||||||
|
|
44
src/peer.go
44
src/peer.go
|
@ -48,8 +48,8 @@ type Peer struct {
|
||||||
|
|
||||||
// state related to WireGuard timers
|
// state related to WireGuard timers
|
||||||
|
|
||||||
keepalivePersistent Timer // set for persistent keepalives
|
keepalivePersistent Timer // set for persistent keep-alive
|
||||||
keepalivePassive Timer // set upon recieving messages
|
keepalivePassive Timer // set upon receiving messages
|
||||||
zeroAllKeys Timer // zero all key material
|
zeroAllKeys Timer // zero all key material
|
||||||
handshakeNew Timer // begin a new handshake (stale)
|
handshakeNew Timer // begin a new handshake (stale)
|
||||||
handshakeDeadline Timer // complete handshake timeout
|
handshakeDeadline Timer // complete handshake timeout
|
||||||
|
@ -69,7 +69,7 @@ type Peer struct {
|
||||||
mutex deadlock.Mutex // held when stopping / starting routines
|
mutex deadlock.Mutex // held when stopping / starting routines
|
||||||
starting sync.WaitGroup // routines pending start
|
starting sync.WaitGroup // routines pending start
|
||||||
stopping sync.WaitGroup // routines pending stop
|
stopping sync.WaitGroup // routines pending stop
|
||||||
stop Signal // size 0, stop all goroutines in peer
|
stop Signal // size 0, stop all go-routines in peer
|
||||||
}
|
}
|
||||||
|
|
||||||
mac CookieGenerator
|
mac CookieGenerator
|
||||||
|
@ -123,7 +123,7 @@ func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) {
|
||||||
}
|
}
|
||||||
device.peers.keyMap[pk] = peer
|
device.peers.keyMap[pk] = peer
|
||||||
|
|
||||||
// precompute DH
|
// pre-compute DH
|
||||||
|
|
||||||
handshake := &peer.handshake
|
handshake := &peer.handshake
|
||||||
handshake.mutex.Lock()
|
handshake.mutex.Lock()
|
||||||
|
@ -186,16 +186,19 @@ func (peer *Peer) String() string {
|
||||||
|
|
||||||
func (peer *Peer) Start() {
|
func (peer *Peer) Start() {
|
||||||
|
|
||||||
|
// should never start a peer on a closed device
|
||||||
|
|
||||||
if peer.device.isClosed.Get() {
|
if peer.device.isClosed.Get() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prevent simultaneous start/stop operations
|
||||||
|
|
||||||
peer.routines.mutex.Lock()
|
peer.routines.mutex.Lock()
|
||||||
defer peer.routines.mutex.Unlock()
|
defer peer.routines.mutex.Unlock()
|
||||||
|
|
||||||
peer.device.log.Debug.Println("Starting:", peer.String())
|
peer.device.log.Debug.Println("Starting:", peer.String())
|
||||||
|
|
||||||
// stop & wait for ungoing routines (if any)
|
// stop & wait for ongoing routines (if any)
|
||||||
|
|
||||||
peer.isRunning.Set(false)
|
peer.isRunning.Set(false)
|
||||||
peer.routines.stop.Broadcast()
|
peer.routines.stop.Broadcast()
|
||||||
|
@ -230,12 +233,15 @@ func (peer *Peer) Start() {
|
||||||
|
|
||||||
func (peer *Peer) Stop() {
|
func (peer *Peer) Stop() {
|
||||||
|
|
||||||
|
// prevent simultaneous start/stop operations
|
||||||
|
|
||||||
peer.routines.mutex.Lock()
|
peer.routines.mutex.Lock()
|
||||||
defer peer.routines.mutex.Unlock()
|
defer peer.routines.mutex.Unlock()
|
||||||
|
|
||||||
peer.device.log.Debug.Println("Stopping:", peer.String())
|
device := peer.device
|
||||||
|
device.log.Debug.Println("Stopping:", peer.String())
|
||||||
|
|
||||||
// stop & wait for ungoing routines (if any)
|
// stop & wait for ongoing peer routines (if any)
|
||||||
|
|
||||||
peer.routines.stop.Broadcast()
|
peer.routines.stop.Broadcast()
|
||||||
peer.routines.starting.Wait()
|
peer.routines.starting.Wait()
|
||||||
|
@ -247,6 +253,28 @@ func (peer *Peer) Stop() {
|
||||||
close(peer.queue.outbound)
|
close(peer.queue.outbound)
|
||||||
close(peer.queue.inbound)
|
close(peer.queue.inbound)
|
||||||
|
|
||||||
|
// clear key pairs
|
||||||
|
|
||||||
|
kp := &peer.keyPairs
|
||||||
|
kp.mutex.Lock()
|
||||||
|
|
||||||
|
device.DeleteKeyPair(kp.previous)
|
||||||
|
device.DeleteKeyPair(kp.current)
|
||||||
|
device.DeleteKeyPair(kp.next)
|
||||||
|
|
||||||
|
kp.previous = nil
|
||||||
|
kp.current = nil
|
||||||
|
kp.next = nil
|
||||||
|
kp.mutex.Unlock()
|
||||||
|
|
||||||
|
// clear handshake state
|
||||||
|
|
||||||
|
hs := &peer.handshake
|
||||||
|
hs.mutex.Lock()
|
||||||
|
device.indices.Delete(hs.localIndex)
|
||||||
|
hs.Clear()
|
||||||
|
hs.mutex.Unlock()
|
||||||
|
|
||||||
// reset signal (to handle repeated stopping)
|
// reset signal (to handle repeated stopping)
|
||||||
|
|
||||||
peer.routines.stop = NewSignal()
|
peer.routines.stop = NewSignal()
|
||||||
|
|
|
@ -274,12 +274,7 @@ func (peer *Peer) RoutineTimerHandler() {
|
||||||
// zero out handshake
|
// zero out handshake
|
||||||
|
|
||||||
device.indices.Delete(hs.localIndex)
|
device.indices.Delete(hs.localIndex)
|
||||||
|
hs.Clear()
|
||||||
hs.localIndex = 0
|
|
||||||
setZero(hs.localEphemeral[:])
|
|
||||||
setZero(hs.remoteEphemeral[:])
|
|
||||||
setZero(hs.chainKey[:])
|
|
||||||
setZero(hs.hash[:])
|
|
||||||
hs.mutex.Unlock()
|
hs.mutex.Unlock()
|
||||||
|
|
||||||
// handshake timers
|
// handshake timers
|
||||||
|
|
Loading…
Reference in a new issue