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  	"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 string
   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 string
   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  

View as plain text