Skip to content

Commit fb11572

Browse files
committed
[dev.boringcrypto.go1.8] crypto/ecdsa: use BoringCrypto
Change-Id: I108e0a527bddd673b16582d206e0697341d0a0ea Reviewed-on: https://go-review.googlesource.com/55478 Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Adam Langley <[email protected]> Reviewed-on: https://go-review.googlesource.com/57940
1 parent ddd775f commit fb11572

File tree

5 files changed

+374
-0
lines changed

5 files changed

+374
-0
lines changed

src/crypto/ecdsa/boring.go

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright 2017 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package ecdsa
6+
7+
import (
8+
"crypto/elliptic"
9+
"crypto/internal/boring"
10+
"math/big"
11+
)
12+
13+
// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
14+
//
15+
// A new 'boring atomic.Value' field in both PublicKey and PrivateKey
16+
// serves as a cache for the most recent conversion. The cache is an
17+
// atomic.Value because code might reasonably set up a key and then
18+
// (thinking it immutable) use it from multiple goroutines simultaneously.
19+
// The first operation initializes the cache; if there are multiple simultaneous
20+
// first operations, they will do redundant work but not step on each other.
21+
//
22+
// We could just assume that once used in a Sign or Verify operation,
23+
// a particular key is never again modified, but that has not been a
24+
// stated assumption before. Just in case there is any existing code that
25+
// does modify the key between operations, we save the original values
26+
// alongside the cached BoringCrypto key and check that the real key
27+
// still matches before using the cached key. The theory is that the real
28+
// operations are significantly more expensive than the comparison.
29+
30+
type boringPub struct {
31+
key *boring.PublicKeyECDSA
32+
orig publicKey
33+
}
34+
35+
// copy of PublicKey without the atomic.Value field, to placate vet.
36+
type publicKey struct {
37+
elliptic.Curve
38+
X, Y *big.Int
39+
}
40+
41+
func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) {
42+
b, _ := pub.boring.Load().(boringPub)
43+
if publicKeyEqual(&b.orig, pub) {
44+
return b.key, nil
45+
}
46+
47+
b.orig = copyPublicKey(pub)
48+
key, err := boring.NewPublicKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y)
49+
if err != nil {
50+
return nil, err
51+
}
52+
b.key = key
53+
pub.boring.Store(b)
54+
return key, nil
55+
}
56+
57+
type boringPriv struct {
58+
key *boring.PrivateKeyECDSA
59+
orig privateKey
60+
}
61+
62+
// copy of PrivateKey without the atomic.Value field, to placate vet.
63+
type privateKey struct {
64+
publicKey
65+
D *big.Int
66+
}
67+
68+
func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) {
69+
b, _ := priv.boring.Load().(boringPriv)
70+
if privateKeyEqual(&b.orig, priv) {
71+
return b.key, nil
72+
}
73+
74+
b.orig = copyPrivateKey(priv)
75+
key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y, b.orig.D)
76+
if err != nil {
77+
return nil, err
78+
}
79+
b.key = key
80+
priv.boring.Store(b)
81+
return key, nil
82+
}
83+
84+
func publicKeyEqual(k1 *publicKey, k2 *PublicKey) bool {
85+
return k1.X != nil &&
86+
k1.Curve.Params() == k2.Curve.Params() &&
87+
k1.X.Cmp(k2.X) == 0 &&
88+
k1.Y.Cmp(k2.Y) == 0
89+
}
90+
91+
func privateKeyEqual(k1 *privateKey, k2 *PrivateKey) bool {
92+
return publicKeyEqual(&k1.publicKey, &k2.PublicKey) &&
93+
k1.D.Cmp(k2.D) == 0
94+
}
95+
96+
func copyPublicKey(k *PublicKey) publicKey {
97+
return publicKey{
98+
Curve: k.Curve,
99+
X: new(big.Int).Set(k.X),
100+
Y: new(big.Int).Set(k.Y),
101+
}
102+
}
103+
104+
func copyPrivateKey(k *PrivateKey) privateKey {
105+
return privateKey{
106+
publicKey: copyPublicKey(&k.PublicKey),
107+
D: new(big.Int).Set(k.D),
108+
}
109+
}

src/crypto/ecdsa/ecdsa.go

