mirror of
https://github.com/golang/go
synced 2024-11-23 07:10:05 -07:00
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 <mike.munday@ibm.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
b76e6f8825
commit
943df4f629
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user