diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index fc654da..148f79b 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -52,4 +52,12 @@ jobs: working-directory: ./.github/workflows/smoke run: NAME="smoke-p256" ./smoke.sh + - name: setup docker image for fips140 + working-directory: ./.github/workflows/smoke + run: NAME="smoke-fips140" CURVE=P256 GOFIPS140=v1.0.0 LDFLAGS=-checklinkname=0 ./build.sh + + - name: run smoke-fips140 + working-directory: ./.github/workflows/smoke + run: NAME="smoke-fips140" ./smoke.sh + timeout-minutes: 10 diff --git a/noise.go b/noise.go index 57990a7..392f0b6 100644 --- a/noise.go +++ b/noise.go @@ -25,6 +25,11 @@ func NewNebulaCipherState(s *noise.CipherState) *NebulaCipherState { } +type cipherAEADDanger interface { + EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error) + DecryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error) +} + // EncryptDanger encrypts and authenticates a given payload. // // out is a destination slice to hold the output of the EncryptDanger operation. @@ -35,20 +40,25 @@ func NewNebulaCipherState(s *noise.CipherState) *NebulaCipherState { // be re-used by callers to minimize garbage collection. func (s *NebulaCipherState) EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error) { if s != nil { - // TODO: Is this okay now that we have made messageCounter atomic? - // Alternative may be to split the counter space into ranges - //if n <= s.n { - // return nil, errors.New("CRITICAL: a duplicate counter value was used") - //} - //s.n = n - nb[0] = 0 - nb[1] = 0 - nb[2] = 0 - nb[3] = 0 - noiseEndianness.PutUint64(nb[4:], n) - out = s.c.(cipher.AEAD).Seal(out, nb, plaintext, ad) - //l.Debugf("Encryption: outlen: %d, nonce: %d, ad: %s, plainlen %d", len(out), n, ad, len(plaintext)) - return out, nil + switch ce := s.c.(type) { + case cipherAEADDanger: + return ce.EncryptDanger(out, ad, plaintext, n, nb) + default: + // TODO: Is this okay now that we have made messageCounter atomic? + // Alternative may be to split the counter space into ranges + //if n <= s.n { + // return nil, errors.New("CRITICAL: a duplicate counter value was used") + //} + //s.n = n + nb[0] = 0 + nb[1] = 0 + nb[2] = 0 + nb[3] = 0 + noiseEndianness.PutUint64(nb[4:], n) + out = s.c.(cipher.AEAD).Seal(out, nb, plaintext, ad) + //l.Debugf("Encryption: outlen: %d, nonce: %d, ad: %s, plainlen %d", len(out), n, ad, len(plaintext)) + return out, nil + } } else { return nil, errors.New("no cipher state available to encrypt") } @@ -56,12 +66,17 @@ func (s *NebulaCipherState) EncryptDanger(out, ad, plaintext []byte, n uint64, n func (s *NebulaCipherState) DecryptDanger(out, ad, ciphertext []byte, n uint64, nb []byte) ([]byte, error) { if s != nil { - nb[0] = 0 - nb[1] = 0 - nb[2] = 0 - nb[3] = 0 - noiseEndianness.PutUint64(nb[4:], n) - return s.c.(cipher.AEAD).Open(out, nb, ciphertext, ad) + switch ce := s.c.(type) { + case cipherAEADDanger: + return ce.DecryptDanger(out, ad, ciphertext, n, nb) + default: + nb[0] = 0 + nb[1] = 0 + nb[2] = 0 + nb[3] = 0 + noiseEndianness.PutUint64(nb[4:], n) + return s.c.(cipher.AEAD).Open(out, nb, ciphertext, ad) + } } else { return []byte{}, nil } diff --git a/noiseutil/fips140.go b/noiseutil/fips140.go index 4fd6f14..3f4507d 100644 --- a/noiseutil/fips140.go +++ b/noiseutil/fips140.go @@ -40,16 +40,12 @@ var CipherAESGCM noise.CipherFunc = cipherFn{cipherAESGCM, "AESGCM"} var emptyPrefix = []byte{0, 0, 0, 0} func cipherAESGCM(k [32]byte) noise.Cipher { - // c, err := aes.NewCipher(k[:]) - // if err != nil { - // panic(err) - // } gcm := aeadAESGCM(k[:], emptyPrefix) return aeadCipher{ gcm, func(n uint64) []byte { - var nonce [12]byte - binary.BigEndian.PutUint64(nonce[4:], n) + var nonce [8]byte + binary.BigEndian.PutUint64(nonce[:], n) return nonce[:] }, } @@ -67,3 +63,14 @@ func (c aeadCipher) Encrypt(out []byte, n uint64, ad, plaintext []byte) []byte { func (c aeadCipher) Decrypt(out []byte, n uint64, ad, ciphertext []byte) ([]byte, error) { return c.Open(out, c.nonce(n), ciphertext, ad) } + +func (c aeadCipher) EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error) { + binary.BigEndian.PutUint64(nb[4:], n) + out = c.Seal(out, nb[4:], plaintext, ad) + return out, nil +} + +func (c aeadCipher) DecryptDanger(out, ad, ciphertext []byte, n uint64, nb []byte) ([]byte, error) { + binary.BigEndian.PutUint64(nb[4:], n) + return c.Open(out, nb[4:], ciphertext, ad) +}