summaryrefslogtreecommitdiff
path: root/java/openjdk6/files/icedtea/security/20130201/7192392.patch
diff options
context:
space:
mode:
Diffstat (limited to 'java/openjdk6/files/icedtea/security/20130201/7192392.patch')
-rw-r--r--java/openjdk6/files/icedtea/security/20130201/7192392.patch695
1 files changed, 0 insertions, 695 deletions
diff --git a/java/openjdk6/files/icedtea/security/20130201/7192392.patch b/java/openjdk6/files/icedtea/security/20130201/7192392.patch
deleted file mode 100644
index 5e51b99c7e64..000000000000
--- a/java/openjdk6/files/icedtea/security/20130201/7192392.patch
+++ /dev/null
@@ -1,695 +0,0 @@
-# HG changeset patch
-# User mbankal
-# Date 1355226562 28800
-# Node ID 726b9456757648efb7c68e41c6bcc08a401eef83
-# Parent aade089d4505d382f49306a90873c4217367e709
-7192392: Better validation of client keys
-Reviewed-by: xuelei
-
-diff --git a/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java b/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java
---- jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java
-+++ jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 1997, 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
-@@ -39,6 +39,7 @@ import javax.crypto.ShortBufferException
- import javax.crypto.ShortBufferException;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.*;
-+import sun.security.util.KeyUtil;
-
- /**
- * This class implements the Diffie-Hellman key agreement protocol between
-@@ -205,6 +206,9 @@ extends KeyAgreementSpi {
- if (pub_g != null && !(init_g.equals(pub_g))) {
- throw new InvalidKeyException("Incompatible parameters");
- }
-+
-+ // validate the Diffie-Hellman public key
-+ KeyUtil.validate(dhPubKey);
-
- // store the y value
- this.y = dhPubKey.getY();
-diff --git a/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java b/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java
---- jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java
-+++ jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2003, 2007, 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
-@@ -37,6 +37,7 @@ import static sun.security.pkcs11.Templa
- import static sun.security.pkcs11.TemplateManager.*;
- import sun.security.pkcs11.wrapper.*;
- import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
-+import sun.security.util.KeyUtil;
-
- /**
- * KeyAgreement implementation class. This class currently supports
-@@ -134,6 +135,8 @@ final class P11KeyAgreement extends KeyA
- BigInteger p, g, y;
- if (key instanceof DHPublicKey) {
- DHPublicKey dhKey = (DHPublicKey)key;
-+ // validate the Diffie-Hellman public key
-+ KeyUtil.validate(dhKey);
- y = dhKey.getY();
- DHParameterSpec params = dhKey.getParams();
- p = params.getP();
-@@ -145,6 +148,8 @@ final class P11KeyAgreement extends KeyA
- try {
- DHPublicKeySpec spec = (DHPublicKeySpec)kf.engineGetKeySpec
- (key, DHPublicKeySpec.class);
-+ // validate the Diffie-Hellman public key
-+ KeyUtil.validate(spec);
- y = spec.getY();
- p = spec.getP();
- g = spec.getG();
-diff --git a/src/share/classes/sun/security/ssl/ClientHandshaker.java b/src/share/classes/sun/security/ssl/ClientHandshaker.java
---- jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java
-+++ jdk/src/share/classes/sun/security/ssl/ClientHandshaker.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
-@@ -168,7 +168,11 @@ final class ClientHandshaker extends Han
- }
- break;
- case K_DH_ANON:
-- this.serverKeyExchange(new DH_ServerKeyExchange(input));
-+ try {
-+ this.serverKeyExchange(new DH_ServerKeyExchange(input));
-+ } catch (GeneralSecurityException e) {
-+ throwSSLException("Server key", e);
-+ }
- break;
- case K_DHE_DSS:
- case K_DHE_RSA:
-@@ -811,7 +815,7 @@ final class ClientHandshaker extends Han
- case K_DHE_RSA:
- case K_DHE_DSS:
- case K_DH_ANON:
-- preMasterSecret = dh.getAgreedSecret(serverDH);
-+ preMasterSecret = dh.getAgreedSecret(serverDH, true);
- break;
- case K_ECDHE_RSA:
- case K_ECDHE_ECDSA:
-diff --git a/src/share/classes/sun/security/ssl/DHClientKeyExchange.java b/src/share/classes/sun/security/ssl/DHClientKeyExchange.java
---- jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java
-+++ jdk/src/share/classes/sun/security/ssl/DHClientKeyExchange.java
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
-+ * Copyright (c) 1997, 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
-@@ -29,7 +29,7 @@ import java.io.IOException;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.math.BigInteger;
--
-+import javax.net.ssl.SSLHandshakeException;
-
- /*
- * Message used by clients to send their Diffie-Hellman public
-@@ -50,7 +50,7 @@ final class DHClientKeyExchange extends
- private byte dh_Yc[]; // 1 to 2^16 -1 bytes
-
- BigInteger getClientPublicKey() {
-- return new BigInteger(1, dh_Yc);
-+ return dh_Yc == null ? null : new BigInteger(1, dh_Yc);
- }
-
- /*
-@@ -72,7 +72,14 @@ final class DHClientKeyExchange extends
- * but that's what the protocol spec requires.)
- */
- DHClientKeyExchange(HandshakeInStream input) throws IOException {
-- dh_Yc = input.getBytes16();
-+ if (input.available() >= 2) {
-+ dh_Yc = input.getBytes16();
-+ } else {
-+ // currently, we don't support cipher suites that requires
-+ // implicit public key of client.
-+ throw new SSLHandshakeException(
-+ "Unsupported implicit client DiffieHellman public key");
-+ }
- }
-
- int messageLength() {
-@@ -84,7 +91,9 @@ final class DHClientKeyExchange extends
- }
-
- void send(HandshakeOutStream s) throws IOException {
-- s.putBytes16(dh_Yc);
-+ if (dh_Yc != null && dh_Yc.length != 0) {
-+ s.putBytes16(dh_Yc);
-+ }
- }
-
- void print(PrintStream s) throws IOException {
-diff --git a/src/share/classes/sun/security/ssl/DHCrypt.java b/src/share/classes/sun/security/ssl/DHCrypt.java
---- jdk/src/share/classes/sun/security/ssl/DHCrypt.java
-+++ jdk/src/share/classes/sun/security/ssl/DHCrypt.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
-@@ -28,11 +28,14 @@ package sun.security.ssl;
-
- import java.math.BigInteger;
- import java.security.*;
-+import java.io.IOException;
-+import javax.net.ssl.SSLHandshakeException;
-
- import javax.crypto.SecretKey;
- import javax.crypto.KeyAgreement;
- import javax.crypto.interfaces.DHPublicKey;
- import javax.crypto.spec.*;
-+import sun.security.util.KeyUtil;
-
- /**
- * This class implements the Diffie-Hellman key exchange algorithm.
-@@ -54,7 +57,8 @@ import javax.crypto.spec.*;
- * . if we are server, call DHCrypt(keyLength,random). This generates
- * an ephemeral keypair of the request length.
- * . if we are client, call DHCrypt(modulus, base, random). This
-- * generates an ephemeral keypair using the parameters specified by the server.
-+ * generates an ephemeral keypair using the parameters specified by
-+ * the server.
- * . send parameters and public value to remote peer
- * . receive peers ephemeral public key
- * . call getAgreedSecret() to calculate the shared secret
-@@ -83,6 +87,9 @@ final class DHCrypt {
- // public component of our key, X = (g ^ x) mod p
- private BigInteger publicValue; // X (aka y)
-
-+ // the times to recover from failure if public key validation
-+ private static int MAX_FAILOVER_TIMES = 2;
-+
- /**
- * Generate a Diffie-Hellman keypair of the specified size.
- */
-@@ -90,9 +97,10 @@ final class DHCrypt {
- try {
- KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
- kpg.initialize(keyLength, random);
-- KeyPair kp = kpg.generateKeyPair();
-- privateKey = kp.getPrivate();
-- DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
-+ DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
-+ if (spec == null) {
-+ throw new RuntimeException("Could not generate DH keypair");
-+ }
- publicValue = spec.getY();
- modulus = spec.getP();
- base = spec.getG();
-@@ -115,9 +123,10 @@ final class DHCrypt {
- KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
- DHParameterSpec params = new DHParameterSpec(modulus, base);
- kpg.initialize(params, random);
-- KeyPair kp = kpg.generateKeyPair();
-- privateKey = kp.getPrivate();
-- DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
-+ DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
-+ if (spec == null) {
-+ throw new RuntimeException("Could not generate DH keypair");
-+ }
- publicValue = spec.getY();
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate DH keypair", e);
-@@ -128,7 +137,8 @@ final class DHCrypt {
- if (key instanceof DHPublicKey) {
- DHPublicKey dhKey = (DHPublicKey)key;
- DHParameterSpec params = dhKey.getParams();
-- return new DHPublicKeySpec(dhKey.getY(), params.getP(), params.getG());
-+ return new DHPublicKeySpec(dhKey.getY(),
-+ params.getP(), params.getG());
- }
- try {
- KeyFactory factory = JsseJce.getKeyFactory("DH");
-@@ -168,16 +178,29 @@ final class DHCrypt {
- * has not been set (or generated).
- *
- * @param peerPublicKey the peer's public key.
-- * @returns the secret, which is an unsigned big-endian integer
-+ * @param keyIsValidated whether the {@code peerPublicKey} has beed
-+ * validated
-+ * @return the secret, which is an unsigned big-endian integer
- * the same size as the Diffie-Hellman modulus.
- */
-- SecretKey getAgreedSecret(BigInteger peerPublicValue) {
-+ SecretKey getAgreedSecret(BigInteger peerPublicValue,
-+ boolean keyIsValidated) throws IOException {
- try {
- KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
- DHPublicKeySpec spec =
- new DHPublicKeySpec(peerPublicValue, modulus, base);
- PublicKey publicKey = kf.generatePublic(spec);
- KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
-+ // validate the Diffie-Hellman public key
-+ if (!keyIsValidated &&
-+ !KeyUtil.isOracleJCEProvider(ka.getProvider().getName())) {
-+ try {
-+ KeyUtil.validate(spec);
-+ } catch (InvalidKeyException ike) {
-+ // prefer handshake_failure alert to internal_error alert
-+ throw new SSLHandshakeException(ike.getMessage());
-+ }
-+ }
- ka.init(privateKey);
- ka.doPhase(publicKey, true);
- return ka.generateSecret("TlsPremasterSecret");
-@@ -186,4 +209,33 @@ final class DHCrypt {
- }
- }
-
-+ // Generate and validate DHPublicKeySpec
-+ private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg)
-+ throws GeneralSecurityException {
-+
-+ boolean doExtraValiadtion =
-+ (!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName()));
-+ for (int i = 0; i <= MAX_FAILOVER_TIMES; i++) {
-+ KeyPair kp = kpg.generateKeyPair();
-+ privateKey = kp.getPrivate();
-+ DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
-+
-+ // validate the Diffie-Hellman public key
-+ if (doExtraValiadtion) {
-+ try {
-+ KeyUtil.validate(spec);
-+ } catch (InvalidKeyException ivke) {
-+ if (i == MAX_FAILOVER_TIMES) {
-+ throw ivke;
-+ }
-+ // otherwise, ignore the exception and try the next one
-+ continue;
-+ }
-+ }
-+
-+ return spec;
-+ }
-+
-+ return null;
-+ }
- }
-diff --git a/src/share/classes/sun/security/ssl/HandshakeMessage.java b/src/share/classes/sun/security/ssl/HandshakeMessage.java
---- jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java
-+++ jdk/src/share/classes/sun/security/ssl/HandshakeMessage.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
-@@ -42,6 +42,7 @@ import javax.security.auth.x500.X500Prin
-
- import javax.crypto.KeyGenerator;
- import javax.crypto.SecretKey;
-+import javax.crypto.spec.DHPublicKeySpec;
- import javax.crypto.spec.SecretKeySpec;
-
- import javax.net.ssl.*;
-@@ -51,6 +52,7 @@ import sun.security.internal.spec.TlsPrf
- import sun.security.internal.spec.TlsPrfParameterSpec;
-
- import sun.security.ssl.CipherSuite.*;
-+import sun.security.util.KeyUtil;
-
- /**
- * Many data structures are involved in the handshake messages. These
-@@ -715,6 +717,7 @@ class DH_ServerKeyExchange extends Serve
- * key exchange.
- */
- DH_ServerKeyExchange(DHCrypt obj) {
-+ // The DH key has been validated in the constructor of DHCrypt.
- getValues(obj);
- signature = null;
- }
-@@ -727,6 +730,7 @@ class DH_ServerKeyExchange extends Serve
- DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
- byte svrNonce[], SecureRandom sr) throws GeneralSecurityException {
-
-+ // The DH key has been validated in the constructor of DHCrypt.
- getValues(obj);
-
- Signature sig;
-@@ -751,10 +755,14 @@ class DH_ServerKeyExchange extends Serve
- * stream, as if sent from server to client for use with
- * DH_anon key exchange
- */
-- DH_ServerKeyExchange(HandshakeInStream input) throws IOException {
-+ DH_ServerKeyExchange(HandshakeInStream input)
-+ throws IOException, GeneralSecurityException {
- dh_p = input.getBytes16();
- dh_g = input.getBytes16();
- dh_Ys = input.getBytes16();
-+ KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
-+ new BigInteger(1, dh_p),
-+ new BigInteger(1, dh_g)));
- signature = null;
- }
-
-@@ -770,7 +778,9 @@ class DH_ServerKeyExchange extends Serve
- dh_p = input.getBytes16();
- dh_g = input.getBytes16();
- dh_Ys = input.getBytes16();
--
-+ KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
-+ new BigInteger(1, dh_p),
-+ new BigInteger(1, dh_g)));
- byte signature[];
- if (dhKeyExchangeFix) {
- signature = input.getBytes16();
-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
-@@ -36,7 +36,7 @@ import javax.net.ssl.*;
- import javax.net.ssl.*;
-
- import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
--import sun.security.util.KeyLength;
-+import sun.security.util.KeyUtil;
-
- /**
- * This is the client key exchange message (CLIENT --> SERVER) used with
-@@ -194,7 +194,7 @@ final class RSAClientKeyExchange extends
- "unable to get the plaintext of the premaster secret");
- }
-
-- int keySize = KeyLength.getKeySize(secretKey);
-+ int keySize = KeyUtil.getKeySize(secretKey);
- if (keySize > 0 && keySize != 384) { // 384 = 48 * 8
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
-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
-@@ -1147,7 +1147,7 @@ final class ServerHandshaker extends Han
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
-- return dh.getAgreedSecret(mesg.getClientPublicKey());
-+ return dh.getAgreedSecret(mesg.getClientPublicKey(), false);
- }
-
- private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
-diff --git a/src/share/classes/sun/security/util/KeyLength.java b/src/share/classes/sun/security/util/KeyLength.java
-deleted file mode 100644
---- jdk/src/share/classes/sun/security/util/KeyLength.java
-+++ /dev/null
-@@ -1,91 +0,0 @@
--/*
-- * 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/KeyUtil.java b/src/share/classes/sun/security/util/KeyUtil.java
-new file mode 100644
---- /dev/null
-+++ jdk/src/share/classes/sun/security/util/KeyUtil.java
-@@ -0,0 +1,184 @@
-+/*
-+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
-+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-+ *
-+ */
-+
-+package sun.security.util;
-+
-+import java.security.Key;
-+import java.security.PrivilegedAction;
-+import java.security.AccessController;
-+import java.security.InvalidKeyException;
-+import java.security.interfaces.ECKey;
-+import java.security.interfaces.RSAKey;
-+import java.security.interfaces.DSAKey;
-+import java.security.spec.KeySpec;
-+import javax.crypto.SecretKey;
-+import javax.crypto.interfaces.DHKey;
-+import javax.crypto.interfaces.DHPublicKey;
-+import javax.crypto.spec.DHParameterSpec;
-+import javax.crypto.spec.DHPublicKeySpec;
-+import java.math.BigInteger;
-+
-+/**
-+ * A utility class to get key length, valiate keys, etc.
-+ */
-+public final class KeyUtil {
-+
-+ /**
-+ * 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
-+ */
-+ public static final 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;
-+ }
-+
-+ /**
-+ * Returns whether the key is valid or not.
-+ * <P>
-+ * Note that this method is only apply to DHPublicKey at present.
-+ *
-+ * @param publicKey
-+ * the key object, cannot be null
-+ *
-+ * @throws NullPointerException if {@code publicKey} is null
-+ * @throws InvalidKeyException if {@code publicKey} is invalid
-+ */
-+ public static final void validate(Key key)
-+ throws InvalidKeyException {
-+ if (key == null) {
-+ throw new NullPointerException(
-+ "The key to be validated cannot be null");
-+ }
-+
-+ if (key instanceof DHPublicKey) {
-+ validateDHPublicKey((DHPublicKey)key);
-+ }
-+ }
-+
-+
-+ /**
-+ * Returns whether the key spec is valid or not.
-+ * <P>
-+ * Note that this method is only apply to DHPublicKeySpec at present.
-+ *
-+ * @param keySpec
-+ * the key spec object, cannot be null
-+ *
-+ * @throws NullPointerException if {@code keySpec} is null
-+ * @throws InvalidKeyException if {@code keySpec} is invalid
-+ */
-+ public static final void validate(KeySpec keySpec)
-+ throws InvalidKeyException {
-+ if (keySpec == null) {
-+ throw new NullPointerException(
-+ "The key spec to be validated cannot be null");
-+ }
-+
-+ if (keySpec instanceof DHPublicKeySpec) {
-+ validateDHPublicKey((DHPublicKeySpec)keySpec);
-+ }
-+ }
-+
-+ /**
-+ * Returns whether the specified provider is Oracle provider or not.
-+ * <P>
-+ * Note that this method is only apply to SunJCE and SunPKCS11 at present.
-+ *
-+ * @param providerName
-+ * the provider name
-+ * @return true if, and only if, the provider of the specified
-+ * {@code providerName} is Oracle provider
-+ */
-+ public static final boolean isOracleJCEProvider(String providerName) {
-+ return providerName != null && (providerName.equals("SunJCE") ||
-+ providerName.startsWith("SunPKCS11"));
-+ }
-+
-+ /**
-+ * Returns whether the Diffie-Hellman public key is valid or not.
-+ *
-+ * Per RFC 2631 and NIST SP800-56A, the following algorithm is used to
-+ * validate Diffie-Hellman public keys:
-+ * 1. Verify that y lies within the interval [2,p-1]. If it does not,
-+ * the key is invalid.
-+ * 2. Compute y^q mod p. If the result == 1, the key is valid.
-+ * Otherwise the key is invalid.
-+ */
-+ private static void validateDHPublicKey(DHPublicKey publicKey)
-+ throws InvalidKeyException {
-+ DHParameterSpec paramSpec = publicKey.getParams();
-+
-+ BigInteger p = paramSpec.getP();
-+ BigInteger g = paramSpec.getG();
-+ BigInteger y = publicKey.getY();
-+
-+ validateDHPublicKey(p, g, y);
-+ }
-+
-+ private static void validateDHPublicKey(DHPublicKeySpec publicKeySpec)
-+ throws InvalidKeyException {
-+ validateDHPublicKey(publicKeySpec.getP(),
-+ publicKeySpec.getG(), publicKeySpec.getY());
-+ }
-+
-+ private static void validateDHPublicKey(BigInteger p,
-+ BigInteger g, BigInteger y) throws InvalidKeyException {
-+
-+ // For better interoperability, the interval is limited to [2, p-2].
-+ BigInteger leftOpen = BigInteger.ONE;
-+ BigInteger rightOpen = p.subtract(BigInteger.ONE);
-+ if (y.compareTo(leftOpen) <= 0) {
-+ throw new InvalidKeyException(
-+ "Diffie-Hellman public key is too small");
-+ }
-+ if (y.compareTo(rightOpen) >= 0) {
-+ throw new InvalidKeyException(
-+ "Diffie-Hellman public key is too large");
-+ }
-+
-+ // Don't bother to check against the y^q mod p if safe primes are used.
-+ }
-+}