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