aboutsummaryrefslogtreecommitdiff
path: root/java/openjdk6/files/icedtea/security/7186286.patch
diff options
context:
space:
mode:
Diffstat (limited to 'java/openjdk6/files/icedtea/security/7186286.patch')
-rw-r--r--java/openjdk6/files/icedtea/security/7186286.patch552
1 files changed, 552 insertions, 0 deletions
diff --git a/java/openjdk6/files/icedtea/security/7186286.patch b/java/openjdk6/files/icedtea/security/7186286.patch
new file mode 100644
index 000000000000..cc5adc1a3cf9
--- /dev/null
+++ b/java/openjdk6/files/icedtea/security/7186286.patch
@@ -0,0 +1,552 @@
+# HG changeset patch
+# User xuelei
+# Date 1343546404 25200
+# Node ID a6294da5a21f609b67a0d4d216028dda9f56e689
+# Parent 88243aa6e67b6b84ff529ccdfd3b476410f60057
+7186286: TLS implementation to better adhere to RFC
+Summary: also reviewed by Alexander Fomin <Alexander.Fomin@Oracle.COM>, Andrew Gross<Andrew.Gross@Oracle.COM>, Sean Coffey<Sean.Coffey@Oracle.COM>
+Reviewed-by: valeriep, wetmore
+
+diff --git a/src/share/classes/sun/security/pkcs11/P11Cipher.java b/src/share/classes/sun/security/pkcs11/P11Cipher.java
+--- jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
++++ jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+@@ -650,7 +650,7 @@
+ // see JCE spec
+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
+ int n = P11SecretKeyFactory.convertKey
+- (token, key, keyAlgorithm).keyLength();
++ (token, key, keyAlgorithm).length();
+ return n;
+ }
+ }
+diff --git a/src/share/classes/sun/security/pkcs11/P11Key.java b/src/share/classes/sun/security/pkcs11/P11Key.java
+--- jdk/src/share/classes/sun/security/pkcs11/P11Key.java
++++ jdk/src/share/classes/sun/security/pkcs11/P11Key.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+@@ -46,6 +46,7 @@
+ import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
+
+ import sun.security.util.DerValue;
++import sun.security.util.Length;
+
+ /**
+ * Key implementation classes.
+@@ -61,7 +62,7 @@
+ * @author Andreas Sterbenz
+ * @since 1.5
+ */
+-abstract class P11Key implements Key {
++abstract class P11Key implements Key, Length {
+
+ private final static String PUBLIC = "public";
+ private final static String PRIVATE = "private";
+@@ -212,7 +213,11 @@
+ return s1;
+ }
+
+- int keyLength() {
++ /**
++ * Return bit length of the key.
++ */
++ @Override
++ public int length() {
+ return keyLength;
+ }
+
+diff --git a/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/share/classes/sun/security/pkcs11/P11RSACipher.java
+--- jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java
++++ jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+@@ -201,7 +201,7 @@
+ } else {
+ throw new InvalidKeyException("Unknown key type: " + p11Key);
+ }
+- int n = (p11Key.keyLength() + 7) >> 3;
++ int n = (p11Key.length() + 7) >> 3;
+ outputSize = n;
+ buffer = new byte[n];
+ maxInputSize = encrypt ? (n - PKCS1_MIN_PADDING_LENGTH) : n;
+@@ -458,7 +458,7 @@
+
+ // see JCE spec
+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
+- int n = P11KeyFactory.convertKey(token, key, algorithm).keyLength();
++ int n = P11KeyFactory.convertKey(token, key, algorithm).length();
+ return n;
+ }
+ }
+diff --git a/src/share/classes/sun/security/pkcs11/P11Signature.java b/src/share/classes/sun/security/pkcs11/P11Signature.java
+--- jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
++++ jdk/src/share/classes/sun/security/pkcs11/P11Signature.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+@@ -274,7 +274,7 @@
+ if (keyAlgorithm.equals("DSA")) {
+ signature = new byte[40];
+ } else {
+- signature = new byte[(p11Key.keyLength() + 7) >> 3];
++ signature = new byte[(p11Key.length() + 7) >> 3];
+ }
+ if (type == T_UPDATE) {
+ token.p11.C_VerifyFinal(session.id(), signature);
+@@ -359,7 +359,7 @@
+ if (keyAlgorithm.equals("RSA") && publicKey != p11Key) {
+ int keyLen;
+ if (publicKey instanceof P11Key) {
+- keyLen = ((P11Key) publicKey).keyLength();
++ keyLen = ((P11Key) publicKey).length();
+ } else {
+ keyLen = ((RSAKey) publicKey).getModulus().bitLength();
+ }
+@@ -620,7 +620,7 @@
+
+ private byte[] pkcs1Pad(byte[] data) {
+ try {
+- int len = (p11Key.keyLength() + 7) >> 3;
++ int len = (p11Key.length() + 7) >> 3;
+ RSAPadding padding = RSAPadding.getInstance
+ (RSAPadding.PAD_BLOCKTYPE_1, len);
+ byte[] padded = padding.pad(data);
+diff --git a/src/share/classes/sun/security/ssl/HandshakeInStream.java b/src/share/classes/sun/security/ssl/HandshakeInStream.java
+--- jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java
++++ jdk/src/share/classes/sun/security/ssl/HandshakeInStream.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+@@ -190,6 +190,7 @@
+
+ byte[] getBytes8() throws IOException {
+ int len = getInt8();
++ verifyLength(len);
+ byte b[] = new byte[len];
+
+ read(b, 0, len);
+@@ -198,6 +199,7 @@
+
+ byte[] getBytes16() throws IOException {
+ int len = getInt16();
++ verifyLength(len);
+ byte b[] = new byte[len];
+
+ read(b, 0, len);
+@@ -206,10 +208,19 @@
+
+ byte[] getBytes24() throws IOException {
+ int len = getInt24();
++ verifyLength(len);
+ byte b[] = new byte[len];
+
+ read(b, 0, len);
+ return b;
+ }
+
++ // Is a length greater than available bytes in the record?
++ private void verifyLength(int len) throws SSLException {
++ if (len > available()) {
++ throw new SSLException(
++ "Not enough data to fill declared vector size");
++ }
++ }
++
+ }
+diff --git a/src/share/classes/sun/security/ssl/Handshaker.java b/src/share/classes/sun/security/ssl/Handshaker.java
+--- jdk/src/share/classes/sun/security/ssl/Handshaker.java
++++ jdk/src/share/classes/sun/security/ssl/Handshaker.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+@@ -776,9 +776,9 @@
+ if (debug != null && Debug.isOn("handshake")) {
+ System.out.println("RSA master secret generation error:");
+ e.printStackTrace(System.out);
+- System.out.println("Generating new random premaster secret");
+ }
+- preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
++ preMasterSecret =
++ RSAClientKeyExchange.generateDummySecret(protocolVersion);
+ // recursive call with new premaster secret
+ return calculateMasterSecret(preMasterSecret, null);
+ }
+@@ -821,9 +821,9 @@
+ System.out.println("RSA PreMasterSecret version error: expected"
+ + protocolVersion + " or " + requestedVersion + ", decrypted: "
+ + premasterVersion);
+- System.out.println("Generating new random premaster secret");
+ }
+- preMasterSecret = RSAClientKeyExchange.generateDummySecret(protocolVersion);
++ preMasterSecret =
++ RSAClientKeyExchange.generateDummySecret(protocolVersion);
+ // recursive call with new premaster secret
+ return calculateMasterSecret(preMasterSecret, null);
+ }
+diff --git a/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java b/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
+--- jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
++++ jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+@@ -36,6 +36,7 @@
+ import javax.net.ssl.*;
+
+ import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
++import sun.security.util.KeyLength;
+
+ /**
+ * This is the client key exchange message (CLIENT --> SERVER) used with
+@@ -85,7 +86,8 @@
+ * it, using its RSA private key. Result is the same size as the
+ * server's public key, and uses PKCS #1 block format 02.
+ */
+- RSAClientKeyExchange(ProtocolVersion protocolVersion, ProtocolVersion maxVersion,
++ RSAClientKeyExchange(ProtocolVersion protocolVersion,
++ ProtocolVersion maxVersion,
+ SecureRandom generator, PublicKey publicKey) throws IOException {
+ if (publicKey.getAlgorithm().equals("RSA") == false) {
+ throw new SSLKeyException("Public key not of type RSA");
+@@ -120,7 +122,8 @@
+ * Server gets the PKCS #1 (block format 02) data, decrypts
+ * it with its private key.
+ */
+- RSAClientKeyExchange(ProtocolVersion currentVersion, HandshakeInStream input,
++ RSAClientKeyExchange(ProtocolVersion currentVersion,
++ ProtocolVersion maxVersion, HandshakeInStream input,
+ int messageSize, PrivateKey privateKey) throws IOException {
+
+ if (privateKey.getAlgorithm().equals("RSA") == false) {
+@@ -143,28 +146,119 @@
+ cipher.init(Cipher.UNWRAP_MODE, privateKey);
+ preMaster = (SecretKey)cipher.unwrap(encrypted,
+ "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
++
++ // polish the premaster secret
++ preMaster = polishPreMasterSecretKey(
++ currentVersion, maxVersion, preMaster, null);
+ } catch (Exception e) {
+- /*
+- * Bogus decrypted ClientKeyExchange? If so, conjure a
+- * a random preMaster secret that will fail later during
+- * Finished message processing. This is a countermeasure against
+- * the "interactive RSA PKCS#1 encryption envelop attack" reported
+- * in June 1998. Preserving the executation path will
+- * mitigate timing attacks and force consistent error handling
+- * that will prevent an attacking client from differentiating
+- * different kinds of decrypted ClientKeyExchange bogosities.
+- */
+- if (debug != null && Debug.isOn("handshake")) {
+- System.out.println("Error decrypting premaster secret:");
+- e.printStackTrace(System.out);
+- System.out.println("Generating random secret");
++ // polish the premaster secret
++ preMaster = polishPreMasterSecretKey(
++ currentVersion, maxVersion, preMaster, e);
++ }
++ }
++
++ /**
++ * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
++ * treating incorrectly formatted message blocks and/or mismatched
++ * version numbers in a manner indistinguishable from correctly
++ * formatted RSA blocks.
++ *
++ * RFC 5246 describes the approach as :
++ *
++ * 1. Generate a string R of 46 random bytes
++ *
++ * 2. Decrypt the message to recover the plaintext M
++ *
++ * 3. If the PKCS#1 padding is not correct, or the length of message
++ * M is not exactly 48 bytes:
++ * pre_master_secret = ClientHello.client_version || R
++ * else If ClientHello.client_version <= TLS 1.0, and version
++ * number check is explicitly disabled:
++ * pre_master_secret = M
++ * else:
++ * pre_master_secret = ClientHello.client_version || M[2..47]
++ *
++ * Note that although TLS 1.2 is not supported in this release, we still
++ * want to make use of the above approach to provide better protection.
++ */
++ private SecretKey polishPreMasterSecretKey(
++ ProtocolVersion currentVersion, ProtocolVersion clientHelloVersion,
++ SecretKey secretKey, Exception failoverException) {
++
++ if (failoverException == null && secretKey != null) {
++ // check the length
++ byte[] encoded = secretKey.getEncoded();
++ if (encoded == null) { // unable to get the encoded key
++ if (debug != null && Debug.isOn("handshake")) {
++ System.out.println(
++ "unable to get the plaintext of the premaster secret");
++ }
++
++ int keySize = KeyLength.getKeySize(secretKey);
++ if (keySize > 0 && keySize != 384) { // 384 = 48 * 8
++ if (debug != null && Debug.isOn("handshake")) {
++ System.out.println(
++ "incorrect length of premaster secret: " +
++ (keySize/8));
++ }
++
++ return generateDummySecret(currentVersion);
++ }
++
++ // The key size is exactly 48 bytes or not accessible.
++ //
++ // Conservatively, pass the checking to master secret
++ // calculation.
++ return secretKey;
++ } else if (encoded.length == 48) {
++ // check the version
++ if (clientHelloVersion.major == encoded[0] &&
++ clientHelloVersion.minor == encoded[1]) {
++
++ return secretKey;
++ } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
++ currentVersion.major == encoded[0] &&
++ currentVersion.minor == encoded[1]) {
++ /*
++ * For compatibility, we maintain the behavior that the
++ * version in pre_master_secret can be the negotiated
++ * version for TLS v1.0 and SSL v3.0.
++ */
++ return secretKey;
++ }
++
++ if (debug != null && Debug.isOn("handshake")) {
++ System.out.println("Mismatching Protocol Versions, " +
++ "ClientHello.client_version is " + clientHelloVersion +
++ ", while PreMasterSecret.client_version is " +
++ ProtocolVersion.valueOf(encoded[0], encoded[1]));
++ }
++ return generateDummySecret(currentVersion);
++ } else {
++ if (debug != null && Debug.isOn("handshake")) {
++ System.out.println(
++ "incorrect length of premaster secret: " +
++ encoded.length);
++ }
++ return generateDummySecret(currentVersion);
+ }
+- preMaster = generateDummySecret(currentVersion);
+ }
++
++ if (debug != null && Debug.isOn("handshake") &&
++ failoverException != null) {
++ System.out.println("Error decrypting premaster secret:");
++ failoverException.printStackTrace(System.out);
++ }
++
++ return generateDummySecret(currentVersion);
+ }
+
+ // generate a premaster secret with the specified version number
+ static SecretKey generateDummySecret(ProtocolVersion version) {
++ if (debug != null && Debug.isOn("handshake")) {
++ System.out.println("Generating a random fake premaster secret");
++ }
++
+ try {
+ KeyGenerator kg =
+ JsseJce.getKeyGenerator("SunTlsRsaPremasterSecret");
+diff --git a/src/share/classes/sun/security/ssl/ServerHandshaker.java b/src/share/classes/sun/security/ssl/ServerHandshaker.java
+--- jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
++++ jdk/src/share/classes/sun/security/ssl/ServerHandshaker.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+@@ -190,8 +190,9 @@
+ * temporary one used for non-export or signing-only
+ * certificates/keys.
+ */
+- RSAClientKeyExchange pms = new RSAClientKeyExchange
+- (protocolVersion, input, message_len, privateKey);
++ RSAClientKeyExchange pms = new RSAClientKeyExchange(
++ protocolVersion, clientRequestedVersion,
++ input, message_len, privateKey);
+ preMasterSecret = this.clientKeyExchange(pms);
+ break;
+ case K_KRB5:
+diff --git a/src/share/classes/sun/security/util/KeyLength.java b/src/share/classes/sun/security/util/KeyLength.java
+new file mode 100644
+--- /dev/null
++++ jdk/src/share/classes/sun/security/util/KeyLength.java
+@@ -0,0 +1,91 @@
++/*
++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation. Oracle designates this
++ * particular file as subject to the "Classpath" exception as provided
++ * by Oracle in the LICENSE file that accompanied this code.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ */
++
++package sun.security.util;
++
++import java.security.Key;
++import java.security.PrivilegedAction;
++import java.security.AccessController;
++import java.security.interfaces.ECKey;
++import java.security.interfaces.RSAKey;
++import java.security.interfaces.DSAKey;
++import javax.crypto.SecretKey;
++import javax.crypto.interfaces.DHKey;
++
++/**
++ * A utility class to get key length
++ */
++public final class KeyLength {
++
++ /**
++ * Returns the key size of the given key object in bits.
++ *
++ * @param key the key object, cannot be null
++ * @return the key size of the given key object in bits, or -1 if the
++ * key size is not accessible
++ */
++ final public static int getKeySize(Key key) {
++ int size = -1;
++
++ if (key instanceof Length) {
++ try {
++ Length ruler = (Length)key;
++ size = ruler.length();
++ } catch (UnsupportedOperationException usoe) {
++ // ignore the exception
++ }
++
++ if (size >= 0) {
++ return size;
++ }
++ }
++
++ // try to parse the length from key specification
++ if (key instanceof SecretKey) {
++ SecretKey sk = (SecretKey)key;
++ String format = sk.getFormat();
++ if ("RAW".equals(format) && sk.getEncoded() != null) {
++ size = (sk.getEncoded().length * 8);
++ } // Otherwise, it may be a unextractable key of PKCS#11, or
++ // a key we are not able to handle.
++ } else if (key instanceof RSAKey) {
++ RSAKey pubk = (RSAKey)key;
++ size = pubk.getModulus().bitLength();
++ } else if (key instanceof ECKey) {
++ ECKey pubk = (ECKey)key;
++ size = pubk.getParams().getOrder().bitLength();
++ } else if (key instanceof DSAKey) {
++ DSAKey pubk = (DSAKey)key;
++ size = pubk.getParams().getP().bitLength();
++ } else if (key instanceof DHKey) {
++ DHKey pubk = (DHKey)key;
++ size = pubk.getParams().getP().bitLength();
++ } // Otherwise, it may be a unextractable key of PKCS#11, or
++ // a key we are not able to handle.
++
++ return size;
++ }
++}
++
+diff --git a/src/share/classes/sun/security/util/Length.java b/src/share/classes/sun/security/util/Length.java
+new file mode 100644
+--- /dev/null
++++ jdk/src/share/classes/sun/security/util/Length.java
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation. Oracle designates this
++ * particular file as subject to the "Classpath" exception as provided
++ * by Oracle in the LICENSE file that accompanied this code.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ */
++
++package sun.security.util;
++
++/**
++ * The Length interface defines the length of an object
++ */
++public interface Length {
++
++ /**
++ * Gets the length of this object
++ * <p>
++ * Note that if a class of java.security.Key implements this interfaces,
++ * the length should be measured in bits.
++ *
++ * @return the length of this object
++ * @throws UnsupportedOperationException if the operation is not supported
++ */
++ public int length();
++}