diff --git a/patches/0002-Add-crypto-backend-GOEXPERIMENTs.patch b/patches/0002-Add-crypto-backend-GOEXPERIMENTs.patch index eb7a94f009..26b349c8ac 100644 --- a/patches/0002-Add-crypto-backend-GOEXPERIMENTs.patch +++ b/patches/0002-Add-crypto-backend-GOEXPERIMENTs.patch @@ -12,8 +12,10 @@ Includes new tests in "build_test.go" and "buildbackend_test.go" to help maintain this feature. For more information, see the test files. --- src/cmd/go/alldocs.go | 3 + + src/cmd/go/internal/cfg/cfg.go | 6 +- src/cmd/go/internal/envcmd/env.go | 3 +- src/cmd/go/internal/help/helpdoc.go | 3 + + src/cmd/go/internal/load/pkg.go | 4 + src/cmd/go/internal/modindex/build_test.go | 73 +++++++++++++++++++ src/cmd/go/testdata/script/env_changed.txt | 3 + src/go/build/buildbackend_test.go | 50 +++++++++++++ @@ -21,33 +23,17 @@ maintain this feature. For more information, see the test files. .../build/testdata/backendtags_system/main.go | 3 + .../backendtags_system/systemcrypto.go | 3 + src/internal/buildcfg/cfg.go | 2 + - src/internal/buildcfg/exp.go | 34 +++++++++ + src/internal/buildcfg/cfg_test.go | 44 +++++++++++ + src/internal/buildcfg/exp.go | 20 +++++ src/internal/cfg/cfg.go | 1 + - .../goexperiment/exp_cngcrypto_off.go | 8 ++ - src/internal/goexperiment/exp_cngcrypto_on.go | 8 ++ - .../goexperiment/exp_darwincrypto_off.go | 8 ++ - .../goexperiment/exp_darwincrypto_on.go | 8 ++ - .../goexperiment/exp_opensslcrypto_off.go | 8 ++ - .../goexperiment/exp_opensslcrypto_on.go | 8 ++ - .../goexperiment/exp_systemcrypto_off.go | 8 ++ - .../goexperiment/exp_systemcrypto_on.go | 8 ++ - src/internal/goexperiment/flags.go | 18 +++++ src/internal/platform/supported.go | 12 +++ src/internal/systemcrypto/systemcrypto.go | 20 +++++ .../systemcrypto/systemcrypto_test.go | 58 +++++++++++++++ - 24 files changed, 351 insertions(+), 1 deletion(-) + 18 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 src/cmd/go/internal/modindex/build_test.go create mode 100644 src/go/build/buildbackend_test.go create mode 100644 src/go/build/testdata/backendtags_system/main.go create mode 100644 src/go/build/testdata/backendtags_system/systemcrypto.go - create mode 100644 src/internal/goexperiment/exp_cngcrypto_off.go - create mode 100644 src/internal/goexperiment/exp_cngcrypto_on.go - create mode 100644 src/internal/goexperiment/exp_darwincrypto_off.go - create mode 100644 src/internal/goexperiment/exp_darwincrypto_on.go - create mode 100644 src/internal/goexperiment/exp_opensslcrypto_off.go - create mode 100644 src/internal/goexperiment/exp_opensslcrypto_on.go - create mode 100644 src/internal/goexperiment/exp_systemcrypto_off.go - create mode 100644 src/internal/goexperiment/exp_systemcrypto_on.go create mode 100644 src/internal/systemcrypto/systemcrypto.go create mode 100644 src/internal/systemcrypto/systemcrypto_test.go @@ -65,6 +51,33 @@ index 74cafe9613917d..31ce076273aba2 100644 // // Additional information available from 'go env' but not read from the environment: // +diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go +index 78cbbb949e7c27..9bdbfb29c2752b 100644 +--- a/src/cmd/go/internal/cfg/cfg.go ++++ b/src/cmd/go/internal/cfg/cfg.go +@@ -14,6 +14,7 @@ import ( + "internal/buildcfg" + "internal/cfg" + "internal/platform" ++ "internal/systemcrypto" + "io" + "io/fs" + "os" +@@ -311,10 +312,13 @@ func computeExperiment() { + + // Add build tags based on the experiments in effect. + exps := Experiment.Enabled() +- expTags := make([]string, 0, len(exps)+len(BuildContext.ToolTags)) ++ expTags := make([]string, 0, len(exps)+len(BuildContext.ToolTags)+1) + for _, exp := range exps { + expTags = append(expTags, "goexperiment."+exp) + } ++ if systemcrypto.EnabledFor(Goos, Goarch) { ++ expTags = append(expTags, "goexperiment.systemcrypto") ++ } + BuildContext.ToolTags = append(expTags, BuildContext.ToolTags...) + } + diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 3d72c368b088a2..4fe28740a6e3c2 100644 --- a/src/cmd/go/internal/envcmd/env.go @@ -100,6 +113,28 @@ index 4f76f7f9c1fc68..783d11609c0bf4 100644 Additional information available from 'go env' but not read from the environment: +diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go +index 1d90061b065f5f..ba582cf1d0773e 100644 +--- a/src/cmd/go/internal/load/pkg.go ++++ b/src/cmd/go/internal/load/pkg.go +@@ -16,6 +16,7 @@ import ( + "go/token" + "internal/godebug" + "internal/platform" ++ "internal/systemcrypto" + "io/fs" + "os" + pathpkg "path" +@@ -2417,6 +2418,9 @@ func (p *Package) setBuildInfo(ctx context.Context, f *modfetch.Fetcher, autoVCS + buildmode = "archive" + } + } ++ if systemcrypto.EnabledFor(cfg.Goos, cfg.Goarch) { ++ appendSetting("microsoft_systemcrypto", "1") ++ } + appendSetting("-buildmode", buildmode) + appendSetting("-compiler", cfg.BuildContext.Compiler) + if gccgoflags := BuildGccgoflags.String(); gccgoflags != "" && cfg.BuildContext.Compiler == "gccgo" { diff --git a/src/cmd/go/internal/modindex/build_test.go b/src/cmd/go/internal/modindex/build_test.go new file mode 100644 index 00000000000000..1756c5d027fee0 @@ -307,77 +342,110 @@ index 89fd74eb823162..6d266ff641d721 100644 // Error is one of the errors found (if any) in the build configuration. var Error error -diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go -index 8eeef17c1f470e..d474ed1d4d466d 100644 ---- a/src/internal/buildcfg/exp.go -+++ b/src/internal/buildcfg/exp.go -@@ -6,6 +6,7 @@ package buildcfg +diff --git a/src/internal/buildcfg/cfg_test.go b/src/internal/buildcfg/cfg_test.go +index 2bbd478280241e..77eaacdc38756d 100644 +--- a/src/internal/buildcfg/cfg_test.go ++++ b/src/internal/buildcfg/cfg_test.go +@@ -6,6 +6,8 @@ package buildcfg import ( - "fmt" -+ "os" - "reflect" - "strings" + "os" ++ "slices" ++ "strings" + "testing" + ) -@@ -29,6 +30,19 @@ type ExperimentFlags struct { - // default in the current toolchain. This is, in effect, the "control" - // configuration and any variation from this is an experiment. - var Experiment ExperimentFlags = func() ExperimentFlags { -+ if SystemCryptoDisabled { -+ // If MS_GO_NOSYSTEMCRYPTO is set, ensure that nosystemcrypto is in GOEXPERIMENT. -+ // We do it here because it is the earliest point where the toolchain tries to retrive -+ // the GOEXPERIMENT value. -+ // The environment variable is updated rather than appending "nosystemcrypto" to the -+ // result of ParseGOEXPERIMENT because the latter will be moved at some point to -+ // internal/goexperiment, which can't import the os package. -+ v := os.Getenv("GOEXPERIMENT") -+ if v != "" { -+ v += "," +@@ -128,6 +130,48 @@ func TestGogoarchTags(t *testing.T) { + GOARM64 = old_goarm64 + } + ++func TestSystemCryptoNotGoExperiment(t *testing.T) { ++ flags, err := ParseGOEXPERIMENT("windows", "amd64", "") ++ if err != nil { ++ t.Fatal(err) ++ } ++ if slices.Contains(flags.Enabled(), "systemcrypto") { ++ t.Fatalf("Enabled() = %v, want no systemcrypto", flags.Enabled()) ++ } ++ if got := flags.String(); got != "" { ++ t.Fatalf("String() = %q, want empty string", got) ++ } ++ ++ if slices.Contains(flags.All(), "systemcrypto") || slices.Contains(flags.All(), "nosystemcrypto") { ++ t.Fatalf("All() = %v, want no systemcrypto setting", flags.All()) ++ } ++ for _, exp := range []string{"opensslcrypto", "cngcrypto", "darwincrypto"} { ++ if slices.Contains(flags.All(), exp) || slices.Contains(flags.All(), "no"+exp) { ++ t.Fatalf("All() = %v, want no %s setting", flags.All(), exp) ++ } ++ if _, err := ParseGOEXPERIMENT("windows", "386", exp); err == nil { ++ t.Fatalf("ParseGOEXPERIMENT accepted %s", exp) + } -+ os.Setenv("GOEXPERIMENT", v+"nosystemcrypto") + } - flags, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT)) - if err != nil { - Error = err -@@ -67,6 +81,18 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - regabiSupported = true - } - -+ // These are the goos/goarch combinations where systemcrypto is -+ // enabled by default. -+ var systemCryptoSupported bool -+ switch goos { -+ case "windows": -+ systemCryptoSupported = goarch == "amd64" || goarch == "arm64" -+ case "linux": -+ systemCryptoSupported = true -+ case "darwin": -+ systemCryptoSupported = true ++ if _, err := ParseGOEXPERIMENT("windows", "386", "systemcrypto"); err == nil { ++ t.Fatal("ParseGOEXPERIMENT accepted systemcrypto") ++ } else if !strings.Contains(err.Error(), "enabled automatically") || !strings.Contains(err.Error(), "MS_GO_NOSYSTEMCRYPTO=1") { ++ t.Fatalf("ParseGOEXPERIMENT systemcrypto error = %q", err) + } ++ if _, err := ParseGOEXPERIMENT("windows", "amd64", "nosystemcrypto"); err == nil { ++ t.Fatal("ParseGOEXPERIMENT accepted nosystemcrypto") ++ } else if !strings.Contains(err.Error(), "MS_GO_NOSYSTEMCRYPTO=1") || !strings.Contains(err.Error(), "systemcrypto supports CGO_ENABLED=0 since Go 1.27") { ++ t.Fatalf("ParseGOEXPERIMENT nosystemcrypto error = %q", err) ++ } ++ ++ t.Setenv("CGO_ENABLED", "0") ++ if _, err := ParseGOEXPERIMENT("windows", "amd64", "systemcrypto"); err == nil { ++ t.Fatal("ParseGOEXPERIMENT accepted systemcrypto with CGO_ENABLED=0") ++ } else if strings.Contains(err.Error(), "systemcrypto supports CGO_ENABLED=0 since Go 1.27") { ++ t.Fatalf("ParseGOEXPERIMENT systemcrypto CGO_ENABLED=0 error = %q", err) ++ } ++} ++ + var goodFIPS = []string{ + "v1.0.0", + "v1.0.1", +diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go +index 8eeef17c1f470e..dda96ef5b15616 100644 +--- a/src/internal/buildcfg/exp.go ++++ b/src/internal/buildcfg/exp.go +@@ -10,12 +10,14 @@ import ( + "strings" + + "internal/goexperiment" ++ goplatform "internal/platform" + ) + + // ExperimentFlags represents a set of GOEXPERIMENT flags relative to a baseline + // (platform-default) experiment configuration. + type ExperimentFlags struct { + goexperiment.Flags + - // Older versions (anything before V16) of dsymutil don't handle - // the .debug_rnglists section in DWARF5. See - // https://github.com/golang/go/issues/26379#issuecomment-2677068742 -@@ -79,6 +105,7 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - dwarf5Supported := (goos != "darwin" && goos != "ios" && goos != "aix") + baseline goexperiment.Flags + } - baseline := goexperiment.Flags{ -+ SystemCrypto: systemCryptoSupported, - RegabiWrappers: regabiSupported, - RegabiArgs: regabiSupported, - Dwarf5: dwarf5Supported, -@@ -126,6 +153,10 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - // to build with any experiment flags. - flags.Flags = goexperiment.Flags{} - continue -+ } else if f == "nosystemcrypto" { -+ // GOEXPERIMENT=nosystemcrypto disables system crypto. -+ flags.Flags.SystemCrypto = false -+ continue - } - val := true +@@ -131,6 +133,21 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { if strings.HasPrefix(f, "no") { -@@ -152,6 +183,9 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { + f, val = f[2:], false + } ++ // Check for removed crypto experiments. ++ switch f { ++ case "systemcrypto": ++ if val { ++ return nil, fmt.Errorf("GOEXPERIMENT=systemcrypto has been removed; system crypto is enabled automatically on supported platforms and can be disabled with MS_GO_NOSYSTEMCRYPTO=1") ++ } ++ return nil, fmt.Errorf("GOEXPERIMENT=nosystemcrypto has been removed; use MS_GO_NOSYSTEMCRYPTO=1 to disable system crypto; note that systemcrypto supports CGO_ENABLED=0 since Go 1.27") ++ case "opensslcrypto", "cngcrypto", "darwincrypto": ++ switch { ++ case goplatform.SystemCryptoSupported(goos, goarch): ++ return nil, fmt.Errorf("systemcrypto is enabled by default, GOEXPERIMENT %s is not necessary", f) ++ default: ++ return nil, fmt.Errorf("GOEXPERIMENT %s has been removed; system crypto is enabled automatically on supported platforms", f) ++ } ++ } + set, ok := names[f] + if !ok { + return nil, fmt.Errorf("unknown GOEXPERIMENT %s", f) +@@ -152,6 +169,9 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { if flags.RegabiArgs && !flags.RegabiWrappers { return nil, fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers") } @@ -398,147 +466,6 @@ index 9329769721b7de..1724afb71b851e 100644 + MS_GO_NOSYSTEMCRYPTO PKG_CONFIG ` -diff --git a/src/internal/goexperiment/exp_cngcrypto_off.go b/src/internal/goexperiment/exp_cngcrypto_off.go -new file mode 100644 -index 00000000000000..eb879f94fa0c42 ---- /dev/null -+++ b/src/internal/goexperiment/exp_cngcrypto_off.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.cngcrypto -+ -+package goexperiment -+ -+const CNGCrypto = false -+const CNGCryptoInt = 0 -diff --git a/src/internal/goexperiment/exp_cngcrypto_on.go b/src/internal/goexperiment/exp_cngcrypto_on.go -new file mode 100644 -index 00000000000000..5b0a55d6c5772e ---- /dev/null -+++ b/src/internal/goexperiment/exp_cngcrypto_on.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.cngcrypto -+ -+package goexperiment -+ -+const CNGCrypto = true -+const CNGCryptoInt = 1 -diff --git a/src/internal/goexperiment/exp_darwincrypto_off.go b/src/internal/goexperiment/exp_darwincrypto_off.go -new file mode 100644 -index 00000000000000..331111ce4759f7 ---- /dev/null -+++ b/src/internal/goexperiment/exp_darwincrypto_off.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.darwincrypto -+ -+package goexperiment -+ -+const DarwinCrypto = false -+const DarwinCryptoInt = 0 -diff --git a/src/internal/goexperiment/exp_darwincrypto_on.go b/src/internal/goexperiment/exp_darwincrypto_on.go -new file mode 100644 -index 00000000000000..4bf785b999ecce ---- /dev/null -+++ b/src/internal/goexperiment/exp_darwincrypto_on.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.darwincrypto -+ -+package goexperiment -+ -+const DarwinCrypto = true -+const DarwinCryptoInt = 1 -diff --git a/src/internal/goexperiment/exp_opensslcrypto_off.go b/src/internal/goexperiment/exp_opensslcrypto_off.go -new file mode 100644 -index 00000000000000..b28c0976a94cb0 ---- /dev/null -+++ b/src/internal/goexperiment/exp_opensslcrypto_off.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.opensslcrypto -+ -+package goexperiment -+ -+const OpenSSLCrypto = false -+const OpenSSLCryptoInt = 0 -diff --git a/src/internal/goexperiment/exp_opensslcrypto_on.go b/src/internal/goexperiment/exp_opensslcrypto_on.go -new file mode 100644 -index 00000000000000..154386b3de81ea ---- /dev/null -+++ b/src/internal/goexperiment/exp_opensslcrypto_on.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.opensslcrypto -+ -+package goexperiment -+ -+const OpenSSLCrypto = true -+const OpenSSLCryptoInt = 1 -diff --git a/src/internal/goexperiment/exp_systemcrypto_off.go b/src/internal/goexperiment/exp_systemcrypto_off.go -new file mode 100644 -index 00000000000000..6afc2ef2c5822e ---- /dev/null -+++ b/src/internal/goexperiment/exp_systemcrypto_off.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.systemcrypto -+ -+package goexperiment -+ -+const SystemCrypto = false -+const SystemCryptoInt = 0 -diff --git a/src/internal/goexperiment/exp_systemcrypto_on.go b/src/internal/goexperiment/exp_systemcrypto_on.go -new file mode 100644 -index 00000000000000..fcd4cb9da0d162 ---- /dev/null -+++ b/src/internal/goexperiment/exp_systemcrypto_on.go -@@ -0,0 +1,8 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.systemcrypto -+ -+package goexperiment -+ -+const SystemCrypto = true -+const SystemCryptoInt = 1 -diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go -index 17fe15270aba60..5f09ad11a701e2 100644 ---- a/src/internal/goexperiment/flags.go -+++ b/src/internal/goexperiment/flags.go -@@ -60,6 +60,24 @@ type Flags struct { - StaticLockRanking bool - BoringCrypto bool - -+ // SystemCrypto enables the system crypto backend for the target GOOS. -+ // The specific backend used depends on the platform: -+ // - Linux: OpenSSL -+ // - Windows: CNG -+ // - Darwin: CommonCrypto/Security.framework -+ // -+ // Platform-specific code should use build constraints like: -+ // //go:build goexperiment.systemcrypto && linux -+ // //go:build goexperiment.systemcrypto && windows -+ // //go:build goexperiment.systemcrypto && darwin -+ SystemCrypto bool -+ -+ // OpenSSLCrypto, CNGCrypto, and DarwinCrypto are deprecated. -+ // Use SystemCrypto instead. -+ OpenSSLCrypto bool -+ CNGCrypto bool -+ DarwinCrypto bool -+ - // Regabi is split into several sub-experiments that can be - // enabled individually. Not all combinations work. - // The "regabi" GOEXPERIMENT is an alias for all "working" diff --git a/src/internal/platform/supported.go b/src/internal/platform/supported.go index 6f37e368596498..471c5cc430bb29 100644 --- a/src/internal/platform/supported.go diff --git a/patches/0003-Implement-crypto-internal-backend.patch b/patches/0003-Implement-crypto-internal-backend.patch index 01752c9fd0..d69ae958d8 100644 --- a/patches/0003-Implement-crypto-internal-backend.patch +++ b/patches/0003-Implement-crypto-internal-backend.patch @@ -12,18 +12,23 @@ desired goexperiments and build tags. .gitignore | 2 + .../compile/internal/logopt/logopt_test.go | 5 + src/cmd/compile/script_test.go | 8 + - src/cmd/dist/build.go | 80 +++- - src/cmd/dist/test.go | 47 +- + src/cmd/compile/testdata/script/README | 2 + + src/cmd/dist/build.go | 68 ++- + src/cmd/dist/test.go | 45 +- src/cmd/go/go_test.go | 11 + src/cmd/go/internal/cfg/cfg.go | 16 + - src/cmd/go/internal/load/pkg.go | 3 + src/cmd/go/internal/tool/tool.go | 9 +- - src/cmd/go/systemcrypto_test.go | 233 +++++++++ + .../verylongtest/testdata/script/README | 2 + + src/cmd/go/systemcrypto_test.go | 250 ++++++++++ + src/cmd/go/testdata/script/README | 2 + + src/cmd/go/testdata/script/darwin_no_cgo.txt | 1 + .../go/testdata/script/env_cross_build.txt | 2 + .../script/test_android_issue62123.txt | 2 + - src/cmd/internal/testdir/testdir_test.go | 7 + - src/cmd/link/internal/ld/main.go | 2 +- + .../internal/fuzztest/testdata/script/README | 2 + + .../internal/script/scripttest/conditions.go | 10 +- + src/cmd/internal/testdir/testdir_test.go | 6 + src/cmd/link/link_test.go | 8 + + src/cmd/link/testdata/script/README | 2 + src/crypto/internal/backend/backend_darwin.go | 442 ++++++++++++++++++ src/crypto/internal/backend/backend_linux.go | 435 +++++++++++++++++ src/crypto/internal/backend/backend_test.go | 56 +++ @@ -52,9 +57,8 @@ desired goexperiments and build tags. .../internal/fips140only/fips140only.go | 11 +- src/crypto/systemcrypto_nocgo_linux.go | 18 + src/go/build/deps_test.go | 24 +- - src/internal/buildcfg/exp.go | 48 +- src/runtime/runtime_boring.go | 5 + - 45 files changed, 2881 insertions(+), 29 deletions(-) + 49 files changed, 2863 insertions(+), 17 deletions(-) create mode 100644 src/cmd/go/systemcrypto_test.go create mode 100644 src/crypto/internal/backend/backend_darwin.go create mode 100644 src/crypto/internal/backend/backend_linux.go @@ -97,14 +101,14 @@ index 344b31f7ac1c1d..b4583113d5aa15 100644 # For files created by specific development environment (e.g. editor), # use alternative ways to exclude files from git. diff --git a/src/cmd/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go -index 1edabf9fb7ff04..f47c17401e480b 100644 +index 1edabf9fb7ff04..5e9fc3507485bc 100644 --- a/src/cmd/compile/internal/logopt/logopt_test.go +++ b/src/cmd/compile/internal/logopt/logopt_test.go @@ -5,6 +5,7 @@ package logopt import ( -+ "internal/goexperiment" ++ "internal/systemcrypto" "internal/testenv" "os" "path/filepath" @@ -112,7 +116,7 @@ index 1edabf9fb7ff04..f47c17401e480b 100644 goos0 := runtime.GOOS if runtime.GOARCH == "amd64" { // Test many things with "linux" (wasm will get "js") arches = []string{"arm", "arm64", "386", "amd64", "mips", "mips64", "loong64", "ppc64le", "riscv64", "s390x", "wasm"} -+ if goexperiment.SystemCrypto { ++ if systemcrypto.Enabled() { + // SystemCrypto does not support cross-compilation on all architectures. + arches = []string{"arm", "arm64", "386", "amd64", "loong64", "ppc64le", "riscv64", "s390x"} + } @@ -120,14 +124,14 @@ index 1edabf9fb7ff04..f47c17401e480b 100644 } diff --git a/src/cmd/compile/script_test.go b/src/cmd/compile/script_test.go -index 0e32e0769ee2e2..eda2d576acc6c6 100644 +index 0e32e0769ee2e2..552dfe13dd6a05 100644 --- a/src/cmd/compile/script_test.go +++ b/src/cmd/compile/script_test.go @@ -7,6 +7,7 @@ package main import ( "cmd/internal/script/scripttest" "flag" -+ "internal/goexperiment" ++ "internal/systemcrypto" "internal/testenv" "os" "runtime" @@ -135,7 +139,7 @@ index 0e32e0769ee2e2..eda2d576acc6c6 100644 // the installed linker with our test binary. doReplacement = false } -+ if goexperiment.SystemCrypto { ++ if systemcrypto.Enabled() { + // If systemcrypto is enabled, we can't replace the compiler + // because the test binary is built with systemcrypto, but the + // compiler is not. This would cause a mismatch in the @@ -145,11 +149,24 @@ index 0e32e0769ee2e2..eda2d576acc6c6 100644 repls := []scripttest.ToolReplacement{} if doReplacement { if testCompiler == "" { +diff --git a/src/cmd/compile/testdata/script/README b/src/cmd/compile/testdata/script/README +index 9ec997a138f0f2..09c4e7955ec162 100644 +--- a/src/cmd/compile/testdata/script/README ++++ b/src/cmd/compile/testdata/script/README +@@ -281,6 +281,8 @@ The available conditions are: + testing.Short() + [symlink] + testenv.HasSymlink() ++[systemcrypto] ++ system crypto is enabled + [verbose] + testing.Verbose() + diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go -index 78d55bec559987..bb3119ef0823d7 100644 +index 78d55bec559987..decf356a449ba9 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go -@@ -1399,6 +1399,80 @@ func toolenv() []string { +@@ -1399,6 +1399,68 @@ func toolenv() []string { // still have full paths for stack traces for compiler crashes and the like. env = append(env, "GOFLAGS=-trimpath -ldflags=-w -gcflags=cmd/...=-dwarf=false") } @@ -185,27 +202,15 @@ index 78d55bec559987..bb3119ef0823d7 100644 + +// toolenvMicrosoft appends Microsoft-specific environment variables to env. +func toolenvMicrosoft(env []string) []string { -+ // Keep all the experiments from the current -+ // environment, but with "systemcrypto" removed and -+ // "nosystemcrypto" added. This is used when building -+ // the Microsoft build of Go to favor portability. -+ // Go only uses crypto packages for non-crypto purposes, -+ // such as generating build IDs. -+ env = updateEnv("GOEXPERIMENT", env, func(value string) string { -+ if value == "" { -+ return "nosystemcrypto" -+ } -+ goexp := strings.Split(value, ",") -+ goexp = slices.DeleteFunc(goexp, func(s string) bool { -+ return s == "systemcrypto" || s == "nosystemcrypto" -+ }) -+ goexp = append(goexp, "nosystemcrypto") -+ return strings.Join(goexp, ",") ++ // Disable system crypto while building the Microsoft build of Go to favor ++ // portability. Go only uses crypto packages for non-crypto purposes, such as ++ // generating build IDs. ++ env = updateEnv("MS_GO_NOSYSTEMCRYPTO", env, func(value string) string { ++ return "1" + }) + + // Build the Go toolchain with "-tags=ms_skipfipscheck". This -+ // allows toolchains not built with the systemcrypto goexperiment to be used -+ // when GODEBUG=fips140=on is set. For example, when running ++ // allows toolchains to be used when GODEBUG=fips140=on is set. For example, when running + // "GODEBUG=fips140=on go test ./..." or "GODEBUG=fips140=on go run .". + env = updateEnv("GOFLAGS", env, func(value string) string { + if value == "" { @@ -230,7 +235,7 @@ index 78d55bec559987..bb3119ef0823d7 100644 return env } -@@ -1641,12 +1715,12 @@ func cmdbootstrap() { +@@ -1641,12 +1703,12 @@ func cmdbootstrap() { os.Setenv("CC", compilerEnvLookup("CC", defaultcc, goos, goarch)) xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch) } @@ -247,7 +252,7 @@ index 78d55bec559987..bb3119ef0823d7 100644 if debug { run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full") diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go -index aadb1ff52b067f..53d661338f2d72 100644 +index aadb1ff52b067f..dc6981715e9ce1 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -158,10 +158,12 @@ func (t *tester) run() { @@ -299,18 +304,15 @@ index aadb1ff52b067f..53d661338f2d72 100644 // Only start multiple test dir shards on builders, // where they get distributed to multiple machines. // See issues 20141 and 31834. -@@ -1380,9 +1386,9 @@ func (t *tester) registerCgoTests(heading string) { +@@ -1380,7 +1386,7 @@ func (t *tester) registerCgoTests(heading string) { // a C linker warning on Linux. // in function `bio_ip_and_port_to_socket_and_addr': // warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking - if staticCheck.skip == nil && goos == "linux" && strings.Contains(goexperiment, "boringcrypto") { + if staticCheck.skip == nil && goos == "linux" && systemCryptoEnabled() { staticCheck.skip = func(*distTest) (string, bool) { -- return "skipping static linking check on Linux when using boringcrypto to avoid C linker warning about getaddrinfo", true -+ return "skipping static linking check on Linux when using systemcrypto to avoid C linker warning about getaddrinfo", true + return "skipping static linking check on Linux when using boringcrypto to avoid C linker warning about getaddrinfo", true } - } - @@ -1908,3 +1914,28 @@ func goexperiments(exps ...string) string { return existing + strings.Join(exps, ",") @@ -341,17 +343,17 @@ index aadb1ff52b067f..53d661338f2d72 100644 + return enabled +} diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go -index 47839e0229b951..2d1a7fa99d551e 100644 +index 47839e0229b951..99ac16a3951934 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go -@@ -13,6 +13,7 @@ import ( - "fmt" +@@ -14,6 +14,7 @@ import ( "go/format" "internal/godebug" -+ "internal/goexperiment" "internal/platform" ++ "internal/systemcrypto" "internal/testenv" "io" + "io/fs" @@ -110,6 +111,13 @@ func TestMain(m *testing.M) { if v := os.Getenv("TESTGO_TOOLCHAIN_VERSION"); v != "" { work.ToolchainVersion = v @@ -370,17 +372,17 @@ index 47839e0229b951..2d1a7fa99d551e 100644 } func TestGoEnv(t *testing.T) { -+ if goexperiment.SystemCrypto { ++ if systemcrypto.Enabled() { + t.Skip("freebsd is not supported by system crypto") + } tg := testgo(t) tg.parallel() defer tg.cleanup() diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go -index 78cbbb949e7c27..dcf9d04dd979f3 100644 +index 9bdbfb29c2752b..80c8211ed03100 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go -@@ -19,6 +19,7 @@ import ( +@@ -20,6 +20,7 @@ import ( "os" "path/filepath" "runtime" @@ -388,7 +390,7 @@ index 78cbbb949e7c27..dcf9d04dd979f3 100644 "strings" "sync" "time" -@@ -229,6 +230,21 @@ func ForceHost() { +@@ -230,6 +231,21 @@ func ForceHost() { BuildContext = defaultContext() // Call SetGOROOT to properly set the GOROOT on the new context. SetGOROOT(Getenv("GOROOT"), false) @@ -410,20 +412,6 @@ index 78cbbb949e7c27..dcf9d04dd979f3 100644 // Recompute experiments: the settings determined depend on GOOS and GOARCH. // This will also update the BuildContext's tool tags to include the new // experiment tags. -diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go -index 1d90061b065f5f..0d5d4fe0556564 100644 ---- a/src/cmd/go/internal/load/pkg.go -+++ b/src/cmd/go/internal/load/pkg.go -@@ -2417,6 +2417,9 @@ func (p *Package) setBuildInfo(ctx context.Context, f *modfetch.Fetcher, autoVCS - buildmode = "archive" - } - } -+ if cfg.Experiment.SystemCrypto { -+ appendSetting("microsoft_systemcrypto", "1") -+ } - appendSetting("-buildmode", buildmode) - appendSetting("-compiler", cfg.BuildContext.Compiler) - if gccgoflags := BuildGccgoflags.String(); gccgoflags != "" && cfg.BuildContext.Compiler == "gccgo" { diff --git a/src/cmd/go/internal/tool/tool.go b/src/cmd/go/internal/tool/tool.go index 97c27c8caa44d6..bb18bb112a314a 100644 --- a/src/cmd/go/internal/tool/tool.go @@ -452,12 +440,25 @@ index 97c27c8caa44d6..bb18bb112a314a 100644 } buildAndRunTool(ld, ctx, tool, args, runFunc) +diff --git a/src/cmd/go/internal/verylongtest/testdata/script/README b/src/cmd/go/internal/verylongtest/testdata/script/README +index 9ec997a138f0f2..09c4e7955ec162 100644 +--- a/src/cmd/go/internal/verylongtest/testdata/script/README ++++ b/src/cmd/go/internal/verylongtest/testdata/script/README +@@ -281,6 +281,8 @@ The available conditions are: + testing.Short() + [symlink] + testenv.HasSymlink() ++[systemcrypto] ++ system crypto is enabled + [verbose] + testing.Verbose() + diff --git a/src/cmd/go/systemcrypto_test.go b/src/cmd/go/systemcrypto_test.go new file mode 100644 -index 00000000000000..d6cc434197cff1 +index 00000000000000..fa5c5b76024ab1 --- /dev/null +++ b/src/cmd/go/systemcrypto_test.go -@@ -0,0 +1,233 @@ +@@ -0,0 +1,250 @@ +// Copyright 2025 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. @@ -469,7 +470,6 @@ index 00000000000000..d6cc434197cff1 + "internal/testenv" + "os" + "path/filepath" -+ "slices" + "strings" + "testing" +) @@ -500,9 +500,14 @@ index 00000000000000..d6cc434197cff1 +` + +func execGoTool(t *testing.T, allowFail bool, env []string, args ...string) (string, bool) { ++ return execGoToolInDir(t, "", allowFail, env, args...) ++} ++ ++func execGoToolInDir(t *testing.T, dir string, allowFail bool, env []string, args ...string) (string, bool) { + t.Helper() + cmd := testenv.Command(t, testenv.GoToolPath(t), args...) + cmd = testenv.CleanCmdEnv(cmd) ++ cmd.Dir = dir + cmd.Env = append(cmd.Env, env...) + out, err := cmd.CombinedOutput() + sout := strings.TrimSpace(string(out)) @@ -540,40 +545,29 @@ index 00000000000000..d6cc434197cff1 + cryptoFile := writeFile(t, fileWithCrypto) + + tt := []struct { -+ goos string -+ goarch string -+ goexp string -+ succeed bool ++ goos string ++ goarch string + }{ -+ {"linux", "386", "", true}, -+ {"linux", "amd64", "", true}, -+ {"linux", "arm64", "", true}, -+ {"linux", "loong64", "", true}, -+ {"linux", "ppc64le", "", true}, -+ {"linux", "riscv64", "", true}, -+ {"linux", "s390x", "", true}, -+ {"linux", "arm", "", true}, -+ {"darwin", "amd64", "", true}, -+ {"darwin", "arm64", "", true}, -+ {"windows", "386", "", false}, // cgoless system crypto not supported on windows/386 -+ {"windows", "amd64", "", true}, -+ {"windows", "arm64", "", true}, ++ {"linux", "386"}, ++ {"linux", "amd64"}, ++ {"linux", "arm64"}, ++ {"linux", "loong64"}, ++ {"linux", "ppc64le"}, ++ {"linux", "riscv64"}, ++ {"linux", "s390x"}, ++ {"linux", "arm"}, ++ {"darwin", "amd64"}, ++ {"darwin", "arm64"}, ++ {"windows", "386"}, ++ {"windows", "amd64"}, ++ {"windows", "arm64"}, + } + for _, tc := range tt { -+ t.Run(tc.goos+"/"+tc.goarch+"/"+tc.goexp, func(t *testing.T) { ++ t.Run(tc.goos+"/"+tc.goarch, func(t *testing.T) { + t.Parallel() -+ if tc.goexp == "" { -+ tc.goexp = "systemcrypto" -+ } else { -+ tc.goexp += ",systemcrypto" -+ } -+ env := []string{"CGO_ENABLED=0", "GOOS=" + tc.goos, "GOARCH=" + tc.goarch, "GOEXPERIMENT=" + tc.goexp, "MS_GO_NOSYSTEMCRYPTO=0"} -+ if out, ok := execGoTool(t, true, env, "build", "-o", outPath(t), cryptoFile); ok != tc.succeed { -+ if tc.succeed { -+ t.Fatalf("expected success, got failure: %s", out) -+ } else { -+ t.Fatalf("expected failure, got success") -+ } ++ env := []string{"CGO_ENABLED=0", "GOOS=" + tc.goos, "GOARCH=" + tc.goarch, "MS_GO_NOSYSTEMCRYPTO=0"} ++ if out, ok := execGoTool(t, true, env, "build", "-o", outPath(t), cryptoFile); !ok { ++ t.Fatalf("expected success, got failure: %s", out) + } + }) + } @@ -625,9 +619,6 @@ index 00000000000000..d6cc434197cff1 + t.Parallel() + out := outPath(t) + env := []string{"CGO_ENABLED=0", "GOOS=" + tt.goos, "GOARCH=" + tt.goarch, "MS_GO_NOSYSTEMCRYPTO=0"} -+ // Set a goexperiment in case the Go toolchain has been built with GOEXPERIMENT=nosystemcrypto. -+ // In that case, systemcrypto will not be enabled by default unless we pass an explicit GOEXPERIMENT. -+ env = append(env, "GOEXPERIMENT=regabi") + execGoTool(t, false, env, "build", "-o", out, cryptoFile) + // Check that the binary has the correct settings. + settings, _ := execGoTool(t, false, nil, "version", "-m", out) @@ -636,95 +627,204 @@ index 00000000000000..d6cc434197cff1 + } + }) + } -+ +} + -+func TestSystemCryptoSetting(t *testing.T) { ++func TestSystemCryptoDisabled(t *testing.T) { + t.Parallel() -+ file := writeFile(t, fileWithCrypto) ++ cryptoFile := writeFile(t, fileWithCrypto) + -+ type testCase struct { -+ enabled bool -+ env []string -+ } -+ tests := []testCase{ -+ {false, []string{"GOEXPERIMENT=nosystemcrypto"}}, -+ {false, []string{"GOEXPERIMENT=systemcrypto,nosystemcrypto"}}, -+ {false, []string{"MS_GO_NOSYSTEMCRYPTO=1"}}, -+ {true, []string{"GOEXPERIMENT=systemcrypto"}}, -+ {true, []string{"GOEXPERIMENT=nosystemcrypto,systemcrypto"}}, -+ } -+ // Duplicate each test with MS_GO_NOSYSTEMCRYPTO=1, which should always result -+ // in systemcrypto being disabled. -+ n := len(tests) -+ for i := range n { -+ tt := tests[i] -+ tests = append(tests, testCase{false, append(tt.env, "MS_GO_NOSYSTEMCRYPTO=1")}) ++ tests := []struct { ++ goos string ++ goarch string ++ }{ ++ {"linux", "amd64"}, ++ {"linux", "arm64"}, ++ {"darwin", "amd64"}, ++ {"darwin", "arm64"}, ++ {"windows", "amd64"}, ++ {"windows", "arm64"}, + } + for _, tt := range tests { -+ t.Run(strings.Join(tt.env, ","), func(t *testing.T) { ++ t.Run(fmt.Sprintf("%s_%s", tt.goos, tt.goarch), func(t *testing.T) { + t.Parallel() + out := outPath(t) -+ -+ if !slices.ContainsFunc(tt.env, func(r string) bool { -+ return strings.HasPrefix(r, "MS_GO_NOSYSTEMCRYPTO=") -+ }) { -+ // Ensure MS_GO_NOSYSTEMCRYPTO is set to 0 if not specified -+ // to avoid interference from the environment. -+ tt.env = append(tt.env, "MS_GO_NOSYSTEMCRYPTO=0") ++ env := []string{"CGO_ENABLED=0", "GOOS=" + tt.goos, "GOARCH=" + tt.goarch, "MS_GO_NOSYSTEMCRYPTO=1"} ++ execGoTool(t, false, env, "build", "-o", out, cryptoFile) ++ settings, _ := execGoTool(t, false, nil, "version", "-m", out) ++ if strings.Contains(settings, "microsoft_systemcrypto=1") { ++ t.Errorf("expected microsoft_systemcrypto=1 not to be in settings, got %v", settings) + } ++ }) ++ } ++} + -+ // Build the binary with the specified GOEXPERIMENT. -+ _, ok := execGoTool(t, true, tt.env, "build", "-o", out, file) -+ if !ok { -+ t.Skip("skipping test because GOEXPERIMENT not supported by the current toolchain") -+ } ++func TestSystemCryptoBuildTag(t *testing.T) { ++ t.Parallel() + -+ // Check that the binary has the correct settings. -+ settings, _ := execGoTool(t, false, nil, "version", "-m", out) -+ hasSetting := strings.Contains(settings, "microsoft_systemcrypto=1") -+ if tt.enabled && !hasSetting { -+ t.Errorf("expected microsoft_systemcrypto=1 in settings, got %v", settings) -+ } else if !tt.enabled && hasSetting { -+ t.Errorf("expected microsoft_systemcrypto=1 not to be in settings, got %v", settings) ++ dir := t.TempDir() ++ files := map[string]string{ ++ "go.mod": "module example.com/systemcrypto-tag\n\ngo 1.27\n", ++ "always.go": "package main\n", ++ "with_system.go": "//go:build goexperiment.systemcrypto\n\npackage main\n", ++ "without_system.go": "//go:build !goexperiment.systemcrypto\n\npackage main\n", ++ } ++ for name, content := range files { ++ if err := os.WriteFile(filepath.Join(dir, name), []byte(content), 0o644); err != nil { ++ t.Fatal(err) ++ } ++ } ++ ++ tests := []struct { ++ name string ++ env []string ++ wantFile string ++ badFile string ++ }{ ++ { ++ name: "supported", ++ env: []string{"GOOS=linux", "GOARCH=amd64", "MS_GO_NOSYSTEMCRYPTO=0"}, ++ wantFile: "with_system.go", ++ badFile: "without_system.go", ++ }, ++ { ++ name: "disabled", ++ env: []string{"GOOS=linux", "GOARCH=amd64", "MS_GO_NOSYSTEMCRYPTO=1"}, ++ wantFile: "without_system.go", ++ badFile: "with_system.go", ++ }, ++ { ++ name: "unsupported", ++ env: []string{"GOOS=windows", "GOARCH=386", "MS_GO_NOSYSTEMCRYPTO=0"}, ++ wantFile: "without_system.go", ++ badFile: "with_system.go", ++ }, ++ } ++ for _, tt := range tests { ++ t.Run(tt.name, func(t *testing.T) { ++ t.Parallel() ++ out, _ := execGoToolInDir(t, dir, false, tt.env, "list", "-f", "{{.GoFiles}}", ".") ++ if !strings.Contains(out, tt.wantFile) || strings.Contains(out, tt.badFile) { ++ t.Fatalf("go list .GoFiles = %q, want %s and not %s", out, tt.wantFile, tt.badFile) + } + }) + } +} +diff --git a/src/cmd/go/testdata/script/README b/src/cmd/go/testdata/script/README +index 9fa2c92c0b32b2..c0dd9e533e8e48 100644 +--- a/src/cmd/go/testdata/script/README ++++ b/src/cmd/go/testdata/script/README +@@ -421,6 +421,8 @@ The available conditions are: + testing.Short() + [symlink] + testenv.HasSymlink() ++[systemcrypto] ++ system crypto is enabled + [trimpath] + test binary was built with -trimpath + [verbose] +diff --git a/src/cmd/go/testdata/script/darwin_no_cgo.txt b/src/cmd/go/testdata/script/darwin_no_cgo.txt +index fa445925b7c374..248be5160833c1 100644 +--- a/src/cmd/go/testdata/script/darwin_no_cgo.txt ++++ b/src/cmd/go/testdata/script/darwin_no_cgo.txt +@@ -4,6 +4,7 @@ + # of cmd/go, which imports approximately everything + # in std (certainly everything relevant). + [!GOOS:darwin] skip ++[systemcrypto] skip + go list -deps cmd/go + ! stdout runtime/cgo + diff --git a/src/cmd/go/testdata/script/env_cross_build.txt b/src/cmd/go/testdata/script/env_cross_build.txt -index 91d1cb936d3652..b7f503d9506324 100644 +index 91d1cb936d3652..cca75b4be873d0 100644 --- a/src/cmd/go/testdata/script/env_cross_build.txt +++ b/src/cmd/go/testdata/script/env_cross_build.txt @@ -1,6 +1,8 @@ # Test that the correct default GOEXPERIMENT is used when cross # building with GOENV (#46815). -+[GOEXPERIMENT:systemcrypto] skip # systemcrypto is not supported on ios nor mips ++[systemcrypto] skip # systemcrypto is not supported on ios nor mips + # Unset variables set by the TestScript harness. Users typically won't # explicitly configure these, and #46815 doesn't repro if they are. env GOOS= diff --git a/src/cmd/go/testdata/script/test_android_issue62123.txt b/src/cmd/go/testdata/script/test_android_issue62123.txt -index 2f46a6b44bffe1..69071289e2de81 100644 +index 2f46a6b44bffe1..b036dde70ed36e 100644 --- a/src/cmd/go/testdata/script/test_android_issue62123.txt +++ b/src/cmd/go/testdata/script/test_android_issue62123.txt @@ -1,3 +1,5 @@ -+[GOEXPERIMENT:systemcrypto] skip # systemcrypto is not supported on android ++[systemcrypto] skip # systemcrypto is not supported on android + env GOOS=android GOARCH=amd64 CGO_ENABLED=0 ! go build -o $devnull cmd/buildid +diff --git a/src/cmd/internal/fuzztest/testdata/script/README b/src/cmd/internal/fuzztest/testdata/script/README +index 9ec997a138f0f2..09c4e7955ec162 100644 +--- a/src/cmd/internal/fuzztest/testdata/script/README ++++ b/src/cmd/internal/fuzztest/testdata/script/README +@@ -281,6 +281,8 @@ The available conditions are: + testing.Short() + [symlink] + testenv.HasSymlink() ++[systemcrypto] ++ system crypto is enabled + [verbose] + testing.Verbose() + +diff --git a/src/cmd/internal/script/scripttest/conditions.go b/src/cmd/internal/script/scripttest/conditions.go +index 6702e9279b106b..09b92a3ed98df1 100644 +--- a/src/cmd/internal/script/scripttest/conditions.go ++++ b/src/cmd/internal/script/scripttest/conditions.go +@@ -9,6 +9,7 @@ import ( + "fmt" + "internal/buildcfg" + "internal/platform" ++ "internal/systemcrypto" + "internal/testenv" + "runtime" + "strings" +@@ -48,6 +49,7 @@ func AddToolChainScriptConditions(t *testing.T, conds map[string]script.Cond, go + add("mustlinkext", script.Condition("platform always requires external linking", mustLinkExt)) + add("pielinkext", script.Condition("platform requires external linking for PIE", pieLinkExt)) + add("race", sysCondition("-race", platform.RaceDetectorSupported, true, goHostOS, goHostArch)) ++ add("systemcrypto", script.Condition("system crypto is enabled", hasSystemCrypto)) + add("symlink", lazyBool("testenv.HasSymlink()", testenv.HasSymlink)) + } + +@@ -96,10 +98,16 @@ func hasGodebug(s *script.State, value string) (bool, error) { + return false, nil + } + +-func hasGoexperiment(s *script.State, value string) (bool, error) { ++func hasSystemCrypto(s *script.State) (bool, error) { + GOOS, _ := s.LookupEnv("GOOS") + GOARCH, _ := s.LookupEnv("GOARCH") ++ return systemcrypto.EnabledFor(GOOS, GOARCH), nil ++} ++ ++func hasGoexperiment(s *script.State, value string) (bool, error) { + goexp, _ := s.LookupEnv("GOEXPERIMENT") ++ GOOS, _ := s.LookupEnv("GOOS") ++ GOARCH, _ := s.LookupEnv("GOARCH") + flags, err := buildcfg.ParseGOEXPERIMENT(GOOS, GOARCH, goexp) + if err != nil { + return false, err diff --git a/src/cmd/internal/testdir/testdir_test.go b/src/cmd/internal/testdir/testdir_test.go -index d81b3a849cb975..bbeca248e4f8e4 100644 +index d81b3a849cb975..f051b6dfa209dd 100644 --- a/src/cmd/internal/testdir/testdir_test.go +++ b/src/cmd/internal/testdir/testdir_test.go -@@ -118,6 +118,13 @@ func Test(t *testing.T) { +@@ -14,6 +14,7 @@ import ( + "go/build" + "go/build/constraint" + "hash/fnv" ++ "internal/systemcrypto" + "internal/testenv" + "io" + "io/fs" +@@ -118,6 +119,11 @@ func Test(t *testing.T) { goDebug = env.GODEBUG tmpDir = t.TempDir() -+ if slices.ContainsFunc(strings.Split(goExperiment, ","), func(s string) bool { -+ return s == "systemcrypto" -+ }) { ++ if systemcrypto.EnabledFor(goos, goarch) { + // Codegen tests cross-compile to platforms that do not support system crypto. + *allCodegen = false + } @@ -732,36 +832,23 @@ index d81b3a849cb975..bbeca248e4f8e4 100644 common := testCommon{ gorootTestDir: filepath.Join(testenv.GOROOT(t), "test"), runoutputGate: make(chan bool, *runoutputLimit), -diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go -index 19ed197a20b57e..5e592c7c6697d7 100644 ---- a/src/cmd/link/internal/ld/main.go -+++ b/src/cmd/link/internal/ld/main.go -@@ -189,7 +189,7 @@ func Main(arch *sys.Arch, theArch Arch) { - } - - buildVersion := buildcfg.Version -- if goexperiment := buildcfg.Experiment.String(); goexperiment != "" { -+ if goexperiment := buildcfg.Experiment.MSString(); goexperiment != "" { - sep := " " - if !strings.Contains(buildVersion, "-") { // See go.dev/issue/75953. - sep = "-" diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go -index e7c406c4ad1eb8..ac36a6dd1ca1a0 100644 +index e7c406c4ad1eb8..7574d1b069807d 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go -@@ -13,6 +13,7 @@ import ( - "errors" +@@ -14,6 +14,7 @@ import ( "internal/abi" "internal/buildcfg" -+ "internal/goexperiment" "internal/platform" ++ "internal/systemcrypto" "internal/testenv" "internal/xcoff" + "os" @@ -368,6 +369,9 @@ func TestBuildForTvOS(t *testing.T) { if runtime.GOOS != "darwin" { t.Skip("skipping on non-darwin platform") } -+ if goexperiment.SystemCrypto { ++ if systemcrypto.Enabled() { + t.Skip("tvOS is not supported by system crypto") + } if testing.Short() && testenv.Builder() == "" { @@ -771,13 +858,26 @@ index e7c406c4ad1eb8..ac36a6dd1ca1a0 100644 t.Skip("skipping on non-{linux,darwin}/amd64 platform") } -+ if goexperiment.SystemCrypto { ++ if systemcrypto.Enabled() { + t.Skip("skipping on system crypto, which does not support android/386") + } + t.Parallel() tmpdir := t.TempDir() +diff --git a/src/cmd/link/testdata/script/README b/src/cmd/link/testdata/script/README +index 9ec997a138f0f2..09c4e7955ec162 100644 +--- a/src/cmd/link/testdata/script/README ++++ b/src/cmd/link/testdata/script/README +@@ -281,6 +281,8 @@ The available conditions are: + testing.Short() + [symlink] + testenv.HasSymlink() ++[systemcrypto] ++ system crypto is enabled + [verbose] + testing.Verbose() + diff --git a/src/crypto/internal/backend/backend_darwin.go b/src/crypto/internal/backend/backend_darwin.go new file mode 100644 index 00000000000000..73830cae246cbd @@ -3326,7 +3426,7 @@ index a8d840b17022cc..2a17f7da2d4aaa 100644 } diff --git a/src/crypto/systemcrypto_nocgo_linux.go b/src/crypto/systemcrypto_nocgo_linux.go new file mode 100644 -index 00000000000000..7500bd3a86472b +index 00000000000000..b3a50c0aae95af --- /dev/null +++ b/src/crypto/systemcrypto_nocgo_linux.go @@ -0,0 +1,18 @@ @@ -3340,7 +3440,7 @@ index 00000000000000..7500bd3a86472b + +func init() { + ` -+ Using GOEXPERIMENT=systemcrypto on Linux requires CGO_ENABLED=1. ++ Using system crypto on Linux requires CGO_ENABLED=1. + + Our cgo-less OpenSSL implementation is only supported on certain architectures. + These architectures are: 386, amd64, arm, arm64, loong64, ppc64le, riscv64 and s390x. @@ -3404,96 +3504,6 @@ index 7834d307b0426d..148fff74886a58 100644 < crypto/internal/fips140cache < crypto/rand < crypto/ed25519 # depends on crypto/rand.Reader -diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go -index d474ed1d4d466d..864f3ab2f05a66 100644 ---- a/src/internal/buildcfg/exp.go -+++ b/src/internal/buildcfg/exp.go -@@ -8,9 +8,11 @@ import ( - "fmt" - "os" - "reflect" -+ "slices" - "strings" - - "internal/goexperiment" -+ goplatform "internal/platform" - ) - - // ExperimentFlags represents a set of GOEXPERIMENT flags relative to a baseline -@@ -81,17 +83,7 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - regabiSupported = true - } - -- // These are the goos/goarch combinations where systemcrypto is -- // enabled by default. -- var systemCryptoSupported bool -- switch goos { -- case "windows": -- systemCryptoSupported = goarch == "amd64" || goarch == "arm64" -- case "linux": -- systemCryptoSupported = true -- case "darwin": -- systemCryptoSupported = true -- } -+ systemCryptoSupported := goplatform.SystemCryptoSupported(goos, goarch) - - // Older versions (anything before V16) of dsymutil don't handle - // the .debug_rnglists section in DWARF5. See -@@ -162,6 +154,16 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - if strings.HasPrefix(f, "no") { - f, val = f[2:], false - } -+ // Check for deprecated per-platform crypto experiments. -+ switch f { -+ case "opensslcrypto", "cngcrypto", "darwincrypto": -+ switch { -+ case goos == "darwin" || goos == "linux" || (goos == "windows" && goarch != "386"): -+ return nil, fmt.Errorf("systemcrypto is enabled by default, GOEXPERIMENT %s is not necessary", f) -+ default: -+ return nil, fmt.Errorf("GOEXPERIMENT %s has been removed, use GOEXPERIMENT=systemcrypto instead", f) -+ } -+ } - set, ok := names[f] - if !ok { - return nil, fmt.Errorf("unknown GOEXPERIMENT %s", f) -@@ -186,6 +188,10 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { - if flags.BoringCrypto { - return nil, fmt.Errorf("GOEXPERIMENT boringcrypto is not supported in the Microsoft build of Go") - } -+ if flags.SystemCrypto && !systemCryptoSupported && goplatform.BuildModeSupported("gc", "default", goos, goarch) { -+ // System crypto enabled but not supported. -+ return nil, fmt.Errorf("GOEXPERIMENT systemcrypto is not supported on %s/%s\n\tFor more information, visit https://github.com/microsoft/go/tree/microsoft/main/eng/doc/fips", goos, goarch) -+ } - return flags, nil - } - -@@ -195,6 +201,26 @@ func (exp *ExperimentFlags) String() string { - return strings.Join(expList(&exp.Flags, &exp.baseline, false), ",") - } - -+// MSString returns the canonical GOEXPERIMENT string to enable this experiment -+// configuration. This is a modified version of what's returned by -+// [ExperimentFlags.String] that ensures experiments that have a different -+// baseline in the Microsoft build of Go are elided. -+// -+// Elision is important because this method is involved in the value of -+// runtime.Version(), and many usages out there, e.g. the standard library -+// go/version package, don't expect the version to contain experiments. -+func (exp *ExperimentFlags) MSString() string { -+ // Parse [String] rather than calling expList directly so that changes to -+ // [String] are reflected in [MSString] without careful tracking. -+ exps := strings.Split(exp.String(), ",") -+ // The Microsoft build of Go default behavior sets a few experiments that we -+ // need to remove from the result. -+ exps = slices.DeleteFunc(exps, func(s string) bool { -+ return s == "nosystemcrypto" -+ }) -+ return strings.Join(exps, ",") -+} -+ - // expList returns the list of lower-cased experiment names for - // experiments that differ from base. base may be nil to indicate no - // experiments. If all is true, then include all experiment flags, diff --git a/src/runtime/runtime_boring.go b/src/runtime/runtime_boring.go index 831ee67afc952d..d2f00d57c10286 100644 --- a/src/runtime/runtime_boring.go diff --git a/patches/0004-Use-crypto-backends.patch b/patches/0004-Use-crypto-backends.patch index 58765e91b1..af257a41a9 100644 --- a/patches/0004-Use-crypto-backends.patch +++ b/patches/0004-Use-crypto-backends.patch @@ -5,12 +5,11 @@ Subject: [PATCH] Use crypto backends --- src/cmd/api/boring_test.go | 2 +- - src/cmd/dist/test.go | 5 +- + src/cmd/dist/test.go | 3 +- src/cmd/go/go_boring_test.go | 6 +- - src/cmd/go/script_test.go | 2 + - src/cmd/go/testdata/script/darwin_no_cgo.txt | 1 + + src/cmd/go/script_test.go | 3 + .../go/testdata/script/gopath_std_vendor.txt | 9 + - src/cmd/link/internal/ld/config.go | 8 + + src/cmd/link/internal/ld/config.go | 7 + src/cmd/link/internal/ld/lib.go | 6 + src/crypto/aes/aes.go | 2 +- src/crypto/aes/aes_test.go | 2 +- @@ -64,7 +63,7 @@ Subject: [PATCH] Use crypto backends src/crypto/rand/rand.go | 2 +- src/crypto/rand/rand_test.go | 9 +- src/crypto/rc4/rc4.go | 18 ++ - src/crypto/rsa/boring.go | 13 +- + src/crypto/rsa/boring.go | 12 +- src/crypto/rsa/boring_test.go | 2 +- src/crypto/rsa/fips.go | 94 +++++---- src/crypto/rsa/notboring.go | 4 +- @@ -102,7 +101,7 @@ Subject: [PATCH] Use crypto backends src/hash/notboring_test.go | 9 + src/net/lookup_test.go | 3 + src/os/exec/exec_test.go | 9 + - 98 files changed, 1627 insertions(+), 251 deletions(-) + 97 files changed, 1624 insertions(+), 250 deletions(-) create mode 100644 src/crypto/dsa/boring.go create mode 100644 src/crypto/dsa/notboring.go create mode 100644 src/crypto/ecdsa/badlinkname.go @@ -128,7 +127,7 @@ index f0e3575637c62a..9eab3b4e66e60b 100644 package main diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go -index 53d661338f2d72..f87b5a6c5fd7fe 100644 +index dc6981715e9ce1..89101acdbe6d73 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -722,7 +722,7 @@ func (t *tester) registerTests() { @@ -140,17 +139,8 @@ index 53d661338f2d72..f87b5a6c5fd7fe 100644 // Test standard crypto packages with fips140=on. t.registerTest("GOFIPS140=latest go test crypto/...", &goTest{ variant: "gofips140", -@@ -1382,7 +1382,7 @@ func (t *tester) registerCgoTests(heading string) { - } - } - -- // Doing a static link with boringcrypto gets -+ // Doing a static link with systemcrypto gets - // a C linker warning on Linux. - // in function `bio_ip_and_port_to_socket_and_addr': - // warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking @@ -1391,7 +1391,6 @@ func (t *tester) registerCgoTests(heading string) { - return "skipping static linking check on Linux when using systemcrypto to avoid C linker warning about getaddrinfo", true + return "skipping static linking check on Linux when using boringcrypto to avoid C linker warning about getaddrinfo", true } } - @@ -178,32 +168,21 @@ index ed0fbf3d53d75b..a2f74c8095d449 100644 func TestBoringInternalLink(t *testing.T) { tg := testgo(t) diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go -index 088b9a8b5fdb2e..6a27473d4ed1d6 100644 +index 088b9a8b5fdb2e..4e1e545367afef 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go -@@ -299,6 +299,8 @@ var extraEnvKeys = []string{ +@@ -299,6 +299,9 @@ var extraEnvKeys = []string{ "GO_TESTING_GOTOOLS", // for gccgo testing "GCCGO", // for gccgo testing "GCCGOTOOLDIR", // for gccgo testing ++ "MS_GO_NOSYSTEMCRYPTO", + + "OPENSSL_FORCE_FIPS_MODE", // useful for testing on Mariner 2. } // updateSum runs 'go mod tidy', 'go list -mod=mod -m all', or -diff --git a/src/cmd/go/testdata/script/darwin_no_cgo.txt b/src/cmd/go/testdata/script/darwin_no_cgo.txt -index fa445925b7c374..e4b9714df817ea 100644 ---- a/src/cmd/go/testdata/script/darwin_no_cgo.txt -+++ b/src/cmd/go/testdata/script/darwin_no_cgo.txt -@@ -4,6 +4,7 @@ - # of cmd/go, which imports approximately everything - # in std (certainly everything relevant). - [!GOOS:darwin] skip -+[GOEXPERIMENT:systemcrypto] skip - go list -deps cmd/go - ! stdout runtime/cgo - diff --git a/src/cmd/go/testdata/script/gopath_std_vendor.txt b/src/cmd/go/testdata/script/gopath_std_vendor.txt -index 4aaf46b5d0f0dc..995d53d0fed9aa 100644 +index 4aaf46b5d0f0dc..46d03fcd4aeae3 100644 --- a/src/cmd/go/testdata/script/gopath_std_vendor.txt +++ b/src/cmd/go/testdata/script/gopath_std_vendor.txt @@ -1,5 +1,14 @@ @@ -215,31 +194,23 @@ index 4aaf46b5d0f0dc..995d53d0fed9aa 100644 +# golang.org/x/net/http2/hpack, so we must make sure it is the only one. +# +# See https://github.com/microsoft/go/issues/481 for more details, such as the -+# dependency chain that would cause the failure if the gocrypt tag isn't used. -+env GOEXPERIMENT=none ++# dependency chain that would cause the failure if systemcrypto isn't disabled. ++env MS_GO_NOSYSTEMCRYPTO=1 + [!compiler:gc] skip go list -f '{{.Dir}}' vendor/golang.org/x/net/http2/hpack diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go -index acbebf28598a9c..5f6d8a91ea384c 100644 +index acbebf28598a9c..6ef32735ddfd57 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go -@@ -7,6 +7,7 @@ package ld - import ( - "fmt" - "internal/buildcfg" -+ "internal/goexperiment" - "internal/platform" - ) - -@@ -34,6 +35,13 @@ func (mode *BuildMode) Set(s string) error { +@@ -34,6 +34,13 @@ func (mode *BuildMode) Set(s string) error { return fmt.Errorf("invalid buildmode: %q", s) case "exe": switch buildcfg.GOOS + "/" + buildcfg.GOARCH { + case "darwin/amd64": + // We can't link against the static object file when using no_pie -+ if goexperiment.SystemCrypto { ++ if platform.SystemCryptoSupported(buildcfg.GOOS, buildcfg.GOARCH) && !buildcfg.SystemCryptoDisabled { + *mode = BuildModePIE + } else { + *mode = BuildModeExe @@ -1395,7 +1366,7 @@ index ed599ad2908dfb..b3106b9ed83811 100644 default: return errors.New("ed25519: expected opts.Hash zero (unhashed message, for standard Ed25519) or SHA-512 (for Ed25519ph)") diff --git a/src/crypto/ed25519/ed25519_test.go b/src/crypto/ed25519/ed25519_test.go -index c8a23e3246a949..02dc683fa1a1b4 100644 +index c8a23e3246a949..843dbee858a5de 100644 --- a/src/crypto/ed25519/ed25519_test.go +++ b/src/crypto/ed25519/ed25519_test.go @@ -9,12 +9,15 @@ import ( @@ -1407,7 +1378,7 @@ index c8a23e3246a949..02dc683fa1a1b4 100644 "crypto/rand" "crypto/sha512" "encoding/hex" -+ "internal/goexperiment" ++ "internal/systemcrypto" "log" "os" + "runtime" @@ -1419,7 +1390,7 @@ index c8a23e3246a949..02dc683fa1a1b4 100644 sig2 := Sign(priv[:], msg) - if !bytes.Equal(sig, sig2[:]) { -+ if !bytes.Equal(sig, sig2[:]) && !(goexperiment.SystemCrypto && runtime.GOOS == "darwin") { ++ if !bytes.Equal(sig, sig2[:]) && !(systemcrypto.Enabled() && runtime.GOOS == "darwin") { t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2) } @@ -2352,7 +2323,7 @@ index 0bc14be888d9d6..4172402e1bb620 100644 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..cd7223c89eeae5 100644 +index eb0ed14e243c6b..5023f354ba7fe3 100644 --- a/src/crypto/pbkdf2/pbkdf2_test.go +++ b/src/crypto/pbkdf2/pbkdf2_test.go @@ -6,12 +6,13 @@ package pbkdf2_test @@ -2366,7 +2337,7 @@ index eb0ed14e243c6b..cd7223c89eeae5 100644 "crypto/sha1" "crypto/sha256" "hash" -+ "internal/goexperiment" ++ "internal/systemcrypto" "testing" ) @@ -2374,7 +2345,7 @@ index eb0ed14e243c6b..cd7223c89eeae5 100644 } func TestMaxKeyLength(t *testing.T) { -+ if goexperiment.SystemCrypto { ++ if systemcrypto.Enabled() { + t.Skip("Some backends don't support keys longer than 32 bytes") + } // This error cannot be triggered on platforms where int is 31 bits (i.e. @@ -2496,10 +2467,10 @@ index c4d2b0d382e7fc..ba8dc141117e59 100644 return } diff --git a/src/crypto/rsa/boring.go b/src/crypto/rsa/boring.go -index b9f9d3154f2589..27bdf13d2268ce 100644 +index b9f9d3154f2589..92b960f7219945 100644 --- a/src/crypto/rsa/boring.go +++ b/src/crypto/rsa/boring.go -@@ -2,15 +2,17 @@ +@@ -2,15 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -2514,18 +2485,17 @@ index b9f9d3154f2589..27bdf13d2268ce 100644 + boring "crypto/internal/backend" + "crypto/internal/backend/bbig" "crypto/internal/boring/bcache" -+ "internal/goexperiment" "math/big" + "runtime" ) // Cached conversions from Go PublicKey/PrivateKey to BoringCrypto. -@@ -62,6 +64,11 @@ type boringPriv struct { +@@ -62,6 +63,11 @@ type boringPriv struct { } func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyRSA, error) { + // CommonCrypto requires the CRT values to be precomputed if nil -+ if goexperiment.SystemCrypto && runtime.GOOS == "darwin" && (priv.Precomputed.Dp == nil || priv.Precomputed.Dq == nil || priv.Precomputed.Qinv == nil) { ++ if runtime.GOOS == "darwin" && (priv.Precomputed.Dp == nil || priv.Precomputed.Dq == nil || priv.Precomputed.Qinv == nil) { + priv.Precompute() + priv.Precomputed.fips = nil + } @@ -2827,7 +2797,7 @@ index c65552cd93526a..910416abe842f5 100644 ciphertext := decodeBase64("fjOVdirUzFoLlukv80dBllMLjXythIf22feqPrNo0YoIjzyzyoMFiLjAc/Y4krkeZ11XFThIrEvw\nkRiZcCq5ng==") _, err := DecryptPKCS1v15(nil, test512Key, ciphertext) diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go -index e03f4ab06603c6..a9d9daba2fd6ce 100644 +index e03f4ab06603c6..088f87ee6a536e 100644 --- a/src/crypto/rsa/pss_test.go +++ b/src/crypto/rsa/pss_test.go @@ -8,14 +8,17 @@ import ( @@ -2841,7 +2811,7 @@ index e03f4ab06603c6..a9d9daba2fd6ce 100644 "crypto/sha256" "crypto/sha512" "encoding/hex" -+ "internal/goexperiment" ++ "internal/systemcrypto" "math/big" "os" + "runtime" @@ -2852,7 +2822,7 @@ index e03f4ab06603c6..a9d9daba2fd6ce 100644 hashed = h.Sum(hashed[:0]) if err := VerifyPSS(key, hash, hashed, sig, opts); err != nil { -+ if goexperiment.SystemCrypto && runtime.GOOS == "darwin" && key.N.BitLen() == 1025 { ++ if systemcrypto.Enabled() && runtime.GOOS == "darwin" && key.N.BitLen() == 1025 { + t.Skip("CommonCrypto doesn't support golden test entries with this key size") + } t.Error(err) @@ -3167,7 +3137,7 @@ index 069938a22dbc5a..8d0e06b86f4359 100644 } h := New224() diff --git a/src/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go -index a18a536ba2896f..7b3b37c3b0c10d 100644 +index a18a536ba2896f..be543811ea94d1 100644 --- a/src/crypto/sha256/sha256_test.go +++ b/src/crypto/sha256/sha256_test.go @@ -8,10 +8,13 @@ package sha256 @@ -3180,7 +3150,7 @@ index a18a536ba2896f..7b3b37c3b0c10d 100644 + "errors" "fmt" "hash" -+ "internal/goexperiment" ++ "internal/systemcrypto" "io" "testing" ) @@ -3277,7 +3247,7 @@ index a18a536ba2896f..7b3b37c3b0c10d 100644 - if allocs != 0 { - t.Fatalf("allocs = %v; want = 0", allocs) + maxAllocs := 0 -+ if goexperiment.SystemCrypto { ++ if systemcrypto.Enabled() { + maxAllocs = 2 + } + if allocs > float64(maxAllocs) { @@ -4476,22 +4446,22 @@ index 42211ed099ed1e..e6d185374ffe6d 100644 const testNXDOMAIN = "invalid.invalid." diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go -index 4f39d9bbe345a8..0a379aaf9c1859 100644 +index 4f39d9bbe345a8..b372f4077a3fe3 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go -@@ -14,6 +14,7 @@ import ( - "errors" +@@ -15,6 +15,7 @@ import ( "flag" "fmt" -+ "internal/goexperiment" "internal/poll" ++ "internal/systemcrypto" "internal/testenv" "io" + "log" @@ -692,6 +693,14 @@ func TestExtraFiles(t *testing.T) { t.Skipf("skipping test on %q", runtime.GOOS) } -+ if goexperiment.SystemCrypto && runtime.GOOS == "linux" { ++ if systemcrypto.Enabled() && runtime.GOOS == "linux" { + // OpenSSL default behavior is to maintain open FDs to any + // random devices that get used by the random number library. + // Since those FDs are not marked FD_CLOEXEC or O_CLOEXEC, diff --git a/patches/0009-Add-appinsights-telemetry.patch b/patches/0009-Add-appinsights-telemetry.patch index a5118539d8..1e48c16b69 100644 --- a/patches/0009-Add-appinsights-telemetry.patch +++ b/patches/0009-Add-appinsights-telemetry.patch @@ -40,15 +40,15 @@ index 71c9d1dc299388..8cab5daec4da54 100644 +these practices. \ No newline at end of file diff --git a/src/cmd/go/internal/telemetrystats/telemetrystats.go b/src/cmd/go/internal/telemetrystats/telemetrystats.go -index c6e58935bb0ee2..0cd7d3582c9ee6 100644 +index c6e58935bb0ee2..82651441fe61fd 100644 --- a/src/cmd/go/internal/telemetrystats/telemetrystats.go +++ b/src/cmd/go/internal/telemetrystats/telemetrystats.go @@ -11,7 +11,12 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/modload" "cmd/internal/telemetry/counter" -+ "internal/buildcfg" + "internal/platform" ++ "internal/systemcrypto" + "os" "strings" + @@ -65,10 +65,10 @@ index c6e58935bb0ee2..0cd7d3582c9ee6 100644 + } + + if platform.SystemCryptoSupported(cfg.Goos, cfg.Goarch) { -+ if buildcfg.SystemCryptoDisabled { -+ counter.Inc("msgo/systemcrypto:disabled") -+ } else { ++ if systemcrypto.EnabledFor(cfg.Goos, cfg.Goarch) { + counter.Inc("msgo/systemcrypto:enabled") ++ } else { ++ counter.Inc("msgo/systemcrypto:disabled") + } + } + diff --git a/patches/0013-Add-Microsoft-version-information.patch b/patches/0013-Add-Microsoft-version-information.patch index f8ae5f87ae..7c03c5ceb3 100644 --- a/patches/0013-Add-Microsoft-version-information.patch +++ b/patches/0013-Add-Microsoft-version-information.patch @@ -31,10 +31,10 @@ Microsoft build of Go version string. create mode 100644 src/cmd/go/testdata/script/gotoolchain_local_ms.txt diff --git a/doc/godebug.md b/doc/godebug.md -index 1736fd71017add..114079d8f99527 100644 +index 4701102b91ec93..f6f8d9a37b138a 100644 --- a/doc/godebug.md +++ b/doc/godebug.md -@@ -216,6 +216,15 @@ Microsoft build of Go 1.26 added a new `ms_tlsprofile` setting that controls the +@@ -236,6 +236,15 @@ Microsoft build of Go 1.26 added a new `ms_tlsprofile` setting that controls the - "default": use the recommended Microsoft TLS settings. This is the default. - "off": use the default upstream Go TLS settings. @@ -51,7 +51,7 @@ index 1736fd71017add..114079d8f99527 100644 Go 1.25 added a new `decoratemappings` setting that controls whether the Go diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go -index 6a1a5258b22dc8..0d6b05a42920bb 100644 +index decf356a449ba9..270607af75229e 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -455,6 +455,22 @@ func findgoversion() string { @@ -264,7 +264,7 @@ index 27d275644a4bd0..3c40024b4b7ab7 100644 } if i := strings.Index(version, "-X:"); i >= 0 { diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go -index 0d5d4fe0556564..78cd9a2680b03f 100644 +index ba582cf1d0773e..ca91bd97545057 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -14,6 +14,7 @@ import ( @@ -274,9 +274,9 @@ index 0d5d4fe0556564..78cd9a2680b03f 100644 + "internal/buildcfg" "internal/godebug" "internal/platform" - "io/fs" -@@ -2420,6 +2421,7 @@ func (p *Package) setBuildInfo(ctx context.Context, f *modfetch.Fetcher, autoVCS - if cfg.Experiment.SystemCrypto { + "internal/systemcrypto" +@@ -2421,6 +2422,7 @@ func (p *Package) setBuildInfo(ctx context.Context, f *modfetch.Fetcher, autoVCS + if systemcrypto.EnabledFor(cfg.Goos, cfg.Goarch) { appendSetting("microsoft_systemcrypto", "1") } + appendSetting("microsoft_toolset_version", buildcfg.Version) @@ -336,7 +336,7 @@ index 00000000000000..24538695be2cf2 +go version +stdout go1.501 diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go -index 5e592c7c6697d7..df70274e03b5df 100644 +index 19ed197a20b57e..92672cc5bb60dc 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -188,15 +188,20 @@ func Main(arch *sys.Arch, theArch Arch) { @@ -348,7 +348,7 @@ index 5e592c7c6697d7..df70274e03b5df 100644 + // versions. This approach is intended to minimize the patch diff and avoid + // touching the same lines as earlier patches. + appendExperimentVersion := func(buildVersion string) string { return buildVersion } - if goexperiment := buildcfg.Experiment.MSString(); goexperiment != "" { + if goexperiment := buildcfg.Experiment.String(); goexperiment != "" { - sep := " " - if !strings.Contains(buildVersion, "-") { // See go.dev/issue/75953. - sep = "-" @@ -447,10 +447,10 @@ index 6d266ff641d721..d1ed759065e278 100644 var Error error diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go -index 1ba17bc136710f..a3868ad860ed4a 100644 +index 360c0f82e1264e..4aee5045a9efac 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go -@@ -51,6 +51,7 @@ var All = []Info{ +@@ -50,6 +50,7 @@ var All = []Info{ {Name: "jstmpllitinterp", Package: "html/template", Opaque: true}, // bug #66217: remove Opaque {Name: "ms_tlsprofile", Package: "crypto/tls", Opaque: true}, {Name: "ms_tlsx25519", Package: "crypto/tls", Opaque: true}, @@ -499,10 +499,10 @@ index a69f4aaede794d..f5c35867b78e26 100644 // GOOS is the running program's operating system target: diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go -index 835aa8ecedb484..78c2673fbe3661 100644 +index 0cc653b0a3d156..145c91337ddab6 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go -@@ -361,6 +361,9 @@ var debug struct { +@@ -351,6 +351,9 @@ var debug struct { // tracebacklabels controls the inclusion of goroutine labels in the // goroutine status header line. tracebacklabels atomic.Int32 @@ -512,7 +512,7 @@ index 835aa8ecedb484..78c2673fbe3661 100644 } var dbgvars = []*dbgVar{ -@@ -398,6 +401,7 @@ var dbgvars = []*dbgVar{ +@@ -387,6 +390,7 @@ var dbgvars = []*dbgVar{ {name: "tracebacklabels", atomic: &debug.tracebacklabels, def: 1}, {name: "tracefpunwindoff", value: &debug.tracefpunwindoff}, {name: "updatemaxprocs", value: &debug.updatemaxprocs, def: 1},