History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/ssl/RSAClientKeyExchange.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/RSAClientKeyExchange.java+286−0
@@ -0,0 +1,286 @@
1+/*
2+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+
27+package sun.security.ssl;
28+
29+import java.io.*;
30+import java.security.*;
31+import java.security.interfaces.*;
32+
33+import javax.crypto.*;
34+import javax.crypto.spec.*;
35+
36+import javax.net.ssl.*;
37+
38+import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
39+
40+/**
41+ * This is the client key exchange message (CLIENT --> SERVER) used with
42+ * all RSA key exchanges; it holds the RSA-encrypted pre-master secret.
43+ *
44+ * The message is encrypted using PKCS #1 block type 02 encryption with the
45+ * server's public key. The padding and resulting message size is a function
46+ * of this server's public key modulus size, but the pre-master secret is
47+ * always exactly 48 bytes.
48+ *
49+ */
50+final class RSAClientKeyExchange extends HandshakeMessage {
51+
52+ /**
53+ * The TLS spec says that the version in the RSA premaster secret must
54+ * be the maximum version supported by the client (i.e. the version it
55+ * requested in its client hello version). However, we (and other
56+ * implementations) used to send the active negotiated version. The
57+ * system property below allows to toggle the behavior.
58+ */
59+ private final static String PROP_NAME =
60+ "com.sun.net.ssl.rsaPreMasterSecretFix";
61+
62+ /*
63+ * Default is "false" (old behavior) for compatibility reasons in
64+ * SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property.
65+ */
66+ private final static boolean rsaPreMasterSecretFix =
67+ Debug.getBooleanProperty(PROP_NAME, false);
68+
69+ /*
70+ * The following field values were encrypted with the server's public
71+ * key (or temp key from server key exchange msg) and are presented
72+ * here in DECRYPTED form.
73+ */
74+ private ProtocolVersion protocolVersion; // preMaster [0,1]
75+ SecretKey preMaster;
76+ private byte[] encrypted; // same size as public modulus
77+
78+ /*
79+ * Client randomly creates a pre-master secret and encrypts it
80+ * using the server's RSA public key; only the server can decrypt
81+ * it, using its RSA private key. Result is the same size as the
82+ * server's public key, and uses PKCS #1 block format 02.
83+ */
84+ RSAClientKeyExchange(ProtocolVersion protocolVersion,
85+ ProtocolVersion maxVersion,
86+ SecureRandom generator, PublicKey publicKey) throws IOException {
87+ if (publicKey.getAlgorithm().equals("RSA") == false) {
88+ throw new SSLKeyException("Public key not of type RSA");
89+ }
90+ this.protocolVersion = protocolVersion;
91+
92+ int major, minor;
93+
94+ if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
95+ major = maxVersion.major;
96+ minor = maxVersion.minor;
97+ } else {
98+ major = protocolVersion.major;
99+ minor = protocolVersion.minor;
100+ }
101+
102+ try {
103+ String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
104+ "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
105+ KeyGenerator kg = JsseJce.getKeyGenerator(s);
106+ kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor),
107+ generator);
108+ preMaster = kg.generateKey();
109+
110+ Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
111+ cipher.init(Cipher.WRAP_MODE, publicKey, generator);
112+ encrypted = cipher.wrap(preMaster);
113+ } catch (GeneralSecurityException e) {
114+ throw (SSLKeyException)new SSLKeyException
115+ ("RSA premaster secret error").initCause(e);
116+ }
117+ }
118+
119+ /*
120+ * Server gets the PKCS #1 (block format 02) data, decrypts
121+ * it with its private key.
122+ */
123+ RSAClientKeyExchange(ProtocolVersion currentVersion,
124+ ProtocolVersion maxVersion,
125+ SecureRandom generator, HandshakeInStream input,
126+ int messageSize, PrivateKey privateKey) throws IOException {
127+
128+ if (privateKey.getAlgorithm().equals("RSA") == false) {
129+ throw new SSLKeyException("Private key not of type RSA");
130+ }
131+
132+ if (currentVersion.v >= ProtocolVersion.TLS10.v) {
133+ encrypted = input.getBytes16();
134+ } else {
135+ encrypted = new byte [messageSize];
136+ if (input.read(encrypted) != messageSize) {
137+ throw new SSLProtocolException
138+ ("SSL: read PreMasterSecret: short read");
139+ }
140+ }
141+
142+ try {
143+ Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
144+ cipher.init(Cipher.UNWRAP_MODE, privateKey);
145+ preMaster = (SecretKey)cipher.unwrap(encrypted,
146+ "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
147+
148+ // polish the premaster secret
149+ preMaster = polishPreMasterSecretKey(currentVersion, maxVersion,
150+ generator, preMaster, null);
151+ } catch (Exception e) {
152+ // polish the premaster secret
153+ preMaster =
154+ polishPreMasterSecretKey(currentVersion, maxVersion,
155+ generator, null, e);
156+ }
157+ }
158+
159+ /**
160+ * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
161+ * treating incorrectly formatted message blocks and/or mismatched
162+ * version numbers in a manner indistinguishable from correctly
163+ * formatted RSA blocks.
164+ *
165+ * RFC 5246 describes the approach as :
166+ *
167+ * 1. Generate a string R of 46 random bytes
168+ *
169+ * 2. Decrypt the message to recover the plaintext M
170+ *
171+ * 3. If the PKCS#1 padding is not correct, or the length of message
172+ * M is not exactly 48 bytes:
173+ * pre_master_secret = ClientHello.client_version || R
174+ * else If ClientHello.client_version <= TLS 1.0, and version
175+ * number check is explicitly disabled:
176+ * pre_master_secret = M
177+ * else:
178+ * pre_master_secret = ClientHello.client_version || M[2..47]
179+ */
180+ private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
181+ ProtocolVersion clientHelloVersion, SecureRandom generator,
182+ SecretKey secretKey, Exception failoverException) {
183+
184+ this.protocolVersion = clientHelloVersion;
185+
186+ if (failoverException == null && secretKey != null) {
187+ // check the length
188+ byte[] encoded = secretKey.getEncoded();
189+ if (encoded == null) { // unable to get the encoded key
190+ if (debug != null && Debug.isOn("handshake")) {
191+ System.out.println(
192+ "unable to get the plaintext of the premaster secret");
193+ }
194+
195+ // We are not always able to get the encoded key of the
196+ // premaster secret. Pass the cheking to master secret
197+ // calculation.
198+ return secretKey;
199+ } else if (encoded.length == 48) {
200+ // check the version
201+ if (clientHelloVersion.major == encoded[0] &&
202+ clientHelloVersion.minor == encoded[1]) {
203+ return secretKey;
204+ } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v) {
205+ /*
206+ * we never checked the client_version in server side
207+ * for TLS v1.0 and SSL v3.0. For compatibility, we
208+ * maintain this behavior.
209+ */
210+ if (currentVersion.major == encoded[0] &&
211+ currentVersion.minor == encoded[1]) {
212+ this.protocolVersion = currentVersion;
213+ return secretKey;
214+ }
215+ }
216+
217+ if (debug != null && Debug.isOn("handshake")) {
218+ System.out.println("Mismatching Protocol Versions, " +
219+ "ClientHello.client_version is " + clientHelloVersion +
220+ ", while PreMasterSecret.client_version is " +
221+ ProtocolVersion.valueOf(encoded[0], encoded[1]));
222+ }
223+ } else {
224+ if (debug != null && Debug.isOn("handshake")) {
225+ System.out.println(
226+ "incorrect length of premaster secret: " +
227+ encoded.length);
228+ }
229+ }
230+ }
231+
232+ if (debug != null && Debug.isOn("handshake")) {
233+ if (failoverException != null) {
234+ System.out.println("Error decrypting premaster secret:");
235+ failoverException.printStackTrace(System.out);
236+ }
237+
238+ System.out.println("Generating random secret");
239+ }
240+
241+ return generateDummySecret(clientHelloVersion);
242+ }
243+
244+ // generate a premaster secret with the specified version number
245+ static SecretKey generateDummySecret(ProtocolVersion version) {
246+ try {
247+ String s = ((version.v >= ProtocolVersion.TLS12.v) ?
248+ "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
249+ KeyGenerator kg = JsseJce.getKeyGenerator(s);
250+ kg.init(new TlsRsaPremasterSecretParameterSpec
251+ (version.major, version.minor));
252+ return kg.generateKey();
253+ } catch (GeneralSecurityException e) {
254+ throw new RuntimeException("Could not generate dummy secret", e);
255+ }
256+ }
257+
258+ @Override
259+ int messageType() {
260+ return ht_client_key_exchange;
261+ }
262+
263+ @Override
264+ int messageLength() {
265+ if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
266+ return encrypted.length + 2;
267+ } else {
268+ return encrypted.length;
269+ }
270+ }
271+
272+ @Override
273+ void send(HandshakeOutStream s) throws IOException {
274+ if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
275+ s.putBytes16(encrypted);
276+ } else {
277+ s.write(encrypted);
278+ }
279+ }
280+
281+ @Override
282+ void print(PrintStream s) throws IOException {
283+ s.println("*** ClientKeyExchange, RSA PreMasterSecret, " +
284+ protocolVersion);
285+ }
286+}