1 // Copyright 2024 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 rsa
6 7 import (
8 "crypto"
9 "crypto/internal/boring"
10 "crypto/internal/fips140/rsa"
11 "crypto/internal/fips140hash"
12 "crypto/internal/fips140only"
13 "errors"
14 "hash"
15 "io"
16 )
17 18 const (
19 // PSSSaltLengthAuto causes the salt in a PSS signature to be as large
20 // as possible when signing, and to be auto-detected when verifying.
21 //
22 // When signing in FIPS 140-3 mode, the salt length is capped at the length
23 // of the hash function used in the signature.
24 PSSSaltLengthAuto = 0
25 // PSSSaltLengthEqualsHash causes the salt length to equal the length
26 // of the hash used in the signature.
27 PSSSaltLengthEqualsHash = -1
28 )
29 30 // PSSOptions contains options for creating and verifying PSS signatures.
31 type PSSOptions struct {
32 // SaltLength controls the length of the salt used in the PSS signature. It
33 // can either be a positive number of bytes, or one of the special
34 // PSSSaltLength constants.
35 SaltLength int
36 37 // Hash is the hash function used to generate the message digest. If not
38 // zero, it overrides the hash function passed to SignPSS. It's required
39 // when using PrivateKey.Sign.
40 Hash crypto.Hash
41 }
42 43 // HashFunc returns opts.Hash so that [PSSOptions] implements [crypto.SignerOpts].
44 func (opts *PSSOptions) HashFunc() crypto.Hash {
45 return opts.Hash
46 }
47 48 func (opts *PSSOptions) saltLength() int {
49 if opts == nil {
50 return PSSSaltLengthAuto
51 }
52 return opts.SaltLength
53 }
54 55 // SignPSS calculates the signature of digest using PSS.
56 //
57 // digest must be the result of hashing the input message using the given hash
58 // function. The opts argument may be nil, in which case sensible defaults are
59 // used. If opts.Hash is set, it overrides hash.
60 //
61 // The signature is randomized depending on the message, key, and salt size,
62 // using bytes from rand. Most applications should use [crypto/rand.Reader] as
63 // rand.
64 func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) {
65 if err := checkPublicKeySize(&priv.PublicKey); err != nil {
66 return nil, err
67 }
68 69 if opts != nil && opts.Hash != 0 {
70 hash = opts.Hash
71 }
72 73 if boring.Enabled && rand == boring.RandReader {
74 bkey, err := boringPrivateKey(priv)
75 if err != nil {
76 return nil, err
77 }
78 return boring.SignRSAPSS(bkey, hash, digest, opts.saltLength())
79 }
80 boring.UnreachableExceptTests()
81 82 h := fips140hash.Unwrap(hash.New())
83 84 if err := checkFIPS140OnlyPrivateKey(priv); err != nil {
85 return nil, err
86 }
87 if fips140only.Enabled && !fips140only.ApprovedHash(h) {
88 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")
89 }
90 if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) {
91 return nil, errors.New("crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode")
92 }
93 94 k, err := fipsPrivateKey(priv)
95 if err != nil {
96 return nil, err
97 }
98 99 saltLength := opts.saltLength()
100 if fips140only.Enabled && saltLength > h.Size() {
101 return nil, errors.New("crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode")
102 }
103 switch saltLength {
104 case PSSSaltLengthAuto:
105 saltLength, err = rsa.PSSMaxSaltLength(k.PublicKey(), h)
106 if err != nil {
107 return nil, fipsError(err)
108 }
109 case PSSSaltLengthEqualsHash:
110 saltLength = h.Size()
111 default:
112 // If we get here saltLength is either > 0 or < -1, in the
113 // latter case we fail out.
114 if saltLength <= 0 {
115 return nil, errors.New("crypto/rsa: invalid PSS salt length")
116 }
117 }
118 119 return fipsError2(rsa.SignPSS(rand, k, h, digest, saltLength))
120 }
121 122 // VerifyPSS verifies a PSS signature.
123 //
124 // A valid signature is indicated by returning a nil error. digest must be the
125 // result of hashing the input message using the given hash function. The opts
126 // argument may be nil, in which case sensible defaults are used. opts.Hash is
127 // ignored.
128 //
129 // The inputs are not considered confidential, and may leak through timing side
130 // channels, or if an attacker has control of part of the inputs.
131 func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error {
132 if err := checkPublicKeySize(pub); err != nil {
133 return err
134 }
135 136 if boring.Enabled {
137 bkey, err := boringPublicKey(pub)
138 if err != nil {
139 return err
140 }
141 if err := boring.VerifyRSAPSS(bkey, hash, digest, sig, opts.saltLength()); err != nil {
142 return ErrVerification
143 }
144 return nil
145 }
146 147 h := fips140hash.Unwrap(hash.New())
148 149 if err := checkFIPS140OnlyPublicKey(pub); err != nil {
150 return err
151 }
152 if fips140only.Enabled && !fips140only.ApprovedHash(h) {
153 return errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
154 }
155 156 k, err := fipsPublicKey(pub)
157 if err != nil {
158 return err
159 }
160 161 saltLength := opts.saltLength()
162 if fips140only.Enabled && saltLength > h.Size() {
163 return errors.New("crypto/rsa: use of PSS salt longer than the hash is not allowed in FIPS 140-only mode")
164 }
165 switch saltLength {
166 case PSSSaltLengthAuto:
167 return fipsError(rsa.VerifyPSS(k, h, digest, sig))
168 case PSSSaltLengthEqualsHash:
169 return fipsError(rsa.VerifyPSSWithSaltLength(k, h, digest, sig, h.Size()))
170 default:
171 return fipsError(rsa.VerifyPSSWithSaltLength(k, h, digest, sig, saltLength))
172 }
173 }
174 175 // EncryptOAEP encrypts the given message with RSA-OAEP.
176 //
177 // OAEP is parameterised by a hash function that is used as a random oracle.
178 // Encryption and decryption of a given message must use the same hash function
179 // and sha256.New() is a reasonable choice.
180 //
181 // The random parameter is used as a source of entropy to ensure that
182 // encrypting the same message twice doesn't result in the same ciphertext.
183 // Most applications should use [crypto/rand.Reader] as random.
184 //
185 // The label parameter may contain arbitrary data that will not be encrypted,
186 // but which gives important context to the message. For example, if a given
187 // public key is used to encrypt two types of messages then distinct label
188 // values could be used to ensure that a ciphertext for one purpose cannot be
189 // used for another by an attacker. If not required it can be empty.
190 //
191 // The message must be no longer than the length of the public modulus minus
192 // twice the hash length, minus a further 2.
193 func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error) {
194 if err := checkPublicKeySize(pub); err != nil {
195 return nil, err
196 }
197 198 defer hash.Reset()
199 200 if boring.Enabled && random == boring.RandReader {
201 hash.Reset()
202 k := pub.Size()
203 if len(msg) > k-2*hash.Size()-2 {
204 return nil, ErrMessageTooLong
205 }
206 bkey, err := boringPublicKey(pub)
207 if err != nil {
208 return nil, err
209 }
210 return boring.EncryptRSAOAEP(hash, hash, bkey, msg, label)
211 }
212 boring.UnreachableExceptTests()
213 214 hash = fips140hash.Unwrap(hash)
215 216 if err := checkFIPS140OnlyPublicKey(pub); err != nil {
217 return nil, err
218 }
219 if fips140only.Enabled && !fips140only.ApprovedHash(hash) {
220 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")
221 }
222 if fips140only.Enabled && !fips140only.ApprovedRandomReader(random) {
223 return nil, errors.New("crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode")
224 }
225 226 k, err := fipsPublicKey(pub)
227 if err != nil {
228 return nil, err
229 }
230 return fipsError2(rsa.EncryptOAEP(hash, hash, random, k, msg, label))
231 }
232 233 // DecryptOAEP decrypts ciphertext using RSA-OAEP.
234 //
235 // OAEP is parameterised by a hash function that is used as a random oracle.
236 // Encryption and decryption of a given message must use the same hash function
237 // and sha256.New() is a reasonable choice.
238 //
239 // The random parameter is legacy and ignored, and it can be nil.
240 //
241 // The label parameter must match the value given when encrypting. See
242 // [EncryptOAEP] for details.
243 func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) {
244 defer hash.Reset()
245 return decryptOAEP(hash, hash, priv, ciphertext, label)
246 }
247 248 func decryptOAEP(hash, mgfHash hash.Hash, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error) {
249 if err := checkPublicKeySize(&priv.PublicKey); err != nil {
250 return nil, err
251 }
252 253 if boring.Enabled {
254 k := priv.Size()
255 if len(ciphertext) > k ||
256 k < hash.Size()*2+2 {
257 return nil, ErrDecryption
258 }
259 bkey, err := boringPrivateKey(priv)
260 if err != nil {
261 return nil, err
262 }
263 out, err := boring.DecryptRSAOAEP(hash, mgfHash, bkey, ciphertext, label)
264 if err != nil {
265 return nil, ErrDecryption
266 }
267 return out, nil
268 }
269 270 hash = fips140hash.Unwrap(hash)
271 mgfHash = fips140hash.Unwrap(mgfHash)
272 273 if err := checkFIPS140OnlyPrivateKey(priv); err != nil {
274 return nil, err
275 }
276 if fips140only.Enabled {
277 if !fips140only.ApprovedHash(hash) || !fips140only.ApprovedHash(mgfHash) {
278 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")
279 }
280 }
281 282 k, err := fipsPrivateKey(priv)
283 if err != nil {
284 return nil, err
285 }
286 287 return fipsError2(rsa.DecryptOAEP(hash, mgfHash, k, ciphertext, label))
288 }
289 290 // SignPKCS1v15 calculates the signature of hashed using
291 // RSASSA-PKCS1-V1_5-SIGN from RSA PKCS #1 v1.5. Note that hashed must
292 // be the result of hashing the input message using the given hash
293 // function. If hash is zero, hashed is signed directly. This isn't
294 // advisable except for interoperability.
295 //
296 // The random parameter is legacy and ignored, and it can be nil.
297 //
298 // This function is deterministic. Thus, if the set of possible
299 // messages is small, an attacker may be able to build a map from
300 // messages to signatures and identify the signed messages. As ever,
301 // signatures provide authenticity, not confidentiality.
302 func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) {
303 var hashName []byte
304 if hash != crypto.Hash(0) {
305 if len(hashed) != hash.Size() {
306 return nil, errors.New("crypto/rsa: input must be hashed message")
307 }
308 hashName = hash.String()
309 }
310 311 if err := checkPublicKeySize(&priv.PublicKey); err != nil {
312 return nil, err
313 }
314 315 if boring.Enabled {
316 bkey, err := boringPrivateKey(priv)
317 if err != nil {
318 return nil, err
319 }
320 return boring.SignRSAPKCS1v15(bkey, hash, hashed)
321 }
322 323 if err := checkFIPS140OnlyPrivateKey(priv); err != nil {
324 return nil, err
325 }
326 if fips140only.Enabled && !fips140only.ApprovedHash(fips140hash.Unwrap(hash.New())) {
327 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")
328 }
329 330 k, err := fipsPrivateKey(priv)
331 if err != nil {
332 return nil, err
333 }
334 return fipsError2(rsa.SignPKCS1v15(k, hashName, hashed))
335 }
336 337 // VerifyPKCS1v15 verifies an RSA PKCS #1 v1.5 signature.
338 // hashed is the result of hashing the input message using the given hash
339 // function and sig is the signature. A valid signature is indicated by
340 // returning a nil error. If hash is zero then hashed is used directly. This
341 // isn't advisable except for interoperability.
342 //
343 // The inputs are not considered confidential, and may leak through timing side
344 // channels, or if an attacker has control of part of the inputs.
345 func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error {
346 var hashName []byte
347 if hash != crypto.Hash(0) {
348 if len(hashed) != hash.Size() {
349 return errors.New("crypto/rsa: input must be hashed message")
350 }
351 hashName = hash.String()
352 }
353 354 if err := checkPublicKeySize(pub); err != nil {
355 return err
356 }
357 358 if boring.Enabled {
359 bkey, err := boringPublicKey(pub)
360 if err != nil {
361 return err
362 }
363 if err := boring.VerifyRSAPKCS1v15(bkey, hash, hashed, sig); err != nil {
364 return ErrVerification
365 }
366 return nil
367 }
368 369 if err := checkFIPS140OnlyPublicKey(pub); err != nil {
370 return err
371 }
372 if fips140only.Enabled && !fips140only.ApprovedHash(fips140hash.Unwrap(hash.New())) {
373 return errors.New("crypto/rsa: use of hash functions other than SHA-2 or SHA-3 is not allowed in FIPS 140-only mode")
374 }
375 376 k, err := fipsPublicKey(pub)
377 if err != nil {
378 return err
379 }
380 return fipsError(rsa.VerifyPKCS1v15(k, hashName, hashed, sig))
381 }
382 383 func fipsError(err error) error {
384 switch err {
385 case rsa.ErrDecryption:
386 return ErrDecryption
387 case rsa.ErrVerification:
388 return ErrVerification
389 case rsa.ErrMessageTooLong:
390 return ErrMessageTooLong
391 }
392 return err
393 }
394 395 func fipsError2[T any](x T, err error) (T, error) {
396 return x, fipsError(err)
397 }
398 399 func checkFIPS140OnlyPublicKey(pub *PublicKey) error {
400 if !fips140only.Enabled {
401 return nil
402 }
403 if pub.N == nil {
404 return errors.New("crypto/rsa: public key missing N")
405 }
406 if pub.N.BitLen() < 2048 {
407 return errors.New("crypto/rsa: use of keys smaller than 2048 bits is not allowed in FIPS 140-only mode")
408 }
409 if pub.N.BitLen()%2 == 1 {
410 return errors.New("crypto/rsa: use of keys with odd size is not allowed in FIPS 140-only mode")
411 }
412 if pub.E <= 1<<16 {
413 return errors.New("crypto/rsa: use of public exponent <= 2¹⁶ is not allowed in FIPS 140-only mode")
414 }
415 if pub.E&1 == 0 {
416 return errors.New("crypto/rsa: use of even public exponent is not allowed in FIPS 140-only mode")
417 }
418 return nil
419 }
420 421 func checkFIPS140OnlyPrivateKey(priv *PrivateKey) error {
422 if !fips140only.Enabled {
423 return nil
424 }
425 if err := checkFIPS140OnlyPublicKey(&priv.PublicKey); err != nil {
426 return err
427 }
428 if len(priv.Primes) != 2 {
429 return errors.New("crypto/rsa: use of multi-prime keys is not allowed in FIPS 140-only mode")
430 }
431 if priv.Primes[0] == nil || priv.Primes[1] == nil || priv.Primes[0].BitLen() != priv.Primes[1].BitLen() {
432 return errors.New("crypto/rsa: use of primes of different sizes is not allowed in FIPS 140-only mode")
433 }
434 return nil
435 }
436