Source file src/crypto/rsa/pkcs1v15.go

     1  // Copyright 2009 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/internal/boring"
     9  	"crypto/internal/fips140/rsa"
    10  	"crypto/internal/fips140only"
    11  	"crypto/internal/rand"
    12  	"crypto/subtle"
    13  	"errors"
    14  	"io"
    15  )
    16  
    17  // This file implements encryption and decryption using PKCS #1 v1.5 padding.
    18  
    19  // PKCS1v15DecryptOptions is for passing options to PKCS #1 v1.5 decryption using
    20  // the [crypto.Decrypter] interface.
    21  //
    22  // Deprecated: PKCS #1 v1.5 encryption is dangerous and should not be used.
    23  // See [draft-irtf-cfrg-rsa-guidance-05] for more information. Use
    24  // [EncryptOAEP] and [DecryptOAEP] instead.
    25  //
    26  // [draft-irtf-cfrg-rsa-guidance-05]: https://www.ietf.org/archive/id/draft-irtf-cfrg-rsa-guidance-05.html#name-rationale
    27  type PKCS1v15DecryptOptions struct {
    28  	// SessionKeyLen is the length of the session key that is being
    29  	// decrypted. If not zero, then a padding error during decryption will
    30  	// cause a random plaintext of this length to be returned rather than
    31  	// an error. These alternatives happen in constant time.
    32  	SessionKeyLen int
    33  }
    34  
    35  // EncryptPKCS1v15 encrypts the given message with RSA and the padding
    36  // scheme from PKCS #1 v1.5.  The message must be no longer than the
    37  // length of the public modulus minus 11 bytes.
    38  //
    39  // The random parameter is used as a source of entropy to ensure that encrypting
    40  // the same message twice doesn't result in the same ciphertext. Since Go 1.26,
    41  // a secure source of random bytes is always used, and the Reader is ignored
    42  // unless GODEBUG=cryptocustomrand=1 is set. This setting will be removed in a
    43  // future Go release. Instead, use [testing/cryptotest.SetGlobalRandom].
    44  //
    45  // Deprecated: PKCS #1 v1.5 encryption is dangerous and should not be used.
    46  // See [draft-irtf-cfrg-rsa-guidance-05] for more information. Use
    47  // [EncryptOAEP] and [DecryptOAEP] instead.
    48  //
    49  // [draft-irtf-cfrg-rsa-guidance-05]: https://www.ietf.org/archive/id/draft-irtf-cfrg-rsa-guidance-05.html#name-rationale
    50  func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error) {
    51  	if fips140only.Enforced() {
    52  		return nil, errors.New("crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode")
    53  	}
    54  
    55  	if err := checkPublicKeySize(pub); err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	k := pub.Size()
    60  	if len(msg) > k-11 {
    61  		return nil, ErrMessageTooLong
    62  	}
    63  
    64  	if boring.Enabled && rand.IsDefaultReader(random) {
    65  		bkey, err := boringPublicKey(pub)
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  		return boring.EncryptRSAPKCS1(bkey, msg)
    70  	}
    71  	boring.UnreachableExceptTests()
    72  
    73  	random = rand.CustomReader(random)
    74  
    75  	// EM = 0x00 || 0x02 || PS || 0x00 || M
    76  	em := make([]byte, k)
    77  	em[1] = 2
    78  	ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):]
    79  	err := nonZeroRandomBytes(ps, random)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	em[len(em)-len(msg)-1] = 0
    84  	copy(mm, msg)
    85  
    86  	if boring.Enabled {
    87  		var bkey *boring.PublicKeyRSA
    88  		bkey, err = boringPublicKey(pub)
    89  		if err != nil {
    90  			return nil, err
    91  		}
    92  		return boring.EncryptRSANoPadding(bkey, em)
    93  	}
    94  
    95  	fk, err := fipsPublicKey(pub)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	return rsa.Encrypt(fk, em)
   100  }
   101  
   102  // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from
   103  // PKCS #1 v1.5. The random parameter is legacy and ignored, and it can be nil.
   104  //
   105  // Deprecated: PKCS #1 v1.5 encryption is dangerous and should not be used.
   106  // Whether this function returns an error or not discloses secret information.
   107  // If an attacker can cause this function to run repeatedly and learn whether
   108  // each instance returned an error then they can decrypt and forge signatures as
   109  // if they had the private key. See [draft-irtf-cfrg-rsa-guidance-05] for more
   110  // information. Use [EncryptOAEP] and [DecryptOAEP] instead.
   111  //
   112  // [draft-irtf-cfrg-rsa-guidance-05]: https://www.ietf.org/archive/id/draft-irtf-cfrg-rsa-guidance-05.html#name-rationale
   113  func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error) {
   114  	if err := checkPublicKeySize(&priv.PublicKey); err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	if boring.Enabled {
   119  		bkey, err := boringPrivateKey(priv)
   120  		if err != nil {
   121  			return nil, err
   122  		}
   123  		out, err := boring.DecryptRSAPKCS1(bkey, ciphertext)
   124  		if err != nil {
   125  			return nil, ErrDecryption
   126  		}
   127  		return out, nil
   128  	}
   129  
   130  	valid, out, index, err := decryptPKCS1v15(priv, ciphertext)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  	if valid == 0 {
   135  		return nil, ErrDecryption
   136  	}
   137  	return out[index:], nil
   138  }
   139  
   140  // DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding
   141  // scheme from PKCS #1 v1.5. The random parameter is legacy and ignored, and it
   142  // can be nil.
   143  //
   144  // DecryptPKCS1v15SessionKey returns an error if the ciphertext is the wrong
   145  // length or if the ciphertext is greater than the public modulus. Otherwise, no
   146  // error is returned. If the padding is valid, the resulting plaintext message
   147  // is copied into key. Otherwise, key is unchanged. These alternatives occur in
   148  // constant time. It is intended that the user of this function generate a
   149  // random session key beforehand and continue the protocol with the resulting
   150  // value.
   151  //
   152  // Note that if the session key is too small then it may be possible for an
   153  // attacker to brute-force it. If they can do that then they can learn whether a
   154  // random value was used (because it'll be different for the same ciphertext)
   155  // and thus whether the padding was correct. This also defeats the point of this
   156  // function. Using at least a 16-byte key will protect against this attack.
   157  //
   158  // This method implements protections against Bleichenbacher chosen ciphertext
   159  // attacks [0] described in RFC 3218 Section 2.3.2 [1]. While these protections
   160  // make a Bleichenbacher attack significantly more difficult, the protections
   161  // are only effective if the rest of the protocol which uses
   162  // DecryptPKCS1v15SessionKey is designed with these considerations in mind. In
   163  // particular, if any subsequent operations which use the decrypted session key
   164  // leak any information about the key (e.g. whether it is a static or random
   165  // key) then the mitigations are defeated. This method must be used extremely
   166  // carefully, and typically should only be used when absolutely necessary for
   167  // compatibility with an existing protocol (such as TLS) that is designed with
   168  // these properties in mind.
   169  //
   170  //   - [0] “Chosen Ciphertext Attacks Against Protocols Based on the RSA Encryption
   171  //     Standard PKCS #1”, Daniel Bleichenbacher, Advances in Cryptology (Crypto '98)
   172  //   - [1] RFC 3218, Preventing the Million Message Attack on CMS,
   173  //     https://www.rfc-editor.org/rfc/rfc3218.html
   174  //
   175  // Deprecated: PKCS #1 v1.5 encryption is dangerous and should not be used. The
   176  // protections implemented by this function are limited and fragile, as
   177  // explained above. See [draft-irtf-cfrg-rsa-guidance-05] for more information.
   178  // Use [EncryptOAEP] and [DecryptOAEP] instead.
   179  //
   180  // [draft-irtf-cfrg-rsa-guidance-05]: https://www.ietf.org/archive/id/draft-irtf-cfrg-rsa-guidance-05.html#name-rationale
   181  func DecryptPKCS1v15SessionKey(random io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error {
   182  	if err := checkPublicKeySize(&priv.PublicKey); err != nil {
   183  		return err
   184  	}
   185  
   186  	k := priv.Size()
   187  	if k-(len(key)+3+8) < 0 {
   188  		return ErrDecryption
   189  	}
   190  
   191  	valid, em, index, err := decryptPKCS1v15(priv, ciphertext)
   192  	if err != nil {
   193  		return err
   194  	}
   195  
   196  	if len(em) != k {
   197  		// This should be impossible because decryptPKCS1v15 always
   198  		// returns the full slice.
   199  		return ErrDecryption
   200  	}
   201  
   202  	valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key)))
   203  	subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):])
   204  	return nil
   205  }
   206  
   207  // decryptPKCS1v15 decrypts ciphertext using priv. It returns one or zero in
   208  // valid that indicates whether the plaintext was correctly structured.
   209  // In either case, the plaintext is returned in em so that it may be read
   210  // independently of whether it was valid in order to maintain constant memory
   211  // access patterns. If the plaintext was valid then index contains the index of
   212  // the original message in em, to allow constant time padding removal.
   213  func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
   214  	if fips140only.Enforced() {
   215  		return 0, nil, 0, errors.New("crypto/rsa: use of PKCS#1 v1.5 encryption is not allowed in FIPS 140-only mode")
   216  	}
   217  
   218  	k := priv.Size()
   219  	if k < 11 {
   220  		err = ErrDecryption
   221  		return 0, nil, 0, err
   222  	}
   223  
   224  	if boring.Enabled {
   225  		var bkey *boring.PrivateKeyRSA
   226  		bkey, err = boringPrivateKey(priv)
   227  		if err != nil {
   228  			return 0, nil, 0, err
   229  		}
   230  		em, err = boring.DecryptRSANoPadding(bkey, ciphertext)
   231  		if err != nil {
   232  			return 0, nil, 0, ErrDecryption
   233  		}
   234  	} else {
   235  		fk, err := fipsPrivateKey(priv)
   236  		if err != nil {
   237  			return 0, nil, 0, err
   238  		}
   239  		em, err = rsa.DecryptWithoutCheck(fk, ciphertext)
   240  		if err != nil {
   241  			return 0, nil, 0, ErrDecryption
   242  		}
   243  	}
   244  
   245  	firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
   246  	secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
   247  
   248  	// The remainder of the plaintext must be a string of non-zero random
   249  	// octets, followed by a 0, followed by the message.
   250  	//   lookingForIndex: 1 iff we are still looking for the zero.
   251  	//   index: the offset of the first zero byte.
   252  	lookingForIndex := 1
   253  
   254  	for i := 2; i < len(em); i++ {
   255  		equals0 := subtle.ConstantTimeByteEq(em[i], 0)
   256  		index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
   257  		lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
   258  	}
   259  
   260  	// The PS padding must be at least 8 bytes long, and it starts two
   261  	// bytes into em.
   262  	validPS := subtle.ConstantTimeLessOrEq(2+8, index)
   263  
   264  	valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS
   265  	index = subtle.ConstantTimeSelect(valid, index+1, 0)
   266  	return valid, em, index, nil
   267  }
   268  
   269  // nonZeroRandomBytes fills the given slice with non-zero random octets.
   270  func nonZeroRandomBytes(s []byte, random io.Reader) (err error) {
   271  	_, err = io.ReadFull(random, s)
   272  	if err != nil {
   273  		return
   274  	}
   275  
   276  	for i := 0; i < len(s); i++ {
   277  		for s[i] == 0 {
   278  			_, err = io.ReadFull(random, s[i:i+1])
   279  			if err != nil {
   280  				return
   281  			}
   282  			// In tests, the PRNG may return all zeros so we do
   283  			// this to break the loop.
   284  			s[i] ^= 0x42
   285  		}
   286  	}
   287  
   288  	return
   289  }
   290  

View as plain text