]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
Clear cryptographic state when interface down
authorMathias Hall-Andersen <mathias@hall-andersen.dk>
Fri, 2 Feb 2018 16:24:29 +0000 (17:24 +0100)
committerMathias Hall-Andersen <mathias@hall-andersen.dk>
Fri, 2 Feb 2018 16:24:29 +0000 (17:24 +0100)
Attempts to clear the cryptographic state for every
peer when the device goes down.

src/device.go
src/keypair.go
src/noise_protocol.go
src/peer.go
src/timers.go

index 0317b604723fb9b223858d72e8575a3f6c4dd15b..c0419877ea85130cf75f65834bcb4e54d4d84a58 100644 (file)
@@ -88,28 +88,6 @@ func unsafeRemovePeer(device *Device, peer *Peer, key NoisePublicKey) {
        device.routing.table.RemovePeer(peer)
        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
 
        delete(device.peers.keyMap, key)
index 7e5297b8e30b79c23090c9d9c300993c8ea0feed..283cb926ecfcbae40482489bcf7ebe8da0a13a22 100644 (file)
@@ -38,5 +38,7 @@ func (kp *KeyPairs) Current() *KeyPair {
 }
 
 func (device *Device) DeleteKeyPair(key *KeyPair) {
-       device.indices.Delete(key.localIndex)
+       if key != nil {
+               device.indices.Delete(key.localIndex)
+       }
 }
index d620a0d597367c10c6414c5bcd7d56099d89944c..c9713c08d486ca28d1cb9829c361e816811c0471 100644 (file)
@@ -121,6 +121,15 @@ func mixHash(dst *[blake2s.Size]byte, h *[blake2s.Size]byte, data []byte) {
        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) {
        mixHash(&h.hash, &h.hash, data)
 }
@@ -138,8 +147,8 @@ func init() {
 
 func (device *Device) CreateMessageInitiation(peer *Peer) (*MessageInitiation, error) {
 
-       device.noise.mutex.Lock()
-       defer device.noise.mutex.Unlock()
+       device.noise.mutex.RLock()
+       defer device.noise.mutex.RUnlock()
 
        handshake := &peer.handshake
        handshake.mutex.Lock()
@@ -393,7 +402,7 @@ func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
 
        ok := func() bool {
 
-               // read lock handshake
+               // lock handshake state
 
                handshake.mutex.RLock()
                defer handshake.mutex.RUnlock()
@@ -402,6 +411,11 @@ func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
                        return false
                }
 
+               // lock private key for reading
+
+               device.noise.mutex.RLock()
+               defer device.noise.mutex.RUnlock()
+
                // finish 3-way DH
 
                mixHash(&hash, &handshake.hash, msg.Ephemeral[:])
@@ -432,7 +446,7 @@ func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
                )
                mixHash(&hash, &hash, tau[:])
 
-               // authenticate
+               // authenticate transcript
 
                aead, _ := chacha20poly1305.New(key[:])
                _, err := aead.Open(nil, ZeroNonce[:], msg.Empty[:], hash[:])
index 3b8f7cca631728612199b5e91c3e3e95b1432c67..7776b71aa32d413db6c21b0720957ae417524bf9 100644 (file)
@@ -48,8 +48,8 @@ type Peer struct {
 
                // state related to WireGuard timers
 
-               keepalivePersistent Timer // set for persistent keepalives
-               keepalivePassive    Timer // set upon recieving messages
+               keepalivePersistent Timer // set for persistent keep-alive
+               keepalivePassive    Timer // set upon receiving messages
                zeroAllKeys         Timer // zero all key material
                handshakeNew        Timer // begin a new handshake (stale)
                handshakeDeadline   Timer // complete handshake timeout
@@ -69,7 +69,7 @@ type Peer struct {
                mutex    deadlock.Mutex // held when stopping / starting routines
                starting sync.WaitGroup // routines pending start
                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
@@ -123,7 +123,7 @@ func (device *Device) NewPeer(pk NoisePublicKey) (*Peer, error) {
        }
        device.peers.keyMap[pk] = peer
 
-       // precompute DH
+       // pre-compute DH
 
        handshake := &peer.handshake
        handshake.mutex.Lock()
@@ -186,16 +186,19 @@ func (peer *Peer) String() string {
 
 func (peer *Peer) Start() {
 
+       // should never start a peer on a closed device
+
        if peer.device.isClosed.Get() {
                return
        }
 
+       // prevent simultaneous start/stop operations
+
        peer.routines.mutex.Lock()
        defer peer.routines.mutex.Unlock()
-
        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.routines.stop.Broadcast()
@@ -230,12 +233,15 @@ func (peer *Peer) Start() {
 
 func (peer *Peer) Stop() {
 
+       // prevent simultaneous start/stop operations
+
        peer.routines.mutex.Lock()
        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.starting.Wait()
@@ -247,6 +253,28 @@ func (peer *Peer) Stop() {
        close(peer.queue.outbound)
        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)
 
        peer.routines.stop = NewSignal()
index 2ef105e00a1a8d858777ea36464c756a602dd6ad..709268870a1555e7e15daeb0ebe6198d5615503a 100644 (file)
@@ -274,12 +274,7 @@ func (peer *Peer) RoutineTimerHandler() {
                        // zero out handshake\r
 \r
                        device.indices.Delete(hs.localIndex)\r
-\r
-                       hs.localIndex = 0\r
-                       setZero(hs.localEphemeral[:])\r
-                       setZero(hs.remoteEphemeral[:])\r
-                       setZero(hs.chainKey[:])\r
-                       setZero(hs.hash[:])\r
+                       hs.Clear()\r
                        hs.mutex.Unlock()\r
 \r
                // handshake timers\r