+42
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ import (
2121
"crypto/aes"
2222
"crypto/cipher"
2323
"crypto/elliptic"
24+
"crypto/internal/boring"
2425
"crypto/sha512"
2526
"encoding/asn1"
2627
"errors"
2728
"io"
2829
"math/big"
30+
"sync/atomic"
2931
)
3032

3133
// A invertible implements fast inverse mod Curve.Params().N
@@ -47,12 +49,16 @@ const (
4749
type PublicKey struct {
4850
elliptic.Curve
4951
X, Y *big.Int
52+
53+
boring atomic.Value
5054
}
5155

5256
// PrivateKey represents a ECDSA private key.
5357
type PrivateKey struct {
5458
PublicKey
5559
D *big.Int
60+
61+
boring atomic.Value
5662
}
5763

5864
type ecdsaSignature struct {
@@ -69,6 +75,15 @@ func (priv *PrivateKey) Public() crypto.PublicKey {
6975
// hardware module. Common uses should use the Sign function in this package
7076
// directly.
7177
func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
78+
if boring.Enabled && rand == boring.RandReader {
79+
b, err := boringPrivateKey(priv)
80+
if err != nil {
81+
return nil, err
82+
}
83+
return boring.SignMarshalECDSA(b, msg)
84+
}
85+
boring.UnreachableExceptTests()
86+
7287
r, s, err := Sign(rand, priv, msg)
7388
if err != nil {
7489
return nil, err
@@ -98,6 +113,15 @@ func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error)
98113

99114
// GenerateKey generates a public and private key pair.
100115
func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
116+
if boring.Enabled && rand == boring.RandReader {
117+
x, y, d, err := boring.GenerateKeyECDSA(c.Params().Name)
118+
if err != nil {
119+
return nil, err
120+
}
121+
return &PrivateKey{PublicKey: PublicKey{Curve: c, X: x, Y: y}, D: d}, nil
122+
}
123+
boring.UnreachableExceptTests()
124+
101125
k, err := randFieldElement(c, rand)
102126
if err != nil {
103127
return nil, err
@@ -149,6 +173,15 @@ var errZeroParam = errors.New("zero parameter")
149173
// returns the signature as a pair of integers. The security of the private key
150174
// depends on the entropy of rand.
151175
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
176+
if boring.Enabled && rand == boring.RandReader {
177+
b, err := boringPrivateKey(priv)
178+
if err != nil {
179+
return nil, nil, err
180+
}
181+
return boring.SignECDSA(b, hash)
182+
}
183+
boring.UnreachableExceptTests()
184+
152185
// Get min(log2(q) / 2, 256) bits of entropy from rand.
153186
entropylen := (priv.Curve.Params().BitSize + 7) / 16
154187
if entropylen > 32 {
@@ -225,6 +258,15 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
225258
// Verify verifies the signature in r, s of hash using the public key, pub. Its
226259
// return value records whether the signature is valid.
227260
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
261+
if boring.Enabled {
262+
b, err := boringPublicKey(pub)
263+
if err != nil {
264+
return false
265+
}
266+
return boring.VerifyECDSA(b, hash, r, s)
267+
}
268+
boring.UnreachableExceptTests()
269+
228270
// See [NSA] 3.4.2
229271
c := pub.Curve
230272
N := c.Params().N

src/crypto/internal/boring/boring.go

+12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package boring
99

1010
// #include "goboringcrypto.h"
1111
import "C"
12+
import "math/big"
1213

1314
const available = true
1415

@@ -41,3 +42,14 @@ func UnreachableExceptTests() {
4142
type fail string
4243

4344
func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" }
45+
46+
func bigToBN(x *big.Int) *C.GO_BIGNUM {
47+
raw := x.Bytes()
48+
return C._goboringcrypto_BN_bin2bn(base(raw), C.size_t(len(raw)), nil)
49+
}
50+
51+
func bnToBig(bn *C.GO_BIGNUM) *big.Int {
52+
raw := make([]byte, C._goboringcrypto_BN_num_bytes(bn))
53+
n := C._goboringcrypto_BN_bn2bin(bn, base(raw))
54+
return new(big.Int).SetBytes(raw[:n])
55+
}

0 commit comments

Comments
 (0)