aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/crypto/ecdsa/ecdsa_s390x.go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2019-09-06 18:12:46 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-09-06 18:12:46 +0000
commitaa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13 (patch)
tree7e63b06d1eec92beec6997c9d3ab47a5d6a835be /libgo/go/crypto/ecdsa/ecdsa_s390x.go
parent920ea3b8ba3164b61ac9490dfdfceb6936eda6dd (diff)
downloadgcc-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/ecdsa_s390x.go')
-rw-r--r--libgo/go/crypto/ecdsa/ecdsa_s390x.go153
1 files changed, 153 insertions, 0 deletions
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)
+}