Source file src/crypto/rsa/fips.go

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

View as plain text