From 0ec037fddf7a29b2620bfd56d8cff326764bb82a Mon Sep 17 00:00:00 2001 From: qmuntal Date: Thu, 9 Jan 2025 17:13:51 +0100 Subject: [PATCH 01/12] implement TLS 1.3 key schedule using crypto/hkdf --- .../0002-Add-crypto-backend-foundation.patch | 296 +++++++++++++++++- 1 file changed, 279 insertions(+), 17 deletions(-) diff --git a/patches/0002-Add-crypto-backend-foundation.patch b/patches/0002-Add-crypto-backend-foundation.patch index a9ae91f13d4..08067460993 100644 --- a/patches/0002-Add-crypto-backend-foundation.patch +++ b/patches/0002-Add-crypto-backend-foundation.patch @@ -63,20 +63,23 @@ Subject: [PATCH] Add crypto backend foundation src/crypto/tls/cipher_suites.go | 2 +- src/crypto/tls/fipsonly/fipsonly.go | 2 +- src/crypto/tls/fipsonly/fipsonly_test.go | 2 +- - src/crypto/tls/handshake_client.go | 10 +- - src/crypto/tls/handshake_client_tls13.go | 14 +- + src/crypto/tls/handshake_client.go | 12 +- + src/crypto/tls/handshake_client_tls13.go | 16 +- src/crypto/tls/handshake_server.go | 10 +- - src/crypto/tls/handshake_server_tls13.go | 25 +- + src/crypto/tls/handshake_server_tls13.go | 27 ++- src/crypto/tls/internal/fips140tls/fipstls.go | 3 +- + src/crypto/tls/internal/tls13/doc.go | 18 ++ + src/crypto/tls/internal/tls13/tls13.go | 182 ++++++++++++++ + src/crypto/tls/key_schedule.go | 2 +- src/crypto/tls/prf.go | 41 ++++ - src/go/build/deps_test.go | 8 +- + src/go/build/deps_test.go | 9 +- src/hash/boring_test.go | 9 + src/hash/example_test.go | 2 + src/hash/marshal_test.go | 9 + src/hash/notboring_test.go | 9 + src/net/smtp/smtp_test.go | 72 ++++-- src/runtime/runtime_boring.go | 5 + - 72 files changed, 1217 insertions(+), 89 deletions(-) + 75 files changed, 1422 insertions(+), 93 deletions(-) create mode 100644 src/crypto/dsa/boring.go create mode 100644 src/crypto/dsa/notboring.go create mode 100644 src/crypto/ed25519/boring.go @@ -90,6 +93,8 @@ Subject: [PATCH] Add crypto backend foundation create mode 100644 src/crypto/internal/backend/fips140/nosystemcrypto.go create mode 100644 src/crypto/internal/backend/nobackend.go create mode 100644 src/crypto/internal/backend/stub.s + create mode 100644 src/crypto/tls/internal/tls13/doc.go + create mode 100644 src/crypto/tls/internal/tls13/tls13.go create mode 100644 src/hash/boring_test.go create mode 100644 src/hash/notboring_test.go @@ -556,10 +561,10 @@ index 275c60b4de49eb..ff8bddf28c4545 100644 "math/big" ) diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go -index 0f9749975ffba9..41ac17df22d7d7 100644 +index f682e6b1c6cfa6..049da55bd70f2c 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go -@@ -18,8 +18,8 @@ import ( +@@ -20,8 +20,8 @@ import ( "crypto" "crypto/ecdh" "crypto/elliptic" @@ -2189,9 +2194,22 @@ index 027bc22c33c921..eba08da985f832 100644 package fipsonly diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go -index 38bd417a0dca72..9eec202234fa94 100644 +index 38bd417a0dca72..8c1ae3c7ec5485 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go +@@ -11,11 +11,11 @@ import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/internal/fips140/mlkem" +- "crypto/internal/fips140/tls13" + "crypto/internal/hpke" + "crypto/rsa" + "crypto/subtle" + "crypto/tls/internal/fips140tls" ++ "crypto/tls/internal/tls13" + "crypto/x509" + "errors" + "fmt" @@ -549,7 +549,15 @@ func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error { // Does the handshake, either a full one or resumes old session. Requires hs.c, @@ -2210,10 +2228,10 @@ index 38bd417a0dca72..9eec202234fa94 100644 isResume, err := hs.processServerHello() diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go -index c0396e75796add..819bc54822f0cb 100644 +index c0396e75796add..2c00e119cb66e4 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go -@@ -8,8 +8,8 @@ import ( +@@ -8,12 +8,12 @@ import ( "bytes" "context" "crypto" @@ -2221,8 +2239,13 @@ index c0396e75796add..819bc54822f0cb 100644 "crypto/hmac" - "crypto/internal/fips140/hkdf" "crypto/internal/fips140/mlkem" - "crypto/internal/fips140/tls13" +- "crypto/internal/fips140/tls13" "crypto/rsa" + "crypto/subtle" ++ "crypto/tls/internal/tls13" + "errors" + "hash" + "slices" @@ -90,8 +90,12 @@ func (hs *clientHandshakeStateTLS13) handshake() error { confTranscript.Write(hs.serverHello.original[:30]) confTranscript.Write(make([]byte, 8)) @@ -2273,10 +2296,10 @@ index 7c75977ad3ffb2..b9db95ca7b9d5a 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 76fff6974e7403..bccf52fb28fcc5 100644 +index 76fff6974e7403..3ef8b56e5c7898 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go -@@ -8,8 +8,9 @@ import ( +@@ -8,13 +8,14 @@ import ( "bytes" "context" "crypto" @@ -2285,8 +2308,14 @@ index 76fff6974e7403..bccf52fb28fcc5 100644 - "crypto/internal/fips140/hkdf" + boring "crypto/internal/backend" "crypto/internal/fips140/mlkem" - "crypto/internal/fips140/tls13" +- "crypto/internal/fips140/tls13" "crypto/internal/hpke" + "crypto/rsa" + "crypto/tls/internal/fips140tls" ++ "crypto/tls/internal/tls13" + "errors" + "hash" + "internal/byteorder" @@ -470,15 +471,19 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error { // interfaces implemented by standard library hashes to clone the state of in // to a new instance of h. It returns nil if the operation fails. @@ -2360,6 +2389,231 @@ index 24d78d60cf5b64..a6bfd3f17c1911 100644 Force() } } +diff --git a/src/crypto/tls/internal/tls13/doc.go b/src/crypto/tls/internal/tls13/doc.go +new file mode 100644 +index 00000000000000..1adf3098356307 +--- /dev/null ++++ b/src/crypto/tls/internal/tls13/doc.go +@@ -0,0 +1,18 @@ ++// 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. ++ ++/* ++Microsoft Go only package. ++ ++TLS 1.3 Key Schedule is normally not part of the FIPS boundary, but upstream Go ++decided to include it in the FIPS boundary to facilitate the FIPS 140-3 certification ++process. ++ ++The problem is that crypto/internal/fips140/tls13 uses crypto/internal/fips140/hkdf, ++which can't be patched to use other backends. ++ ++To solve this problem, we created this package, which is a direct copy of ++crypto/internal/fips140/tls13, but uses crypto/hkdf instead of crypto/internal/fips140/hkdf. ++*/ ++package tls13 +diff --git a/src/crypto/tls/internal/tls13/tls13.go b/src/crypto/tls/internal/tls13/tls13.go +new file mode 100644 +index 00000000000000..573896b9c1e6a8 +--- /dev/null ++++ b/src/crypto/tls/internal/tls13/tls13.go +@@ -0,0 +1,182 @@ ++// Copyright 2024 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package tls13 implements the TLS 1.3 Key Schedule as specified in RFC 8446, ++// Section 7.1 and allowed by FIPS 140-3 IG 2.4.B Resolution 7. ++package tls13 ++ ++import ( ++ "crypto/hkdf" ++ "hash" ++ "internal/byteorder" ++) ++ ++// We don't set the service indicator in this package but we delegate that to ++// the underlying functions because the TLS 1.3 KDF does not have a standard of ++// its own. ++ ++// ExpandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1. ++func ExpandLabel[H hash.Hash](hash func() H, secret []byte, label string, context []byte, length int) []byte { ++ if len("tls13 ")+len(label) > 255 || len(context) > 255 { ++ // It should be impossible for this to panic: labels are fixed strings, ++ // and context is either a fixed-length computed hash, or parsed from a ++ // field which has the same length limitation. ++ // ++ // Another reasonable approach might be to return a randomized slice if ++ // we encounter an error, which would break the connection, but avoid ++ // panicking. This would perhaps be safer but significantly more ++ // confusing to users. ++ panic("tls13: label or context too long") ++ } ++ hkdfLabel := make([]byte, 0, 2+1+len("tls13 ")+len(label)+1+len(context)) ++ hkdfLabel = byteorder.BEAppendUint16(hkdfLabel, uint16(length)) ++ hkdfLabel = append(hkdfLabel, byte(len("tls13 ")+len(label))) ++ hkdfLabel = append(hkdfLabel, "tls13 "...) ++ hkdfLabel = append(hkdfLabel, label...) ++ hkdfLabel = append(hkdfLabel, byte(len(context))) ++ hkdfLabel = append(hkdfLabel, context...) ++ key, err := hkdf.Expand(hash, secret, string(hkdfLabel), length) ++ if err != nil { ++ panic(err) ++ } ++ return key ++} ++ ++func extract[H hash.Hash](hash func() H, newSecret, currentSecret []byte) []byte { ++ if newSecret == nil { ++ newSecret = make([]byte, hash().Size()) ++ } ++ prk, err := hkdf.Extract(hash, newSecret, currentSecret) ++ if err != nil { ++ panic(err) ++ } ++ return prk ++} ++ ++func deriveSecret[H hash.Hash](hash func() H, secret []byte, label string, transcript hash.Hash) []byte { ++ if transcript == nil { ++ transcript = hash() ++ } ++ return ExpandLabel(hash, secret, label, transcript.Sum(nil), transcript.Size()) ++} ++ ++const ( ++ resumptionBinderLabel = "res binder" ++ clientEarlyTrafficLabel = "c e traffic" ++ clientHandshakeTrafficLabel = "c hs traffic" ++ serverHandshakeTrafficLabel = "s hs traffic" ++ clientApplicationTrafficLabel = "c ap traffic" ++ serverApplicationTrafficLabel = "s ap traffic" ++ earlyExporterLabel = "e exp master" ++ exporterLabel = "exp master" ++ resumptionLabel = "res master" ++) ++ ++type EarlySecret struct { ++ secret []byte ++ hash func() hash.Hash ++} ++ ++func NewEarlySecret[H hash.Hash](h func() H, psk []byte) *EarlySecret { ++ return &EarlySecret{ ++ secret: extract(h, psk, nil), ++ hash: func() hash.Hash { return h() }, ++ } ++} ++ ++func (s *EarlySecret) ResumptionBinderKey() []byte { ++ return deriveSecret(s.hash, s.secret, resumptionBinderLabel, nil) ++} ++ ++// ClientEarlyTrafficSecret derives the client_early_traffic_secret from the ++// early secret and the transcript up to the ClientHello. ++func (s *EarlySecret) ClientEarlyTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, clientEarlyTrafficLabel, transcript) ++} ++ ++type HandshakeSecret struct { ++ secret []byte ++ hash func() hash.Hash ++} ++ ++func (s *EarlySecret) HandshakeSecret(sharedSecret []byte) *HandshakeSecret { ++ derived := deriveSecret(s.hash, s.secret, "derived", nil) ++ return &HandshakeSecret{ ++ secret: extract(s.hash, sharedSecret, derived), ++ hash: s.hash, ++ } ++} ++ ++// ClientHandshakeTrafficSecret derives the client_handshake_traffic_secret from ++// the handshake secret and the transcript up to the ServerHello. ++func (s *HandshakeSecret) ClientHandshakeTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, clientHandshakeTrafficLabel, transcript) ++} ++ ++// ServerHandshakeTrafficSecret derives the server_handshake_traffic_secret from ++// the handshake secret and the transcript up to the ServerHello. ++func (s *HandshakeSecret) ServerHandshakeTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, serverHandshakeTrafficLabel, transcript) ++} ++ ++type MasterSecret struct { ++ secret []byte ++ hash func() hash.Hash ++} ++ ++func (s *HandshakeSecret) MasterSecret() *MasterSecret { ++ derived := deriveSecret(s.hash, s.secret, "derived", nil) ++ return &MasterSecret{ ++ secret: extract(s.hash, nil, derived), ++ hash: s.hash, ++ } ++} ++ ++// ClientApplicationTrafficSecret derives the client_application_traffic_secret_0 ++// from the master secret and the transcript up to the server Finished. ++func (s *MasterSecret) ClientApplicationTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, clientApplicationTrafficLabel, transcript) ++} ++ ++// ServerApplicationTrafficSecret derives the server_application_traffic_secret_0 ++// from the master secret and the transcript up to the server Finished. ++func (s *MasterSecret) ServerApplicationTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, serverApplicationTrafficLabel, transcript) ++} ++ ++// ResumptionMasterSecret derives the resumption_master_secret from the master secret ++// and the transcript up to the client Finished. ++func (s *MasterSecret) ResumptionMasterSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, resumptionLabel, transcript) ++} ++ ++type ExporterMasterSecret struct { ++ secret []byte ++ hash func() hash.Hash ++} ++ ++// ExporterMasterSecret derives the exporter_master_secret from the master secret ++// and the transcript up to the server Finished. ++func (s *MasterSecret) ExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { ++ return &ExporterMasterSecret{ ++ secret: deriveSecret(s.hash, s.secret, exporterLabel, transcript), ++ hash: s.hash, ++ } ++} ++ ++// EarlyExporterMasterSecret derives the exporter_master_secret from the early secret ++// and the transcript up to the ClientHello. ++func (s *EarlySecret) EarlyExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { ++ return &ExporterMasterSecret{ ++ secret: deriveSecret(s.hash, s.secret, earlyExporterLabel, transcript), ++ hash: s.hash, ++ } ++} ++ ++func (s *ExporterMasterSecret) Exporter(label string, context []byte, length int) []byte { ++ secret := deriveSecret(s.hash, s.secret, label, nil) ++ h := s.hash() ++ h.Write(context) ++ return ExpandLabel(s.hash, secret, "exporter", h.Sum(nil), length) ++} +diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go +index 38d6d3f7be1673..b236ae44a34030 100644 +--- a/src/crypto/tls/key_schedule.go ++++ b/src/crypto/tls/key_schedule.go +@@ -8,7 +8,7 @@ import ( + "crypto/ecdh" + "crypto/hmac" + "crypto/internal/fips140/mlkem" +- "crypto/internal/fips140/tls13" ++ "crypto/tls/internal/tls13" + "errors" + "hash" + "io" diff --git a/src/crypto/tls/prf.go b/src/crypto/tls/prf.go index e7369542a73270..ff52175e4ac636 100644 --- a/src/crypto/tls/prf.go @@ -2430,7 +2684,7 @@ index e7369542a73270..ff52175e4ac636 100644 } } diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index d9d985dca4ade4..de88160bcf3a1c 100644 +index a62a5173b9c6bc..9ef5b8ea058783 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -493,6 +493,8 @@ var depsRules = ` @@ -2458,7 +2712,15 @@ index d9d985dca4ade4..de88160bcf3a1c 100644 < crypto/boring < crypto/aes, crypto/des, -@@ -534,6 +539,7 @@ var depsRules = ` +@@ -526,6 +531,7 @@ var depsRules = ` + crypto/pbkdf2, + crypto/ecdh, + crypto/mlkem ++ < crypto/tls/internal/tls13 + < CRYPTO; + + CGO, fmt, net !< CRYPTO; +@@ -534,6 +540,7 @@ var depsRules = ` CRYPTO, FMT, math/big < crypto/internal/boring/bbig @@ -2466,7 +2728,7 @@ index d9d985dca4ade4..de88160bcf3a1c 100644 < crypto/rand < crypto/ed25519 # depends on crypto/rand.Reader < encoding/asn1 -@@ -547,7 +553,7 @@ var depsRules = ` +@@ -547,7 +554,7 @@ var depsRules = ` # TLS, Prince of Dependencies. From 275f45435345cecae939b1891904d0ec5db603b7 Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Fri, 10 Jan 2025 10:34:12 -0800 Subject: [PATCH 02/12] 1ES PT compliance: split internal publish job, half is a release job --- eng/pipeline/stages/builders-to-stages.yml | 3 +- ...h-stage.yml => internal-publish-stage.yml} | 131 +++++++++--------- .../steps/download-signed-binaries-task.yml | 31 ++++- eng/pipeline/variables/publish-internal.yml | 15 ++ 4 files changed, 111 insertions(+), 69 deletions(-) rename eng/pipeline/stages/{publish-stage.yml => internal-publish-stage.yml} (67%) create mode 100644 eng/pipeline/variables/publish-internal.yml diff --git a/eng/pipeline/stages/builders-to-stages.yml b/eng/pipeline/stages/builders-to-stages.yml index 84943fc740b..5234e5f4b75 100644 --- a/eng/pipeline/stages/builders-to-stages.yml +++ b/eng/pipeline/stages/builders-to-stages.yml @@ -70,11 +70,10 @@ stages: - template: pool.yml parameters: inner: - template: publish-stage.yml + template: internal-publish-stage.yml parameters: builder: { os: windows, arch: amd64 } official: true - public: false builders: - ${{ each builder in parameters.builders }}: - ${{ if eq(builder.config, 'buildandpack') }}: diff --git a/eng/pipeline/stages/publish-stage.yml b/eng/pipeline/stages/internal-publish-stage.yml similarity index 67% rename from eng/pipeline/stages/publish-stage.yml rename to eng/pipeline/stages/internal-publish-stage.yml index 7b74f02dae5..68de6916585 100644 --- a/eng/pipeline/stages/publish-stage.yml +++ b/eng/pipeline/stages/internal-publish-stage.yml @@ -5,9 +5,6 @@ # Create a build asset JSON file as a pipeline artifact and publish build artifacts to blob storage. parameters: - - name: public - type: boolean - - name: pool type: object @@ -28,34 +25,19 @@ parameters: default: false stages: - - stage: Publish${{ parameters.public }} - ${{ if parameters.public }}: - displayName: Publish Public - ${{ else }}: - displayName: Publish Internal + - stage: PrePublish + displayName: Pre Internal Publish ${{ if eq(parameters.publishExistingRunID, 'nil') }}: dependsOn: Sign ${{ else }}: dependsOn: [] + jobs: - - job: Publish + - job: PrePublish pool: ${{ parameters.pool }} variables: - - name: blobBackupAccount - value: golangartifactsbackup - - name: blobContainer - ${{ if parameters.public }}: - value: 'https://dotnetbuildoutput.blob.core.windows.net/golang/microsoft' - ${{ else }}: - value: 'https://$(blobBackupAccount).blob.core.windows.net/microsoft' - - - name: blobPrefix - value: '$(PublishBranchAlias)/$(Build.BuildNumber)' - - name: blobDestinationUrl - value: '$(blobContainer)/$(blobPrefix)' - - - group: go-storage + - template: ../variables/publish-internal.yml workspace: clean: all @@ -68,17 +50,11 @@ stages: # Single file publish requires folder to be specified. # https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/1es-pipeline-templates/features/sbom#specifying-sbom-build-drop-path-build-component-path-package-name-and-package-version-per-1es-pt-output sbomBuildDropPath: $(Pipeline.Workspace)/Binaries Signed - ${{ if parameters.public }}: - artifact: BuildAssets - ${{ else }}: - artifact: BuildAssetsInternal + artifact: BuildAssetsInternal - ${{ if parameters.publishSymbols }}: - output: pipelineArtifact path: $(Pipeline.Workspace)/Symbols - ${{ if parameters.public }}: - artifact: Symbols - ${{ else }}: - artifact: SymbolsInternal + artifact: SymbolsInternal steps: - template: ../steps/checkout-windows-task.yml @@ -96,40 +72,9 @@ stages: -destination-url '$(blobDestinationUrl)' ` -branch '$(PublishBranchAlias)' ` -o '$(Pipeline.Workspace)/Binaries Signed/assets.json' - displayName: 'Create build asset JSON' - - - ${{ if parameters.public }}: - - task: AzureCLI@2 - displayName: Upload to blob storage - inputs: - azureSubscription: GoLang - scriptType: bash - scriptLocation: inlineScript - # Send literal '*' to az: it handles the wildcard itself. Az copy only accepts one - # "from" argument, so we can't use the shell's wildcard expansion. - inlineScript: | - az storage copy -s '*' -d '$(blobDestinationUrl)' --sas-token '$(dotnetbuildoutput-golang-write-sas-query)' - workingDirectory: '$(Pipeline.Workspace)/Binaries Signed/' - - ${{ else }}: - - task: AzureFileCopy@6 - displayName: Upload to blob storage - inputs: - Destination: AzureBlob - azureSubscription: golang-pme-storage - storage: $(blobBackupAccount) - ContainerName: microsoft - SourcePath: '$(Pipeline.Workspace)/Binaries Signed/*' - BlobPrefix: $(blobPrefix) - - - pwsh: | - Write-Host 'Generated links to artifacts in blob storage:' - Write-Host '' - Get-ChildItem -File -Path '.' | %{ - Write-Host "$(blobDestinationUrl)/$($_.Name)" - } - displayName: Show expected uploaded URLs - workingDirectory: '$(Pipeline.Workspace)/Binaries Signed/' + displayName: '🧾 Create build asset JSON' + # Gather symbols from all builders. - ${{ if eq(parameters.publishSymbols, true) }}: - ${{ each builder in parameters.builders }}: - ${{ if eq(parameters.publishExistingRunID, 'nil') }}: @@ -164,8 +109,62 @@ stages: } Copy-Item $_.FullName $flatDir } - displayName: 'Flatten: Symbols ${{ builder.id }}' + displayName: '🫓 Flatten: Symbols ${{ builder.id }}' workingDirectory: '$(Pipeline.Workspace)' + + - stage: Publish + displayName: Publish Internal + dependsOn: PrePublish + + jobs: + - job: Publish + pool: ${{ parameters.pool }} + + variables: + - template: ../variables/publish-internal.yml + + workspace: + clean: all + + templateContext: + type: releaseJob # https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/1es-pipeline-templates/features/releasepipelines/releaseworkflows/releasejob + isProduction: true + inputs: + - input: pipelineArtifact + artifactName: BuildAssetsInternal + - ${{ if parameters.publishSymbols }}: + - input: pipelineArtifact + artifactName: SymbolsInternal + path: $(Pipeline.Workspace)/Symbols + + steps: + - template: ../steps/find-PublishBranchAlias-task.yml + + - template: ../steps/download-signed-binaries-task.yml + parameters: + runID: ${{ parameters.publishExistingRunID }} + ReleaseJob: true + + - task: AzureFileCopy@6 + displayName: ↗️ Upload to blob storage + inputs: + Destination: AzureBlob + azureSubscription: golang-pme-storage + storage: $(blobBackupAccount) + ContainerName: microsoft + SourcePath: '$(Pipeline.Workspace)/Binaries Signed/*' + BlobPrefix: $(blobPrefix) + + - pwsh: | + Write-Host 'Generated links to artifacts in blob storage:' + Write-Host '' + Get-ChildItem -File -Path '.' | %{ + Write-Host "$(blobDestinationUrl)/$($_.Name)" + } + displayName: 🧾 Show expected uploaded URLs + workingDirectory: '$(Pipeline.Workspace)/Binaries Signed/' + + - ${{ if parameters.publishSymbols }}: - task: PublishSymbols@2 inputs: SymbolsFolder: $(Pipeline.Workspace)/Symbols @@ -175,4 +174,4 @@ stages: # in the AzDO repo, but we pull them at build time using a git submodule. # See https://github.com/microsoft/go-lab/issues/67. IndexSources: false - displayName: Publish symbols + displayName: ↗️ Publish symbols diff --git a/eng/pipeline/steps/download-signed-binaries-task.yml b/eng/pipeline/steps/download-signed-binaries-task.yml index dd3ca27a4a3..314f45ba12a 100644 --- a/eng/pipeline/steps/download-signed-binaries-task.yml +++ b/eng/pipeline/steps/download-signed-binaries-task.yml @@ -9,14 +9,43 @@ parameters: type: string default: 'nil' + - name: ReleaseJob + type: boolean + default: false + steps: - - ${{ if eq(parameters.runID, 'nil') }}: + - ${{ if parameters.ReleaseJob }}: + + - task: 1ES.DownloadPipelineArtifact@1 + displayName: 'Download: Binaries Signed' + inputs: + ${{ if eq(parameters.runID, 'nil') }}: + buildType: current + ${{ else }}: + buildType: specific + runVersion: 'specific' + runId: ${{ parameters.runID }} + project: $(System.TeamProject) + definition: $(System.DefinitionId) + artifactName: Binaries Signed + targetPath: '$(Pipeline.Workspace)/Binaries Signed' + + # The 1ES step tries to validate the SBOM manifests after download, so we can't assign + # 'patterns' to filter them out. Instead, remove them after validation is done. + - pwsh: | + Remove-Item -Path '$(Pipeline.Workspace)/Binaries Signed/_manifest' -Recurse -Force + displayName: Delete SBOM manifests + + - ${{ elseif eq(parameters.runID, 'nil') }}: + - download: current artifact: Binaries Signed # Filter out manifests added by 1ES pipeline template. patterns: '!_manifest/**' displayName: 'Download: Binaries Signed' + - ${{ else }}: + - task: DownloadPipelineArtifact@2 displayName: 'Download: Binaries Signed (Specific)' inputs: diff --git a/eng/pipeline/variables/publish-internal.yml b/eng/pipeline/variables/publish-internal.yml new file mode 100644 index 00000000000..e3fb6321b3d --- /dev/null +++ b/eng/pipeline/variables/publish-internal.yml @@ -0,0 +1,15 @@ +# Copyright (c) Microsoft Corporation. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# Variables that determine where to publish internal artifacts. + +variables: + - name: blobBackupAccount + value: golangartifactsbackup + - name: blobContainer + value: 'https://$(blobBackupAccount).blob.core.windows.net/microsoft' + - name: blobPrefix + value: '$(PublishBranchAlias)/$(Build.BuildNumber)' + - name: blobDestinationUrl + value: '$(blobContainer)/$(blobPrefix)' From c27a861f11d05d6837e5167a648e77842616ce9b Mon Sep 17 00:00:00 2001 From: qmuntal Date: Mon, 13 Jan 2025 09:24:18 +0100 Subject: [PATCH 03/12] update submodule to 44a6f817ea --- go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go b/go index 39f2032c175..44a6f817ea0 160000 --- a/go +++ b/go @@ -1 +1 @@ -Subproject commit 39f2032c17516a55c165d329dd5e2e07f49132b0 +Subproject commit 44a6f817ea0fbeb3ba4aa398794c4e80dba13b1e From 07598476a64f611e79846aedf0dd9d1b40ace872 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Mon, 13 Jan 2025 09:32:42 +0100 Subject: [PATCH 04/12] fix conflicts --- .../0002-Add-crypto-backend-foundation.patch | 131 ++++++++++-------- patches/0004-Add-OpenSSL-crypto-backend.patch | 18 +-- patches/0005-Add-CNG-crypto-backend.patch | 10 +- 3 files changed, 91 insertions(+), 68 deletions(-) diff --git a/patches/0002-Add-crypto-backend-foundation.patch b/patches/0002-Add-crypto-backend-foundation.patch index d5a9f151c16..99140818363 100644 --- a/patches/0002-Add-crypto-backend-foundation.patch +++ b/patches/0002-Add-crypto-backend-foundation.patch @@ -38,7 +38,7 @@ Subject: [PATCH] Add crypto backend foundation src/crypto/internal/backend/stub.s | 10 + src/crypto/internal/cryptotest/allocations.go | 2 +- .../internal/cryptotest/implementations.go | 2 +- - src/crypto/md5/md5.go | 7 + + src/crypto/md5/md5.go | 10 + src/crypto/md5/md5_test.go | 21 ++ src/crypto/pbkdf2/pbkdf2.go | 4 + src/crypto/pbkdf2/pbkdf2_test.go | 2 +- @@ -54,7 +54,7 @@ Subject: [PATCH] Add crypto backend foundation src/crypto/rsa/pss_test.go | 5 + src/crypto/rsa/rsa.go | 4 +- src/crypto/rsa/rsa_test.go | 12 +- - src/crypto/sha1/sha1.go | 2 +- + src/crypto/sha1/sha1.go | 8 +- src/crypto/sha1/sha1_test.go | 19 +- src/crypto/sha256/sha256.go | 6 +- src/crypto/sha256/sha256_test.go | 29 +++ @@ -66,8 +66,8 @@ Subject: [PATCH] Add crypto backend foundation src/crypto/tls/handshake_client.go | 12 +- src/crypto/tls/handshake_client_tls13.go | 16 +- src/crypto/tls/handshake_server.go | 10 +- - src/crypto/tls/handshake_server_tls13.go | 27 ++- - src/crypto/tls/internal/fips140tls/fipstls.go | 3 + src/crypto/tls/handshake_server_tls13.go | 27 +- + src/crypto/tls/internal/fips140tls/fipstls.go | 3 +- src/crypto/tls/internal/tls13/doc.go | 18 ++ src/crypto/tls/internal/tls13/tls13.go | 182 ++++++++++++++ src/crypto/tls/key_schedule.go | 2 +- @@ -79,7 +79,7 @@ Subject: [PATCH] Add crypto backend foundation src/hash/notboring_test.go | 9 + src/net/smtp/smtp_test.go | 72 ++++-- src/runtime/runtime_boring.go | 5 + - 75 files changed, 1426 insertions(+), 93 deletions(-) + 75 files changed, 1432 insertions(+), 96 deletions(-) create mode 100644 src/crypto/dsa/boring.go create mode 100644 src/crypto/dsa/notboring.go create mode 100644 src/crypto/ed25519/boring.go @@ -561,7 +561,7 @@ index 275c60b4de49eb..ff8bddf28c4545 100644 "math/big" ) diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go -index f682e6b1c6cfa6..049da55bd70f2c 100644 +index cb308b41e9df86..8f73855aa738de 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go @@ -20,8 +20,8 @@ import ( @@ -573,8 +573,8 @@ index f682e6b1c6cfa6..049da55bd70f2c 100644 + boring "crypto/internal/backend" + "crypto/internal/backend/bbig" "crypto/internal/fips140/ecdsa" + "crypto/internal/fips140hash" "crypto/internal/fips140only" - "crypto/internal/randutil" diff --git a/src/crypto/ecdsa/notboring.go b/src/crypto/ecdsa/notboring.go index 039bd82ed21f9f..69a97d9bf250be 100644 --- a/src/crypto/ecdsa/notboring.go @@ -819,7 +819,7 @@ index 00000000000000..b0cdd44d81c753 + panic("boringcrypto: not available") +} diff --git a/src/crypto/hkdf/hkdf.go b/src/crypto/hkdf/hkdf.go -index 7cfbe2c60de356..78139ed6170da5 100644 +index 6b02522866d57f..37e67ec184af5d 100644 --- a/src/crypto/hkdf/hkdf.go +++ b/src/crypto/hkdf/hkdf.go @@ -11,6 +11,7 @@ @@ -828,40 +828,40 @@ index 7cfbe2c60de356..78139ed6170da5 100644 import ( + boring "crypto/internal/backend" "crypto/internal/fips140/hkdf" + "crypto/internal/fips140hash" "crypto/internal/fips140only" - "errors" -@@ -27,6 +28,9 @@ func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { - if err := checkFIPS140Only(h, secret); err != nil { +@@ -29,6 +30,9 @@ func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + if err := checkFIPS140Only(fh, secret); err != nil { return nil, err } + if boring.Enabled && boring.SupportsHKDF() { -+ return boring.ExtractHKDF(func() hash.Hash { return h() }, secret, salt) ++ return boring.ExtractHKDF(fh, secret, salt) + } - return hkdf.Extract(h, secret, salt), nil + return hkdf.Extract(fh, secret, salt), nil } -@@ -47,6 +51,9 @@ func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen +@@ -50,6 +54,9 @@ func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen return nil, errors.New("hkdf: requested key length too large") } + if boring.Enabled && boring.SupportsHKDF() { -+ return boring.ExpandHKDF(func() hash.Hash { return h() }, pseudorandomKey, []byte(info), keyLength) ++ return boring.ExpandHKDF(fh, pseudorandomKey, []byte(info), keyLength) + } - return hkdf.Expand(h, pseudorandomKey, info, keyLength), nil + return hkdf.Expand(fh, pseudorandomKey, info, keyLength), nil } -@@ -63,6 +70,13 @@ func Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLen +@@ -67,6 +74,13 @@ func Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLen return nil, errors.New("hkdf: requested key length too large") } + if boring.Enabled && boring.SupportsHKDF() { -+ pseudorandomKey, err := boring.ExtractHKDF(func() hash.Hash { return h() }, secret, salt) ++ pseudorandomKey, err := boring.ExtractHKDF(fh, secret, salt) + if err != nil { + return nil, err + } -+ return boring.ExpandHKDF(func() hash.Hash { return h() }, pseudorandomKey, []byte(info), keyLength) ++ return boring.ExpandHKDF(fh, pseudorandomKey, []byte(info), keyLength) + } - return hkdf.Key(h, secret, salt, info, keyLength), nil + return hkdf.Key(fh, secret, salt, info, keyLength), nil } diff --git a/src/crypto/hkdf/hkdf_test.go b/src/crypto/hkdf/hkdf_test.go @@ -878,7 +878,7 @@ index 201b440289bb2d..4ed4960ff35b66 100644 "crypto/md5" "crypto/sha1" diff --git a/src/crypto/hmac/hmac.go b/src/crypto/hmac/hmac.go -index 72f5a4abea9d35..c88c6cbd128451 100644 +index 554c8c9b78940b..c68a394280cc2c 100644 --- a/src/crypto/hmac/hmac.go +++ b/src/crypto/hmac/hmac.go @@ -22,7 +22,7 @@ timing side-channels: @@ -888,8 +888,8 @@ index 72f5a4abea9d35..c88c6cbd128451 100644 - "crypto/internal/boring" + boring "crypto/internal/backend" "crypto/internal/fips140/hmac" + "crypto/internal/fips140hash" "crypto/internal/fips140only" - "crypto/subtle" diff --git a/src/crypto/hmac/hmac_test.go b/src/crypto/hmac/hmac_test.go index 7accad763244a1..dd3211f2c37af3 100644 --- a/src/crypto/hmac/hmac_test.go @@ -1433,7 +1433,7 @@ index 3fa730459050f6..1f28f12a6e7b4f 100644 "internal/goos" "internal/testenv" diff --git a/src/crypto/md5/md5.go b/src/crypto/md5/md5.go -index 75e1fc7404724a..60428f8e1201de 100644 +index a0384e175f31bd..f7aa6da36f02de 100644 --- a/src/crypto/md5/md5.go +++ b/src/crypto/md5/md5.go @@ -12,6 +12,7 @@ package md5 @@ -1444,21 +1444,24 @@ index 75e1fc7404724a..60428f8e1201de 100644 "crypto/internal/fips140only" "errors" "hash" -@@ -107,6 +108,9 @@ func New() hash.Hash { - if fips140only.Enabled { - panic("crypto/md5: use of MD5 is not allowed in FIPS 140-only mode") - } +@@ -104,6 +105,9 @@ func consumeUint32(b []byte) ([]byte, uint32) { + // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal + // state of the hash. + func New() hash.Hash { + if boring.Enabled && boring.SupportsHash(crypto.MD5) { + return boring.NewMD5() + } d := new(digest) d.Reset() return d -@@ -187,6 +191,9 @@ func Sum(data []byte) [Size]byte { - if fips140only.Enabled { - panic("crypto/md5: use of MD5 is not allowed in FIPS 140-only mode") - } +@@ -188,6 +192,12 @@ func (d *digest) checkSum() [Size]byte { + + // Sum returns the MD5 checksum of the data. + func Sum(data []byte) [Size]byte { + if boring.Enabled && boring.SupportsHash(crypto.MD5) { ++ if fips140only.Enabled { ++ panic("crypto/md5: use of MD5 is not allowed in FIPS 140-only mode") ++ } + return boring.MD5(data) + } var d digest @@ -1535,7 +1538,7 @@ index 437d9b9d4c0e0d..ee28c55f846e81 100644 continue } diff --git a/src/crypto/pbkdf2/pbkdf2.go b/src/crypto/pbkdf2/pbkdf2.go -index d40daab5e5b879..c32b3fd82b99b0 100644 +index 271d2b03312ef0..ff76299fbe4782 100644 --- a/src/crypto/pbkdf2/pbkdf2.go +++ b/src/crypto/pbkdf2/pbkdf2.go @@ -11,6 +11,7 @@ @@ -1544,16 +1547,16 @@ index d40daab5e5b879..c32b3fd82b99b0 100644 import ( + boring "crypto/internal/backend" "crypto/internal/fips140/pbkdf2" + "crypto/internal/fips140hash" "crypto/internal/fips140only" - "errors" -@@ -45,5 +46,8 @@ func Key[Hash hash.Hash](h func() Hash, password string, salt []byte, iter, keyL +@@ -47,5 +48,8 @@ func Key[Hash hash.Hash](h func() Hash, password string, salt []byte, iter, keyL return nil, errors.New("crypto/pbkdf2: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") } } + if boring.Enabled && boring.SupportsPBKDF2() { -+ return boring.PBKDF2([]byte(password), salt, iter, keyLength, func() hash.Hash { return h() }) ++ return boring.PBKDF2([]byte(password), salt, iter, keyLength, fh) + } - return pbkdf2.Key(h, password, salt, iter, keyLength) + return pbkdf2.Key(fh, password, salt, iter, keyLength) } diff --git a/src/crypto/pbkdf2/pbkdf2_test.go b/src/crypto/pbkdf2/pbkdf2_test.go index 03980c7e54d3be..4968a666fad4e5 100644 @@ -1686,7 +1689,7 @@ index 838fcc1244bdbe..d89f732345e8a3 100644 // Note: Can run these tests against the non-BoringCrypto // version of the code by using "CGO_ENABLED=0 go test". diff --git a/src/crypto/rsa/fips.go b/src/crypto/rsa/fips.go -index 24dfb38cf625bd..ccb027810a7e07 100644 +index 8373c125ae3096..bcc534151f9ac3 100644 --- a/src/crypto/rsa/fips.go +++ b/src/crypto/rsa/fips.go @@ -6,7 +6,7 @@ package rsa @@ -1696,9 +1699,9 @@ index 24dfb38cf625bd..ccb027810a7e07 100644 - "crypto/internal/boring" + boring "crypto/internal/backend" "crypto/internal/fips140/rsa" + "crypto/internal/fips140hash" "crypto/internal/fips140only" - "errors" -@@ -78,7 +78,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, +@@ -70,7 +70,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, hash = opts.Hash } @@ -1707,8 +1710,8 @@ index 24dfb38cf625bd..ccb027810a7e07 100644 bkey, err := boringPrivateKey(priv) if err != nil { return nil, err -@@ -136,7 +136,7 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts - return errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") +@@ -133,7 +133,7 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts + return err } - if boring.Enabled { @@ -1716,8 +1719,8 @@ index 24dfb38cf625bd..ccb027810a7e07 100644 bkey, err := boringPublicKey(pub) if err != nil { return err -@@ -249,7 +249,7 @@ func decryptOAEP(hash, mgfHash hash.Hash, priv *PrivateKey, ciphertext []byte, l - } +@@ -250,7 +250,7 @@ func decryptOAEP(hash, mgfHash hash.Hash, priv *PrivateKey, ciphertext []byte, l + return nil, err } - if boring.Enabled { @@ -1725,8 +1728,8 @@ index 24dfb38cf625bd..ccb027810a7e07 100644 k := priv.Size() if len(ciphertext) > k || k < hash.Size()*2+2 { -@@ -305,7 +305,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ - return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") +@@ -312,7 +312,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ + return nil, err } - if boring.Enabled { @@ -1830,7 +1833,7 @@ index e03f4ab06603c6..a4af0a2144870a 100644 err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts) good := test.good diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go -index fb23f003a6f217..be374dad6969d5 100644 +index 95bb4becd2ff8c..73991434dabaf1 100644 --- a/src/crypto/rsa/rsa.go +++ b/src/crypto/rsa/rsa.go @@ -42,8 +42,8 @@ package rsa @@ -1845,7 +1848,7 @@ index fb23f003a6f217..be374dad6969d5 100644 "crypto/internal/fips140/rsa" "crypto/internal/fips140only" diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go -index 2535661040273a..f9543d9cc89e7b 100644 +index 73b0c3749eedb2..b527a355074482 100644 --- a/src/crypto/rsa/rsa_test.go +++ b/src/crypto/rsa/rsa_test.go @@ -8,7 +8,7 @@ import ( @@ -1857,7 +1860,7 @@ index 2535661040273a..f9543d9cc89e7b 100644 "crypto/internal/cryptotest" "crypto/rand" . "crypto/rsa" -@@ -129,6 +129,11 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { +@@ -146,6 +146,11 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { if priv.D.Cmp(priv.N) > 0 { t.Errorf("private exponent too large") } @@ -1869,7 +1872,7 @@ index 2535661040273a..f9543d9cc89e7b 100644 msg := []byte("hi!") enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg) -@@ -209,6 +214,11 @@ func testEverything(t *testing.T, priv *PrivateKey) { +@@ -226,6 +231,11 @@ func testEverything(t *testing.T, priv *PrivateKey) { if err := priv.Validate(); err != nil { t.Errorf("Validate() failed: %s", err) } @@ -1882,7 +1885,7 @@ index 2535661040273a..f9543d9cc89e7b 100644 msg := []byte("test") enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg) diff --git a/src/crypto/sha1/sha1.go b/src/crypto/sha1/sha1.go -index b799f0d2fb1548..9aa23e9aa17e89 100644 +index d2ffaac0aeb674..23d8ad44d0bd9a 100644 --- a/src/crypto/sha1/sha1.go +++ b/src/crypto/sha1/sha1.go @@ -10,7 +10,7 @@ package sha1 @@ -1894,6 +1897,22 @@ index b799f0d2fb1548..9aa23e9aa17e89 100644 "crypto/internal/fips140only" "errors" "hash" +@@ -266,12 +266,12 @@ func (d *digest) constSum() [Size]byte { + + // Sum returns the SHA-1 checksum of the data. + func Sum(data []byte) [Size]byte { +- if boring.Enabled { +- return boring.SHA1(data) +- } + if fips140only.Enabled { + panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode") + } ++ if boring.Enabled { ++ return boring.SHA1(data) ++ } + var d digest + d.Reset() + d.Write(data) diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go index 9d707b7cde5c2d..8da08b3d860a85 100644 --- a/src/crypto/sha1/sha1_test.go @@ -2688,7 +2707,7 @@ index e7369542a73270..ff52175e4ac636 100644 } } diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index a62a5173b9c6bc..9ef5b8ea058783 100644 +index e3e01077c18b17..30811455e88418 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -493,6 +493,8 @@ var depsRules = ` @@ -2700,7 +2719,7 @@ index a62a5173b9c6bc..9ef5b8ea058783 100644 FIPS, internal/godebug < crypto/fips140; crypto, hash !< FIPS; -@@ -506,12 +508,15 @@ var depsRules = ` +@@ -506,7 +508,9 @@ var depsRules = ` FIPS, internal/godebug, hash, embed, crypto/internal/boring/sig, crypto/internal/boring/syso, @@ -2710,13 +2729,15 @@ index a62a5173b9c6bc..9ef5b8ea058783 100644 < crypto/internal/fips140only < crypto < crypto/subtle +@@ -514,6 +518,7 @@ var depsRules = ` + < crypto/internal/fips140hash < crypto/cipher < crypto/internal/boring + < crypto/internal/backend < crypto/boring < crypto/aes, crypto/des, -@@ -526,6 +531,7 @@ var depsRules = ` +@@ -527,6 +532,7 @@ var depsRules = ` crypto/pbkdf2, crypto/ecdh, crypto/mlkem @@ -2724,7 +2745,7 @@ index a62a5173b9c6bc..9ef5b8ea058783 100644 < CRYPTO; CGO, fmt, net !< CRYPTO; -@@ -534,6 +540,7 @@ var depsRules = ` +@@ -535,6 +541,7 @@ var depsRules = ` CRYPTO, FMT, math/big < crypto/internal/boring/bbig @@ -2732,7 +2753,7 @@ index a62a5173b9c6bc..9ef5b8ea058783 100644 < crypto/rand < crypto/ed25519 # depends on crypto/rand.Reader < encoding/asn1 -@@ -547,7 +554,7 @@ var depsRules = ` +@@ -548,7 +555,7 @@ var depsRules = ` # TLS, Prince of Dependencies. diff --git a/patches/0004-Add-OpenSSL-crypto-backend.patch b/patches/0004-Add-OpenSSL-crypto-backend.patch index 592110ad461..823455a0f40 100644 --- a/patches/0004-Add-OpenSSL-crypto-backend.patch +++ b/patches/0004-Add-OpenSSL-crypto-backend.patch @@ -492,10 +492,10 @@ index 00000000000000..44d91d5b7ba3d5 + return openssl.VerifyDSA(pub, hashed, sig) +} diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go -index f9543d9cc89e7b..f07c75821aab13 100644 +index b527a355074482..906c469482030a 100644 --- a/src/crypto/rsa/rsa_test.go +++ b/src/crypto/rsa/rsa_test.go -@@ -846,6 +846,9 @@ func TestDecryptOAEP(t *testing.T) { +@@ -863,6 +863,9 @@ func TestDecryptOAEP(t *testing.T) { } func Test2DecryptOAEP(t *testing.T) { @@ -528,10 +528,10 @@ index 9e661352f16e0b..e51f0f57540a83 100644 golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.32.1-0.20241206180132-552d8ac903a1 h1:+Yk1FZ5E+/ewA0nOO/HRYs9E4yeqpGOShuSAdzCNNoQ= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index b39db00839ab43..392f8d8c52c4b6 100644 +index 30811455e88418..3de94c93629e3d 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go -@@ -509,12 +509,14 @@ var depsRules = ` +@@ -509,7 +509,7 @@ var depsRules = ` crypto/internal/boring/sig, crypto/internal/boring/syso, encoding/binary, @@ -540,14 +540,16 @@ index b39db00839ab43..392f8d8c52c4b6 100644 crypto/internal/backend/fips140 < crypto/internal/fips140only < crypto - < crypto/subtle +@@ -517,6 +517,8 @@ var depsRules = ` + < crypto/sha3 + < crypto/internal/fips140hash < crypto/cipher + < github.com/golang-fips/openssl/v2/internal/subtle + < github.com/golang-fips/openssl/v2 < crypto/internal/boring < crypto/internal/backend < crypto/boring -@@ -538,6 +540,7 @@ var depsRules = ` +@@ -540,6 +542,7 @@ var depsRules = ` # CRYPTO-MATH is crypto that exposes math/big APIs - no cgo, net; fmt now ok. CRYPTO, FMT, math/big @@ -555,7 +557,7 @@ index b39db00839ab43..392f8d8c52c4b6 100644 < crypto/internal/boring/bbig < crypto/internal/backend/bbig < crypto/rand -@@ -842,7 +845,7 @@ var buildIgnore = []byte("\n//go:build ignore") +@@ -844,7 +847,7 @@ var buildIgnore = []byte("\n//go:build ignore") func findImports(pkg string) ([]string, error) { vpkg := pkg @@ -564,7 +566,7 @@ index b39db00839ab43..392f8d8c52c4b6 100644 vpkg = "vendor/" + pkg } dir := filepath.Join(Default.GOROOT, "src", vpkg) -@@ -852,7 +855,7 @@ func findImports(pkg string) ([]string, error) { +@@ -854,7 +857,7 @@ func findImports(pkg string) ([]string, error) { } var imports []string var haveImport = map[string]bool{} diff --git a/patches/0005-Add-CNG-crypto-backend.patch b/patches/0005-Add-CNG-crypto-backend.patch index bffe90d870b..fb3554d8d1b 100644 --- a/patches/0005-Add-CNG-crypto-backend.patch +++ b/patches/0005-Add-CNG-crypto-backend.patch @@ -511,12 +511,12 @@ index e51f0f57540a83..abebb59dcd7739 100644 golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.32.1-0.20241206180132-552d8ac903a1 h1:+Yk1FZ5E+/ewA0nOO/HRYs9E4yeqpGOShuSAdzCNNoQ= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index 392f8d8c52c4b6..997244c84e57c5 100644 +index 3de94c93629e3d..8effe9041f3f5f 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go -@@ -515,6 +515,10 @@ var depsRules = ` - < crypto - < crypto/subtle +@@ -517,6 +517,10 @@ var depsRules = ` + < crypto/sha3 + < crypto/internal/fips140hash < crypto/cipher + < github.com/microsoft/go-crypto-winnative/internal/subtle + < github.com/microsoft/go-crypto-winnative/internal/sysdll @@ -525,7 +525,7 @@ index 392f8d8c52c4b6..997244c84e57c5 100644 < github.com/golang-fips/openssl/v2/internal/subtle < github.com/golang-fips/openssl/v2 < crypto/internal/boring -@@ -540,6 +544,7 @@ var depsRules = ` +@@ -542,6 +546,7 @@ var depsRules = ` # CRYPTO-MATH is crypto that exposes math/big APIs - no cgo, net; fmt now ok. CRYPTO, FMT, math/big From b3541eb79231412946575f30255c4d61e4aed801 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Mon, 13 Jan 2025 10:33:57 +0100 Subject: [PATCH 05/12] centralize crypto backends GOEXPERIMENT definitions --- .../0001-Add-systemcrypto-GOEXPERIMENT.patch | 104 ++++++++++++++---- patches/0004-Add-OpenSSL-crypto-backend.patch | 49 +-------- patches/0005-Add-CNG-crypto-backend.patch | 71 ++---------- 3 files changed, 97 insertions(+), 127 deletions(-) diff --git a/patches/0001-Add-systemcrypto-GOEXPERIMENT.patch b/patches/0001-Add-systemcrypto-GOEXPERIMENT.patch index 1c2e50368f3..38e1ae8445b 100644 --- a/patches/0001-Add-systemcrypto-GOEXPERIMENT.patch +++ b/patches/0001-Add-systemcrypto-GOEXPERIMENT.patch @@ -3,7 +3,7 @@ From: Davis Goodin Date: Wed, 31 May 2023 16:54:31 -0500 Subject: [PATCH] Add systemcrypto GOEXPERIMENT -Adds systemcrypto GOEXPERIMENT and modifies tag handling to make +Adds crypto backend GOEXPERIMENTs and modifies tag handling to make goexperiment.systemcrypto behave as an alias that enables the recommended backend for the target GOOS. See src/internal/goexperiment/flags.go for more information about the behavior. @@ -19,24 +19,32 @@ maintain this feature. For more information, see the test files. .../testdata/backendtags_openssl/openssl.go | 3 + .../build/testdata/backendtags_system/main.go | 3 + .../backendtags_system/systemcrypto.go | 3 + - .../goexperiment/exp_systemcrypto_off.go | 9 +++ - .../goexperiment/exp_systemcrypto_on.go | 9 +++ - src/internal/goexperiment/flags.go | 15 ++++ - 11 files changed, 292 insertions(+) + .../goexperiment/exp_cngcrypto_off.go | 8 ++ + src/internal/goexperiment/exp_cngcrypto_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 | 17 +++++ + 15 files changed, 324 insertions(+) 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_openssl/main.go create mode 100644 src/go/build/testdata/backendtags_openssl/openssl.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_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 diff --git a/src/cmd/go/internal/modindex/build.go b/src/cmd/go/internal/modindex/build.go -index b57f2f6368f0fe..9ddde1ce9a2286 100644 +index b4dacb0f523a8d..615ae461eb8cdc 100644 --- a/src/cmd/go/internal/modindex/build.go +++ b/src/cmd/go/internal/modindex/build.go -@@ -880,13 +880,67 @@ func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool { +@@ -886,13 +886,67 @@ func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool { name = "goexperiment.boringcrypto" // boringcrypto is an old name for goexperiment.boringcrypto } @@ -184,10 +192,10 @@ index 00000000000000..1756c5d027fee0 + } +} diff --git a/src/go/build/build.go b/src/go/build/build.go -index dd6cdc903a21a8..48adcfed5cf3cb 100644 +index 9ffffda08a99b1..570937cba3cb85 100644 --- a/src/go/build/build.go +++ b/src/go/build/build.go -@@ -1947,13 +1947,67 @@ func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool { +@@ -1984,13 +1984,67 @@ func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool { name = "goexperiment.boringcrypto" // boringcrypto is an old name for goexperiment.boringcrypto } @@ -363,16 +371,71 @@ index 00000000000000..eb8a026982259c +//go:build goexperiment.systemcrypto + +package main +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_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..bd33cd6159c166 +index 00000000000000..6afc2ef2c5822e --- /dev/null +++ b/src/internal/goexperiment/exp_systemcrypto_off.go -@@ -0,0 +1,9 @@ +@@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.systemcrypto -+// +build !goexperiment.systemcrypto + +package goexperiment + @@ -380,27 +443,29 @@ index 00000000000000..bd33cd6159c166 +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..9c5b0bbc7b99dc +index 00000000000000..fcd4cb9da0d162 --- /dev/null +++ b/src/internal/goexperiment/exp_systemcrypto_on.go -@@ -0,0 +1,9 @@ +@@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.systemcrypto -+// +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 ae3cbaf89fa5dd..de79140b2d4780 100644 +index 31b3d0315b64f8..8c140f0dbed134 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go -@@ -60,6 +60,21 @@ type Flags struct { +@@ -59,6 +59,23 @@ type Flags struct { + PreemptibleLoops bool StaticLockRanking bool BoringCrypto bool - ++ OpenSSLCrypto bool ++ CNGCrypto bool ++ + // SystemCrypto enables the OpenSSL or CNG crypto experiment depending on + // which one is appropriate on the target GOOS. + // @@ -415,7 +480,6 @@ index ae3cbaf89fa5dd..de79140b2d4780 100644 + // "any crypto backend is enabled", even if GOEXPERIMENT=systemcrypto is not + // being used to build the Go program. + SystemCrypto 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/patches/0004-Add-OpenSSL-crypto-backend.patch b/patches/0004-Add-OpenSSL-crypto-backend.patch index 823455a0f40..4f0f799e95f 100644 --- a/patches/0004-Add-OpenSSL-crypto-backend.patch +++ b/patches/0004-Add-OpenSSL-crypto-backend.patch @@ -15,16 +15,11 @@ Subject: [PATCH] Add OpenSSL crypto backend src/go.sum | 2 + src/go/build/deps_test.go | 9 +- src/go/build/vendor_test.go | 1 + - .../goexperiment/exp_opensslcrypto_off.go | 9 + - .../goexperiment/exp_opensslcrypto_on.go | 9 + - src/internal/goexperiment/flags.go | 1 + src/os/exec/exec_test.go | 9 + - 15 files changed, 450 insertions(+), 5 deletions(-) + 12 files changed, 431 insertions(+), 5 deletions(-) create mode 100644 src/crypto/internal/backend/bbig/big_openssl.go create mode 100644 src/crypto/internal/backend/fips140/openssl.go create mode 100644 src/crypto/internal/backend/openssl_linux.go - create mode 100644 src/internal/goexperiment/exp_opensslcrypto_off.go - create mode 100644 src/internal/goexperiment/exp_opensslcrypto_on.go diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 0c992118f4287b..0de6e80fd985a3 100644 @@ -587,48 +582,6 @@ index 7f6237ffd59c11..7c821ae4bc5727 100644 } // Verify that the vendor directories contain only packages matching the list above. -diff --git a/src/internal/goexperiment/exp_opensslcrypto_off.go b/src/internal/goexperiment/exp_opensslcrypto_off.go -new file mode 100644 -index 00000000000000..62033547c6143a ---- /dev/null -+++ b/src/internal/goexperiment/exp_opensslcrypto_off.go -@@ -0,0 +1,9 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.opensslcrypto -+// +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..a7f2712e9e1464 ---- /dev/null -+++ b/src/internal/goexperiment/exp_opensslcrypto_on.go -@@ -0,0 +1,9 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.opensslcrypto -+// +build goexperiment.opensslcrypto -+ -+package goexperiment -+ -+const OpenSSLCrypto = true -+const OpenSSLCryptoInt = 1 -diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go -index e126e388e84025..233a12ee542328 100644 ---- a/src/internal/goexperiment/flags.go -+++ b/src/internal/goexperiment/flags.go -@@ -59,6 +59,7 @@ type Flags struct { - PreemptibleLoops bool - StaticLockRanking bool - BoringCrypto bool -+ OpenSSLCrypto bool - - // SystemCrypto enables the OpenSSL or CNG crypto experiment depending on - // which one is appropriate on the target GOOS. diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 8c623871932f7d..2fa55073f5c19c 100644 --- a/src/os/exec/exec_test.go diff --git a/patches/0005-Add-CNG-crypto-backend.patch b/patches/0005-Add-CNG-crypto-backend.patch index fb3554d8d1b..4bdd4c4811b 100644 --- a/patches/0005-Add-CNG-crypto-backend.patch +++ b/patches/0005-Add-CNG-crypto-backend.patch @@ -4,27 +4,22 @@ Date: Tue, 19 Jul 2022 15:58:02 +0200 Subject: [PATCH] Add CNG crypto backend --- - src/crypto/ecdsa/badlinkname.go | 17 + - src/crypto/internal/backend/backend_test.go | 4 +- - src/crypto/internal/backend/bbig/big_cng.go | 12 + - src/crypto/internal/backend/cng_windows.go | 320 ++++++++++++++++++ - src/crypto/internal/backend/common.go | 9 +- - src/crypto/internal/backend/fips140/cng.go | 33 ++ - src/crypto/rsa/pss_test.go | 2 +- - src/go.mod | 1 + - src/go.sum | 2 + - src/go/build/deps_test.go | 5 + - src/go/build/vendor_test.go | 1 + - .../goexperiment/exp_cngcrypto_off.go | 9 + - src/internal/goexperiment/exp_cngcrypto_on.go | 9 + - src/internal/goexperiment/flags.go | 1 + - 14 files changed, 420 insertions(+), 5 deletions(-) + src/crypto/ecdsa/badlinkname.go | 17 ++ + src/crypto/internal/backend/backend_test.go | 4 +- + src/crypto/internal/backend/bbig/big_cng.go | 12 + + src/crypto/internal/backend/cng_windows.go | 320 ++++++++++++++++++++ + src/crypto/internal/backend/common.go | 9 +- + src/crypto/internal/backend/fips140/cng.go | 33 ++ + src/crypto/rsa/pss_test.go | 2 +- + src/go.mod | 1 + + src/go.sum | 2 + + src/go/build/deps_test.go | 5 + + src/go/build/vendor_test.go | 1 + + 11 files changed, 401 insertions(+), 5 deletions(-) create mode 100644 src/crypto/ecdsa/badlinkname.go create mode 100644 src/crypto/internal/backend/bbig/big_cng.go create mode 100644 src/crypto/internal/backend/cng_windows.go create mode 100644 src/crypto/internal/backend/fips140/cng.go - create mode 100644 src/internal/goexperiment/exp_cngcrypto_off.go - create mode 100644 src/internal/goexperiment/exp_cngcrypto_on.go diff --git a/src/crypto/ecdsa/badlinkname.go b/src/crypto/ecdsa/badlinkname.go new file mode 100644 @@ -545,45 +540,3 @@ index 7c821ae4bc5727..1d0b9b20e9b1d4 100644 } // Verify that the vendor directories contain only packages matching the list above. -diff --git a/src/internal/goexperiment/exp_cngcrypto_off.go b/src/internal/goexperiment/exp_cngcrypto_off.go -new file mode 100644 -index 00000000000000..831460053281e2 ---- /dev/null -+++ b/src/internal/goexperiment/exp_cngcrypto_off.go -@@ -0,0 +1,9 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build !goexperiment.cngcrypto -+// +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..99ee2542ca38a9 ---- /dev/null -+++ b/src/internal/goexperiment/exp_cngcrypto_on.go -@@ -0,0 +1,9 @@ -+// Code generated by mkconsts.go. DO NOT EDIT. -+ -+//go:build goexperiment.cngcrypto -+// +build goexperiment.cngcrypto -+ -+package goexperiment -+ -+const CNGCrypto = true -+const CNGCryptoInt = 1 -diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go -index 233a12ee542328..8c140f0dbed134 100644 ---- a/src/internal/goexperiment/flags.go -+++ b/src/internal/goexperiment/flags.go -@@ -60,6 +60,7 @@ type Flags struct { - StaticLockRanking bool - BoringCrypto bool - OpenSSLCrypto bool -+ CNGCrypto bool - - // SystemCrypto enables the OpenSSL or CNG crypto experiment depending on - // which one is appropriate on the target GOOS. From 1debdcc219c0dda014c80246fd28c8e595d00b64 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:36:18 +0000 Subject: [PATCH 06/12] build(deps): bump github/codeql-action from 3.28.0 to 3.28.1 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.0 to 3.28.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/48ab28a6f5dbc2a99bf1e0131198dd8f1df78169...b6a472f63d85b9c78a3ac5e89422239fc15e9b3c) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d61b4590e0f..b0538026046 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -23,16 +23,16 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Initialize CodeQL - uses: github/codeql-action/init@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 + uses: github/codeql-action/init@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 with: languages: go - name: Autobuild - uses: github/codeql-action/autobuild@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 + uses: github/codeql-action/autobuild@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 with: working-directory: eng/_util - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0 + uses: github/codeql-action/analyze@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1 with: category: /language:go From 09f1d99312b2bad603c8a506059dfe5f74a59f54 Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Mon, 13 Jan 2025 20:31:14 +0100 Subject: [PATCH 07/12] Rename patch file --- ...MENT.patch => 0001-Add-crypto-backend-GOEXPERIMENTs.patch} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename patches/{0001-Add-systemcrypto-GOEXPERIMENT.patch => 0001-Add-crypto-backend-GOEXPERIMENTs.patch} (99%) diff --git a/patches/0001-Add-systemcrypto-GOEXPERIMENT.patch b/patches/0001-Add-crypto-backend-GOEXPERIMENTs.patch similarity index 99% rename from patches/0001-Add-systemcrypto-GOEXPERIMENT.patch rename to patches/0001-Add-crypto-backend-GOEXPERIMENTs.patch index 38e1ae8445b..27387faef14 100644 --- a/patches/0001-Add-systemcrypto-GOEXPERIMENT.patch +++ b/patches/0001-Add-crypto-backend-GOEXPERIMENTs.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Wed, 31 May 2023 16:54:31 -0500 -Subject: [PATCH] Add systemcrypto GOEXPERIMENT +Subject: [PATCH] Add crypto backend GOEXPERIMENTs Adds crypto backend GOEXPERIMENTs and modifies tag handling to make goexperiment.systemcrypto behave as an alias that enables the recommended @@ -482,4 +482,4 @@ index 31b3d0315b64f8..8c140f0dbed134 100644 + SystemCrypto bool // Regabi is split into several sub-experiments that can be - // enabled individually. Not all combinations work. + // enabled individually. Not all combinations work. \ No newline at end of file From 8fe8183d617f8f456f96cd0ff2ca58f57b5f5907 Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Mon, 13 Jan 2025 20:34:50 +0100 Subject: [PATCH 08/12] Fix newline at end of file From bc5af7d4cfcaf689130183105cb13b13d057d7e5 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Mon, 13 Jan 2025 20:38:06 +0100 Subject: [PATCH 09/12] add newline --- patches/0001-Add-crypto-backend-GOEXPERIMENTs.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/0001-Add-crypto-backend-GOEXPERIMENTs.patch b/patches/0001-Add-crypto-backend-GOEXPERIMENTs.patch index 27387faef14..8d07cee4e4e 100644 --- a/patches/0001-Add-crypto-backend-GOEXPERIMENTs.patch +++ b/patches/0001-Add-crypto-backend-GOEXPERIMENTs.patch @@ -482,4 +482,4 @@ index 31b3d0315b64f8..8c140f0dbed134 100644 + SystemCrypto bool // Regabi is split into several sub-experiments that can be - // enabled individually. Not all combinations work. \ No newline at end of file + // enabled individually. Not all combinations work. From 7ef39ed1ba33de557048ec76709b9c7147780248 Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Tue, 14 Jan 2025 08:52:21 +0100 Subject: [PATCH 10/12] Add backend external deps in the vendor patch (#1483) * add backend external deps in the vendor patch * Update CNG crypto backend and foundation dates * Apply suggestions from code review Co-authored-by: Davis Goodin * fix comments --------- Co-authored-by: Davis Goodin --- ...atch => 0002-Vendor-crypto-backends.patch} | 56 ++++++++++++++++++- ... 0003-Add-crypto-backend-foundation.patch} | 0 ...> 0004-Add-BoringSSL-crypto-backend.patch} | 0 ... => 0005-Add-OpenSSL-crypto-backend.patch} | 26 +-------- ...atch => 0006-Add-CNG-crypto-backend.patch} | 28 +--------- 5 files changed, 56 insertions(+), 54 deletions(-) rename patches/{0006-Vendor-crypto-backends.patch => 0002-Vendor-crypto-backends.patch} (99%) rename patches/{0002-Add-crypto-backend-foundation.patch => 0003-Add-crypto-backend-foundation.patch} (100%) rename patches/{0003-Add-BoringSSL-crypto-backend.patch => 0004-Add-BoringSSL-crypto-backend.patch} (100%) rename patches/{0004-Add-OpenSSL-crypto-backend.patch => 0005-Add-OpenSSL-crypto-backend.patch} (94%) rename patches/{0005-Add-CNG-crypto-backend.patch => 0006-Add-CNG-crypto-backend.patch} (92%) diff --git a/patches/0006-Vendor-crypto-backends.patch b/patches/0002-Vendor-crypto-backends.patch similarity index 99% rename from patches/0006-Vendor-crypto-backends.patch rename to patches/0002-Vendor-crypto-backends.patch index 24e3632a13f..264f3b12012 100644 --- a/patches/0006-Vendor-crypto-backends.patch +++ b/patches/0002-Vendor-crypto-backends.patch @@ -3,8 +3,12 @@ From: Quim Muntal Date: Mon, 23 May 2022 12:59:36 +0000 Subject: [PATCH] Vendor crypto backends -To reproduce, run 'go mod vendor' in 'go/src'. +To reproduce changes in 'src/vendor', run 'go mod vendor' in 'src'. +Use a 'go' that was recently built by the current branch to ensure stable results. --- + src/crypto/internal/backend/deps_ignore.go | 16 + + src/go.mod | 5 + + src/go.sum | 4 + .../golang-fips/openssl/v2/.gitignore | 1 + .../golang-fips/openssl/v2/.gitleaks.toml | 9 + .../github.com/golang-fips/openssl/v2/LICENSE | 20 + @@ -69,7 +73,8 @@ To reproduce, run 'go mod vendor' in 'go/src'. .../internal/subtle/aliasing.go | 32 + .../internal/sysdll/sys_windows.go | 55 ++ src/vendor/modules.txt | 11 + - 64 files changed, 10969 insertions(+), 6 deletions(-) + 67 files changed, 11000 insertions(+) + create mode 100644 src/crypto/internal/backend/deps_ignore.go create mode 100644 src/vendor/github.com/golang-fips/openssl/v2/.gitignore create mode 100644 src/vendor/github.com/golang-fips/openssl/v2/.gitleaks.toml create mode 100644 src/vendor/github.com/golang-fips/openssl/v2/LICENSE @@ -134,6 +139,53 @@ To reproduce, run 'go mod vendor' in 'go/src'. create mode 100644 src/vendor/github.com/microsoft/go-crypto-winnative/internal/subtle/aliasing.go create mode 100644 src/vendor/github.com/microsoft/go-crypto-winnative/internal/sysdll/sys_windows.go +diff --git a/src/crypto/internal/backend/deps_ignore.go b/src/crypto/internal/backend/deps_ignore.go +new file mode 100644 +index 00000000000000..7e537a55af954e +--- /dev/null ++++ b/src/crypto/internal/backend/deps_ignore.go +@@ -0,0 +1,16 @@ ++// 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. ++ ++//go:build ignore ++ ++package backend ++ ++import ( ++ _ "github.com/golang-fips/openssl/v2" ++ _ "github.com/microsoft/go-crypto-winnative/cng" ++) ++ ++// This file is here just to declare the external dependencies ++// that are used by the backend package. This allows to track ++// their versions in a single patch file. +diff --git a/src/go.mod b/src/go.mod +index 7a1318dcac32ba..4ca039fa96ba3c 100644 +--- a/src/go.mod ++++ b/src/go.mod +@@ -11,3 +11,8 @@ require ( + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect + ) ++ ++require ( ++ github.com/golang-fips/openssl/v2 v2.0.4-0.20250107115006-eb155dada337 ++ github.com/microsoft/go-crypto-winnative v0.0.0-20250108090702-b49854c00e37 ++) +diff --git a/src/go.sum b/src/go.sum +index 9e661352f16e0b..abebb59dcd7739 100644 +--- a/src/go.sum ++++ b/src/go.sum +@@ -1,3 +1,7 @@ ++github.com/golang-fips/openssl/v2 v2.0.4-0.20250107115006-eb155dada337 h1:OhuURhDVbg+f/BvlG+qT5sQVkutwhI0Kmsy7koQ4l9A= ++github.com/golang-fips/openssl/v2 v2.0.4-0.20250107115006-eb155dada337/go.mod h1:OYUBsoxLpFu8OFyhZHxfpN8lgcsw8JhTC3BQK7+XUc0= ++github.com/microsoft/go-crypto-winnative v0.0.0-20250108090702-b49854c00e37 h1:KB8xmJcFSPlZFMg2mxz5b6DCE8k1qpHy2HFevAJLELI= ++github.com/microsoft/go-crypto-winnative v0.0.0-20250108090702-b49854c00e37/go.mod h1:JkxQeL8dGcyCuKjn1Etz4NmQrOMImMy4BA9hptEfVFA= + golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= + golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= + golang.org/x/net v0.32.1-0.20241206180132-552d8ac903a1 h1:+Yk1FZ5E+/ewA0nOO/HRYs9E4yeqpGOShuSAdzCNNoQ= diff --git a/src/vendor/github.com/golang-fips/openssl/v2/.gitignore b/src/vendor/github.com/golang-fips/openssl/v2/.gitignore new file mode 100644 index 00000000000000..79b5594df7fa29 diff --git a/patches/0002-Add-crypto-backend-foundation.patch b/patches/0003-Add-crypto-backend-foundation.patch similarity index 100% rename from patches/0002-Add-crypto-backend-foundation.patch rename to patches/0003-Add-crypto-backend-foundation.patch diff --git a/patches/0003-Add-BoringSSL-crypto-backend.patch b/patches/0004-Add-BoringSSL-crypto-backend.patch similarity index 100% rename from patches/0003-Add-BoringSSL-crypto-backend.patch rename to patches/0004-Add-BoringSSL-crypto-backend.patch diff --git a/patches/0004-Add-OpenSSL-crypto-backend.patch b/patches/0005-Add-OpenSSL-crypto-backend.patch similarity index 94% rename from patches/0004-Add-OpenSSL-crypto-backend.patch rename to patches/0005-Add-OpenSSL-crypto-backend.patch index 4f0f799e95f..648570df40b 100644 --- a/patches/0004-Add-OpenSSL-crypto-backend.patch +++ b/patches/0005-Add-OpenSSL-crypto-backend.patch @@ -11,12 +11,10 @@ Subject: [PATCH] Add OpenSSL crypto backend .../internal/backend/fips140/openssl.go | 41 +++ src/crypto/internal/backend/openssl_linux.go | 345 ++++++++++++++++++ src/crypto/rsa/rsa_test.go | 3 + - src/go.mod | 1 + - src/go.sum | 2 + src/go/build/deps_test.go | 9 +- src/go/build/vendor_test.go | 1 + src/os/exec/exec_test.go | 9 + - 12 files changed, 431 insertions(+), 5 deletions(-) + 10 files changed, 428 insertions(+), 5 deletions(-) create mode 100644 src/crypto/internal/backend/bbig/big_openssl.go create mode 100644 src/crypto/internal/backend/fips140/openssl.go create mode 100644 src/crypto/internal/backend/openssl_linux.go @@ -500,28 +498,6 @@ index b527a355074482..906c469482030a 100644 random := rand.Reader msg := []byte{0xed, 0x36, 0x90, 0x8d, 0xbe, 0xfc, 0x35, 0x40, 0x70, 0x4f, 0xf5, 0x9d, 0x6e, 0xc2, 0xeb, 0xf5, 0x27, 0xae, 0x65, 0xb0, 0x59, 0x29, 0x45, 0x25, 0x8c, 0xc1, 0x91, 0x22} -diff --git a/src/go.mod b/src/go.mod -index 7a1318dcac32ba..f12d9b4d9172ab 100644 ---- a/src/go.mod -+++ b/src/go.mod -@@ -3,6 +3,7 @@ module std - go 1.24 - - require ( -+ github.com/golang-fips/openssl/v2 v2.0.4-0.20250107115006-eb155dada337 - golang.org/x/crypto v0.30.0 - golang.org/x/net v0.32.1-0.20241206180132-552d8ac903a1 - ) -diff --git a/src/go.sum b/src/go.sum -index 9e661352f16e0b..e51f0f57540a83 100644 ---- a/src/go.sum -+++ b/src/go.sum -@@ -1,3 +1,5 @@ -+github.com/golang-fips/openssl/v2 v2.0.4-0.20250107115006-eb155dada337 h1:OhuURhDVbg+f/BvlG+qT5sQVkutwhI0Kmsy7koQ4l9A= -+github.com/golang-fips/openssl/v2 v2.0.4-0.20250107115006-eb155dada337/go.mod h1:OYUBsoxLpFu8OFyhZHxfpN8lgcsw8JhTC3BQK7+XUc0= - golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= - golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= - golang.org/x/net v0.32.1-0.20241206180132-552d8ac903a1 h1:+Yk1FZ5E+/ewA0nOO/HRYs9E4yeqpGOShuSAdzCNNoQ= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 30811455e88418..3de94c93629e3d 100644 --- a/src/go/build/deps_test.go diff --git a/patches/0005-Add-CNG-crypto-backend.patch b/patches/0006-Add-CNG-crypto-backend.patch similarity index 92% rename from patches/0005-Add-CNG-crypto-backend.patch rename to patches/0006-Add-CNG-crypto-backend.patch index 4bdd4c4811b..5b5ed57f448 100644 --- a/patches/0005-Add-CNG-crypto-backend.patch +++ b/patches/0006-Add-CNG-crypto-backend.patch @@ -11,11 +11,9 @@ Subject: [PATCH] Add CNG crypto backend src/crypto/internal/backend/common.go | 9 +- src/crypto/internal/backend/fips140/cng.go | 33 ++ src/crypto/rsa/pss_test.go | 2 +- - src/go.mod | 1 + - src/go.sum | 2 + src/go/build/deps_test.go | 5 + src/go/build/vendor_test.go | 1 + - 11 files changed, 401 insertions(+), 5 deletions(-) + 9 files changed, 398 insertions(+), 5 deletions(-) create mode 100644 src/crypto/ecdsa/badlinkname.go create mode 100644 src/crypto/internal/backend/bbig/big_cng.go create mode 100644 src/crypto/internal/backend/cng_windows.go @@ -481,30 +479,6 @@ index a4af0a2144870a..7d7115cff81cea 100644 if err != nil { t.Fatal(err) } -diff --git a/src/go.mod b/src/go.mod -index f12d9b4d9172ab..96bdcd421e1129 100644 ---- a/src/go.mod -+++ b/src/go.mod -@@ -4,6 +4,7 @@ go 1.24 - - require ( - github.com/golang-fips/openssl/v2 v2.0.4-0.20250107115006-eb155dada337 -+ github.com/microsoft/go-crypto-winnative v0.0.0-20250108090702-b49854c00e37 - golang.org/x/crypto v0.30.0 - golang.org/x/net v0.32.1-0.20241206180132-552d8ac903a1 - ) -diff --git a/src/go.sum b/src/go.sum -index e51f0f57540a83..abebb59dcd7739 100644 ---- a/src/go.sum -+++ b/src/go.sum -@@ -1,5 +1,7 @@ - github.com/golang-fips/openssl/v2 v2.0.4-0.20250107115006-eb155dada337 h1:OhuURhDVbg+f/BvlG+qT5sQVkutwhI0Kmsy7koQ4l9A= - github.com/golang-fips/openssl/v2 v2.0.4-0.20250107115006-eb155dada337/go.mod h1:OYUBsoxLpFu8OFyhZHxfpN8lgcsw8JhTC3BQK7+XUc0= -+github.com/microsoft/go-crypto-winnative v0.0.0-20250108090702-b49854c00e37 h1:KB8xmJcFSPlZFMg2mxz5b6DCE8k1qpHy2HFevAJLELI= -+github.com/microsoft/go-crypto-winnative v0.0.0-20250108090702-b49854c00e37/go.mod h1:JkxQeL8dGcyCuKjn1Etz4NmQrOMImMy4BA9hptEfVFA= - golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= - golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= - golang.org/x/net v0.32.1-0.20241206180132-552d8ac903a1 h1:+Yk1FZ5E+/ewA0nOO/HRYs9E4yeqpGOShuSAdzCNNoQ= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 3de94c93629e3d..8effe9041f3f5f 100644 --- a/src/go/build/deps_test.go From 9cf47877181eb12dea68893654f8d371beda6a42 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Tue, 14 Jan 2025 10:45:11 +0100 Subject: [PATCH 11/12] clean up patch files --- patches/0002-Vendor-crypto-backends.patch | 16 ++- .../0003-Add-crypto-backend-foundation.patch | 135 +++++++++++++----- .../0004-Add-BoringSSL-crypto-backend.patch | 16 ++- patches/0005-Add-OpenSSL-crypto-backend.patch | 71 +++------ patches/0006-Add-CNG-crypto-backend.patch | 112 ++------------- 5 files changed, 154 insertions(+), 196 deletions(-) diff --git a/patches/0002-Vendor-crypto-backends.patch b/patches/0002-Vendor-crypto-backends.patch index 264f3b12012..27f1d7f925f 100644 --- a/patches/0002-Vendor-crypto-backends.patch +++ b/patches/0002-Vendor-crypto-backends.patch @@ -9,6 +9,7 @@ Use a 'go' that was recently built by the current branch to ensure stable result src/crypto/internal/backend/deps_ignore.go | 16 + src/go.mod | 5 + src/go.sum | 4 + + src/go/build/vendor_test.go | 2 + .../golang-fips/openssl/v2/.gitignore | 1 + .../golang-fips/openssl/v2/.gitleaks.toml | 9 + .../github.com/golang-fips/openssl/v2/LICENSE | 20 + @@ -73,7 +74,7 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../internal/subtle/aliasing.go | 32 + .../internal/sysdll/sys_windows.go | 55 ++ src/vendor/modules.txt | 11 + - 67 files changed, 11000 insertions(+) + 68 files changed, 11002 insertions(+) create mode 100644 src/crypto/internal/backend/deps_ignore.go create mode 100644 src/vendor/github.com/golang-fips/openssl/v2/.gitignore create mode 100644 src/vendor/github.com/golang-fips/openssl/v2/.gitleaks.toml @@ -186,6 +187,19 @@ index 9e661352f16e0b..abebb59dcd7739 100644 golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/net v0.32.1-0.20241206180132-552d8ac903a1 h1:+Yk1FZ5E+/ewA0nOO/HRYs9E4yeqpGOShuSAdzCNNoQ= +diff --git a/src/go/build/vendor_test.go b/src/go/build/vendor_test.go +index 7f6237ffd59c11..1d0b9b20e9b1d4 100644 +--- a/src/go/build/vendor_test.go ++++ b/src/go/build/vendor_test.go +@@ -22,6 +22,8 @@ var allowedPackagePrefixes = []string{ + "github.com/google/pprof", + "github.com/ianlancetaylor/demangle", + "rsc.io/markdown", ++ "github.com/golang-fips/openssl", ++ "github.com/microsoft/go-crypto-winnative", + } + + // Verify that the vendor directories contain only packages matching the list above. diff --git a/src/vendor/github.com/golang-fips/openssl/v2/.gitignore b/src/vendor/github.com/golang-fips/openssl/v2/.gitignore new file mode 100644 index 00000000000000..79b5594df7fa29 diff --git a/patches/0003-Add-crypto-backend-foundation.patch b/patches/0003-Add-crypto-backend-foundation.patch index 99140818363..32a93ef2774 100644 --- a/patches/0003-Add-crypto-backend-foundation.patch +++ b/patches/0003-Add-crypto-backend-foundation.patch @@ -6,6 +6,7 @@ Subject: [PATCH] Add crypto backend foundation --- src/cmd/api/boring_test.go | 2 +- src/cmd/go/go_boring_test.go | 2 +- + .../go/testdata/script/gopath_std_vendor.txt | 9 + src/crypto/aes/aes.go | 2 +- src/crypto/boring/boring.go | 4 +- src/crypto/cipher/ctr_aes_test.go | 2 +- @@ -17,6 +18,7 @@ Subject: [PATCH] Add crypto backend foundation src/crypto/ecdh/ecdh.go | 2 +- src/crypto/ecdh/ecdh_test.go | 4 + src/crypto/ecdh/nist.go | 2 +- + src/crypto/ecdsa/badlinkname.go | 19 ++ src/crypto/ecdsa/boring.go | 6 +- src/crypto/ecdsa/ecdsa.go | 4 +- src/crypto/ecdsa/notboring.go | 4 +- @@ -29,12 +31,12 @@ Subject: [PATCH] Add crypto backend foundation src/crypto/hmac/hmac_test.go | 2 +- src/crypto/internal/backend/backend_test.go | 30 +++ src/crypto/internal/backend/bbig/big.go | 17 ++ - src/crypto/internal/backend/common.go | 72 ++++++ - .../internal/backend/fips140/fips140.go | 55 +++++ + src/crypto/internal/backend/common.go | 58 +++++ + .../internal/backend/fips140/fips140.go | 55 ++++ .../internal/backend/fips140/isrequirefips.go | 9 + .../internal/backend/fips140/norequirefips.go | 9 + .../backend/fips140/nosystemcrypto.go | 11 + - src/crypto/internal/backend/nobackend.go | 233 ++++++++++++++++++ + src/crypto/internal/backend/nobackend.go | 236 ++++++++++++++++++ src/crypto/internal/backend/stub.s | 10 + src/crypto/internal/cryptotest/allocations.go | 2 +- .../internal/cryptotest/implementations.go | 2 +- @@ -51,9 +53,9 @@ Subject: [PATCH] Add crypto backend foundation src/crypto/rsa/notboring.go | 4 +- src/crypto/rsa/pkcs1v15.go | 6 +- src/crypto/rsa/pkcs1v15_test.go | 5 + - src/crypto/rsa/pss_test.go | 5 + + src/crypto/rsa/pss_test.go | 9 +- src/crypto/rsa/rsa.go | 4 +- - src/crypto/rsa/rsa_test.go | 12 +- + src/crypto/rsa/rsa_test.go | 15 +- src/crypto/sha1/sha1.go | 8 +- src/crypto/sha1/sha1_test.go | 19 +- src/crypto/sha256/sha256.go | 6 +- @@ -79,9 +81,10 @@ Subject: [PATCH] Add crypto backend foundation src/hash/notboring_test.go | 9 + src/net/smtp/smtp_test.go | 72 ++++-- src/runtime/runtime_boring.go | 5 + - 75 files changed, 1432 insertions(+), 96 deletions(-) + 77 files changed, 1455 insertions(+), 97 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 create mode 100644 src/crypto/ed25519/boring.go create mode 100644 src/crypto/ed25519/notboring.go create mode 100644 src/crypto/internal/backend/backend_test.go @@ -124,6 +127,25 @@ index ed0fbf3d53d75b..06478963f4be44 100644 package main_test +diff --git a/src/cmd/go/testdata/script/gopath_std_vendor.txt b/src/cmd/go/testdata/script/gopath_std_vendor.txt +index 4aaf46b5d0f0dc..ec58a217400caa 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 @@ + env GO111MODULE=off + ++# Disable systemcrypto while evaluating test dependencies to avoid importing ++# vendored crypto module dependencies like golang-fips/openssl. This test script ++# is not set up to handle any vendored libraries being imported other than ++# 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 ++ + [!compiler:gc] skip + + go list -f '{{.Dir}}' vendor/golang.org/x/net/http2/hpack diff --git a/src/crypto/aes/aes.go b/src/crypto/aes/aes.go index 5bc2d13d673e0a..b803c77be62a66 100644 --- a/src/crypto/aes/aes.go @@ -539,6 +561,31 @@ index acef8298943c2b..ca6171cf775117 100644 "crypto/internal/fips140/ecdh" "crypto/internal/fips140only" "errors" +diff --git a/src/crypto/ecdsa/badlinkname.go b/src/crypto/ecdsa/badlinkname.go +new file mode 100644 +index 00000000000000..1dc05d09b2062d +--- /dev/null ++++ b/src/crypto/ecdsa/badlinkname.go +@@ -0,0 +1,19 @@ ++// 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. ++ ++//go:build goexperiment.systemcrypto ++ ++package ecdsa ++ ++import _ "unsafe" ++ ++// The symbols below are pulled by some crypto backend in the Microsoft Go compiler. ++// We provide a push linkname here, to keep them accessible with pull linknames. ++ ++//go:linkname encodeSignature ++//go:linkname parseSignature ++ ++// This supplements other linknames that are already added by ++// https://github.com/golang/go/commit/41aab30bd260297ad8ddad47e98fdf8390a9a67e ++// See that commit for more information. diff --git a/src/crypto/ecdsa/boring.go b/src/crypto/ecdsa/boring.go index 275c60b4de49eb..ff8bddf28c4545 100644 --- a/src/crypto/ecdsa/boring.go @@ -964,10 +1011,10 @@ index 00000000000000..20251a290dc2e0 +} diff --git a/src/crypto/internal/backend/common.go b/src/crypto/internal/backend/common.go new file mode 100644 -index 00000000000000..858e76e3c51c06 +index 00000000000000..0402524861dc53 --- /dev/null +++ b/src/crypto/internal/backend/common.go -@@ -0,0 +1,72 @@ +@@ -0,0 +1,58 @@ +// Copyright 2022 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. @@ -977,7 +1024,6 @@ index 00000000000000..858e76e3c51c06 +import ( + "crypto/internal/backend/fips140" + "crypto/internal/boring/sig" -+ "internal/goexperiment" + "runtime" +) + @@ -1014,7 +1060,11 @@ index 00000000000000..858e76e3c51c06 +// UnreachableExceptTests marks code that should be unreachable +// when backend is in use. It panics. +func UnreachableExceptTests() { -+ if Enabled { ++ // runtime_arg0 is not supported on windows. ++ // We are going through the same code patch on linux, ++ // so if we are unintentionally calling an 'unreachable' function, ++ // we will catch it there. ++ if Enabled && runtime.GOOS != "windows" { + name := runtime_arg0() + // If ran on Windows we'd need to allow _test.exe and .test.exe as well. + if !hasSuffix(name, "_test") && !hasSuffix(name, ".test") { @@ -1023,23 +1073,6 @@ index 00000000000000..858e76e3c51c06 + } + } +} -+ -+func IsRSAKeySupported(primes int) bool { -+ if goexperiment.BoringCrypto { -+ return true -+ } -+ // CNG only supports 2-prime RSA keys. -+ // The built-in OpenSSL 3 providers and OpenSSL 1 do support n-prime RSA keys, -+ // but the SymCrypt provider for OpenSSL only supports 2-prime RSA keys. -+ // Only 2-prime RSA keys are FIPS compliant, other n having compatibility -+ // and security issues. Even crypto/rsa deprecated rsa.GenerateMultiPrimeKey as of Go 1.21. -+ // Given the above reasons, we only support 2-prime RSA keys. -+ return primes == 2 -+} -+ -+func IsSaltSupported(salt int) bool { -+ return true -+} diff --git a/src/crypto/internal/backend/fips140/fips140.go b/src/crypto/internal/backend/fips140/fips140.go new file mode 100644 index 00000000000000..f54d39970319af @@ -1153,10 +1186,10 @@ index 00000000000000..83691d7dd42d51 +} diff --git a/src/crypto/internal/backend/nobackend.go b/src/crypto/internal/backend/nobackend.go new file mode 100644 -index 00000000000000..3ebb6d5e4b4bb5 +index 00000000000000..4a3d8b729da30f --- /dev/null +++ b/src/crypto/internal/backend/nobackend.go -@@ -0,0 +1,233 @@ +@@ -0,0 +1,236 @@ +// 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. @@ -1228,6 +1261,9 @@ index 00000000000000..3ebb6d5e4b4bb5 + panic("cryptobackend: not available") +} + ++func SupportsRSAKeyPrimes(primes int) bool { panic("cryptobackend: not available") } ++func SupportsRSASaltLength(salt int) bool { panic("cryptobackend: not available") } ++ +type PublicKeyRSA struct{ _ int } +type PrivateKeyRSA struct{ _ int } + @@ -1689,7 +1725,7 @@ index 838fcc1244bdbe..d89f732345e8a3 100644 // Note: Can run these tests against the non-BoringCrypto // version of the code by using "CGO_ENABLED=0 go test". diff --git a/src/crypto/rsa/fips.go b/src/crypto/rsa/fips.go -index 8373c125ae3096..bcc534151f9ac3 100644 +index 8373c125ae3096..cee523891d5897 100644 --- a/src/crypto/rsa/fips.go +++ b/src/crypto/rsa/fips.go @@ -6,7 +6,7 @@ package rsa @@ -1706,7 +1742,7 @@ index 8373c125ae3096..bcc534151f9ac3 100644 } - if boring.Enabled && rand == boring.RandReader { -+ if boring.Enabled && rand == boring.RandReader && boring.IsRSAKeySupported(len(priv.Primes)) && boring.SupportsHash(hash) { ++ if boring.Enabled && rand == boring.RandReader && boring.SupportsRSAKeyPrimes(len(priv.Primes)) && boring.SupportsHash(hash) { bkey, err := boringPrivateKey(priv) if err != nil { return nil, err @@ -1715,7 +1751,7 @@ index 8373c125ae3096..bcc534151f9ac3 100644 } - if boring.Enabled { -+ if boring.Enabled && boring.IsSaltSupported(opts.saltLength()) && boring.SupportsHash(hash) { ++ if boring.Enabled && boring.SupportsRSASaltLength(opts.saltLength()) && boring.SupportsHash(hash) { bkey, err := boringPublicKey(pub) if err != nil { return err @@ -1724,7 +1760,7 @@ index 8373c125ae3096..bcc534151f9ac3 100644 } - if boring.Enabled { -+ if boring.Enabled && boring.IsRSAKeySupported(len(priv.Primes)) { ++ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { k := priv.Size() if len(ciphertext) > k || k < hash.Size()*2+2 { @@ -1733,7 +1769,7 @@ index 8373c125ae3096..bcc534151f9ac3 100644 } - if boring.Enabled { -+ if boring.Enabled && boring.IsRSAKeySupported(len(priv.Primes)) { ++ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { bkey, err := boringPrivateKey(priv) if err != nil { return nil, err @@ -1756,7 +1792,7 @@ index 2abc0436405f8a..3e4d6f3eef61e6 100644 func boringPublicKey(*PublicKey) (*boring.PublicKeyRSA, error) { panic("boringcrypto: not available") diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go -index f1e4ef48a4fd1c..cb5aa30920bb7d 100644 +index f1e4ef48a4fd1c..a179a4388e3ee5 100644 --- a/src/crypto/rsa/pkcs1v15.go +++ b/src/crypto/rsa/pkcs1v15.go @@ -5,7 +5,7 @@ @@ -1773,7 +1809,7 @@ index f1e4ef48a4fd1c..cb5aa30920bb7d 100644 } - if boring.Enabled { -+ if boring.Enabled && boring.IsRSAKeySupported(len(priv.Primes)) { ++ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { bkey, err := boringPrivateKey(priv) if err != nil { return nil, err @@ -1782,7 +1818,7 @@ index f1e4ef48a4fd1c..cb5aa30920bb7d 100644 } - if boring.Enabled { -+ if boring.Enabled && boring.IsRSAKeySupported(len(priv.Primes)) { ++ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { var bkey *boring.PrivateKeyRSA bkey, err = boringPrivateKey(priv) if err != nil { @@ -1810,7 +1846,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..a4af0a2144870a 100644 +index e03f4ab06603c6..f31d492d53cf96 100644 --- a/src/crypto/rsa/pss_test.go +++ b/src/crypto/rsa/pss_test.go @@ -8,6 +8,7 @@ import ( @@ -1832,6 +1868,17 @@ index e03f4ab06603c6..a4af0a2144870a 100644 opts.SaltLength = test.verifySaltLength err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts) good := test.good +@@ -241,7 +246,9 @@ func fromHex(hexStr string) []byte { + + func TestInvalidPSSSaltLength(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") +- key, err := GenerateKey(rand.Reader, 245) ++ // Most crypto backends don't support generating RSA keys with a bit size ++ // lower than 512, so we use 512 here. ++ key, err := GenerateKey(rand.Reader, 512) + if err != nil { + t.Fatal(err) + } diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go index 95bb4becd2ff8c..73991434dabaf1 100644 --- a/src/crypto/rsa/rsa.go @@ -1848,7 +1895,7 @@ index 95bb4becd2ff8c..73991434dabaf1 100644 "crypto/internal/fips140/rsa" "crypto/internal/fips140only" diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go -index 73b0c3749eedb2..b527a355074482 100644 +index 73b0c3749eedb2..1a712a0e1c5d95 100644 --- a/src/crypto/rsa/rsa_test.go +++ b/src/crypto/rsa/rsa_test.go @@ -8,7 +8,7 @@ import ( @@ -1884,6 +1931,16 @@ index 73b0c3749eedb2..b527a355074482 100644 msg := []byte("test") enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg) +@@ -853,6 +863,9 @@ func TestDecryptOAEP(t *testing.T) { + } + + func Test2DecryptOAEP(t *testing.T) { ++ if boring.Enabled { ++ t.Skip("Some crypto backends don't supports OAEPOptions.MGFHash.") ++ } + random := rand.Reader + + msg := []byte{0xed, 0x36, 0x90, 0x8d, 0xbe, 0xfc, 0x35, 0x40, 0x70, 0x4f, 0xf5, 0x9d, 0x6e, 0xc2, 0xeb, 0xf5, 0x27, 0xae, 0x65, 0xb0, 0x59, 0x29, 0x45, 0x25, 0x8c, 0xc1, 0x91, 0x22} diff --git a/src/crypto/sha1/sha1.go b/src/crypto/sha1/sha1.go index d2ffaac0aeb674..23d8ad44d0bd9a 100644 --- a/src/crypto/sha1/sha1.go diff --git a/patches/0004-Add-BoringSSL-crypto-backend.patch b/patches/0004-Add-BoringSSL-crypto-backend.patch index ca91aaff124..7ab03583455 100644 --- a/patches/0004-Add-BoringSSL-crypto-backend.patch +++ b/patches/0004-Add-BoringSSL-crypto-backend.patch @@ -5,9 +5,9 @@ Subject: [PATCH] Add BoringSSL crypto backend --- .../internal/backend/bbig/big_boring.go | 12 + - src/crypto/internal/backend/boring_linux.go | 267 ++++++++++++++++++ + src/crypto/internal/backend/boring_linux.go | 275 ++++++++++++++++++ src/crypto/internal/backend/fips140/boring.go | 11 + - 3 files changed, 290 insertions(+) + 3 files changed, 298 insertions(+) create mode 100644 src/crypto/internal/backend/bbig/big_boring.go create mode 100644 src/crypto/internal/backend/boring_linux.go create mode 100644 src/crypto/internal/backend/fips140/boring.go @@ -32,10 +32,10 @@ index 00000000000000..0b62cef68546d0 +var Dec = bbig.Dec diff --git a/src/crypto/internal/backend/boring_linux.go b/src/crypto/internal/backend/boring_linux.go new file mode 100644 -index 00000000000000..94bc444f10eb2b +index 00000000000000..c49291c2f62b4c --- /dev/null +++ b/src/crypto/internal/backend/boring_linux.go -@@ -0,0 +1,267 @@ +@@ -0,0 +1,275 @@ +// 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. @@ -116,6 +116,14 @@ index 00000000000000..94bc444f10eb2b + return boring.VerifyECDSA(pub, hash, sig) +} + ++func SupportsRSAKeyPrimes(primes int) bool { ++ return true ++} ++ ++func SupportsRSASaltLength(salt int) bool { ++ return true ++} ++ +type PublicKeyRSA = boring.PublicKeyRSA +type PrivateKeyRSA = boring.PrivateKeyRSA + diff --git a/patches/0005-Add-OpenSSL-crypto-backend.patch b/patches/0005-Add-OpenSSL-crypto-backend.patch index 648570df40b..b353bd0cfea 100644 --- a/patches/0005-Add-OpenSSL-crypto-backend.patch +++ b/patches/0005-Add-OpenSSL-crypto-backend.patch @@ -5,16 +5,13 @@ Subject: [PATCH] Add OpenSSL crypto backend --- src/cmd/dist/test.go | 3 +- - .../go/testdata/script/gopath_std_vendor.txt | 9 + src/cmd/link/internal/ld/lib.go | 1 + .../internal/backend/bbig/big_openssl.go | 12 + - .../internal/backend/fips140/openssl.go | 41 +++ - src/crypto/internal/backend/openssl_linux.go | 345 ++++++++++++++++++ - src/crypto/rsa/rsa_test.go | 3 + + .../internal/backend/fips140/openssl.go | 41 ++ + src/crypto/internal/backend/openssl_linux.go | 358 ++++++++++++++++++ src/go/build/deps_test.go | 9 +- - src/go/build/vendor_test.go | 1 + src/os/exec/exec_test.go | 9 + - 10 files changed, 428 insertions(+), 5 deletions(-) + 7 files changed, 428 insertions(+), 5 deletions(-) create mode 100644 src/crypto/internal/backend/bbig/big_openssl.go create mode 100644 src/crypto/internal/backend/fips140/openssl.go create mode 100644 src/crypto/internal/backend/openssl_linux.go @@ -37,25 +34,6 @@ index 0c992118f4287b..0de6e80fd985a3 100644 // Static linking tests if goos != "android" && p != "netbsd/arm" && !t.msan && !t.asan { // TODO(#56629): Why does this fail on netbsd-arm? -diff --git a/src/cmd/go/testdata/script/gopath_std_vendor.txt b/src/cmd/go/testdata/script/gopath_std_vendor.txt -index 4aaf46b5d0f0dc..6fe798cf4a94e9 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 @@ - env GO111MODULE=off - -+# Disable OpenSSLCrypto backend while evaluating test dependencies to avoid importing -+# vendored crypto module dependencies like golang-fips/openssl. This test script -+# is not set up to handle any vendored libraries being imported other than -+# 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 -+ - [!compiler:gc] skip - - go list -f '{{.Dir}}' vendor/golang.org/x/net/http2/hpack diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 2d8f964f3594c6..a587e1abde57c9 100644 --- a/src/cmd/link/internal/ld/lib.go @@ -135,10 +113,10 @@ index 00000000000000..118efa3a492a7d +} diff --git a/src/crypto/internal/backend/openssl_linux.go b/src/crypto/internal/backend/openssl_linux.go new file mode 100644 -index 00000000000000..44d91d5b7ba3d5 +index 00000000000000..0f3aea733ac2a5 --- /dev/null +++ b/src/crypto/internal/backend/openssl_linux.go -@@ -0,0 +1,345 @@ +@@ -0,0 +1,358 @@ +// 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. @@ -273,6 +251,19 @@ index 00000000000000..44d91d5b7ba3d5 + return openssl.VerifyECDSA(pub, hash, sig) +} + ++func SupportsRSAKeyPrimes(primes int) bool { ++ // The built-in OpenSSL 3 providers and OpenSSL 1 do support n-prime RSA keys, ++ // but SCOSSL only supports 2-prime RSA keys. ++ // Only 2-prime RSA keys are FIPS compliant, other n having compatibility ++ // and security issues. Even crypto/rsa deprecated rsa.GenerateMultiPrimeKey as of Go 1.21. ++ // Given the above reasons, we only support what SCOSSL supports. ++ return primes == 2 ++} ++ ++func SupportsRSASaltLength(salt int) bool { ++ return true ++} ++ +type PublicKeyRSA = openssl.PublicKeyRSA +type PrivateKeyRSA = openssl.PrivateKeyRSA + @@ -484,20 +475,6 @@ index 00000000000000..44d91d5b7ba3d5 + + return openssl.VerifyDSA(pub, hashed, sig) +} -diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go -index b527a355074482..906c469482030a 100644 ---- a/src/crypto/rsa/rsa_test.go -+++ b/src/crypto/rsa/rsa_test.go -@@ -863,6 +863,9 @@ func TestDecryptOAEP(t *testing.T) { - } - - func Test2DecryptOAEP(t *testing.T) { -+ if boring.Enabled { -+ t.Skip("OpenSSL backend does not supports OAEPOptions.MGFHash yet.") -+ } - random := rand.Reader - - msg := []byte{0xed, 0x36, 0x90, 0x8d, 0xbe, 0xfc, 0x35, 0x40, 0x70, 0x4f, 0xf5, 0x9d, 0x6e, 0xc2, 0xeb, 0xf5, 0x27, 0xae, 0x65, 0xb0, 0x59, 0x29, 0x45, 0x25, 0x8c, 0xc1, 0x91, 0x22} diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 30811455e88418..3de94c93629e3d 100644 --- a/src/go/build/deps_test.go @@ -546,18 +523,6 @@ index 30811455e88418..3de94c93629e3d 100644 haveImport["C"] = true // kludge: prevent C from appearing in crypto/internal/boring imports } fset := token.NewFileSet() -diff --git a/src/go/build/vendor_test.go b/src/go/build/vendor_test.go -index 7f6237ffd59c11..7c821ae4bc5727 100644 ---- a/src/go/build/vendor_test.go -+++ b/src/go/build/vendor_test.go -@@ -22,6 +22,7 @@ var allowedPackagePrefixes = []string{ - "github.com/google/pprof", - "github.com/ianlancetaylor/demangle", - "rsc.io/markdown", -+ "github.com/golang-fips/openssl", - } - - // Verify that the vendor directories contain only packages matching the list above. diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 8c623871932f7d..2fa55073f5c19c 100644 --- a/src/os/exec/exec_test.go diff --git a/patches/0006-Add-CNG-crypto-backend.patch b/patches/0006-Add-CNG-crypto-backend.patch index 5b5ed57f448..256c9bef28d 100644 --- a/patches/0006-Add-CNG-crypto-backend.patch +++ b/patches/0006-Add-CNG-crypto-backend.patch @@ -4,59 +4,15 @@ Date: Tue, 19 Jul 2022 15:58:02 +0200 Subject: [PATCH] Add CNG crypto backend --- - src/crypto/ecdsa/badlinkname.go | 17 ++ - src/crypto/internal/backend/backend_test.go | 4 +- src/crypto/internal/backend/bbig/big_cng.go | 12 + - src/crypto/internal/backend/cng_windows.go | 320 ++++++++++++++++++++ - src/crypto/internal/backend/common.go | 9 +- + src/crypto/internal/backend/cng_windows.go | 329 ++++++++++++++++++++ src/crypto/internal/backend/fips140/cng.go | 33 ++ - src/crypto/rsa/pss_test.go | 2 +- src/go/build/deps_test.go | 5 + - src/go/build/vendor_test.go | 1 + - 9 files changed, 398 insertions(+), 5 deletions(-) - create mode 100644 src/crypto/ecdsa/badlinkname.go + 4 files changed, 379 insertions(+) create mode 100644 src/crypto/internal/backend/bbig/big_cng.go create mode 100644 src/crypto/internal/backend/cng_windows.go create mode 100644 src/crypto/internal/backend/fips140/cng.go -diff --git a/src/crypto/ecdsa/badlinkname.go b/src/crypto/ecdsa/badlinkname.go -new file mode 100644 -index 00000000000000..0d00b7bb3a7fc8 ---- /dev/null -+++ b/src/crypto/ecdsa/badlinkname.go -@@ -0,0 +1,17 @@ -+// Copyright 2024 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package ecdsa -+ -+import _ "unsafe" -+ -+// The symbols below are pulled by the CNG backend in the Microsoft Go compiler. -+// We provide a push linkname here, to keep them accessible with pull linknames. -+ -+//go:linkname encodeSignature -+//go:linkname parseSignature -+ -+// This supplements other linknames that are already added by -+// https://github.com/golang/go/commit/41aab30bd260297ad8ddad47e98fdf8390a9a67e -+// See that commit for more information. -diff --git a/src/crypto/internal/backend/backend_test.go b/src/crypto/internal/backend/backend_test.go -index c2c06d3bff8c74..837cff477e257e 100644 ---- a/src/crypto/internal/backend/backend_test.go -+++ b/src/crypto/internal/backend/backend_test.go -@@ -4,9 +4,7 @@ - - package backend - --import ( -- "testing" --) -+import "testing" - - // Test that Unreachable panics. - func TestUnreachable(t *testing.T) { diff --git a/src/crypto/internal/backend/bbig/big_cng.go b/src/crypto/internal/backend/bbig/big_cng.go new file mode 100644 index 00000000000000..92623031fd87d0 @@ -77,10 +33,10 @@ index 00000000000000..92623031fd87d0 +var Dec = bbig.Dec diff --git a/src/crypto/internal/backend/cng_windows.go b/src/crypto/internal/backend/cng_windows.go new file mode 100644 -index 00000000000000..495260a08dd029 +index 00000000000000..6bfbdc57f0518b --- /dev/null +++ b/src/crypto/internal/backend/cng_windows.go -@@ -0,0 +1,320 @@ +@@ -0,0 +1,329 @@ +// 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. @@ -206,6 +162,15 @@ index 00000000000000..495260a08dd029 + return cng.VerifyECDSA(pub, hash, r, s) +} + ++func SupportsRSAKeyPrimes(primes int) bool { ++ // CNG only supports 2-prime RSA keys. ++ return primes == 2 ++} ++ ++func SupportsRSASaltLength(salt int) bool { ++ return salt != 0 // rsa.PSSSaltLengthAuto ++} ++ +type PublicKeyRSA = cng.PublicKeyRSA +type PrivateKeyRSA = cng.PrivateKeyRSA + @@ -401,32 +366,6 @@ index 00000000000000..495260a08dd029 +func VerifyDSA(pub *PublicKeyDSA, hashed []byte, r, s cng.BigInt, encodeSignature func(r, s cng.BigInt) ([]byte, error)) bool { + return cng.VerifyDSA(pub, hashed, r, s) +} -diff --git a/src/crypto/internal/backend/common.go b/src/crypto/internal/backend/common.go -index 858e76e3c51c06..91223c0ef0f810 100644 ---- a/src/crypto/internal/backend/common.go -+++ b/src/crypto/internal/backend/common.go -@@ -44,7 +44,11 @@ func hasSuffix(s, t string) bool { - // UnreachableExceptTests marks code that should be unreachable - // when backend is in use. It panics. - func UnreachableExceptTests() { -- if Enabled { -+ // runtime_arg0 is not supported on windows. -+ // We are going through the same code patch on linux, -+ // so if we are unintentionally calling an 'unreachable' function, -+ // we will catch it there. -+ if Enabled && !goexperiment.CNGCrypto { - name := runtime_arg0() - // If ran on Windows we'd need to allow _test.exe and .test.exe as well. - if !hasSuffix(name, "_test") && !hasSuffix(name, ".test") { -@@ -68,5 +72,8 @@ func IsRSAKeySupported(primes int) bool { - } - - func IsSaltSupported(salt int) bool { -+ if goexperiment.CNGCrypto { -+ return salt != 0 // rsa.PSSSaltLengthAuto -+ } - return true - } diff --git a/src/crypto/internal/backend/fips140/cng.go b/src/crypto/internal/backend/fips140/cng.go new file mode 100644 index 00000000000000..f769d15f94ab05 @@ -466,19 +405,6 @@ index 00000000000000..f769d15f94ab05 + } + return enabled != 0 +} -diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go -index a4af0a2144870a..7d7115cff81cea 100644 ---- a/src/crypto/rsa/pss_test.go -+++ b/src/crypto/rsa/pss_test.go -@@ -246,7 +246,7 @@ func fromHex(hexStr string) []byte { - - func TestInvalidPSSSaltLength(t *testing.T) { - t.Setenv("GODEBUG", "rsa1024min=0") -- key, err := GenerateKey(rand.Reader, 245) -+ key, err := GenerateKey(rand.Reader, 512) - if err != nil { - t.Fatal(err) - } diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 3de94c93629e3d..8effe9041f3f5f 100644 --- a/src/go/build/deps_test.go @@ -502,15 +428,3 @@ index 3de94c93629e3d..8effe9041f3f5f 100644 < github.com/golang-fips/openssl/v2/bbig < crypto/internal/boring/bbig < crypto/internal/backend/bbig -diff --git a/src/go/build/vendor_test.go b/src/go/build/vendor_test.go -index 7c821ae4bc5727..1d0b9b20e9b1d4 100644 ---- a/src/go/build/vendor_test.go -+++ b/src/go/build/vendor_test.go -@@ -23,6 +23,7 @@ var allowedPackagePrefixes = []string{ - "github.com/ianlancetaylor/demangle", - "rsc.io/markdown", - "github.com/golang-fips/openssl", -+ "github.com/microsoft/go-crypto-winnative", - } - - // Verify that the vendor directories contain only packages matching the list above. From dfd8d2d855938ea180ce386e57ad5fe98d6c3d7f Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Tue, 14 Jan 2025 13:37:44 +0100 Subject: [PATCH 12/12] split crypto backend foundation patch (#1485) --- .../0003-Add-crypto-backend-foundation.patch | 2448 +---------------- patches/0005-Add-OpenSSL-crypto-backend.patch | 24 +- patches/0007-Use-crypto-backends.patch | 2443 ++++++++++++++++ ....patch => 0008-Add-backend-code-gen.patch} | 0 ...patch => 0009-Update-default-go.env.patch} | 0 ... 0010-Skip-failing-tests-on-Windows.patch} | 0 ...OFIPS-when-running-the-Go-toolchain.patch} | 0 ...pport-for-logging-used-Windows-APIs.patch} | 0 ... 0013-remove-long-path-support-hack.patch} | 0 ...ernal-go.mod-files-used-for-codegen.patch} | 0 ...21-when-TLS-fipsonly-mode-is-enable.patch} | 0 11 files changed, 2464 insertions(+), 2451 deletions(-) create mode 100644 patches/0007-Use-crypto-backends.patch rename patches/{0007-Add-backend-code-gen.patch => 0008-Add-backend-code-gen.patch} (100%) rename patches/{0008-Update-default-go.env.patch => 0009-Update-default-go.env.patch} (100%) rename patches/{0009-Skip-failing-tests-on-Windows.patch => 0010-Skip-failing-tests-on-Windows.patch} (100%) rename patches/{0010-unset-GOFIPS-when-running-the-Go-toolchain.patch => 0011-unset-GOFIPS-when-running-the-Go-toolchain.patch} (100%) rename patches/{0011-add-support-for-logging-used-Windows-APIs.patch => 0012-add-support-for-logging-used-Windows-APIs.patch} (100%) rename patches/{0012-remove-long-path-support-hack.patch => 0013-remove-long-path-support-hack.patch} (100%) rename patches/{0013-Omit-internal-go.mod-files-used-for-codegen.patch => 0014-Omit-internal-go.mod-files-used-for-codegen.patch} (100%) rename patches/{0014-Support-curve-P-521-when-TLS-fipsonly-mode-is-enable.patch => 0015-Support-curve-P-521-when-TLS-fipsonly-mode-is-enable.patch} (100%) diff --git a/patches/0003-Add-crypto-backend-foundation.patch b/patches/0003-Add-crypto-backend-foundation.patch index 32a93ef2774..2d37ac5751f 100644 --- a/patches/0003-Add-crypto-backend-foundation.patch +++ b/patches/0003-Add-crypto-backend-foundation.patch @@ -1,34 +1,9 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: qmuntal -Date: Thu, 30 Jun 2022 10:03:03 +0200 +Date: Tue, 14 Jan 2025 11:09:56 +0100 Subject: [PATCH] Add crypto backend foundation --- - src/cmd/api/boring_test.go | 2 +- - src/cmd/go/go_boring_test.go | 2 +- - .../go/testdata/script/gopath_std_vendor.txt | 9 + - src/crypto/aes/aes.go | 2 +- - src/crypto/boring/boring.go | 4 +- - src/crypto/cipher/ctr_aes_test.go | 2 +- - src/crypto/cipher/gcm_test.go | 2 +- - src/crypto/des/cipher.go | 7 + - src/crypto/dsa/boring.go | 113 +++++++++ - src/crypto/dsa/dsa.go | 88 +++++++ - src/crypto/dsa/notboring.go | 16 ++ - src/crypto/ecdh/ecdh.go | 2 +- - src/crypto/ecdh/ecdh_test.go | 4 + - src/crypto/ecdh/nist.go | 2 +- - src/crypto/ecdsa/badlinkname.go | 19 ++ - src/crypto/ecdsa/boring.go | 6 +- - src/crypto/ecdsa/ecdsa.go | 4 +- - src/crypto/ecdsa/notboring.go | 4 +- - src/crypto/ed25519/boring.go | 71 ++++++ - src/crypto/ed25519/ed25519.go | 73 ++++++ - src/crypto/ed25519/notboring.go | 16 ++ - src/crypto/hkdf/hkdf.go | 14 ++ - src/crypto/hkdf/hkdf_test.go | 2 +- - src/crypto/hmac/hmac.go | 2 +- - src/crypto/hmac/hmac_test.go | 2 +- src/crypto/internal/backend/backend_test.go | 30 +++ src/crypto/internal/backend/bbig/big.go | 17 ++ src/crypto/internal/backend/common.go | 58 +++++ @@ -38,55 +13,9 @@ Subject: [PATCH] Add crypto backend foundation .../backend/fips140/nosystemcrypto.go | 11 + src/crypto/internal/backend/nobackend.go | 236 ++++++++++++++++++ src/crypto/internal/backend/stub.s | 10 + - src/crypto/internal/cryptotest/allocations.go | 2 +- - .../internal/cryptotest/implementations.go | 2 +- - src/crypto/md5/md5.go | 10 + - src/crypto/md5/md5_test.go | 21 ++ - src/crypto/pbkdf2/pbkdf2.go | 4 + - src/crypto/pbkdf2/pbkdf2_test.go | 2 +- - src/crypto/purego_test.go | 2 +- - src/crypto/rand/rand.go | 2 +- - src/crypto/rc4/rc4.go | 18 ++ - src/crypto/rsa/boring.go | 6 +- - src/crypto/rsa/boring_test.go | 2 +- - src/crypto/rsa/fips.go | 10 +- - src/crypto/rsa/notboring.go | 4 +- - src/crypto/rsa/pkcs1v15.go | 6 +- - src/crypto/rsa/pkcs1v15_test.go | 5 + - src/crypto/rsa/pss_test.go | 9 +- - src/crypto/rsa/rsa.go | 4 +- - src/crypto/rsa/rsa_test.go | 15 +- - src/crypto/sha1/sha1.go | 8 +- - src/crypto/sha1/sha1_test.go | 19 +- - src/crypto/sha256/sha256.go | 6 +- - src/crypto/sha256/sha256_test.go | 29 +++ - src/crypto/sha512/sha512.go | 2 +- - src/crypto/sha512/sha512_test.go | 29 +++ - src/crypto/tls/cipher_suites.go | 2 +- - src/crypto/tls/fipsonly/fipsonly.go | 2 +- - src/crypto/tls/fipsonly/fipsonly_test.go | 2 +- - src/crypto/tls/handshake_client.go | 12 +- - src/crypto/tls/handshake_client_tls13.go | 16 +- - src/crypto/tls/handshake_server.go | 10 +- - src/crypto/tls/handshake_server_tls13.go | 27 +- - src/crypto/tls/internal/fips140tls/fipstls.go | 3 +- - src/crypto/tls/internal/tls13/doc.go | 18 ++ - src/crypto/tls/internal/tls13/tls13.go | 182 ++++++++++++++ - src/crypto/tls/key_schedule.go | 2 +- - src/crypto/tls/prf.go | 41 +++ - src/go/build/deps_test.go | 9 +- - src/hash/boring_test.go | 9 + - src/hash/example_test.go | 2 + - src/hash/marshal_test.go | 9 + - src/hash/notboring_test.go | 9 + - src/net/smtp/smtp_test.go | 72 ++++-- + src/go/build/deps_test.go | 7 +- src/runtime/runtime_boring.go | 5 + - 77 files changed, 1455 insertions(+), 97 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 - create mode 100644 src/crypto/ed25519/boring.go - create mode 100644 src/crypto/ed25519/notboring.go + 11 files changed, 446 insertions(+), 1 deletion(-) create mode 100644 src/crypto/internal/backend/backend_test.go create mode 100644 src/crypto/internal/backend/bbig/big.go create mode 100644 src/crypto/internal/backend/common.go @@ -96,860 +25,7 @@ Subject: [PATCH] Add crypto backend foundation create mode 100644 src/crypto/internal/backend/fips140/nosystemcrypto.go create mode 100644 src/crypto/internal/backend/nobackend.go create mode 100644 src/crypto/internal/backend/stub.s - create mode 100644 src/crypto/tls/internal/tls13/doc.go - create mode 100644 src/crypto/tls/internal/tls13/tls13.go - create mode 100644 src/hash/boring_test.go - create mode 100644 src/hash/notboring_test.go -diff --git a/src/cmd/api/boring_test.go b/src/cmd/api/boring_test.go -index f0e3575637c62a..9eab3b4e66e60b 100644 ---- a/src/cmd/api/boring_test.go -+++ b/src/cmd/api/boring_test.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto -+//go:build goexperiment.systemcrypto - - package main - -diff --git a/src/cmd/go/go_boring_test.go b/src/cmd/go/go_boring_test.go -index ed0fbf3d53d75b..06478963f4be44 100644 ---- a/src/cmd/go/go_boring_test.go -+++ b/src/cmd/go/go_boring_test.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto -+//go:build goexperiment.systemcrypto - - package main_test - -diff --git a/src/cmd/go/testdata/script/gopath_std_vendor.txt b/src/cmd/go/testdata/script/gopath_std_vendor.txt -index 4aaf46b5d0f0dc..ec58a217400caa 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 @@ - env GO111MODULE=off - -+# Disable systemcrypto while evaluating test dependencies to avoid importing -+# vendored crypto module dependencies like golang-fips/openssl. This test script -+# is not set up to handle any vendored libraries being imported other than -+# 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 -+ - [!compiler:gc] skip - - go list -f '{{.Dir}}' vendor/golang.org/x/net/http2/hpack -diff --git a/src/crypto/aes/aes.go b/src/crypto/aes/aes.go -index 5bc2d13d673e0a..b803c77be62a66 100644 ---- a/src/crypto/aes/aes.go -+++ b/src/crypto/aes/aes.go -@@ -15,7 +15,7 @@ package aes - - import ( - "crypto/cipher" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/aes" - "strconv" - ) -diff --git a/src/crypto/boring/boring.go b/src/crypto/boring/boring.go -index 097c37e343fdb8..a5d603896d3890 100644 ---- a/src/crypto/boring/boring.go -+++ b/src/crypto/boring/boring.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto -+//go:build goexperiment.systemcrypto - - // Package boring exposes functions that are only available when building with - // Go+BoringCrypto. This package is available on all targets as long as the -@@ -13,7 +13,7 @@ - // is satisfied, so that applications can tag files that use this package. - package boring - --import "crypto/internal/boring" -+import boring "crypto/internal/backend" - - // Enabled reports whether BoringCrypto handles supported crypto operations. - func Enabled() bool { -diff --git a/src/crypto/cipher/ctr_aes_test.go b/src/crypto/cipher/ctr_aes_test.go -index 33942467784ad3..0282ffa9fa23c8 100644 ---- a/src/crypto/cipher/ctr_aes_test.go -+++ b/src/crypto/cipher/ctr_aes_test.go -@@ -14,7 +14,7 @@ import ( - "bytes" - "crypto/aes" - "crypto/cipher" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/cryptotest" - fipsaes "crypto/internal/fips140/aes" - "encoding/hex" -diff --git a/src/crypto/cipher/gcm_test.go b/src/crypto/cipher/gcm_test.go -index ea2b4e29e2b67f..f884b0d0fbefe7 100644 ---- a/src/crypto/cipher/gcm_test.go -+++ b/src/crypto/cipher/gcm_test.go -@@ -8,7 +8,7 @@ import ( - "bytes" - "crypto/aes" - "crypto/cipher" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/cryptotest" - "crypto/internal/fips140" - fipsaes "crypto/internal/fips140/aes" -diff --git a/src/crypto/des/cipher.go b/src/crypto/des/cipher.go -index 21303b384cf757..0d3c4f810cfd8f 100644 ---- a/src/crypto/des/cipher.go -+++ b/src/crypto/des/cipher.go -@@ -6,6 +6,7 @@ package des - - import ( - "crypto/cipher" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/alias" - "crypto/internal/fips140only" - "errors" -@@ -36,6 +37,9 @@ func NewCipher(key []byte) (cipher.Block, error) { - if len(key) != 8 { - return nil, KeySizeError(len(key)) - } -+ if boring.Enabled && boring.SupportsDESCipher() { -+ return boring.NewDESCipher(key) -+ } - - c := new(desCipher) - c.generateSubkeys(key) -@@ -84,6 +88,9 @@ func NewTripleDESCipher(key []byte) (cipher.Block, error) { - if len(key) != 24 { - return nil, KeySizeError(len(key)) - } -+ if boring.Enabled && boring.SupportsTripleDESCipher() { -+ return boring.NewTripleDESCipher(key) -+ } - - c := new(tripleDESCipher) - c.cipher1.generateSubkeys(key[:8]) -diff --git a/src/crypto/dsa/boring.go b/src/crypto/dsa/boring.go -new file mode 100644 -index 00000000000000..7ea0c8c423e9ee ---- /dev/null -+++ b/src/crypto/dsa/boring.go -@@ -0,0 +1,113 @@ -+// 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 dsa -+ -+import ( -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/bbig" -+ "crypto/internal/boring/bcache" -+ "math/big" -+) -+ -+// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto. -+// -+// The first operation on a PublicKey or PrivateKey makes a parallel -+// BoringCrypto key and saves it in pubCache or privCache. -+// -+// We could just assume that once used in a sign/verify/encrypt/decrypt operation, -+// a particular key is never again modified, but that has not been a -+// stated assumption before. Just in case there is any existing code that -+// does modify the key between operations, we save the original values -+// alongside the cached BoringCrypto key and check that the real key -+// still matches before using the cached key. The theory is that the real -+// operations are significantly more expensive than the comparison. -+ -+type boringPub struct { -+ key *boring.PublicKeyDSA -+ orig PublicKey -+} -+ -+var pubCache bcache.Cache[PublicKey, boringPub] -+var privCache bcache.Cache[PrivateKey, boringPriv] -+ -+func init() { -+ pubCache.Register() -+ privCache.Register() -+} -+ -+func boringPublicKey(pub *PublicKey) (*boring.PublicKeyDSA, error) { -+ b := pubCache.Get(pub) -+ if b != nil && publicKeyEqual(&b.orig, pub) { -+ return b.key, nil -+ } -+ -+ b = new(boringPub) -+ b.orig = copyPublicKey(pub) -+ key, err := boring.NewPublicKeyDSA(bbig.Enc(b.orig.P), bbig.Enc(b.orig.Q), bbig.Enc(b.orig.G), bbig.Enc(b.orig.Y)) -+ if err != nil { -+ return nil, err -+ } -+ b.key = key -+ pubCache.Put(pub, b) -+ return key, nil -+} -+ -+type boringPriv struct { -+ key *boring.PrivateKeyDSA -+ orig PrivateKey -+} -+ -+func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyDSA, error) { -+ b := privCache.Get(priv) -+ if b != nil && privateKeyEqual(&b.orig, priv) { -+ return b.key, nil -+ } -+ -+ b = new(boringPriv) -+ b.orig = copyPrivateKey(priv) -+ -+ P := b.orig.P -+ Q := b.orig.Q -+ G := b.orig.G -+ X := b.orig.X -+ Y := b.orig.Y -+ -+ key, err := boring.NewPrivateKeyDSA(bbig.Enc(P), bbig.Enc(Q), bbig.Enc(G), bbig.Enc(X), bbig.Enc(Y)) -+ if err != nil { -+ return nil, err -+ } -+ b.key = key -+ privCache.Put(priv, b) -+ return key, nil -+} -+ -+func publicKeyEqual(k1, k2 *PublicKey) bool { -+ return k1.Y != nil && k1.Y.Cmp(k2.Y) == 0 && k1.P.Cmp(k2.P) == 0 && k1.Q.Cmp(k2.Q) == 0 && k1.G.Cmp(k2.G) == 0 -+} -+ -+func copyPublicKey(k *PublicKey) PublicKey { -+ return PublicKey{ -+ Parameters: Parameters{ -+ P: new(big.Int).Set(k.P), -+ Q: new(big.Int).Set(k.Q), -+ G: new(big.Int).Set(k.G), -+ }, -+ Y: new(big.Int).Set(k.Y), -+ } -+} -+ -+func privateKeyEqual(k1, k2 *PrivateKey) bool { -+ return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) && -+ k1.X.Cmp(k2.X) == 0 -+} -+ -+func copyPrivateKey(k *PrivateKey) PrivateKey { -+ return PrivateKey{ -+ PublicKey: copyPublicKey(&k.PublicKey), -+ X: new(big.Int).Set(k.X), -+ } -+} -diff --git a/src/crypto/dsa/dsa.go b/src/crypto/dsa/dsa.go -index 000becc82dfb79..6430bb3ea5e437 100644 ---- a/src/crypto/dsa/dsa.go -+++ b/src/crypto/dsa/dsa.go -@@ -18,8 +18,13 @@ import ( - "io" - "math/big" - -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/bbig" - "crypto/internal/fips140only" - "crypto/internal/randutil" -+ -+ "golang.org/x/crypto/cryptobyte" -+ "golang.org/x/crypto/cryptobyte/asn1" - ) - - // Parameters represents the domain parameters for a key. These parameters can -@@ -91,6 +96,17 @@ func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes - return errors.New("crypto/dsa: invalid ParameterSizes") - } - -+ if boring.Enabled && boring.SupportsDSA(L, N) { -+ p, q, g, err := boring.GenerateParametersDSA(L, N) -+ if err != nil { -+ return err -+ } -+ params.P = bbig.Dec(p) -+ params.Q = bbig.Dec(q) -+ params.G = bbig.Dec(g) -+ return nil -+ } -+ - qBytes := make([]byte, N/8) - pBytes := make([]byte, L/8) - -@@ -170,6 +186,17 @@ func GenerateKey(priv *PrivateKey, rand io.Reader) error { - return errors.New("crypto/dsa: parameters not set up before generating key") - } - -+ if boring.Enabled && boring.SupportsDSA(priv.P.BitLen(), priv.Q.BitLen()) { -+ x, y, err := boring.GenerateKeyDSA(bbig.Enc(priv.P), bbig.Enc(priv.Q), bbig.Enc(priv.G)) -+ if err != nil { -+ return err -+ } -+ priv.X = bbig.Dec(x) -+ priv.Y = bbig.Dec(y) -+ -+ return nil -+ } -+ - x := new(big.Int) - xBytes := make([]byte, priv.Q.BitLen()/8) - -@@ -225,6 +252,18 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err - err = ErrInvalidPublicKey - return - } -+ -+ if boring.Enabled && boring.SupportsDSA(priv.P.BitLen(), priv.Q.BitLen()) { -+ b, err := boringPrivateKey(priv) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ r, s, err := boring.SignDSA(b, hash, parseSignature) -+ -+ return bbig.Dec(r), bbig.Dec(s), err -+ } -+ - n >>= 3 - - var attempts int -@@ -288,6 +327,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") - } - -+ if boring.Enabled && boring.SupportsDSA(pub.P.BitLen(), pub.Q.BitLen()) { -+ bkey, err := boringPublicKey(pub) -+ if err != nil { -+ return false -+ } -+ -+ return boring.VerifyDSA(bkey, hash, bbig.Enc(r), bbig.Enc(s), encodeSignature) -+ } - // FIPS 186-3, section 4.7 - - if pub.P.Sign() == 0 { -@@ -324,3 +371,44 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { - - return v.Cmp(r) == 0 - } -+ -+func parseSignature(sig []byte) (boring.BigInt, boring.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 boring.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) -+ }) -+} -diff --git a/src/crypto/dsa/notboring.go b/src/crypto/dsa/notboring.go -new file mode 100644 -index 00000000000000..cd02ff5a00c3dc ---- /dev/null -+++ b/src/crypto/dsa/notboring.go -@@ -0,0 +1,16 @@ -+// Copyright 2022 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 dsa -+ -+import boring "crypto/internal/backend" -+ -+func boringPublicKey(*PublicKey) (*boring.PublicKeyDSA, error) { -+ panic("boringcrypto: not available") -+} -+func boringPrivateKey(*PrivateKey) (*boring.PrivateKeyDSA, error) { -+ panic("boringcrypto: not available") -+} -diff --git a/src/crypto/ecdh/ecdh.go b/src/crypto/ecdh/ecdh.go -index 231f1ea04c1010..cfa113e2345816 100644 ---- a/src/crypto/ecdh/ecdh.go -+++ b/src/crypto/ecdh/ecdh.go -@@ -8,7 +8,7 @@ package ecdh - - import ( - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/ecdh" - "crypto/subtle" - "errors" -diff --git a/src/crypto/ecdh/ecdh_test.go b/src/crypto/ecdh/ecdh_test.go -index 75d2480775669f..6a4d26fbafe090 100644 ---- a/src/crypto/ecdh/ecdh_test.go -+++ b/src/crypto/ecdh/ecdh_test.go -@@ -9,6 +9,7 @@ import ( - "crypto" - "crypto/cipher" - "crypto/ecdh" -+ boring "crypto/internal/backend" - "crypto/rand" - "crypto/sha256" - "encoding/hex" -@@ -280,6 +281,9 @@ var invalidPrivateKeys = map[ecdh.Curve][]string{ - } - - func TestNewPrivateKey(t *testing.T) { -+ if boring.Enabled { -+ t.Skip("skipping test with different results when using different backends") -+ } - testAllCurves(t, func(t *testing.T, curve ecdh.Curve) { - for _, input := range invalidPrivateKeys[curve] { - k, err := curve.NewPrivateKey(hexDecode(t, input)) -diff --git a/src/crypto/ecdh/nist.go b/src/crypto/ecdh/nist.go -index acef8298943c2b..ca6171cf775117 100644 ---- a/src/crypto/ecdh/nist.go -+++ b/src/crypto/ecdh/nist.go -@@ -6,7 +6,7 @@ package ecdh - - import ( - "bytes" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/ecdh" - "crypto/internal/fips140only" - "errors" -diff --git a/src/crypto/ecdsa/badlinkname.go b/src/crypto/ecdsa/badlinkname.go -new file mode 100644 -index 00000000000000..1dc05d09b2062d ---- /dev/null -+++ b/src/crypto/ecdsa/badlinkname.go -@@ -0,0 +1,19 @@ -+// 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. -+ -+//go:build goexperiment.systemcrypto -+ -+package ecdsa -+ -+import _ "unsafe" -+ -+// The symbols below are pulled by some crypto backend in the Microsoft Go compiler. -+// We provide a push linkname here, to keep them accessible with pull linknames. -+ -+//go:linkname encodeSignature -+//go:linkname parseSignature -+ -+// This supplements other linknames that are already added by -+// https://github.com/golang/go/commit/41aab30bd260297ad8ddad47e98fdf8390a9a67e -+// See that commit for more information. -diff --git a/src/crypto/ecdsa/boring.go b/src/crypto/ecdsa/boring.go -index 275c60b4de49eb..ff8bddf28c4545 100644 ---- a/src/crypto/ecdsa/boring.go -+++ b/src/crypto/ecdsa/boring.go -@@ -2,13 +2,13 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto -+//go:build goexperiment.systemcrypto - - package ecdsa - - import ( -- "crypto/internal/boring" -- "crypto/internal/boring/bbig" -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/bbig" - "crypto/internal/boring/bcache" - "math/big" - ) -diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go -index cb308b41e9df86..8f73855aa738de 100644 ---- a/src/crypto/ecdsa/ecdsa.go -+++ b/src/crypto/ecdsa/ecdsa.go -@@ -20,8 +20,8 @@ import ( - "crypto" - "crypto/ecdh" - "crypto/elliptic" -- "crypto/internal/boring" -- "crypto/internal/boring/bbig" -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/bbig" - "crypto/internal/fips140/ecdsa" - "crypto/internal/fips140hash" - "crypto/internal/fips140only" -diff --git a/src/crypto/ecdsa/notboring.go b/src/crypto/ecdsa/notboring.go -index 039bd82ed21f9f..69a97d9bf250be 100644 ---- a/src/crypto/ecdsa/notboring.go -+++ b/src/crypto/ecdsa/notboring.go -@@ -2,11 +2,11 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build !boringcrypto -+//go:build !goexperiment.systemcrypto - - package ecdsa - --import "crypto/internal/boring" -+import boring "crypto/internal/backend" - - func boringPublicKey(*PublicKey) (*boring.PublicKeyECDSA, error) { - panic("boringcrypto: not available") -diff --git a/src/crypto/ed25519/boring.go b/src/crypto/ed25519/boring.go -new file mode 100644 -index 00000000000000..cce33e4d6cc927 ---- /dev/null -+++ b/src/crypto/ed25519/boring.go -@@ -0,0 +1,71 @@ -+// Copyright 2023 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 ed25519 -+ -+import ( -+ boring "crypto/internal/backend" -+ "crypto/internal/boring/bcache" -+ "unsafe" -+) -+ -+var pubCache bcache.Cache[byte, boringPub] -+var privCache bcache.Cache[byte, boringPriv] -+ -+func init() { -+ if boring.Enabled && boring.SupportsEd25519() { -+ pubCache.Register() -+ privCache.Register() -+ } -+} -+ -+type boringPub struct { -+ key *boring.PublicKeyEd25519 -+ orig [PublicKeySize]byte -+} -+ -+func boringPublicKey(pub PublicKey) (*boring.PublicKeyEd25519, error) { -+ // Use the pointer to the underlying pub array as key. -+ p := unsafe.SliceData(pub) -+ b := pubCache.Get(p) -+ if b != nil && PublicKey(b.orig[:]).Equal(pub) { -+ return b.key, nil -+ } -+ -+ b = new(boringPub) -+ copy(b.orig[:], pub) -+ key, err := boring.NewPublicKeyEd25519(b.orig[:]) -+ if err != nil { -+ return nil, err -+ } -+ b.key = key -+ pubCache.Put(p, b) -+ return key, nil -+} -+ -+type boringPriv struct { -+ key *boring.PrivateKeyEd25519 -+ orig [PrivateKeySize]byte -+} -+ -+func boringPrivateKey(priv PrivateKey) (*boring.PrivateKeyEd25519, error) { -+ // Use the pointer to the underlying priv array as key. -+ p := unsafe.SliceData(priv) -+ b := privCache.Get(p) -+ if b != nil && PrivateKey(b.orig[:]).Equal(priv) { -+ return b.key, nil -+ } -+ -+ b = new(boringPriv) -+ copy(b.orig[:], priv) -+ key, err := boring.NewPrivateKeyEd25519(b.orig[:]) -+ if err != nil { -+ return nil, err -+ } -+ b.key = key -+ privCache.Put(p, b) -+ return key, nil -+} -diff --git a/src/crypto/ed25519/ed25519.go b/src/crypto/ed25519/ed25519.go -index c1f8ff784e4a5c..6476bfbe896d6c 100644 ---- a/src/crypto/ed25519/ed25519.go -+++ b/src/crypto/ed25519/ed25519.go -@@ -17,6 +17,7 @@ package ed25519 - - import ( - "crypto" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/ed25519" - "crypto/internal/fips140only" - cryptorand "crypto/rand" -@@ -24,6 +25,7 @@ import ( - "errors" - "io" - "strconv" -+ "sync" - ) - - const ( -@@ -138,6 +140,22 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - if rand == nil { - rand = cryptorand.Reader - } -+ if boring.Enabled && boring.SupportsEd25519() { -+ if rand == boring.RandReader { -+ priv, err := boring.GenerateKeyEd25519() -+ if err != nil { -+ return nil, nil, err -+ } -+ privData, err := priv.Bytes() -+ if err != nil { -+ return nil, nil, err -+ } -+ privKey := PrivateKey(privData) -+ pubKey := privKey.Public().(PublicKey) -+ return pubKey, privKey, err -+ } -+ boring.UnreachableExceptTests() -+ } - - seed := make([]byte, SeedSize) - if _, err := io.ReadFull(rand, seed); err != nil { -@@ -154,6 +172,17 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { - // with RFC 8032. RFC 8032's private keys correspond to seeds in this - // package. - func NewKeyFromSeed(seed []byte) PrivateKey { -+ if boring.Enabled && boring.SupportsEd25519() { -+ key, err := boring.NewPrivateKeyEd25519FromSeed(seed) -+ if err != nil { -+ panic(err) -+ } -+ d, err := key.Bytes() -+ if err != nil { -+ panic(err) -+ } -+ return PrivateKey(d) -+ } - // Outline the function body so that the returned key can be stack-allocated. - privateKey := make([]byte, PrivateKeySize) - newKeyFromSeed(privateKey, seed) -@@ -172,6 +201,17 @@ func newKeyFromSeed(privateKey, seed []byte) { - // Sign signs the message with privateKey and returns a signature. It will - // panic if len(privateKey) is not [PrivateKeySize]. - func Sign(privateKey PrivateKey, message []byte) []byte { -+ if boring.Enabled && boring.SupportsEd25519() { -+ priv, err := boringPrivateKey(privateKey) -+ if err != nil { -+ panic(err) -+ } -+ signature, err := boring.SignEd25519(priv, message) -+ if err != nil { -+ panic(err) -+ } -+ return signature -+ } - // Outline the function body so that the returned signature can be - // stack-allocated. - signature := make([]byte, SignatureSize) -@@ -200,6 +240,32 @@ func Verify(publicKey PublicKey, message, sig []byte) bool { - return VerifyWithOptions(publicKey, message, sig, &Options{Hash: crypto.Hash(0)}) == nil - } - -+// testMalleability returns true if the crypto backend correctly rejects -+// malleable signatures. The only known backend that fails to do so is -+// OpenSSL version 1.1.1a or lower. -+// See https://github.com/openssl/openssl/issues/7693. -+var testMalleability = sync.OnceValue(func() bool { -+ msg := []byte{0x54, 0x65, 0x73, 0x74} -+ sig := []byte{ -+ 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a, -+ 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b, -+ 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67, -+ 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d, -+ 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33, -+ 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d, -+ } -+ pkey := []byte{ -+ 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5, -+ 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34, -+ 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa, -+ } -+ pub, err := boring.NewPublicKeyEd25519(pkey) -+ if err != nil { -+ return false -+ } -+ return boring.VerifyEd25519(pub, msg, sig) != nil -+}) -+ - // VerifyWithOptions reports whether sig is a valid signature of message by - // publicKey. A valid signature is indicated by returning a nil error. It will - // panic if len(publicKey) is not [PublicKeySize]. -@@ -228,6 +294,13 @@ func VerifyWithOptions(publicKey PublicKey, message, sig []byte, opts *Options) - } - return ed25519.VerifyCtx(k, message, sig, opts.Context) - case opts.Hash == crypto.Hash(0): // Ed25519 -+ if boring.Enabled && boring.SupportsEd25519() && testMalleability() { -+ pub, err := boringPublicKey(publicKey) -+ if err != nil { -+ return err -+ } -+ return boring.VerifyEd25519(pub, message, sig) -+ } - return ed25519.Verify(k, message, sig) - 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/notboring.go b/src/crypto/ed25519/notboring.go -new file mode 100644 -index 00000000000000..b0cdd44d81c753 ---- /dev/null -+++ b/src/crypto/ed25519/notboring.go -@@ -0,0 +1,16 @@ -+// Copyright 2023 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 ed25519 -+ -+import boring "crypto/internal/backend" -+ -+func boringPublicKey(PublicKey) (*boring.PublicKeyEd25519, error) { -+ panic("boringcrypto: not available") -+} -+func boringPrivateKey(PrivateKey) (*boring.PrivateKeyEd25519, error) { -+ panic("boringcrypto: not available") -+} -diff --git a/src/crypto/hkdf/hkdf.go b/src/crypto/hkdf/hkdf.go -index 6b02522866d57f..37e67ec184af5d 100644 ---- a/src/crypto/hkdf/hkdf.go -+++ b/src/crypto/hkdf/hkdf.go -@@ -11,6 +11,7 @@ - package hkdf - - import ( -+ boring "crypto/internal/backend" - "crypto/internal/fips140/hkdf" - "crypto/internal/fips140hash" - "crypto/internal/fips140only" -@@ -29,6 +30,9 @@ func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { - if err := checkFIPS140Only(fh, secret); err != nil { - return nil, err - } -+ if boring.Enabled && boring.SupportsHKDF() { -+ return boring.ExtractHKDF(fh, secret, salt) -+ } - return hkdf.Extract(fh, secret, salt), nil - } - -@@ -50,6 +54,9 @@ func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen - return nil, errors.New("hkdf: requested key length too large") - } - -+ if boring.Enabled && boring.SupportsHKDF() { -+ return boring.ExpandHKDF(fh, pseudorandomKey, []byte(info), keyLength) -+ } - return hkdf.Expand(fh, pseudorandomKey, info, keyLength), nil - } - -@@ -67,6 +74,13 @@ func Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLen - return nil, errors.New("hkdf: requested key length too large") - } - -+ if boring.Enabled && boring.SupportsHKDF() { -+ pseudorandomKey, err := boring.ExtractHKDF(fh, secret, salt) -+ if err != nil { -+ return nil, err -+ } -+ return boring.ExpandHKDF(fh, pseudorandomKey, []byte(info), keyLength) -+ } - return hkdf.Key(fh, secret, salt, info, keyLength), nil - } - -diff --git a/src/crypto/hkdf/hkdf_test.go b/src/crypto/hkdf/hkdf_test.go -index 201b440289bb2d..4ed4960ff35b66 100644 ---- a/src/crypto/hkdf/hkdf_test.go -+++ b/src/crypto/hkdf/hkdf_test.go -@@ -6,7 +6,7 @@ package hkdf - - import ( - "bytes" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140" - "crypto/md5" - "crypto/sha1" -diff --git a/src/crypto/hmac/hmac.go b/src/crypto/hmac/hmac.go -index 554c8c9b78940b..c68a394280cc2c 100644 ---- a/src/crypto/hmac/hmac.go -+++ b/src/crypto/hmac/hmac.go -@@ -22,7 +22,7 @@ timing side-channels: - package hmac - - import ( -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/hmac" - "crypto/internal/fips140hash" - "crypto/internal/fips140only" -diff --git a/src/crypto/hmac/hmac_test.go b/src/crypto/hmac/hmac_test.go -index 7accad763244a1..dd3211f2c37af3 100644 ---- a/src/crypto/hmac/hmac_test.go -+++ b/src/crypto/hmac/hmac_test.go -@@ -5,7 +5,7 @@ - package hmac - - import ( -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/cryptotest" - "crypto/md5" - "crypto/sha1" diff --git a/src/crypto/internal/backend/backend_test.go b/src/crypto/internal/backend/backend_test.go new file mode 100644 index 00000000000000..c2c06d3bff8c74 @@ -1442,1329 +518,8 @@ index 00000000000000..5e4b436554d44d +// Having this assembly file keeps the go command +// from complaining about the missing body +// (because the implementation might be here). -diff --git a/src/crypto/internal/cryptotest/allocations.go b/src/crypto/internal/cryptotest/allocations.go -index 70055af70b42ec..3c4b4fbaa98ded 100644 ---- a/src/crypto/internal/cryptotest/allocations.go -+++ b/src/crypto/internal/cryptotest/allocations.go -@@ -5,7 +5,7 @@ - package cryptotest - - import ( -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "internal/asan" - "internal/msan" - "internal/race" -diff --git a/src/crypto/internal/cryptotest/implementations.go b/src/crypto/internal/cryptotest/implementations.go -index 3fa730459050f6..1f28f12a6e7b4f 100644 ---- a/src/crypto/internal/cryptotest/implementations.go -+++ b/src/crypto/internal/cryptotest/implementations.go -@@ -5,7 +5,7 @@ - package cryptotest - - import ( -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/impl" - "internal/goos" - "internal/testenv" -diff --git a/src/crypto/md5/md5.go b/src/crypto/md5/md5.go -index a0384e175f31bd..f7aa6da36f02de 100644 ---- a/src/crypto/md5/md5.go -+++ b/src/crypto/md5/md5.go -@@ -12,6 +12,7 @@ package md5 - - import ( - "crypto" -+ boring "crypto/internal/backend" - "crypto/internal/fips140only" - "errors" - "hash" -@@ -104,6 +105,9 @@ func consumeUint32(b []byte) ([]byte, uint32) { - // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal - // state of the hash. - func New() hash.Hash { -+ if boring.Enabled && boring.SupportsHash(crypto.MD5) { -+ return boring.NewMD5() -+ } - d := new(digest) - d.Reset() - return d -@@ -188,6 +192,12 @@ func (d *digest) checkSum() [Size]byte { - - // Sum returns the MD5 checksum of the data. - func Sum(data []byte) [Size]byte { -+ if boring.Enabled && boring.SupportsHash(crypto.MD5) { -+ if fips140only.Enabled { -+ panic("crypto/md5: use of MD5 is not allowed in FIPS 140-only mode") -+ } -+ return boring.MD5(data) -+ } - var d digest - d.Reset() - d.Write(data) -diff --git a/src/crypto/md5/md5_test.go b/src/crypto/md5/md5_test.go -index 437d9b9d4c0e0d..ee28c55f846e81 100644 ---- a/src/crypto/md5/md5_test.go -+++ b/src/crypto/md5/md5_test.go -@@ -6,12 +6,14 @@ package md5 - - import ( - "bytes" -+ boring "crypto/internal/backend" - "crypto/internal/cryptotest" - "crypto/rand" - "encoding" - "fmt" - "hash" - "io" -+ "strings" - "testing" - "unsafe" - ) -@@ -88,6 +90,11 @@ func TestGolden(t *testing.T) { - } - - func TestGoldenMarshal(t *testing.T) { -+ if boring.Enabled { -+ if _, ok := New().(encoding.BinaryMarshaler); !ok { -+ t.Skip("BinaryMarshaler not implemented") -+ } -+ } - for _, g := range golden { - h := New() - h2 := New() -@@ -96,6 +103,9 @@ func TestGoldenMarshal(t *testing.T) { - - state, err := h.(encoding.BinaryMarshaler).MarshalBinary() - if err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("could not marshal: %v", err) - continue - } -@@ -157,6 +167,9 @@ func TestLarge(t *testing.T) { - - // Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match. - func TestBlockGeneric(t *testing.T) { -+ if boring.Enabled { -+ t.Skip("digest is not used when boring.Enabled is set") -+ } - gen, asm := New().(*digest), New().(*digest) - buf := make([]byte, BlockSize*20) // arbitrary factor - rand.Read(buf) -@@ -204,10 +217,18 @@ func safeSum(h hash.Hash) (sum []byte, err error) { - } - - func TestLargeHashes(t *testing.T) { -+ if boring.Enabled { -+ if _, ok := New().(encoding.BinaryUnmarshaler); !ok { -+ t.Skip("BinaryUnmarshaler not implemented") -+ } -+ } - for i, test := range largeUnmarshalTests { - - h := New() - if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("test %d could not unmarshal: %v", i, err) - continue - } -diff --git a/src/crypto/pbkdf2/pbkdf2.go b/src/crypto/pbkdf2/pbkdf2.go -index 271d2b03312ef0..ff76299fbe4782 100644 ---- a/src/crypto/pbkdf2/pbkdf2.go -+++ b/src/crypto/pbkdf2/pbkdf2.go -@@ -11,6 +11,7 @@ - package pbkdf2 - - import ( -+ boring "crypto/internal/backend" - "crypto/internal/fips140/pbkdf2" - "crypto/internal/fips140hash" - "crypto/internal/fips140only" -@@ -47,5 +48,8 @@ func Key[Hash hash.Hash](h func() Hash, password string, salt []byte, iter, keyL - return nil, errors.New("crypto/pbkdf2: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") - } - } -+ if boring.Enabled && boring.SupportsPBKDF2() { -+ return boring.PBKDF2([]byte(password), salt, iter, keyLength, fh) -+ } - 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 03980c7e54d3be..4968a666fad4e5 100644 ---- a/src/crypto/pbkdf2/pbkdf2_test.go -+++ b/src/crypto/pbkdf2/pbkdf2_test.go -@@ -6,7 +6,7 @@ package pbkdf2_test - - import ( - "bytes" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140" - "crypto/pbkdf2" - "crypto/sha1" -diff --git a/src/crypto/purego_test.go b/src/crypto/purego_test.go -index 62be347e0c6822..d284b5cf7814a6 100644 ---- a/src/crypto/purego_test.go -+++ b/src/crypto/purego_test.go -@@ -41,7 +41,7 @@ func TestPureGoTag(t *testing.T) { - } - - for _, pkgName := range pkgs { -- if strings.Contains(pkgName, "/boring") { -+ if strings.Contains(pkgName, "/boring") || strings.Contains(pkgName, "/internal/backend") || strings.Contains(pkgName, "tls/fipsonly") { - continue - } - -diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go -index 1ca16caa9563e6..3ef22b5ff8222b 100644 ---- a/src/crypto/rand/rand.go -+++ b/src/crypto/rand/rand.go -@@ -7,7 +7,7 @@ - package rand - - import ( -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140" - "crypto/internal/fips140/drbg" - "crypto/internal/sysrand" -diff --git a/src/crypto/rc4/rc4.go b/src/crypto/rc4/rc4.go -index 90943a0935befb..09ebdfd733e5d6 100644 ---- a/src/crypto/rc4/rc4.go -+++ b/src/crypto/rc4/rc4.go -@@ -10,6 +10,7 @@ - package rc4 - - import ( -+ boring "crypto/internal/backend" - "crypto/internal/fips140/alias" - "crypto/internal/fips140only" - "errors" -@@ -20,6 +21,8 @@ import ( - type Cipher struct { - s [256]uint32 - i, j uint8 -+ -+ boring *boring.RC4Cipher - } - - type KeySizeError int -@@ -38,6 +41,13 @@ func NewCipher(key []byte) (*Cipher, error) { - if k < 1 || k > 256 { - return nil, KeySizeError(k) - } -+ if boring.Enabled && boring.SupportsRC4() { -+ c, err := boring.NewRC4Cipher(key) -+ if err != nil { -+ return nil, err -+ } -+ return &Cipher{boring: c}, nil -+ } - var c Cipher - for i := 0; i < 256; i++ { - c.s[i] = uint32(i) -@@ -55,6 +65,10 @@ func NewCipher(key []byte) (*Cipher, error) { - // Deprecated: Reset can't guarantee that the key will be entirely removed from - // the process's memory. - func (c *Cipher) Reset() { -+ if boring.Enabled && boring.SupportsRC4() { -+ c.boring.Reset() -+ return -+ } - for i := range c.s { - c.s[i] = 0 - } -@@ -64,6 +78,10 @@ func (c *Cipher) Reset() { - // XORKeyStream sets dst to the result of XORing src with the key stream. - // Dst and src must overlap entirely or not at all. - func (c *Cipher) XORKeyStream(dst, src []byte) { -+ if boring.Enabled && boring.SupportsRC4() { -+ c.boring.XORKeyStream(dst, src) -+ return -+ } - if len(src) == 0 { - return - } -diff --git a/src/crypto/rsa/boring.go b/src/crypto/rsa/boring.go -index b9f9d3154f2589..d52faddef45549 100644 ---- a/src/crypto/rsa/boring.go -+++ b/src/crypto/rsa/boring.go -@@ -2,13 +2,13 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto -+//go:build goexperiment.systemcrypto - - package rsa - - import ( -- "crypto/internal/boring" -- "crypto/internal/boring/bbig" -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/bbig" - "crypto/internal/boring/bcache" - "math/big" - ) -diff --git a/src/crypto/rsa/boring_test.go b/src/crypto/rsa/boring_test.go -index 838fcc1244bdbe..d89f732345e8a3 100644 ---- a/src/crypto/rsa/boring_test.go -+++ b/src/crypto/rsa/boring_test.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto -+//go:build goexperiment.systemcrypto - - // Note: Can run these tests against the non-BoringCrypto - // version of the code by using "CGO_ENABLED=0 go test". -diff --git a/src/crypto/rsa/fips.go b/src/crypto/rsa/fips.go -index 8373c125ae3096..cee523891d5897 100644 ---- a/src/crypto/rsa/fips.go -+++ b/src/crypto/rsa/fips.go -@@ -6,7 +6,7 @@ package rsa - - import ( - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/rsa" - "crypto/internal/fips140hash" - "crypto/internal/fips140only" -@@ -70,7 +70,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, - hash = opts.Hash - } - -- if boring.Enabled && rand == boring.RandReader { -+ if boring.Enabled && rand == boring.RandReader && boring.SupportsRSAKeyPrimes(len(priv.Primes)) && boring.SupportsHash(hash) { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err -@@ -133,7 +133,7 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts - return err - } - -- if boring.Enabled { -+ if boring.Enabled && boring.SupportsRSASaltLength(opts.saltLength()) && boring.SupportsHash(hash) { - bkey, err := boringPublicKey(pub) - if err != nil { - return err -@@ -250,7 +250,7 @@ func decryptOAEP(hash, mgfHash hash.Hash, priv *PrivateKey, ciphertext []byte, l - return nil, err - } - -- if boring.Enabled { -+ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { - k := priv.Size() - if len(ciphertext) > k || - k < hash.Size()*2+2 { -@@ -312,7 +312,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ - return nil, err - } - -- if boring.Enabled { -+ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err -diff --git a/src/crypto/rsa/notboring.go b/src/crypto/rsa/notboring.go -index 2abc0436405f8a..3e4d6f3eef61e6 100644 ---- a/src/crypto/rsa/notboring.go -+++ b/src/crypto/rsa/notboring.go -@@ -2,11 +2,11 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build !boringcrypto -+//go:build !goexperiment.systemcrypto - - package rsa - --import "crypto/internal/boring" -+import boring "crypto/internal/backend" - - func boringPublicKey(*PublicKey) (*boring.PublicKeyRSA, error) { - panic("boringcrypto: not available") -diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go -index f1e4ef48a4fd1c..a179a4388e3ee5 100644 ---- a/src/crypto/rsa/pkcs1v15.go -+++ b/src/crypto/rsa/pkcs1v15.go -@@ -5,7 +5,7 @@ - package rsa - - import ( -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/rsa" - "crypto/internal/fips140only" - "crypto/internal/randutil" -@@ -104,7 +104,7 @@ func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]b - return nil, err - } - -- if boring.Enabled { -+ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err -@@ -203,7 +203,7 @@ func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, - return 0, nil, 0, err - } - -- if boring.Enabled { -+ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { - var bkey *boring.PrivateKeyRSA - bkey, err = boringPrivateKey(priv) - if err != nil { -diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go -index c65552cd93526a..910416abe842f5 100644 ---- a/src/crypto/rsa/pkcs1v15_test.go -+++ b/src/crypto/rsa/pkcs1v15_test.go -@@ -7,6 +7,7 @@ package rsa_test - import ( - "bytes" - "crypto" -+ boring "crypto/internal/backend" - "crypto/rand" - . "crypto/rsa" - "crypto/sha1" -@@ -235,6 +236,10 @@ func TestVerifyPKCS1v15(t *testing.T) { - } - - func TestOverlongMessagePKCS1v15(t *testing.T) { -+ if boring.Enabled { -+ // See for example https://github.com/golang-fips/openssl/pull/142. -+ t.Skip("Some backends do not return an error for overlong messages.") -+ } - t.Setenv("GODEBUG", "rsa1024min=0") - 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..f31d492d53cf96 100644 ---- a/src/crypto/rsa/pss_test.go -+++ b/src/crypto/rsa/pss_test.go -@@ -8,6 +8,7 @@ import ( - "bufio" - "compress/bzip2" - "crypto" -+ boring "crypto/internal/backend" - "crypto/internal/fips140" - "crypto/rand" - . "crypto/rsa" -@@ -180,6 +181,10 @@ func TestPSSSigning(t *testing.T) { - continue - } - -+ if boring.Enabled && test.good != test.fipsGood { -+ t.Skip("skipping test with different results when using different backends") -+ } -+ - opts.SaltLength = test.verifySaltLength - err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts) - good := test.good -@@ -241,7 +246,9 @@ func fromHex(hexStr string) []byte { - - func TestInvalidPSSSaltLength(t *testing.T) { - t.Setenv("GODEBUG", "rsa1024min=0") -- key, err := GenerateKey(rand.Reader, 245) -+ // Most crypto backends don't support generating RSA keys with a bit size -+ // lower than 512, so we use 512 here. -+ key, err := GenerateKey(rand.Reader, 512) - if err != nil { - t.Fatal(err) - } -diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go -index 95bb4becd2ff8c..73991434dabaf1 100644 ---- a/src/crypto/rsa/rsa.go -+++ b/src/crypto/rsa/rsa.go -@@ -42,8 +42,8 @@ package rsa - - import ( - "crypto" -- "crypto/internal/boring" -- "crypto/internal/boring/bbig" -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/bbig" - "crypto/internal/fips140/bigmod" - "crypto/internal/fips140/rsa" - "crypto/internal/fips140only" -diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go -index 73b0c3749eedb2..1a712a0e1c5d95 100644 ---- a/src/crypto/rsa/rsa_test.go -+++ b/src/crypto/rsa/rsa_test.go -@@ -8,7 +8,7 @@ import ( - "bufio" - "bytes" - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/cryptotest" - "crypto/rand" - . "crypto/rsa" -@@ -146,6 +146,11 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { - if priv.D.Cmp(priv.N) > 0 { - t.Errorf("private exponent too large") - } -+ if boring.Enabled && priv.N.BitLen() < 512 { -+ // Some crypto backends (e.g. CNG and OpenSSL with SymCrypt) don't support key sizes -+ // lower than 512 and intentionally fail rather than fall back to Go crypto. -+ t.Skip("skipping allocations test with BoringCrypto") -+ } - - msg := []byte("hi!") - enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg) -@@ -226,6 +231,11 @@ func testEverything(t *testing.T, priv *PrivateKey) { - if err := priv.Validate(); err != nil { - t.Errorf("Validate() failed: %s", err) - } -+ if boring.Enabled && priv.N.BitLen() < 512 { -+ // Some crypto backends (e.g. CNG and OpenSSL with SymCrypt) don't support key sizes -+ // lower than 512 and intentionally fail rather than fall back to Go crypto. -+ t.Skip("skipping allocations test with BoringCrypto") -+ } - - msg := []byte("test") - enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg) -@@ -853,6 +863,9 @@ func TestDecryptOAEP(t *testing.T) { - } - - func Test2DecryptOAEP(t *testing.T) { -+ if boring.Enabled { -+ t.Skip("Some crypto backends don't supports OAEPOptions.MGFHash.") -+ } - random := rand.Reader - - msg := []byte{0xed, 0x36, 0x90, 0x8d, 0xbe, 0xfc, 0x35, 0x40, 0x70, 0x4f, 0xf5, 0x9d, 0x6e, 0xc2, 0xeb, 0xf5, 0x27, 0xae, 0x65, 0xb0, 0x59, 0x29, 0x45, 0x25, 0x8c, 0xc1, 0x91, 0x22} -diff --git a/src/crypto/sha1/sha1.go b/src/crypto/sha1/sha1.go -index d2ffaac0aeb674..23d8ad44d0bd9a 100644 ---- a/src/crypto/sha1/sha1.go -+++ b/src/crypto/sha1/sha1.go -@@ -10,7 +10,7 @@ package sha1 - - import ( - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140only" - "errors" - "hash" -@@ -266,12 +266,12 @@ func (d *digest) constSum() [Size]byte { - - // Sum returns the SHA-1 checksum of the data. - func Sum(data []byte) [Size]byte { -- if boring.Enabled { -- return boring.SHA1(data) -- } - if fips140only.Enabled { - panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode") - } -+ if boring.Enabled { -+ return boring.SHA1(data) -+ } - var d digest - d.Reset() - d.Write(data) -diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go -index 9d707b7cde5c2d..8da08b3d860a85 100644 ---- a/src/crypto/sha1/sha1_test.go -+++ b/src/crypto/sha1/sha1_test.go -@@ -8,13 +8,14 @@ package sha1 - - import ( - "bytes" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/cryptotest" - "crypto/rand" - "encoding" - "fmt" - "hash" - "io" -+ "strings" - "testing" - ) - -@@ -97,6 +98,11 @@ func TestGolden(t *testing.T) { - } - - func TestGoldenMarshal(t *testing.T) { -+ if boring.Enabled { -+ if _, ok := New().(encoding.BinaryMarshaler); !ok { -+ t.Skip("BinaryMarshaler not implemented") -+ } -+ } - h := New() - h2 := New() - for _, g := range golden { -@@ -107,6 +113,9 @@ func TestGoldenMarshal(t *testing.T) { - - state, err := h.(encoding.BinaryMarshaler).MarshalBinary() - if err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("could not marshal: %v", err) - continue - } -@@ -210,10 +219,18 @@ func safeSum(h hash.Hash) (sum []byte, err error) { - } - - func TestLargeHashes(t *testing.T) { -+ if boring.Enabled { -+ if _, ok := New().(encoding.BinaryMarshaler); !ok { -+ t.Skip("BinaryMarshaler not implemented") -+ } -+ } - for i, test := range largeUnmarshalTests { - - h := New() - if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("test %d could not unmarshal: %v", i, err) - continue - } -diff --git a/src/crypto/sha256/sha256.go b/src/crypto/sha256/sha256.go -index 069938a22dbc5a..8d0e06b86f4359 100644 ---- a/src/crypto/sha256/sha256.go -+++ b/src/crypto/sha256/sha256.go -@@ -8,7 +8,7 @@ package sha256 - - import ( - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/sha256" - "hash" - ) -@@ -43,7 +43,7 @@ func New() hash.Hash { - // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal - // state of the hash. - func New224() hash.Hash { -- if boring.Enabled { -+ if boring.Enabled && boring.SupportsHash(crypto.SHA224) { - return boring.NewSHA224() - } - return sha256.New224() -@@ -63,7 +63,7 @@ func Sum256(data []byte) [Size]byte { - - // Sum224 returns the SHA224 checksum of the data. - func Sum224(data []byte) [Size224]byte { -- if boring.Enabled { -+ if boring.Enabled && boring.SupportsHash(crypto.SHA224) { - return boring.SHA224(data) - } - h := New224() -diff --git a/src/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go -index e1af9640e25547..c4f142c1430285 100644 ---- a/src/crypto/sha256/sha256_test.go -+++ b/src/crypto/sha256/sha256_test.go -@@ -8,11 +8,13 @@ package sha256 - - import ( - "bytes" -+ boring "crypto/internal/backend" - "crypto/internal/cryptotest" - "encoding" - "fmt" - "hash" - "io" -+ "strings" - "testing" - ) - -@@ -155,6 +157,11 @@ func testGoldenMarshal(t *testing.T) { - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { -+ if boring.Enabled { -+ if _, ok := tt.newHash().(encoding.BinaryMarshaler); !ok { -+ t.Skip("BinaryMarshaler not implemented") -+ } -+ } - for _, g := range tt.gold { - h := tt.newHash() - h2 := tt.newHash() -@@ -163,6 +170,9 @@ func testGoldenMarshal(t *testing.T) { - - state, err := h.(encoding.BinaryMarshaler).MarshalBinary() - if err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("could not marshal: %v", err) - continue - } -@@ -204,8 +214,19 @@ func TestMarshalTypeMismatch(t *testing.T) { - h1 := New() - h2 := New224() - -+ if boring.Enabled { -+ _, ok1 := h1.(encoding.BinaryMarshaler) -+ _, ok2 := h2.(encoding.BinaryUnmarshaler) -+ if !ok1 || !ok2 { -+ t.Skip("BinaryMarshaler not implemented") -+ } -+ } -+ - state1, err := h1.(encoding.BinaryMarshaler).MarshalBinary() - if err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("could not marshal: %v", err) - } - -@@ -275,10 +296,18 @@ func safeSum(h hash.Hash) (sum []byte, err error) { - return h.Sum(nil), nil - } - func TestLargeHashes(t *testing.T) { -+ if boring.Enabled { -+ if _, ok := New().(encoding.BinaryUnmarshaler); !ok { -+ t.Skip("BinaryUnmarshaler not implemented") -+ } -+ } - for i, test := range largeUnmarshalTests { - - h := New() - if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("test %d could not unmarshal: %v", i, err) - continue - } -diff --git a/src/crypto/sha512/sha512.go b/src/crypto/sha512/sha512.go -index 1435eac1f5b5dc..17e8501154762a 100644 ---- a/src/crypto/sha512/sha512.go -+++ b/src/crypto/sha512/sha512.go -@@ -12,7 +12,7 @@ package sha512 - - import ( - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/sha512" - "hash" - ) -diff --git a/src/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go -index 1fe9d132bb186d..97b7da8c2d3d88 100644 ---- a/src/crypto/sha512/sha512_test.go -+++ b/src/crypto/sha512/sha512_test.go -@@ -8,12 +8,14 @@ package sha512 - - import ( - "bytes" -+ boring "crypto/internal/backend" - "crypto/internal/cryptotest" - "encoding" - "encoding/hex" - "fmt" - "hash" - "io" -+ "strings" - "testing" - ) - -@@ -744,6 +746,11 @@ func testGoldenMarshal(t *testing.T) { - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - for _, test := range tt.golden { -+ if boring.Enabled { -+ if _, ok := tt.newHash().(encoding.BinaryMarshaler); !ok { -+ t.Skip("BinaryMarshaler not implemented") -+ } -+ } - h := tt.newHash() - h2 := tt.newHash() - -@@ -751,6 +758,9 @@ func testGoldenMarshal(t *testing.T) { - - state, err := h.(encoding.BinaryMarshaler).MarshalBinary() - if err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("could not marshal: %v", err) - return - } -@@ -805,8 +815,19 @@ func TestMarshalMismatch(t *testing.T) { - h1 := fn1() - h2 := fn2() - -+ if boring.Enabled { -+ _, ok1 := h1.(encoding.BinaryMarshaler) -+ _, ok2 := h2.(encoding.BinaryUnmarshaler) -+ if !ok1 || !ok2 { -+ t.Skip("BinaryMarshaler not implemented") -+ } -+ } -+ - state, err := h1.(encoding.BinaryMarshaler).MarshalBinary() - if err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("i=%d: could not marshal: %v", i, err) - continue - } -@@ -880,10 +901,18 @@ func safeSum(h hash.Hash) (sum []byte, err error) { - } - - func TestLargeHashes(t *testing.T) { -+ if boring.Enabled { -+ if _, ok := New().(encoding.BinaryUnmarshaler); !ok { -+ t.Skip("BinaryUnmarshaler not implemented") -+ } -+ } - for i, test := range largeUnmarshalTests { - - h := New() - if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Errorf("test %d could not unmarshal: %v", i, err) - continue - } -diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go -index 01d65688284f97..d8a26c24024348 100644 ---- a/src/crypto/tls/cipher_suites.go -+++ b/src/crypto/tls/cipher_suites.go -@@ -10,7 +10,7 @@ import ( - "crypto/cipher" - "crypto/des" - "crypto/hmac" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - fipsaes "crypto/internal/fips140/aes" - "crypto/internal/fips140/aes/gcm" - "crypto/rc4" -diff --git a/src/crypto/tls/fipsonly/fipsonly.go b/src/crypto/tls/fipsonly/fipsonly.go -index e702f44e986746..e506a0d8841237 100644 ---- a/src/crypto/tls/fipsonly/fipsonly.go -+++ b/src/crypto/tls/fipsonly/fipsonly.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto -+//go:build goexperiment.systemcrypto - - // Package fipsonly restricts all TLS configuration to FIPS-approved settings. - // -diff --git a/src/crypto/tls/fipsonly/fipsonly_test.go b/src/crypto/tls/fipsonly/fipsonly_test.go -index 027bc22c33c921..eba08da985f832 100644 ---- a/src/crypto/tls/fipsonly/fipsonly_test.go -+++ b/src/crypto/tls/fipsonly/fipsonly_test.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto -+//go:build goexperiment.systemcrypto - - package fipsonly - -diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go -index 38bd417a0dca72..8c1ae3c7ec5485 100644 ---- a/src/crypto/tls/handshake_client.go -+++ b/src/crypto/tls/handshake_client.go -@@ -11,11 +11,11 @@ import ( - "crypto/ecdsa" - "crypto/ed25519" - "crypto/internal/fips140/mlkem" -- "crypto/internal/fips140/tls13" - "crypto/internal/hpke" - "crypto/rsa" - "crypto/subtle" - "crypto/tls/internal/fips140tls" -+ "crypto/tls/internal/tls13" - "crypto/x509" - "errors" - "fmt" -@@ -549,7 +549,15 @@ func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error { - - // Does the handshake, either a full one or resumes old session. Requires hs.c, - // hs.hello, hs.serverHello, and, optionally, hs.session to be set. --func (hs *clientHandshakeState) handshake() error { -+func (hs *clientHandshakeState) handshake() (err error) { -+ defer func() { -+ if err == nil { -+ err = recoverFromBoringPRFError() -+ if err != nil { -+ hs.c.sendAlert(alertInternalError) -+ } -+ } -+ }() - c := hs.c - - isResume, err := hs.processServerHello() -diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go -index c0396e75796add..2c00e119cb66e4 100644 ---- a/src/crypto/tls/handshake_client_tls13.go -+++ b/src/crypto/tls/handshake_client_tls13.go -@@ -8,12 +8,12 @@ import ( - "bytes" - "context" - "crypto" -+ "crypto/hkdf" - "crypto/hmac" -- "crypto/internal/fips140/hkdf" - "crypto/internal/fips140/mlkem" -- "crypto/internal/fips140/tls13" - "crypto/rsa" - "crypto/subtle" -+ "crypto/tls/internal/tls13" - "errors" - "hash" - "slices" -@@ -90,8 +90,12 @@ func (hs *clientHandshakeStateTLS13) handshake() error { - confTranscript.Write(hs.serverHello.original[:30]) - confTranscript.Write(make([]byte, 8)) - confTranscript.Write(hs.serverHello.original[38:]) -+ secret, err := hkdf.Extract(hs.suite.hash.New, hs.echContext.innerHello.random, nil) -+ if err != nil { -+ return err -+ } - acceptConfirmation := tls13.ExpandLabel(hs.suite.hash.New, -- hkdf.Extract(hs.suite.hash.New, hs.echContext.innerHello.random, nil), -+ secret, - "ech accept confirmation", - confTranscript.Sum(nil), - 8, -@@ -264,8 +268,12 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { - copy(hrrHello, hs.serverHello.original) - hrrHello = bytes.Replace(hrrHello, hs.serverHello.encryptedClientHello, make([]byte, 8), 1) - confTranscript.Write(hrrHello) -+ secret, err := hkdf.Extract(hs.suite.hash.New, hs.echContext.innerHello.random, nil) -+ if err != nil { -+ return err -+ } - acceptConfirmation := tls13.ExpandLabel(hs.suite.hash.New, -- hkdf.Extract(hs.suite.hash.New, hs.echContext.innerHello.random, nil), -+ secret, - "hrr ech accept confirmation", - confTranscript.Sum(nil), - 8, -diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go -index 7c75977ad3ffb2..b9db95ca7b9d5a 100644 ---- a/src/crypto/tls/handshake_server.go -+++ b/src/crypto/tls/handshake_server.go -@@ -64,7 +64,15 @@ func (c *Conn) serverHandshake(ctx context.Context) error { - return hs.handshake() - } - --func (hs *serverHandshakeState) handshake() error { -+func (hs *serverHandshakeState) handshake() (err error) { -+ defer func() { -+ if err == nil { -+ err = recoverFromBoringPRFError() -+ if err != nil { -+ hs.c.sendAlert(alertInternalError) -+ } -+ } -+ }() - c := hs.c - - 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 76fff6974e7403..3ef8b56e5c7898 100644 ---- a/src/crypto/tls/handshake_server_tls13.go -+++ b/src/crypto/tls/handshake_server_tls13.go -@@ -8,13 +8,14 @@ import ( - "bytes" - "context" - "crypto" -+ "crypto/hkdf" - "crypto/hmac" -- "crypto/internal/fips140/hkdf" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/mlkem" -- "crypto/internal/fips140/tls13" - "crypto/internal/hpke" - "crypto/rsa" - "crypto/tls/internal/fips140tls" -+ "crypto/tls/internal/tls13" - "errors" - "hash" - "internal/byteorder" -@@ -470,15 +471,19 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error { - // interfaces implemented by standard library hashes to clone the state of in - // to a new instance of h. It returns nil if the operation fails. - func cloneHash(in hash.Hash, h crypto.Hash) hash.Hash { -+ if boring.Enabled { -+ // CNG and OpenSSL with SymCrypt hash functions do not implement the -+ // encoding.BinaryMarshaler interface, but they do implement the Clone method. -+ if cloner, ok := in.(interface{ Clone() hash.Hash }); ok { -+ return cloner.Clone() -+ } -+ } - // Recreate the interface to avoid importing encoding. - type binaryMarshaler interface { - MarshalBinary() (data []byte, err error) - UnmarshalBinary(data []byte) error - } - marshaler, ok := in.(binaryMarshaler) -- if !ok { -- return nil -- } - state, err := marshaler.MarshalBinary() - if err != nil { - return nil -@@ -572,8 +577,12 @@ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) - if err := transcriptMsg(helloRetryRequest, confTranscript); err != nil { - return nil, err - } -+ secret, err := hkdf.Extract(hs.suite.hash.New, hs.clientHello.random, nil) -+ if err != nil { -+ return nil, err -+ } - acceptConfirmation := tls13.ExpandLabel(hs.suite.hash.New, -- hkdf.Extract(hs.suite.hash.New, hs.clientHello.random, nil), -+ secret, - "hrr ech accept confirmation", - confTranscript.Sum(nil), - 8, -@@ -734,9 +743,13 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { - if err := transcriptMsg(hs.hello, echTranscript); err != nil { - return err - } -+ secret, err := hkdf.Extract(hs.suite.hash.New, hs.clientHello.random, nil) -+ if err != nil { -+ return err -+ } - // compute the acceptance message - acceptConfirmation := tls13.ExpandLabel(hs.suite.hash.New, -- hkdf.Extract(hs.suite.hash.New, hs.clientHello.random, nil), -+ secret, - "ech accept confirmation", - echTranscript.Sum(nil), - 8, -diff --git a/src/crypto/tls/internal/fips140tls/fipstls.go b/src/crypto/tls/internal/fips140tls/fipstls.go -index 24d78d60cf5b64..a6bfd3f17c1911 100644 ---- a/src/crypto/tls/internal/fips140tls/fipstls.go -+++ b/src/crypto/tls/internal/fips140tls/fipstls.go -@@ -6,6 +6,7 @@ - package fips140tls - - import ( -+ bfips140 "crypto/internal/backend/fips140" - "crypto/internal/fips140" - "sync/atomic" - ) -@@ -13,7 +14,7 @@ import ( - var required atomic.Bool - - func init() { -- if fips140.Enabled { -+ if fips140.Enabled || bfips140.Enabled() { - Force() - } - } -diff --git a/src/crypto/tls/internal/tls13/doc.go b/src/crypto/tls/internal/tls13/doc.go -new file mode 100644 -index 00000000000000..1adf3098356307 ---- /dev/null -+++ b/src/crypto/tls/internal/tls13/doc.go -@@ -0,0 +1,18 @@ -+// 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. -+ -+/* -+Microsoft Go only package. -+ -+TLS 1.3 Key Schedule is normally not part of the FIPS boundary, but upstream Go -+decided to include it in the FIPS boundary to facilitate the FIPS 140-3 certification -+process. -+ -+The problem is that crypto/internal/fips140/tls13 uses crypto/internal/fips140/hkdf, -+which can't be patched to use other backends. -+ -+To solve this problem, we created this package, which is a direct copy of -+crypto/internal/fips140/tls13, but uses crypto/hkdf instead of crypto/internal/fips140/hkdf. -+*/ -+package tls13 -diff --git a/src/crypto/tls/internal/tls13/tls13.go b/src/crypto/tls/internal/tls13/tls13.go -new file mode 100644 -index 00000000000000..573896b9c1e6a8 ---- /dev/null -+++ b/src/crypto/tls/internal/tls13/tls13.go -@@ -0,0 +1,182 @@ -+// Copyright 2024 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Package tls13 implements the TLS 1.3 Key Schedule as specified in RFC 8446, -+// Section 7.1 and allowed by FIPS 140-3 IG 2.4.B Resolution 7. -+package tls13 -+ -+import ( -+ "crypto/hkdf" -+ "hash" -+ "internal/byteorder" -+) -+ -+// We don't set the service indicator in this package but we delegate that to -+// the underlying functions because the TLS 1.3 KDF does not have a standard of -+// its own. -+ -+// ExpandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1. -+func ExpandLabel[H hash.Hash](hash func() H, secret []byte, label string, context []byte, length int) []byte { -+ if len("tls13 ")+len(label) > 255 || len(context) > 255 { -+ // It should be impossible for this to panic: labels are fixed strings, -+ // and context is either a fixed-length computed hash, or parsed from a -+ // field which has the same length limitation. -+ // -+ // Another reasonable approach might be to return a randomized slice if -+ // we encounter an error, which would break the connection, but avoid -+ // panicking. This would perhaps be safer but significantly more -+ // confusing to users. -+ panic("tls13: label or context too long") -+ } -+ hkdfLabel := make([]byte, 0, 2+1+len("tls13 ")+len(label)+1+len(context)) -+ hkdfLabel = byteorder.BEAppendUint16(hkdfLabel, uint16(length)) -+ hkdfLabel = append(hkdfLabel, byte(len("tls13 ")+len(label))) -+ hkdfLabel = append(hkdfLabel, "tls13 "...) -+ hkdfLabel = append(hkdfLabel, label...) -+ hkdfLabel = append(hkdfLabel, byte(len(context))) -+ hkdfLabel = append(hkdfLabel, context...) -+ key, err := hkdf.Expand(hash, secret, string(hkdfLabel), length) -+ if err != nil { -+ panic(err) -+ } -+ return key -+} -+ -+func extract[H hash.Hash](hash func() H, newSecret, currentSecret []byte) []byte { -+ if newSecret == nil { -+ newSecret = make([]byte, hash().Size()) -+ } -+ prk, err := hkdf.Extract(hash, newSecret, currentSecret) -+ if err != nil { -+ panic(err) -+ } -+ return prk -+} -+ -+func deriveSecret[H hash.Hash](hash func() H, secret []byte, label string, transcript hash.Hash) []byte { -+ if transcript == nil { -+ transcript = hash() -+ } -+ return ExpandLabel(hash, secret, label, transcript.Sum(nil), transcript.Size()) -+} -+ -+const ( -+ resumptionBinderLabel = "res binder" -+ clientEarlyTrafficLabel = "c e traffic" -+ clientHandshakeTrafficLabel = "c hs traffic" -+ serverHandshakeTrafficLabel = "s hs traffic" -+ clientApplicationTrafficLabel = "c ap traffic" -+ serverApplicationTrafficLabel = "s ap traffic" -+ earlyExporterLabel = "e exp master" -+ exporterLabel = "exp master" -+ resumptionLabel = "res master" -+) -+ -+type EarlySecret struct { -+ secret []byte -+ hash func() hash.Hash -+} -+ -+func NewEarlySecret[H hash.Hash](h func() H, psk []byte) *EarlySecret { -+ return &EarlySecret{ -+ secret: extract(h, psk, nil), -+ hash: func() hash.Hash { return h() }, -+ } -+} -+ -+func (s *EarlySecret) ResumptionBinderKey() []byte { -+ return deriveSecret(s.hash, s.secret, resumptionBinderLabel, nil) -+} -+ -+// ClientEarlyTrafficSecret derives the client_early_traffic_secret from the -+// early secret and the transcript up to the ClientHello. -+func (s *EarlySecret) ClientEarlyTrafficSecret(transcript hash.Hash) []byte { -+ return deriveSecret(s.hash, s.secret, clientEarlyTrafficLabel, transcript) -+} -+ -+type HandshakeSecret struct { -+ secret []byte -+ hash func() hash.Hash -+} -+ -+func (s *EarlySecret) HandshakeSecret(sharedSecret []byte) *HandshakeSecret { -+ derived := deriveSecret(s.hash, s.secret, "derived", nil) -+ return &HandshakeSecret{ -+ secret: extract(s.hash, sharedSecret, derived), -+ hash: s.hash, -+ } -+} -+ -+// ClientHandshakeTrafficSecret derives the client_handshake_traffic_secret from -+// the handshake secret and the transcript up to the ServerHello. -+func (s *HandshakeSecret) ClientHandshakeTrafficSecret(transcript hash.Hash) []byte { -+ return deriveSecret(s.hash, s.secret, clientHandshakeTrafficLabel, transcript) -+} -+ -+// ServerHandshakeTrafficSecret derives the server_handshake_traffic_secret from -+// the handshake secret and the transcript up to the ServerHello. -+func (s *HandshakeSecret) ServerHandshakeTrafficSecret(transcript hash.Hash) []byte { -+ return deriveSecret(s.hash, s.secret, serverHandshakeTrafficLabel, transcript) -+} -+ -+type MasterSecret struct { -+ secret []byte -+ hash func() hash.Hash -+} -+ -+func (s *HandshakeSecret) MasterSecret() *MasterSecret { -+ derived := deriveSecret(s.hash, s.secret, "derived", nil) -+ return &MasterSecret{ -+ secret: extract(s.hash, nil, derived), -+ hash: s.hash, -+ } -+} -+ -+// ClientApplicationTrafficSecret derives the client_application_traffic_secret_0 -+// from the master secret and the transcript up to the server Finished. -+func (s *MasterSecret) ClientApplicationTrafficSecret(transcript hash.Hash) []byte { -+ return deriveSecret(s.hash, s.secret, clientApplicationTrafficLabel, transcript) -+} -+ -+// ServerApplicationTrafficSecret derives the server_application_traffic_secret_0 -+// from the master secret and the transcript up to the server Finished. -+func (s *MasterSecret) ServerApplicationTrafficSecret(transcript hash.Hash) []byte { -+ return deriveSecret(s.hash, s.secret, serverApplicationTrafficLabel, transcript) -+} -+ -+// ResumptionMasterSecret derives the resumption_master_secret from the master secret -+// and the transcript up to the client Finished. -+func (s *MasterSecret) ResumptionMasterSecret(transcript hash.Hash) []byte { -+ return deriveSecret(s.hash, s.secret, resumptionLabel, transcript) -+} -+ -+type ExporterMasterSecret struct { -+ secret []byte -+ hash func() hash.Hash -+} -+ -+// ExporterMasterSecret derives the exporter_master_secret from the master secret -+// and the transcript up to the server Finished. -+func (s *MasterSecret) ExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { -+ return &ExporterMasterSecret{ -+ secret: deriveSecret(s.hash, s.secret, exporterLabel, transcript), -+ hash: s.hash, -+ } -+} -+ -+// EarlyExporterMasterSecret derives the exporter_master_secret from the early secret -+// and the transcript up to the ClientHello. -+func (s *EarlySecret) EarlyExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { -+ return &ExporterMasterSecret{ -+ secret: deriveSecret(s.hash, s.secret, earlyExporterLabel, transcript), -+ hash: s.hash, -+ } -+} -+ -+func (s *ExporterMasterSecret) Exporter(label string, context []byte, length int) []byte { -+ secret := deriveSecret(s.hash, s.secret, label, nil) -+ h := s.hash() -+ h.Write(context) -+ return ExpandLabel(s.hash, secret, "exporter", h.Sum(nil), length) -+} -diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go -index 38d6d3f7be1673..b236ae44a34030 100644 ---- a/src/crypto/tls/key_schedule.go -+++ b/src/crypto/tls/key_schedule.go -@@ -8,7 +8,7 @@ import ( - "crypto/ecdh" - "crypto/hmac" - "crypto/internal/fips140/mlkem" -- "crypto/internal/fips140/tls13" -+ "crypto/tls/internal/tls13" - "errors" - "hash" - "io" -diff --git a/src/crypto/tls/prf.go b/src/crypto/tls/prf.go -index e7369542a73270..ff52175e4ac636 100644 ---- a/src/crypto/tls/prf.go -+++ b/src/crypto/tls/prf.go -@@ -7,6 +7,7 @@ package tls - import ( - "crypto" - "crypto/hmac" -+ boring "crypto/internal/backend" - "crypto/internal/fips140/tls12" - "crypto/md5" - "crypto/sha1" -@@ -47,9 +48,42 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) { - } - } - -+type boringPRFError struct { -+ err error -+} -+ -+func (e *boringPRFError) Error() string { -+ return e.err.Error() -+} -+ -+// recoverFromBoringPRFError recovers from a panic caused by the boring backend. -+// It returns the error if it was a boringPRFError, or panics if the panic was -+// caused by something else. -+func recoverFromBoringPRFError() error { -+ if p := recover(); p != nil { -+ if err, ok := p.(boringPRFError); ok { -+ // Could happen, for example, if the seed is too large. The Go implementation doesn't limit the seed size, -+ // as RFC 5705 doesn't specify a limit, but stock OpenSSL restrict it to 1024 and CNG to 256. -+ return err.err -+ } -+ panic(p) -+ } -+ return nil -+} -+ -+func panicBoringPRFError(err error) { -+ panic(boringPRFError{err}) -+} -+ - // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. - func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { - result := make([]byte, keyLen) -+ if boring.Enabled && boring.SupportsTLS1PRF() { -+ if err := boring.TLS1PRF(result, secret, []byte(label), seed, nil); err != nil { -+ panicBoringPRFError(fmt.Errorf("crypto/tls: prf10: %v", err)) -+ } -+ return result -+ } - hashSHA1 := sha1.New - hashMD5 := md5.New - -@@ -72,6 +106,13 @@ func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { - // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. - func prf12(hashFunc func() hash.Hash) prfFunc { - return func(secret []byte, label string, seed []byte, keyLen int) []byte { -+ if boring.Enabled && boring.SupportsTLS1PRF() { -+ result := make([]byte, keyLen) -+ if err := boring.TLS1PRF(result, secret, []byte(label), seed, hashFunc); err != nil { -+ panicBoringPRFError(fmt.Errorf("crypto/tls: prf12: %v", err)) -+ } -+ return result -+ } - return tls12.PRF(hashFunc, secret, label, seed, keyLen) - } - } diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index e3e01077c18b17..30811455e88418 100644 +index e3e01077c18b17..a46d6c034ca1e0 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -493,6 +493,8 @@ var depsRules = ` @@ -2776,17 +531,17 @@ index e3e01077c18b17..30811455e88418 100644 FIPS, internal/godebug < crypto/fips140; crypto, hash !< FIPS; -@@ -506,7 +508,9 @@ var depsRules = ` +@@ -506,7 +508,8 @@ var depsRules = ` FIPS, internal/godebug, hash, embed, crypto/internal/boring/sig, crypto/internal/boring/syso, -+ encoding/binary, - crypto/internal/boring/bcache +- crypto/internal/boring/bcache ++ crypto/internal/boring/bcache, + crypto/internal/backend/fips140 < crypto/internal/fips140only < crypto < crypto/subtle -@@ -514,6 +518,7 @@ var depsRules = ` +@@ -514,6 +517,7 @@ var depsRules = ` < crypto/internal/fips140hash < crypto/cipher < crypto/internal/boring @@ -2794,15 +549,7 @@ index e3e01077c18b17..30811455e88418 100644 < crypto/boring < crypto/aes, crypto/des, -@@ -527,6 +532,7 @@ var depsRules = ` - crypto/pbkdf2, - crypto/ecdh, - crypto/mlkem -+ < crypto/tls/internal/tls13 - < CRYPTO; - - CGO, fmt, net !< CRYPTO; -@@ -535,6 +541,7 @@ var depsRules = ` +@@ -535,6 +539,7 @@ var depsRules = ` CRYPTO, FMT, math/big < crypto/internal/boring/bbig @@ -2810,183 +557,6 @@ index e3e01077c18b17..30811455e88418 100644 < crypto/rand < crypto/ed25519 # depends on crypto/rand.Reader < encoding/asn1 -@@ -548,7 +555,7 @@ var depsRules = ` - - # TLS, Prince of Dependencies. - -- FIPS, sync/atomic < crypto/tls/internal/fips140tls; -+ FIPS, sync/atomic, crypto/internal/backend/fips140 < crypto/tls/internal/fips140tls; - - crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly; - -diff --git a/src/hash/boring_test.go b/src/hash/boring_test.go -new file mode 100644 -index 00000000000000..52748c44698076 ---- /dev/null -+++ b/src/hash/boring_test.go -@@ -0,0 +1,9 @@ -+// 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. -+ -+//go:build goexperiment.systemcrypto -+ -+package hash_test -+ -+const boringEnabled = true -diff --git a/src/hash/example_test.go b/src/hash/example_test.go -index f07b9aaa2c4898..b380537215634d 100644 ---- a/src/hash/example_test.go -+++ b/src/hash/example_test.go -@@ -2,6 +2,8 @@ - // 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 hash_test - - import ( -diff --git a/src/hash/marshal_test.go b/src/hash/marshal_test.go -index 3091f7a67acede..23736034d5c352 100644 ---- a/src/hash/marshal_test.go -+++ b/src/hash/marshal_test.go -@@ -21,6 +21,7 @@ import ( - "hash/crc32" - "hash/crc64" - "hash/fnv" -+ "strings" - "testing" - ) - -@@ -65,6 +66,11 @@ func TestMarshalHash(t *testing.T) { - } - - h := tt.new() -+ if boringEnabled { -+ if _, ok := h.(encoding.BinaryMarshaler); !ok { -+ t.Skip("BinaryMarshaler not implemented") -+ } -+ } - h.Write(buf[:256]) - sum := h.Sum(nil) - -@@ -80,6 +86,9 @@ func TestMarshalHash(t *testing.T) { - } - enc, err := h2m.MarshalBinary() - if err != nil { -+ if strings.Contains(err.Error(), "hash state is not marshallable") { -+ t.Skip("BinaryMarshaler not supported") -+ } - t.Fatalf("MarshalBinary: %v", err) - } - if !bytes.Equal(enc, tt.golden) { -diff --git a/src/hash/notboring_test.go b/src/hash/notboring_test.go -new file mode 100644 -index 00000000000000..11dc691600b110 ---- /dev/null -+++ b/src/hash/notboring_test.go -@@ -0,0 +1,9 @@ -+// 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. -+ -+//go:build !goexperiment.systemcrypto -+ -+package hash_test -+ -+const boringEnabled = false -diff --git a/src/net/smtp/smtp_test.go b/src/net/smtp/smtp_test.go -index 389eda9ad54b99..110d60beb0e70c 100644 ---- a/src/net/smtp/smtp_test.go -+++ b/src/net/smtp/smtp_test.go -@@ -1136,40 +1136,60 @@ func sendMail(hostPort string) error { - - // localhostCert is a PEM-encoded TLS cert generated from src/crypto/tls: - // --// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com \ -+// Use a 2048-bits RSA key to make it FIPS-compliant. -+// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com \ - // --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h - var localhostCert = []byte(` - -----BEGIN CERTIFICATE----- --MIICFDCCAX2gAwIBAgIRAK0xjnaPuNDSreeXb+z+0u4wDQYJKoZIhvcNAQELBQAw --EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2 --MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw --gYkCgYEA0nFbQQuOWsjbGtejcpWz153OlziZM4bVjJ9jYruNw5n2Ry6uYQAffhqa --JOInCmmcVe2siJglsyH9aRh6vKiobBbIUXXUU1ABd56ebAzlt0LobLlx7pZEMy30 --LqIi9E6zmL3YvdGzpYlkFRnRrqwEtWYbGBf3znO250S56CCWH2UCAwEAAaNoMGYw --DgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQF --MAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAAAAAAAAAA --AAAAAAEwDQYJKoZIhvcNAQELBQADgYEAbZtDS2dVuBYvb+MnolWnCNqvw1w5Gtgi --NmvQQPOMgM3m+oQSCPRTNGSg25e1Qbo7bgQDv8ZTnq8FgOJ/rbkyERw2JckkHpD4 --n4qcK27WkEDBtQFlPihIM8hLIuzWoi/9wygiElTy/tVL3y7fGCvY2/k1KBthtZGF --tN8URjVmyEo= -+MIIDOTCCAiGgAwIBAgIQKhWw7zkzXjX78HaPlVbNrjANBgkqhkiG9w0BAQsFADAS -+MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw -+MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -+MIIBCgKCAQEAy1EYLA8IFvZyUPY+uI7KToneaQPvIzQiOeWlDnFnoanw6h3KpoVc -++yNbinK41WfXoSN/1kJ9gmGiFhJTPZ4rQ7DJsD7ethcpuz4uIimdWPohcBzwgbx4 -+wjhUgfUsCO6m76fFqrhbkHMDiS2iUjg2gyMVQCrqi8EuBW16yFQdJqPU04p+2rYw -+eJ9lzdeSLR4yvx7p1JS8sS4DbSyrAUaJ9J1sH/gu0nSHNMo7WtIu9K8JmPeYR4X5 -+5KLURBU9PmvoGW+5ss/xS6SnacHAD9FebNPQqGB/soBA9gdJIN+5KW0xcE38Zz5Q -+wAAUiU+VlWuZmge0sI8Ix8uIPIvGQSKN0wIDAQABo4GIMIGFMA4GA1UdDwEB/wQE -+AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -+DgQWBBRNMP9Cr0yrXpMpsgEtDr8FPmUEazAuBgNVHREEJzAlggtleGFtcGxlLmNv -+bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAF0/z -+KEnZrAsz4ov4fEvKY42EbKPm8s0pklPLmKVIh/iS7jTxxxvgDtOToiJ6IXY8Cfb3 -+nG1i78YakoVPUL5Cfh5LKDefMoefk6575ur2+gSdzgNmKUnlVfOMfpflia/ugATZ -+5ORhpmKRKWzwXQ67S5XeVlZAehTsywQstsDu8WEVoSUnRSk1jZsCThOQfdlpox+K -+71rGPSTxB9yCHMzZsk4xyZlGLaC0vDSJ+Zb5gWvAcvkSnpREvmc3/9TaW/lbUed6 -+uhO17lARcUhPCzkR5wAZCo/PihHMSXL8cqT4QdIux75OBxB/3EgLHL7KQw28A50g -+DogldK8zx1ZADmupUA== - -----END CERTIFICATE-----`) - - // localhostKey is the private key for localhostCert. - var localhostKey = []byte(testingKey(` - -----BEGIN RSA TESTING KEY----- --MIICXgIBAAKBgQDScVtBC45ayNsa16NylbPXnc6XOJkzhtWMn2Niu43DmfZHLq5h --AB9+Gpok4icKaZxV7ayImCWzIf1pGHq8qKhsFshRddRTUAF3np5sDOW3QuhsuXHu --lkQzLfQuoiL0TrOYvdi90bOliWQVGdGurAS1ZhsYF/fOc7bnRLnoIJYfZQIDAQAB --AoGBAMst7OgpKyFV6c3JwyI/jWqxDySL3caU+RuTTBaodKAUx2ZEmNJIlx9eudLA --kucHvoxsM/eRxlxkhdFxdBcwU6J+zqooTnhu/FE3jhrT1lPrbhfGhyKnUrB0KKMM --VY3IQZyiehpxaeXAwoAou6TbWoTpl9t8ImAqAMY8hlULCUqlAkEA+9+Ry5FSYK/m --542LujIcCaIGoG1/Te6Sxr3hsPagKC2rH20rDLqXwEedSFOpSS0vpzlPAzy/6Rbb --PHTJUhNdwwJBANXkA+TkMdbJI5do9/mn//U0LfrCR9NkcoYohxfKz8JuhgRQxzF2 --6jpo3q7CdTuuRixLWVfeJzcrAyNrVcBq87cCQFkTCtOMNC7fZnCTPUv+9q1tcJyB --vNjJu3yvoEZeIeuzouX9TJE21/33FaeDdsXbRhQEj23cqR38qFHsF1qAYNMCQQDP --QXLEiJoClkR2orAmqjPLVhR3t2oB3INcnEjLNSq8LHyQEfXyaFfu4U9l5+fRPL2i --jiC0k/9L5dHUsF0XZothAkEA23ddgRs+Id/HxtojqqUT27B8MT/IGNrYsp4DvS/c --qgkeluku4GjxRlDMBuXk94xOBEinUs+p/hwP1Alll80Tpg== -+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLURgsDwgW9nJQ -+9j64jspOid5pA+8jNCI55aUOcWehqfDqHcqmhVz7I1uKcrjVZ9ehI3/WQn2CYaIW -+ElM9nitDsMmwPt62Fym7Pi4iKZ1Y+iFwHPCBvHjCOFSB9SwI7qbvp8WquFuQcwOJ -+LaJSODaDIxVAKuqLwS4FbXrIVB0mo9TTin7atjB4n2XN15ItHjK/HunUlLyxLgNt -+LKsBRon0nWwf+C7SdIc0yjta0i70rwmY95hHhfnkotREFT0+a+gZb7myz/FLpKdp -+wcAP0V5s09CoYH+ygED2B0kg37kpbTFwTfxnPlDAABSJT5WVa5maB7SwjwjHy4g8 -+i8ZBIo3TAgMBAAECggEAc7dv/oN/ozIY1iOQhxId6p1lTHfEv1CIulMNoi7BQK2s -+RFM4Z5Y32WfCTgYFVNCJVVkTBStKq85Npio/3i4Libcw03K05wY/5iX5s8/jkiSq -+q1iNOgm+4SuWTXDw4xSRRo1CX2wWERykwoqKfCkqPXDWQ3Mpkukb/FLXMvVMshRA -+9v9L6MyrCnsFHl8q2J6hcC+RQJ0pb5I4NF6KhMxABWxxxlDO0zYLA0wfhEn8nj/l -+J37QLHmsA7pzxo+NqDTPgpfBuuTbRVGMkC+fPCXYinbubBeURFO2j2yBlseK+Vbd -+sEffiAnPr4ocCz0k0tHAMMY7hKHup2HWuJGFu0IhAQKBgQDkKFEEcYWNx5Ybl1LV -+qr2qIYofpFL+Gu5MWSZxzZbE8u9v0tTsp8SRhXkgjeHY6qjBUBnLgklOKwSigQAm -+j9de44cXjnUIArzeAHsH3fzpYrLfsvBla6wQyr34D0chVCZ0cX/s/zXkSN4PcEkA -+GGfKAENrGskDyc4uq1sIactu8wKBgQDkIL/XT7ysvsaxA+SfIs2CHgb8GNKgtoI1 -+QyR0+MfeJGCLwI9qcLbVzXda34qrzQw3YLIm2VHqhzJ4zb0gnyJ4adPZYwpLTgiU -+jVksBVIwBTfbxYvF2+07poCSobCFKLGQnAujhDDIGDAUKQXQmFcqUNWw0QHfQzkS -+xs36H27doQKBgQCjM8+YLRgKbc0LGXhwTHz1GJ6zuZiAGYWB6XddimEhqmDpjVcv -+nWY3bdFSHwuBXYGvHfwFncGP/6eGEl6oNtYpEvoMOKOwQj0VVCStYPZLf4VSDK52 -+7ckcDdpLeao4xffn7VRDk97Z1+G4C2q8fbioPv36vCMz6YPp0DsCzqJtTwKBgCUN -+4LtDW10fu7xC6p6ik4jgAbhu+79ZBbtLBZ/uTOCbPgdVJrZeSoRd1FYxWx/etW5F -+SYqf3/tdLGiM2nxy/LFcVynHOYPTz/b5IpPQ5XGhV1peMv7XYyg+OkIW+0oVuwnH -+HujXbukBbMXJiAVCyV25NYx71ncCP0H6grhu5J4hAoGAUaketZWHD/ks9JCoPtfy -+pNnXqrIvTp1cSGJpVUQT/DUqAjevyZ5Q8PFPf09BZ6uYlXtCqsp7pA/fqNdlJRPR -+tHRjpZ5XauBiFdpRNH4tJBTiWWhyuWhkWn369Az7HP3CIlJLeq2FlKCvMClcO4op -+Qc9LHT7jqtcy+LqAVBpsJ/o= - -----END RSA TESTING KEY-----`)) - - func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/src/runtime/runtime_boring.go b/src/runtime/runtime_boring.go index 5a98b20253181c..9042f2c2795e19 100644 --- a/src/runtime/runtime_boring.go diff --git a/patches/0005-Add-OpenSSL-crypto-backend.patch b/patches/0005-Add-OpenSSL-crypto-backend.patch index b353bd0cfea..7cfe62fcf7a 100644 --- a/patches/0005-Add-OpenSSL-crypto-backend.patch +++ b/patches/0005-Add-OpenSSL-crypto-backend.patch @@ -476,19 +476,19 @@ index 00000000000000..0f3aea733ac2a5 + return openssl.VerifyDSA(pub, hashed, sig) +} diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go -index 30811455e88418..3de94c93629e3d 100644 +index a46d6c034ca1e0..12086de2c2e766 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go -@@ -509,7 +509,7 @@ var depsRules = ` +@@ -505,7 +505,7 @@ var depsRules = ` + NONE < crypto/internal/boring/sig, crypto/internal/boring/syso; + sync/atomic < crypto/internal/boring/bcache; + +- FIPS, internal/godebug, hash, embed, ++ FIPS, internal/godebug, hash, embed, encoding/binary, crypto/internal/boring/sig, crypto/internal/boring/syso, - encoding/binary, -- crypto/internal/boring/bcache -+ crypto/internal/boring/bcache, - crypto/internal/backend/fips140 - < crypto/internal/fips140only - < crypto -@@ -517,6 +517,8 @@ var depsRules = ` + crypto/internal/boring/bcache, +@@ -516,6 +516,8 @@ var depsRules = ` < crypto/sha3 < crypto/internal/fips140hash < crypto/cipher @@ -497,7 +497,7 @@ index 30811455e88418..3de94c93629e3d 100644 < crypto/internal/boring < crypto/internal/backend < crypto/boring -@@ -540,6 +542,7 @@ var depsRules = ` +@@ -538,6 +540,7 @@ var depsRules = ` # CRYPTO-MATH is crypto that exposes math/big APIs - no cgo, net; fmt now ok. CRYPTO, FMT, math/big @@ -505,7 +505,7 @@ index 30811455e88418..3de94c93629e3d 100644 < crypto/internal/boring/bbig < crypto/internal/backend/bbig < crypto/rand -@@ -844,7 +847,7 @@ var buildIgnore = []byte("\n//go:build ignore") +@@ -842,7 +845,7 @@ var buildIgnore = []byte("\n//go:build ignore") func findImports(pkg string) ([]string, error) { vpkg := pkg @@ -514,7 +514,7 @@ index 30811455e88418..3de94c93629e3d 100644 vpkg = "vendor/" + pkg } dir := filepath.Join(Default.GOROOT, "src", vpkg) -@@ -854,7 +857,7 @@ func findImports(pkg string) ([]string, error) { +@@ -852,7 +855,7 @@ func findImports(pkg string) ([]string, error) { } var imports []string var haveImport = map[string]bool{} diff --git a/patches/0007-Use-crypto-backends.patch b/patches/0007-Use-crypto-backends.patch new file mode 100644 index 00000000000..f00c8e992fe --- /dev/null +++ b/patches/0007-Use-crypto-backends.patch @@ -0,0 +1,2443 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: qmuntal +Date: Tue, 14 Jan 2025 11:10:21 +0100 +Subject: [PATCH] Use crypto backends + +--- + src/cmd/api/boring_test.go | 2 +- + src/cmd/go/go_boring_test.go | 2 +- + .../go/testdata/script/gopath_std_vendor.txt | 9 + + src/crypto/aes/aes.go | 2 +- + src/crypto/boring/boring.go | 4 +- + src/crypto/cipher/ctr_aes_test.go | 2 +- + src/crypto/cipher/gcm_test.go | 2 +- + src/crypto/des/cipher.go | 7 + + src/crypto/dsa/boring.go | 113 +++++++++++ + src/crypto/dsa/dsa.go | 88 +++++++++ + src/crypto/dsa/notboring.go | 16 ++ + src/crypto/ecdh/ecdh.go | 2 +- + src/crypto/ecdh/ecdh_test.go | 4 + + src/crypto/ecdh/nist.go | 2 +- + src/crypto/ecdsa/badlinkname.go | 19 ++ + src/crypto/ecdsa/boring.go | 6 +- + src/crypto/ecdsa/ecdsa.go | 4 +- + src/crypto/ecdsa/notboring.go | 4 +- + src/crypto/ed25519/boring.go | 71 +++++++ + src/crypto/ed25519/ed25519.go | 73 +++++++ + src/crypto/ed25519/notboring.go | 16 ++ + src/crypto/hkdf/hkdf.go | 14 ++ + src/crypto/hkdf/hkdf_test.go | 2 +- + src/crypto/hmac/hmac.go | 2 +- + src/crypto/hmac/hmac_test.go | 2 +- + src/crypto/internal/cryptotest/allocations.go | 2 +- + .../internal/cryptotest/implementations.go | 2 +- + src/crypto/md5/md5.go | 10 + + src/crypto/md5/md5_test.go | 21 ++ + src/crypto/pbkdf2/pbkdf2.go | 4 + + src/crypto/pbkdf2/pbkdf2_test.go | 2 +- + src/crypto/purego_test.go | 2 +- + src/crypto/rand/rand.go | 2 +- + src/crypto/rc4/rc4.go | 18 ++ + src/crypto/rsa/boring.go | 6 +- + src/crypto/rsa/boring_test.go | 2 +- + src/crypto/rsa/fips.go | 10 +- + src/crypto/rsa/notboring.go | 4 +- + src/crypto/rsa/pkcs1v15.go | 6 +- + src/crypto/rsa/pkcs1v15_test.go | 5 + + src/crypto/rsa/pss_test.go | 9 +- + src/crypto/rsa/rsa.go | 4 +- + src/crypto/rsa/rsa_test.go | 15 +- + src/crypto/sha1/sha1.go | 8 +- + src/crypto/sha1/sha1_test.go | 19 +- + src/crypto/sha256/sha256.go | 6 +- + src/crypto/sha256/sha256_test.go | 29 +++ + src/crypto/sha512/sha512.go | 2 +- + src/crypto/sha512/sha512_test.go | 29 +++ + src/crypto/tls/cipher_suites.go | 2 +- + src/crypto/tls/fipsonly/fipsonly.go | 2 +- + src/crypto/tls/fipsonly/fipsonly_test.go | 2 +- + src/crypto/tls/handshake_client.go | 12 +- + src/crypto/tls/handshake_client_tls13.go | 16 +- + src/crypto/tls/handshake_server.go | 10 +- + src/crypto/tls/handshake_server_tls13.go | 27 ++- + src/crypto/tls/internal/fips140tls/fipstls.go | 3 +- + src/crypto/tls/internal/tls13/doc.go | 18 ++ + src/crypto/tls/internal/tls13/tls13.go | 182 ++++++++++++++++++ + src/crypto/tls/key_schedule.go | 2 +- + src/crypto/tls/prf.go | 41 ++++ + src/go/build/deps_test.go | 3 +- + src/hash/boring_test.go | 9 + + src/hash/example_test.go | 2 + + src/hash/marshal_test.go | 9 + + src/hash/notboring_test.go | 9 + + src/net/smtp/smtp_test.go | 72 ++++--- + 67 files changed, 1009 insertions(+), 97 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 + create mode 100644 src/crypto/ed25519/boring.go + create mode 100644 src/crypto/ed25519/notboring.go + create mode 100644 src/crypto/tls/internal/tls13/doc.go + create mode 100644 src/crypto/tls/internal/tls13/tls13.go + create mode 100644 src/hash/boring_test.go + create mode 100644 src/hash/notboring_test.go + +diff --git a/src/cmd/api/boring_test.go b/src/cmd/api/boring_test.go +index f0e3575637c62a..9eab3b4e66e60b 100644 +--- a/src/cmd/api/boring_test.go ++++ b/src/cmd/api/boring_test.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build goexperiment.systemcrypto + + package main + +diff --git a/src/cmd/go/go_boring_test.go b/src/cmd/go/go_boring_test.go +index ed0fbf3d53d75b..06478963f4be44 100644 +--- a/src/cmd/go/go_boring_test.go ++++ b/src/cmd/go/go_boring_test.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build goexperiment.systemcrypto + + package main_test + +diff --git a/src/cmd/go/testdata/script/gopath_std_vendor.txt b/src/cmd/go/testdata/script/gopath_std_vendor.txt +index 4aaf46b5d0f0dc..ec58a217400caa 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 @@ + env GO111MODULE=off + ++# Disable systemcrypto while evaluating test dependencies to avoid importing ++# vendored crypto module dependencies like golang-fips/openssl. This test script ++# is not set up to handle any vendored libraries being imported other than ++# 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 ++ + [!compiler:gc] skip + + go list -f '{{.Dir}}' vendor/golang.org/x/net/http2/hpack +diff --git a/src/crypto/aes/aes.go b/src/crypto/aes/aes.go +index 5bc2d13d673e0a..b803c77be62a66 100644 +--- a/src/crypto/aes/aes.go ++++ b/src/crypto/aes/aes.go +@@ -15,7 +15,7 @@ package aes + + import ( + "crypto/cipher" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/aes" + "strconv" + ) +diff --git a/src/crypto/boring/boring.go b/src/crypto/boring/boring.go +index 097c37e343fdb8..a5d603896d3890 100644 +--- a/src/crypto/boring/boring.go ++++ b/src/crypto/boring/boring.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build goexperiment.systemcrypto + + // Package boring exposes functions that are only available when building with + // Go+BoringCrypto. This package is available on all targets as long as the +@@ -13,7 +13,7 @@ + // is satisfied, so that applications can tag files that use this package. + package boring + +-import "crypto/internal/boring" ++import boring "crypto/internal/backend" + + // Enabled reports whether BoringCrypto handles supported crypto operations. + func Enabled() bool { +diff --git a/src/crypto/cipher/ctr_aes_test.go b/src/crypto/cipher/ctr_aes_test.go +index 33942467784ad3..0282ffa9fa23c8 100644 +--- a/src/crypto/cipher/ctr_aes_test.go ++++ b/src/crypto/cipher/ctr_aes_test.go +@@ -14,7 +14,7 @@ import ( + "bytes" + "crypto/aes" + "crypto/cipher" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/cryptotest" + fipsaes "crypto/internal/fips140/aes" + "encoding/hex" +diff --git a/src/crypto/cipher/gcm_test.go b/src/crypto/cipher/gcm_test.go +index ea2b4e29e2b67f..f884b0d0fbefe7 100644 +--- a/src/crypto/cipher/gcm_test.go ++++ b/src/crypto/cipher/gcm_test.go +@@ -8,7 +8,7 @@ import ( + "bytes" + "crypto/aes" + "crypto/cipher" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/cryptotest" + "crypto/internal/fips140" + fipsaes "crypto/internal/fips140/aes" +diff --git a/src/crypto/des/cipher.go b/src/crypto/des/cipher.go +index 21303b384cf757..0d3c4f810cfd8f 100644 +--- a/src/crypto/des/cipher.go ++++ b/src/crypto/des/cipher.go +@@ -6,6 +6,7 @@ package des + + import ( + "crypto/cipher" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/alias" + "crypto/internal/fips140only" + "errors" +@@ -36,6 +37,9 @@ func NewCipher(key []byte) (cipher.Block, error) { + if len(key) != 8 { + return nil, KeySizeError(len(key)) + } ++ if boring.Enabled && boring.SupportsDESCipher() { ++ return boring.NewDESCipher(key) ++ } + + c := new(desCipher) + c.generateSubkeys(key) +@@ -84,6 +88,9 @@ func NewTripleDESCipher(key []byte) (cipher.Block, error) { + if len(key) != 24 { + return nil, KeySizeError(len(key)) + } ++ if boring.Enabled && boring.SupportsTripleDESCipher() { ++ return boring.NewTripleDESCipher(key) ++ } + + c := new(tripleDESCipher) + c.cipher1.generateSubkeys(key[:8]) +diff --git a/src/crypto/dsa/boring.go b/src/crypto/dsa/boring.go +new file mode 100644 +index 00000000000000..7ea0c8c423e9ee +--- /dev/null ++++ b/src/crypto/dsa/boring.go +@@ -0,0 +1,113 @@ ++// 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 dsa ++ ++import ( ++ boring "crypto/internal/backend" ++ "crypto/internal/backend/bbig" ++ "crypto/internal/boring/bcache" ++ "math/big" ++) ++ ++// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto. ++// ++// The first operation on a PublicKey or PrivateKey makes a parallel ++// BoringCrypto key and saves it in pubCache or privCache. ++// ++// We could just assume that once used in a sign/verify/encrypt/decrypt operation, ++// a particular key is never again modified, but that has not been a ++// stated assumption before. Just in case there is any existing code that ++// does modify the key between operations, we save the original values ++// alongside the cached BoringCrypto key and check that the real key ++// still matches before using the cached key. The theory is that the real ++// operations are significantly more expensive than the comparison. ++ ++type boringPub struct { ++ key *boring.PublicKeyDSA ++ orig PublicKey ++} ++ ++var pubCache bcache.Cache[PublicKey, boringPub] ++var privCache bcache.Cache[PrivateKey, boringPriv] ++ ++func init() { ++ pubCache.Register() ++ privCache.Register() ++} ++ ++func boringPublicKey(pub *PublicKey) (*boring.PublicKeyDSA, error) { ++ b := pubCache.Get(pub) ++ if b != nil && publicKeyEqual(&b.orig, pub) { ++ return b.key, nil ++ } ++ ++ b = new(boringPub) ++ b.orig = copyPublicKey(pub) ++ key, err := boring.NewPublicKeyDSA(bbig.Enc(b.orig.P), bbig.Enc(b.orig.Q), bbig.Enc(b.orig.G), bbig.Enc(b.orig.Y)) ++ if err != nil { ++ return nil, err ++ } ++ b.key = key ++ pubCache.Put(pub, b) ++ return key, nil ++} ++ ++type boringPriv struct { ++ key *boring.PrivateKeyDSA ++ orig PrivateKey ++} ++ ++func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyDSA, error) { ++ b := privCache.Get(priv) ++ if b != nil && privateKeyEqual(&b.orig, priv) { ++ return b.key, nil ++ } ++ ++ b = new(boringPriv) ++ b.orig = copyPrivateKey(priv) ++ ++ P := b.orig.P ++ Q := b.orig.Q ++ G := b.orig.G ++ X := b.orig.X ++ Y := b.orig.Y ++ ++ key, err := boring.NewPrivateKeyDSA(bbig.Enc(P), bbig.Enc(Q), bbig.Enc(G), bbig.Enc(X), bbig.Enc(Y)) ++ if err != nil { ++ return nil, err ++ } ++ b.key = key ++ privCache.Put(priv, b) ++ return key, nil ++} ++ ++func publicKeyEqual(k1, k2 *PublicKey) bool { ++ return k1.Y != nil && k1.Y.Cmp(k2.Y) == 0 && k1.P.Cmp(k2.P) == 0 && k1.Q.Cmp(k2.Q) == 0 && k1.G.Cmp(k2.G) == 0 ++} ++ ++func copyPublicKey(k *PublicKey) PublicKey { ++ return PublicKey{ ++ Parameters: Parameters{ ++ P: new(big.Int).Set(k.P), ++ Q: new(big.Int).Set(k.Q), ++ G: new(big.Int).Set(k.G), ++ }, ++ Y: new(big.Int).Set(k.Y), ++ } ++} ++ ++func privateKeyEqual(k1, k2 *PrivateKey) bool { ++ return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) && ++ k1.X.Cmp(k2.X) == 0 ++} ++ ++func copyPrivateKey(k *PrivateKey) PrivateKey { ++ return PrivateKey{ ++ PublicKey: copyPublicKey(&k.PublicKey), ++ X: new(big.Int).Set(k.X), ++ } ++} +diff --git a/src/crypto/dsa/dsa.go b/src/crypto/dsa/dsa.go +index 000becc82dfb79..6430bb3ea5e437 100644 +--- a/src/crypto/dsa/dsa.go ++++ b/src/crypto/dsa/dsa.go +@@ -18,8 +18,13 @@ import ( + "io" + "math/big" + ++ boring "crypto/internal/backend" ++ "crypto/internal/backend/bbig" + "crypto/internal/fips140only" + "crypto/internal/randutil" ++ ++ "golang.org/x/crypto/cryptobyte" ++ "golang.org/x/crypto/cryptobyte/asn1" + ) + + // Parameters represents the domain parameters for a key. These parameters can +@@ -91,6 +96,17 @@ func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes + return errors.New("crypto/dsa: invalid ParameterSizes") + } + ++ if boring.Enabled && boring.SupportsDSA(L, N) { ++ p, q, g, err := boring.GenerateParametersDSA(L, N) ++ if err != nil { ++ return err ++ } ++ params.P = bbig.Dec(p) ++ params.Q = bbig.Dec(q) ++ params.G = bbig.Dec(g) ++ return nil ++ } ++ + qBytes := make([]byte, N/8) + pBytes := make([]byte, L/8) + +@@ -170,6 +186,17 @@ func GenerateKey(priv *PrivateKey, rand io.Reader) error { + return errors.New("crypto/dsa: parameters not set up before generating key") + } + ++ if boring.Enabled && boring.SupportsDSA(priv.P.BitLen(), priv.Q.BitLen()) { ++ x, y, err := boring.GenerateKeyDSA(bbig.Enc(priv.P), bbig.Enc(priv.Q), bbig.Enc(priv.G)) ++ if err != nil { ++ return err ++ } ++ priv.X = bbig.Dec(x) ++ priv.Y = bbig.Dec(y) ++ ++ return nil ++ } ++ + x := new(big.Int) + xBytes := make([]byte, priv.Q.BitLen()/8) + +@@ -225,6 +252,18 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err + err = ErrInvalidPublicKey + return + } ++ ++ if boring.Enabled && boring.SupportsDSA(priv.P.BitLen(), priv.Q.BitLen()) { ++ b, err := boringPrivateKey(priv) ++ if err != nil { ++ return nil, nil, err ++ } ++ ++ r, s, err := boring.SignDSA(b, hash, parseSignature) ++ ++ return bbig.Dec(r), bbig.Dec(s), err ++ } ++ + n >>= 3 + + var attempts int +@@ -288,6 +327,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") + } + ++ if boring.Enabled && boring.SupportsDSA(pub.P.BitLen(), pub.Q.BitLen()) { ++ bkey, err := boringPublicKey(pub) ++ if err != nil { ++ return false ++ } ++ ++ return boring.VerifyDSA(bkey, hash, bbig.Enc(r), bbig.Enc(s), encodeSignature) ++ } + // FIPS 186-3, section 4.7 + + if pub.P.Sign() == 0 { +@@ -324,3 +371,44 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { + + return v.Cmp(r) == 0 + } ++ ++func parseSignature(sig []byte) (boring.BigInt, boring.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 boring.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) ++ }) ++} +diff --git a/src/crypto/dsa/notboring.go b/src/crypto/dsa/notboring.go +new file mode 100644 +index 00000000000000..cd02ff5a00c3dc +--- /dev/null ++++ b/src/crypto/dsa/notboring.go +@@ -0,0 +1,16 @@ ++// Copyright 2022 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 dsa ++ ++import boring "crypto/internal/backend" ++ ++func boringPublicKey(*PublicKey) (*boring.PublicKeyDSA, error) { ++ panic("boringcrypto: not available") ++} ++func boringPrivateKey(*PrivateKey) (*boring.PrivateKeyDSA, error) { ++ panic("boringcrypto: not available") ++} +diff --git a/src/crypto/ecdh/ecdh.go b/src/crypto/ecdh/ecdh.go +index 231f1ea04c1010..cfa113e2345816 100644 +--- a/src/crypto/ecdh/ecdh.go ++++ b/src/crypto/ecdh/ecdh.go +@@ -8,7 +8,7 @@ package ecdh + + import ( + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/ecdh" + "crypto/subtle" + "errors" +diff --git a/src/crypto/ecdh/ecdh_test.go b/src/crypto/ecdh/ecdh_test.go +index 75d2480775669f..6a4d26fbafe090 100644 +--- a/src/crypto/ecdh/ecdh_test.go ++++ b/src/crypto/ecdh/ecdh_test.go +@@ -9,6 +9,7 @@ import ( + "crypto" + "crypto/cipher" + "crypto/ecdh" ++ boring "crypto/internal/backend" + "crypto/rand" + "crypto/sha256" + "encoding/hex" +@@ -280,6 +281,9 @@ var invalidPrivateKeys = map[ecdh.Curve][]string{ + } + + func TestNewPrivateKey(t *testing.T) { ++ if boring.Enabled { ++ t.Skip("skipping test with different results when using different backends") ++ } + testAllCurves(t, func(t *testing.T, curve ecdh.Curve) { + for _, input := range invalidPrivateKeys[curve] { + k, err := curve.NewPrivateKey(hexDecode(t, input)) +diff --git a/src/crypto/ecdh/nist.go b/src/crypto/ecdh/nist.go +index acef8298943c2b..ca6171cf775117 100644 +--- a/src/crypto/ecdh/nist.go ++++ b/src/crypto/ecdh/nist.go +@@ -6,7 +6,7 @@ package ecdh + + import ( + "bytes" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/ecdh" + "crypto/internal/fips140only" + "errors" +diff --git a/src/crypto/ecdsa/badlinkname.go b/src/crypto/ecdsa/badlinkname.go +new file mode 100644 +index 00000000000000..1dc05d09b2062d +--- /dev/null ++++ b/src/crypto/ecdsa/badlinkname.go +@@ -0,0 +1,19 @@ ++// 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. ++ ++//go:build goexperiment.systemcrypto ++ ++package ecdsa ++ ++import _ "unsafe" ++ ++// The symbols below are pulled by some crypto backend in the Microsoft Go compiler. ++// We provide a push linkname here, to keep them accessible with pull linknames. ++ ++//go:linkname encodeSignature ++//go:linkname parseSignature ++ ++// This supplements other linknames that are already added by ++// https://github.com/golang/go/commit/41aab30bd260297ad8ddad47e98fdf8390a9a67e ++// See that commit for more information. +diff --git a/src/crypto/ecdsa/boring.go b/src/crypto/ecdsa/boring.go +index 275c60b4de49eb..ff8bddf28c4545 100644 +--- a/src/crypto/ecdsa/boring.go ++++ b/src/crypto/ecdsa/boring.go +@@ -2,13 +2,13 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build goexperiment.systemcrypto + + package ecdsa + + import ( +- "crypto/internal/boring" +- "crypto/internal/boring/bbig" ++ boring "crypto/internal/backend" ++ "crypto/internal/backend/bbig" + "crypto/internal/boring/bcache" + "math/big" + ) +diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go +index cb308b41e9df86..8f73855aa738de 100644 +--- a/src/crypto/ecdsa/ecdsa.go ++++ b/src/crypto/ecdsa/ecdsa.go +@@ -20,8 +20,8 @@ import ( + "crypto" + "crypto/ecdh" + "crypto/elliptic" +- "crypto/internal/boring" +- "crypto/internal/boring/bbig" ++ boring "crypto/internal/backend" ++ "crypto/internal/backend/bbig" + "crypto/internal/fips140/ecdsa" + "crypto/internal/fips140hash" + "crypto/internal/fips140only" +diff --git a/src/crypto/ecdsa/notboring.go b/src/crypto/ecdsa/notboring.go +index 039bd82ed21f9f..69a97d9bf250be 100644 +--- a/src/crypto/ecdsa/notboring.go ++++ b/src/crypto/ecdsa/notboring.go +@@ -2,11 +2,11 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build !boringcrypto ++//go:build !goexperiment.systemcrypto + + package ecdsa + +-import "crypto/internal/boring" ++import boring "crypto/internal/backend" + + func boringPublicKey(*PublicKey) (*boring.PublicKeyECDSA, error) { + panic("boringcrypto: not available") +diff --git a/src/crypto/ed25519/boring.go b/src/crypto/ed25519/boring.go +new file mode 100644 +index 00000000000000..cce33e4d6cc927 +--- /dev/null ++++ b/src/crypto/ed25519/boring.go +@@ -0,0 +1,71 @@ ++// Copyright 2023 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 ed25519 ++ ++import ( ++ boring "crypto/internal/backend" ++ "crypto/internal/boring/bcache" ++ "unsafe" ++) ++ ++var pubCache bcache.Cache[byte, boringPub] ++var privCache bcache.Cache[byte, boringPriv] ++ ++func init() { ++ if boring.Enabled && boring.SupportsEd25519() { ++ pubCache.Register() ++ privCache.Register() ++ } ++} ++ ++type boringPub struct { ++ key *boring.PublicKeyEd25519 ++ orig [PublicKeySize]byte ++} ++ ++func boringPublicKey(pub PublicKey) (*boring.PublicKeyEd25519, error) { ++ // Use the pointer to the underlying pub array as key. ++ p := unsafe.SliceData(pub) ++ b := pubCache.Get(p) ++ if b != nil && PublicKey(b.orig[:]).Equal(pub) { ++ return b.key, nil ++ } ++ ++ b = new(boringPub) ++ copy(b.orig[:], pub) ++ key, err := boring.NewPublicKeyEd25519(b.orig[:]) ++ if err != nil { ++ return nil, err ++ } ++ b.key = key ++ pubCache.Put(p, b) ++ return key, nil ++} ++ ++type boringPriv struct { ++ key *boring.PrivateKeyEd25519 ++ orig [PrivateKeySize]byte ++} ++ ++func boringPrivateKey(priv PrivateKey) (*boring.PrivateKeyEd25519, error) { ++ // Use the pointer to the underlying priv array as key. ++ p := unsafe.SliceData(priv) ++ b := privCache.Get(p) ++ if b != nil && PrivateKey(b.orig[:]).Equal(priv) { ++ return b.key, nil ++ } ++ ++ b = new(boringPriv) ++ copy(b.orig[:], priv) ++ key, err := boring.NewPrivateKeyEd25519(b.orig[:]) ++ if err != nil { ++ return nil, err ++ } ++ b.key = key ++ privCache.Put(p, b) ++ return key, nil ++} +diff --git a/src/crypto/ed25519/ed25519.go b/src/crypto/ed25519/ed25519.go +index c1f8ff784e4a5c..6476bfbe896d6c 100644 +--- a/src/crypto/ed25519/ed25519.go ++++ b/src/crypto/ed25519/ed25519.go +@@ -17,6 +17,7 @@ package ed25519 + + import ( + "crypto" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/ed25519" + "crypto/internal/fips140only" + cryptorand "crypto/rand" +@@ -24,6 +25,7 @@ import ( + "errors" + "io" + "strconv" ++ "sync" + ) + + const ( +@@ -138,6 +140,22 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { + if rand == nil { + rand = cryptorand.Reader + } ++ if boring.Enabled && boring.SupportsEd25519() { ++ if rand == boring.RandReader { ++ priv, err := boring.GenerateKeyEd25519() ++ if err != nil { ++ return nil, nil, err ++ } ++ privData, err := priv.Bytes() ++ if err != nil { ++ return nil, nil, err ++ } ++ privKey := PrivateKey(privData) ++ pubKey := privKey.Public().(PublicKey) ++ return pubKey, privKey, err ++ } ++ boring.UnreachableExceptTests() ++ } + + seed := make([]byte, SeedSize) + if _, err := io.ReadFull(rand, seed); err != nil { +@@ -154,6 +172,17 @@ func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) { + // with RFC 8032. RFC 8032's private keys correspond to seeds in this + // package. + func NewKeyFromSeed(seed []byte) PrivateKey { ++ if boring.Enabled && boring.SupportsEd25519() { ++ key, err := boring.NewPrivateKeyEd25519FromSeed(seed) ++ if err != nil { ++ panic(err) ++ } ++ d, err := key.Bytes() ++ if err != nil { ++ panic(err) ++ } ++ return PrivateKey(d) ++ } + // Outline the function body so that the returned key can be stack-allocated. + privateKey := make([]byte, PrivateKeySize) + newKeyFromSeed(privateKey, seed) +@@ -172,6 +201,17 @@ func newKeyFromSeed(privateKey, seed []byte) { + // Sign signs the message with privateKey and returns a signature. It will + // panic if len(privateKey) is not [PrivateKeySize]. + func Sign(privateKey PrivateKey, message []byte) []byte { ++ if boring.Enabled && boring.SupportsEd25519() { ++ priv, err := boringPrivateKey(privateKey) ++ if err != nil { ++ panic(err) ++ } ++ signature, err := boring.SignEd25519(priv, message) ++ if err != nil { ++ panic(err) ++ } ++ return signature ++ } + // Outline the function body so that the returned signature can be + // stack-allocated. + signature := make([]byte, SignatureSize) +@@ -200,6 +240,32 @@ func Verify(publicKey PublicKey, message, sig []byte) bool { + return VerifyWithOptions(publicKey, message, sig, &Options{Hash: crypto.Hash(0)}) == nil + } + ++// testMalleability returns true if the crypto backend correctly rejects ++// malleable signatures. The only known backend that fails to do so is ++// OpenSSL version 1.1.1a or lower. ++// See https://github.com/openssl/openssl/issues/7693. ++var testMalleability = sync.OnceValue(func() bool { ++ msg := []byte{0x54, 0x65, 0x73, 0x74} ++ sig := []byte{ ++ 0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a, ++ 0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b, ++ 0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67, ++ 0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d, ++ 0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33, ++ 0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d, ++ } ++ pkey := []byte{ ++ 0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5, ++ 0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34, ++ 0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa, ++ } ++ pub, err := boring.NewPublicKeyEd25519(pkey) ++ if err != nil { ++ return false ++ } ++ return boring.VerifyEd25519(pub, msg, sig) != nil ++}) ++ + // VerifyWithOptions reports whether sig is a valid signature of message by + // publicKey. A valid signature is indicated by returning a nil error. It will + // panic if len(publicKey) is not [PublicKeySize]. +@@ -228,6 +294,13 @@ func VerifyWithOptions(publicKey PublicKey, message, sig []byte, opts *Options) + } + return ed25519.VerifyCtx(k, message, sig, opts.Context) + case opts.Hash == crypto.Hash(0): // Ed25519 ++ if boring.Enabled && boring.SupportsEd25519() && testMalleability() { ++ pub, err := boringPublicKey(publicKey) ++ if err != nil { ++ return err ++ } ++ return boring.VerifyEd25519(pub, message, sig) ++ } + return ed25519.Verify(k, message, sig) + 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/notboring.go b/src/crypto/ed25519/notboring.go +new file mode 100644 +index 00000000000000..b0cdd44d81c753 +--- /dev/null ++++ b/src/crypto/ed25519/notboring.go +@@ -0,0 +1,16 @@ ++// Copyright 2023 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 ed25519 ++ ++import boring "crypto/internal/backend" ++ ++func boringPublicKey(PublicKey) (*boring.PublicKeyEd25519, error) { ++ panic("boringcrypto: not available") ++} ++func boringPrivateKey(PrivateKey) (*boring.PrivateKeyEd25519, error) { ++ panic("boringcrypto: not available") ++} +diff --git a/src/crypto/hkdf/hkdf.go b/src/crypto/hkdf/hkdf.go +index 6b02522866d57f..37e67ec184af5d 100644 +--- a/src/crypto/hkdf/hkdf.go ++++ b/src/crypto/hkdf/hkdf.go +@@ -11,6 +11,7 @@ + package hkdf + + import ( ++ boring "crypto/internal/backend" + "crypto/internal/fips140/hkdf" + "crypto/internal/fips140hash" + "crypto/internal/fips140only" +@@ -29,6 +30,9 @@ func Extract[H hash.Hash](h func() H, secret, salt []byte) ([]byte, error) { + if err := checkFIPS140Only(fh, secret); err != nil { + return nil, err + } ++ if boring.Enabled && boring.SupportsHKDF() { ++ return boring.ExtractHKDF(fh, secret, salt) ++ } + return hkdf.Extract(fh, secret, salt), nil + } + +@@ -50,6 +54,9 @@ func Expand[H hash.Hash](h func() H, pseudorandomKey []byte, info string, keyLen + return nil, errors.New("hkdf: requested key length too large") + } + ++ if boring.Enabled && boring.SupportsHKDF() { ++ return boring.ExpandHKDF(fh, pseudorandomKey, []byte(info), keyLength) ++ } + return hkdf.Expand(fh, pseudorandomKey, info, keyLength), nil + } + +@@ -67,6 +74,13 @@ func Key[Hash hash.Hash](h func() Hash, secret, salt []byte, info string, keyLen + return nil, errors.New("hkdf: requested key length too large") + } + ++ if boring.Enabled && boring.SupportsHKDF() { ++ pseudorandomKey, err := boring.ExtractHKDF(fh, secret, salt) ++ if err != nil { ++ return nil, err ++ } ++ return boring.ExpandHKDF(fh, pseudorandomKey, []byte(info), keyLength) ++ } + return hkdf.Key(fh, secret, salt, info, keyLength), nil + } + +diff --git a/src/crypto/hkdf/hkdf_test.go b/src/crypto/hkdf/hkdf_test.go +index 201b440289bb2d..4ed4960ff35b66 100644 +--- a/src/crypto/hkdf/hkdf_test.go ++++ b/src/crypto/hkdf/hkdf_test.go +@@ -6,7 +6,7 @@ package hkdf + + import ( + "bytes" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140" + "crypto/md5" + "crypto/sha1" +diff --git a/src/crypto/hmac/hmac.go b/src/crypto/hmac/hmac.go +index 554c8c9b78940b..c68a394280cc2c 100644 +--- a/src/crypto/hmac/hmac.go ++++ b/src/crypto/hmac/hmac.go +@@ -22,7 +22,7 @@ timing side-channels: + package hmac + + import ( +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/hmac" + "crypto/internal/fips140hash" + "crypto/internal/fips140only" +diff --git a/src/crypto/hmac/hmac_test.go b/src/crypto/hmac/hmac_test.go +index 7accad763244a1..dd3211f2c37af3 100644 +--- a/src/crypto/hmac/hmac_test.go ++++ b/src/crypto/hmac/hmac_test.go +@@ -5,7 +5,7 @@ + package hmac + + import ( +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/cryptotest" + "crypto/md5" + "crypto/sha1" +diff --git a/src/crypto/internal/cryptotest/allocations.go b/src/crypto/internal/cryptotest/allocations.go +index 70055af70b42ec..3c4b4fbaa98ded 100644 +--- a/src/crypto/internal/cryptotest/allocations.go ++++ b/src/crypto/internal/cryptotest/allocations.go +@@ -5,7 +5,7 @@ + package cryptotest + + import ( +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "internal/asan" + "internal/msan" + "internal/race" +diff --git a/src/crypto/internal/cryptotest/implementations.go b/src/crypto/internal/cryptotest/implementations.go +index 3fa730459050f6..1f28f12a6e7b4f 100644 +--- a/src/crypto/internal/cryptotest/implementations.go ++++ b/src/crypto/internal/cryptotest/implementations.go +@@ -5,7 +5,7 @@ + package cryptotest + + import ( +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/impl" + "internal/goos" + "internal/testenv" +diff --git a/src/crypto/md5/md5.go b/src/crypto/md5/md5.go +index a0384e175f31bd..f7aa6da36f02de 100644 +--- a/src/crypto/md5/md5.go ++++ b/src/crypto/md5/md5.go +@@ -12,6 +12,7 @@ package md5 + + import ( + "crypto" ++ boring "crypto/internal/backend" + "crypto/internal/fips140only" + "errors" + "hash" +@@ -104,6 +105,9 @@ func consumeUint32(b []byte) ([]byte, uint32) { + // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal + // state of the hash. + func New() hash.Hash { ++ if boring.Enabled && boring.SupportsHash(crypto.MD5) { ++ return boring.NewMD5() ++ } + d := new(digest) + d.Reset() + return d +@@ -188,6 +192,12 @@ func (d *digest) checkSum() [Size]byte { + + // Sum returns the MD5 checksum of the data. + func Sum(data []byte) [Size]byte { ++ if boring.Enabled && boring.SupportsHash(crypto.MD5) { ++ if fips140only.Enabled { ++ panic("crypto/md5: use of MD5 is not allowed in FIPS 140-only mode") ++ } ++ return boring.MD5(data) ++ } + var d digest + d.Reset() + d.Write(data) +diff --git a/src/crypto/md5/md5_test.go b/src/crypto/md5/md5_test.go +index 437d9b9d4c0e0d..ee28c55f846e81 100644 +--- a/src/crypto/md5/md5_test.go ++++ b/src/crypto/md5/md5_test.go +@@ -6,12 +6,14 @@ package md5 + + import ( + "bytes" ++ boring "crypto/internal/backend" + "crypto/internal/cryptotest" + "crypto/rand" + "encoding" + "fmt" + "hash" + "io" ++ "strings" + "testing" + "unsafe" + ) +@@ -88,6 +90,11 @@ func TestGolden(t *testing.T) { + } + + func TestGoldenMarshal(t *testing.T) { ++ if boring.Enabled { ++ if _, ok := New().(encoding.BinaryMarshaler); !ok { ++ t.Skip("BinaryMarshaler not implemented") ++ } ++ } + for _, g := range golden { + h := New() + h2 := New() +@@ -96,6 +103,9 @@ func TestGoldenMarshal(t *testing.T) { + + state, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("could not marshal: %v", err) + continue + } +@@ -157,6 +167,9 @@ func TestLarge(t *testing.T) { + + // Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match. + func TestBlockGeneric(t *testing.T) { ++ if boring.Enabled { ++ t.Skip("digest is not used when boring.Enabled is set") ++ } + gen, asm := New().(*digest), New().(*digest) + buf := make([]byte, BlockSize*20) // arbitrary factor + rand.Read(buf) +@@ -204,10 +217,18 @@ func safeSum(h hash.Hash) (sum []byte, err error) { + } + + func TestLargeHashes(t *testing.T) { ++ if boring.Enabled { ++ if _, ok := New().(encoding.BinaryUnmarshaler); !ok { ++ t.Skip("BinaryUnmarshaler not implemented") ++ } ++ } + for i, test := range largeUnmarshalTests { + + h := New() + if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("test %d could not unmarshal: %v", i, err) + continue + } +diff --git a/src/crypto/pbkdf2/pbkdf2.go b/src/crypto/pbkdf2/pbkdf2.go +index 271d2b03312ef0..ff76299fbe4782 100644 +--- a/src/crypto/pbkdf2/pbkdf2.go ++++ b/src/crypto/pbkdf2/pbkdf2.go +@@ -11,6 +11,7 @@ + package pbkdf2 + + import ( ++ boring "crypto/internal/backend" + "crypto/internal/fips140/pbkdf2" + "crypto/internal/fips140hash" + "crypto/internal/fips140only" +@@ -47,5 +48,8 @@ func Key[Hash hash.Hash](h func() Hash, password string, salt []byte, iter, keyL + return nil, errors.New("crypto/pbkdf2: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode") + } + } ++ if boring.Enabled && boring.SupportsPBKDF2() { ++ return boring.PBKDF2([]byte(password), salt, iter, keyLength, fh) ++ } + 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 03980c7e54d3be..4968a666fad4e5 100644 +--- a/src/crypto/pbkdf2/pbkdf2_test.go ++++ b/src/crypto/pbkdf2/pbkdf2_test.go +@@ -6,7 +6,7 @@ package pbkdf2_test + + import ( + "bytes" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140" + "crypto/pbkdf2" + "crypto/sha1" +diff --git a/src/crypto/purego_test.go b/src/crypto/purego_test.go +index 62be347e0c6822..d284b5cf7814a6 100644 +--- a/src/crypto/purego_test.go ++++ b/src/crypto/purego_test.go +@@ -41,7 +41,7 @@ func TestPureGoTag(t *testing.T) { + } + + for _, pkgName := range pkgs { +- if strings.Contains(pkgName, "/boring") { ++ if strings.Contains(pkgName, "/boring") || strings.Contains(pkgName, "/internal/backend") || strings.Contains(pkgName, "tls/fipsonly") { + continue + } + +diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go +index 1ca16caa9563e6..3ef22b5ff8222b 100644 +--- a/src/crypto/rand/rand.go ++++ b/src/crypto/rand/rand.go +@@ -7,7 +7,7 @@ + package rand + + import ( +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140" + "crypto/internal/fips140/drbg" + "crypto/internal/sysrand" +diff --git a/src/crypto/rc4/rc4.go b/src/crypto/rc4/rc4.go +index 90943a0935befb..09ebdfd733e5d6 100644 +--- a/src/crypto/rc4/rc4.go ++++ b/src/crypto/rc4/rc4.go +@@ -10,6 +10,7 @@ + package rc4 + + import ( ++ boring "crypto/internal/backend" + "crypto/internal/fips140/alias" + "crypto/internal/fips140only" + "errors" +@@ -20,6 +21,8 @@ import ( + type Cipher struct { + s [256]uint32 + i, j uint8 ++ ++ boring *boring.RC4Cipher + } + + type KeySizeError int +@@ -38,6 +41,13 @@ func NewCipher(key []byte) (*Cipher, error) { + if k < 1 || k > 256 { + return nil, KeySizeError(k) + } ++ if boring.Enabled && boring.SupportsRC4() { ++ c, err := boring.NewRC4Cipher(key) ++ if err != nil { ++ return nil, err ++ } ++ return &Cipher{boring: c}, nil ++ } + var c Cipher + for i := 0; i < 256; i++ { + c.s[i] = uint32(i) +@@ -55,6 +65,10 @@ func NewCipher(key []byte) (*Cipher, error) { + // Deprecated: Reset can't guarantee that the key will be entirely removed from + // the process's memory. + func (c *Cipher) Reset() { ++ if boring.Enabled && boring.SupportsRC4() { ++ c.boring.Reset() ++ return ++ } + for i := range c.s { + c.s[i] = 0 + } +@@ -64,6 +78,10 @@ func (c *Cipher) Reset() { + // XORKeyStream sets dst to the result of XORing src with the key stream. + // Dst and src must overlap entirely or not at all. + func (c *Cipher) XORKeyStream(dst, src []byte) { ++ if boring.Enabled && boring.SupportsRC4() { ++ c.boring.XORKeyStream(dst, src) ++ return ++ } + if len(src) == 0 { + return + } +diff --git a/src/crypto/rsa/boring.go b/src/crypto/rsa/boring.go +index b9f9d3154f2589..d52faddef45549 100644 +--- a/src/crypto/rsa/boring.go ++++ b/src/crypto/rsa/boring.go +@@ -2,13 +2,13 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build goexperiment.systemcrypto + + package rsa + + import ( +- "crypto/internal/boring" +- "crypto/internal/boring/bbig" ++ boring "crypto/internal/backend" ++ "crypto/internal/backend/bbig" + "crypto/internal/boring/bcache" + "math/big" + ) +diff --git a/src/crypto/rsa/boring_test.go b/src/crypto/rsa/boring_test.go +index 838fcc1244bdbe..d89f732345e8a3 100644 +--- a/src/crypto/rsa/boring_test.go ++++ b/src/crypto/rsa/boring_test.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build goexperiment.systemcrypto + + // Note: Can run these tests against the non-BoringCrypto + // version of the code by using "CGO_ENABLED=0 go test". +diff --git a/src/crypto/rsa/fips.go b/src/crypto/rsa/fips.go +index 8373c125ae3096..cee523891d5897 100644 +--- a/src/crypto/rsa/fips.go ++++ b/src/crypto/rsa/fips.go +@@ -6,7 +6,7 @@ package rsa + + import ( + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/rsa" + "crypto/internal/fips140hash" + "crypto/internal/fips140only" +@@ -70,7 +70,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, + hash = opts.Hash + } + +- if boring.Enabled && rand == boring.RandReader { ++ if boring.Enabled && rand == boring.RandReader && boring.SupportsRSAKeyPrimes(len(priv.Primes)) && boring.SupportsHash(hash) { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err +@@ -133,7 +133,7 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts + return err + } + +- if boring.Enabled { ++ if boring.Enabled && boring.SupportsRSASaltLength(opts.saltLength()) && boring.SupportsHash(hash) { + bkey, err := boringPublicKey(pub) + if err != nil { + return err +@@ -250,7 +250,7 @@ func decryptOAEP(hash, mgfHash hash.Hash, priv *PrivateKey, ciphertext []byte, l + return nil, err + } + +- if boring.Enabled { ++ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { + k := priv.Size() + if len(ciphertext) > k || + k < hash.Size()*2+2 { +@@ -312,7 +312,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ + return nil, err + } + +- if boring.Enabled { ++ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err +diff --git a/src/crypto/rsa/notboring.go b/src/crypto/rsa/notboring.go +index 2abc0436405f8a..3e4d6f3eef61e6 100644 +--- a/src/crypto/rsa/notboring.go ++++ b/src/crypto/rsa/notboring.go +@@ -2,11 +2,11 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build !boringcrypto ++//go:build !goexperiment.systemcrypto + + package rsa + +-import "crypto/internal/boring" ++import boring "crypto/internal/backend" + + func boringPublicKey(*PublicKey) (*boring.PublicKeyRSA, error) { + panic("boringcrypto: not available") +diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go +index f1e4ef48a4fd1c..a179a4388e3ee5 100644 +--- a/src/crypto/rsa/pkcs1v15.go ++++ b/src/crypto/rsa/pkcs1v15.go +@@ -5,7 +5,7 @@ + package rsa + + import ( +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/rsa" + "crypto/internal/fips140only" + "crypto/internal/randutil" +@@ -104,7 +104,7 @@ func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]b + return nil, err + } + +- if boring.Enabled { ++ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err +@@ -203,7 +203,7 @@ func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, + return 0, nil, 0, err + } + +- if boring.Enabled { ++ if boring.Enabled && boring.SupportsRSAKeyPrimes(len(priv.Primes)) { + var bkey *boring.PrivateKeyRSA + bkey, err = boringPrivateKey(priv) + if err != nil { +diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go +index c65552cd93526a..910416abe842f5 100644 +--- a/src/crypto/rsa/pkcs1v15_test.go ++++ b/src/crypto/rsa/pkcs1v15_test.go +@@ -7,6 +7,7 @@ package rsa_test + import ( + "bytes" + "crypto" ++ boring "crypto/internal/backend" + "crypto/rand" + . "crypto/rsa" + "crypto/sha1" +@@ -235,6 +236,10 @@ func TestVerifyPKCS1v15(t *testing.T) { + } + + func TestOverlongMessagePKCS1v15(t *testing.T) { ++ if boring.Enabled { ++ // See for example https://github.com/golang-fips/openssl/pull/142. ++ t.Skip("Some backends do not return an error for overlong messages.") ++ } + t.Setenv("GODEBUG", "rsa1024min=0") + 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..f31d492d53cf96 100644 +--- a/src/crypto/rsa/pss_test.go ++++ b/src/crypto/rsa/pss_test.go +@@ -8,6 +8,7 @@ import ( + "bufio" + "compress/bzip2" + "crypto" ++ boring "crypto/internal/backend" + "crypto/internal/fips140" + "crypto/rand" + . "crypto/rsa" +@@ -180,6 +181,10 @@ func TestPSSSigning(t *testing.T) { + continue + } + ++ if boring.Enabled && test.good != test.fipsGood { ++ t.Skip("skipping test with different results when using different backends") ++ } ++ + opts.SaltLength = test.verifySaltLength + err = VerifyPSS(&rsaPrivateKey.PublicKey, hash, hashed, sig, &opts) + good := test.good +@@ -241,7 +246,9 @@ func fromHex(hexStr string) []byte { + + func TestInvalidPSSSaltLength(t *testing.T) { + t.Setenv("GODEBUG", "rsa1024min=0") +- key, err := GenerateKey(rand.Reader, 245) ++ // Most crypto backends don't support generating RSA keys with a bit size ++ // lower than 512, so we use 512 here. ++ key, err := GenerateKey(rand.Reader, 512) + if err != nil { + t.Fatal(err) + } +diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go +index 95bb4becd2ff8c..73991434dabaf1 100644 +--- a/src/crypto/rsa/rsa.go ++++ b/src/crypto/rsa/rsa.go +@@ -42,8 +42,8 @@ package rsa + + import ( + "crypto" +- "crypto/internal/boring" +- "crypto/internal/boring/bbig" ++ boring "crypto/internal/backend" ++ "crypto/internal/backend/bbig" + "crypto/internal/fips140/bigmod" + "crypto/internal/fips140/rsa" + "crypto/internal/fips140only" +diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go +index 73b0c3749eedb2..1a712a0e1c5d95 100644 +--- a/src/crypto/rsa/rsa_test.go ++++ b/src/crypto/rsa/rsa_test.go +@@ -8,7 +8,7 @@ import ( + "bufio" + "bytes" + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/cryptotest" + "crypto/rand" + . "crypto/rsa" +@@ -146,6 +146,11 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { + if priv.D.Cmp(priv.N) > 0 { + t.Errorf("private exponent too large") + } ++ if boring.Enabled && priv.N.BitLen() < 512 { ++ // Some crypto backends (e.g. CNG and OpenSSL with SymCrypt) don't support key sizes ++ // lower than 512 and intentionally fail rather than fall back to Go crypto. ++ t.Skip("skipping allocations test with BoringCrypto") ++ } + + msg := []byte("hi!") + enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg) +@@ -226,6 +231,11 @@ func testEverything(t *testing.T, priv *PrivateKey) { + if err := priv.Validate(); err != nil { + t.Errorf("Validate() failed: %s", err) + } ++ if boring.Enabled && priv.N.BitLen() < 512 { ++ // Some crypto backends (e.g. CNG and OpenSSL with SymCrypt) don't support key sizes ++ // lower than 512 and intentionally fail rather than fall back to Go crypto. ++ t.Skip("skipping allocations test with BoringCrypto") ++ } + + msg := []byte("test") + enc, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg) +@@ -853,6 +863,9 @@ func TestDecryptOAEP(t *testing.T) { + } + + func Test2DecryptOAEP(t *testing.T) { ++ if boring.Enabled { ++ t.Skip("Some crypto backends don't supports OAEPOptions.MGFHash.") ++ } + random := rand.Reader + + msg := []byte{0xed, 0x36, 0x90, 0x8d, 0xbe, 0xfc, 0x35, 0x40, 0x70, 0x4f, 0xf5, 0x9d, 0x6e, 0xc2, 0xeb, 0xf5, 0x27, 0xae, 0x65, 0xb0, 0x59, 0x29, 0x45, 0x25, 0x8c, 0xc1, 0x91, 0x22} +diff --git a/src/crypto/sha1/sha1.go b/src/crypto/sha1/sha1.go +index d2ffaac0aeb674..23d8ad44d0bd9a 100644 +--- a/src/crypto/sha1/sha1.go ++++ b/src/crypto/sha1/sha1.go +@@ -10,7 +10,7 @@ package sha1 + + import ( + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140only" + "errors" + "hash" +@@ -266,12 +266,12 @@ func (d *digest) constSum() [Size]byte { + + // Sum returns the SHA-1 checksum of the data. + func Sum(data []byte) [Size]byte { +- if boring.Enabled { +- return boring.SHA1(data) +- } + if fips140only.Enabled { + panic("crypto/sha1: use of SHA-1 is not allowed in FIPS 140-only mode") + } ++ if boring.Enabled { ++ return boring.SHA1(data) ++ } + var d digest + d.Reset() + d.Write(data) +diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go +index 9d707b7cde5c2d..8da08b3d860a85 100644 +--- a/src/crypto/sha1/sha1_test.go ++++ b/src/crypto/sha1/sha1_test.go +@@ -8,13 +8,14 @@ package sha1 + + import ( + "bytes" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/cryptotest" + "crypto/rand" + "encoding" + "fmt" + "hash" + "io" ++ "strings" + "testing" + ) + +@@ -97,6 +98,11 @@ func TestGolden(t *testing.T) { + } + + func TestGoldenMarshal(t *testing.T) { ++ if boring.Enabled { ++ if _, ok := New().(encoding.BinaryMarshaler); !ok { ++ t.Skip("BinaryMarshaler not implemented") ++ } ++ } + h := New() + h2 := New() + for _, g := range golden { +@@ -107,6 +113,9 @@ func TestGoldenMarshal(t *testing.T) { + + state, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("could not marshal: %v", err) + continue + } +@@ -210,10 +219,18 @@ func safeSum(h hash.Hash) (sum []byte, err error) { + } + + func TestLargeHashes(t *testing.T) { ++ if boring.Enabled { ++ if _, ok := New().(encoding.BinaryMarshaler); !ok { ++ t.Skip("BinaryMarshaler not implemented") ++ } ++ } + for i, test := range largeUnmarshalTests { + + h := New() + if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("test %d could not unmarshal: %v", i, err) + continue + } +diff --git a/src/crypto/sha256/sha256.go b/src/crypto/sha256/sha256.go +index 069938a22dbc5a..8d0e06b86f4359 100644 +--- a/src/crypto/sha256/sha256.go ++++ b/src/crypto/sha256/sha256.go +@@ -8,7 +8,7 @@ package sha256 + + import ( + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/sha256" + "hash" + ) +@@ -43,7 +43,7 @@ func New() hash.Hash { + // [encoding.BinaryUnmarshaler] to marshal and unmarshal the internal + // state of the hash. + func New224() hash.Hash { +- if boring.Enabled { ++ if boring.Enabled && boring.SupportsHash(crypto.SHA224) { + return boring.NewSHA224() + } + return sha256.New224() +@@ -63,7 +63,7 @@ func Sum256(data []byte) [Size]byte { + + // Sum224 returns the SHA224 checksum of the data. + func Sum224(data []byte) [Size224]byte { +- if boring.Enabled { ++ if boring.Enabled && boring.SupportsHash(crypto.SHA224) { + return boring.SHA224(data) + } + h := New224() +diff --git a/src/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go +index e1af9640e25547..c4f142c1430285 100644 +--- a/src/crypto/sha256/sha256_test.go ++++ b/src/crypto/sha256/sha256_test.go +@@ -8,11 +8,13 @@ package sha256 + + import ( + "bytes" ++ boring "crypto/internal/backend" + "crypto/internal/cryptotest" + "encoding" + "fmt" + "hash" + "io" ++ "strings" + "testing" + ) + +@@ -155,6 +157,11 @@ func testGoldenMarshal(t *testing.T) { + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { ++ if boring.Enabled { ++ if _, ok := tt.newHash().(encoding.BinaryMarshaler); !ok { ++ t.Skip("BinaryMarshaler not implemented") ++ } ++ } + for _, g := range tt.gold { + h := tt.newHash() + h2 := tt.newHash() +@@ -163,6 +170,9 @@ func testGoldenMarshal(t *testing.T) { + + state, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("could not marshal: %v", err) + continue + } +@@ -204,8 +214,19 @@ func TestMarshalTypeMismatch(t *testing.T) { + h1 := New() + h2 := New224() + ++ if boring.Enabled { ++ _, ok1 := h1.(encoding.BinaryMarshaler) ++ _, ok2 := h2.(encoding.BinaryUnmarshaler) ++ if !ok1 || !ok2 { ++ t.Skip("BinaryMarshaler not implemented") ++ } ++ } ++ + state1, err := h1.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("could not marshal: %v", err) + } + +@@ -275,10 +296,18 @@ func safeSum(h hash.Hash) (sum []byte, err error) { + return h.Sum(nil), nil + } + func TestLargeHashes(t *testing.T) { ++ if boring.Enabled { ++ if _, ok := New().(encoding.BinaryUnmarshaler); !ok { ++ t.Skip("BinaryUnmarshaler not implemented") ++ } ++ } + for i, test := range largeUnmarshalTests { + + h := New() + if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("test %d could not unmarshal: %v", i, err) + continue + } +diff --git a/src/crypto/sha512/sha512.go b/src/crypto/sha512/sha512.go +index 1435eac1f5b5dc..17e8501154762a 100644 +--- a/src/crypto/sha512/sha512.go ++++ b/src/crypto/sha512/sha512.go +@@ -12,7 +12,7 @@ package sha512 + + import ( + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/sha512" + "hash" + ) +diff --git a/src/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go +index 1fe9d132bb186d..97b7da8c2d3d88 100644 +--- a/src/crypto/sha512/sha512_test.go ++++ b/src/crypto/sha512/sha512_test.go +@@ -8,12 +8,14 @@ package sha512 + + import ( + "bytes" ++ boring "crypto/internal/backend" + "crypto/internal/cryptotest" + "encoding" + "encoding/hex" + "fmt" + "hash" + "io" ++ "strings" + "testing" + ) + +@@ -744,6 +746,11 @@ func testGoldenMarshal(t *testing.T) { + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + for _, test := range tt.golden { ++ if boring.Enabled { ++ if _, ok := tt.newHash().(encoding.BinaryMarshaler); !ok { ++ t.Skip("BinaryMarshaler not implemented") ++ } ++ } + h := tt.newHash() + h2 := tt.newHash() + +@@ -751,6 +758,9 @@ func testGoldenMarshal(t *testing.T) { + + state, err := h.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("could not marshal: %v", err) + return + } +@@ -805,8 +815,19 @@ func TestMarshalMismatch(t *testing.T) { + h1 := fn1() + h2 := fn2() + ++ if boring.Enabled { ++ _, ok1 := h1.(encoding.BinaryMarshaler) ++ _, ok2 := h2.(encoding.BinaryUnmarshaler) ++ if !ok1 || !ok2 { ++ t.Skip("BinaryMarshaler not implemented") ++ } ++ } ++ + state, err := h1.(encoding.BinaryMarshaler).MarshalBinary() + if err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("i=%d: could not marshal: %v", i, err) + continue + } +@@ -880,10 +901,18 @@ func safeSum(h hash.Hash) (sum []byte, err error) { + } + + func TestLargeHashes(t *testing.T) { ++ if boring.Enabled { ++ if _, ok := New().(encoding.BinaryUnmarshaler); !ok { ++ t.Skip("BinaryUnmarshaler not implemented") ++ } ++ } + for i, test := range largeUnmarshalTests { + + h := New() + if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Errorf("test %d could not unmarshal: %v", i, err) + continue + } +diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go +index 01d65688284f97..d8a26c24024348 100644 +--- a/src/crypto/tls/cipher_suites.go ++++ b/src/crypto/tls/cipher_suites.go +@@ -10,7 +10,7 @@ import ( + "crypto/cipher" + "crypto/des" + "crypto/hmac" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + fipsaes "crypto/internal/fips140/aes" + "crypto/internal/fips140/aes/gcm" + "crypto/rc4" +diff --git a/src/crypto/tls/fipsonly/fipsonly.go b/src/crypto/tls/fipsonly/fipsonly.go +index e702f44e986746..e506a0d8841237 100644 +--- a/src/crypto/tls/fipsonly/fipsonly.go ++++ b/src/crypto/tls/fipsonly/fipsonly.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build goexperiment.systemcrypto + + // Package fipsonly restricts all TLS configuration to FIPS-approved settings. + // +diff --git a/src/crypto/tls/fipsonly/fipsonly_test.go b/src/crypto/tls/fipsonly/fipsonly_test.go +index 027bc22c33c921..eba08da985f832 100644 +--- a/src/crypto/tls/fipsonly/fipsonly_test.go ++++ b/src/crypto/tls/fipsonly/fipsonly_test.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build goexperiment.systemcrypto + + package fipsonly + +diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go +index 38bd417a0dca72..8c1ae3c7ec5485 100644 +--- a/src/crypto/tls/handshake_client.go ++++ b/src/crypto/tls/handshake_client.go +@@ -11,11 +11,11 @@ import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/internal/fips140/mlkem" +- "crypto/internal/fips140/tls13" + "crypto/internal/hpke" + "crypto/rsa" + "crypto/subtle" + "crypto/tls/internal/fips140tls" ++ "crypto/tls/internal/tls13" + "crypto/x509" + "errors" + "fmt" +@@ -549,7 +549,15 @@ func (c *Conn) pickTLSVersion(serverHello *serverHelloMsg) error { + + // Does the handshake, either a full one or resumes old session. Requires hs.c, + // hs.hello, hs.serverHello, and, optionally, hs.session to be set. +-func (hs *clientHandshakeState) handshake() error { ++func (hs *clientHandshakeState) handshake() (err error) { ++ defer func() { ++ if err == nil { ++ err = recoverFromBoringPRFError() ++ if err != nil { ++ hs.c.sendAlert(alertInternalError) ++ } ++ } ++ }() + c := hs.c + + isResume, err := hs.processServerHello() +diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go +index c0396e75796add..2c00e119cb66e4 100644 +--- a/src/crypto/tls/handshake_client_tls13.go ++++ b/src/crypto/tls/handshake_client_tls13.go +@@ -8,12 +8,12 @@ import ( + "bytes" + "context" + "crypto" ++ "crypto/hkdf" + "crypto/hmac" +- "crypto/internal/fips140/hkdf" + "crypto/internal/fips140/mlkem" +- "crypto/internal/fips140/tls13" + "crypto/rsa" + "crypto/subtle" ++ "crypto/tls/internal/tls13" + "errors" + "hash" + "slices" +@@ -90,8 +90,12 @@ func (hs *clientHandshakeStateTLS13) handshake() error { + confTranscript.Write(hs.serverHello.original[:30]) + confTranscript.Write(make([]byte, 8)) + confTranscript.Write(hs.serverHello.original[38:]) ++ secret, err := hkdf.Extract(hs.suite.hash.New, hs.echContext.innerHello.random, nil) ++ if err != nil { ++ return err ++ } + acceptConfirmation := tls13.ExpandLabel(hs.suite.hash.New, +- hkdf.Extract(hs.suite.hash.New, hs.echContext.innerHello.random, nil), ++ secret, + "ech accept confirmation", + confTranscript.Sum(nil), + 8, +@@ -264,8 +268,12 @@ func (hs *clientHandshakeStateTLS13) processHelloRetryRequest() error { + copy(hrrHello, hs.serverHello.original) + hrrHello = bytes.Replace(hrrHello, hs.serverHello.encryptedClientHello, make([]byte, 8), 1) + confTranscript.Write(hrrHello) ++ secret, err := hkdf.Extract(hs.suite.hash.New, hs.echContext.innerHello.random, nil) ++ if err != nil { ++ return err ++ } + acceptConfirmation := tls13.ExpandLabel(hs.suite.hash.New, +- hkdf.Extract(hs.suite.hash.New, hs.echContext.innerHello.random, nil), ++ secret, + "hrr ech accept confirmation", + confTranscript.Sum(nil), + 8, +diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go +index 7c75977ad3ffb2..b9db95ca7b9d5a 100644 +--- a/src/crypto/tls/handshake_server.go ++++ b/src/crypto/tls/handshake_server.go +@@ -64,7 +64,15 @@ func (c *Conn) serverHandshake(ctx context.Context) error { + return hs.handshake() + } + +-func (hs *serverHandshakeState) handshake() error { ++func (hs *serverHandshakeState) handshake() (err error) { ++ defer func() { ++ if err == nil { ++ err = recoverFromBoringPRFError() ++ if err != nil { ++ hs.c.sendAlert(alertInternalError) ++ } ++ } ++ }() + c := hs.c + + 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 76fff6974e7403..3ef8b56e5c7898 100644 +--- a/src/crypto/tls/handshake_server_tls13.go ++++ b/src/crypto/tls/handshake_server_tls13.go +@@ -8,13 +8,14 @@ import ( + "bytes" + "context" + "crypto" ++ "crypto/hkdf" + "crypto/hmac" +- "crypto/internal/fips140/hkdf" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/mlkem" +- "crypto/internal/fips140/tls13" + "crypto/internal/hpke" + "crypto/rsa" + "crypto/tls/internal/fips140tls" ++ "crypto/tls/internal/tls13" + "errors" + "hash" + "internal/byteorder" +@@ -470,15 +471,19 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error { + // interfaces implemented by standard library hashes to clone the state of in + // to a new instance of h. It returns nil if the operation fails. + func cloneHash(in hash.Hash, h crypto.Hash) hash.Hash { ++ if boring.Enabled { ++ // CNG and OpenSSL with SymCrypt hash functions do not implement the ++ // encoding.BinaryMarshaler interface, but they do implement the Clone method. ++ if cloner, ok := in.(interface{ Clone() hash.Hash }); ok { ++ return cloner.Clone() ++ } ++ } + // Recreate the interface to avoid importing encoding. + type binaryMarshaler interface { + MarshalBinary() (data []byte, err error) + UnmarshalBinary(data []byte) error + } + marshaler, ok := in.(binaryMarshaler) +- if !ok { +- return nil +- } + state, err := marshaler.MarshalBinary() + if err != nil { + return nil +@@ -572,8 +577,12 @@ func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) + if err := transcriptMsg(helloRetryRequest, confTranscript); err != nil { + return nil, err + } ++ secret, err := hkdf.Extract(hs.suite.hash.New, hs.clientHello.random, nil) ++ if err != nil { ++ return nil, err ++ } + acceptConfirmation := tls13.ExpandLabel(hs.suite.hash.New, +- hkdf.Extract(hs.suite.hash.New, hs.clientHello.random, nil), ++ secret, + "hrr ech accept confirmation", + confTranscript.Sum(nil), + 8, +@@ -734,9 +743,13 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error { + if err := transcriptMsg(hs.hello, echTranscript); err != nil { + return err + } ++ secret, err := hkdf.Extract(hs.suite.hash.New, hs.clientHello.random, nil) ++ if err != nil { ++ return err ++ } + // compute the acceptance message + acceptConfirmation := tls13.ExpandLabel(hs.suite.hash.New, +- hkdf.Extract(hs.suite.hash.New, hs.clientHello.random, nil), ++ secret, + "ech accept confirmation", + echTranscript.Sum(nil), + 8, +diff --git a/src/crypto/tls/internal/fips140tls/fipstls.go b/src/crypto/tls/internal/fips140tls/fipstls.go +index 24d78d60cf5b64..a6bfd3f17c1911 100644 +--- a/src/crypto/tls/internal/fips140tls/fipstls.go ++++ b/src/crypto/tls/internal/fips140tls/fipstls.go +@@ -6,6 +6,7 @@ + package fips140tls + + import ( ++ bfips140 "crypto/internal/backend/fips140" + "crypto/internal/fips140" + "sync/atomic" + ) +@@ -13,7 +14,7 @@ import ( + var required atomic.Bool + + func init() { +- if fips140.Enabled { ++ if fips140.Enabled || bfips140.Enabled() { + Force() + } + } +diff --git a/src/crypto/tls/internal/tls13/doc.go b/src/crypto/tls/internal/tls13/doc.go +new file mode 100644 +index 00000000000000..1adf3098356307 +--- /dev/null ++++ b/src/crypto/tls/internal/tls13/doc.go +@@ -0,0 +1,18 @@ ++// 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. ++ ++/* ++Microsoft Go only package. ++ ++TLS 1.3 Key Schedule is normally not part of the FIPS boundary, but upstream Go ++decided to include it in the FIPS boundary to facilitate the FIPS 140-3 certification ++process. ++ ++The problem is that crypto/internal/fips140/tls13 uses crypto/internal/fips140/hkdf, ++which can't be patched to use other backends. ++ ++To solve this problem, we created this package, which is a direct copy of ++crypto/internal/fips140/tls13, but uses crypto/hkdf instead of crypto/internal/fips140/hkdf. ++*/ ++package tls13 +diff --git a/src/crypto/tls/internal/tls13/tls13.go b/src/crypto/tls/internal/tls13/tls13.go +new file mode 100644 +index 00000000000000..573896b9c1e6a8 +--- /dev/null ++++ b/src/crypto/tls/internal/tls13/tls13.go +@@ -0,0 +1,182 @@ ++// Copyright 2024 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++// Package tls13 implements the TLS 1.3 Key Schedule as specified in RFC 8446, ++// Section 7.1 and allowed by FIPS 140-3 IG 2.4.B Resolution 7. ++package tls13 ++ ++import ( ++ "crypto/hkdf" ++ "hash" ++ "internal/byteorder" ++) ++ ++// We don't set the service indicator in this package but we delegate that to ++// the underlying functions because the TLS 1.3 KDF does not have a standard of ++// its own. ++ ++// ExpandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1. ++func ExpandLabel[H hash.Hash](hash func() H, secret []byte, label string, context []byte, length int) []byte { ++ if len("tls13 ")+len(label) > 255 || len(context) > 255 { ++ // It should be impossible for this to panic: labels are fixed strings, ++ // and context is either a fixed-length computed hash, or parsed from a ++ // field which has the same length limitation. ++ // ++ // Another reasonable approach might be to return a randomized slice if ++ // we encounter an error, which would break the connection, but avoid ++ // panicking. This would perhaps be safer but significantly more ++ // confusing to users. ++ panic("tls13: label or context too long") ++ } ++ hkdfLabel := make([]byte, 0, 2+1+len("tls13 ")+len(label)+1+len(context)) ++ hkdfLabel = byteorder.BEAppendUint16(hkdfLabel, uint16(length)) ++ hkdfLabel = append(hkdfLabel, byte(len("tls13 ")+len(label))) ++ hkdfLabel = append(hkdfLabel, "tls13 "...) ++ hkdfLabel = append(hkdfLabel, label...) ++ hkdfLabel = append(hkdfLabel, byte(len(context))) ++ hkdfLabel = append(hkdfLabel, context...) ++ key, err := hkdf.Expand(hash, secret, string(hkdfLabel), length) ++ if err != nil { ++ panic(err) ++ } ++ return key ++} ++ ++func extract[H hash.Hash](hash func() H, newSecret, currentSecret []byte) []byte { ++ if newSecret == nil { ++ newSecret = make([]byte, hash().Size()) ++ } ++ prk, err := hkdf.Extract(hash, newSecret, currentSecret) ++ if err != nil { ++ panic(err) ++ } ++ return prk ++} ++ ++func deriveSecret[H hash.Hash](hash func() H, secret []byte, label string, transcript hash.Hash) []byte { ++ if transcript == nil { ++ transcript = hash() ++ } ++ return ExpandLabel(hash, secret, label, transcript.Sum(nil), transcript.Size()) ++} ++ ++const ( ++ resumptionBinderLabel = "res binder" ++ clientEarlyTrafficLabel = "c e traffic" ++ clientHandshakeTrafficLabel = "c hs traffic" ++ serverHandshakeTrafficLabel = "s hs traffic" ++ clientApplicationTrafficLabel = "c ap traffic" ++ serverApplicationTrafficLabel = "s ap traffic" ++ earlyExporterLabel = "e exp master" ++ exporterLabel = "exp master" ++ resumptionLabel = "res master" ++) ++ ++type EarlySecret struct { ++ secret []byte ++ hash func() hash.Hash ++} ++ ++func NewEarlySecret[H hash.Hash](h func() H, psk []byte) *EarlySecret { ++ return &EarlySecret{ ++ secret: extract(h, psk, nil), ++ hash: func() hash.Hash { return h() }, ++ } ++} ++ ++func (s *EarlySecret) ResumptionBinderKey() []byte { ++ return deriveSecret(s.hash, s.secret, resumptionBinderLabel, nil) ++} ++ ++// ClientEarlyTrafficSecret derives the client_early_traffic_secret from the ++// early secret and the transcript up to the ClientHello. ++func (s *EarlySecret) ClientEarlyTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, clientEarlyTrafficLabel, transcript) ++} ++ ++type HandshakeSecret struct { ++ secret []byte ++ hash func() hash.Hash ++} ++ ++func (s *EarlySecret) HandshakeSecret(sharedSecret []byte) *HandshakeSecret { ++ derived := deriveSecret(s.hash, s.secret, "derived", nil) ++ return &HandshakeSecret{ ++ secret: extract(s.hash, sharedSecret, derived), ++ hash: s.hash, ++ } ++} ++ ++// ClientHandshakeTrafficSecret derives the client_handshake_traffic_secret from ++// the handshake secret and the transcript up to the ServerHello. ++func (s *HandshakeSecret) ClientHandshakeTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, clientHandshakeTrafficLabel, transcript) ++} ++ ++// ServerHandshakeTrafficSecret derives the server_handshake_traffic_secret from ++// the handshake secret and the transcript up to the ServerHello. ++func (s *HandshakeSecret) ServerHandshakeTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, serverHandshakeTrafficLabel, transcript) ++} ++ ++type MasterSecret struct { ++ secret []byte ++ hash func() hash.Hash ++} ++ ++func (s *HandshakeSecret) MasterSecret() *MasterSecret { ++ derived := deriveSecret(s.hash, s.secret, "derived", nil) ++ return &MasterSecret{ ++ secret: extract(s.hash, nil, derived), ++ hash: s.hash, ++ } ++} ++ ++// ClientApplicationTrafficSecret derives the client_application_traffic_secret_0 ++// from the master secret and the transcript up to the server Finished. ++func (s *MasterSecret) ClientApplicationTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, clientApplicationTrafficLabel, transcript) ++} ++ ++// ServerApplicationTrafficSecret derives the server_application_traffic_secret_0 ++// from the master secret and the transcript up to the server Finished. ++func (s *MasterSecret) ServerApplicationTrafficSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, serverApplicationTrafficLabel, transcript) ++} ++ ++// ResumptionMasterSecret derives the resumption_master_secret from the master secret ++// and the transcript up to the client Finished. ++func (s *MasterSecret) ResumptionMasterSecret(transcript hash.Hash) []byte { ++ return deriveSecret(s.hash, s.secret, resumptionLabel, transcript) ++} ++ ++type ExporterMasterSecret struct { ++ secret []byte ++ hash func() hash.Hash ++} ++ ++// ExporterMasterSecret derives the exporter_master_secret from the master secret ++// and the transcript up to the server Finished. ++func (s *MasterSecret) ExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { ++ return &ExporterMasterSecret{ ++ secret: deriveSecret(s.hash, s.secret, exporterLabel, transcript), ++ hash: s.hash, ++ } ++} ++ ++// EarlyExporterMasterSecret derives the exporter_master_secret from the early secret ++// and the transcript up to the ClientHello. ++func (s *EarlySecret) EarlyExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { ++ return &ExporterMasterSecret{ ++ secret: deriveSecret(s.hash, s.secret, earlyExporterLabel, transcript), ++ hash: s.hash, ++ } ++} ++ ++func (s *ExporterMasterSecret) Exporter(label string, context []byte, length int) []byte { ++ secret := deriveSecret(s.hash, s.secret, label, nil) ++ h := s.hash() ++ h.Write(context) ++ return ExpandLabel(s.hash, secret, "exporter", h.Sum(nil), length) ++} +diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go +index 38d6d3f7be1673..b236ae44a34030 100644 +--- a/src/crypto/tls/key_schedule.go ++++ b/src/crypto/tls/key_schedule.go +@@ -8,7 +8,7 @@ import ( + "crypto/ecdh" + "crypto/hmac" + "crypto/internal/fips140/mlkem" +- "crypto/internal/fips140/tls13" ++ "crypto/tls/internal/tls13" + "errors" + "hash" + "io" +diff --git a/src/crypto/tls/prf.go b/src/crypto/tls/prf.go +index e7369542a73270..ff52175e4ac636 100644 +--- a/src/crypto/tls/prf.go ++++ b/src/crypto/tls/prf.go +@@ -7,6 +7,7 @@ package tls + import ( + "crypto" + "crypto/hmac" ++ boring "crypto/internal/backend" + "crypto/internal/fips140/tls12" + "crypto/md5" + "crypto/sha1" +@@ -47,9 +48,42 @@ func pHash(result, secret, seed []byte, hash func() hash.Hash) { + } + } + ++type boringPRFError struct { ++ err error ++} ++ ++func (e *boringPRFError) Error() string { ++ return e.err.Error() ++} ++ ++// recoverFromBoringPRFError recovers from a panic caused by the boring backend. ++// It returns the error if it was a boringPRFError, or panics if the panic was ++// caused by something else. ++func recoverFromBoringPRFError() error { ++ if p := recover(); p != nil { ++ if err, ok := p.(boringPRFError); ok { ++ // Could happen, for example, if the seed is too large. The Go implementation doesn't limit the seed size, ++ // as RFC 5705 doesn't specify a limit, but stock OpenSSL restrict it to 1024 and CNG to 256. ++ return err.err ++ } ++ panic(p) ++ } ++ return nil ++} ++ ++func panicBoringPRFError(err error) { ++ panic(boringPRFError{err}) ++} ++ + // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. + func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { + result := make([]byte, keyLen) ++ if boring.Enabled && boring.SupportsTLS1PRF() { ++ if err := boring.TLS1PRF(result, secret, []byte(label), seed, nil); err != nil { ++ panicBoringPRFError(fmt.Errorf("crypto/tls: prf10: %v", err)) ++ } ++ return result ++ } + hashSHA1 := sha1.New + hashMD5 := md5.New + +@@ -72,6 +106,13 @@ func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { + // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. + func prf12(hashFunc func() hash.Hash) prfFunc { + return func(secret []byte, label string, seed []byte, keyLen int) []byte { ++ if boring.Enabled && boring.SupportsTLS1PRF() { ++ result := make([]byte, keyLen) ++ if err := boring.TLS1PRF(result, secret, []byte(label), seed, hashFunc); err != nil { ++ panicBoringPRFError(fmt.Errorf("crypto/tls: prf12: %v", err)) ++ } ++ return result ++ } + return tls12.PRF(hashFunc, secret, label, seed, keyLen) + } + } +diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go +index 8d175079a8c793..c2846667df81de 100644 +--- a/src/go/build/deps_test.go ++++ b/src/go/build/deps_test.go +@@ -537,6 +537,7 @@ var depsRules = ` + crypto/pbkdf2, + crypto/ecdh, + crypto/mlkem ++ < crypto/tls/internal/tls13 + < CRYPTO; + + CGO, fmt, net !< CRYPTO; +@@ -561,7 +562,7 @@ var depsRules = ` + + # TLS, Prince of Dependencies. + +- FIPS, sync/atomic < crypto/tls/internal/fips140tls; ++ FIPS, sync/atomic, crypto/internal/backend/fips140 < crypto/tls/internal/fips140tls; + + crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly; + +diff --git a/src/hash/boring_test.go b/src/hash/boring_test.go +new file mode 100644 +index 00000000000000..52748c44698076 +--- /dev/null ++++ b/src/hash/boring_test.go +@@ -0,0 +1,9 @@ ++// 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. ++ ++//go:build goexperiment.systemcrypto ++ ++package hash_test ++ ++const boringEnabled = true +diff --git a/src/hash/example_test.go b/src/hash/example_test.go +index f07b9aaa2c4898..b380537215634d 100644 +--- a/src/hash/example_test.go ++++ b/src/hash/example_test.go +@@ -2,6 +2,8 @@ + // 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 hash_test + + import ( +diff --git a/src/hash/marshal_test.go b/src/hash/marshal_test.go +index 3091f7a67acede..23736034d5c352 100644 +--- a/src/hash/marshal_test.go ++++ b/src/hash/marshal_test.go +@@ -21,6 +21,7 @@ import ( + "hash/crc32" + "hash/crc64" + "hash/fnv" ++ "strings" + "testing" + ) + +@@ -65,6 +66,11 @@ func TestMarshalHash(t *testing.T) { + } + + h := tt.new() ++ if boringEnabled { ++ if _, ok := h.(encoding.BinaryMarshaler); !ok { ++ t.Skip("BinaryMarshaler not implemented") ++ } ++ } + h.Write(buf[:256]) + sum := h.Sum(nil) + +@@ -80,6 +86,9 @@ func TestMarshalHash(t *testing.T) { + } + enc, err := h2m.MarshalBinary() + if err != nil { ++ if strings.Contains(err.Error(), "hash state is not marshallable") { ++ t.Skip("BinaryMarshaler not supported") ++ } + t.Fatalf("MarshalBinary: %v", err) + } + if !bytes.Equal(enc, tt.golden) { +diff --git a/src/hash/notboring_test.go b/src/hash/notboring_test.go +new file mode 100644 +index 00000000000000..11dc691600b110 +--- /dev/null ++++ b/src/hash/notboring_test.go +@@ -0,0 +1,9 @@ ++// 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. ++ ++//go:build !goexperiment.systemcrypto ++ ++package hash_test ++ ++const boringEnabled = false +diff --git a/src/net/smtp/smtp_test.go b/src/net/smtp/smtp_test.go +index 389eda9ad54b99..110d60beb0e70c 100644 +--- a/src/net/smtp/smtp_test.go ++++ b/src/net/smtp/smtp_test.go +@@ -1136,40 +1136,60 @@ func sendMail(hostPort string) error { + + // localhostCert is a PEM-encoded TLS cert generated from src/crypto/tls: + // +-// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com \ ++// Use a 2048-bits RSA key to make it FIPS-compliant. ++// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com \ + // --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h + var localhostCert = []byte(` + -----BEGIN CERTIFICATE----- +-MIICFDCCAX2gAwIBAgIRAK0xjnaPuNDSreeXb+z+0u4wDQYJKoZIhvcNAQELBQAw +-EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2 +-MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw +-gYkCgYEA0nFbQQuOWsjbGtejcpWz153OlziZM4bVjJ9jYruNw5n2Ry6uYQAffhqa +-JOInCmmcVe2siJglsyH9aRh6vKiobBbIUXXUU1ABd56ebAzlt0LobLlx7pZEMy30 +-LqIi9E6zmL3YvdGzpYlkFRnRrqwEtWYbGBf3znO250S56CCWH2UCAwEAAaNoMGYw +-DgYDVR0PAQH/BAQDAgKkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQF +-MAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAAAAAAAAAA +-AAAAAAEwDQYJKoZIhvcNAQELBQADgYEAbZtDS2dVuBYvb+MnolWnCNqvw1w5Gtgi +-NmvQQPOMgM3m+oQSCPRTNGSg25e1Qbo7bgQDv8ZTnq8FgOJ/rbkyERw2JckkHpD4 +-n4qcK27WkEDBtQFlPihIM8hLIuzWoi/9wygiElTy/tVL3y7fGCvY2/k1KBthtZGF +-tN8URjVmyEo= ++MIIDOTCCAiGgAwIBAgIQKhWw7zkzXjX78HaPlVbNrjANBgkqhkiG9w0BAQsFADAS ++MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw ++MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A ++MIIBCgKCAQEAy1EYLA8IFvZyUPY+uI7KToneaQPvIzQiOeWlDnFnoanw6h3KpoVc +++yNbinK41WfXoSN/1kJ9gmGiFhJTPZ4rQ7DJsD7ethcpuz4uIimdWPohcBzwgbx4 ++wjhUgfUsCO6m76fFqrhbkHMDiS2iUjg2gyMVQCrqi8EuBW16yFQdJqPU04p+2rYw ++eJ9lzdeSLR4yvx7p1JS8sS4DbSyrAUaJ9J1sH/gu0nSHNMo7WtIu9K8JmPeYR4X5 ++5KLURBU9PmvoGW+5ss/xS6SnacHAD9FebNPQqGB/soBA9gdJIN+5KW0xcE38Zz5Q ++wAAUiU+VlWuZmge0sI8Ix8uIPIvGQSKN0wIDAQABo4GIMIGFMA4GA1UdDwEB/wQE ++AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud ++DgQWBBRNMP9Cr0yrXpMpsgEtDr8FPmUEazAuBgNVHREEJzAlggtleGFtcGxlLmNv ++bYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAQEAF0/z ++KEnZrAsz4ov4fEvKY42EbKPm8s0pklPLmKVIh/iS7jTxxxvgDtOToiJ6IXY8Cfb3 ++nG1i78YakoVPUL5Cfh5LKDefMoefk6575ur2+gSdzgNmKUnlVfOMfpflia/ugATZ ++5ORhpmKRKWzwXQ67S5XeVlZAehTsywQstsDu8WEVoSUnRSk1jZsCThOQfdlpox+K ++71rGPSTxB9yCHMzZsk4xyZlGLaC0vDSJ+Zb5gWvAcvkSnpREvmc3/9TaW/lbUed6 ++uhO17lARcUhPCzkR5wAZCo/PihHMSXL8cqT4QdIux75OBxB/3EgLHL7KQw28A50g ++DogldK8zx1ZADmupUA== + -----END CERTIFICATE-----`) + + // localhostKey is the private key for localhostCert. + var localhostKey = []byte(testingKey(` + -----BEGIN RSA TESTING KEY----- +-MIICXgIBAAKBgQDScVtBC45ayNsa16NylbPXnc6XOJkzhtWMn2Niu43DmfZHLq5h +-AB9+Gpok4icKaZxV7ayImCWzIf1pGHq8qKhsFshRddRTUAF3np5sDOW3QuhsuXHu +-lkQzLfQuoiL0TrOYvdi90bOliWQVGdGurAS1ZhsYF/fOc7bnRLnoIJYfZQIDAQAB +-AoGBAMst7OgpKyFV6c3JwyI/jWqxDySL3caU+RuTTBaodKAUx2ZEmNJIlx9eudLA +-kucHvoxsM/eRxlxkhdFxdBcwU6J+zqooTnhu/FE3jhrT1lPrbhfGhyKnUrB0KKMM +-VY3IQZyiehpxaeXAwoAou6TbWoTpl9t8ImAqAMY8hlULCUqlAkEA+9+Ry5FSYK/m +-542LujIcCaIGoG1/Te6Sxr3hsPagKC2rH20rDLqXwEedSFOpSS0vpzlPAzy/6Rbb +-PHTJUhNdwwJBANXkA+TkMdbJI5do9/mn//U0LfrCR9NkcoYohxfKz8JuhgRQxzF2 +-6jpo3q7CdTuuRixLWVfeJzcrAyNrVcBq87cCQFkTCtOMNC7fZnCTPUv+9q1tcJyB +-vNjJu3yvoEZeIeuzouX9TJE21/33FaeDdsXbRhQEj23cqR38qFHsF1qAYNMCQQDP +-QXLEiJoClkR2orAmqjPLVhR3t2oB3INcnEjLNSq8LHyQEfXyaFfu4U9l5+fRPL2i +-jiC0k/9L5dHUsF0XZothAkEA23ddgRs+Id/HxtojqqUT27B8MT/IGNrYsp4DvS/c +-qgkeluku4GjxRlDMBuXk94xOBEinUs+p/hwP1Alll80Tpg== ++MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLURgsDwgW9nJQ ++9j64jspOid5pA+8jNCI55aUOcWehqfDqHcqmhVz7I1uKcrjVZ9ehI3/WQn2CYaIW ++ElM9nitDsMmwPt62Fym7Pi4iKZ1Y+iFwHPCBvHjCOFSB9SwI7qbvp8WquFuQcwOJ ++LaJSODaDIxVAKuqLwS4FbXrIVB0mo9TTin7atjB4n2XN15ItHjK/HunUlLyxLgNt ++LKsBRon0nWwf+C7SdIc0yjta0i70rwmY95hHhfnkotREFT0+a+gZb7myz/FLpKdp ++wcAP0V5s09CoYH+ygED2B0kg37kpbTFwTfxnPlDAABSJT5WVa5maB7SwjwjHy4g8 ++i8ZBIo3TAgMBAAECggEAc7dv/oN/ozIY1iOQhxId6p1lTHfEv1CIulMNoi7BQK2s ++RFM4Z5Y32WfCTgYFVNCJVVkTBStKq85Npio/3i4Libcw03K05wY/5iX5s8/jkiSq ++q1iNOgm+4SuWTXDw4xSRRo1CX2wWERykwoqKfCkqPXDWQ3Mpkukb/FLXMvVMshRA ++9v9L6MyrCnsFHl8q2J6hcC+RQJ0pb5I4NF6KhMxABWxxxlDO0zYLA0wfhEn8nj/l ++J37QLHmsA7pzxo+NqDTPgpfBuuTbRVGMkC+fPCXYinbubBeURFO2j2yBlseK+Vbd ++sEffiAnPr4ocCz0k0tHAMMY7hKHup2HWuJGFu0IhAQKBgQDkKFEEcYWNx5Ybl1LV ++qr2qIYofpFL+Gu5MWSZxzZbE8u9v0tTsp8SRhXkgjeHY6qjBUBnLgklOKwSigQAm ++j9de44cXjnUIArzeAHsH3fzpYrLfsvBla6wQyr34D0chVCZ0cX/s/zXkSN4PcEkA ++GGfKAENrGskDyc4uq1sIactu8wKBgQDkIL/XT7ysvsaxA+SfIs2CHgb8GNKgtoI1 ++QyR0+MfeJGCLwI9qcLbVzXda34qrzQw3YLIm2VHqhzJ4zb0gnyJ4adPZYwpLTgiU ++jVksBVIwBTfbxYvF2+07poCSobCFKLGQnAujhDDIGDAUKQXQmFcqUNWw0QHfQzkS ++xs36H27doQKBgQCjM8+YLRgKbc0LGXhwTHz1GJ6zuZiAGYWB6XddimEhqmDpjVcv ++nWY3bdFSHwuBXYGvHfwFncGP/6eGEl6oNtYpEvoMOKOwQj0VVCStYPZLf4VSDK52 ++7ckcDdpLeao4xffn7VRDk97Z1+G4C2q8fbioPv36vCMz6YPp0DsCzqJtTwKBgCUN ++4LtDW10fu7xC6p6ik4jgAbhu+79ZBbtLBZ/uTOCbPgdVJrZeSoRd1FYxWx/etW5F ++SYqf3/tdLGiM2nxy/LFcVynHOYPTz/b5IpPQ5XGhV1peMv7XYyg+OkIW+0oVuwnH ++HujXbukBbMXJiAVCyV25NYx71ncCP0H6grhu5J4hAoGAUaketZWHD/ks9JCoPtfy ++pNnXqrIvTp1cSGJpVUQT/DUqAjevyZ5Q8PFPf09BZ6uYlXtCqsp7pA/fqNdlJRPR ++tHRjpZ5XauBiFdpRNH4tJBTiWWhyuWhkWn369Az7HP3CIlJLeq2FlKCvMClcO4op ++Qc9LHT7jqtcy+LqAVBpsJ/o= + -----END RSA TESTING KEY-----`)) + + func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/patches/0007-Add-backend-code-gen.patch b/patches/0008-Add-backend-code-gen.patch similarity index 100% rename from patches/0007-Add-backend-code-gen.patch rename to patches/0008-Add-backend-code-gen.patch diff --git a/patches/0008-Update-default-go.env.patch b/patches/0009-Update-default-go.env.patch similarity index 100% rename from patches/0008-Update-default-go.env.patch rename to patches/0009-Update-default-go.env.patch diff --git a/patches/0009-Skip-failing-tests-on-Windows.patch b/patches/0010-Skip-failing-tests-on-Windows.patch similarity index 100% rename from patches/0009-Skip-failing-tests-on-Windows.patch rename to patches/0010-Skip-failing-tests-on-Windows.patch diff --git a/patches/0010-unset-GOFIPS-when-running-the-Go-toolchain.patch b/patches/0011-unset-GOFIPS-when-running-the-Go-toolchain.patch similarity index 100% rename from patches/0010-unset-GOFIPS-when-running-the-Go-toolchain.patch rename to patches/0011-unset-GOFIPS-when-running-the-Go-toolchain.patch diff --git a/patches/0011-add-support-for-logging-used-Windows-APIs.patch b/patches/0012-add-support-for-logging-used-Windows-APIs.patch similarity index 100% rename from patches/0011-add-support-for-logging-used-Windows-APIs.patch rename to patches/0012-add-support-for-logging-used-Windows-APIs.patch diff --git a/patches/0012-remove-long-path-support-hack.patch b/patches/0013-remove-long-path-support-hack.patch similarity index 100% rename from patches/0012-remove-long-path-support-hack.patch rename to patches/0013-remove-long-path-support-hack.patch diff --git a/patches/0013-Omit-internal-go.mod-files-used-for-codegen.patch b/patches/0014-Omit-internal-go.mod-files-used-for-codegen.patch similarity index 100% rename from patches/0013-Omit-internal-go.mod-files-used-for-codegen.patch rename to patches/0014-Omit-internal-go.mod-files-used-for-codegen.patch diff --git a/patches/0014-Support-curve-P-521-when-TLS-fipsonly-mode-is-enable.patch b/patches/0015-Support-curve-P-521-when-TLS-fipsonly-mode-is-enable.patch similarity index 100% rename from patches/0014-Support-curve-P-521-when-TLS-fipsonly-mode-is-enable.patch rename to patches/0015-Support-curve-P-521-when-TLS-fipsonly-mode-is-enable.patch