Skip to content

Commit c9eda5b

Browse files
committed
initial implementation of macOS crypto backend
1 parent 1eb2f56 commit c9eda5b

17 files changed

+5110
-1266
lines changed

eng/_util/buildutil/buildutil.go

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ func AppendExperimentEnv(experiment string) {
9191
if strings.Contains(experiment, "opensslcrypto") ||
9292
strings.Contains(experiment, "cngcrypto") ||
9393
strings.Contains(experiment, "boringcrypto") ||
94+
strings.Contains(experiment, "darwincrypto") ||
9495
strings.Contains(experiment, "systemcrypto") {
9596

9697
experiment += ",allowcryptofallback"

eng/pipeline/stages/go-builder-matrix-stages.yml

+3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ stages:
8181
- { os: linux, arch: arm64, config: buildandpack }
8282
- ${{ if parameters.innerloop }}:
8383
- { os: darwin, arch: amd64, config: devscript }
84+
- { os: darwin, arch: amd64, config: test }
85+
- { experiment: darwincrypto, os: darwin, arch: amd64, config: test }
86+
- { experiment: darwincrypto, os: darwin, arch: amd64, config: test, fips: true }
8487
- { os: linux, arch: amd64, config: devscript }
8588
- { os: linux, arch: amd64, config: test }
8689
- { os: linux, arch: amd64, config: test, distro: ubuntu }

patches/0001-Add-systemcrypto-GOEXPERIMENT.patch

+44-20
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@ information about the behavior.
1111
Includes new tests in "build_test.go" and "buildbackend_test.go" to help
1212
maintain this feature. For more information, see the test files.
1313
---
14-
src/cmd/go/internal/modindex/build.go | 54 ++++++++++++++
15-
src/cmd/go/internal/modindex/build_test.go | 73 +++++++++++++++++++
16-
src/go/build/build.go | 54 ++++++++++++++
17-
src/go/build/buildbackend_test.go | 66 +++++++++++++++++
14+
src/cmd/go/internal/modindex/build.go | 57 +++++++++++++
15+
src/cmd/go/internal/modindex/build_test.go | 73 ++++++++++++++++
16+
src/go/build/build.go | 57 +++++++++++++
17+
src/go/build/buildbackend_test.go | 84 +++++++++++++++++++
1818
.../testdata/backendtags_openssl/main.go | 3 +
1919
.../testdata/backendtags_openssl/openssl.go | 3 +
2020
.../build/testdata/backendtags_system/main.go | 3 +
2121
.../backendtags_system/systemcrypto.go | 3 +
22-
.../goexperiment/exp_systemcrypto_off.go | 9 +++
23-
.../goexperiment/exp_systemcrypto_on.go | 9 +++
22+
.../goexperiment/exp_systemcrypto_off.go | 9 ++
23+
.../goexperiment/exp_systemcrypto_on.go | 9 ++
2424
src/internal/goexperiment/flags.go | 15 ++++
25-
11 files changed, 292 insertions(+)
25+
11 files changed, 316 insertions(+)
2626
create mode 100644 src/cmd/go/internal/modindex/build_test.go
2727
create mode 100644 src/go/build/buildbackend_test.go
2828
create mode 100644 src/go/build/testdata/backendtags_openssl/main.go
@@ -33,16 +33,17 @@ maintain this feature. For more information, see the test files.
3333
create mode 100644 src/internal/goexperiment/exp_systemcrypto_on.go
3434

3535
diff --git a/src/cmd/go/internal/modindex/build.go b/src/cmd/go/internal/modindex/build.go
36-
index b57f2f6368f0fe..9ddde1ce9a2286 100644
36+
index b4dacb0f523a8d..4315c288d10cb3 100644
3737
--- a/src/cmd/go/internal/modindex/build.go
3838
+++ b/src/cmd/go/internal/modindex/build.go
39-
@@ -880,13 +880,67 @@ func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool {
39+
@@ -886,13 +886,70 @@ func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool {
4040
name = "goexperiment.boringcrypto" // boringcrypto is an old name for goexperiment.boringcrypto
4141
}
4242

4343
+ const system = "goexperiment.systemcrypto"
4444
+ const openssl = "goexperiment.opensslcrypto"
4545
+ const cng = "goexperiment.cngcrypto"
46+
+ const darwin = "goexperiment.darwincrypto"
4647
+ const boring = "goexperiment.boringcrypto"
4748
+ // Implement the SystemCrypto GOEXPERIMENT logic. This is done here rather
4849
+ // than during GOEXPERIMENT parsing so "-tags goexperiment.systemcrypto"
@@ -63,11 +64,12 @@ index b57f2f6368f0fe..9ddde1ce9a2286 100644
6364
+ satisfiedByAnyBackend := name == system
6465
+ satisfiedBySystemCrypto :=
6566
+ (ctxt.GOOS == "linux" && name == openssl) ||
66-
+ (ctxt.GOOS == "windows" && name == cng)
67+
+ (ctxt.GOOS == "windows" && name == cng) ||
68+
+ (ctxt.GOOS == "darwin" && name == darwin)
6769
+ satisfiedBy := func(tag string) bool {
6870
+ if satisfiedByAnyBackend {
6971
+ switch tag {
70-
+ case openssl, cng, boring:
72+
+ case openssl, cng, darwin, boring:
7173
+ return true
7274
+ }
7375
+ }
@@ -81,6 +83,7 @@ index b57f2f6368f0fe..9ddde1ce9a2286 100644
8183
+ if satisfiedByAnyBackend {
8284
+ allTags[openssl] = true
8385
+ allTags[cng] = true
86+
+ allTags[darwin] = true
8487
+ allTags[boring] = true
8588
+ }
8689
+ if satisfiedBySystemCrypto {
@@ -184,16 +187,17 @@ index 00000000000000..1756c5d027fee0
184187
+ }
185188
+}
186189
diff --git a/src/go/build/build.go b/src/go/build/build.go
187-
index dd6cdc903a21a8..48adcfed5cf3cb 100644
190+
index 9ffffda08a99b1..78fd536fa6a6d1 100644
188191
--- a/src/go/build/build.go
189192
+++ b/src/go/build/build.go
190-
@@ -1947,13 +1947,67 @@ func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool {
193+
@@ -1984,13 +1984,70 @@ func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool {
191194
name = "goexperiment.boringcrypto" // boringcrypto is an old name for goexperiment.boringcrypto
192195
}
193196

194197
+ const system = "goexperiment.systemcrypto"
195198
+ const openssl = "goexperiment.opensslcrypto"
196199
+ const cng = "goexperiment.cngcrypto"
200+
+ const darwin = "goexperiment.darwincrypto"
197201
+ const boring = "goexperiment.boringcrypto"
198202
+ // Implement the SystemCrypto GOEXPERIMENT logic. This is done here rather
199203
+ // than during GOEXPERIMENT parsing so "-tags goexperiment.systemcrypto"
@@ -214,11 +218,12 @@ index dd6cdc903a21a8..48adcfed5cf3cb 100644
214218
+ satisfiedByAnyBackend := name == system
215219
+ satisfiedBySystemCrypto :=
216220
+ (ctxt.GOOS == "linux" && name == openssl) ||
217-
+ (ctxt.GOOS == "windows" && name == cng)
221+
+ (ctxt.GOOS == "windows" && name == cng) ||
222+
+ (ctxt.GOOS == "darwin" && name == darwin)
218223
+ satisfiedBy := func(tag string) bool {
219224
+ if satisfiedByAnyBackend {
220225
+ switch tag {
221-
+ case openssl, cng, boring:
226+
+ case openssl, cng, darwin, boring:
222227
+ return true
223228
+ }
224229
+ }
@@ -232,6 +237,7 @@ index dd6cdc903a21a8..48adcfed5cf3cb 100644
232237
+ if satisfiedByAnyBackend {
233238
+ allTags[openssl] = true
234239
+ allTags[cng] = true
240+
+ allTags[darwin] = true
235241
+ allTags[boring] = true
236242
+ }
237243
+ if satisfiedBySystemCrypto {
@@ -257,10 +263,10 @@ index dd6cdc903a21a8..48adcfed5cf3cb 100644
257263
}
258264
diff --git a/src/go/build/buildbackend_test.go b/src/go/build/buildbackend_test.go
259265
new file mode 100644
260-
index 00000000000000..a22abbb42e37c0
266+
index 00000000000000..aa3c5f1007ed79
261267
--- /dev/null
262268
+++ b/src/go/build/buildbackend_test.go
263-
@@ -0,0 +1,66 @@
269+
@@ -0,0 +1,84 @@
264270
+// Copyright 2023 The Go Authors. All rights reserved.
265271
+// Use of this source code is governed by a BSD-style
266272
+// license that can be found in the LICENSE file.
@@ -318,14 +324,32 @@ index 00000000000000..a22abbb42e37c0
318324
+ if err != nil {
319325
+ t.Fatal(err)
320326
+ }
321-
+ want = []string{"goexperiment.boringcrypto", "goexperiment.cngcrypto", "goexperiment.opensslcrypto", "goexperiment.systemcrypto"}
327+
+ want = []string{"goexperiment.boringcrypto", "goexperiment.cngcrypto", "goexperiment.darwincrypto", "goexperiment.opensslcrypto", "goexperiment.systemcrypto"}
322328
+ if !reflect.DeepEqual(p.AllTags, want) {
323329
+ t.Errorf("AllTags = %v, want %v", p.AllTags, want)
324330
+ }
325331
+ wantFiles = []string{"main.go", "systemcrypto.go"}
326332
+ if !reflect.DeepEqual(p.GoFiles, wantFiles) {
327333
+ t.Errorf("GoFiles = %v, want %v", p.GoFiles, wantFiles)
328334
+ }
335+
+
336+
+ ctxt.GOARCH = "amd64"
337+
+ ctxt.GOOS = "darwin"
338+
+ ctxt.BuildTags = []string{"goexperiment.darwincrypto"}
339+
+ p, err = ctxt.ImportDir("testdata/backendtags_openssl", 0)
340+
+ if err != nil {
341+
+ t.Fatal(err)
342+
+ }
343+
+ // Given the current GOOS (darwin), systemcrypto would not affect the
344+
+ // decision, so we don't want it to be included in AllTags.
345+
+ want = []string{"goexperiment.opensslcrypto"}
346+
+ if !reflect.DeepEqual(p.AllTags, want) {
347+
+ t.Errorf("AllTags = %v, want %v", p.AllTags, want)
348+
+ }
349+
+ wantFiles = []string{"main.go"}
350+
+ if !reflect.DeepEqual(p.GoFiles, wantFiles) {
351+
+ t.Errorf("GoFiles = %v, want %v", p.GoFiles, wantFiles)
352+
+ }
329353
+}
330354
diff --git a/src/go/build/testdata/backendtags_openssl/main.go b/src/go/build/testdata/backendtags_openssl/main.go
331355
new file mode 100644
@@ -394,14 +418,14 @@ index 00000000000000..9c5b0bbc7b99dc
394418
+const SystemCrypto = true
395419
+const SystemCryptoInt = 1
396420
diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go
397-
index ae3cbaf89fa5dd..de79140b2d4780 100644
421+
index 31b3d0315b64f8..de1dfa6e567a71 100644
398422
--- a/src/internal/goexperiment/flags.go
399423
+++ b/src/internal/goexperiment/flags.go
400424
@@ -60,6 +60,21 @@ type Flags struct {
401425
StaticLockRanking bool
402426
BoringCrypto bool
403427

404-
+ // SystemCrypto enables the OpenSSL or CNG crypto experiment depending on
428+
+ // SystemCrypto enables the OpenSSL, CNG or Darwin crypto experiment depending on
405429
+ // which one is appropriate on the target GOOS.
406430
+ //
407431
+ // If SystemCrypto is enabled but no crypto experiment is appropriate on the

patches/0002-Add-crypto-backend-foundation.patch

+21-21
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ index 039bd82ed21f9f..69a97d9bf250be 100644
590590
panic("boringcrypto: not available")
591591
diff --git a/src/crypto/ed25519/boring.go b/src/crypto/ed25519/boring.go
592592
new file mode 100644
593-
index 00000000000000..3a7d7b76c8d8d7
593+
index 00000000000000..ff5c426b4fdaea
594594
--- /dev/null
595595
+++ b/src/crypto/ed25519/boring.go
596596
@@ -0,0 +1,71 @@
@@ -619,11 +619,11 @@ index 00000000000000..3a7d7b76c8d8d7
619619
+}
620620
+
621621
+type boringPub struct {
622-
+ key *boring.PublicKeyEd25519
622+
+ key boring.PublicKeyEd25519
623623
+ orig [PublicKeySize]byte
624624
+}
625625
+
626-
+func boringPublicKey(pub PublicKey) (*boring.PublicKeyEd25519, error) {
626+
+func boringPublicKey(pub PublicKey) (boring.PublicKeyEd25519, error) {
627627
+ // Use the pointer to the underlying pub array as key.
628628
+ p := unsafe.SliceData(pub)
629629
+ b := pubCache.Get(p)
@@ -635,19 +635,19 @@ index 00000000000000..3a7d7b76c8d8d7
635635
+ copy(b.orig[:], pub)
636636
+ key, err := boring.NewPublicKeyEd25119(b.orig[:])
637637
+ if err != nil {
638-
+ return nil, err
638+
+ return key, err
639639
+ }
640640
+ b.key = key
641641
+ pubCache.Put(p, b)
642642
+ return key, nil
643643
+}
644644
+
645645
+type boringPriv struct {
646-
+ key *boring.PrivateKeyEd25519
646+
+ key boring.PrivateKeyEd25519
647647
+ orig [PrivateKeySize]byte
648648
+}
649649
+
650-
+func boringPrivateKey(priv PrivateKey) (*boring.PrivateKeyEd25519, error) {
650+
+func boringPrivateKey(priv PrivateKey) (boring.PrivateKeyEd25519, error) {
651651
+ // Use the pointer to the underlying priv array as key.
652652
+ p := unsafe.SliceData(priv)
653653
+ b := privCache.Get(p)
@@ -659,7 +659,7 @@ index 00000000000000..3a7d7b76c8d8d7
659659
+ copy(b.orig[:], priv)
660660
+ key, err := boring.NewPrivateKeyEd25119(b.orig[:])
661661
+ if err != nil {
662-
+ return nil, err
662+
+ return key, err
663663
+ }
664664
+ b.key = key
665665
+ privCache.Put(p, b)
@@ -793,7 +793,7 @@ index c1f8ff784e4a5c..308d814ff6302b 100644
793793
return errors.New("ed25519: expected opts.Hash zero (unhashed message, for standard Ed25519) or SHA-512 (for Ed25519ph)")
794794
diff --git a/src/crypto/ed25519/notboring.go b/src/crypto/ed25519/notboring.go
795795
new file mode 100644
796-
index 00000000000000..b0cdd44d81c753
796+
index 00000000000000..77b69a3be88183
797797
--- /dev/null
798798
+++ b/src/crypto/ed25519/notboring.go
799799
@@ -0,0 +1,16 @@
@@ -807,10 +807,10 @@ index 00000000000000..b0cdd44d81c753
807807
+
808808
+import boring "crypto/internal/backend"
809809
+
810-
+func boringPublicKey(PublicKey) (*boring.PublicKeyEd25519, error) {
810+
+func boringPublicKey(PublicKey) (boring.PublicKeyEd25519, error) {
811811
+ panic("boringcrypto: not available")
812812
+}
813-
+func boringPrivateKey(PrivateKey) (*boring.PrivateKeyEd25519, error) {
813+
+func boringPrivateKey(PrivateKey) (boring.PrivateKeyEd25519, error) {
814814
+ panic("boringcrypto: not available")
815815
+}
816816
diff --git a/src/crypto/hkdf/hkdf.go b/src/crypto/hkdf/hkdf.go
@@ -936,15 +936,15 @@ index 00000000000000..c2c06d3bff8c74
936936
+}
937937
diff --git a/src/crypto/internal/backend/bbig/big.go b/src/crypto/internal/backend/bbig/big.go
938938
new file mode 100644
939-
index 00000000000000..20251a290dc2e0
939+
index 00000000000000..ab3f30825dcfa1
940940
--- /dev/null
941941
+++ b/src/crypto/internal/backend/bbig/big.go
942942
@@ -0,0 +1,17 @@
943943
+// Copyright 2022 The Go Authors. All rights reserved.
944944
+// Use of this source code is governed by a BSD-style
945945
+// license that can be found in the LICENSE file.
946946
+
947-
+//go:build !goexperiment.systemcrypto
947+
+//go:build !goexperiment.systemcrypto || (goexperiment.darwincrypto && !cgo)
948948
+
949949
+package bbig
950950
+
@@ -1148,7 +1148,7 @@ index 00000000000000..83691d7dd42d51
11481148
+}
11491149
diff --git a/src/crypto/internal/backend/nobackend.go b/src/crypto/internal/backend/nobackend.go
11501150
new file mode 100644
1151-
index 00000000000000..71e0ec9dc25a02
1151+
index 00000000000000..06e19c55345187
11521152
--- /dev/null
11531153
+++ b/src/crypto/internal/backend/nobackend.go
11541154
@@ -0,0 +1,229 @@
@@ -1317,37 +1317,37 @@ index 00000000000000..71e0ec9dc25a02
13171317
+
13181318
+type PublicKeyEd25519 struct{}
13191319
+
1320-
+func (k *PublicKeyEd25519) Bytes() ([]byte, error) {
1320+
+func (k PublicKeyEd25519) Bytes() ([]byte, error) {
13211321
+ panic("cryptobackend: not available")
13221322
+}
13231323
+
13241324
+type PrivateKeyEd25519 struct{}
13251325
+
1326-
+func (k *PrivateKeyEd25519) Bytes() ([]byte, error) {
1326+
+func (k PrivateKeyEd25519) Bytes() ([]byte, error) {
13271327
+ panic("cryptobackend: not available")
13281328
+}
13291329
+
1330-
+func GenerateKeyEd25519() (*PrivateKeyEd25519, error) {
1330+
+func GenerateKeyEd25519() (PrivateKeyEd25519, error) {
13311331
+ panic("cryptobackend: not available")
13321332
+}
13331333
+
1334-
+func NewPrivateKeyEd25119(priv []byte) (*PrivateKeyEd25519, error) {
1334+
+func NewPrivateKeyEd25119(priv []byte) (PrivateKeyEd25519, error) {
13351335
+ panic("cryptobackend: not available")
13361336
+}
13371337
+
1338-
+func NewPublicKeyEd25119(pub []byte) (*PublicKeyEd25519, error) {
1338+
+func NewPublicKeyEd25119(pub []byte) (PublicKeyEd25519, error) {
13391339
+ panic("cryptobackend: not available")
13401340
+}
13411341
+
1342-
+func NewPrivateKeyEd25519FromSeed(seed []byte) (*PrivateKeyEd25519, error) {
1342+
+func NewPrivateKeyEd25519FromSeed(seed []byte) (PrivateKeyEd25519, error) {
13431343
+ panic("cryptobackend: not available")
13441344
+}
13451345
+
1346-
+func SignEd25519(priv *PrivateKeyEd25519, message []byte) ([]byte, error) {
1346+
+func SignEd25519(priv PrivateKeyEd25519, message []byte) ([]byte, error) {
13471347
+ panic("cryptobackend: not available")
13481348
+}
13491349
+
1350-
+func VerifyEd25519(pub *PublicKeyEd25519, message, sig []byte) error {
1350+
+func VerifyEd25519(pub PublicKeyEd25519, message, sig []byte) error {
13511351
+ panic("cryptobackend: not available")
13521352
+}
13531353
+

patches/0003-Add-BoringSSL-crypto-backend.patch

+8-8
Original file line numberDiff line numberDiff line change
@@ -235,37 +235,37 @@ index 00000000000000..b1bd6d5ba756d7
235235
+
236236
+type PublicKeyEd25519 struct{}
237237
+
238-
+func (k *PublicKeyEd25519) Bytes() ([]byte, error) {
238+
+func (k PublicKeyEd25519) Bytes() ([]byte, error) {
239239
+ panic("cryptobackend: not available")
240240
+}
241241
+
242242
+type PrivateKeyEd25519 struct{}
243243
+
244-
+func (k *PrivateKeyEd25519) Bytes() ([]byte, error) {
244+
+func (k PrivateKeyEd25519) Bytes() ([]byte, error) {
245245
+ panic("cryptobackend: not available")
246246
+}
247247
+
248-
+func GenerateKeyEd25519() (*PrivateKeyEd25519, error) {
248+
+func GenerateKeyEd25519() (PrivateKeyEd25519, error) {
249249
+ panic("cryptobackend: not available")
250250
+}
251251
+
252-
+func NewPrivateKeyEd25119(priv []byte) (*PrivateKeyEd25519, error) {
252+
+func NewPrivateKeyEd25119(priv []byte) (PrivateKeyEd25519, error) {
253253
+ panic("cryptobackend: not available")
254254
+}
255255
+
256-
+func NewPublicKeyEd25119(pub []byte) (*PublicKeyEd25519, error) {
256+
+func NewPublicKeyEd25119(pub []byte) (PublicKeyEd25519, error) {
257257
+ panic("cryptobackend: not available")
258258
+}
259259
+
260-
+func NewPrivateKeyEd25519FromSeed(seed []byte) (*PrivateKeyEd25519, error) {
260+
+func NewPrivateKeyEd25519FromSeed(seed []byte) (PrivateKeyEd25519, error) {
261261
+ panic("cryptobackend: not available")
262262
+}
263263
+
264-
+func SignEd25519(priv *PrivateKeyEd25519, message []byte) ([]byte, error) {
264+
+func SignEd25519(priv PrivateKeyEd25519, message []byte) ([]byte, error) {
265265
+ panic("cryptobackend: not available")
266266
+}
267267
+
268-
+func VerifyEd25519(pub *PublicKeyEd25519, message, sig []byte) error {
268+
+func VerifyEd25519(pub PublicKeyEd25519, message, sig []byte) error {
269269
+ panic("cryptobackend: not available")
270270
+}
271271
+

0 commit comments

Comments
 (0)