From 83662683f66c7b8ac0c998eccd26a835f9c1e7ea Mon Sep 17 00:00:00 2001 From: qmuntal Date: Tue, 22 Sep 2026 16:59:58 +0200 Subject: [PATCH] crypto: move TLS 1.2 PRF fallback logic to cryptobackend Restore prf10 to upstream behavior and move TLS 1.2 PRF backend selection and Go fallback into cryptobackend/tls12. Preserve native errors and leave master-secret derivation and handshake error handling unchanged. Updates #2489. --- cryptobackend/tls12/init.go | 7 -- cryptobackend/tls12/nobackend.go | 2 +- cryptobackend/tls12/tls12.go | 23 ++++ cryptobackend/tls12/tls12_darwin.go | 2 +- cryptobackend/tls12/tls12_msgostd.go | 16 +++ cryptobackend/tls12/tls12_nomsgostd.go | 13 +++ cryptobackend/tls12/tls12_openssl.go | 2 +- cryptobackend/tls12/tls12_windows.go | 2 +- .../0001-Vendor-external-dependencies.patch | 109 ++++++++++++++---- patches/0002-Add-crypto-backends.patch | 35 ++---- 10 files changed, 153 insertions(+), 58 deletions(-) delete mode 100644 cryptobackend/tls12/init.go create mode 100644 cryptobackend/tls12/tls12.go create mode 100644 cryptobackend/tls12/tls12_msgostd.go create mode 100644 cryptobackend/tls12/tls12_nomsgostd.go diff --git a/cryptobackend/tls12/init.go b/cryptobackend/tls12/init.go deleted file mode 100644 index 11f4c37aac..0000000000 --- a/cryptobackend/tls12/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 tls12 - -import _ "github.com/microsoft/go/cryptobackend" diff --git a/cryptobackend/tls12/nobackend.go b/cryptobackend/tls12/nobackend.go index cb967817da..3a7a8e3924 100644 --- a/cryptobackend/tls12/nobackend.go +++ b/cryptobackend/tls12/nobackend.go @@ -9,6 +9,6 @@ package tls12 import "hash" func SupportsPRF() bool { panic("cryptobackend: not available") } -func PRF(result, secret []byte, label string, seed []byte, h func() hash.Hash) error { +func prf[H hash.Hash](result, secret []byte, label string, seed []byte, h func() H) error { panic("cryptobackend: not available") } diff --git a/cryptobackend/tls12/tls12.go b/cryptobackend/tls12/tls12.go new file mode 100644 index 0000000000..535d07382c --- /dev/null +++ b/cryptobackend/tls12/tls12.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 tls12 + +import ( + "hash" + + "github.com/microsoft/go/cryptobackend" +) + +// PRF implements the TLS 1.2 pseudo-random function as defined in RFC 5246, Section 5. +func PRF[H hash.Hash](h func() H, secret []byte, label string, seed []byte, keyLen int) ([]byte, error) { + if backend.Enabled && SupportsPRF() { + result := make([]byte, keyLen) + if err := prf(result, secret, label, seed, h); err != nil { + return nil, err + } + return result, nil + } + return prfFallback(h, secret, label, seed, keyLen) +} diff --git a/cryptobackend/tls12/tls12_darwin.go b/cryptobackend/tls12/tls12_darwin.go index 78014828c6..bc1b0c5222 100644 --- a/cryptobackend/tls12/tls12_darwin.go +++ b/cryptobackend/tls12/tls12_darwin.go @@ -9,6 +9,6 @@ package tls12 import "hash" func SupportsPRF() bool { return false } -func PRF(result, secret []byte, label string, seed []byte, h func() hash.Hash) error { +func prf[H hash.Hash](result, secret []byte, label string, seed []byte, h func() H) error { panic("cryptobackend: not available") } diff --git a/cryptobackend/tls12/tls12_msgostd.go b/cryptobackend/tls12/tls12_msgostd.go new file mode 100644 index 0000000000..69b74a5d11 --- /dev/null +++ b/cryptobackend/tls12/tls12_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 tls12 + +import ( + fallback "crypto/internal/fips140/tls12" + "hash" +) + +func prfFallback[H hash.Hash](h func() H, secret []byte, label string, seed []byte, keyLen int) ([]byte, error) { + return fallback.PRF(h, secret, label, seed, keyLen), nil +} diff --git a/cryptobackend/tls12/tls12_nomsgostd.go b/cryptobackend/tls12/tls12_nomsgostd.go new file mode 100644 index 0000000000..6077eb43de --- /dev/null +++ b/cryptobackend/tls12/tls12_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 tls12 + +import "hash" + +func prfFallback[H hash.Hash](h func() H, secret []byte, label string, seed []byte, keyLen int) ([]byte, error) { + panic("cryptobackend: not available") +} diff --git a/cryptobackend/tls12/tls12_openssl.go b/cryptobackend/tls12/tls12_openssl.go index a1c4e380e3..d7cd268358 100644 --- a/cryptobackend/tls12/tls12_openssl.go +++ b/cryptobackend/tls12/tls12_openssl.go @@ -13,6 +13,6 @@ import ( ) func SupportsPRF() bool { return openssl.SupportsTLS1PRF() } -func PRF(result, secret []byte, label string, seed []byte, h func() hash.Hash) error { +func prf[H hash.Hash](result, secret []byte, label string, seed []byte, h func() H) error { return openssl.TLS1PRF(result, secret, []byte(label), seed, h) } diff --git a/cryptobackend/tls12/tls12_windows.go b/cryptobackend/tls12/tls12_windows.go index 9e50ac1bb7..f970f0b478 100644 --- a/cryptobackend/tls12/tls12_windows.go +++ b/cryptobackend/tls12/tls12_windows.go @@ -13,6 +13,6 @@ import ( ) func SupportsPRF() bool { return true } -func PRF(result, secret []byte, label string, seed []byte, h func() hash.Hash) error { +func prf[H hash.Hash](result, secret []byte, label string, seed []byte, h func() H) error { return cng.TLS1PRF(result, secret, []byte(label), seed, h) } diff --git a/patches/0001-Vendor-external-dependencies.patch b/patches/0001-Vendor-external-dependencies.patch index a44956df59..2cb20418b3 100644 --- a/patches/0001-Vendor-external-dependencies.patch +++ b/patches/0001-Vendor-external-dependencies.patch @@ -428,9 +428,11 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../cryptobackend/sha512/zsha512_msgostd.go | 35 + .../cryptobackend/sha512/zsha512_nomsgostd.go | 41 + .../microsoft/go/cryptobackend/stub.s | 10 + - .../microsoft/go/cryptobackend/tls12/init.go | 7 + .../go/cryptobackend/tls12/nobackend.go | 14 + + .../microsoft/go/cryptobackend/tls12/tls12.go | 23 + .../go/cryptobackend/tls12/tls12_darwin.go | 14 + + .../go/cryptobackend/tls12/tls12_msgostd.go | 16 + + .../go/cryptobackend/tls12/tls12_nomsgostd.go | 13 + .../go/cryptobackend/tls12/tls12_openssl.go | 18 + .../go/cryptobackend/tls12/tls12_windows.go | 18 + .../go/cryptobackend/tls13/hash_msgostd.go | 16 + @@ -442,7 +444,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 + - 434 files changed, 40957 insertions(+), 7 deletions(-) + 436 files changed, 41002 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 @@ -856,9 +858,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/sha512/zsha512_msgostd.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/sha512/zsha512_nomsgostd.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/stub.s - create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/tls12/init.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/tls12/nobackend.go + create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_darwin.go + create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_msgostd.go + create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_nomsgostd.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_openssl.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_windows.go create mode 100644 src/vendor/github.com/microsoft/go/cryptobackend/tls13/hash_msgostd.go @@ -46296,22 +46300,9 @@ index 00000000000000..5e4b436554d44d +// Having this assembly file keeps the go command +// from complaining about the missing body +// (because the implementation might be here). -diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/tls12/init.go b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/init.go -new file mode 100644 -index 00000000000000..11f4c37aaccefb ---- /dev/null -+++ b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/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 tls12 -+ -+import _ "github.com/microsoft/go/cryptobackend" diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/tls12/nobackend.go b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/nobackend.go new file mode 100644 -index 00000000000000..cb967817da26b7 +index 00000000000000..3a7a8e392453f3 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/nobackend.go @@ -0,0 +1,14 @@ @@ -46326,12 +46317,41 @@ index 00000000000000..cb967817da26b7 +import "hash" + +func SupportsPRF() bool { panic("cryptobackend: not available") } -+func PRF(result, secret []byte, label string, seed []byte, h func() hash.Hash) error { ++func prf[H hash.Hash](result, secret []byte, label string, seed []byte, h func() H) error { + panic("cryptobackend: not available") +} +diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12.go b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12.go +new file mode 100644 +index 00000000000000..535d07382c5687 +--- /dev/null ++++ b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12.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 tls12 ++ ++import ( ++ "hash" ++ ++ "github.com/microsoft/go/cryptobackend" ++) ++ ++// PRF implements the TLS 1.2 pseudo-random function as defined in RFC 5246, Section 5. ++func PRF[H hash.Hash](h func() H, secret []byte, label string, seed []byte, keyLen int) ([]byte, error) { ++ if backend.Enabled && SupportsPRF() { ++ result := make([]byte, keyLen) ++ if err := prf(result, secret, label, seed, h); err != nil { ++ return nil, err ++ } ++ return result, nil ++ } ++ return prfFallback(h, secret, label, seed, keyLen) ++} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_darwin.go b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_darwin.go new file mode 100644 -index 00000000000000..78014828c62b5e +index 00000000000000..bc1b0c52226af6 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_darwin.go @@ -0,0 +1,14 @@ @@ -46346,12 +46366,53 @@ index 00000000000000..78014828c62b5e +import "hash" + +func SupportsPRF() bool { return false } -+func PRF(result, secret []byte, label string, seed []byte, h func() hash.Hash) error { ++func prf[H hash.Hash](result, secret []byte, label string, seed []byte, h func() H) error { ++ panic("cryptobackend: not available") ++} +diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_msgostd.go b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_msgostd.go +new file mode 100644 +index 00000000000000..69b74a5d119761 +--- /dev/null ++++ b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_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 tls12 ++ ++import ( ++ fallback "crypto/internal/fips140/tls12" ++ "hash" ++) ++ ++func prfFallback[H hash.Hash](h func() H, secret []byte, label string, seed []byte, keyLen int) ([]byte, error) { ++ return fallback.PRF(h, secret, label, seed, keyLen), nil ++} +diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_nomsgostd.go b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_nomsgostd.go +new file mode 100644 +index 00000000000000..6077eb43deec54 +--- /dev/null ++++ b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_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 tls12 ++ ++import "hash" ++ ++func prfFallback[H hash.Hash](h func() H, secret []byte, label string, seed []byte, keyLen int) ([]byte, error) { + panic("cryptobackend: not available") +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_openssl.go b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_openssl.go new file mode 100644 -index 00000000000000..a1c4e380e3909b +index 00000000000000..d7cd2683580172 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_openssl.go @@ -0,0 +1,18 @@ @@ -46370,12 +46431,12 @@ index 00000000000000..a1c4e380e3909b +) + +func SupportsPRF() bool { return openssl.SupportsTLS1PRF() } -+func PRF(result, secret []byte, label string, seed []byte, h func() hash.Hash) error { ++func prf[H hash.Hash](result, secret []byte, label string, seed []byte, h func() H) error { + return openssl.TLS1PRF(result, secret, []byte(label), seed, h) +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_windows.go b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_windows.go new file mode 100644 -index 00000000000000..9e50ac1bb7864f +index 00000000000000..f970f0b4789303 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/tls12/tls12_windows.go @@ -0,0 +1,18 @@ @@ -46394,7 +46455,7 @@ index 00000000000000..9e50ac1bb7864f +) + +func SupportsPRF() bool { return true } -+func PRF(result, secret []byte, label string, seed []byte, h func() hash.Hash) error { ++func prf[H hash.Hash](result, secret []byte, label string, seed []byte, h func() H) error { + return cng.TLS1PRF(result, secret, []byte(label), seed, h) +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/tls13/hash_msgostd.go b/src/vendor/github.com/microsoft/go/cryptobackend/tls13/hash_msgostd.go diff --git a/patches/0002-Add-crypto-backends.patch b/patches/0002-Add-crypto-backends.patch index 2b9b828caa..4bbdb51c7b 100644 --- a/patches/0002-Add-crypto-backends.patch +++ b/patches/0002-Add-crypto-backends.patch @@ -123,7 +123,7 @@ Subject: [PATCH] Add crypto backends src/crypto/tls/handshake_server_tls13.go | 6 +- src/crypto/tls/handshake_test.go | 3 +- src/crypto/tls/key_schedule.go | 3 +- - src/crypto/tls/prf.go | 27 ++ + src/crypto/tls/prf.go | 19 +- src/crypto/tls/prf_test.go | 9 + src/crypto/x509/verify_test.go | 2 +- src/go/build/buildbackend_test.go | 50 +++ @@ -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, 2444 insertions(+), 393 deletions(-) + 139 files changed, 2435 insertions(+), 394 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 @@ -5807,7 +5807,7 @@ index 652a6489b899d6..f25da189bf72c9 100644 // This file contains the functions necessary to compute the TLS 1.3 key diff --git a/src/crypto/tls/prf.go b/src/crypto/tls/prf.go -index bc59300f41c762..5b99af426de295 100644 +index bc59300f41c762..698bc79a80aead 100644 --- a/src/crypto/tls/prf.go +++ b/src/crypto/tls/prf.go @@ -8,6 +8,7 @@ import ( @@ -5818,17 +5818,16 @@ index bc59300f41c762..5b99af426de295 100644 "crypto/md5" "crypto/sha1" "crypto/sha256" -@@ -15,6 +16,9 @@ import ( +@@ -15,6 +16,8 @@ import ( "errors" "fmt" "hash" + -+ boring "github.com/microsoft/go/cryptobackend" + btls12 "github.com/microsoft/go/cryptobackend/tls12" ) type prfFunc func(secret []byte, label string, seed []byte, keyLen int) []byte -@@ -47,9 +51,25 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) { +@@ -47,6 +50,16 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) { } } @@ -5845,29 +5844,19 @@ index bc59300f41c762..5b99af426de295 100644 // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { result := make([]byte, keyLen) -+ if boring.Enabled && btls12.SupportsPRF() { -+ if err := btls12.PRF(result, secret, label, seed, nil); err != nil { -+ panic(boringPRFError{fmt.Errorf("crypto/tls: prf10: %v", err)}) -+ } -+ return result -+ } - hashSHA1 := sha1.New - hashMD5 := md5.New - -@@ -72,6 +92,13 @@ func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { +@@ -72,7 +85,11 @@ func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. func prf12(hashFunc func() hash.Hash) prfFunc { return func(secret []byte, label string, seed []byte, keyLen int) []byte { -+ if boring.Enabled && btls12.SupportsPRF() { -+ result := make([]byte, keyLen) -+ if err := btls12.PRF(result, secret, label, seed, fips140hash.UnwrapNew(hashFunc)); err != nil { -+ panic(boringPRFError{fmt.Errorf("crypto/tls: prf12: %v", err)}) -+ } -+ return result +- return tls12.PRF(hashFunc, secret, label, seed, keyLen) ++ result, err := btls12.PRF(fips140hash.UnwrapNew(hashFunc), secret, label, seed, keyLen) ++ if err != nil { ++ panic(boringPRFError{fmt.Errorf("crypto/tls: prf12: %v", err)}) + } - return tls12.PRF(hashFunc, secret, label, seed, keyLen) ++ return result } } + diff --git a/src/crypto/tls/prf_test.go b/src/crypto/tls/prf_test.go index 8233985a62bd22..70fb5c9c4b8c2d 100644 --- a/src/crypto/tls/prf_test.go