aesgcm.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. package noiseutil
  2. import (
  3. "crypto/cipher"
  4. "encoding/binary"
  5. "errors"
  6. "github.com/DefinedNet/noise"
  7. )
  8. // CipherStateAESGCM is the data-plane wrapper for the AES-GCM AEAD cipher.
  9. // AES-GCM uses big-endian nonce encoding per the Noise spec.
  10. type CipherStateAESGCM struct {
  11. c cipher.AEAD
  12. }
  13. // NewCipherStateAESGCM extracts the underlying AEAD from the post-handshake noise.CipherState.
  14. // The caller is responsible for ensuring the noise cipher is actually AES-GCM,
  15. // otherwise the type assertion still succeeds but the nonce endianness will be wrong on the wire.
  16. func NewCipherStateAESGCM(s *noise.CipherState) *CipherStateAESGCM {
  17. return &CipherStateAESGCM{c: s.Cipher().(cipher.AEAD)}
  18. }
  19. func (s *CipherStateAESGCM) EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error) {
  20. if s == nil {
  21. return nil, errors.New("no cipher state available to encrypt")
  22. }
  23. if n >= RejectAfterMessages {
  24. return nil, ErrMessageCounterExhausted
  25. }
  26. nb[0] = 0
  27. nb[1] = 0
  28. nb[2] = 0
  29. nb[3] = 0
  30. binary.BigEndian.PutUint64(nb[4:], n)
  31. return s.c.Seal(out, nb, plaintext, ad), nil
  32. }
  33. func (s *CipherStateAESGCM) DecryptDanger(out, ad, ciphertext []byte, n uint64, nb []byte) ([]byte, error) {
  34. if s == nil {
  35. return []byte{}, nil
  36. }
  37. nb[0] = 0
  38. nb[1] = 0
  39. nb[2] = 0
  40. nb[3] = 0
  41. binary.BigEndian.PutUint64(nb[4:], n)
  42. return s.c.Open(out, nb, ciphertext, ad)
  43. }
  44. func (s *CipherStateAESGCM) Overhead() int {
  45. if s == nil {
  46. return 0
  47. }
  48. return s.c.Overhead()
  49. }