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