1
2
3
4
5
6
7 package ecdsa
8
9 import (
10 "crypto/internal/fips140/bigmod"
11 "crypto/internal/fips140deps/cpu"
12 "crypto/internal/impl"
13 "errors"
14 )
15
16
17
18
19
20
21
22
23
24
25 func kdsa(fc uint64, params *[4096]byte) (errn uint64)
26
27 var supportsKDSA = cpu.S390XHasECDSA
28
29 func init() {
30
31
32 impl.Register("ecdsa", "CPACF", &supportsKDSA)
33 }
34
35
36
37
38
39
40 func canUseKDSA(c curveID) (functionCode uint64, blockSize int, ok bool) {
41 if !supportsKDSA {
42 return 0, 0, false
43 }
44 switch c {
45 case p256:
46 return 1, 32, true
47 case p384:
48 return 2, 48, true
49 case p521:
50
51 return 3, 80, true
52 }
53 return 0, 0, false
54 }
55
56 func hashToBytes[P Point[P]](c *Curve[P], hash []byte) []byte {
57 e := bigmod.NewNat()
58 hashToNat(c, e, hash)
59 return e.Bytes(c.N)
60 }
61
62
63 func randomScalar[P Point[P]](c *Curve[P], generate func([]byte) error) (k *bigmod.Nat, err error) {
64 for {
65 b := make([]byte, c.N.Size())
66 if err := generate(b); err != nil {
67 return nil, err
68 }
69 if excess := len(b)*8 - c.N.BitLen(); excess > 0 {
70 if c.curve != p521 {
71 panic("ecdsa: internal error: unexpectedly masking off bits")
72 }
73 b = rightShift(b, excess)
74 }
75 if k, err := bigmod.NewNat().SetBytes(b, c.N); err == nil && k.IsZero() == 0 {
76 return k, nil
77 }
78 }
79 }
80
81 func appendBlock(p []byte, blocksize int, b []byte) []byte {
82 if len(b) > blocksize {
83 panic("ecdsa: internal error: appendBlock input larger than block")
84 }
85 padding := blocksize - len(b)
86 p = append(p, make([]byte, padding)...)
87 return append(p, b...)
88 }
89
90 func trimBlock(p []byte, size int) ([]byte, error) {
91 for _, b := range p[:len(p)-size] {
92 if b != 0 {
93 return nil, errors.New("ecdsa: internal error: KDSA produced invalid signature")
94 }
95 }
96 return p[len(p)-size:], nil
97 }
98
99 func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte) (*Signature, error) {
100 functionCode, blockSize, ok := canUseKDSA(c.curve)
101 if !ok {
102 return signGeneric(c, priv, drbg, hash)
103 }
104 for {
105 k, err := randomScalar(c, func(b []byte) error {
106 drbg.Generate(b)
107 return nil
108 })
109 if err != nil {
110 return nil, err
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 var params [4096]byte
133
134
135
136
137 p := params[:2*blockSize]
138 p = appendBlock(p, blockSize, hashToBytes(c, hash))
139 p = appendBlock(p, blockSize, priv.d)
140 p = appendBlock(p, blockSize, k.Bytes(c.N))
141
142
143
144
145 switch kdsa(functionCode+136, ¶ms) {
146 case 0:
147 elementSize := (c.N.BitLen() + 7) / 8
148 r, err := trimBlock(params[:blockSize], elementSize)
149 if err != nil {
150 return nil, err
151 }
152 s, err := trimBlock(params[blockSize:2*blockSize], elementSize)
153 if err != nil {
154 return nil, err
155 }
156 return &Signature{R: r, S: s}, nil
157 case 1:
158 return nil, errors.New("zero parameter")
159 case 2:
160 continue
161 }
162 }
163 }
164
165 func verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error {
166 functionCode, blockSize, ok := canUseKDSA(c.curve)
167 if !ok {
168 return verifyGeneric(c, pub, hash, sig)
169 }
170
171 r, s := sig.R, sig.S
172 if len(r) > blockSize || len(s) > blockSize {
173 return errors.New("invalid signature")
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195 var params [4096]byte
196
197
198
199
200 p := params[:0]
201 p = appendBlock(p, blockSize, r)
202 p = appendBlock(p, blockSize, s)
203 p = appendBlock(p, blockSize, hashToBytes(c, hash))
204 p = appendBlock(p, blockSize, pub.q[1:1+len(pub.q)/2])
205 p = appendBlock(p, blockSize, pub.q[1+len(pub.q)/2:])
206 if kdsa(functionCode, ¶ms) != 0 {
207 return errors.New("invalid signature")
208 }
209 return nil
210 }
211
View as plain text