@@ -19,7 +19,7 @@ desired goexperiments and build tags.
1919 src/cmd/go/internal/cfg/cfg.go | 16 +
2020 src/cmd/go/internal/load/pkg.go | 3 +
2121 src/cmd/go/internal/tool/tool.go | 9 +-
22- src/cmd/go/systemcrypto_test.go | 197 ++++++++++
22+ src/cmd/go/systemcrypto_test.go | 249 ++ ++++++++++
2323 .../go/testdata/script/env_cross_build.txt | 2 +
2424 .../script/test_android_issue62123.txt | 2 +
2525 src/cmd/internal/testdir/testdir_test.go | 7 +
@@ -55,7 +55,7 @@ desired goexperiments and build tags.
5555 src/internal/buildcfg/exp.go | 57 +++
5656 src/runtime/runtime_boring.go | 5 +
5757 src/syscall/exec_linux_test.go | 4 +
58- 46 files changed, 2367 insertions(+), 22 deletions(-)
58+ 46 files changed, 2419 insertions(+), 22 deletions(-)
5959 create mode 100644 src/cmd/go/systemcrypto_test.go
6060 create mode 100644 src/crypto/internal/backend/backend_test.go
6161 create mode 100644 src/crypto/internal/backend/bbig/big.go
@@ -455,7 +455,7 @@ index a4edd854f1d35a..10ee92536b96cd 100644
455455 // This will also update the BuildContext's tool tags to include the new
456456 // experiment tags.
457457diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
458- index 554963240049e4..2a2647fde9ce91 100644
458+ index 3b8bbdc91b8191..53a58e23f8b05c 100644
459459--- a/src/cmd/go/internal/load/pkg.go
460460+++ b/src/cmd/go/internal/load/pkg.go
461461@@ -2412,6 +2412,9 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
@@ -469,10 +469,10 @@ index 554963240049e4..2a2647fde9ce91 100644
469469 appendSetting("-compiler", cfg.BuildContext.Compiler)
470470 if gccgoflags := BuildGccgoflags.String(); gccgoflags != "" && cfg.BuildContext.Compiler == "gccgo" {
471471diff --git a/src/cmd/go/internal/tool/tool.go b/src/cmd/go/internal/tool/tool.go
472- index 75a8fab78ad31b..57f1d79e89f36e 100644
472+ index e283c7354f5a34..ad56d64a29f684 100644
473473--- a/src/cmd/go/internal/tool/tool.go
474474+++ b/src/cmd/go/internal/tool/tool.go
475- @@ -304 ,6 +304 ,10 @@ func buildAndRunBuiltinTool(loaderstate *modload.State, ctx context.Context, too
475+ @@ -305 ,6 +305 ,10 @@ func buildAndRunBuiltinTool(loaderstate *modload.State, ctx context.Context, too
476476 // Override GOOS and GOARCH for the build to build the tool using
477477 // the same GOOS and GOARCH as this go command.
478478 cfg.ForceHost()
@@ -483,7 +483,7 @@ index 75a8fab78ad31b..57f1d79e89f36e 100644
483483
484484 // Ignore go.mod and go.work: we don't need them, and we want to be able
485485 // to run the tool even if there's an issue with the module or workspace the
486- @@ -311 ,8 +315 ,11 @@ func buildAndRunBuiltinTool(loaderstate *modload.State, ctx context.Context, too
486+ @@ -312 ,8 +316 ,11 @@ func buildAndRunBuiltinTool(loaderstate *modload.State, ctx context.Context, too
487487 loaderstate.RootMode = modload.NoRoot
488488
489489 runFunc := func(b *work.Builder, ctx context.Context, a *work.Action) error {
@@ -498,21 +498,23 @@ index 75a8fab78ad31b..57f1d79e89f36e 100644
498498 buildAndRunTool(loaderstate, ctx, tool, args, runFunc)
499499diff --git a/src/cmd/go/systemcrypto_test.go b/src/cmd/go/systemcrypto_test.go
500500new file mode 100644
501- index 00000000000000..7335b47c237fd9
501+ index 00000000000000..b6ba8158598a6c
502502--- /dev/null
503503+++ b/src/cmd/go/systemcrypto_test.go
504- @@ -0,0 +1,197 @@
504+ @@ -0,0 +1,249 @@
505505+ // Copyright 2025 The Go Authors. All rights reserved.
506506+ // Use of this source code is governed by a BSD-style
507507+ // license that can be found in the LICENSE file.
508508+
509509+ package main_test
510510+
511511+ import (
512+ + "fmt"
512513+ "internal/testenv"
513514+ "os"
514515+ "path/filepath"
515516+ "runtime"
517+ + "slices"
516518+ "strings"
517519+ "testing"
518520+ )
@@ -594,8 +596,8 @@ index 00000000000000..7335b47c237fd9
594596+ {"linux", "arm", "ms_nocgo_cngcrypto", false}, // cgoless OpenSSL not supported on linux/arm
595597+ {"linux", "amd64", "ms_nocgo_opensslcrypto", true},
596598+ {"linux", "arm64", "ms_nocgo_opensslcrypto", true},
597- + {"darwin", "amd64", "", true}, // cgoless system crypto not supported on darwin/amd64
598- + {"darwin", "arm64", "", true}, // cgoless system crypto not supported on darwin/arm64
599+ + {"darwin", "amd64", "", true},
600+ + {"darwin", "arm64", "", true},
599601+ {"windows", "386", "", false}, // cgoless system crypto not supported on windows/386
600602+ {"windows", "amd64", "", true},
601603+ {"windows", "arm64", "", true},
@@ -608,7 +610,7 @@ index 00000000000000..7335b47c237fd9
608610+ } else {
609611+ tc.goexp += ",systemcrypto"
610612+ }
611- + env := []string{"CGO_ENABLED=0", "GOOS=" + tc.goos, "GOARCH=" + tc.goarch, "GOEXPERIMENT=" + tc.goexp}
613+ + env := []string{"CGO_ENABLED=0", "GOOS=" + tc.goos, "GOARCH=" + tc.goarch, "GOEXPERIMENT=" + tc.goexp, "MS_GO_NOSYSTEMCRYPTO=0" }
612614+ if out, ok := execGoTool(t, true, env, "build", "-o", outPath(t), cryptoFile); ok != tc.succeed {
613615+ if tc.succeed {
614616+ t.Fatalf("expected success, got failure: %s", out)
@@ -644,6 +646,48 @@ index 00000000000000..7335b47c237fd9
644646+ // and presence of system-provided crypto, and it can't be tested here.
645647+ }
646648+
649+ + func TestSystemCryptoDefault(t *testing.T) {
650+ + t.Parallel()
651+ + cryptoFile := writeFile(t, fileWithCrypto)
652+ +
653+ + // Add here all the OS/ARCH combinations that enable systemcrypto by default.
654+ + type testCase struct {
655+ + goos string
656+ + goarch string
657+ + }
658+ + test := []testCase{
659+ + {"linux", "amd64"},
660+ + {"linux", "arm64"},
661+ + {"darwin", "amd64"},
662+ + {"darwin", "arm64"},
663+ + {"windows", "amd64"},
664+ + {"windows", "arm64"},
665+ + }
666+ + for _, tt := range test {
667+ + t.Run(fmt.Sprintf("%s_%s", tt.goos, tt.goarch), func(t *testing.T) {
668+ + t.Parallel()
669+ + out := outPath(t)
670+ + env := []string{"CGO_ENABLED=0", "GOOS=" + tt.goos, "GOARCH=" + tt.goarch, "MS_GO_NOSYSTEMCRYPTO=0"}
671+ + if tt.goos == "linux" {
672+ + // On linux, set ms_nocgo_opensslcrypto to allow cross-compilation without cgo.
673+ + env = append(env, "GOEXPERIMENT=ms_nocgo_opensslcrypto")
674+ + } else {
675+ + // Set a goexperiment in case the Go toolchain has been built with GOEXPERIMENT=nosystemcrypto.
676+ + // In that case, systemcrypto will not be enabled by default unless we pass an explicit GOEXPERIMENT.
677+ + env = append(env, "GOEXPERIMENT=regabi")
678+ +
679+ + }
680+ + execGoTool(t, false, env, "build", "-o", out, cryptoFile)
681+ + // Check that the binary has the correct settings.
682+ + settings, _ := execGoTool(t, false, nil, "version", "-m", out)
683+ + if !strings.Contains(settings, "microsoft_systemcrypto=1") {
684+ + t.Errorf("expected microsoft_systemcrypto=1 in settings, got %v", settings)
685+ + }
686+ + })
687+ + }
688+ +
689+ + }
690+ +
647691+ func TestSystemCryptoSetting(t *testing.T) {
648692+ t.Parallel()
649693+ file := writeFile(t, fileWithCrypto)
@@ -682,6 +726,14 @@ index 00000000000000..7335b47c237fd9
682726+ t.Parallel()
683727+ out := outPath(t)
684728+
729+ + if !slices.ContainsFunc(tt.env, func(r string) bool {
730+ + return strings.HasPrefix(r, "MS_GO_NOSYSTEMCRYPTO=")
731+ + }) {
732+ + // Ensure MS_GO_NOSYSTEMCRYPTO is set to 0 if not specified
733+ + // to avoid interference from the environment.
734+ + tt.env = append(tt.env, "MS_GO_NOSYSTEMCRYPTO=0")
735+ + }
736+ +
685737+ // Build the binary with the specified GOEXPERIMENT.
686738+ _, ok := execGoTool(t, true, tt.env, "build", "-o", out, file)
687739+ if !ok {
@@ -690,10 +742,10 @@ index 00000000000000..7335b47c237fd9
690742+
691743+ // Check that the binary has the correct settings.
692744+ settings, _ := execGoTool(t, false, nil, "version", "-m", out)
693- + hashSetting := strings.Contains(settings, "microsoft_systemcrypto=1")
694- + if tt.enabled && !hashSetting {
745+ + hasSetting := strings.Contains(settings, "microsoft_systemcrypto=1")
746+ + if tt.enabled && !hasSetting {
695747+ t.Errorf("expected microsoft_systemcrypto=1 in settings, got %v", settings)
696- + } else if !tt.enabled && hashSetting {
748+ + } else if !tt.enabled && hasSetting {
697749+ t.Errorf("expected microsoft_systemcrypto=1 not to be in settings, got %v", settings)
698750+ }
699751+ })
@@ -2916,7 +2968,7 @@ index 373efd8319c675..1f245d570092a3 100644
29162968 < crypto/rand
29172969 < crypto/ed25519 # depends on crypto/rand.Reader
29182970diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go
2919- index 0d1e9dd6d1171c..adf26041b0cf89 100644
2971+ index 14ca07c56683f1..64c37df9e9fced 100644
29202972--- a/src/internal/buildcfg/exp.go
29212973+++ b/src/internal/buildcfg/exp.go
29222974@@ -5,12 +5,15 @@
@@ -2935,7 +2987,7 @@ index 0d1e9dd6d1171c..adf26041b0cf89 100644
29352987 )
29362988
29372989 // ExperimentFlags represents a set of GOEXPERIMENT flags relative to a baseline
2938- @@ -194 ,6 +197 ,60 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) {
2990+ @@ -195 ,6 +198 ,60 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) {
29392991 if flags.BoringCrypto {
29402992 return nil, fmt.Errorf("GOEXPERIMENT boringcrypto is not supported in the Microsoft build of Go")
29412993 }
0 commit comments