1
2
3
4
5 package rsa
6
7 import (
8 "crypto"
9 "crypto/internal/boring"
10 "crypto/internal/fips140/rsa"
11 "crypto/internal/fips140only"
12 "errors"
13 "hash"
14 "io"
15 )
16
17 const (
18
19
20
21
22
23 PSSSaltLengthAuto = 0
24
25
26 PSSSaltLengthEqualsHash = -1
27 )
28
29
30 type PSSOptions struct {
31
32
33
34 SaltLength int
35
36
37
38
39 Hash crypto.Hash
40 }
41
42
43 func (opts *PSSOptions) HashFunc() crypto.Hash {
44 return opts.Hash
45 }
46
47 func (opts *PSSOptions) saltLength() int {
48 if opts == nil {
49 return PSSSaltLengthAuto
50 }
51 return opts.SaltLength
52 }
53
54
55
56
57
58
59
60
61
62
63 func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) {
64 if err := checkPublicKeySize(&priv.PublicKey); err != nil {
65 return nil, err
66 }
67 if err := checkFIPS140OnlyPrivateKey(priv); err != nil {
68 return nil, err
69 }
70 if fips140only.Enabled && !fips140only.ApprovedHash(hash.New()) {
71 return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
72 }
73 if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) {
74 return nil, errors.New("crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode")
75 }
76
77 if opts != nil && opts.Hash != 0 {
78 hash = opts.Hash
79 }
80
81 if boring.Enabled && rand == boring.RandReader {
82 bkey, err := boringPrivateKey(priv)
83 if err != nil {
84 return nil, err
85 }
86 return boring.SignRSAPSS(bkey, hash, digest, opts.saltLength())
87 }
88 boring.UnreachableExceptTests()
89
90 k, err := fipsPrivateKey(priv)
91 if err != nil {
92 return nil, err
93 }
94 h := hash.New()
95
96 saltLength := opts.saltLength()
97 if fips140only.Enabled && saltLength > hash.Size() {
98 return nil, errors.New("crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode")
99 }
100 switch saltLength {
101 case PSSSaltLengthAuto:
102 saltLength, err = rsa.PSSMaxSaltLength(k.PublicKey(), h)
103 if err != nil {
104 return nil, fipsError(err)
105 }
106 case PSSSaltLengthEqualsHash:
107 saltLength = hash.Size()
108 default:
109
110
111 if saltLength <= 0 {
112 return nil, errors.New("crypto/rsa: invalid PSS salt length")
113 }
114 }
115
116 return fipsError2(rsa.SignPSS(rand, k, h, digest, saltLength))
117 }
118
119
120
121
122
123
124
125
126
127
128 func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error {
129 if err := checkPublicKeySize(pub); err != nil {
130 return err
131 }
132 if err := checkFIPS140OnlyPublicKey(pub); err != nil {
133 return err
134 }
135 if fips140only.Enabled && !fips140only.ApprovedHash(hash.New()) {
136 return errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
137 }
138
139 if boring.Enabled {
140 bkey, err := boringPublicKey(pub)
141 if err != nil {
142 return err
143 }
144 if err := boring.VerifyRSAPSS(bkey, hash, digest, sig, opts.saltLength()); err != nil {
145 return ErrVerification
146 }
147 return nil
148 }
149
150 k, err := fipsPublicKey(pub)
151 if err != nil {
152 return err
153 }
154
155 saltLength := opts.saltLength()
156 if fips140only.Enabled && saltLength > hash.Size() {
157 return errors.New("crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode")
158 }
159 switch saltLength {
160 case PSSSaltLengthAuto:
161 return fipsError(rsa.VerifyPSS(k, hash.New(), digest, sig))
162 case PSSSaltLengthEqualsHash:
163 return fipsError(rsa.VerifyPSSWithSaltLength(k, hash.New(), digest, sig, hash.Size()))
164 default:
165 return fipsError(rsa.VerifyPSSWithSaltLength(k, hash.New(), digest, sig, saltLength))
166 }
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error) {
188 if err := checkPublicKeySize(pub); err != nil {
189 return nil, err
190 }
191 if err := checkFIPS140OnlyPublicKey(pub); err != nil {
192 return nil, err
193 }
194 if fips140only.Enabled && !fips140only.ApprovedHash(hash) {
195 return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
196 }
197 if fips140only.Enabled && !fips140only.ApprovedRandomReader(random) {
198 return nil, errors.New("crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode")
199 }
200
201 defer hash.Reset()
202
203 if boring.Enabled && random == boring.RandReader {
204 hash.Reset()
205 k := pub.Size()
206 if len(msg) > k-2*hash.Size()-2 {
207 return nil, ErrMessageTooLong
208 }
209 bkey, err := boringPublicKey(pub)
210 if err != nil {
211 return nil, err
212 }
213 return boring.EncryptRSAOAEP(hash, hash, bkey, msg, label)
214 }
215 boring.UnreachableExceptTests()
216
217 k, err := fipsPublicKey(pub)
218 if err != nil {
219 return nil, err
220 }
221 return fipsError2(rsa.EncryptOAEP(hash, hash, random, k, msg, label))
222 }
223
224
225
226
227
228
229
230
231
232
233
234 func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) {
235 defer hash.Reset()
236 return decryptOAEP(hash, hash, priv, ciphertext, label)
237 }
238
239 func decryptOAEP(hash, mgfHash hash.Hash, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) {
240 if err := checkPublicKeySize(&priv.PublicKey); err != nil {
241 return nil, err
242 }
243 if err := checkFIPS140OnlyPrivateKey(priv); err != nil {
244 return nil, err
245 }
246 if fips140only.Enabled {
247 if !fips140only.ApprovedHash(hash) || !fips140only.ApprovedHash(mgfHash) {
248 return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
249 }
250 }
251
252 if boring.Enabled {
253 k := priv.Size()
254 if len(ciphertext) > k ||
255 k < hash.Size()*2+2 {
256 return nil, ErrDecryption
257 }
258 bkey, err := boringPrivateKey(priv)
259 if err != nil {
260 return nil, err
261 }
262 out, err := boring.DecryptRSAOAEP(hash, mgfHash, bkey, ciphertext, label)
263 if err != nil {
264 return nil, ErrDecryption
265 }
266 return out, nil
267 }
268
269 k, err := fipsPrivateKey(priv)
270 if err != nil {
271 return nil, err
272 }
273
274 return fipsError2(rsa.DecryptOAEP(hash, mgfHash, k, ciphertext, label))
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288
289 func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
290 var hashName string
291 if hash != crypto.Hash(0) {
292 if len(hashed) != hash.Size() {
293 return nil, errors.New("crypto/rsa: input must be hashed message")
294 }
295 hashName = hash.String()
296 }
297
298 if err := checkPublicKeySize(&priv.PublicKey); err != nil {
299 return nil, err
300 }
301 if err := checkFIPS140OnlyPrivateKey(priv); err != nil {
302 return nil, err
303 }
304 if fips140only.Enabled && !fips140only.ApprovedHash(hash.New()) {
305 return nil, errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
306 }
307
308 if boring.Enabled {
309 bkey, err := boringPrivateKey(priv)
310 if err != nil {
311 return nil, err
312 }
313 return boring.SignRSAPKCS1v15(bkey, hash, hashed)
314 }
315
316 k, err := fipsPrivateKey(priv)
317 if err != nil {
318 return nil, err
319 }
320 return fipsError2(rsa.SignPKCS1v15(k, hashName, hashed))
321 }
322
323
324
325
326
327
328
329
330
331 func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error {
332 if err := checkPublicKeySize(pub); err != nil {
333 return err
334 }
335 if err := checkFIPS140OnlyPublicKey(pub); err != nil {
336 return err
337 }
338 if fips140only.Enabled && !fips140only.ApprovedHash(hash.New()) {
339 return errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
340 }
341
342 if boring.Enabled {
343 bkey, err := boringPublicKey(pub)
344 if err != nil {
345 return err
346 }
347 if err := boring.VerifyRSAPKCS1v15(bkey, hash, hashed, sig); err != nil {
348 return ErrVerification
349 }
350 return nil
351 }
352
353 k, err := fipsPublicKey(pub)
354 if err != nil {
355 return err
356 }
357 var hashName string
358 if hash != crypto.Hash(0) {
359 if len(hashed) != hash.Size() {
360 return errors.New("crypto/rsa: input must be hashed message")
361 }
362 hashName = hash.String()
363 }
364 return fipsError(rsa.VerifyPKCS1v15(k, hashName, hashed, sig))
365 }
366
367 func fipsError(err error) error {
368 switch err {
369 case rsa.ErrDecryption:
370 return ErrDecryption
371 case rsa.ErrVerification:
372 return ErrVerification
373 case rsa.ErrMessageTooLong:
374 return ErrMessageTooLong
375 }
376 return err
377 }
378
379 func fipsError2[T any](x T, err error) (T, error) {
380 return x, fipsError(err)
381 }
382
383 func checkFIPS140OnlyPublicKey(pub *PublicKey) error {
384 if !fips140only.Enabled {
385 return nil
386 }
387 if pub.N == nil {
388 return errors.New("crypto/rsa: public key missing N")
389 }
390 if pub.N.BitLen() < 2048 {
391 return errors.New("crypto/rsa: use of keys smaller than 2048 bits is not allowed in FIPS 140-only mode")
392 }
393 if pub.N.BitLen()%2 == 1 {
394 return errors.New("crypto/rsa: use of keys with odd size is not allowed in FIPS 140-only mode")
395 }
396 if pub.E <= 1<<16 {
397 return errors.New("crypto/rsa: use of public exponent <= 2¹⁶ is not allowed in FIPS 140-only mode")
398 }
399 if pub.E&1 == 0 {
400 return errors.New("crypto/rsa: use of even public exponent is not allowed in FIPS 140-only mode")
401 }
402 return nil
403 }
404
405 func checkFIPS140OnlyPrivateKey(priv *PrivateKey) error {
406 if !fips140only.Enabled {
407 return nil
408 }
409 if err := checkFIPS140OnlyPublicKey(&priv.PublicKey); err != nil {
410 return err
411 }
412 if len(priv.Primes) != 2 {
413 return errors.New("crypto/rsa: use of multi-prime keys is not allowed in FIPS 140-only mode")
414 }
415 if priv.Primes[0] == nil || priv.Primes[1] == nil || priv.Primes[0].BitLen() != priv.Primes[1].BitLen() {
416 return errors.New("crypto/rsa: use of primes of different sizes is not allowed in FIPS 140-only mode")
417 }
418 return nil
419 }
420
View as plain text