diff options
author | Ian Lance Taylor <iant@golang.org> | 2019-09-06 18:12:46 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-09-06 18:12:46 +0000 |
commit | aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13 (patch) | |
tree | 7e63b06d1eec92beec6997c9d3ab47a5d6a835be /libgo/go/crypto/ecdsa | |
parent | 920ea3b8ba3164b61ac9490dfdfceb6936eda6dd (diff) | |
download | gcc-aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13.zip gcc-aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13.tar.gz gcc-aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13.tar.bz2 |
libgo: update to Go 1.13beta1 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/193497
From-SVN: r275473
Diffstat (limited to 'libgo/go/crypto/ecdsa')
-rw-r--r-- | libgo/go/crypto/ecdsa/ecdsa.go | 19 | ||||
-rw-r--r-- | libgo/go/crypto/ecdsa/ecdsa_noasm.go | 22 | ||||
-rw-r--r-- | libgo/go/crypto/ecdsa/ecdsa_s390x.go | 153 | ||||
-rw-r--r-- | libgo/go/crypto/ecdsa/ecdsa_s390x_test.go | 33 |
4 files changed, 221 insertions, 6 deletions
diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go index e059f18..ddc3b35 100644 --- a/libgo/go/crypto/ecdsa/ecdsa.go +++ b/libgo/go/crypto/ecdsa/ecdsa.go @@ -21,13 +21,12 @@ import ( "crypto/aes" "crypto/cipher" "crypto/elliptic" + "crypto/internal/randutil" "crypto/sha512" "encoding/asn1" "errors" "io" "math/big" - - "crypto/internal/randutil" ) // A invertible implements fast inverse mod Curve.Params().N @@ -190,14 +189,21 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err // See [NSA] 3.4.1 c := priv.PublicKey.Curve + e := hashToInt(hash, c) + r, s, err = sign(priv, &csprng, c, e) + return +} + +func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, e *big.Int) (r, s *big.Int, err error) { N := c.Params().N if N.Sign() == 0 { return nil, nil, errZeroParam } + var k, kInv *big.Int for { for { - k, err = randFieldElement(c, csprng) + k, err = randFieldElement(c, *csprng) if err != nil { r = nil return @@ -215,8 +221,6 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err break } } - - e := hashToInt(hash, c) s = new(big.Int).Mul(priv.D, r) s.Add(s, e) s.Mul(s, kInv) @@ -225,7 +229,6 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err break } } - return } @@ -243,8 +246,12 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool { return false } e := hashToInt(hash, c) + return verify(pub, c, e, r, s) +} +func verifyGeneric(pub *PublicKey, c elliptic.Curve, e, r, s *big.Int) bool { var w *big.Int + N := c.Params().N if in, ok := c.(invertible); ok { w = in.Inverse(s) } else { diff --git a/libgo/go/crypto/ecdsa/ecdsa_noasm.go b/libgo/go/crypto/ecdsa/ecdsa_noasm.go new file mode 100644 index 0000000..d9f9cff --- /dev/null +++ b/libgo/go/crypto/ecdsa/ecdsa_noasm.go @@ -0,0 +1,22 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !s390x gccgo + +package ecdsa + +import ( + "crypto/cipher" + "crypto/elliptic" + "math/big" +) + +func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, e *big.Int) (r, s *big.Int, err error) { + r, s, err = signGeneric(priv, csprng, c, e) + return +} + +func verify(pub *PublicKey, c elliptic.Curve, e, r, s *big.Int) bool { + return verifyGeneric(pub, c, e, r, s) +} diff --git a/libgo/go/crypto/ecdsa/ecdsa_s390x.go b/libgo/go/crypto/ecdsa/ecdsa_s390x.go new file mode 100644 index 0000000..f07c3bf --- /dev/null +++ b/libgo/go/crypto/ecdsa/ecdsa_s390x.go @@ -0,0 +1,153 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x,!gccgo + +package ecdsa + +import ( + "crypto/cipher" + "crypto/elliptic" + "internal/cpu" + "math/big" +) + +// s390x accelerated signatures +//go:noescape +func kdsaSig(fc uint64, block *[1720]byte) (errn uint64) + +type signverify int + +const ( + signing signverify = iota + verifying +) + +// bufferOffsets represents the offset of a particular parameter in +// the buffer passed to the KDSA instruction. +type bufferOffsets struct { + baseSize int + hashSize int + offsetHash int + offsetKey1 int + offsetRNorKey2 int + offsetR int + offsetS int + functionCode uint64 +} + +func canUseKDSA(sv signverify, c elliptic.Curve, bo *bufferOffsets) bool { + if !cpu.S390X.HasECDSA { + return false + } + + switch c.Params().Name { + case "P-256": + bo.baseSize = 32 + bo.hashSize = 32 + bo.offsetHash = 64 + bo.offsetKey1 = 96 + bo.offsetRNorKey2 = 128 + bo.offsetR = 0 + bo.offsetS = 32 + if sv == signing { + bo.functionCode = 137 + } else { + bo.functionCode = 1 + } + return true + case "P-384": + bo.baseSize = 48 + bo.hashSize = 48 + bo.offsetHash = 96 + bo.offsetKey1 = 144 + bo.offsetRNorKey2 = 192 + bo.offsetR = 0 + bo.offsetS = 48 + if sv == signing { + bo.functionCode = 138 + } else { + bo.functionCode = 2 + } + return true + case "P-521": + bo.baseSize = 66 + bo.hashSize = 80 + bo.offsetHash = 160 + bo.offsetKey1 = 254 + bo.offsetRNorKey2 = 334 + bo.offsetR = 14 + bo.offsetS = 94 + if sv == signing { + bo.functionCode = 139 + } else { + bo.functionCode = 3 + } + return true + } + return false +} + +// zeroExtendAndCopy pads src with leading zeros until it has the size given. +// It then copies the padded src into the dst. Bytes beyond size in dst are +// not modified. +func zeroExtendAndCopy(dst, src []byte, size int) { + nz := size - len(src) + if nz < 0 { + panic("src is too long") + } + // the compiler should replace this loop with a memclr call + z := dst[:nz] + for i := range z { + z[i] = 0 + } + copy(dst[nz:size], src[:size-nz]) + return +} + +func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, e *big.Int) (r, s *big.Int, err error) { + var bo bufferOffsets + if canUseKDSA(signing, c, &bo) && e.Sign() != 0 { + var buffer [1720]byte + for { + var k *big.Int + k, err = randFieldElement(c, csprng) + if err != nil { + return nil, nil, err + } + zeroExtendAndCopy(buffer[bo.offsetHash:], e.Bytes(), bo.hashSize) + zeroExtendAndCopy(buffer[bo.offsetKey1:], priv.D.Bytes(), bo.baseSize) + zeroExtendAndCopy(buffer[bo.offsetRNorKey2:], k.Bytes(), bo.baseSize) + errn := kdsaSig(bo.functionCode, &buffer) + if errn == 2 { + return nil, nil, errZeroParam + } + if errn == 0 { // success == 0 means successful signing + r = new(big.Int) + r.SetBytes(buffer[bo.offsetR : bo.offsetR+bo.baseSize]) + s = new(big.Int) + s.SetBytes(buffer[bo.offsetS : bo.offsetS+bo.baseSize]) + return + } + //at this point, it must be that errn == 1: retry + } + } + r, s, err = signGeneric(priv, csprng, c, e) + return +} + +func verify(pub *PublicKey, c elliptic.Curve, e, r, s *big.Int) bool { + var bo bufferOffsets + if canUseKDSA(verifying, c, &bo) && e.Sign() != 0 { + var buffer [1720]byte + zeroExtendAndCopy(buffer[bo.offsetR:], r.Bytes(), bo.baseSize) + zeroExtendAndCopy(buffer[bo.offsetS:], s.Bytes(), bo.baseSize) + zeroExtendAndCopy(buffer[bo.offsetHash:], e.Bytes(), bo.hashSize) + zeroExtendAndCopy(buffer[bo.offsetKey1:], pub.X.Bytes(), bo.baseSize) + zeroExtendAndCopy(buffer[bo.offsetRNorKey2:], pub.Y.Bytes(), bo.baseSize) + errn := kdsaSig(bo.functionCode, &buffer) + return errn == 0 + } + return verifyGeneric(pub, c, e, r, s) +} diff --git a/libgo/go/crypto/ecdsa/ecdsa_s390x_test.go b/libgo/go/crypto/ecdsa/ecdsa_s390x_test.go new file mode 100644 index 0000000..80babc9 --- /dev/null +++ b/libgo/go/crypto/ecdsa/ecdsa_s390x_test.go @@ -0,0 +1,33 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build s390x,!gccgo + +package ecdsa + +import ( + "crypto/elliptic" + "testing" +) + +func TestNoAsm(t *testing.T) { + curves := [...]elliptic.Curve{ + elliptic.P256(), + elliptic.P384(), + elliptic.P521(), + } + + for _, curve := range curves { + // override the name of the curve to stop the assembly path being taken + params := *curve.Params() + name := params.Name + params.Name = name + "_GENERIC_OVERRIDE" + + testKeyGeneration(t, ¶ms, name) + testSignAndVerify(t, ¶ms, name) + testNonceSafety(t, ¶ms, name) + testINDCCA(t, ¶ms, name) + testNegativeInputs(t, ¶ms, name) + } +} |