Skip to content

Commit 7b756dd

Browse files
committed
crypto/ecdh: remove 8 byte pointer overhead for non boringcrypto builds
Change-Id: I3e6f5e43a20291ed7030df3c0b47481f725a3dcb
1 parent c208b91 commit 7b756dd

File tree

4 files changed

+69
-56
lines changed

4 files changed

+69
-56
lines changed

src/crypto/ecdh/ecdh.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ type Curve interface {
6666
// with [crypto/x509.MarshalPKIXPublicKey]. For NIST curves, they then need to
6767
// be converted with [crypto/ecdsa.PublicKey.ECDH] after parsing.
6868
type PublicKey struct {
69+
boring boring.PublicKeyECDH
70+
6971
curve Curve
7072
publicKey []byte
71-
boring *boring.PublicKeyECDH
7273
}
7374

7475
// Bytes returns a copy of the encoding of the public key.
@@ -105,9 +106,10 @@ func (k *PublicKey) Curve() Curve {
105106
// with [crypto/x509.MarshalPKCS8PrivateKey]. For NIST curves, they then need to
106107
// be converted with [crypto/ecdsa.PrivateKey.ECDH] after parsing.
107108
type PrivateKey struct {
109+
boring boring.PrivateKeyECDH
110+
108111
curve Curve
109112
privateKey []byte
110-
boring *boring.PrivateKeyECDH
111113
// publicKey is set under publicKeyOnce, to allow loading private keys with
112114
// NewPrivateKey without having to perform a scalar multiplication.
113115
publicKey *PublicKey
@@ -160,7 +162,7 @@ func (k *PrivateKey) Curve() Curve {
160162

161163
func (k *PrivateKey) PublicKey() *PublicKey {
162164
k.publicKeyOnce.Do(func() {
163-
if k.boring != nil {
165+
if boring.Enabled && k.boring.Valid() {
164166
// Because we already checked in NewPrivateKey that the key is valid,
165167
// there should not be any possible errors from BoringCrypto,
166168
// so we turn the error into a panic.

src/crypto/ecdh/nist.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func (c *nistCurve[Point]) NewPrivateKey(key []byte) (*PrivateKey, error) {
9393
return k, nil
9494
}
9595

96-
func newBoringPrivateKey(c Curve, bk *boring.PrivateKeyECDH, privateKey []byte) (*PrivateKey, error) {
96+
func newBoringPrivateKey(c Curve, bk boring.PrivateKeyECDH, privateKey []byte) (*PrivateKey, error) {
9797
k := &PrivateKey{
9898
curve: c,
9999
boring: bk,

src/crypto/internal/boring/ecdh.go

+56-46
Original file line numberDiff line numberDiff line change
@@ -15,69 +15,79 @@ import (
1515
)
1616

1717
type PublicKeyECDH struct {
18+
p *publicKeyECDH
19+
}
20+
21+
type publicKeyECDH struct {
1822
curve string
1923
key *C.GO_EC_POINT
2024
group *C.GO_EC_GROUP
2125
bytes []byte
2226
}
2327

24-
func (k *PublicKeyECDH) finalize() {
28+
func (k *publicKeyECDH) finalize() {
2529
C._goboringcrypto_EC_POINT_free(k.key)
2630
}
2731

2832
type PrivateKeyECDH struct {
33+
p *privateKeyECDH
34+
}
35+
36+
type privateKeyECDH struct {
2937
curve string
3038
key *C.GO_EC_KEY
3139
}
3240

33-
func (k *PrivateKeyECDH) finalize() {
41+
func (k *PrivateKeyECDH) Valid() bool { return k.p != nil }
42+
43+
func (k *privateKeyECDH) finalize() {
3444
C._goboringcrypto_EC_KEY_free(k.key)
3545
}
3646

37-
func NewPublicKeyECDH(curve string, bytes []byte) (*PublicKeyECDH, error) {
47+
func NewPublicKeyECDH(curve string, bytes []byte) (PublicKeyECDH, error) {
3848
if len(bytes) < 1 {
39-
return nil, errors.New("NewPublicKeyECDH: missing key")
49+
return PublicKeyECDH{}, errors.New("NewPublicKeyECDH: missing key")
4050
}
4151

4252
nid, err := curveNID(curve)
4353
if err != nil {
44-
return nil, err
54+
return PublicKeyECDH{}, err
4555
}
4656

4757
group := C._goboringcrypto_EC_GROUP_new_by_curve_name(nid)
4858
if group == nil {
49-
return nil, fail("EC_GROUP_new_by_curve_name")
59+
return PublicKeyECDH{}, fail("EC_GROUP_new_by_curve_name")
5060
}
5161
defer C._goboringcrypto_EC_GROUP_free(group)
5262
key := C._goboringcrypto_EC_POINT_new(group)
5363
if key == nil {
54-
return nil, fail("EC_POINT_new")
64+
return PublicKeyECDH{}, fail("EC_POINT_new")
5565
}
5666
ok := C._goboringcrypto_EC_POINT_oct2point(group, key, (*C.uint8_t)(unsafe.Pointer(&bytes[0])), C.size_t(len(bytes)), nil) != 0
5767
if !ok {
5868
C._goboringcrypto_EC_POINT_free(key)
59-
return nil, errors.New("point not on curve")
69+
return PublicKeyECDH{}, errors.New("point not on curve")
6070
}
6171

62-
k := &PublicKeyECDH{curve, key, group, append([]byte(nil), bytes...)}
72+
k := &publicKeyECDH{curve, key, group, append([]byte(nil), bytes...)}
6373
// Note: Because of the finalizer, any time k.key is passed to cgo,
6474
// that call must be followed by a call to runtime.KeepAlive(k),
6575
// to make sure k is not collected (and finalized) before the cgo
6676
// call returns.
67-
runtime.SetFinalizer(k, (*PublicKeyECDH).finalize)
68-
return k, nil
77+
runtime.SetFinalizer(k, (*publicKeyECDH).finalize)
78+
return PublicKeyECDH{p: k}, nil
6979
}
7080

71-
func (k *PublicKeyECDH) Bytes() []byte { return k.bytes }
81+
func (k *PublicKeyECDH) Bytes() []byte { return k.p.bytes }
7282

73-
func NewPrivateKeyECDH(curve string, bytes []byte) (*PrivateKeyECDH, error) {
83+
func NewPrivateKeyECDH(curve string, bytes []byte) (PrivateKeyECDH, error) {
7484
nid, err := curveNID(curve)
7585
if err != nil {
76-
return nil, err
86+
return PrivateKeyECDH{}, err
7787
}
7888
key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid)
7989
if key == nil {
80-
return nil, fail("EC_KEY_new_by_curve_name")
90+
return PrivateKeyECDH{}, fail("EC_KEY_new_by_curve_name")
8191
}
8292
b := bytesToBN(bytes)
8393
ok := b != nil && C._goboringcrypto_EC_KEY_set_private_key(key, b) != 0
@@ -86,42 +96,42 @@ func NewPrivateKeyECDH(curve string, bytes []byte) (*PrivateKeyECDH, error) {
8696
}
8797
if !ok {
8898
C._goboringcrypto_EC_KEY_free(key)
89-
return nil, fail("EC_KEY_set_private_key")
99+
return PrivateKeyECDH{}, fail("EC_KEY_set_private_key")
90100
}
91-
k := &PrivateKeyECDH{curve, key}
101+
k := &privateKeyECDH{curve, key}
92102
// Note: Same as in NewPublicKeyECDH regarding finalizer and KeepAlive.
93-
runtime.SetFinalizer(k, (*PrivateKeyECDH).finalize)
94-
return k, nil
103+
runtime.SetFinalizer(k, (*privateKeyECDH).finalize)
104+
return PrivateKeyECDH{p: k}, nil
95105
}
96106

97-
func (k *PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) {
107+
func (k *PrivateKeyECDH) PublicKey() (PublicKeyECDH, error) {
98108
defer runtime.KeepAlive(k)
99109

100-
group := C._goboringcrypto_EC_KEY_get0_group(k.key)
110+
group := C._goboringcrypto_EC_KEY_get0_group(k.p.key)
101111
if group == nil {
102-
return nil, fail("EC_KEY_get0_group")
112+
return PublicKeyECDH{}, fail("EC_KEY_get0_group")
103113
}
104-
kbig := C._goboringcrypto_EC_KEY_get0_private_key(k.key)
114+
kbig := C._goboringcrypto_EC_KEY_get0_private_key(k.p.key)
105115
if kbig == nil {
106-
return nil, fail("EC_KEY_get0_private_key")
116+
return PublicKeyECDH{}, fail("EC_KEY_get0_private_key")
107117
}
108118
pt := C._goboringcrypto_EC_POINT_new(group)
109119
if pt == nil {
110-
return nil, fail("EC_POINT_new")
120+
return PublicKeyECDH{}, fail("EC_POINT_new")
111121
}
112122
if C._goboringcrypto_EC_POINT_mul(group, pt, kbig, nil, nil, nil) == 0 {
113123
C._goboringcrypto_EC_POINT_free(pt)
114-
return nil, fail("EC_POINT_mul")
124+
return PublicKeyECDH{}, fail("EC_POINT_mul")
115125
}
116-
bytes, err := pointBytesECDH(k.curve, group, pt)
126+
bytes, err := pointBytesECDH(k.p.curve, group, pt)
117127
if err != nil {
118128
C._goboringcrypto_EC_POINT_free(pt)
119-
return nil, err
129+
return PublicKeyECDH{}, err
120130
}
121-
pub := &PublicKeyECDH{k.curve, pt, group, bytes}
131+
pub := &publicKeyECDH{k.p.curve, pt, group, bytes}
122132
// Note: Same as in NewPublicKeyECDH regarding finalizer and KeepAlive.
123-
runtime.SetFinalizer(pub, (*PublicKeyECDH).finalize)
124-
return pub, nil
133+
runtime.SetFinalizer(pub, (*publicKeyECDH).finalize)
134+
return PublicKeyECDH{p: pub}, nil
125135
}
126136

127137
func pointBytesECDH(curve string, group *C.GO_EC_GROUP, pt *C.GO_EC_POINT) ([]byte, error) {
@@ -133,12 +143,12 @@ func pointBytesECDH(curve string, group *C.GO_EC_GROUP, pt *C.GO_EC_POINT) ([]by
133143
return out, nil
134144
}
135145

136-
func ECDH(priv *PrivateKeyECDH, pub *PublicKeyECDH) ([]byte, error) {
137-
group := C._goboringcrypto_EC_KEY_get0_group(priv.key)
146+
func ECDH(priv PrivateKeyECDH, pub PublicKeyECDH) ([]byte, error) {
147+
group := C._goboringcrypto_EC_KEY_get0_group(priv.p.key)
138148
if group == nil {
139149
return nil, fail("EC_KEY_get0_group")
140150
}
141-
privBig := C._goboringcrypto_EC_KEY_get0_private_key(priv.key)
151+
privBig := C._goboringcrypto_EC_KEY_get0_private_key(priv.p.key)
142152
if privBig == nil {
143153
return nil, fail("EC_KEY_get0_private_key")
144154
}
@@ -147,10 +157,10 @@ func ECDH(priv *PrivateKeyECDH, pub *PublicKeyECDH) ([]byte, error) {
147157
return nil, fail("EC_POINT_new")
148158
}
149159
defer C._goboringcrypto_EC_POINT_free(pt)
150-
if C._goboringcrypto_EC_POINT_mul(group, pt, nil, pub.key, privBig, nil) == 0 {
160+
if C._goboringcrypto_EC_POINT_mul(group, pt, nil, pub.p.key, privBig, nil) == 0 {
151161
return nil, fail("EC_POINT_mul")
152162
}
153-
out, err := xCoordBytesECDH(priv.curve, group, pt)
163+
out, err := xCoordBytesECDH(priv.p.curve, group, pt)
154164
if err != nil {
155165
return nil, err
156166
}
@@ -187,38 +197,38 @@ func curveSize(curve string) int {
187197
}
188198
}
189199

190-
func GenerateKeyECDH(curve string) (*PrivateKeyECDH, []byte, error) {
200+
func GenerateKeyECDH(curve string) (PrivateKeyECDH, []byte, error) {
191201
nid, err := curveNID(curve)
192202
if err != nil {
193-
return nil, nil, err
203+
return PrivateKeyECDH{}, nil, err
194204
}
195205
key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid)
196206
if key == nil {
197-
return nil, nil, fail("EC_KEY_new_by_curve_name")
207+
return PrivateKeyECDH{}, nil, fail("EC_KEY_new_by_curve_name")
198208
}
199209
if C._goboringcrypto_EC_KEY_generate_key_fips(key) == 0 {
200210
C._goboringcrypto_EC_KEY_free(key)
201-
return nil, nil, fail("EC_KEY_generate_key_fips")
211+
return PrivateKeyECDH{}, nil, fail("EC_KEY_generate_key_fips")
202212
}
203213

204214
group := C._goboringcrypto_EC_KEY_get0_group(key)
205215
if group == nil {
206216
C._goboringcrypto_EC_KEY_free(key)
207-
return nil, nil, fail("EC_KEY_get0_group")
217+
return PrivateKeyECDH{}, nil, fail("EC_KEY_get0_group")
208218
}
209219
b := C._goboringcrypto_EC_KEY_get0_private_key(key)
210220
if b == nil {
211221
C._goboringcrypto_EC_KEY_free(key)
212-
return nil, nil, fail("EC_KEY_get0_private_key")
222+
return PrivateKeyECDH{}, nil, fail("EC_KEY_get0_private_key")
213223
}
214224
bytes, err := bigBytesECDH(curve, b)
215225
if err != nil {
216226
C._goboringcrypto_EC_KEY_free(key)
217-
return nil, nil, err
227+
return PrivateKeyECDH{}, nil, err
218228
}
219229

220-
k := &PrivateKeyECDH{curve, key}
230+
k := &privateKeyECDH{curve, key}
221231
// Note: Same as in NewPublicKeyECDH regarding finalizer and KeepAlive.
222-
runtime.SetFinalizer(k, (*PrivateKeyECDH).finalize)
223-
return k, bytes, nil
232+
runtime.SetFinalizer(k, (*privateKeyECDH).finalize)
233+
return PrivateKeyECDH{p: k}, bytes, nil
224234
}

src/crypto/internal/boring/notboring.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,10 @@ func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen
115115
type PublicKeyECDH struct{}
116116
type PrivateKeyECDH struct{}
117117

118-
func ECDH(*PrivateKeyECDH, *PublicKeyECDH) ([]byte, error) { panic("boringcrypto: not available") }
119-
func GenerateKeyECDH(string) (*PrivateKeyECDH, []byte, error) { panic("boringcrypto: not available") }
120-
func NewPrivateKeyECDH(string, []byte) (*PrivateKeyECDH, error) { panic("boringcrypto: not available") }
121-
func NewPublicKeyECDH(string, []byte) (*PublicKeyECDH, error) { panic("boringcrypto: not available") }
122-
func (*PublicKeyECDH) Bytes() []byte { panic("boringcrypto: not available") }
123-
func (*PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) { panic("boringcrypto: not available") }
118+
func ECDH(PrivateKeyECDH, PublicKeyECDH) ([]byte, error) { panic("boringcrypto: not available") }
119+
func GenerateKeyECDH(string) (PrivateKeyECDH, []byte, error) { panic("boringcrypto: not available") }
120+
func NewPrivateKeyECDH(string, []byte) (PrivateKeyECDH, error) { panic("boringcrypto: not available") }
121+
func NewPublicKeyECDH(string, []byte) (PublicKeyECDH, error) { panic("boringcrypto: not available") }
122+
func (*PublicKeyECDH) Bytes() []byte { panic("boringcrypto: not available") }
123+
func (*PrivateKeyECDH) PublicKey() (PublicKeyECDH, error) { panic("boringcrypto: not available") }
124+
func (*PrivateKeyECDH) Valid() bool { panic("boringcrypto: not available") }

0 commit comments

Comments
 (0)