86 if (publicKey.getAlgorithm().equals("RSA") == false) { |
69 if (publicKey.getAlgorithm().equals("RSA") == false) { |
87 throw new SSLKeyException("Public key not of type RSA"); |
70 throw new SSLKeyException("Public key not of type RSA"); |
88 } |
71 } |
89 this.protocolVersion = protocolVersion; |
72 this.protocolVersion = protocolVersion; |
90 |
73 |
91 int major, minor; |
|
92 |
|
93 if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) { |
|
94 major = maxVersion.major; |
|
95 minor = maxVersion.minor; |
|
96 } else { |
|
97 major = protocolVersion.major; |
|
98 minor = protocolVersion.minor; |
|
99 } |
|
100 |
|
101 try { |
74 try { |
102 String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ? |
75 String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ? |
103 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); |
76 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); |
104 KeyGenerator kg = JsseJce.getKeyGenerator(s); |
77 KeyGenerator kg = JsseJce.getKeyGenerator(s); |
105 kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor), |
78 kg.init(new TlsRsaPremasterSecretParameterSpec( |
106 generator); |
79 maxVersion.v, protocolVersion.v), generator); |
107 preMaster = kg.generateKey(); |
80 preMaster = kg.generateKey(); |
108 |
81 |
109 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); |
82 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); |
110 cipher.init(Cipher.WRAP_MODE, publicKey, generator); |
83 cipher.init(Cipher.WRAP_MODE, publicKey, generator); |
111 encrypted = cipher.wrap(preMaster); |
84 encrypted = cipher.wrap(preMaster); |
136 throw new SSLProtocolException( |
109 throw new SSLProtocolException( |
137 "SSL: read PreMasterSecret: short read"); |
110 "SSL: read PreMasterSecret: short read"); |
138 } |
111 } |
139 } |
112 } |
140 |
113 |
141 Exception failover = null; |
|
142 byte[] encoded = null; |
|
143 try { |
114 try { |
144 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); |
115 Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); |
145 // Cannot generate key here, please don't use Cipher.UNWRAP_MODE! |
116 // Cannot generate key here, please don't use Cipher.UNWRAP_MODE! |
146 cipher.init(Cipher.DECRYPT_MODE, privateKey); |
117 cipher.init(Cipher.UNWRAP_MODE, privateKey, |
147 encoded = cipher.doFinal(encrypted); |
118 new TlsRsaPremasterSecretParameterSpec( |
148 } catch (BadPaddingException bpe) { |
119 maxVersion.v, currentVersion.v), |
149 failover = bpe; |
120 generator); |
150 encoded = null; |
121 preMaster = (SecretKey)cipher.unwrap(encrypted, |
151 } catch (IllegalBlockSizeException ibse) { |
122 "TlsRsaPremasterSecret", Cipher.SECRET_KEY); |
152 // the message it too big to process with RSA |
123 } catch (InvalidKeyException ibk) { |
|
124 // the message is too big to process with RSA |
153 throw new SSLProtocolException( |
125 throw new SSLProtocolException( |
154 "Unable to process PreMasterSecret, may be too big"); |
126 "Unable to process PreMasterSecret, may be too big"); |
155 } catch (Exception e) { |
127 } catch (Exception e) { |
156 // unlikely to happen, otherwise, must be a provider exception |
128 // unlikely to happen, otherwise, must be a provider exception |
157 if (debug != null && Debug.isOn("handshake")) { |
129 if (debug != null && Debug.isOn("handshake")) { |
158 System.out.println("RSA premaster secret decryption error:"); |
130 System.out.println("RSA premaster secret decryption error:"); |
159 e.printStackTrace(System.out); |
131 e.printStackTrace(System.out); |
160 } |
132 } |
161 throw new RuntimeException("Could not generate dummy secret", e); |
133 throw new RuntimeException("Could not generate dummy secret", e); |
162 } |
|
163 |
|
164 // polish the premaster secret |
|
165 preMaster = polishPreMasterSecretKey( |
|
166 currentVersion, maxVersion, generator, encoded, failover); |
|
167 } |
|
168 |
|
169 /** |
|
170 * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246, |
|
171 * treating incorrectly formatted message blocks and/or mismatched |
|
172 * version numbers in a manner indistinguishable from correctly |
|
173 * formatted RSA blocks. |
|
174 * |
|
175 * RFC 5246 describes the approach as : |
|
176 * |
|
177 * 1. Generate a string R of 48 random bytes |
|
178 * |
|
179 * 2. Decrypt the message to recover the plaintext M |
|
180 * |
|
181 * 3. If the PKCS#1 padding is not correct, or the length of message |
|
182 * M is not exactly 48 bytes: |
|
183 * pre_master_secret = R |
|
184 * else If ClientHello.client_version <= TLS 1.0, and version |
|
185 * number check is explicitly disabled: |
|
186 * premaster secret = M |
|
187 * else If M[0..1] != ClientHello.client_version: |
|
188 * premaster secret = R |
|
189 * else: |
|
190 * premaster secret = M |
|
191 * |
|
192 * Note that #2 has completed before the call of this method. |
|
193 */ |
|
194 private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion, |
|
195 ProtocolVersion clientHelloVersion, SecureRandom generator, |
|
196 byte[] encoded, Exception failoverException) { |
|
197 |
|
198 this.protocolVersion = clientHelloVersion; |
|
199 if (generator == null) { |
|
200 generator = new SecureRandom(); |
|
201 } |
|
202 byte[] random = new byte[48]; |
|
203 generator.nextBytes(random); |
|
204 |
|
205 if (failoverException == null && encoded != null) { |
|
206 // check the length |
|
207 if (encoded.length != 48) { |
|
208 if (debug != null && Debug.isOn("handshake")) { |
|
209 System.out.println( |
|
210 "incorrect length of premaster secret: " + |
|
211 encoded.length); |
|
212 } |
|
213 |
|
214 return generatePreMasterSecret( |
|
215 clientHelloVersion, random, generator); |
|
216 } |
|
217 |
|
218 if (clientHelloVersion.major != encoded[0] || |
|
219 clientHelloVersion.minor != encoded[1]) { |
|
220 |
|
221 if (clientHelloVersion.v <= ProtocolVersion.TLS10.v && |
|
222 currentVersion.major == encoded[0] && |
|
223 currentVersion.minor == encoded[1]) { |
|
224 /* |
|
225 * For compatibility, we maintain the behavior that the |
|
226 * version in pre_master_secret can be the negotiated |
|
227 * version for TLS v1.0 and SSL v3.0. |
|
228 */ |
|
229 this.protocolVersion = currentVersion; |
|
230 } else { |
|
231 if (debug != null && Debug.isOn("handshake")) { |
|
232 System.out.println("Mismatching Protocol Versions, " + |
|
233 "ClientHello.client_version is " + |
|
234 clientHelloVersion + |
|
235 ", while PreMasterSecret.client_version is " + |
|
236 ProtocolVersion.valueOf(encoded[0], encoded[1])); |
|
237 } |
|
238 |
|
239 encoded = random; |
|
240 } |
|
241 } |
|
242 |
|
243 return generatePreMasterSecret( |
|
244 clientHelloVersion, encoded, generator); |
|
245 } |
|
246 |
|
247 if (debug != null && Debug.isOn("handshake") && |
|
248 failoverException != null) { |
|
249 System.out.println("Error decrypting premaster secret:"); |
|
250 failoverException.printStackTrace(System.out); |
|
251 } |
|
252 |
|
253 return generatePreMasterSecret(clientHelloVersion, random, generator); |
|
254 } |
|
255 |
|
256 // generate a premaster secret with the specified version number |
|
257 private static SecretKey generatePreMasterSecret( |
|
258 ProtocolVersion version, byte[] encodedSecret, |
|
259 SecureRandom generator) { |
|
260 |
|
261 if (debug != null && Debug.isOn("handshake")) { |
|
262 System.out.println("Generating a random fake premaster secret"); |
|
263 } |
|
264 |
|
265 try { |
|
266 String s = ((version.v >= ProtocolVersion.TLS12.v) ? |
|
267 "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); |
|
268 KeyGenerator kg = JsseJce.getKeyGenerator(s); |
|
269 kg.init(new TlsRsaPremasterSecretParameterSpec( |
|
270 version.major, version.minor, encodedSecret), generator); |
|
271 return kg.generateKey(); |
|
272 } catch (InvalidAlgorithmParameterException | |
|
273 NoSuchAlgorithmException iae) { |
|
274 // unlikely to happen, otherwise, must be a provider exception |
|
275 if (debug != null && Debug.isOn("handshake")) { |
|
276 System.out.println("RSA premaster secret generation error:"); |
|
277 iae.printStackTrace(System.out); |
|
278 } |
|
279 throw new RuntimeException("Could not generate dummy secret", iae); |
|
280 } |
134 } |
281 } |
135 } |
282 |
136 |
283 @Override |
137 @Override |
284 int messageType() { |
138 int messageType() { |