aesgcm.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. package noiseutil
  2. import (
  3. "crypto/cipher"
  4. "encoding/binary"
  5. "errors"
  6. "github.com/flynn/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. nb[0] = 0
  24. nb[1] = 0
  25. nb[2] = 0
  26. nb[3] = 0
  27. binary.BigEndian.PutUint64(nb[4:], n)
  28. return s.c.Seal(out, nb, plaintext, ad), nil
  29. }
  30. func (s *CipherStateAESGCM) DecryptDanger(out, ad, ciphertext []byte, n uint64, nb []byte) ([]byte, error) {
  31. if s == nil {
  32. return []byte{}, nil
  33. }
  34. nb[0] = 0
  35. nb[1] = 0
  36. nb[2] = 0
  37. nb[3] = 0
  38. binary.BigEndian.PutUint64(nb[4:], n)
  39. return s.c.Open(out, nb, ciphertext, ad)
  40. }
  41. func (s *CipherStateAESGCM) Overhead() int {
  42. if s == nil {
  43. return 0
  44. }
  45. return s.c.Overhead()
  46. }