diff --git a/cryptobackend/backend_test.go b/cryptobackend/backend_test.go index 12b268bd9f..0af5d2dd3c 100644 --- a/cryptobackend/backend_test.go +++ b/cryptobackend/backend_test.go @@ -4,11 +4,18 @@ package backend +//go:generate go test -run ^TestXCryptoDependencyIsSynced$ . -generate + import ( + "bytes" + "encoding/json" + "flag" + "fmt" "go/parser" "go/token" "io/fs" "os" + "os/exec" "path/filepath" "strconv" "strings" @@ -16,6 +23,9 @@ import ( ) const rootImportPath = "github.com/microsoft/go/cryptobackend" +const xCryptoModulePath = "golang.org/x/crypto" + +var generate = flag.Bool("generate", false, "update generated files") // Test that Unreachable panics. func TestUnreachable(t *testing.T) { @@ -118,3 +128,150 @@ func importsPackage(t *testing.T, file, importPath string) bool { } return false } + +func TestXCryptoDependencyIsSynced(t *testing.T) { + root, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + + if *generate { + if err := syncXCryptoDependency(root); err != nil { + t.Fatal(err) + } + return + } + if err := verifyXCryptoDependency(root); err != nil { + t.Fatal(err) + } +} + +func syncXCryptoDependency(root string) error { + xCryptoVersion, err := sourceXCryptoVersion(root) + if err != nil { + return err + } + if err := runGo(root, "mod", "edit", "-require="+xCryptoModulePath+"@"+xCryptoVersion); err != nil { + return err + } + if err := runGo(root, "mod", "tidy"); err != nil { + return err + } + return verifyXCryptoDependency(root) +} + +func verifyXCryptoDependency(root string) error { + xCryptoVersion, err := sourceXCryptoVersion(root) + if err != nil { + return err + } + backendVersion, ok, err := requiredModuleVersion(root, xCryptoModulePath) + if err != nil { + return fmt.Errorf("reading cryptobackend/go.mod: %w", err) + } + if !ok { + return fmt.Errorf("cryptobackend/go.mod does not require %s; run \"go generate\" from cryptobackend", xCryptoModulePath) + } + if backendVersion != xCryptoVersion { + return fmt.Errorf("cryptobackend/go.mod requires %s %s, want %s; run \"go generate\" from cryptobackend", xCryptoModulePath, backendVersion, xCryptoVersion) + } + tidyDiff, err := goModTidyDiff(root) + if err != nil { + return err + } + if tidyDiff != "" { + return fmt.Errorf("cryptobackend module is not tidy; run \"go generate\" from cryptobackend\n%s", tidyDiff) + } + return nil +} + +func sourceXCryptoVersion(root string) (string, error) { + patchPath := filepath.Clean(filepath.Join(root, "..", "patches", "0001-Vendor-external-dependencies.patch")) + data, err := os.ReadFile(patchPath) + if err != nil { + return "", fmt.Errorf("reading %s: %w", patchPath, err) + } + version, ok := requiredModuleVersionFromGoModPatch(data, xCryptoModulePath) + if !ok { + return "", fmt.Errorf("%s does not require %s", patchPath, xCryptoModulePath) + } + return version, nil +} + +func requiredModuleVersionFromGoModPatch(patch []byte, modulePath string) (string, bool) { + inGoMod := false + for line := range strings.SplitSeq(string(patch), "\n") { + if strings.HasPrefix(line, "diff --git ") { + inGoMod = strings.Contains(line, " a/src/go.mod ") + continue + } + if !inGoMod { + continue + } + trimmed := strings.TrimSpace(line) + if !strings.HasPrefix(trimmed, "+") || strings.HasPrefix(trimmed, "+++") { + continue + } + fields := strings.Fields(strings.TrimPrefix(trimmed, "+")) + if len(fields) >= 2 && fields[0] == modulePath { + return fields[1], true + } + } + return "", false +} + +type goModFile struct { + Require []moduleRequirement +} + +type moduleRequirement struct { + Path string + Version string +} + +func requiredModuleVersion(dir, modulePath string) (version string, ok bool, err error) { + data, err := goOutput(dir, "mod", "edit", "-json") + if err != nil { + return "", false, err + } + var goMod goModFile + if err := json.Unmarshal(data, &goMod); err != nil { + return "", false, err + } + for _, require := range goMod.Require { + if require.Path == modulePath { + return require.Version, true, nil + } + } + return "", false, nil +} + +func runGo(dir string, args ...string) error { + _, err := goOutput(dir, args...) + return err +} + +func goModTidyDiff(dir string) (string, error) { + cmd := exec.Command("go", "mod", "tidy", "-diff") + cmd.Dir = dir + var stderr bytes.Buffer + cmd.Stderr = &stderr + out, err := cmd.Output() + if err == nil { + return string(out), nil + } + if len(out) > 0 { + return string(out), nil + } + return "", fmt.Errorf("running go mod tidy -diff in %s: %v\n%s", dir, err, stderr.String()) +} + +func goOutput(dir string, args ...string) ([]byte, error) { + cmd := exec.Command("go", args...) + cmd.Dir = dir + out, err := cmd.CombinedOutput() + if err != nil { + return nil, fmt.Errorf("running go %s in %s: %v\n%s", strings.Join(args, " "), dir, err, out) + } + return out, nil +} diff --git a/cryptobackend/dsa/dsa_darwin.go b/cryptobackend/dsa/dsa_darwin.go index 0654c1962d..36db87c344 100644 --- a/cryptobackend/dsa/dsa_darwin.go +++ b/cryptobackend/dsa/dsa_darwin.go @@ -17,9 +17,9 @@ func GenerateParameters(l, n int) (p, q, g BigInt, err error) { panic("cryptobac func GenerateKey(p, q, g BigInt) (x, y BigInt, err error) { panic("cryptobackend: not available") } func NewPrivateKey(p, q, g, x, y BigInt) (*PrivateKey, error) { panic("cryptobackend: not available") } func NewPublicKey(p, q, g, y BigInt) (*PublicKey, error) { panic("cryptobackend: not available") } -func Sign(priv *PrivateKey, hash []byte, parseSignature func([]byte) (BigInt, BigInt, error)) (r, s BigInt, err error) { +func Sign(priv *PrivateKey, hash []byte) (r, s BigInt, err error) { panic("cryptobackend: not available") } -func Verify(pub *PublicKey, hashed []byte, r, s BigInt, encodeSignature func(r, s BigInt) ([]byte, error)) bool { +func Verify(pub *PublicKey, hashed []byte, r, s BigInt) bool { panic("cryptobackend: not available") } diff --git a/cryptobackend/dsa/dsa_linux.go b/cryptobackend/dsa/dsa_linux.go index e6d47ef708..b4f281495b 100644 --- a/cryptobackend/dsa/dsa_linux.go +++ b/cryptobackend/dsa/dsa_linux.go @@ -6,7 +6,15 @@ package dsa -import "github.com/microsoft/go-crypto-openssl/openssl" +import ( + "errors" + "math/big" + + "github.com/microsoft/go-crypto-openssl/openssl" + "github.com/microsoft/go/cryptobackend/bbig" + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" +) type BigInt = openssl.BigInt type PrivateKey = openssl.PrivateKeyDSA @@ -26,21 +34,60 @@ func NewPrivateKey(p, q, g, x, y BigInt) (*PrivateKey, error) { func NewPublicKey(p, q, g, y BigInt) (*PublicKey, error) { return openssl.NewPublicKeyDSA(openssl.DSAParameters{P: p, Q: q, G: g}, y) } -func Sign(priv *PrivateKey, hash []byte, parseSignature func([]byte) (BigInt, BigInt, error)) (r, s BigInt, err error) { +func Sign(priv *PrivateKey, hash []byte) (r, s BigInt, err error) { sig, err := openssl.SignDSA(priv, hash) if err != nil { return nil, nil, err } - r, s, err = parseSignature(sig) - if err != nil { - return nil, nil, err - } - return BigInt(r), BigInt(s), nil + return parseSignature(sig) } -func Verify(pub *PublicKey, hashed []byte, r, s BigInt, encodeSignature func(r, s BigInt) ([]byte, error)) bool { +func Verify(pub *PublicKey, hashed []byte, r, s BigInt) bool { sig, err := encodeSignature(r, s) if err != nil { return false } return openssl.VerifyDSA(pub, hashed, sig) } + +func parseSignature(sig []byte) (BigInt, BigInt, error) { + var r, s []byte + var inner cryptobyte.String + input := cryptobyte.String(sig) + if !input.ReadASN1(&inner, asn1.SEQUENCE) || + !input.Empty() || + !inner.ReadASN1Integer(&r) || + !inner.ReadASN1Integer(&s) || + !inner.Empty() { + return nil, nil, errors.New("invalid ASN.1") + } + return bbig.Enc(new(big.Int).SetBytes(r)), bbig.Enc(new(big.Int).SetBytes(s)), nil +} + +func encodeSignature(r, s BigInt) ([]byte, error) { + rb, sb := bbig.Dec(r), bbig.Dec(s) + if rb == nil || rb.Sign() <= 0 || sb == nil || sb.Sign() <= 0 { + return nil, errors.New("invalid integer") + } + var b cryptobyte.Builder + b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + addASN1IntBytes(b, rb.Bytes()) + addASN1IntBytes(b, sb.Bytes()) + }) + return b.Bytes() +} + +func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) { + for len(bytes) > 0 && bytes[0] == 0 { + bytes = bytes[1:] + } + if len(bytes) == 0 { + b.SetError(errors.New("invalid integer")) + return + } + b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) { + if bytes[0]&0x80 != 0 { + c.AddUint8(0) + } + c.AddBytes(bytes) + }) +} diff --git a/cryptobackend/dsa/dsa_windows.go b/cryptobackend/dsa/dsa_windows.go index 30f19c4dfa..181d015ef1 100644 --- a/cryptobackend/dsa/dsa_windows.go +++ b/cryptobackend/dsa/dsa_windows.go @@ -29,9 +29,9 @@ func NewPrivateKey(p, q, g, x, y BigInt) (*PrivateKey, error) { func NewPublicKey(p, q, g, y BigInt) (*PublicKey, error) { return cng.NewPublicKeyDSA(cng.DSAParameters{P: p, Q: q, G: g}, y) } -func Sign(priv *PrivateKey, hash []byte, parseSignature func([]byte) (BigInt, BigInt, error)) (r, s BigInt, err error) { +func Sign(priv *PrivateKey, hash []byte) (r, s BigInt, err error) { return cng.SignDSA(priv, hash) } -func Verify(pub *PublicKey, hashed []byte, r, s BigInt, encodeSignature func(r, s BigInt) ([]byte, error)) bool { +func Verify(pub *PublicKey, hashed []byte, r, s BigInt) bool { return cng.VerifyDSA(pub, hashed, r, s) } diff --git a/cryptobackend/dsa/nobackend.go b/cryptobackend/dsa/nobackend.go index 0dba0c2a39..5a3d7ed932 100644 --- a/cryptobackend/dsa/nobackend.go +++ b/cryptobackend/dsa/nobackend.go @@ -15,9 +15,9 @@ func GenerateParameters(l, n int) (p, q, g BigInt, err error) { panic("cryptobac func GenerateKey(p, q, g BigInt) (x, y BigInt, err error) { panic("cryptobackend: not available") } func NewPrivateKey(p, q, g, x, y BigInt) (*PrivateKey, error) { panic("cryptobackend: not available") } func NewPublicKey(p, q, g, y BigInt) (*PublicKey, error) { panic("cryptobackend: not available") } -func Sign(priv *PrivateKey, hash []byte, parseSignature func([]byte) (BigInt, BigInt, error)) (r, s BigInt, err error) { +func Sign(priv *PrivateKey, hash []byte) (r, s BigInt, err error) { panic("cryptobackend: not available") } -func Verify(pub *PublicKey, hashed []byte, r, s BigInt, encodeSignature func(r, s BigInt) ([]byte, error)) bool { +func Verify(pub *PublicKey, hashed []byte, r, s BigInt) bool { panic("cryptobackend: not available") } diff --git a/cryptobackend/ecdsa/ecdsa_darwin.go b/cryptobackend/ecdsa/ecdsa_darwin.go index 80d4dcb6ef..2bce40cb49 100644 --- a/cryptobackend/ecdsa/ecdsa_darwin.go +++ b/cryptobackend/ecdsa/ecdsa_darwin.go @@ -6,11 +6,7 @@ package ecdsa -import ( - "errors" - - "github.com/microsoft/go-crypto-darwin/xcrypto" -) +import "github.com/microsoft/go-crypto-darwin/xcrypto" type BigInt = xcrypto.BigInt type PrivateKey = xcrypto.PrivateKeyECDSA @@ -34,10 +30,6 @@ func NewPublicKey(curve string, X, Y BigInt) (*PublicKey, error) { return xcrypto.NewPublicKeyECDSA(curve, X, Y) } -func Sign(priv *PrivateKey, hash []byte) (r, s []byte, err error) { - return nil, nil, errors.ErrUnsupported -} - func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { return xcrypto.SignMarshalECDSA(priv, hash) } @@ -45,7 +37,3 @@ func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { func VerifyASN1(pub *PublicKey, hash, sig []byte) (bool, error) { return xcrypto.VerifyECDSA(pub, hash, sig), nil } - -func Verify(pub *PublicKey, hash, r, s []byte) (bool, error) { - return false, errors.ErrUnsupported -} diff --git a/cryptobackend/ecdsa/ecdsa_linux.go b/cryptobackend/ecdsa/ecdsa_linux.go index bf9978d2d4..5781c3280d 100644 --- a/cryptobackend/ecdsa/ecdsa_linux.go +++ b/cryptobackend/ecdsa/ecdsa_linux.go @@ -6,11 +6,7 @@ package ecdsa -import ( - "errors" - - "github.com/microsoft/go-crypto-openssl/openssl" -) +import "github.com/microsoft/go-crypto-openssl/openssl" type BigInt = openssl.BigInt type PrivateKey = openssl.PrivateKeyECDSA @@ -28,10 +24,6 @@ func NewPublicKey(curve string, X, Y BigInt) (*PublicKey, error) { return openssl.NewPublicKeyECDSA(curve, X, Y) } -func Sign(priv *PrivateKey, hash []byte) (r, s []byte, err error) { - return nil, nil, errors.ErrUnsupported -} - func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { return openssl.SignMarshalECDSA(priv, hash) } @@ -39,7 +31,3 @@ func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { func VerifyASN1(pub *PublicKey, hash, sig []byte) (bool, error) { return openssl.VerifyECDSA(pub, hash, sig), nil } - -func Verify(pub *PublicKey, hash, r, s []byte) (bool, error) { - return false, errors.ErrUnsupported -} diff --git a/cryptobackend/ecdsa/ecdsa_windows.go b/cryptobackend/ecdsa/ecdsa_windows.go index 6a282cd4eb..6c5c85197a 100644 --- a/cryptobackend/ecdsa/ecdsa_windows.go +++ b/cryptobackend/ecdsa/ecdsa_windows.go @@ -10,6 +10,8 @@ import ( "errors" "github.com/microsoft/go-crypto-winnative/cng" + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" ) type BigInt = cng.BigInt @@ -34,18 +36,56 @@ func NewPublicKey(curve string, X, Y BigInt) (*PublicKey, error) { return cng.NewPublicKeyECDSA(curve, X, Y) } -func Sign(priv *PrivateKey, hash []byte) (r, s []byte, err error) { - return cng.SignECDSA(priv, hash) -} - func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { - return nil, errors.ErrUnsupported + r, s, err := cng.SignECDSA(priv, hash) + if err != nil { + return nil, err + } + return encodeSignature(r, s) } func VerifyASN1(pub *PublicKey, hash, sig []byte) (bool, error) { - return false, errors.ErrUnsupported + r, s, err := parseSignature(sig) + if err != nil { + return false, err + } + return cng.VerifyECDSA(pub, hash, cng.BigInt(r), cng.BigInt(s)), nil } -func Verify(pub *PublicKey, hash, r, s []byte) (bool, error) { - return cng.VerifyECDSA(pub, hash, cng.BigInt(r), cng.BigInt(s)), nil +func encodeSignature(r, s []byte) ([]byte, error) { + var b cryptobyte.Builder + b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + addASN1IntBytes(b, r) + addASN1IntBytes(b, s) + }) + return b.Bytes() +} + +func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) { + for len(bytes) > 0 && bytes[0] == 0 { + bytes = bytes[1:] + } + if len(bytes) == 0 { + b.SetError(errors.New("invalid integer")) + return + } + b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) { + if bytes[0]&0x80 != 0 { + c.AddUint8(0) + } + c.AddBytes(bytes) + }) +} + +func parseSignature(sig []byte) (r, s []byte, err error) { + var inner cryptobyte.String + input := cryptobyte.String(sig) + if !input.ReadASN1(&inner, asn1.SEQUENCE) || + !input.Empty() || + !inner.ReadASN1Integer(&r) || + !inner.ReadASN1Integer(&s) || + !inner.Empty() { + return nil, nil, errors.New("invalid ASN.1") + } + return r, s, nil } diff --git a/cryptobackend/ecdsa/nobackend.go b/cryptobackend/ecdsa/nobackend.go index 9698c57e46..984ceac404 100644 --- a/cryptobackend/ecdsa/nobackend.go +++ b/cryptobackend/ecdsa/nobackend.go @@ -18,15 +18,9 @@ func NewPrivateKey(curve string, X, Y, D BigInt) (*PrivateKey, error) { func NewPublicKey(curve string, X, Y BigInt) (*PublicKey, error) { panic("cryptobackend: not available") } -func Sign(priv *PrivateKey, hash []byte) (r, s []byte, err error) { - panic("cryptobackend: not available") -} func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { panic("cryptobackend: not available") } func VerifyASN1(pub *PublicKey, hash, sig []byte) (bool, error) { panic("cryptobackend: not available") } -func Verify(pub *PublicKey, hash, r, s []byte) (bool, error) { - panic("cryptobackend: not available") -} diff --git a/cryptobackend/go.mod b/cryptobackend/go.mod index 09a0c9b5d7..e9aa07a7a6 100644 --- a/cryptobackend/go.mod +++ b/cryptobackend/go.mod @@ -6,4 +6,5 @@ require ( github.com/microsoft/go-crypto-darwin v0.0.3-0.20260606063346-8a6eda5eab53 github.com/microsoft/go-crypto-openssl v0.5.0 github.com/microsoft/go-crypto-winnative v0.0.0-20260605073512-713d2add0825 + golang.org/x/crypto v0.52.1-0.20260526024921-9beb694f9766 ) diff --git a/cryptobackend/go.sum b/cryptobackend/go.sum index 6fe40ce3a0..6ef447a631 100644 --- a/cryptobackend/go.sum +++ b/cryptobackend/go.sum @@ -4,3 +4,5 @@ github.com/microsoft/go-crypto-openssl v0.5.0 h1:wTcBB5QN4YtsKcZdqWojL5pWIF/P+PV github.com/microsoft/go-crypto-openssl v0.5.0/go.mod h1:gJrjX+yWGi9pkbfPVDDh+ZbgjtQoRSXHjb/ZyjwKk34= github.com/microsoft/go-crypto-winnative v0.0.0-20260605073512-713d2add0825 h1:nmQ1K/L5GISW8UwbUwE376h3WXREEpREFdc3fNklcXc= github.com/microsoft/go-crypto-winnative v0.0.0-20260605073512-713d2add0825/go.mod h1:a1Z07CJIuWa8WT/pzFIGNTTKS96s8o1B1TPOziAHUxw= +golang.org/x/crypto v0.52.1-0.20260526024921-9beb694f9766 h1:ABD+jVg0H4Hwu2sGcUtKeb3T8mlS+jS3uWrkTAPcXjs= +golang.org/x/crypto v0.52.1-0.20260526024921-9beb694f9766/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= diff --git a/cryptobackend/rsa/rsa_darwin.go b/cryptobackend/rsa/rsa_darwin.go index 22ca259a18..b932d97b59 100644 --- a/cryptobackend/rsa/rsa_darwin.go +++ b/cryptobackend/rsa/rsa_darwin.go @@ -8,10 +8,15 @@ package rsa import ( "crypto" + "errors" "hash" - _ "unsafe" + "math/big" "github.com/microsoft/go-crypto-darwin/xcrypto" + "github.com/microsoft/go/cryptobackend/bbig" + + "golang.org/x/crypto/cryptobyte" + "golang.org/x/crypto/cryptobyte/asn1" ) type BigInt = xcrypto.BigInt @@ -33,14 +38,59 @@ func SupportsPKCS1v15Signature(h crypto.Hash) bool { func SupportsPSSHash(h crypto.Hash) bool { return xcrypto.SupportsHash(h) } -//go:linkname decodeKey crypto/rsa.decodeKey -func decodeKey(data []byte) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) +func decodeKey(data []byte) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { + bad := func(e error) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { + return nil, nil, nil, nil, nil, nil, nil, nil, e + } + input := cryptobyte.String(data) + var seq cryptobyte.String + var version int + n, e, d, p, q, dp, dq, qinv := new(big.Int), new(big.Int), new(big.Int), new(big.Int), + new(big.Int), new(big.Int), new(big.Int), new(big.Int) + if !input.ReadASN1(&seq, asn1.SEQUENCE) { + return bad(errors.New("invalid ASN.1 structure: not a sequence")) + } + if !input.Empty() { + return bad(errors.New("invalid ASN.1 structure: trailing data")) + } + if !seq.ReadASN1Integer(&version) || version != 0 { + return bad(errors.New("invalid ASN.1 structure: unsupported version")) + } + if !seq.ReadASN1Integer(n) || !seq.ReadASN1Integer(e) || + !seq.ReadASN1Integer(d) || !seq.ReadASN1Integer(p) || + !seq.ReadASN1Integer(q) || !seq.ReadASN1Integer(dp) || + !seq.ReadASN1Integer(dq) || !seq.ReadASN1Integer(qinv) || + !seq.Empty() { + return bad(errors.New("invalid ASN.1 structure")) + } + return bbig.Enc(n), bbig.Enc(e), bbig.Enc(d), bbig.Enc(p), bbig.Enc(q), + bbig.Enc(dp), bbig.Enc(dq), bbig.Enc(qinv), nil +} -//go:linkname encodeKey crypto/rsa.encodeKey -func encodeKey(N, E, D, P, Q, Dp, Dq, Qinv BigInt) ([]byte, error) +func encodeKey(N, E, D, P, Q, Dp, Dq, Qinv BigInt) ([]byte, error) { + builder := cryptobyte.NewBuilder(nil) + builder.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1Int64(0) + b.AddASN1BigInt(bbig.Dec(N)) + b.AddASN1BigInt(bbig.Dec(E)) + b.AddASN1BigInt(bbig.Dec(D)) + b.AddASN1BigInt(bbig.Dec(P)) + b.AddASN1BigInt(bbig.Dec(Q)) + b.AddASN1BigInt(bbig.Dec(Dp)) + b.AddASN1BigInt(bbig.Dec(Dq)) + b.AddASN1BigInt(bbig.Dec(Qinv)) + }) + return builder.Bytes() +} -//go:linkname encodePublicKey crypto/rsa.encodePublicKey -func encodePublicKey(N, E BigInt) ([]byte, error) +func encodePublicKey(N, E BigInt) ([]byte, error) { + builder := cryptobyte.NewBuilder(nil) + builder.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { + b.AddASN1BigInt(bbig.Dec(N)) + b.AddASN1BigInt(bbig.Dec(E)) + }) + return builder.Bytes() +} func GenerateKey(bits int) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { data, err := xcrypto.GenerateKeyRSA(bits) diff --git a/patches/0001-Vendor-external-dependencies.patch b/patches/0001-Vendor-external-dependencies.patch index c9792b7408..88376a30e9 100644 --- a/patches/0001-Vendor-external-dependencies.patch +++ b/patches/0001-Vendor-external-dependencies.patch @@ -307,7 +307,7 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../go/cryptobackend/drbg/rand_linux.go | 19 + .../go/cryptobackend/drbg/rand_windows.go | 19 + .../go/cryptobackend/dsa/dsa_darwin.go | 25 + - .../go/cryptobackend/dsa/dsa_linux.go | 46 + + .../go/cryptobackend/dsa/dsa_linux.go | 93 + .../go/cryptobackend/dsa/dsa_windows.go | 37 + .../microsoft/go/cryptobackend/dsa/init.go | 7 + .../go/cryptobackend/dsa/nobackend.go | 23 + @@ -316,11 +316,11 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../go/cryptobackend/ecdh/ecdh_windows.go | 32 + .../microsoft/go/cryptobackend/ecdh/init.go | 7 + .../go/cryptobackend/ecdh/nobackend.go | 22 + - .../go/cryptobackend/ecdsa/ecdsa_darwin.go | 51 + - .../go/cryptobackend/ecdsa/ecdsa_linux.go | 45 + - .../go/cryptobackend/ecdsa/ecdsa_windows.go | 51 + + .../go/cryptobackend/ecdsa/ecdsa_darwin.go | 39 + + .../go/cryptobackend/ecdsa/ecdsa_linux.go | 33 + + .../go/cryptobackend/ecdsa/ecdsa_windows.go | 91 + .../microsoft/go/cryptobackend/ecdsa/init.go | 7 + - .../go/cryptobackend/ecdsa/nobackend.go | 32 + + .../go/cryptobackend/ecdsa/nobackend.go | 26 + .../cryptobackend/ed25519/ed25519_darwin.go | 24 + .../go/cryptobackend/ed25519/ed25519_linux.go | 24 + .../cryptobackend/ed25519/ed25519_windows.go | 21 + @@ -384,7 +384,7 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../go/cryptobackend/rc4/rc4_windows.go | 15 + .../microsoft/go/cryptobackend/rsa/init.go | 7 + .../go/cryptobackend/rsa/nobackend.go | 61 + - .../go/cryptobackend/rsa/rsa_darwin.go | 100 + + .../go/cryptobackend/rsa/rsa_darwin.go | 150 + .../go/cryptobackend/rsa/rsa_linux.go | 85 + .../go/cryptobackend/rsa/rsa_windows.go | 77 + .../microsoft/go/cryptobackend/sha1/init.go | 7 + @@ -419,7 +419,7 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../go/cryptobackend/tls13/tls13_linux.go | 18 + .../go/cryptobackend/tls13/tls13_windows.go | 14 + src/vendor/modules.txt | 55 + - 411 files changed, 39323 insertions(+), 11 deletions(-) + 411 files changed, 39430 insertions(+), 11 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 @@ -41451,7 +41451,7 @@ index 00000000000000..e1e2192cdf5b6d +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/dsa/dsa_darwin.go b/src/vendor/github.com/microsoft/go/cryptobackend/dsa/dsa_darwin.go new file mode 100644 -index 00000000000000..0654c1962dd371 +index 00000000000000..36db87c344ad67 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/dsa/dsa_darwin.go @@ -0,0 +1,25 @@ @@ -41474,18 +41474,18 @@ index 00000000000000..0654c1962dd371 +func GenerateKey(p, q, g BigInt) (x, y BigInt, err error) { panic("cryptobackend: not available") } +func NewPrivateKey(p, q, g, x, y BigInt) (*PrivateKey, error) { panic("cryptobackend: not available") } +func NewPublicKey(p, q, g, y BigInt) (*PublicKey, error) { panic("cryptobackend: not available") } -+func Sign(priv *PrivateKey, hash []byte, parseSignature func([]byte) (BigInt, BigInt, error)) (r, s BigInt, err error) { ++func Sign(priv *PrivateKey, hash []byte) (r, s BigInt, err error) { + panic("cryptobackend: not available") +} -+func Verify(pub *PublicKey, hashed []byte, r, s BigInt, encodeSignature func(r, s BigInt) ([]byte, error)) bool { ++func Verify(pub *PublicKey, hashed []byte, r, s BigInt) bool { + panic("cryptobackend: not available") +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/dsa/dsa_linux.go b/src/vendor/github.com/microsoft/go/cryptobackend/dsa/dsa_linux.go new file mode 100644 -index 00000000000000..e6d47ef708758b +index 00000000000000..b4f281495b2713 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/dsa/dsa_linux.go -@@ -0,0 +1,46 @@ +@@ -0,0 +1,93 @@ +// 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. @@ -41494,7 +41494,15 @@ index 00000000000000..e6d47ef708758b + +package dsa + -+import "github.com/microsoft/go-crypto-openssl/openssl" ++import ( ++ "errors" ++ "math/big" ++ ++ "github.com/microsoft/go-crypto-openssl/openssl" ++ "github.com/microsoft/go/cryptobackend/bbig" ++ "golang.org/x/crypto/cryptobyte" ++ "golang.org/x/crypto/cryptobyte/asn1" ++) + +type BigInt = openssl.BigInt +type PrivateKey = openssl.PrivateKeyDSA @@ -41514,27 +41522,66 @@ index 00000000000000..e6d47ef708758b +func NewPublicKey(p, q, g, y BigInt) (*PublicKey, error) { + return openssl.NewPublicKeyDSA(openssl.DSAParameters{P: p, Q: q, G: g}, y) +} -+func Sign(priv *PrivateKey, hash []byte, parseSignature func([]byte) (BigInt, BigInt, error)) (r, s BigInt, err error) { ++func Sign(priv *PrivateKey, hash []byte) (r, s BigInt, err error) { + sig, err := openssl.SignDSA(priv, hash) + if err != nil { + return nil, nil, err + } -+ r, s, err = parseSignature(sig) -+ if err != nil { -+ return nil, nil, err -+ } -+ return BigInt(r), BigInt(s), nil ++ return parseSignature(sig) +} -+func Verify(pub *PublicKey, hashed []byte, r, s BigInt, encodeSignature func(r, s BigInt) ([]byte, error)) bool { ++func Verify(pub *PublicKey, hashed []byte, r, s BigInt) bool { + sig, err := encodeSignature(r, s) + if err != nil { + return false + } + return openssl.VerifyDSA(pub, hashed, sig) +} ++ ++func parseSignature(sig []byte) (BigInt, BigInt, error) { ++ var r, s []byte ++ var inner cryptobyte.String ++ input := cryptobyte.String(sig) ++ if !input.ReadASN1(&inner, asn1.SEQUENCE) || ++ !input.Empty() || ++ !inner.ReadASN1Integer(&r) || ++ !inner.ReadASN1Integer(&s) || ++ !inner.Empty() { ++ return nil, nil, errors.New("invalid ASN.1") ++ } ++ return bbig.Enc(new(big.Int).SetBytes(r)), bbig.Enc(new(big.Int).SetBytes(s)), nil ++} ++ ++func encodeSignature(r, s BigInt) ([]byte, error) { ++ rb, sb := bbig.Dec(r), bbig.Dec(s) ++ if rb == nil || rb.Sign() <= 0 || sb == nil || sb.Sign() <= 0 { ++ return nil, errors.New("invalid integer") ++ } ++ var b cryptobyte.Builder ++ b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { ++ addASN1IntBytes(b, rb.Bytes()) ++ addASN1IntBytes(b, sb.Bytes()) ++ }) ++ return b.Bytes() ++} ++ ++func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) { ++ for len(bytes) > 0 && bytes[0] == 0 { ++ bytes = bytes[1:] ++ } ++ if len(bytes) == 0 { ++ b.SetError(errors.New("invalid integer")) ++ return ++ } ++ b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) { ++ if bytes[0]&0x80 != 0 { ++ c.AddUint8(0) ++ } ++ c.AddBytes(bytes) ++ }) ++} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/dsa/dsa_windows.go b/src/vendor/github.com/microsoft/go/cryptobackend/dsa/dsa_windows.go new file mode 100644 -index 00000000000000..30f19c4dfa4c92 +index 00000000000000..181d015ef11058 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/dsa/dsa_windows.go @@ -0,0 +1,37 @@ @@ -41569,10 +41616,10 @@ index 00000000000000..30f19c4dfa4c92 +func NewPublicKey(p, q, g, y BigInt) (*PublicKey, error) { + return cng.NewPublicKeyDSA(cng.DSAParameters{P: p, Q: q, G: g}, y) +} -+func Sign(priv *PrivateKey, hash []byte, parseSignature func([]byte) (BigInt, BigInt, error)) (r, s BigInt, err error) { ++func Sign(priv *PrivateKey, hash []byte) (r, s BigInt, err error) { + return cng.SignDSA(priv, hash) +} -+func Verify(pub *PublicKey, hashed []byte, r, s BigInt, encodeSignature func(r, s BigInt) ([]byte, error)) bool { ++func Verify(pub *PublicKey, hashed []byte, r, s BigInt) bool { + return cng.VerifyDSA(pub, hashed, r, s) +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/dsa/init.go b/src/vendor/github.com/microsoft/go/cryptobackend/dsa/init.go @@ -41590,7 +41637,7 @@ index 00000000000000..198bc973ae790c +import _ "github.com/microsoft/go/cryptobackend" diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/dsa/nobackend.go b/src/vendor/github.com/microsoft/go/cryptobackend/dsa/nobackend.go new file mode 100644 -index 00000000000000..0dba0c2a39d8a5 +index 00000000000000..5a3d7ed9322674 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/dsa/nobackend.go @@ -0,0 +1,23 @@ @@ -41611,10 +41658,10 @@ index 00000000000000..0dba0c2a39d8a5 +func GenerateKey(p, q, g BigInt) (x, y BigInt, err error) { panic("cryptobackend: not available") } +func NewPrivateKey(p, q, g, x, y BigInt) (*PrivateKey, error) { panic("cryptobackend: not available") } +func NewPublicKey(p, q, g, y BigInt) (*PublicKey, error) { panic("cryptobackend: not available") } -+func Sign(priv *PrivateKey, hash []byte, parseSignature func([]byte) (BigInt, BigInt, error)) (r, s BigInt, err error) { ++func Sign(priv *PrivateKey, hash []byte) (r, s BigInt, err error) { + panic("cryptobackend: not available") +} -+func Verify(pub *PublicKey, hashed []byte, r, s BigInt, encodeSignature func(r, s BigInt) ([]byte, error)) bool { ++func Verify(pub *PublicKey, hashed []byte, r, s BigInt) bool { + panic("cryptobackend: not available") +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/ecdh/ecdh_darwin.go b/src/vendor/github.com/microsoft/go/cryptobackend/ecdh/ecdh_darwin.go @@ -41768,10 +41815,10 @@ index 00000000000000..e168a1b84d7532 +func ECDH(priv *PrivateKey, pub *PublicKey) ([]byte, error) { panic("cryptobackend: not available") } diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/ecdsa_darwin.go b/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/ecdsa_darwin.go new file mode 100644 -index 00000000000000..80d4dcb6ef577f +index 00000000000000..2bce40cb490cdb --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/ecdsa_darwin.go -@@ -0,0 +1,51 @@ +@@ -0,0 +1,39 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -41780,11 +41827,7 @@ index 00000000000000..80d4dcb6ef577f + +package ecdsa + -+import ( -+ "errors" -+ -+ "github.com/microsoft/go-crypto-darwin/xcrypto" -+) ++import "github.com/microsoft/go-crypto-darwin/xcrypto" + +type BigInt = xcrypto.BigInt +type PrivateKey = xcrypto.PrivateKeyECDSA @@ -41808,10 +41851,6 @@ index 00000000000000..80d4dcb6ef577f + return xcrypto.NewPublicKeyECDSA(curve, X, Y) +} + -+func Sign(priv *PrivateKey, hash []byte) (r, s []byte, err error) { -+ return nil, nil, errors.ErrUnsupported -+} -+ +func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { + return xcrypto.SignMarshalECDSA(priv, hash) +} @@ -41819,16 +41858,12 @@ index 00000000000000..80d4dcb6ef577f +func VerifyASN1(pub *PublicKey, hash, sig []byte) (bool, error) { + return xcrypto.VerifyECDSA(pub, hash, sig), nil +} -+ -+func Verify(pub *PublicKey, hash, r, s []byte) (bool, error) { -+ return false, errors.ErrUnsupported -+} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/ecdsa_linux.go b/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/ecdsa_linux.go new file mode 100644 -index 00000000000000..bf9978d2d4c68e +index 00000000000000..5781c3280d6c78 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/ecdsa_linux.go -@@ -0,0 +1,45 @@ +@@ -0,0 +1,33 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -41837,11 +41872,7 @@ index 00000000000000..bf9978d2d4c68e + +package ecdsa + -+import ( -+ "errors" -+ -+ "github.com/microsoft/go-crypto-openssl/openssl" -+) ++import "github.com/microsoft/go-crypto-openssl/openssl" + +type BigInt = openssl.BigInt +type PrivateKey = openssl.PrivateKeyECDSA @@ -41859,10 +41890,6 @@ index 00000000000000..bf9978d2d4c68e + return openssl.NewPublicKeyECDSA(curve, X, Y) +} + -+func Sign(priv *PrivateKey, hash []byte) (r, s []byte, err error) { -+ return nil, nil, errors.ErrUnsupported -+} -+ +func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { + return openssl.SignMarshalECDSA(priv, hash) +} @@ -41870,16 +41897,12 @@ index 00000000000000..bf9978d2d4c68e +func VerifyASN1(pub *PublicKey, hash, sig []byte) (bool, error) { + return openssl.VerifyECDSA(pub, hash, sig), nil +} -+ -+func Verify(pub *PublicKey, hash, r, s []byte) (bool, error) { -+ return false, errors.ErrUnsupported -+} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/ecdsa_windows.go b/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/ecdsa_windows.go new file mode 100644 -index 00000000000000..6a282cd4eb7ed5 +index 00000000000000..6c5c85197a6a07 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/ecdsa_windows.go -@@ -0,0 +1,51 @@ +@@ -0,0 +1,91 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -41892,6 +41915,8 @@ index 00000000000000..6a282cd4eb7ed5 + "errors" + + "github.com/microsoft/go-crypto-winnative/cng" ++ "golang.org/x/crypto/cryptobyte" ++ "golang.org/x/crypto/cryptobyte/asn1" +) + +type BigInt = cng.BigInt @@ -41916,20 +41941,58 @@ index 00000000000000..6a282cd4eb7ed5 + return cng.NewPublicKeyECDSA(curve, X, Y) +} + -+func Sign(priv *PrivateKey, hash []byte) (r, s []byte, err error) { -+ return cng.SignECDSA(priv, hash) -+} -+ +func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { -+ return nil, errors.ErrUnsupported ++ r, s, err := cng.SignECDSA(priv, hash) ++ if err != nil { ++ return nil, err ++ } ++ return encodeSignature(r, s) +} + +func VerifyASN1(pub *PublicKey, hash, sig []byte) (bool, error) { -+ return false, errors.ErrUnsupported ++ r, s, err := parseSignature(sig) ++ if err != nil { ++ return false, err ++ } ++ return cng.VerifyECDSA(pub, hash, cng.BigInt(r), cng.BigInt(s)), nil +} + -+func Verify(pub *PublicKey, hash, r, s []byte) (bool, error) { -+ return cng.VerifyECDSA(pub, hash, cng.BigInt(r), cng.BigInt(s)), nil ++func encodeSignature(r, s []byte) ([]byte, error) { ++ var b cryptobyte.Builder ++ b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { ++ addASN1IntBytes(b, r) ++ addASN1IntBytes(b, s) ++ }) ++ return b.Bytes() ++} ++ ++func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) { ++ for len(bytes) > 0 && bytes[0] == 0 { ++ bytes = bytes[1:] ++ } ++ if len(bytes) == 0 { ++ b.SetError(errors.New("invalid integer")) ++ return ++ } ++ b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) { ++ if bytes[0]&0x80 != 0 { ++ c.AddUint8(0) ++ } ++ c.AddBytes(bytes) ++ }) ++} ++ ++func parseSignature(sig []byte) (r, s []byte, err error) { ++ var inner cryptobyte.String ++ input := cryptobyte.String(sig) ++ if !input.ReadASN1(&inner, asn1.SEQUENCE) || ++ !input.Empty() || ++ !inner.ReadASN1Integer(&r) || ++ !inner.ReadASN1Integer(&s) || ++ !inner.Empty() { ++ return nil, nil, errors.New("invalid ASN.1") ++ } ++ return r, s, nil +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/init.go b/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/init.go new file mode 100644 @@ -41946,10 +42009,10 @@ index 00000000000000..9d257ffe06362e +import _ "github.com/microsoft/go/cryptobackend" diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/nobackend.go b/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/nobackend.go new file mode 100644 -index 00000000000000..9698c57e46aa79 +index 00000000000000..984ceac4040ee3 --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/ecdsa/nobackend.go -@@ -0,0 +1,32 @@ +@@ -0,0 +1,26 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -41970,18 +42033,12 @@ index 00000000000000..9698c57e46aa79 +func NewPublicKey(curve string, X, Y BigInt) (*PublicKey, error) { + panic("cryptobackend: not available") +} -+func Sign(priv *PrivateKey, hash []byte) (r, s []byte, err error) { -+ panic("cryptobackend: not available") -+} +func SignASN1(priv *PrivateKey, hash []byte) ([]byte, error) { + panic("cryptobackend: not available") +} +func VerifyASN1(pub *PublicKey, hash, sig []byte) (bool, error) { + panic("cryptobackend: not available") +} -+func Verify(pub *PublicKey, hash, r, s []byte) (bool, error) { -+ panic("cryptobackend: not available") -+} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/ed25519/ed25519_darwin.go b/src/vendor/github.com/microsoft/go/cryptobackend/ed25519/ed25519_darwin.go new file mode 100644 index 00000000000000..339ad263058c45 @@ -43636,10 +43693,10 @@ index 00000000000000..0ea9f01be8ec8c +} diff --git a/src/vendor/github.com/microsoft/go/cryptobackend/rsa/rsa_darwin.go b/src/vendor/github.com/microsoft/go/cryptobackend/rsa/rsa_darwin.go new file mode 100644 -index 00000000000000..22ca259a1833bf +index 00000000000000..b932d97b59d71a --- /dev/null +++ b/src/vendor/github.com/microsoft/go/cryptobackend/rsa/rsa_darwin.go -@@ -0,0 +1,100 @@ +@@ -0,0 +1,150 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. @@ -43650,10 +43707,15 @@ index 00000000000000..22ca259a1833bf + +import ( + "crypto" ++ "errors" + "hash" -+ _ "unsafe" ++ "math/big" + + "github.com/microsoft/go-crypto-darwin/xcrypto" ++ "github.com/microsoft/go/cryptobackend/bbig" ++ ++ "golang.org/x/crypto/cryptobyte" ++ "golang.org/x/crypto/cryptobyte/asn1" +) + +type BigInt = xcrypto.BigInt @@ -43675,14 +43737,59 @@ index 00000000000000..22ca259a1833bf + +func SupportsPSSHash(h crypto.Hash) bool { return xcrypto.SupportsHash(h) } + -+//go:linkname decodeKey crypto/rsa.decodeKey -+func decodeKey(data []byte) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) -+ -+//go:linkname encodeKey crypto/rsa.encodeKey -+func encodeKey(N, E, D, P, Q, Dp, Dq, Qinv BigInt) ([]byte, error) ++func decodeKey(data []byte) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { ++ bad := func(e error) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { ++ return nil, nil, nil, nil, nil, nil, nil, nil, e ++ } ++ input := cryptobyte.String(data) ++ var seq cryptobyte.String ++ var version int ++ n, e, d, p, q, dp, dq, qinv := new(big.Int), new(big.Int), new(big.Int), new(big.Int), ++ new(big.Int), new(big.Int), new(big.Int), new(big.Int) ++ if !input.ReadASN1(&seq, asn1.SEQUENCE) { ++ return bad(errors.New("invalid ASN.1 structure: not a sequence")) ++ } ++ if !input.Empty() { ++ return bad(errors.New("invalid ASN.1 structure: trailing data")) ++ } ++ if !seq.ReadASN1Integer(&version) || version != 0 { ++ return bad(errors.New("invalid ASN.1 structure: unsupported version")) ++ } ++ if !seq.ReadASN1Integer(n) || !seq.ReadASN1Integer(e) || ++ !seq.ReadASN1Integer(d) || !seq.ReadASN1Integer(p) || ++ !seq.ReadASN1Integer(q) || !seq.ReadASN1Integer(dp) || ++ !seq.ReadASN1Integer(dq) || !seq.ReadASN1Integer(qinv) || ++ !seq.Empty() { ++ return bad(errors.New("invalid ASN.1 structure")) ++ } ++ return bbig.Enc(n), bbig.Enc(e), bbig.Enc(d), bbig.Enc(p), bbig.Enc(q), ++ bbig.Enc(dp), bbig.Enc(dq), bbig.Enc(qinv), nil ++} ++ ++func encodeKey(N, E, D, P, Q, Dp, Dq, Qinv BigInt) ([]byte, error) { ++ builder := cryptobyte.NewBuilder(nil) ++ builder.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { ++ b.AddASN1Int64(0) ++ b.AddASN1BigInt(bbig.Dec(N)) ++ b.AddASN1BigInt(bbig.Dec(E)) ++ b.AddASN1BigInt(bbig.Dec(D)) ++ b.AddASN1BigInt(bbig.Dec(P)) ++ b.AddASN1BigInt(bbig.Dec(Q)) ++ b.AddASN1BigInt(bbig.Dec(Dp)) ++ b.AddASN1BigInt(bbig.Dec(Dq)) ++ b.AddASN1BigInt(bbig.Dec(Qinv)) ++ }) ++ return builder.Bytes() ++} + -+//go:linkname encodePublicKey crypto/rsa.encodePublicKey -+func encodePublicKey(N, E BigInt) ([]byte, error) ++func encodePublicKey(N, E BigInt) ([]byte, error) { ++ builder := cryptobyte.NewBuilder(nil) ++ builder.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { ++ b.AddASN1BigInt(bbig.Dec(N)) ++ b.AddASN1BigInt(bbig.Dec(E)) ++ }) ++ return builder.Bytes() ++} + +func GenerateKey(bits int) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { + data, err := xcrypto.GenerateKeyRSA(bits) diff --git a/patches/0002-Add-crypto-backends.patch b/patches/0002-Add-crypto-backends.patch index dc4950201b..2fa402b7ce 100644 --- a/patches/0002-Add-crypto-backends.patch +++ b/patches/0002-Add-crypto-backends.patch @@ -47,7 +47,7 @@ Subject: [PATCH] Add crypto backends src/crypto/cipher/gcm_test.go | 9 +- src/crypto/des/cipher.go | 9 + src/crypto/dsa/boring.go | 114 ++++++++ - src/crypto/dsa/dsa.go | 90 ++++++ + src/crypto/dsa/dsa.go | 47 +++ src/crypto/dsa/dsa_test.go | 8 + src/crypto/dsa/notboring.go | 16 ++ src/crypto/ecdh/ecdh.go | 7 +- @@ -56,7 +56,7 @@ Subject: [PATCH] Add crypto backends src/crypto/ecdh/x25519.go | 51 ++++ src/crypto/ecdsa/badlinkname.go | 19 ++ src/crypto/ecdsa/boring.go | 19 +- - src/crypto/ecdsa/ecdsa.go | 33 ++- + src/crypto/ecdsa/ecdsa.go | 19 +- src/crypto/ecdsa/notboring.go | 8 +- src/crypto/ed25519/boring.go | 73 +++++ src/crypto/ed25519/ed25519.go | 73 +++++ @@ -100,7 +100,6 @@ Subject: [PATCH] Add crypto backends src/crypto/rsa/pkcs1v15_test.go | 5 + src/crypto/rsa/pss_test.go | 14 +- src/crypto/rsa/rsa.go | 44 +-- - src/crypto/rsa/rsa_darwin.go | 72 +++++ src/crypto/rsa/rsa_test.go | 7 +- src/crypto/sha1/sha1.go | 15 +- src/crypto/sha1/sha1_test.go | 11 +- @@ -126,7 +125,7 @@ Subject: [PATCH] Add crypto backends src/crypto/tls/prf_test.go | 9 + src/crypto/x509/verify_test.go | 2 +- src/go/build/buildbackend_test.go | 50 ++++ - src/go/build/deps_test.go | 86 +++++- + src/go/build/deps_test.go | 90 +++++- .../build/testdata/backendtags_system/main.go | 3 + .../backendtags_system/systemcrypto.go | 3 + src/hash/boring_test.go | 9 + @@ -144,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 + - 140 files changed, 2953 insertions(+), 376 deletions(-) + 139 files changed, 2827 insertions(+), 377 deletions(-) create mode 100644 src/cmd/go/internal/modindex/build_test.go create mode 100644 src/cmd/go/systemcrypto_test.go create mode 100644 src/crypto/dsa/boring.go @@ -152,7 +151,6 @@ Subject: [PATCH] Add crypto backends create mode 100644 src/crypto/ecdsa/badlinkname.go create mode 100644 src/crypto/ed25519/boring.go create mode 100644 src/crypto/ed25519/notboring.go - create mode 100644 src/crypto/rsa/rsa_darwin.go create mode 100644 src/crypto/systemcrypto_nocgo_linux.go create mode 100644 src/crypto/tls/internal/tls13/doc.go create mode 100644 src/crypto/tls/internal/tls13/tls13.go @@ -342,7 +340,7 @@ index 78d55bec559987..decf356a449ba9 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 56ec2558530b84..34e937e8111062 100644 +index 43ac003c7907c7..4daeb1a5ced0eb 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -158,10 +158,12 @@ func (t *tester) run() { @@ -372,7 +370,7 @@ index 56ec2558530b84..34e937e8111062 100644 } } -@@ -720,7 +722,7 @@ func (t *tester) registerTests() { +@@ -731,7 +733,7 @@ func (t *tester) registerTests() { }) // Check that all crypto packages compile (and test correctly, in longmode) with fips. @@ -381,7 +379,7 @@ index 56ec2558530b84..34e937e8111062 100644 // Test standard crypto packages with fips140=on. t.registerTest("GOFIPS140=latest go test crypto/...", &goTest{ variant: "gofips140", -@@ -784,7 +786,9 @@ func (t *tester) registerTests() { +@@ -795,7 +797,9 @@ func (t *tester) registerTests() { } // Test ios/amd64 for the iOS simulator. @@ -392,7 +390,7 @@ index 56ec2558530b84..34e937e8111062 100644 t.registerTest("GOOS=ios on darwin/amd64", &goTest{ variant: "amd64ios", -@@ -1033,7 +1037,9 @@ func (t *tester) registerTests() { +@@ -1044,7 +1048,9 @@ func (t *tester) registerTests() { t.registerRaceTests() } @@ -403,7 +401,7 @@ index 56ec2558530b84..34e937e8111062 100644 // Only start multiple test dir shards on builders, // where they get distributed to multiple machines. // See issues 20141 and 31834. -@@ -1390,12 +1396,11 @@ func (t *tester) registerCgoTests(heading string) { +@@ -1401,12 +1407,11 @@ 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 @@ -417,7 +415,7 @@ index 56ec2558530b84..34e937e8111062 100644 // Static linking tests if goos != "android" && p != "netbsd/arm" && !t.msan && !t.asan { // TODO(#56629): Why does this fail on netbsd-arm? -@@ -1918,3 +1923,28 @@ func goexperiments(exps ...string) string { +@@ -1929,3 +1934,28 @@ func goexperiments(exps ...string) string { return existing + strings.Join(exps, ",") } @@ -617,7 +615,7 @@ 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 1a2adcf4bf7c65..cbcca50146fabe 100644 +index 2985cff67cec0b..d345585b33be9a 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -16,6 +16,7 @@ import ( @@ -1851,10 +1849,10 @@ index 00000000000000..a6f50a16df8dda + } +} diff --git a/src/crypto/dsa/dsa.go b/src/crypto/dsa/dsa.go -index 6724f861b7f2f0..e4cf1440a40b59 100644 +index 6724f861b7f2f0..7d0bd731b16081 100644 --- a/src/crypto/dsa/dsa.go +++ b/src/crypto/dsa/dsa.go -@@ -20,6 +20,13 @@ import ( +@@ -20,6 +20,10 @@ import ( "crypto/internal/fips140only" "crypto/internal/rand" @@ -1862,13 +1860,10 @@ index 6724f861b7f2f0..e4cf1440a40b59 100644 + boring "github.com/microsoft/go/cryptobackend" + "github.com/microsoft/go/cryptobackend/bbig" + bdsa "github.com/microsoft/go/cryptobackend/dsa" -+ -+ "golang.org/x/crypto/cryptobyte" -+ "golang.org/x/crypto/cryptobyte/asn1" ) // Parameters represents the domain parameters for a key. These parameters can -@@ -91,6 +98,17 @@ func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes +@@ -91,6 +95,17 @@ func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes return errors.New("crypto/dsa: invalid ParameterSizes") } @@ -1886,7 +1881,7 @@ index 6724f861b7f2f0..e4cf1440a40b59 100644 qBytes := make([]byte, N/8) pBytes := make([]byte, L/8) -@@ -170,6 +188,17 @@ func GenerateKey(priv *PrivateKey, rand io.Reader) error { +@@ -170,6 +185,17 @@ func GenerateKey(priv *PrivateKey, rand io.Reader) error { return errors.New("crypto/dsa: parameters not set up before generating key") } @@ -1904,7 +1899,7 @@ index 6724f861b7f2f0..e4cf1440a40b59 100644 x := new(big.Int) xBytes := make([]byte, priv.Q.BitLen()/8) -@@ -229,6 +258,18 @@ func Sign(random io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err e +@@ -229,6 +255,18 @@ func Sign(random io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err e err = ErrInvalidPublicKey return } @@ -1915,7 +1910,7 @@ index 6724f861b7f2f0..e4cf1440a40b59 100644 + return nil, nil, err + } + -+ r, s, err := bdsa.Sign(b, hash, parseSignature) ++ r, s, err := bdsa.Sign(b, hash) + + return bbig.Dec(r), bbig.Dec(s), err + } @@ -1923,8 +1918,8 @@ index 6724f861b7f2f0..e4cf1440a40b59 100644 n >>= 3 var attempts int -@@ -292,6 +333,14 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { - panic("crypto/dsa: use of DSA is not allowed in FIPS 140-only mode") +@@ -305,6 +343,15 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { + return false } + if boring.Enabled && bdsa.Supports(pub.P.BitLen(), pub.Q.BitLen()) { @@ -1933,56 +1928,12 @@ index 6724f861b7f2f0..e4cf1440a40b59 100644 + return false + } + -+ return bdsa.Verify(bkey, hash, bbig.Enc(r), bbig.Enc(s), encodeSignature) -+ } - // FIPS 186-3, section 4.7 - - if pub.P.Sign() == 0 { -@@ -328,3 +377,44 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { - - return v.Cmp(r) == 0 - } -+ -+func parseSignature(sig []byte) (bdsa.BigInt, bdsa.BigInt, error) { -+ var r, s []byte -+ var inner cryptobyte.String -+ input := cryptobyte.String(sig) -+ if !input.ReadASN1(&inner, asn1.SEQUENCE) || -+ !input.Empty() || -+ !inner.ReadASN1Integer(&r) || -+ !inner.ReadASN1Integer(&s) || -+ !inner.Empty() { -+ return nil, nil, errors.New("invalid ASN.1") ++ return bdsa.Verify(bkey, hash, bbig.Enc(r), bbig.Enc(s)) + } -+ return bbig.Enc(new(big.Int).SetBytes(r)), bbig.Enc(new(big.Int).SetBytes(s)), nil -+} -+ -+func encodeSignature(r, s bdsa.BigInt) ([]byte, error) { -+ var b cryptobyte.Builder -+ b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ addASN1IntBytes(b, bbig.Dec(r).Bytes()) -+ addASN1IntBytes(b, bbig.Dec(s).Bytes()) -+ }) -+ return b.Bytes() -+} + -+// addASN1IntBytes encodes in ASN.1 a positive integer represented as -+// a big-endian byte slice with zero or more leading zeroes. -+func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) { -+ for len(bytes) > 0 && bytes[0] == 0 { -+ bytes = bytes[1:] -+ } -+ if len(bytes) == 0 { -+ b.SetError(errors.New("invalid integer")) -+ return -+ } -+ b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) { -+ if bytes[0]&0x80 != 0 { -+ c.AddUint8(0) -+ } -+ c.AddBytes(bytes) -+ }) -+} + w := new(big.Int).ModInverse(s, pub.Q) + if w == nil { + return false diff --git a/src/crypto/dsa/dsa_test.go b/src/crypto/dsa/dsa_test.go index ad85eac0a7f0b1..a4cc9c067e3f2c 100644 --- a/src/crypto/dsa/dsa_test.go @@ -2433,7 +2384,7 @@ index 275c60b4de49eb..a5b6ae9dc90505 100644 return nil, err } diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go -index 40a89017570171..3b621083d54ac1 100644 +index 40a89017570171..24b8ae80344ee8 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go @@ -20,8 +20,6 @@ import ( @@ -2467,7 +2418,7 @@ index 40a89017570171..3b621083d54ac1 100644 if err != nil { return nil, err } -@@ -389,12 +391,19 @@ func SignASN1(r io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { +@@ -389,12 +391,12 @@ func SignASN1(r io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { return nil, errors.New("ecdsa: hash cannot be empty") } @@ -2478,18 +2429,11 @@ index 40a89017570171..3b621083d54ac1 100644 return nil, err } - return boring.SignMarshalECDSA(b, hash) -+ if sig, err := becdsa.SignASN1(b, hash); err != errors.ErrUnsupported { -+ return sig, err -+ } -+ rs, ss, err := becdsa.Sign(b, hash) -+ if err != nil { -+ return nil, err -+ } -+ return encodeSignature(rs, ss) ++ return becdsa.SignASN1(b, hash) } boring.UnreachableExceptTests() -@@ -510,12 +519,20 @@ func VerifyASN1(pub *PublicKey, hash, sig []byte) bool { +@@ -510,12 +512,13 @@ func VerifyASN1(pub *PublicKey, hash, sig []byte) bool { return false } @@ -2500,14 +2444,7 @@ index 40a89017570171..3b621083d54ac1 100644 return false } - return boring.VerifyECDSA(key, hash, sig) -+ if ok, err := becdsa.VerifyASN1(key, hash, sig); err != errors.ErrUnsupported { -+ return err == nil && ok -+ } -+ r, s, err := parseSignature(sig) -+ if err != nil { -+ return false -+ } -+ ok, err := becdsa.Verify(key, hash, r, s) ++ ok, err := becdsa.VerifyASN1(key, hash, sig) + return err == nil && ok } boring.UnreachableExceptTests() @@ -4972,84 +4909,6 @@ index 93e08ed6cd8f71..0052585b9e7c63 100644 k, err := rsa.GenerateKey(random, bits) if bits < 256 && err != nil { // Toy-sized keys have a non-negligible chance of hitting two hard -diff --git a/src/crypto/rsa/rsa_darwin.go b/src/crypto/rsa/rsa_darwin.go -new file mode 100644 -index 00000000000000..717fe71a1886d5 ---- /dev/null -+++ b/src/crypto/rsa/rsa_darwin.go -@@ -0,0 +1,72 @@ -+// Copyright 2017 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 goexperiment.systemcrypto -+ -+package rsa -+ -+import ( -+ "errors" -+ "math/big" -+ _ "unsafe" -+ -+ "github.com/microsoft/go/cryptobackend/bbig" -+ brsa "github.com/microsoft/go/cryptobackend/rsa" -+ -+ "golang.org/x/crypto/cryptobyte" -+ "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+//go:linkname decodeKey -+func decodeKey(data []byte) (N, E, D, P, Q, Dp, Dq, Qinv brsa.BigInt, err error) { -+ bad := func(e error) (N, E, D, P, Q, Dp, Dq, Qinv brsa.BigInt, err error) { -+ return nil, nil, nil, nil, nil, nil, nil, nil, e -+ } -+ input := cryptobyte.String(data) -+ var version int -+ n, e, d, p, q, dp, dq, qinv := new(big.Int), new(big.Int), new(big.Int), new(big.Int), -+ new(big.Int), new(big.Int), new(big.Int), new(big.Int) -+ // Parse the ASN.1 sequence -+ if !input.ReadASN1(&input, asn1.SEQUENCE) { -+ return bad(errors.New("invalid ASN.1 structure: not a sequence")) -+ } -+ if !input.ReadASN1Integer(&version) || version != 0 { -+ return bad(errors.New("invalid ASN.1 structure: unsupported version")) -+ } -+ if !input.ReadASN1Integer(n) || !input.ReadASN1Integer(e) || -+ !input.ReadASN1Integer(d) || !input.ReadASN1Integer(p) || -+ !input.ReadASN1Integer(q) || !input.ReadASN1Integer(dp) || -+ !input.ReadASN1Integer(dq) || !input.ReadASN1Integer(qinv) { -+ return bad(errors.New("invalid ASN.1 structure")) -+ } -+ return bbig.Enc(n), bbig.Enc(e), bbig.Enc(d), bbig.Enc(p), bbig.Enc(q), -+ bbig.Enc(dp), bbig.Enc(dq), bbig.Enc(qinv), nil -+} -+ -+//go:linkname encodeKey -+func encodeKey(N, E, D, P, Q, Dp, Dq, Qinv brsa.BigInt) ([]byte, error) { -+ builder := cryptobyte.NewBuilder(nil) -+ builder.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ b.AddASN1Int64(0) // Add version as int64 -+ b.AddASN1BigInt(bbig.Dec(N)) // Add modulus -+ b.AddASN1BigInt(bbig.Dec(E)) // Add public exponent -+ b.AddASN1BigInt(bbig.Dec(D)) // Add private exponent -+ b.AddASN1BigInt(bbig.Dec(P)) // Add prime1 -+ b.AddASN1BigInt(bbig.Dec(Q)) // Add prime2 -+ b.AddASN1BigInt(bbig.Dec(Dp)) // Add exponent1 -+ b.AddASN1BigInt(bbig.Dec(Dq)) // Add exponent2 -+ b.AddASN1BigInt(bbig.Dec(Qinv)) // Add coefficient -+ }) -+ return builder.Bytes() -+} -+ -+//go:linkname encodePublicKey -+func encodePublicKey(N, E brsa.BigInt) ([]byte, error) { -+ builder := cryptobyte.NewBuilder(nil) -+ builder.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ b.AddASN1BigInt(bbig.Dec(N)) // Add modulus -+ b.AddASN1BigInt(bbig.Dec(E)) // Add public exponent -+ }) -+ return builder.Bytes() -+} diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go index 8c1b22bf4f41b4..386016b33f717a 100644 --- a/src/crypto/rsa/rsa_test.go @@ -6075,7 +5934,7 @@ index 027bc22c33c921..eba08da985f832 100644 package fipsonly diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go -index 52bf6087b62955..6d97d1fba0dfa9 100644 +index 54227aabfb698c..89b973986e4485 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -11,11 +11,11 @@ import ( @@ -6114,7 +5973,7 @@ index 52bf6087b62955..6d97d1fba0dfa9 100644 // If we did not load a session (hs.session == nil), but we did set a diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go -index d367020c2066bf..6a83eda3573245 100644 +index f55150697d96f6..552b82a476aea9 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -10,9 +10,9 @@ import ( @@ -6129,7 +5988,7 @@ index d367020c2066bf..6a83eda3573245 100644 "hash" "slices" diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go -index cde70463ef0fa4..4df9e6f5aac92c 100644 +index a4544a13051f51..f889d38b5e922c 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -64,7 +64,20 @@ func (c *Conn) serverHandshake(ctx context.Context) error { @@ -6155,7 +6014,7 @@ index cde70463ef0fa4..4df9e6f5aac92c 100644 if err := hs.processClientHello(); err != nil { diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go -index 3175d74587d83a..ed7c2de8db51f1 100644 +index 2c96e2435ae156..462afaeae882c1 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -11,9 +11,9 @@ import ( @@ -6593,7 +6452,7 @@ index 00000000000000..ffb835ce34a2f7 + } +} diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index a71759adcb7363..fac04fccb099c1 100644 +index a71759adcb7363..abba83862c5ae1 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -372,8 +372,10 @@ var depsRules = ` @@ -6639,7 +6498,7 @@ index a71759adcb7363..fac04fccb099c1 100644 < crypto/internal/fips140only < crypto < crypto/subtle -@@ -577,6 +592,54 @@ var depsRules = ` +@@ -577,6 +592,51 @@ var depsRules = ` github.com/microsoft/go-crypto-winnative/internal/bcrypt < github.com/microsoft/go-crypto-winnative/cng; @@ -6671,9 +6530,7 @@ index a71759adcb7363..fac04fccb099c1 100644 + github.com/microsoft/go/cryptobackend/chacha20poly1305, + github.com/microsoft/go/cryptobackend/des, + github.com/microsoft/go/cryptobackend/drbg, -+ github.com/microsoft/go/cryptobackend/dsa, + github.com/microsoft/go/cryptobackend/ecdh, -+ github.com/microsoft/go/cryptobackend/ecdsa, + github.com/microsoft/go/cryptobackend/ed25519, + github.com/microsoft/go/cryptobackend/hkdf, + github.com/microsoft/go/cryptobackend/hmac, @@ -6682,7 +6539,6 @@ index a71759adcb7363..fac04fccb099c1 100644 + github.com/microsoft/go/cryptobackend/mlkem, + github.com/microsoft/go/cryptobackend/pbkdf2, + github.com/microsoft/go/cryptobackend/rc4, -+ github.com/microsoft/go/cryptobackend/rsa, + github.com/microsoft/go/cryptobackend/sha1, + github.com/microsoft/go/cryptobackend/sha256, + github.com/microsoft/go/cryptobackend/sha3, @@ -6694,7 +6550,7 @@ index a71759adcb7363..fac04fccb099c1 100644 FIPS, internal/godebug, embed, crypto/internal/boring/sig, crypto/internal/boring/syso, -@@ -584,7 +647,9 @@ var depsRules = ` +@@ -584,7 +644,9 @@ var depsRules = ` crypto/internal/fips140only, crypto, crypto/subtle, @@ -6705,7 +6561,7 @@ index a71759adcb7363..fac04fccb099c1 100644 < crypto/sha3 < crypto/internal/fips140hash < crypto/internal/boring -@@ -603,6 +668,7 @@ var depsRules = ` +@@ -603,6 +665,7 @@ var depsRules = ` crypto/ecdh, crypto/mlkem, crypto/mldsa @@ -6713,7 +6569,7 @@ index a71759adcb7363..fac04fccb099c1 100644 < CRYPTO; CRYPTO -@@ -616,8 +682,16 @@ var depsRules = ` +@@ -616,15 +679,28 @@ var depsRules = ` math/big, github.com/microsoft/go-crypto-darwin/xcrypto < github.com/microsoft/go-crypto-darwin/bbig; math/big, github.com/microsoft/go-crypto-winnative/cng < github.com/microsoft/go-crypto-winnative/cng/bbig; @@ -6732,6 +6588,19 @@ index a71759adcb7363..fac04fccb099c1 100644 < crypto/internal/fips140cache < crypto/rand < crypto/ed25519 # depends on crypto/rand.Reader + < encoding/asn1 + < golang.org/x/crypto/cryptobyte/asn1 + < golang.org/x/crypto/cryptobyte +- < crypto/dsa, crypto/elliptic, crypto/rsa ++ < github.com/microsoft/go/cryptobackend/dsa, ++ github.com/microsoft/go/cryptobackend/ecdsa, ++ github.com/microsoft/go/cryptobackend/rsa, ++ crypto/elliptic ++ < crypto/dsa ++ < crypto/rsa + < crypto/ecdsa + < CRYPTO-MATH; + diff --git a/src/go/build/testdata/backendtags_system/main.go b/src/go/build/testdata/backendtags_system/main.go new file mode 100644 index 00000000000000..38dd16da61accb @@ -6891,7 +6760,7 @@ index 2bbd478280241e..77eaacdc38756d 100644 "v1.0.0", "v1.0.1", diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go -index 8eeef17c1f470e..dda96ef5b15616 100644 +index bf411a8dbbfcde..9b6ca9feb0b23b 100644 --- a/src/internal/buildcfg/exp.go +++ b/src/internal/buildcfg/exp.go @@ -10,12 +10,14 @@ import ( @@ -6909,7 +6778,7 @@ index 8eeef17c1f470e..dda96ef5b15616 100644 baseline goexperiment.Flags } -@@ -131,6 +133,21 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { +@@ -130,6 +132,21 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { if strings.HasPrefix(f, "no") { f, val = f[2:], false } @@ -6931,7 +6800,7 @@ index 8eeef17c1f470e..dda96ef5b15616 100644 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) { +@@ -151,6 +168,9 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) { if flags.RegabiArgs && !flags.RegabiWrappers { return nil, fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers") }