From c0f6410d80b81da4cfa732126268b077970ff0f2 Mon Sep 17 00:00:00 2001 From: Malcolm Lockyer Date: Fri, 5 Sep 2025 13:17:23 +1200 Subject: [PATCH] fix(fips): encrypt the chisel private key file for fips [be-12132] (#1149) --- api/crypto/aes.go | 15 +++++++++ api/crypto/aes_test.go | 59 ++++++++++++++++++++++++++++++++++++ api/filesystem/filesystem.go | 2 +- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/api/crypto/aes.go b/api/crypto/aes.go index 6809f1dc4..5ad2f6bea 100644 --- a/api/crypto/aes.go +++ b/api/crypto/aes.go @@ -388,3 +388,18 @@ func aesDecryptOFB(input io.Reader, passphrase []byte) (io.Reader, error) { return reader, nil } + +// HasEncryptedHeader checks if the data has an encrypted header, note that fips +// mode changes this behavior and so will only recognize data encrypted by the +// same mode (fips enabled or disabled) +func HasEncryptedHeader(data []byte) bool { + return hasEncryptedHeader(data, fips.FIPSMode()) +} + +func hasEncryptedHeader(data []byte, fipsMode bool) bool { + if fipsMode { + return bytes.HasPrefix(data, []byte(aesGcmFIPSHeader)) + } + + return bytes.HasPrefix(data, []byte(aesGcmHeader)) +} diff --git a/api/crypto/aes_test.go b/api/crypto/aes_test.go index f5772d2bb..2280e522b 100644 --- a/api/crypto/aes_test.go +++ b/api/crypto/aes_test.go @@ -350,3 +350,62 @@ func legacyAesEncrypt(input io.Reader, output io.Writer, passphrase []byte) erro return nil } + +func Test_hasEncryptedHeader(t *testing.T) { + tests := []struct { + name string + data []byte + fipsMode bool + want bool + }{ + { + name: "non-FIPS mode with valid header", + data: []byte("AES256-GCM" + "some encrypted data"), + fipsMode: false, + want: true, + }, + { + name: "non-FIPS mode with FIPS header", + data: []byte("FIPS-AES256-GCM" + "some encrypted data"), + fipsMode: false, + want: false, + }, + { + name: "FIPS mode with valid header", + data: []byte("FIPS-AES256-GCM" + "some encrypted data"), + fipsMode: true, + want: true, + }, + { + name: "FIPS mode with non-FIPS header", + data: []byte("AES256-GCM" + "some encrypted data"), + fipsMode: true, + want: false, + }, + { + name: "invalid header", + data: []byte("INVALID-HEADER" + "some data"), + fipsMode: false, + want: false, + }, + { + name: "empty data", + data: []byte{}, + fipsMode: false, + want: false, + }, + { + name: "nil data", + data: nil, + fipsMode: false, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := hasEncryptedHeader(tt.data, tt.fipsMode) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/api/filesystem/filesystem.go b/api/filesystem/filesystem.go index 43e38b4e7..284b6df33 100644 --- a/api/filesystem/filesystem.go +++ b/api/filesystem/filesystem.go @@ -848,7 +848,7 @@ func defaultMTLSCertPathUnderFileStore() (string, string, string) { return caCertPath, certPath, keyPath } -// GetDefaultChiselPrivateKeyPath returns the chisle private key path +// GetDefaultChiselPrivateKeyPath returns the chisel private key path func (service *Service) GetDefaultChiselPrivateKeyPath() string { privateKeyPath := defaultChiselPrivateKeyPathUnderFileStore() return service.wrapFileStore(privateKeyPath)