cipher_state.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. package noiseutil
  2. import (
  3. "errors"
  4. "fmt"
  5. "math"
  6. "github.com/DefinedNet/noise"
  7. )
  8. // RejectHeadroom is the wrap gap for senders racing the counter, sized large enough for any routine count.
  9. const RejectHeadroom = uint64(1) << 40
  10. // RejectAfterMessages is the nonce ceiling: encrypting stops RejectHeadroom short of the wrap.
  11. const RejectAfterMessages = math.MaxUint64 - RejectHeadroom
  12. // ErrMessageCounterExhausted is returned by EncryptDanger once the nonce reaches RejectAfterMessages.
  13. var ErrMessageCounterExhausted = errors.New("message counter exhausted")
  14. // CipherState is the post-handshake AEAD cipher used for the data plane.
  15. // Each supported cipher has its own concrete implementation in this package with the nonce endianness hardcoded,
  16. // so the encrypt/decrypt fast path avoids interface dispatch on the byte order.
  17. type CipherState interface {
  18. // EncryptDanger encrypts and authenticates a given payload.
  19. //
  20. // out is a destination slice to hold the output of the EncryptDanger operation.
  21. // - ad is additional data, which will be authenticated and appended to out, but not encrypted.
  22. // - plaintext is encrypted, authenticated and appended to out.
  23. // - n is a nonce value which must never be re-used with this key.
  24. // - nb is a scratch buffer used to assemble the nonce.
  25. EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error)
  26. // DecryptDanger authenticates and decrypts a given payload, with the same argument shape as EncryptDanger.
  27. DecryptDanger(out, ad, ciphertext []byte, n uint64, nb []byte) ([]byte, error)
  28. // Overhead returns the AEAD tag size, or 0 if the receiver is nil.
  29. Overhead() int
  30. }
  31. // NewCipherState wraps the post-handshake noise.CipherState in the per-cipher type that matches cipherFunc.
  32. // cipherFunc must be the same cipher used to build the noise CipherSuite that produced s.
  33. func NewCipherState(s *noise.CipherState, cipherFunc noise.CipherFunc) CipherState {
  34. if cs, ok := s.Cipher().(CipherState); ok {
  35. return cs
  36. }
  37. switch cipherFunc.CipherName() {
  38. case noise.CipherAESGCM.CipherName():
  39. return NewCipherStateAESGCM(s)
  40. case noise.CipherChaChaPoly.CipherName():
  41. return NewCipherStateChaChaPoly(s)
  42. default:
  43. panic(fmt.Sprintf("noiseutil: unsupported cipher %q", cipherFunc.CipherName()))
  44. }
  45. }