mirror of
https://github.com/logos-messaging/noise.git
synced 2026-05-22 09:59:30 +00:00
Add ErrMaxNonce before n overflows
This commit is contained in:
parent
0d4f803fc7
commit
927fa1b4bb
@ -2,6 +2,7 @@ package noise
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "gopkg.in/check.v1"
|
. "gopkg.in/check.v1"
|
||||||
@ -582,9 +583,14 @@ func (NoiseSuite) TestRekey(c *C) {
|
|||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
c.Assert(string(serverMessage), Equals, string(res))
|
c.Assert(string(serverMessage), Equals, string(res))
|
||||||
|
|
||||||
|
preNonce := csR1.Nonce()
|
||||||
|
|
||||||
csR1.Rekey()
|
csR1.Rekey()
|
||||||
csI1.Rekey()
|
csI1.Rekey()
|
||||||
|
|
||||||
|
postNonce := csR1.Nonce()
|
||||||
|
c.Assert(preNonce, Equals, postNonce)
|
||||||
|
|
||||||
serverMessage = []byte("bye bye")
|
serverMessage = []byte("bye bye")
|
||||||
msg, err = csR1.Encrypt(nil, nil, serverMessage)
|
msg, err = csR1.Encrypt(nil, nil, serverMessage)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
@ -600,4 +606,13 @@ func (NoiseSuite) TestRekey(c *C) {
|
|||||||
res, err = csI1.Decrypt(nil, nil, msg)
|
res, err = csI1.Decrypt(nil, nil, msg)
|
||||||
c.Assert(err, NotNil)
|
c.Assert(err, NotNil)
|
||||||
c.Assert(string(serverMessage), Not(Equals), string(res))
|
c.Assert(string(serverMessage), Not(Equals), string(res))
|
||||||
|
|
||||||
|
// check nonce overflow handling
|
||||||
|
csI1.n = math.MaxUint64
|
||||||
|
msg, err = csI1.Encrypt(nil, nil, nil)
|
||||||
|
c.Assert(err, Equals, ErrMaxNonce)
|
||||||
|
c.Assert(msg, IsNil)
|
||||||
|
msg, err = csI1.Decrypt(nil, nil, nil)
|
||||||
|
c.Assert(err, Equals, ErrMaxNonce)
|
||||||
|
c.Assert(msg, IsNil)
|
||||||
}
|
}
|
||||||
|
|||||||
23
state.go
23
state.go
@ -25,16 +25,25 @@ type CipherState struct {
|
|||||||
invalid bool
|
invalid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MaxNonce is the maximum value of n that is allowed. ErrMaxNonce is returned
|
||||||
|
// by Encrypt and Decrypt after this has been reached. 2^64-1 is reserved for rekeys.
|
||||||
|
const MaxNonce = uint64(math.MaxUint64) - 1
|
||||||
|
|
||||||
|
var ErrMaxNonce = errors.New("noise: cipherstate has reached maximum n, a new handshake must be performed")
|
||||||
var ErrCipherSuiteCopied = errors.New("noise: CipherSuite has been copied, state is invalid")
|
var ErrCipherSuiteCopied = errors.New("noise: CipherSuite has been copied, state is invalid")
|
||||||
|
|
||||||
// Encrypt encrypts the plaintext and then appends the ciphertext and an
|
// Encrypt encrypts the plaintext and then appends the ciphertext and an
|
||||||
// authentication tag across the ciphertext and optional authenticated data to
|
// authentication tag across the ciphertext and optional authenticated data to
|
||||||
// out. This method automatically increments the nonce after every call, so
|
// out. This method automatically increments the nonce after every call, so
|
||||||
// messages must be decrypted in the same order.
|
// messages must be decrypted in the same order. ErrMaxNonce is returned after
|
||||||
|
// the maximum nonce of 2^64-2 is reached.
|
||||||
func (s *CipherState) Encrypt(out, ad, plaintext []byte) ([]byte, error) {
|
func (s *CipherState) Encrypt(out, ad, plaintext []byte) ([]byte, error) {
|
||||||
if s.invalid {
|
if s.invalid {
|
||||||
return nil, ErrCipherSuiteCopied
|
return nil, ErrCipherSuiteCopied
|
||||||
}
|
}
|
||||||
|
if s.n > MaxNonce {
|
||||||
|
return nil, ErrMaxNonce
|
||||||
|
}
|
||||||
out = s.c.Encrypt(out, s.n, ad, plaintext)
|
out = s.c.Encrypt(out, s.n, ad, plaintext)
|
||||||
s.n++
|
s.n++
|
||||||
return out, nil
|
return out, nil
|
||||||
@ -43,11 +52,15 @@ func (s *CipherState) Encrypt(out, ad, plaintext []byte) ([]byte, error) {
|
|||||||
// Decrypt checks the authenticity of the ciphertext and authenticated data and
|
// Decrypt checks the authenticity of the ciphertext and authenticated data and
|
||||||
// then decrypts and appends the plaintext to out. This method automatically
|
// then decrypts and appends the plaintext to out. This method automatically
|
||||||
// increments the nonce after every call, messages must be provided in the same
|
// increments the nonce after every call, messages must be provided in the same
|
||||||
// order that they were encrypted with no missing messages.
|
// order that they were encrypted with no missing messages. ErrMaxNonce is
|
||||||
|
// returned after the maximum nonce of 2^64-2 is reached.
|
||||||
func (s *CipherState) Decrypt(out, ad, ciphertext []byte) ([]byte, error) {
|
func (s *CipherState) Decrypt(out, ad, ciphertext []byte) ([]byte, error) {
|
||||||
if s.invalid {
|
if s.invalid {
|
||||||
return nil, ErrCipherSuiteCopied
|
return nil, ErrCipherSuiteCopied
|
||||||
}
|
}
|
||||||
|
if s.n > MaxNonce {
|
||||||
|
return nil, ErrMaxNonce
|
||||||
|
}
|
||||||
out, err := s.c.Decrypt(out, s.n, ad, ciphertext)
|
out, err := s.c.Decrypt(out, s.n, ad, ciphertext)
|
||||||
s.n++
|
s.n++
|
||||||
return out, err
|
return out, err
|
||||||
@ -64,6 +77,12 @@ func (s *CipherState) Cipher() Cipher {
|
|||||||
return s.c
|
return s.c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nonce returns the current value of n. This can be used to determine if a
|
||||||
|
// new handshake should be performed due to approaching MaxNonce.
|
||||||
|
func (s *CipherState) Nonce() uint64 {
|
||||||
|
return s.n
|
||||||
|
}
|
||||||
|
|
||||||
func (s *CipherState) Rekey() {
|
func (s *CipherState) Rekey() {
|
||||||
var zeros [32]byte
|
var zeros [32]byte
|
||||||
var out []byte
|
var out []byte
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user