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

View as plain text