github.com/slackhq/nebula@v1.9.0/noiseutil/boring.go (about) 1 //go:build boringcrypto 2 // +build boringcrypto 3 4 package noiseutil 5 6 import ( 7 "crypto/aes" 8 "crypto/cipher" 9 "encoding/binary" 10 11 // unsafe needed for go:linkname 12 _ "unsafe" 13 14 "github.com/flynn/noise" 15 ) 16 17 // EncryptLockNeeded indicates if calls to Encrypt need a lock 18 // This is true for boringcrypto because the Seal function verifies that the 19 // nonce is strictly increasing. 20 const EncryptLockNeeded = true 21 22 // NewGCMTLS is no longer exposed in go1.19+, so we need to link it in 23 // See: https://github.com/golang/go/issues/56326 24 // 25 // NewGCMTLS is the internal method used with boringcrypto that provices a 26 // validated mode of AES-GCM which enforces the nonce is strictly 27 // monotonically increasing. This is the TLS 1.2 specification for nonce 28 // generation (which also matches the method used by the Noise Protocol) 29 // 30 // - https://github.com/golang/go/blob/go1.19/src/crypto/tls/cipher_suites.go#L520-L522 31 // - https://github.com/golang/go/blob/go1.19/src/crypto/internal/boring/aes.go#L235-L237 32 // - https://github.com/golang/go/blob/go1.19/src/crypto/internal/boring/aes.go#L250 33 // - https://github.com/google/boringssl/blob/ae223d6138807a13006342edfeef32e813246b39/include/openssl/aead.h#L379-L381 34 // - https://github.com/google/boringssl/blob/ae223d6138807a13006342edfeef32e813246b39/crypto/fipsmodule/cipher/e_aes.c#L1082-L1093 35 // 36 //go:linkname newGCMTLS crypto/internal/boring.NewGCMTLS 37 func newGCMTLS(c cipher.Block) (cipher.AEAD, error) 38 39 type cipherFn struct { 40 fn func([32]byte) noise.Cipher 41 name string 42 } 43 44 func (c cipherFn) Cipher(k [32]byte) noise.Cipher { return c.fn(k) } 45 func (c cipherFn) CipherName() string { return c.name } 46 47 // CipherAESGCM is the AES256-GCM AEAD cipher (using NewGCMTLS when GoBoring is present) 48 var CipherAESGCM noise.CipherFunc = cipherFn{cipherAESGCMBoring, "AESGCM"} 49 50 func cipherAESGCMBoring(k [32]byte) noise.Cipher { 51 c, err := aes.NewCipher(k[:]) 52 if err != nil { 53 panic(err) 54 } 55 gcm, err := newGCMTLS(c) 56 if err != nil { 57 panic(err) 58 } 59 return aeadCipher{ 60 gcm, 61 func(n uint64) []byte { 62 var nonce [12]byte 63 binary.BigEndian.PutUint64(nonce[4:], n) 64 return nonce[:] 65 }, 66 } 67 } 68 69 type aeadCipher struct { 70 cipher.AEAD 71 nonce func(uint64) []byte 72 } 73 74 func (c aeadCipher) Encrypt(out []byte, n uint64, ad, plaintext []byte) []byte { 75 return c.Seal(out, c.nonce(n), plaintext, ad) 76 } 77 78 func (c aeadCipher) Decrypt(out []byte, n uint64, ad, ciphertext []byte) ([]byte, error) { 79 return c.Open(out, c.nonce(n), ciphertext, ad) 80 }