From e5991b0e4dccb1c843ce9cded39ca9718761d4aa Mon Sep 17 00:00:00 2001 From: Ganbold Nasanbat Date: Wed, 3 Jun 2026 13:02:36 +0800 Subject: [PATCH] pkcs12: cap PBKDF iteration count to prevent CPU exhaustion --- pkcs12/crypto.go | 4 +++- pkcs12/mac.go | 5 ++++- pkcs12/pkcs12_test.go | 9 +++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pkcs12/crypto.go b/pkcs12/crypto.go index 212538cb5a..2923a12836 100644 --- a/pkcs12/crypto.go +++ b/pkcs12/crypto.go @@ -80,9 +80,11 @@ func pbDecrypterFor(algorithm pkix.AlgorithmIdentifier, password []byte) (cipher return nil, 0, err } + if params.Iterations <= 0 || params.Iterations > 10_000_000 { + return nil, 0, errors.New("pkcs12: iteration count out of safe range") + } key := cipherType.deriveKey(params.Salt, password, params.Iterations) iv := cipherType.deriveIV(params.Salt, password, params.Iterations) - block, err := cipherType.create(key) if err != nil { return nil, 0, err diff --git a/pkcs12/mac.go b/pkcs12/mac.go index 5f38aa7de8..7c3938f594 100644 --- a/pkcs12/mac.go +++ b/pkcs12/mac.go @@ -9,6 +9,7 @@ import ( "crypto/sha1" "crypto/x509/pkix" "encoding/asn1" + "errors" ) type macData struct { @@ -31,7 +32,9 @@ func verifyMac(macData *macData, message, password []byte) error { if !macData.Mac.Algorithm.Algorithm.Equal(oidSHA1) { return NotImplementedError("unknown digest algorithm: " + macData.Mac.Algorithm.Algorithm.String()) } - + if macData.Iterations <= 0 || macData.Iterations > 10_000_000 { + return errors.New("pkcs12: iteration count out of safe range") + } key := pbkdf(sha1Sum, 20, 64, macData.MacSalt, password, macData.Iterations, 3, 20) mac := hmac.New(sha1.New, key) diff --git a/pkcs12/pkcs12_test.go b/pkcs12/pkcs12_test.go index 68476a822f..87cc4a7ef8 100644 --- a/pkcs12/pkcs12_test.go +++ b/pkcs12/pkcs12_test.go @@ -139,3 +139,12 @@ p8SsTugkit8wOwYJKoZIhvcNAQkUMS4eLABGAHIAaQBlAG4AZABsAHkAIABuAGEAbQBlACAAZgBv AHIAIABjAGUAcgB0MDEwITAJBgUrDgMCGgUABBRFsNz3Zd1O1GI8GTuFwCWuDOjEEwQIuBEfIcAy HQ8CAggA`, } + +func TestDecodeHugeIterationCount(t *testing.T) { + // Minimal PFX with Iterations = 2^31 + // Should return error, not hang + _, _, err := Decode(hugeIterPFX, "password") + if err == nil { + t.Fatal("expected error for huge iteration count, got nil") + } +}