From cccab1eda7251e7b0f779c2dcf7a5202c436612b Mon Sep 17 00:00:00 2001 From: qmuntal Date: Tue, 22 Sep 2026 14:30:13 +0200 Subject: [PATCH 1/2] crypto: move HKDF and PBKDF2 fallback logic to cryptobackend Move HKDF and PBKDF2 backend selection and pure-Go fallback into cryptobackend, following the hash and HMAC packages. Keep FIPS-only checks in the public crypto packages and add custom-hash fallback tests. Updates #2489. --- cryptobackend/hkdf/hkdf.go | 34 ++- cryptobackend/hkdf/hkdf_darwin.go | 4 +- cryptobackend/hkdf/hkdf_msgostd.go | 24 ++ cryptobackend/hkdf/hkdf_nomsgostd.go | 21 ++ cryptobackend/hkdf/hkdf_openssl.go | 4 +- cryptobackend/hkdf/hkdf_test.go | 59 +++++ cryptobackend/hkdf/hkdf_windows.go | 4 +- cryptobackend/hkdf/init.go | 7 - cryptobackend/hkdf/nobackend.go | 4 +- cryptobackend/pbkdf2/init.go | 7 - cryptobackend/pbkdf2/nobackend.go | 2 +- cryptobackend/pbkdf2/pbkdf2.go | 23 ++ cryptobackend/pbkdf2/pbkdf2_darwin.go | 2 +- cryptobackend/pbkdf2/pbkdf2_msgostd.go | 16 ++ cryptobackend/pbkdf2/pbkdf2_nomsgostd.go | 13 + cryptobackend/pbkdf2/pbkdf2_openssl.go | 2 +- cryptobackend/pbkdf2/pbkdf2_test.go | 36 +++ cryptobackend/pbkdf2/pbkdf2_windows.go | 2 +- .../0001-Vendor-external-dependencies.patch | 249 +++++++++++++----- patches/0002-Add-crypto-backends.patch | 69 +++-- 20 files changed, 454 insertions(+), 128 deletions(-) create mode 100644 cryptobackend/hkdf/hkdf_msgostd.go create mode 100644 cryptobackend/hkdf/hkdf_nomsgostd.go create mode 100644 cryptobackend/hkdf/hkdf_test.go delete mode 100644 cryptobackend/hkdf/init.go delete mode 100644 cryptobackend/pbkdf2/init.go create mode 100644 cryptobackend/pbkdf2/pbkdf2.go create mode 100644 cryptobackend/pbkdf2/pbkdf2_msgostd.go create mode 100644 cryptobackend/pbkdf2/pbkdf2_nomsgostd.go create mode 100644 cryptobackend/pbkdf2/pbkdf2_test.go diff --git a/cryptobackend/hkdf/hkdf.go b/cryptobackend/hkdf/hkdf.go index 8d9c6cc9fb..5de49b17e7 100644 --- a/cryptobackend/hkdf/hkdf.go +++ b/cryptobackend/hkdf/hkdf.go @@ -4,12 +4,36 @@ package hkdf -import "hash" +import ( + "hash" + "github.com/microsoft/go/cryptobackend" +) + +// Extract generates a pseudorandom key for use with [Expand] from a secret and salt. +func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + if backend.Enabled && Supports(h()) { + return extract(h, secret, salt) + } + return extractFallback(h, secret, salt) +} + +// Expand derives a key from a pseudorandom key and context info. +func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { + if backend.Enabled && Supports(h()) { + return expand(h, pseudorandomKey, info, keyLen) + } + return expandFallback(h, pseudorandomKey, info, keyLen) +} + +// Key derives a key from a secret, salt, and context info. func Key[H hash.Hash](h func() H, secret, salt []byte, info string, keyLen int) ([]byte, error) { - prk, err := Extract(h, secret, salt) - if err != nil { - return nil, err + if backend.Enabled && Supports(h()) { + prk, err := extract(h, secret, salt) + if err != nil { + return nil, err + } + return expand(h, prk, info, keyLen) } - return Expand(h, prk, info, keyLen) + return keyFallback(h, secret, salt, info, keyLen) } diff --git a/cryptobackend/hkdf/hkdf_darwin.go b/cryptobackend/hkdf/hkdf_darwin.go index c3b7fe3a0b..de875ad84a 100644 --- a/cryptobackend/hkdf/hkdf_darwin.go +++ b/cryptobackend/hkdf/hkdf_darwin.go @@ -18,9 +18,9 @@ func Supports(h hash.Hash) bool { return ok && h.Size() != 16 } -func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { +func extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { return xcrypto.ExtractHKDF(h, secret, salt) } -func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { +func expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { return xcrypto.ExpandHKDF(h, pseudorandomKey, []byte(info), keyLen) } diff --git a/cryptobackend/hkdf/hkdf_msgostd.go b/cryptobackend/hkdf/hkdf_msgostd.go new file mode 100644 index 0000000000..7f8f5e2d1a --- /dev/null +++ b/cryptobackend/hkdf/hkdf_msgostd.go @@ -0,0 +1,24 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build msgostd || cmd_go_bootstrap + +package hkdf + +import ( + fallback "crypto/internal/fips140/hkdf" + "hash" +) + +func extractFallback[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + return fallback.Extract(h, secret, salt), nil +} + +func expandFallback[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { + return fallback.Expand(h, pseudorandomKey, info, keyLen), nil +} + +func keyFallback[H hash.Hash](h func() H, secret, salt []byte, info string, keyLen int) ([]byte, error) { + return fallback.Key(h, secret, salt, info, keyLen), nil +} diff --git a/cryptobackend/hkdf/hkdf_nomsgostd.go b/cryptobackend/hkdf/hkdf_nomsgostd.go new file mode 100644 index 0000000000..24d96abd94 --- /dev/null +++ b/cryptobackend/hkdf/hkdf_nomsgostd.go @@ -0,0 +1,21 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !msgostd && !cmd_go_bootstrap + +package hkdf + +import "hash" + +func extractFallback[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + panic("cryptobackend: not available") +} + +func expandFallback[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { + panic("cryptobackend: not available") +} + +func keyFallback[H hash.Hash](h func() H, secret, salt []byte, info string, keyLen int) ([]byte, error) { + panic("cryptobackend: not available") +} diff --git a/cryptobackend/hkdf/hkdf_openssl.go b/cryptobackend/hkdf/hkdf_openssl.go index f1603e0076..245cf678e6 100644 --- a/cryptobackend/hkdf/hkdf_openssl.go +++ b/cryptobackend/hkdf/hkdf_openssl.go @@ -17,9 +17,9 @@ func Supports(h hash.Hash) bool { return ok && openssl.SupportsHKDF() } -func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { +func extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { return openssl.ExtractHKDF(h, secret, salt) } -func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { +func expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { return openssl.ExpandHKDF(h, pseudorandomKey, []byte(info), keyLen) } diff --git a/cryptobackend/hkdf/hkdf_test.go b/cryptobackend/hkdf/hkdf_test.go new file mode 100644 index 0000000000..1036b6aea9 --- /dev/null +++ b/cryptobackend/hkdf/hkdf_test.go @@ -0,0 +1,59 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hkdf_test + +import ( + "bytes" + "crypto/hkdf" + "crypto/sha256" + "encoding/hex" + "hash" + "testing" +) + +type wrappedHash struct { + hash.Hash +} + +// TestFallback exercises the GOROOT-vendored backend, where the Go fallback is available. +func TestFallback(t *testing.T) { + h := func() wrappedHash { return wrappedHash{sha256.New()} } + // RFC 5869, test case 1, using a hash that native backends do not recognize. + secret := bytes.Repeat([]byte{0x0b}, 22) + salt := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c} + info := string([]byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}) + wantPRK, err := hex.DecodeString("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") + if err != nil { + t.Fatal(err) + } + wantKey, err := hex.DecodeString("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") + if err != nil { + t.Fatal(err) + } + + prk, err := hkdf.Extract(h, secret, salt) + if err != nil || !bytes.Equal(prk, wantPRK) { + t.Fatalf("Extract = %x, %v; want %x, nil", prk, err, wantPRK) + } + expanded, err := hkdf.Expand(h, prk, info, len(wantKey)) + if err != nil || !bytes.Equal(expanded, wantKey) { + t.Fatalf("Expand = %x, %v; want %x, nil", expanded, err, wantKey) + } + key, err := hkdf.Key(h, secret, salt, info, len(wantKey)) + if err != nil || !bytes.Equal(key, wantKey) { + t.Fatalf("Key = %x, %v; want %x, nil", key, err, wantKey) + } + + key, err = hkdf.Key(h, secret, nil, "", 0) + if err != nil || len(key) != 0 { + t.Fatalf("Key with zero length = %x, %v; want an empty key", key, err) + } + if _, err := hkdf.Key(h, secret, salt, info, 255*sha256.Size+1); err == nil { + t.Error("Key accepted an excessive key length") + } + if _, err := hkdf.Expand(h, prk, info, 255*sha256.Size+1); err == nil { + t.Error("Expand accepted an excessive key length") + } +} diff --git a/cryptobackend/hkdf/hkdf_windows.go b/cryptobackend/hkdf/hkdf_windows.go index ee1e9fdbbd..f846525bf8 100644 --- a/cryptobackend/hkdf/hkdf_windows.go +++ b/cryptobackend/hkdf/hkdf_windows.go @@ -17,9 +17,9 @@ func Supports(h hash.Hash) bool { return ok && cng.SupportsHKDF() } -func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { +func extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { return cng.ExtractHKDF(h, secret, salt) } -func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { +func expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { return cng.ExpandHKDF(h, pseudorandomKey, []byte(info), keyLen) } diff --git a/cryptobackend/hkdf/init.go b/cryptobackend/hkdf/init.go deleted file mode 100644 index 78838e1a5d..0000000000 --- a/cryptobackend/hkdf/init.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2026 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package hkdf - -import _ "github.com/microsoft/go/cryptobackend" diff --git a/cryptobackend/hkdf/nobackend.go b/cryptobackend/hkdf/nobackend.go index b3e91ec72b..a2d8179096 100644 --- a/cryptobackend/hkdf/nobackend.go +++ b/cryptobackend/hkdf/nobackend.go @@ -9,9 +9,9 @@ package hkdf import "hash" func Supports(h hash.Hash) bool { panic("cryptobackend: not available") } -func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { +func extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { panic("cryptobackend: not available") } -func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { +func expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { panic("cryptobackend: not available") } diff --git a/cryptobackend/pbkdf2/init.go b/cryptobackend/pbkdf2/init.go deleted file mode 100644 index 89a597b393..0000000000 --- a/cryptobackend/pbkdf2/init.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2026 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pbkdf2 - -import _ "github.com/microsoft/go/cryptobackend" diff --git a/cryptobackend/pbkdf2/nobackend.go b/cryptobackend/pbkdf2/nobackend.go index 0581daddbf..923dd15a43 100644 --- a/cryptobackend/pbkdf2/nobackend.go +++ b/cryptobackend/pbkdf2/nobackend.go @@ -9,6 +9,6 @@ package pbkdf2 import "hash" func Supports(h hash.Hash) bool { panic("cryptobackend: not available") } -func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { +func key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { panic("cryptobackend: not available") } diff --git a/cryptobackend/pbkdf2/pbkdf2.go b/cryptobackend/pbkdf2/pbkdf2.go new file mode 100644 index 0000000000..96199c7d12 --- /dev/null +++ b/cryptobackend/pbkdf2/pbkdf2.go @@ -0,0 +1,23 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pbkdf2 + +import ( + "errors" + "hash" + + "github.com/microsoft/go/cryptobackend" +) + +// Key derives a key from a password, salt, and iteration count. +func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { + if backend.Enabled && Supports(h()) { + if keyLength <= 0 { + return nil, errors.New("pbkdf2: keyLength must be larger than 0") + } + return key(h, password, salt, iter, keyLength) + } + return keyFallback(h, password, salt, iter, keyLength) +} diff --git a/cryptobackend/pbkdf2/pbkdf2_darwin.go b/cryptobackend/pbkdf2/pbkdf2_darwin.go index d5fe415ec0..7fd37a0455 100644 --- a/cryptobackend/pbkdf2/pbkdf2_darwin.go +++ b/cryptobackend/pbkdf2/pbkdf2_darwin.go @@ -18,6 +18,6 @@ func Supports(h hash.Hash) bool { return ok && h.Size() != 16 && (h.BlockSize() == 64 || h.BlockSize() == 128) } -func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { +func key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { return xcrypto.PBKDF2([]byte(password), salt, iter, keyLength, h) } diff --git a/cryptobackend/pbkdf2/pbkdf2_msgostd.go b/cryptobackend/pbkdf2/pbkdf2_msgostd.go new file mode 100644 index 0000000000..f1fd0b8090 --- /dev/null +++ b/cryptobackend/pbkdf2/pbkdf2_msgostd.go @@ -0,0 +1,16 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build msgostd || cmd_go_bootstrap + +package pbkdf2 + +import ( + fallback "crypto/internal/fips140/pbkdf2" + "hash" +) + +func keyFallback[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { + return fallback.Key(h, password, salt, iter, keyLength) +} diff --git a/cryptobackend/pbkdf2/pbkdf2_nomsgostd.go b/cryptobackend/pbkdf2/pbkdf2_nomsgostd.go new file mode 100644 index 0000000000..212a127223 --- /dev/null +++ b/cryptobackend/pbkdf2/pbkdf2_nomsgostd.go @@ -0,0 +1,13 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !msgostd && !cmd_go_bootstrap + +package pbkdf2 + +import "hash" + +func keyFallback[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { + panic("cryptobackend: not available") +} diff --git a/cryptobackend/pbkdf2/pbkdf2_openssl.go b/cryptobackend/pbkdf2/pbkdf2_openssl.go index 32ea8f1894..1062b0f006 100644 --- a/cryptobackend/pbkdf2/pbkdf2_openssl.go +++ b/cryptobackend/pbkdf2/pbkdf2_openssl.go @@ -17,6 +17,6 @@ func Supports(h hash.Hash) bool { return ok && openssl.SupportsPBKDF2() } -func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { +func key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { return openssl.PBKDF2([]byte(password), salt, iter, keyLength, h) } diff --git a/cryptobackend/pbkdf2/pbkdf2_test.go b/cryptobackend/pbkdf2/pbkdf2_test.go new file mode 100644 index 0000000000..0d67b7cc2b --- /dev/null +++ b/cryptobackend/pbkdf2/pbkdf2_test.go @@ -0,0 +1,36 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pbkdf2_test + +import ( + "bytes" + "crypto/pbkdf2" + "crypto/sha256" + "encoding/hex" + "hash" + "testing" +) + +type wrappedHash struct { + hash.Hash +} + +// TestFallback exercises the GOROOT-vendored backend, where the Go fallback is available. +func TestFallback(t *testing.T) { + h := func() wrappedHash { return wrappedHash{sha256.New()} } + want, err := hex.DecodeString("ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43") + if err != nil { + t.Fatal(err) + } + key, err := pbkdf2.Key(h, "password", []byte("salt"), 2, len(want)) + if err != nil || !bytes.Equal(key, want) { + t.Fatalf("Key = %x, %v; want %x, nil", key, err, want) + } + for _, keyLength := range []int{-1, 0} { + if _, err := pbkdf2.Key(h, "password", []byte("salt"), 2, keyLength); err == nil { + t.Errorf("Key accepted keyLength %d", keyLength) + } + } +} diff --git a/cryptobackend/pbkdf2/pbkdf2_windows.go b/cryptobackend/pbkdf2/pbkdf2_windows.go index df4f4c6813..1d5ab1726c 100644 --- a/cryptobackend/pbkdf2/pbkdf2_windows.go +++ b/cryptobackend/pbkdf2/pbkdf2_windows.go @@ -17,6 +17,6 @@ func Supports(h hash.Hash) bool { return ok } -func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { +func key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { return cng.PBKDF2([]byte(password), salt, iter, keyLength, h) } diff --git a/patches/0001-Vendor-external-dependencies.patch b/patches/0001-Vendor-external-dependencies.patch index f70e06774f..a44956df59 100644 --- a/patches/0001-Vendor-external-dependencies.patch +++ b/patches/0001-Vendor-external-dependencies.patch @@ -331,11 +331,12 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../go/cryptobackend/ed25519/init.go | 7 + .../go/cryptobackend/ed25519/nobackend.go | 21 + .../go/cryptobackend/fips140/fips140.go | 15 + - .../microsoft/go/cryptobackend/hkdf/hkdf.go | 15 + + .../microsoft/go/cryptobackend/hkdf/hkdf.go | 39 + .../go/cryptobackend/hkdf/hkdf_darwin.go | 26 + + .../go/cryptobackend/hkdf/hkdf_msgostd.go | 24 + + .../go/cryptobackend/hkdf/hkdf_nomsgostd.go | 21 + .../go/cryptobackend/hkdf/hkdf_openssl.go | 25 + .../go/cryptobackend/hkdf/hkdf_windows.go | 25 + - .../microsoft/go/cryptobackend/hkdf/init.go | 7 + .../go/cryptobackend/hkdf/nobackend.go | 17 + .../microsoft/go/cryptobackend/hmac/hmac.go | 22 + .../go/cryptobackend/hmac/hmac_darwin.go | 17 + @@ -374,9 +375,11 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../go/cryptobackend/mlkem/mlkem_windows.go | 31 + .../go/cryptobackend/mlkem/nobackend.go | 51 + .../microsoft/go/cryptobackend/nobackend.go | 15 + - .../microsoft/go/cryptobackend/pbkdf2/init.go | 7 + .../go/cryptobackend/pbkdf2/nobackend.go | 14 + + .../go/cryptobackend/pbkdf2/pbkdf2.go | 23 + .../go/cryptobackend/pbkdf2/pbkdf2_darwin.go | 23 + + .../go/cryptobackend/pbkdf2/pbkdf2_msgostd.go | 16 + + .../cryptobackend/pbkdf2/pbkdf2_nomsgostd.go | 13 + .../go/cryptobackend/pbkdf2/pbkdf2_openssl.go | 22 + .../go/cryptobackend/pbkdf2/pbkdf2_windows.go | 22 + .../microsoft/go/cryptobackend/rc4/init.go | 7 + @@ -439,7 +442,7 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../go/cryptobackend/tls13/tls13_openssl.go | 18 + .../go/cryptobackend/tls13/tls13_windows.go | 14 + src/vendor/modules.txt | 54 + - 431 files changed, 40850 insertions(+), 7 deletions(-) + 434 files changed, 40957 insertions(+), 7 deletions(-) create mode 100644 src/cmd/internal/telemetry/counter/deps_ignore.go create mode 100644 src/cmd/vendor/github.com/microsoft/go-infra/telemetry/LICENSE create mode 100644 src/cmd/vendor/github.com/microsoft/go-infra/telemetry/README.md @@ -758,9 +761,10 @@ Use a 'go' that was recently built by the current branch to ensure stable result create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/fips140/fips140.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_darwin.go + create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_msgostd.go + create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_nomsgostd.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_openssl.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_windows.go - create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hkdf/init.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hkdf/nobackend.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hmac/hmac.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/hmac/hmac_darwin.go @@ -799,9 +803,11 @@ Use a 'go' that was recently built by the current branch to ensure stable result create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/mlkem/mlkem_windows.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/mlkem/nobackend.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/nobackend.go - create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/init.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/nobackend.go + create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_darwin.go + create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_msgostd.go + create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_nomsgostd.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_openssl.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_windows.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/rc4/init.go @@ -42605,28 +42611,52 @@ index 00000000000000..2b98ef4138312e +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf.go b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf.go new file mode 100644 -index 00000000000000..8d9c6cc9fbd514 +index 00000000000000..5de49b17e75d6b --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf.go -@@ -0,0 +1,15 @@ +@@ -0,0 +1,39 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package hkdf + -+import "hash" ++import ( ++ "hash" + ++ "github.com/microsoft/go/cryptobackend" ++) ++ ++// Extract generates a pseudorandom key for use with [Expand] from a secret and salt. ++func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { ++ if backend.Enabled && Supports(h()) { ++ return extract(h, secret, salt) ++ } ++ return extractFallback(h, secret, salt) ++} ++ ++// Expand derives a key from a pseudorandom key and context info. ++func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { ++ if backend.Enabled && Supports(h()) { ++ return expand(h, pseudorandomKey, info, keyLen) ++ } ++ return expandFallback(h, pseudorandomKey, info, keyLen) ++} ++ ++// Key derives a key from a secret, salt, and context info. +func Key[H hash.Hash](h func() H, secret, salt []byte, info string, keyLen int) ([]byte, error) { -+ prk, err := Extract(h, secret, salt) -+ if err != nil { -+ return nil, err ++ if backend.Enabled && Supports(h()) { ++ prk, err := extract(h, secret, salt) ++ if err != nil { ++ return nil, err ++ } ++ return expand(h, prk, info, keyLen) + } -+ return Expand(h, prk, info, keyLen) ++ return keyFallback(h, secret, salt, info, keyLen) +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_darwin.go b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_darwin.go new file mode 100644 -index 00000000000000..c3b7fe3a0bf083 +index 00000000000000..de875ad84af76c --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_darwin.go @@ -0,0 +1,26 @@ @@ -42650,15 +42680,72 @@ index 00000000000000..c3b7fe3a0bf083 + return ok && h.Size() != 16 +} + -+func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { ++func extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + return xcrypto.ExtractHKDF(h, secret, salt) +} -+func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { ++func expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { + return xcrypto.ExpandHKDF(h, pseudorandomKey, []byte(info), keyLen) +} +diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_msgostd.go b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_msgostd.go +new file mode 100644 +index 00000000000000..7f8f5e2d1a35ac +--- /dev/null ++++ b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_msgostd.go +@@ -0,0 +1,24 @@ ++// Copyright 2026 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build msgostd || cmd_go_bootstrap ++ ++package hkdf ++ ++import ( ++ fallback "crypto/internal/fips140/hkdf" ++ "hash" ++) ++ ++func extractFallback[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { ++ return fallback.Extract(h, secret, salt), nil ++} ++ ++func expandFallback[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { ++ return fallback.Expand(h, pseudorandomKey, info, keyLen), nil ++} ++ ++func keyFallback[H hash.Hash](h func() H, secret, salt []byte, info string, keyLen int) ([]byte, error) { ++ return fallback.Key(h, secret, salt, info, keyLen), nil ++} +diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_nomsgostd.go b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_nomsgostd.go +new file mode 100644 +index 00000000000000..24d96abd94626a +--- /dev/null ++++ b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_nomsgostd.go +@@ -0,0 +1,21 @@ ++// Copyright 2026 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !msgostd && !cmd_go_bootstrap ++ ++package hkdf ++ ++import "hash" ++ ++func extractFallback[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { ++ panic("cryptobackend: not available") ++} ++ ++func expandFallback[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { ++ panic("cryptobackend: not available") ++} ++ ++func keyFallback[H hash.Hash](h func() H, secret, salt []byte, info string, keyLen int) ([]byte, error) { ++ panic("cryptobackend: not available") ++} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_openssl.go b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_openssl.go new file mode 100644 -index 00000000000000..f1603e00760688 +index 00000000000000..245cf678e68f1b --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_openssl.go @@ -0,0 +1,25 @@ @@ -42681,15 +42768,15 @@ index 00000000000000..f1603e00760688 + return ok && openssl.SupportsHKDF() +} + -+func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { ++func extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + return openssl.ExtractHKDF(h, secret, salt) +} -+func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { ++func expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { + return openssl.ExpandHKDF(h, pseudorandomKey, []byte(info), keyLen) +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_windows.go b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_windows.go new file mode 100644 -index 00000000000000..ee1e9fdbbdbbbf +index 00000000000000..f846525bf8c905 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/hkdf_windows.go @@ -0,0 +1,25 @@ @@ -42712,28 +42799,15 @@ index 00000000000000..ee1e9fdbbdbbbf + return ok && cng.SupportsHKDF() +} + -+func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { ++func extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + return cng.ExtractHKDF(h, secret, salt) +} -+func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { ++func expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { + return cng.ExpandHKDF(h, pseudorandomKey, []byte(info), keyLen) +} -diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/init.go b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/init.go -new file mode 100644 -index 00000000000000..78838e1a5df924 ---- /dev/null -+++ b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/init.go -@@ -0,0 +1,7 @@ -+// Copyright 2026 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package hkdf -+ -+import _ "github.com/microsoft/go/cryptobackend" diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/nobackend.go b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/nobackend.go new file mode 100644 -index 00000000000000..b3e91ec72b8810 +index 00000000000000..a2d8179096c4d6 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/hkdf/nobackend.go @@ -0,0 +1,17 @@ @@ -42748,10 +42822,10 @@ index 00000000000000..b3e91ec72b8810 +import "hash" + +func Supports(h hash.Hash) bool { panic("cryptobackend: not available") } -+func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { ++func extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + panic("cryptobackend: not available") +} -+func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { ++func expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen int) ([]byte, error) { + panic("cryptobackend: not available") +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/hmac/hmac.go b/src/vendor/github.com/microsoft/go/cryptobackend/hmac/hmac.go @@ -43814,22 +43888,9 @@ index 00000000000000..5c7c1fc6d53878 +} + +const Enabled = false -diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/init.go b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/init.go -new file mode 100644 -index 00000000000000..89a597b39369ce ---- /dev/null -+++ b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/init.go -@@ -0,0 +1,7 @@ -+// Copyright 2026 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package pbkdf2 -+ -+import _ "github.com/microsoft/go/cryptobackend" diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/nobackend.go b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/nobackend.go new file mode 100644 -index 00000000000000..0581daddbf8765 +index 00000000000000..923dd15a4354df --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/nobackend.go @@ -0,0 +1,14 @@ @@ -43844,12 +43905,41 @@ index 00000000000000..0581daddbf8765 +import "hash" + +func Supports(h hash.Hash) bool { panic("cryptobackend: not available") } -+func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { ++func key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { + panic("cryptobackend: not available") +} +diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2.go b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2.go +new file mode 100644 +index 00000000000000..96199c7d128874 +--- /dev/null ++++ b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2.go +@@ -0,0 +1,23 @@ ++// Copyright 2026 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package pbkdf2 ++ ++import ( ++ "errors" ++ "hash" ++ ++ "github.com/microsoft/go/cryptobackend" ++) ++ ++// Key derives a key from a password, salt, and iteration count. ++func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { ++ if backend.Enabled && Supports(h()) { ++ if keyLength <= 0 { ++ return nil, errors.New("pbkdf2: keyLength must be larger than 0") ++ } ++ return key(h, password, salt, iter, keyLength) ++ } ++ return keyFallback(h, password, salt, iter, keyLength) ++} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_darwin.go b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_darwin.go new file mode 100644 -index 00000000000000..d5fe415ec03c8e +index 00000000000000..7fd37a045535b5 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_darwin.go @@ -0,0 +1,23 @@ @@ -43873,12 +43963,53 @@ index 00000000000000..d5fe415ec03c8e + return ok && h.Size() != 16 && (h.BlockSize() == 64 || h.BlockSize() == 128) +} + -+func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { ++func key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { + return xcrypto.PBKDF2([]byte(password), salt, iter, keyLength, h) +} +diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_msgostd.go b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_msgostd.go +new file mode 100644 +index 00000000000000..f1fd0b80900c71 +--- /dev/null ++++ b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_msgostd.go +@@ -0,0 +1,16 @@ ++// Copyright 2026 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build msgostd || cmd_go_bootstrap ++ ++package pbkdf2 ++ ++import ( ++ fallback "crypto/internal/fips140/pbkdf2" ++ "hash" ++) ++ ++func keyFallback[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { ++ return fallback.Key(h, password, salt, iter, keyLength) ++} +diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_nomsgostd.go b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_nomsgostd.go +new file mode 100644 +index 00000000000000..212a127223908c +--- /dev/null ++++ b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_nomsgostd.go +@@ -0,0 +1,13 @@ ++// Copyright 2026 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++//go:build !msgostd && !cmd_go_bootstrap ++ ++package pbkdf2 ++ ++import "hash" ++ ++func keyFallback[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { ++ panic("cryptobackend: not available") ++} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_openssl.go b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_openssl.go new file mode 100644 -index 00000000000000..32ea8f189417ec +index 00000000000000..1062b0f006a881 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_openssl.go @@ -0,0 +1,22 @@ @@ -43901,12 +44032,12 @@ index 00000000000000..32ea8f189417ec + return ok && openssl.SupportsPBKDF2() +} + -+func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { ++func key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { + return openssl.PBKDF2([]byte(password), salt, iter, keyLength, h) +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_windows.go b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_windows.go new file mode 100644 -index 00000000000000..df4f4c68138783 +index 00000000000000..1d5ab1726c2e07 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/pbkdf2/pbkdf2_windows.go @@ -0,0 +1,22 @@ @@ -43929,7 +44060,7 @@ index 00000000000000..df4f4c68138783 + return ok +} + -+func Key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { ++func key[H hash.Hash](h func() H, password string, salt []byte, iter, keyLength int) ([]byte, error) { + return cng.PBKDF2([]byte(password), salt, iter, keyLength, h) +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/rc4/init.go b/src/vendor/github.com/microsoft/go/cryptobackend/rc4/init.go diff --git a/patches/0002-Add-crypto-backends.patch b/patches/0002-Add-crypto-backends.patch index bc07c87956..2b9b828caa 100644 --- a/patches/0002-Add-crypto-backends.patch +++ b/patches/0002-Add-crypto-backends.patch @@ -65,7 +65,7 @@ Subject: [PATCH] Add crypto backends src/crypto/ed25519/notboring.go | 16 + src/crypto/fips140/enforcement_test.go | 4 + src/crypto/fips140/fips140.go | 3 +- - src/crypto/hkdf/hkdf.go | 12 + + src/crypto/hkdf/hkdf.go | 9 +- src/crypto/hkdf/hkdf_test.go | 2 +- src/crypto/hmac/hmac.go | 3 +- src/crypto/hmac/hmac_test.go | 2 +- @@ -87,7 +87,7 @@ Subject: [PATCH] Add crypto backends src/crypto/mldsa/mldsa_test.go | 67 +++- src/crypto/mlkem/mlkem.go | 121 ++++++- src/crypto/mlkem/mlkem_test.go | 8 + - src/crypto/pbkdf2/pbkdf2.go | 9 + + src/crypto/pbkdf2/pbkdf2.go | 3 +- src/crypto/pbkdf2/pbkdf2_test.go | 6 +- src/crypto/purego_test.go | 2 +- src/crypto/rand/rand.go | 6 +- @@ -143,7 +143,7 @@ Subject: [PATCH] Add crypto backends src/os/exec/exec_test.go | 9 + src/runtime/runtime_boring.go | 5 + src/syscall/syscall_windows.go | 3 + - 139 files changed, 2458 insertions(+), 388 deletions(-) + 139 files changed, 2444 insertions(+), 393 deletions(-) create mode 100644 src/cmd/go/systemcrypto_test.go create mode 100644 src/crypto/dsa/boring.go create mode 100644 src/crypto/dsa/notboring.go @@ -2731,49 +2731,50 @@ index d3f63d3bf18fcb..bc6d8b62ae2103 100644 // Version returns the FIPS 140-3 Go Cryptographic Module version (such as diff --git a/src/crypto/hkdf/hkdf.go b/src/crypto/hkdf/hkdf.go -index 88439922a5032e..973cc813207d56 100644 +index 88439922a5032e..6de1ec18be98ad 100644 --- a/src/crypto/hkdf/hkdf.go +++ b/src/crypto/hkdf/hkdf.go -@@ -16,6 +16,9 @@ import ( +@@ -11,11 +11,12 @@ + package hkdf + + import ( +- "crypto/internal/fips140/hkdf" + "crypto/internal/fips140hash" "crypto/internal/fips140only" "errors" "hash" + -+ boring "github.com/microsoft/go/cryptobackend" -+ bhkdf "github.com/microsoft/go/cryptobackend/hkdf" ++ "github.com/microsoft/go/cryptobackend/hkdf" ) // Extract generates a pseudorandom key for use with [Expand] from an input -@@ -29,6 +32,9 @@ func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { +@@ -29,7 +30,7 @@ func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { if err := checkFIPS140Only(fh, secret); err != nil { return nil, err } -+ if boring.Enabled && bhkdf.Supports(fh()) { -+ return bhkdf.Extract(fh, secret, salt) -+ } - return hkdf.Extract(fh, secret, salt), nil +- return hkdf.Extract(fh, secret, salt), nil ++ return hkdf.Extract(fh, secret, salt) } -@@ -50,6 +56,9 @@ func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen + // Expand derives a key from the given hash, key, and optional context info, +@@ -50,7 +51,7 @@ func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen return nil, errors.New("hkdf: requested key length too large") } -+ if boring.Enabled && bhkdf.Supports(fh()) { -+ return bhkdf.Expand(fh, pseudorandomKey, info, keyLength) -+ } - return hkdf.Expand(fh, pseudorandomKey, info, keyLength), nil +- return hkdf.Expand(fh, pseudorandomKey, info, keyLength), nil ++ return hkdf.Expand(fh, pseudorandomKey, info, keyLength) } -@@ -67,6 +76,9 @@ func Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLen + // Key derives a key from the given hash, secret, salt and context info, +@@ -67,7 +68,7 @@ func Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLen return nil, errors.New("hkdf: requested key length too large") } -+ if boring.Enabled && bhkdf.Supports(fh()) { -+ return bhkdf.Key(fh, secret, salt, info, keyLength) -+ } - return hkdf.Key(fh, secret, salt, info, keyLength), nil +- return hkdf.Key(fh, secret, salt, info, keyLength), nil ++ return hkdf.Key(fh, secret, salt, info, keyLength) } + func checkFIPS140Only[Hash hash.Hash](h func() Hash, key []byte) error { diff --git a/src/crypto/hkdf/hkdf_test.go b/src/crypto/hkdf/hkdf_test.go index 57d90f88e93e75..da5a26c770800b 100644 --- a/src/crypto/hkdf/hkdf_test.go @@ -3991,31 +3992,23 @@ index e1c2ef49f15ce0..4635cc347880ec 100644 rand.Read(seed) dk, err := NewDecapsulationKey768(seed) diff --git a/src/crypto/pbkdf2/pbkdf2.go b/src/crypto/pbkdf2/pbkdf2.go -index 0bc14be888d9d6..bde65657424e09 100644 +index 0bc14be888d9d6..fc363e7053da9b 100644 --- a/src/crypto/pbkdf2/pbkdf2.go +++ b/src/crypto/pbkdf2/pbkdf2.go -@@ -16,6 +16,9 @@ import ( +@@ -11,11 +11,12 @@ + package pbkdf2 + + import ( +- "crypto/internal/fips140/pbkdf2" + "crypto/internal/fips140hash" "crypto/internal/fips140only" "errors" "hash" + -+ boring "github.com/microsoft/go/cryptobackend" -+ bpbkdf2 "github.com/microsoft/go/cryptobackend/pbkdf2" ++ "github.com/microsoft/go/cryptobackend/pbkdf2" ) // Key derives a key from the password, salt and iteration count, returning a -@@ -50,5 +53,11 @@ func Key[Hash hash.Hash](h func() Hash, password string, salt []byte, iter, keyL - return nil, errors.New("crypto/pbkdf2: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") - } - } -+ if boring.Enabled && bpbkdf2.Supports(fh()) { -+ if keyLength <= 0 { -+ return nil, errors.New("pkbdf2: keyLength must be larger than 0") -+ } -+ return bpbkdf2.Key(fh, password, salt, iter, keyLength) -+ } - return pbkdf2.Key(fh, password, salt, iter, keyLength) - } diff --git a/src/crypto/pbkdf2/pbkdf2_test.go b/src/crypto/pbkdf2/pbkdf2_test.go index eb0ed14e243c6b..c0cdca547261c0 100644 --- a/src/crypto/pbkdf2/pbkdf2_test.go From beae3725d34821df143ec1113f691ef2a2530bf5 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Tue, 22 Sep 2026 14:39:18 +0200 Subject: [PATCH 2/2] crypto: remove backend-local KDF tests Rely on the existing standard-library HKDF and PBKDF2 tests. --- cryptobackend/hkdf/hkdf_test.go | 59 ----------------------------- cryptobackend/pbkdf2/pbkdf2_test.go | 36 ------------------ 2 files changed, 95 deletions(-) delete mode 100644 cryptobackend/hkdf/hkdf_test.go delete mode 100644 cryptobackend/pbkdf2/pbkdf2_test.go diff --git a/cryptobackend/hkdf/hkdf_test.go b/cryptobackend/hkdf/hkdf_test.go deleted file mode 100644 index 1036b6aea9..0000000000 --- a/cryptobackend/hkdf/hkdf_test.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2026 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package hkdf_test - -import ( - "bytes" - "crypto/hkdf" - "crypto/sha256" - "encoding/hex" - "hash" - "testing" -) - -type wrappedHash struct { - hash.Hash -} - -// TestFallback exercises the GOROOT-vendored backend, where the Go fallback is available. -func TestFallback(t *testing.T) { - h := func() wrappedHash { return wrappedHash{sha256.New()} } - // RFC 5869, test case 1, using a hash that native backends do not recognize. - secret := bytes.Repeat([]byte{0x0b}, 22) - salt := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c} - info := string([]byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}) - wantPRK, err := hex.DecodeString("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") - if err != nil { - t.Fatal(err) - } - wantKey, err := hex.DecodeString("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") - if err != nil { - t.Fatal(err) - } - - prk, err := hkdf.Extract(h, secret, salt) - if err != nil || !bytes.Equal(prk, wantPRK) { - t.Fatalf("Extract = %x, %v; want %x, nil", prk, err, wantPRK) - } - expanded, err := hkdf.Expand(h, prk, info, len(wantKey)) - if err != nil || !bytes.Equal(expanded, wantKey) { - t.Fatalf("Expand = %x, %v; want %x, nil", expanded, err, wantKey) - } - key, err := hkdf.Key(h, secret, salt, info, len(wantKey)) - if err != nil || !bytes.Equal(key, wantKey) { - t.Fatalf("Key = %x, %v; want %x, nil", key, err, wantKey) - } - - key, err = hkdf.Key(h, secret, nil, "", 0) - if err != nil || len(key) != 0 { - t.Fatalf("Key with zero length = %x, %v; want an empty key", key, err) - } - if _, err := hkdf.Key(h, secret, salt, info, 255*sha256.Size+1); err == nil { - t.Error("Key accepted an excessive key length") - } - if _, err := hkdf.Expand(h, prk, info, 255*sha256.Size+1); err == nil { - t.Error("Expand accepted an excessive key length") - } -} diff --git a/cryptobackend/pbkdf2/pbkdf2_test.go b/cryptobackend/pbkdf2/pbkdf2_test.go deleted file mode 100644 index 0d67b7cc2b..0000000000 --- a/cryptobackend/pbkdf2/pbkdf2_test.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2026 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pbkdf2_test - -import ( - "bytes" - "crypto/pbkdf2" - "crypto/sha256" - "encoding/hex" - "hash" - "testing" -) - -type wrappedHash struct { - hash.Hash -} - -// TestFallback exercises the GOROOT-vendored backend, where the Go fallback is available. -func TestFallback(t *testing.T) { - h := func() wrappedHash { return wrappedHash{sha256.New()} } - want, err := hex.DecodeString("ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43") - if err != nil { - t.Fatal(err) - } - key, err := pbkdf2.Key(h, "password", []byte("salt"), 2, len(want)) - if err != nil || !bytes.Equal(key, want) { - t.Fatalf("Key = %x, %v; want %x, nil", key, err, want) - } - for _, keyLength := range []int{-1, 0} { - if _, err := pbkdf2.Key(h, "password", []byte("salt"), 2, keyLength); err == nil { - t.Errorf("Key accepted keyLength %d", keyLength) - } - } -}