From 775b2384e7db6b2be0a753450f2a8305179c3a89 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 18 Aug 2017 09:11:40 -0400 Subject: [dev.boringcrypto.go1.8] 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 TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor Reviewed-by: Adam Langley Reviewed-on: https://go-review.googlesource.com/57941 --- src/crypto/ecdsa/boring.go | 49 +++++++++++++++++++--------------------------- src/crypto/ecdsa/ecdsa.go | 6 +++--- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/crypto/ecdsa/boring.go b/src/crypto/ecdsa/boring.go index 3e59f76a14..fa15ecb850 100644 --- a/src/crypto/ecdsa/boring.go +++ b/src/crypto/ecdsa/boring.go @@ -5,9 +5,10 @@ package ecdsa import ( - "crypto/elliptic" "crypto/internal/boring" "math/big" + "sync/atomic" + "unsafe" ) // Cached conversions from Go PublicKey/PrivateKey to BoringCrypto. @@ -29,81 +30,71 @@ import ( type boringPub struct { key *boring.PublicKeyECDSA - orig publicKey -} - -// copy of PublicKey without the atomic.Value field, to placate vet. -type publicKey struct { - elliptic.Curve - X, Y *big.Int + orig PublicKey } func boringPublicKey(pub *PublicKey) (*boring.PublicKeyECDSA, error) { - b, _ := pub.boring.Load().(boringPub) - if publicKeyEqual(&b.orig, pub) { + b := (*boringPub)(atomic.LoadPointer(&pub.boring)) + if b != nil && publicKeyEqual(&b.orig, pub) { return b.key, nil } + b = new(boringPub) b.orig = copyPublicKey(pub) key, err := boring.NewPublicKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y) if err != nil { return nil, err } b.key = key - pub.boring.Store(b) + atomic.StorePointer(&pub.boring, unsafe.Pointer(b)) return key, nil } type boringPriv struct { key *boring.PrivateKeyECDSA - orig privateKey -} - -// copy of PrivateKey without the atomic.Value field, to placate vet. -type privateKey struct { - publicKey - D *big.Int + orig PrivateKey } func boringPrivateKey(priv *PrivateKey) (*boring.PrivateKeyECDSA, error) { - b, _ := priv.boring.Load().(boringPriv) - if privateKeyEqual(&b.orig, priv) { + b := (*boringPriv)(atomic.LoadPointer(&priv.boring)) + if b != nil && privateKeyEqual(&b.orig, priv) { return b.key, nil } + b = new(boringPriv) b.orig = copyPrivateKey(priv) key, err := boring.NewPrivateKeyECDSA(b.orig.Curve.Params().Name, b.orig.X, b.orig.Y, b.orig.D) if err != nil { return nil, err } b.key = key - priv.boring.Store(b) + atomic.StorePointer(&priv.boring, unsafe.Pointer(b)) return key, nil } -func publicKeyEqual(k1 *publicKey, k2 *PublicKey) bool { +func publicKeyEqual(k1, k2 *PublicKey) bool { return k1.X != nil && k1.Curve.Params() == k2.Curve.Params() && k1.X.Cmp(k2.X) == 0 && k1.Y.Cmp(k2.Y) == 0 } -func privateKeyEqual(k1 *privateKey, k2 *PrivateKey) bool { - return publicKeyEqual(&k1.publicKey, &k2.PublicKey) && +func privateKeyEqual(k1, k2 *PrivateKey) bool { + return publicKeyEqual(&k1.PublicKey, &k2.PublicKey) && k1.D.Cmp(k2.D) == 0 } -func copyPublicKey(k *PublicKey) publicKey { - return publicKey{ +func copyPublicKey(k *PublicKey) PublicKey { + return PublicKey{ Curve: k.Curve, X: new(big.Int).Set(k.X), Y: new(big.Int).Set(k.Y), } } -func copyPrivateKey(k *PrivateKey) privateKey { - return privateKey{ - publicKey: copyPublicKey(&k.PublicKey), +func copyPrivateKey(k *PrivateKey) PrivateKey { + return PrivateKey{ + PublicKey: copyPublicKey(&k.PublicKey), D: new(big.Int).Set(k.D), } } diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go index a3fa743e66..3fe1dda660 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go @@ -27,7 +27,7 @@ import ( "errors" "io" "math/big" - "sync/atomic" + "unsafe" ) // A invertible implements fast inverse mod Curve.Params().N @@ -50,7 +50,7 @@ type PublicKey struct { elliptic.Curve X, Y *big.Int - boring atomic.Value + boring unsafe.Pointer } // PrivateKey represents a ECDSA private key. @@ -58,7 +58,7 @@ type PrivateKey struct { PublicKey D *big.Int - boring atomic.Value + boring unsafe.Pointer } type ecdsaSignature struct { -- cgit v1.2.3-54-g00ecf