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