Source file src/crypto/ecdsa/ecdsa_s390x.go
1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ecdsa 6 7 import ( 8 "crypto/cipher" 9 "crypto/elliptic" 10 "internal/cpu" 11 "math/big" 12 ) 13 14 // kdsa invokes the "compute digital signature authentication" 15 // instruction with the given function code and 4096 byte 16 // parameter block. 17 // 18 // The return value corresponds to the condition code set by the 19 // instruction. Interrupted invocations are handled by the 20 // function. 21 //go:noescape 22 func kdsa(fc uint64, params *[4096]byte) (errn uint64) 23 24 // testingDisableKDSA forces the generic fallback path. It must only be set in tests. 25 var testingDisableKDSA bool 26 27 // canUseKDSA checks if KDSA instruction is available, and if it is, it checks 28 // the name of the curve to see if it matches the curves supported(P-256, P-384, P-521). 29 // Then, based on the curve name, a function code and a block size will be assigned. 30 // If KDSA instruction is not available or if the curve is not supported, canUseKDSA 31 // will set ok to false. 32 func canUseKDSA(c elliptic.Curve) (functionCode uint64, blockSize int, ok bool) { 33 if testingDisableKDSA { 34 return 0, 0, false 35 } 36 if !cpu.S390X.HasECDSA { 37 return 0, 0, false 38 } 39 switch c.Params().Name { 40 case "P-256": 41 return 1, 32, true 42 case "P-384": 43 return 2, 48, true 44 case "P-521": 45 return 3, 80, true 46 } 47 return 0, 0, false // A mismatch 48 } 49 50 func hashToBytes(dst, hash []byte, c elliptic.Curve) { 51 l := len(dst) 52 if n := c.Params().N.BitLen(); n == l*8 { 53 // allocation free path for curves with a length that is a whole number of bytes 54 if len(hash) >= l { 55 // truncate hash 56 copy(dst, hash[:l]) 57 return 58 } 59 // pad hash with leading zeros 60 p := l - len(hash) 61 for i := 0; i < p; i++ { 62 dst[i] = 0 63 } 64 copy(dst[p:], hash) 65 return 66 } 67 // TODO(mundaym): avoid hashToInt call here 68 hashToInt(hash, c).FillBytes(dst) 69 } 70 71 func sign(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash []byte) (r, s *big.Int, err error) { 72 if functionCode, blockSize, ok := canUseKDSA(c); ok { 73 for { 74 var k *big.Int 75 k, err = randFieldElement(c, *csprng) 76 if err != nil { 77 return nil, nil, err 78 } 79 80 // The parameter block looks like the following for sign. 81 // +---------------------+ 82 // | Signature(R) | 83 // +---------------------+ 84 // | Signature(S) | 85 // +---------------------+ 86 // | Hashed Message | 87 // +---------------------+ 88 // | Private Key | 89 // +---------------------+ 90 // | Random Number | 91 // +---------------------+ 92 // | | 93 // | ... | 94 // | | 95 // +---------------------+ 96 // The common components(signatureR, signatureS, hashedMessage, privateKey and 97 // random number) each takes block size of bytes. The block size is different for 98 // different curves and is set by canUseKDSA function. 99 var params [4096]byte 100 101 // Copy content into the parameter block. In the sign case, 102 // we copy hashed message, private key and random number into 103 // the parameter block. 104 hashToBytes(params[2*blockSize:3*blockSize], hash, c) 105 priv.D.FillBytes(params[3*blockSize : 4*blockSize]) 106 k.FillBytes(params[4*blockSize : 5*blockSize]) 107 // Convert verify function code into a sign function code by adding 8. 108 // We also need to set the 'deterministic' bit in the function code, by 109 // adding 128, in order to stop the instruction using its own random number 110 // generator in addition to the random number we supply. 111 switch kdsa(functionCode+136, ¶ms) { 112 case 0: // success 113 r = new(big.Int) 114 r.SetBytes(params[:blockSize]) 115 s = new(big.Int) 116 s.SetBytes(params[blockSize : 2*blockSize]) 117 return 118 case 1: // error 119 return nil, nil, errZeroParam 120 case 2: // retry 121 continue 122 } 123 panic("unreachable") 124 } 125 } 126 return signGeneric(priv, csprng, c, hash) 127 } 128 129 func verify(pub *PublicKey, c elliptic.Curve, hash []byte, r, s *big.Int) bool { 130 if functionCode, blockSize, ok := canUseKDSA(c); ok { 131 // The parameter block looks like the following for verify: 132 // +---------------------+ 133 // | Signature(R) | 134 // +---------------------+ 135 // | Signature(S) | 136 // +---------------------+ 137 // | Hashed Message | 138 // +---------------------+ 139 // | Public Key X | 140 // +---------------------+ 141 // | Public Key Y | 142 // +---------------------+ 143 // | | 144 // | ... | 145 // | | 146 // +---------------------+ 147 // The common components(signatureR, signatureS, hashed message, public key X, 148 // and public key Y) each takes block size of bytes. The block size is different for 149 // different curves and is set by canUseKDSA function. 150 var params [4096]byte 151 152 // Copy content into the parameter block. In the verify case, 153 // we copy signature (r), signature(s), hashed message, public key x component, 154 // and public key y component into the parameter block. 155 r.FillBytes(params[0*blockSize : 1*blockSize]) 156 s.FillBytes(params[1*blockSize : 2*blockSize]) 157 hashToBytes(params[2*blockSize:3*blockSize], hash, c) 158 pub.X.FillBytes(params[3*blockSize : 4*blockSize]) 159 pub.Y.FillBytes(params[4*blockSize : 5*blockSize]) 160 return kdsa(functionCode, ¶ms) == 0 161 } 162 return verifyGeneric(pub, c, hash, r, s) 163 } 164