mirror of
https://git.zx2c4.com/wireguard-go
synced 2026-10-22 06:22:48 +00:00
device: noise: reject response consumption after intermediate initiation
Two threads begin processing the identical response message, received twice. The first thread, A, runs. While it's running, the second one, B, gets partway through, and during that slow calculation, A completes and then also a handshake initiation that's already been queued up runs in thread C. The handshake initiation creation succeeds, and sets the state back to waiting-for-response, at which point thread B resumes. Thread B then copies the state back to the peer, and begins a new session, using that state, which is the same session as the one made in thread A. This seems basically impossible to hit in a meaningful way in practice, but ensure that it absolutely cannot happen by comparing the ephemeral private key that's on the stack with the latest one that the peer's handshake state has. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
@@ -509,7 +509,7 @@ func (device *Device) CreateMessageResponse(peer *Peer) (*MessageResponse, error
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
|
||||
func (device *Device) ConsumeMessageResponse(msg *MessageResponse) (peer *Peer) {
|
||||
if msg.Type != MessageResponseType {
|
||||
return nil
|
||||
}
|
||||
@@ -523,8 +523,9 @@ func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
|
||||
}
|
||||
|
||||
var (
|
||||
hash [blake2s.Size]byte
|
||||
chainKey [blake2s.Size]byte
|
||||
hash [blake2s.Size]byte
|
||||
chainKey [blake2s.Size]byte
|
||||
localEphemeral NoisePrivateKey
|
||||
)
|
||||
|
||||
ok := func() bool {
|
||||
@@ -582,6 +583,10 @@ func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
|
||||
return false
|
||||
}
|
||||
mixHash(&hash, &hash, msg.Empty[:])
|
||||
|
||||
// allow unlocking temporarily
|
||||
copy(localEphemeral[:], handshake.localEphemeral[:])
|
||||
|
||||
return true
|
||||
}()
|
||||
|
||||
@@ -592,18 +597,22 @@ func (device *Device) ConsumeMessageResponse(msg *MessageResponse) *Peer {
|
||||
// update handshake state
|
||||
|
||||
handshake.mutex.Lock()
|
||||
|
||||
handshake.hash = hash
|
||||
handshake.chainKey = chainKey
|
||||
handshake.remoteIndex = msg.Sender
|
||||
handshake.state = handshakeResponseConsumed
|
||||
if handshake.state == handshakeInitiationCreated &&
|
||||
handshake.localEphemeral.Equals(localEphemeral) {
|
||||
handshake.hash = hash
|
||||
handshake.chainKey = chainKey
|
||||
handshake.remoteIndex = msg.Sender
|
||||
handshake.state = handshakeResponseConsumed
|
||||
peer = lookup.peer
|
||||
}
|
||||
|
||||
handshake.mutex.Unlock()
|
||||
|
||||
setZero(hash[:])
|
||||
setZero(chainKey[:])
|
||||
setZero(localEphemeral[:])
|
||||
|
||||
return lookup.peer
|
||||
return
|
||||
}
|
||||
|
||||
/* Derives a new keypair from the current handshake state
|
||||
|
||||
Reference in New Issue
Block a user