[dev.boringcrypto] crypto/ecdsa: use unsafe.Pointer instead of atomic.Value

Using atomic.Value causes vet errors in code copying
PublicKey or PrivateKey structures. I don't think the errors
are accurate, but it's easier to work around them than
to change vet or change atomic.Value.

See #21504.

Change-Id: I3a3435c1fc664cc5166c81674f6f7c58dab35f21
Reviewed-on: https://go-review.googlesource.com/56671
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
Russ Cox 2017-08-18 09:11:40 -04:00
parent b1f201e951
commit bc38fda367
2 changed files with 23 additions and 32 deletions

View File

@ -5,9 +5,10 @@
package ecdsa package ecdsa
import ( import (
"crypto/elliptic"
"crypto/internal/boring" "crypto/internal/boring"
"math/big" "math/big"
"sync/atomic"
"unsafe"
) )
// Cached conversions from Go PublicKey/PrivateKey to BoringCrypto. // Cached conversions from Go PublicKey/PrivateKey to BoringCrypto.
@ -29,81 +30,71 @@ import (
type boringPub struct { type boringPub struct {
key *boring.PublicKeyECDSA key *boring.PublicKeyECDSA
orig publicKey orig PublicKey
}
// copy of PublicKey without the atomic.Value field, to placate vet.
type publicKey struct {
elliptic.Curve
X, Y *big.Int
} }
func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) { func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) {
b, _ := pub.boring.Load().(boringPub) b := (*boringPub)(atomic.LoadPointer(&pub.boring))
if publicKeyEqual(&b.orig, pub) { if b != nil && publicKeyEqual(&b.orig, pub) {
return b.key, nil return b.key, nil
} }
b = new(boringPub)
b.orig = copyPublicKey(pub) b.orig = copyPublicKey(pub)
key, err := boring.NewPublicKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y) key, err := boring.NewPublicKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y)
if err != nil { if err != nil {
return nil, err return nil, err
} }
b.key = key b.key = key
pub.boring.Store(b) atomic.StorePointer(&pub.boring, unsafe.Pointer(b))
return key, nil return key, nil
} }
type boringPriv struct { type boringPriv struct {
key *boring.PrivateKeyECDSA key *boring.PrivateKeyECDSA
orig privateKey orig PrivateKey
}
// copy of PrivateKey without the atomic.Value field, to placate vet.
type privateKey struct {
publicKey
D *big.Int
} }
func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) { func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) {
b, _ := priv.boring.Load().(boringPriv) b := (*boringPriv)(atomic.LoadPointer(&priv.boring))
if privateKeyEqual(&b.orig, priv) { if b != nil && privateKeyEqual(&b.orig, priv) {
return b.key, nil return b.key, nil
} }
b = new(boringPriv)
b.orig = copyPrivateKey(priv) b.orig = copyPrivateKey(priv)
key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y, b.orig.D) key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y, b.orig.D)
if err != nil { if err != nil {
return nil, err return nil, err
} }
b.key = key b.key = key
priv.boring.Store(b) atomic.StorePointer(&priv.boring, unsafe.Pointer(b))
return key, nil return key, nil
} }
func publicKeyEqual(k1 *publicKey, k2 *PublicKey) bool { func publicKeyEqual(k1, k2 *PublicKey) bool {
return k1.X != nil && return k1.X != nil &&
k1.Curve.Params() == k2.Curve.Params() && k1.Curve.Params() == k2.Curve.Params() &&
k1.X.Cmp(k2.X) == 0 && k1.X.Cmp(k2.X) == 0 &&
k1.Y.Cmp(k2.Y) == 0 k1.Y.Cmp(k2.Y) == 0
} }
func privateKeyEqual(k1 *privateKey, k2 *PrivateKey) bool { func privateKeyEqual(k1, k2 *PrivateKey) bool {
return publicKeyEqual(&k1.publicKey, &k2.PublicKey) && return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) &&
k1.D.Cmp(k2.D) == 0 k1.D.Cmp(k2.D) == 0
} }
func copyPublicKey(k *PublicKey) publicKey { func copyPublicKey(k *PublicKey) PublicKey {
return publicKey{ return PublicKey{
Curve: k.Curve, Curve: k.Curve,
X: new(big.Int).Set(k.X), X: new(big.Int).Set(k.X),
Y: new(big.Int).Set(k.Y), Y: new(big.Int).Set(k.Y),
} }
} }
func copyPrivateKey(k *PrivateKey) privateKey { func copyPrivateKey(k *PrivateKey) PrivateKey {
return privateKey{ return PrivateKey{
publicKey: copyPublicKey(&k.PublicKey), PublicKey: copyPublicKey(&k.PublicKey),
D: new(big.Int).Set(k.D), D: new(big.Int).Set(k.D),
} }
} }

View File

@ -27,7 +27,7 @@ import (
"errors" "errors"
"io" "io"
"math/big" "math/big"
"sync/atomic" "unsafe"
) )
// A invertible implements fast inverse mod Curve.Params().N // A invertible implements fast inverse mod Curve.Params().N
@ -50,7 +50,7 @@ type PublicKey struct {
elliptic.Curve elliptic.Curve
X, Y *big.Int X, Y *big.Int
boring atomic.Value boring unsafe.Pointer
} }
// PrivateKey represents a ECDSA private key. // PrivateKey represents a ECDSA private key.
@ -58,7 +58,7 @@ type PrivateKey struct {
PublicKey PublicKey
D *big.Int D *big.Int
boring atomic.Value boring unsafe.Pointer
} }
type ecdsaSignature struct { type ecdsaSignature struct {