mirror of
https://github.com/golang/go
synced 2024-11-17 10:14:46 -07:00
crypto/ecdsa: use FillBytes on s390x
Originally, zeroExtendAndCopy is used to pad src with leading zeros and copy the padded src into the destination. It is no longer needed after CL 230397 introduced FillBytes. We can simply use that and remove the zeroExtendAndCopy function. It is cleaner and reduces some allocation. In addition, this patch tries to avoid calling hashToInt function in both Sign and Verify function so some allocation is reduced. Benchmarks: name old alloc/op new alloc/op delta SignP256-8 1.60kB ± 0% 1.49kB ± 0% -7.23% (p=0.000 n=20+20) SignP384-8 1.74kB ± 0% 1.59kB ± 0% -8.50% (p=0.000 n=20+18) VerifyP256-8 176B ± 0% 0B -100.00% (p=0.000 n=20+20) KeyGeneration-8 640B ± 0% 640B ± 0% ~ (all equal) name old allocs/op new allocs/op delta SignP256-8 22.0 ± 0% 17.0 ± 0% -22.73% (p=0.000 n=20+20) SignP384-8 22.0 ± 0% 17.0 ± 0% -22.73% (p=0.000 n=20+20) VerifyP256-8 7.00 ± 0% 0.00 -100.00% (p=0.000 n=20+20) KeyGeneration-8 13.0 ± 0% 13.0 ± 0% ~ (all equal) Change-Id: Ic4c95191eded55deb3420d97db501689f3b173c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/232297 Reviewed-by: Michael Munday <mike.munday@ibm.com> Run-TryBot: Michael Munday <mike.munday@ibm.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Filippo Valsorda <filippo@golang.org>
This commit is contained in:
parent
8b0d00b164
commit
54a112d719
@ -41,26 +41,29 @@ func canUseKDSA(c elliptic.Curve) (functionCode uint64, blockSize int, ok bool)
|
||||
return 0, 0, false // A mismatch
|
||||
}
|
||||
|
||||
// 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")
|
||||
func hashToBytes(dst, hash []byte, c elliptic.Curve) {
|
||||
l := len(dst)
|
||||
if n := c.Params().N.BitLen(); n == l*8 {
|
||||
// allocation free path for curves with a length that is a whole number of bytes
|
||||
if len(hash) >= l {
|
||||
// truncate hash
|
||||
copy(dst, hash[:l])
|
||||
return
|
||||
}
|
||||
// pad hash with leading zeros
|
||||
p := l - len(hash)
|
||||
for i := 0; i < p; i++ {
|
||||
dst[i] = 0
|
||||
}
|
||||
copy(dst[p:], hash)
|
||||
return
|
||||
}
|
||||
// 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
|
||||
// TODO(mundaym): avoid hashToInt call here
|
||||
hashToInt(hash, c).FillBytes(dst)
|
||||
}
|
||||
|
||||
func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash []byte) (r, s *big.Int, err error) {
|
||||
if functionCode, blockSize, ok := canUseKDSA(c); ok {
|
||||
e := hashToInt(hash, c)
|
||||
for {
|
||||
var k *big.Int
|
||||
k, err = randFieldElement(c, *csprng)
|
||||
@ -89,17 +92,12 @@ func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash
|
||||
// different curves and is set by canUseKDSA function.
|
||||
var params [4096]byte
|
||||
|
||||
startingOffset := 2 * blockSize // Set the starting location for copying
|
||||
// Copy content into the parameter block. In the sign case,
|
||||
// we copy hashed message, private key and random number into
|
||||
// the parameter block. Since those are consecutive components in the parameter
|
||||
// block, we use a for loop here.
|
||||
for i, v := range []*big.Int{e, priv.D, k} {
|
||||
startPosition := startingOffset + i*blockSize
|
||||
endPosition := startPosition + blockSize
|
||||
zeroExtendAndCopy(params[startPosition:endPosition], v.Bytes(), blockSize)
|
||||
}
|
||||
|
||||
// the parameter block.
|
||||
hashToBytes(params[2*blockSize:3*blockSize], hash, c)
|
||||
priv.D.FillBytes(params[3*blockSize : 4*blockSize])
|
||||
k.FillBytes(params[4*blockSize : 5*blockSize])
|
||||
// Convert verify function code into a sign function code by adding 8.
|
||||
// We also need to set the 'deterministic' bit in the function code, by
|
||||
// adding 128, in order to stop the instruction using its own random number
|
||||
@ -124,7 +122,6 @@ func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash
|
||||
|
||||
func verify(pub *PublicKey, c elliptic.Curve, hash []byte, r, s *big.Int) bool {
|
||||
if functionCode, blockSize, ok := canUseKDSA(c); ok {
|
||||
e := hashToInt(hash, c)
|
||||
// The parameter block looks like the following for verify:
|
||||
// +---------------------+
|
||||
// | Signature(R) |
|
||||
@ -149,13 +146,11 @@ func verify(pub *PublicKey, c elliptic.Curve, hash []byte, r, s *big.Int) bool {
|
||||
// Copy content into the parameter block. In the verify case,
|
||||
// we copy signature (r), signature(s), hashed message, public key x component,
|
||||
// and public key y component into the parameter block.
|
||||
// Since those are consecutive components in the parameter block, we use a for loop here.
|
||||
for i, v := range []*big.Int{r, s, e, pub.X, pub.Y} {
|
||||
startPosition := i * blockSize
|
||||
endPosition := startPosition + blockSize
|
||||
zeroExtendAndCopy(params[startPosition:endPosition], v.Bytes(), blockSize)
|
||||
}
|
||||
|
||||
r.FillBytes(params[0*blockSize : 1*blockSize])
|
||||
s.FillBytes(params[1*blockSize : 2*blockSize])
|
||||
hashToBytes(params[2*blockSize:3*blockSize], hash, c)
|
||||
pub.X.FillBytes(params[3*blockSize : 4*blockSize])
|
||||
pub.Y.FillBytes(params[4*blockSize : 5*blockSize])
|
||||
return kdsa(functionCode, ¶ms) == 0
|
||||
}
|
||||
return verifyGeneric(pub, c, hash, r, s)
|
||||
|
Loading…
Reference in New Issue
Block a user