diff options
Diffstat (limited to 'java/openjdk6/files/icedtea/security/20130201/7192392.patch')
-rw-r--r-- | java/openjdk6/files/icedtea/security/20130201/7192392.patch | 695 |
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. -+ } -+} |