wgengine/magicsock: cache precomputed nacl/box shared keys
Updates #483
This commit is contained in:
parent
a975e86bb8
commit
a83ca9e734
|
@ -95,6 +95,7 @@ type Conn struct {
|
||||||
discoOfNode map[tailcfg.NodeKey]tailcfg.DiscoKey
|
discoOfNode map[tailcfg.NodeKey]tailcfg.DiscoKey
|
||||||
|
|
||||||
endpointOfDisco map[tailcfg.DiscoKey]*discoEndpoint
|
endpointOfDisco map[tailcfg.DiscoKey]*discoEndpoint
|
||||||
|
sharedDiscoKey map[tailcfg.DiscoKey]*[32]byte // nacl/box precomputed key
|
||||||
|
|
||||||
// addrsByUDP is a map of every remote ip:port to a priority
|
// addrsByUDP is a map of every remote ip:port to a priority
|
||||||
// list of endpoint addresses for a peer.
|
// list of endpoint addresses for a peer.
|
||||||
|
@ -250,6 +251,7 @@ func newConn() *Conn {
|
||||||
derpStarted: make(chan struct{}),
|
derpStarted: make(chan struct{}),
|
||||||
peerLastDerp: make(map[key.Public]int),
|
peerLastDerp: make(map[key.Public]int),
|
||||||
endpointOfDisco: make(map[tailcfg.DiscoKey]*discoEndpoint),
|
endpointOfDisco: make(map[tailcfg.DiscoKey]*discoEndpoint),
|
||||||
|
sharedDiscoKey: make(map[tailcfg.DiscoKey]*[32]byte),
|
||||||
}
|
}
|
||||||
c.endpointsUpdateWaiter = sync.NewCond(&c.mu)
|
c.endpointsUpdateWaiter = sync.NewCond(&c.mu)
|
||||||
return c
|
return c
|
||||||
|
@ -499,6 +501,11 @@ func (c *Conn) SetNetInfoCallback(fn func(*tailcfg.NetInfo)) {
|
||||||
func (c *Conn) SetDiscoPrivateKey(k key.Private) {
|
func (c *Conn) SetDiscoPrivateKey(k key.Private) {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
if !c.discoPrivate.IsZero() && c.discoPrivate != k {
|
||||||
|
// TODO: support changing a key at runtime; need to
|
||||||
|
// clear a bunch of maps at least
|
||||||
|
panic("unsupported")
|
||||||
|
}
|
||||||
c.discoPrivate = k
|
c.discoPrivate = k
|
||||||
c.logf("magicsock: disco key set; public: %x", k.Public())
|
c.logf("magicsock: disco key set; public: %x", k.Public())
|
||||||
}
|
}
|
||||||
|
@ -1348,7 +1355,7 @@ func (c *Conn) handleDiscoMessage(msg []byte, addr *net.UDPAddr) bool {
|
||||||
var nonce [nonceLen]byte
|
var nonce [nonceLen]byte
|
||||||
copy(nonce[:], msg[len(magic)+len(key.Public{}):])
|
copy(nonce[:], msg[len(magic)+len(key.Public{}):])
|
||||||
sealedBox := msg[headerLen:]
|
sealedBox := msg[headerLen:]
|
||||||
payload, ok := box.Open(nil, sealedBox, &nonce, key.Public(sender).B32(), c.discoPrivate.B32())
|
payload, ok := box.OpenAfterPrecomputation(nil, sealedBox, &nonce, c.sharedDiscoKeyLocked(sender))
|
||||||
if !ok {
|
if !ok {
|
||||||
c.logf("magicsock: failed to open disco message box purportedly from %s (disco key %x)", senderNode.Key.ShortString(), sender[:])
|
c.logf("magicsock: failed to open disco message box purportedly from %s (disco key %x)", senderNode.Key.ShortString(), sender[:])
|
||||||
return false
|
return false
|
||||||
|
@ -1358,6 +1365,16 @@ func (c *Conn) handleDiscoMessage(msg []byte, addr *net.UDPAddr) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Conn) sharedDiscoKeyLocked(k tailcfg.DiscoKey) *[32]byte {
|
||||||
|
if v, ok := c.sharedDiscoKey[k]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
shared := new([32]byte)
|
||||||
|
box.Precompute(shared, key.Public(k).B32(), c.discoPrivate.B32())
|
||||||
|
c.sharedDiscoKey[k] = shared
|
||||||
|
return shared
|
||||||
|
}
|
||||||
|
|
||||||
// SetPrivateKey sets the connection's private key.
|
// SetPrivateKey sets the connection's private key.
|
||||||
//
|
//
|
||||||
// This is only used to be able prove our identity when connecting to
|
// This is only used to be able prove our identity when connecting to
|
||||||
|
@ -1491,6 +1508,7 @@ func (c *Conn) SetNetworkMap(nm *controlclient.NetworkMap) {
|
||||||
if _, ok := c.nodeOfDisco[dk]; !ok {
|
if _, ok := c.nodeOfDisco[dk]; !ok {
|
||||||
de.cleanup()
|
de.cleanup()
|
||||||
delete(c.endpointOfDisco, dk)
|
delete(c.endpointOfDisco, dk)
|
||||||
|
delete(c.sharedDiscoKey, dk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -841,12 +841,11 @@ func TestDiscoMessage(t *testing.T) {
|
||||||
peer1Priv := key.NewPrivate()
|
peer1Priv := key.NewPrivate()
|
||||||
peer1Pub := peer1Priv.Public()
|
peer1Pub := peer1Priv.Public()
|
||||||
|
|
||||||
c := &Conn{
|
c := newConn()
|
||||||
logf: t.Logf,
|
c.logf = t.Logf
|
||||||
discoPrivate: key.NewPrivate(),
|
c.SetDiscoPrivateKey(key.NewPrivate())
|
||||||
nodeOfDisco: map[tailcfg.DiscoKey]*tailcfg.Node{
|
c.nodeOfDisco = map[tailcfg.DiscoKey]*tailcfg.Node{
|
||||||
tailcfg.DiscoKey(peer1Pub): &tailcfg.Node{Key: tailcfg.NodeKey{1: 1}},
|
tailcfg.DiscoKey(peer1Pub): &tailcfg.Node{Key: tailcfg.NodeKey{1: 1}},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const payload = "why hello"
|
const payload = "why hello"
|
||||||
|
|
Loading…
Reference in New Issue