From 943df4f629560f5c33474dd82e2b534ea5f8653f Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Wed, 16 Oct 2019 21:49:09 +0100 Subject: [PATCH] crypto/ecdsa: remove s390x assembly This a revert of CL 174437 and follow up fix CL 201317. The s390x assembly in this package makes use of an instruction (specifically KDSA) which is not supported by the current build machine. Remove this assembly for now, we can revisit this functionality once we have a newer build machine and can ensure that this assembly is well tested. Updates #34927. Change-Id: I779286fa7d9530a254b53a515ee76b1218821f2f Reviewed-on: https://go-review.googlesource.com/c/go/+/201360 Run-TryBot: Michael Munday TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- src/crypto/ecdsa/ecdsa.go | 16 +-- src/crypto/ecdsa/ecdsa_noasm.go | 22 ---- src/crypto/ecdsa/ecdsa_s390x.go | 153 --------------------------- src/crypto/ecdsa/ecdsa_s390x.s | 31 ------ src/crypto/ecdsa/ecdsa_s390x_test.go | 33 ------ 5 files changed, 4 insertions(+), 251 deletions(-) delete mode 100644 src/crypto/ecdsa/ecdsa_noasm.go delete mode 100644 src/crypto/ecdsa/ecdsa_s390x.go delete mode 100644 src/crypto/ecdsa/ecdsa_s390x.s delete mode 100644 src/crypto/ecdsa/ecdsa_s390x_test.go diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go index d1c7975aa9..65911e737a 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go @@ -199,21 +199,14 @@ 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 @@ -231,6 +224,8 @@ func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve break } } + + e := hashToInt(hash, c) s = new(big.Int).Mul(priv.D, r) s.Add(s, e) s.Mul(s, kInv) @@ -239,6 +234,7 @@ func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve break } } + return } @@ -256,12 +252,8 @@ 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/src/crypto/ecdsa/ecdsa_noasm.go b/src/crypto/ecdsa/ecdsa_noasm.go deleted file mode 100644 index 2dfdb866d6..0000000000 --- a/src/crypto/ecdsa/ecdsa_noasm.go +++ /dev/null @@ -1,22 +0,0 @@ -// 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 - -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/src/crypto/ecdsa/ecdsa_s390x.go b/src/crypto/ecdsa/ecdsa_s390x.go deleted file mode 100644 index 485f5fe971..0000000000 --- a/src/crypto/ecdsa/ecdsa_s390x.go +++ /dev/null @@ -1,153 +0,0 @@ -// 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 *[4096]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 [4096]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 [4096]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/src/crypto/ecdsa/ecdsa_s390x.s b/src/crypto/ecdsa/ecdsa_s390x.s deleted file mode 100644 index c064400709..0000000000 --- a/src/crypto/ecdsa/ecdsa_s390x.s +++ /dev/null @@ -1,31 +0,0 @@ -// 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. - -#include "textflag.h" - -// func kdsaSig(fc uint64, block *[4096]byte) (errn uint64) -TEXT ·kdsaSig(SB), NOSPLIT|NOFRAME, $0-24 - MOVD fc+0(FP), R0 // function code - MOVD block+8(FP), R1 // address parameter block - -loop: - WORD $0xB93A0008 // compute digital signature authentication - BVS loop // branch back if interrupted - BEQ success // signature creation successful - BGT retry // signing unsuccessful, but retry with new CSPRN - -error: - MOVD $2, R2 // fallthrough indicates fatal error - MOVD R2, errn+16(FP) // return 2 - sign/verify abort - RET - -retry: - MOVD $1, R2 - MOVD R2, errn+16(FP) // return 1 - sign/verify was unsuccessful -- if sign, retry with new RN - RET - -success: - MOVD $0, R2 - MOVD R2, errn+16(FP) // return 0 - sign/verify was successful - RET diff --git a/src/crypto/ecdsa/ecdsa_s390x_test.go b/src/crypto/ecdsa/ecdsa_s390x_test.go deleted file mode 100644 index 80babc9cb4..0000000000 --- a/src/crypto/ecdsa/ecdsa_s390x_test.go +++ /dev/null @@ -1,33 +0,0 @@ -// 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) - } -}