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