fips.mx raw

   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