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 func appendBlock(p []byte, blocksize int, b []byte) []byte {
63 if len(b) > blocksize {
64 panic("ecdsa: internal error: appendBlock input larger than block")
65 }
66 padding := blocksize - len(b)
67 p = append(p, make([]byte, padding)...)
68 return append(p, b...)
69 }
70
71 func trimBlock(p []byte, size int) ([]byte, error) {
72 for _, b := range p[:len(p)-size] {
73 if b != 0 {
74 return nil, errors.New("ecdsa: internal error: KDSA produced invalid signature")
75 }
76 }
77 return p[len(p)-size:], nil
78 }
79
80 func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte) (*Signature, error) {
81 functionCode, blockSize, ok := canUseKDSA(c.curve)
82 if !ok {
83 return signGeneric(c, priv, drbg, hash)
84 }
85 for {
86 k, _, err := randomPoint(c, func(b []byte) error {
87 drbg.Generate(b)
88 return nil
89 })
90 if err != nil {
91 return nil, err
92 }
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113 var params [4096]byte
114
115
116
117
118 p := params[:2*blockSize]
119 p = appendBlock(p, blockSize, hashToBytes(c, hash))
120 p = appendBlock(p, blockSize, priv.d)
121 p = appendBlock(p, blockSize, k.Bytes(c.N))
122
123
124
125
126 switch kdsa(functionCode+136, ¶ms) {
127 case 0:
128 elementSize := (c.N.BitLen() + 7) / 8
129 r, err := trimBlock(params[:blockSize], elementSize)
130 if err != nil {
131 return nil, err
132 }
133 s, err := trimBlock(params[blockSize:2*blockSize], elementSize)
134 if err != nil {
135 return nil, err
136 }
137 return &Signature{R: r, S: s}, nil
138 case 1:
139 return nil, errors.New("zero parameter")
140 case 2:
141 continue
142 }
143 }
144 }
145
146 func verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature) error {
147 functionCode, blockSize, ok := canUseKDSA(c.curve)
148 if !ok {
149 return verifyGeneric(c, pub, hash, sig)
150 }
151
152 r, s := sig.R, sig.S
153 if len(r) > blockSize || len(s) > blockSize {
154 return errors.New("invalid signature")
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 var params [4096]byte
177
178
179
180
181 p := params[:0]
182 p = appendBlock(p, blockSize, r)
183 p = appendBlock(p, blockSize, s)
184 p = appendBlock(p, blockSize, hashToBytes(c, hash))
185 p = appendBlock(p, blockSize, pub.q[1:1+len(pub.q)/2])
186 p = appendBlock(p, blockSize, pub.q[1+len(pub.q)/2:])
187 if kdsa(functionCode, ¶ms) != 0 {
188 return errors.New("invalid signature")
189 }
190 return nil
191 }
192
View as plain text