From c88652d3aed5a5796d73ffd9d37a1208d1e27130 Mon Sep 17 00:00:00 2001 From: Kaan Yalti Date: Fri, 14 Mar 2025 10:29:01 -0400 Subject: [PATCH] Enhancement/5039 remove x crypto fips (#7072) * enhancement(5039): replace x/crypto/pbkdf2 with stdlib pbkdf2 * enhancement(5039): added nolint comment (cherry picked from commit 33df025dea6cb6ef67bd6d5cdd03914347fe286e) --- .../pkg/agent/vault/vault_file_notwindows.go | 15 +++++++++++---- internal/pkg/crypto/hash.go | 10 ++++++++-- internal/pkg/crypto/io.go | 19 ++++++++++++------- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/internal/pkg/agent/vault/vault_file_notwindows.go b/internal/pkg/agent/vault/vault_file_notwindows.go index 0bdff9dcf41..343820498d1 100644 --- a/internal/pkg/agent/vault/vault_file_notwindows.go +++ b/internal/pkg/agent/vault/vault_file_notwindows.go @@ -7,6 +7,7 @@ package vault import ( + "crypto/pbkdf2" "crypto/rand" "crypto/sha256" "errors" @@ -15,14 +16,14 @@ import ( "path/filepath" "syscall" - "golang.org/x/crypto/pbkdf2" - "github.com/elastic/elastic-agent/internal/pkg/agent/vault/aesgcm" "github.com/elastic/elastic-agent/pkg/utils" ) const ( - saltSize = 8 + saltSize = 8 + keyLen int = 32 + iterCount int = 12022 ) func (v *FileVault) encrypt(data []byte) ([]byte, error) { @@ -56,7 +57,13 @@ func deriveKey(pw []byte, salt []byte) ([]byte, []byte, error) { return nil, nil, err } } - return pbkdf2.Key(pw, salt, 12022, 32, sha256.New), salt, nil + + key, err := pbkdf2.Key(sha256.New, string(pw), salt, iterCount, keyLen) + if err != nil { + return nil, nil, err + } + + return key, salt, nil } func tightenPermissions(path string, ownership utils.FileOwner) error { diff --git a/internal/pkg/crypto/hash.go b/internal/pkg/crypto/hash.go index b88f0d47e34..5f8826e761c 100644 --- a/internal/pkg/crypto/hash.go +++ b/internal/pkg/crypto/hash.go @@ -33,7 +33,10 @@ func GeneratePBKDF2FromPassword(password []byte) ([]byte, error) { // Write hash // SALT|KEY - key := stretchPassword(password, salt, hashIterations, hashKeyLength) + key, err := stretchPassword(password, salt, hashIterations, hashKeyLength) + if err != nil { + return nil, fmt.Errorf("failed to stretch password: %w", err) + } hash := new(bytes.Buffer) hash.Write(salt) hash.Write(key) @@ -55,7 +58,10 @@ func ComparePBKDF2HashAndPassword(hash []byte, password []byte) error { // SALT|KEY salt := hash[:hashSaltLength] keyFromHash := hash[hashSaltLength:hashTotalLength] - keyFromPassword := stretchPassword(password, salt, hashIterations, hashKeyLength) + keyFromPassword, err := stretchPassword(password, salt, hashIterations, hashKeyLength) + if err != nil { + return fmt.Errorf("failed to stretch password: %w", err) + } if !hmac.Equal(keyFromHash, keyFromPassword) { return ErrMismatchedHashAndPassword } diff --git a/internal/pkg/crypto/io.go b/internal/pkg/crypto/io.go index dc49bf34845..0ea633afe57 100644 --- a/internal/pkg/crypto/io.go +++ b/internal/pkg/crypto/io.go @@ -8,14 +8,13 @@ import ( "bytes" "crypto/aes" "crypto/cipher" + "crypto/pbkdf2" "crypto/rand" "crypto/sha512" "encoding/binary" "errors" "fmt" "io" - - "golang.org/x/crypto/pbkdf2" ) // Option is the default options used to generate the encrypt and decrypt writer. @@ -127,12 +126,15 @@ func (w *Writer) Write(b []byte) (int, error) { w.wroteHeader = true // Stretch the user provided key. - passwordBytes := stretchPassword( + passwordBytes, err := stretchPassword( w.password, w.salt, w.option.IterationsCount, w.option.KeyLength, ) + if err != nil { + return 0, fmt.Errorf("failed to stretch password: %w", err) + } // Select AES-256: because len(passwordBytes) == 32 bytes. block, err := aes.NewCipher(passwordBytes) @@ -194,7 +196,7 @@ func (w *Writer) writeBlock(b []byte) error { encodedBytes := w.gcm.Seal(nil, iv, b, nil) l := make([]byte, 4) - binary.LittleEndian.PutUint32(l, uint32(len(encodedBytes))) + binary.LittleEndian.PutUint32(l, uint32(len(encodedBytes))) //nolint:gosec // ignoring unsafe type conversion //nolint:errcheck // Ignore the error at this point. w.writer.Write(l) @@ -265,12 +267,15 @@ func (r *Reader) Read(b []byte) (int, error) { salt := buf[vLen : vLen+r.option.SaltLength] // Stretch the user provided key. - passwordBytes := stretchPassword( + passwordBytes, err := stretchPassword( r.password, salt, r.option.IterationsCount, r.option.KeyLength, ) + if err != nil { + return 0, fmt.Errorf("failed to stretch password: %w", err) + } block, err := aes.NewCipher(passwordBytes) if err != nil { @@ -372,6 +377,6 @@ func randomBytes(length int) ([]byte, error) { return r, nil } -func stretchPassword(password, salt []byte, c, kl int) []byte { - return pbkdf2.Key(password, salt, c, kl, sha512.New) +func stretchPassword(password, salt []byte, c, kl int) ([]byte, error) { + return pbkdf2.Key(sha512.New, string(password), salt, c, kl) }