mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
control/noise: factor out nonce checking and incrementing into a type.
Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
parent
d3acd35a90
commit
a34350ffda
@ -51,7 +51,7 @@ type Conn struct {
|
||||
type rxState struct {
|
||||
sync.Mutex
|
||||
cipher cipher.AEAD
|
||||
nonce [chp.NonceSize]byte
|
||||
nonce nonce
|
||||
buf [maxMessageSize]byte
|
||||
n int // number of valid bytes in buf
|
||||
next int // offset of next undecrypted packet
|
||||
@ -62,7 +62,7 @@ type rxState struct {
|
||||
type txState struct {
|
||||
sync.Mutex
|
||||
cipher cipher.AEAD
|
||||
nonce [chp.NonceSize]byte
|
||||
nonce nonce
|
||||
buf [maxMessageSize]byte
|
||||
err error // records the first partial write error for all future calls
|
||||
}
|
||||
@ -86,12 +86,6 @@ func (c *Conn) Peer() key.MachinePublic {
|
||||
return c.peer
|
||||
}
|
||||
|
||||
// validNonce reports whether nonce is in the valid range for use: 0
|
||||
// through 2^64-2.
|
||||
func validNonce(nonce []byte) bool {
|
||||
return binary.BigEndian.Uint32(nonce[:4]) == 0 && binary.BigEndian.Uint64(nonce[4:]) != invalidNonce
|
||||
}
|
||||
|
||||
// readNLocked reads into c.rx.buf until buf contains at least total
|
||||
// bytes. Returns a slice of the available bytes in rxBuf, or an
|
||||
// error if fewer than total bytes are available.
|
||||
@ -123,15 +117,12 @@ func (c *Conn) decryptLocked(msg []byte) (err error) {
|
||||
// be.
|
||||
ciphertext := msg[headerLen:]
|
||||
|
||||
if !validNonce(c.rx.nonce[:]) {
|
||||
if !c.rx.nonce.Valid() {
|
||||
return errCipherExhausted{}
|
||||
}
|
||||
|
||||
c.rx.plaintext, err = c.rx.cipher.Open(ciphertext[:0], c.rx.nonce[:], ciphertext, nil)
|
||||
|
||||
// Safe to increment the nonce here, because we checked for nonce
|
||||
// wraparound above.
|
||||
binary.BigEndian.PutUint64(c.rx.nonce[4:], 1+binary.BigEndian.Uint64(c.rx.nonce[4:]))
|
||||
c.rx.nonce.Increment()
|
||||
|
||||
if err != nil {
|
||||
// Once a decryption has failed, our Conn is no longer
|
||||
@ -147,7 +138,7 @@ func (c *Conn) decryptLocked(msg []byte) (err error) {
|
||||
// packet header) and returns a slice of the ciphertext, or an error
|
||||
// if the cipher is exhausted (i.e. can no longer be used safely).
|
||||
func (c *Conn) encryptLocked(plaintext []byte) ([]byte, error) {
|
||||
if !validNonce(c.tx.nonce[:]) {
|
||||
if !c.tx.nonce.Valid() {
|
||||
// Received 2^64-1 messages on this cipher state. Connection
|
||||
// is no longer usable.
|
||||
return nil, errCipherExhausted{}
|
||||
@ -156,10 +147,7 @@ func (c *Conn) encryptLocked(plaintext []byte) ([]byte, error) {
|
||||
c.tx.buf[0] = msgTypeRecord
|
||||
binary.BigEndian.PutUint16(c.tx.buf[1:headerLen], uint16(len(plaintext)+chp.Overhead))
|
||||
ret := c.tx.cipher.Seal(c.tx.buf[:headerLen], c.tx.nonce[:], plaintext, nil)
|
||||
|
||||
// Safe to increment the nonce here, because we checked for nonce
|
||||
// wraparound above.
|
||||
binary.BigEndian.PutUint64(c.tx.nonce[4:], 1+binary.BigEndian.Uint64(c.tx.nonce[4:]))
|
||||
c.tx.nonce.Increment()
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
@ -357,3 +345,16 @@ func (e errReadTooBig) Temporary() bool {
|
||||
return false
|
||||
}
|
||||
func (e errReadTooBig) Timeout() bool { return false }
|
||||
|
||||
type nonce [chp.NonceSize]byte
|
||||
|
||||
func (n *nonce) Valid() bool {
|
||||
return binary.BigEndian.Uint32(n[:4]) == 0 && binary.BigEndian.Uint64(n[4:]) != invalidNonce
|
||||
}
|
||||
|
||||
func (n *nonce) Increment() {
|
||||
if !n.Valid() {
|
||||
panic("increment of invalid nonce")
|
||||
}
|
||||
binary.BigEndian.PutUint64(n[4:], 1+binary.BigEndian.Uint64(n[4:]))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user