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

View as plain text