8076328: Enforce key exchange constraints
authorxuelei
Wed, 22 Apr 2015 05:09:54 +0000
changeset 31712 e4d5230193da
parent 31711 cca718f2fcf0
child 31713 8d27f9edac84
8076328: Enforce key exchange constraints Reviewed-by: wetmore, igerasim, ahgross, asmotrak
jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java
jdk/src/java.base/share/classes/sun/security/ssl/DHCrypt.java
jdk/src/java.base/share/classes/sun/security/ssl/ECDHCrypt.java
jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java
jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java
jdk/src/java.base/share/conf/security/java.security
jdk/test/javax/net/ssl/sanity/interop/ClientJSSEServerJSSE.java
jdk/test/sun/security/ec/TestEC.java
jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java
jdk/test/sun/security/ssl/DHKeyExchange/DHEKeySizing.java
jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java	Wed Apr 22 05:09:54 2015 +0000
@@ -723,6 +723,14 @@
             // NOTREACHED
         }
         ephemeralServerKey = mesg.getPublicKey();
+
+        // check constraints of RSA PublicKey
+        if (!algorithmConstraints.permits(
+            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), ephemeralServerKey)) {
+
+            throw new SSLHandshakeException("RSA ServerKeyExchange " +
+                    "does not comply to algorithm constraints");
+        }
     }
 
     /*
@@ -739,6 +747,9 @@
         dh = new DHCrypt(mesg.getModulus(), mesg.getBase(),
                                             sslContext.getSecureRandom());
         serverDH = mesg.getServerPublicKey();
+
+        // check algorithm constraints
+        dh.checkConstraints(algorithmConstraints, serverDH);
     }
 
     private void serverKeyExchange(ECDH_ServerKeyExchange mesg)
@@ -749,6 +760,14 @@
         ECPublicKey key = mesg.getPublicKey();
         ecdh = new ECDHCrypt(key.getParams(), sslContext.getSecureRandom());
         ephemeralServerKey = key;
+
+        // check constraints of EC PublicKey
+        if (!algorithmConstraints.permits(
+            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), ephemeralServerKey)) {
+
+            throw new SSLHandshakeException("ECDH ServerKeyExchange " +
+                    "does not comply to algorithm constraints");
+        }
     }
 
     /*
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DHCrypt.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DHCrypt.java	Wed Apr 22 05:09:54 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, 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
@@ -34,6 +34,7 @@
 import javax.crypto.KeyAgreement;
 import javax.crypto.interfaces.DHPublicKey;
 import javax.crypto.spec.*;
+import java.util.EnumSet;
 
 import sun.security.util.KeyUtil;
 
@@ -216,6 +217,28 @@
         }
     }
 
+    // Check constraints of the specified DH public key.
+    void checkConstraints(AlgorithmConstraints constraints,
+            BigInteger peerPublicValue) throws SSLHandshakeException {
+
+        try {
+            KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
+            DHPublicKeySpec spec =
+                        new DHPublicKeySpec(peerPublicValue, modulus, base);
+            DHPublicKey publicKey = (DHPublicKey)kf.generatePublic(spec);
+
+            // check constraints of DHPublicKey
+            if (!constraints.permits(
+                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
+                throw new SSLHandshakeException(
+                    "DHPublicKey does not comply to algorithm constraints");
+            }
+        } catch (GeneralSecurityException gse) {
+            throw (SSLHandshakeException) new SSLHandshakeException(
+                    "Could not generate DHPublicKey").initCause(gse);
+        }
+    }
+
     // Generate and validate DHPublicKeySpec
     private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg)
             throws GeneralSecurityException {
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ECDHCrypt.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ECDHCrypt.java	Wed Apr 22 05:09:54 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, 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,6 +29,7 @@
 import java.security.interfaces.ECPublicKey;
 import java.security.spec.*;
 
+import java.util.EnumSet;
 import javax.crypto.SecretKey;
 import javax.crypto.KeyAgreement;
 import javax.net.ssl.SSLHandshakeException;
@@ -88,8 +89,11 @@
         return publicKey;
     }
 
-    // called by ClientHandshaker with either the server's static or ephemeral public key
-    SecretKey getAgreedSecret(PublicKey peerPublicKey) throws SSLHandshakeException {
+    // called by ClientHandshaker with either the server's static or
+    // ephemeral public key
+    SecretKey getAgreedSecret(
+            PublicKey peerPublicKey) throws SSLHandshakeException {
+
         try {
             KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
             ka.init(privateKey);
@@ -102,10 +106,13 @@
     }
 
     // called by ServerHandshaker
-    SecretKey getAgreedSecret(byte[] encodedPoint) throws SSLHandshakeException {
+    SecretKey getAgreedSecret(
+            byte[] encodedPoint) throws SSLHandshakeException {
+
         try {
             ECParameterSpec params = publicKey.getParams();
-            ECPoint point = JsseJce.decodePoint(encodedPoint, params.getCurve());
+            ECPoint point =
+                    JsseJce.decodePoint(encodedPoint, params.getCurve());
             KeyFactory kf = JsseJce.getKeyFactory("EC");
             ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
             PublicKey peerPublicKey = kf.generatePublic(spec);
@@ -116,4 +123,30 @@
         }
     }
 
+    // Check constraints of the specified EC public key.
+    void checkConstraints(AlgorithmConstraints constraints,
+            byte[] encodedPoint) throws SSLHandshakeException {
+
+        try {
+
+            ECParameterSpec params = publicKey.getParams();
+            ECPoint point =
+                    JsseJce.decodePoint(encodedPoint, params.getCurve());
+            ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
+
+            KeyFactory kf = JsseJce.getKeyFactory("EC");
+            ECPublicKey publicKey = (ECPublicKey)kf.generatePublic(spec);
+
+            // check constraints of ECPublicKey
+            if (!constraints.permits(
+                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), publicKey)) {
+                throw new SSLHandshakeException(
+                    "ECPublicKey does not comply to algorithm constraints");
+            }
+        } catch (GeneralSecurityException | java.io.IOException e) {
+            throw (SSLHandshakeException) new SSLHandshakeException(
+                    "Could not generate ECPublicKey").initCause(e);
+        }
+    }
+
 }
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java	Wed Apr 22 05:09:54 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, 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
@@ -87,7 +87,7 @@
     String                      identificationProtocol;
 
     // The cryptographic algorithm constraints
-    private AlgorithmConstraints    algorithmConstraints = null;
+    AlgorithmConstraints        algorithmConstraints = null;
 
     // Local supported signature and algorithms
     Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java	Wed Apr 22 05:09:54 2015 +0000
@@ -32,6 +32,7 @@
 import java.security.cert.*;
 import java.security.interfaces.*;
 import java.security.spec.ECParameterSpec;
+import java.math.BigInteger;
 
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
@@ -1571,7 +1572,13 @@
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
         }
-        return dh.getAgreedSecret(mesg.getClientPublicKey(), false);
+
+        BigInteger publicKeyValue = mesg.getClientPublicKey();
+
+        // check algorithm constraints
+        dh.checkConstraints(algorithmConstraints, publicKeyValue);
+
+        return dh.getAgreedSecret(publicKeyValue, false);
     }
 
     private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
@@ -1580,7 +1587,13 @@
         if (debug != null && Debug.isOn("handshake")) {
             mesg.print(System.out);
         }
-        return ecdh.getAgreedSecret(mesg.getEncodedPoint());
+
+        byte[] publicPoint = mesg.getEncodedPoint();
+
+        // check algorithm constraints
+        ecdh.checkConstraints(algorithmConstraints, publicPoint);
+
+        return ecdh.getAgreedSecret(publicPoint);
     }
 
     /*
--- a/jdk/src/java.base/share/conf/security/java.security	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/src/java.base/share/conf/security/java.security	Wed Apr 22 05:09:54 2015 +0000
@@ -541,7 +541,7 @@
 #
 # Example:
 #   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3, RC4
+jdk.tls.disabledAlgorithms=SSLv3, RC4, DH keySize < 768
 
 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS)
 # processing in JSSE implementation.
@@ -580,7 +580,7 @@
 #     1. JSSE cipher suite name, e.g., TLS_RSA_WITH_AES_128_CBC_SHA
 #     2. JSSE key exchange algorithm name, e.g., RSA
 #     3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC
-#     4. JSSE message digest algorithm name, e.g., SHA-1
+#     4. JSSE message digest algorithm name, e.g., SHA
 #
 # See SSL/TLS specifications and "Java Cryptography Architecture Standard
 # Algorithm Name Documentation" for information about the algorithm names.
@@ -598,4 +598,4 @@
         DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \
         DH_RSA_EXPORT, RSA_EXPORT, \
         DH_anon, ECDH_anon, \
-        RC4_128, RC4_40, DES_CBC, DES40_CBC
\ No newline at end of file
+        RC4_128, RC4_40, DES_CBC, DES40_CBC
--- a/jdk/test/javax/net/ssl/sanity/interop/ClientJSSEServerJSSE.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/test/javax/net/ssl/sanity/interop/ClientJSSEServerJSSE.java	Wed Apr 22 05:09:54 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, 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
@@ -33,13 +33,10 @@
 public class ClientJSSEServerJSSE {
 
     public static void main(String[] args) throws Exception {
-        // reset the security property to make sure that the algorithms
+        // reset security properties to make sure that the algorithms
         // and keys used in this test are not disabled.
         Security.setProperty("jdk.tls.disabledAlgorithms", "");
-
-        // MD5 is used in this test case, don't disable MD5 algorithm.
-        Security.setProperty(
-                "jdk.certpath.disabledAlgorithms", "MD2, RSA keySize < 1024");
+        Security.setProperty("jdk.certpath.disabledAlgorithms", "");
 
         CipherTest.main(new JSSEFactory(), args);
     }
--- a/jdk/test/sun/security/ec/TestEC.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/test/sun/security/ec/TestEC.java	Wed Apr 22 05:09:54 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, 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
@@ -60,13 +60,10 @@
 public class TestEC {
 
     public static void main(String[] args) throws Exception {
-        // reset the security property to make sure that the algorithms
+        // reset security properties to make sure that the algorithms
         // and keys used in this test are not disabled.
         Security.setProperty("jdk.tls.disabledAlgorithms", "");
-
-        // MD5 is used in this test case, don't disable MD5 algorithm.
-        Security.setProperty(
-                "jdk.certpath.disabledAlgorithms", "MD2, RSA keySize < 1024");
+        Security.setProperty("jdk.certpath.disabledAlgorithms", "");
 
         ProvidersSnapshot snapshot = ProvidersSnapshot.create();
         try {
--- a/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java	Wed Apr 22 05:09:54 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, 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
@@ -43,18 +43,15 @@
     private static String[] cmdArgs;
 
     public static void main(String[] args) throws Exception {
-        // reset the security property to make sure that the algorithms
-        // and keys used in this test are not disabled.
-        Security.setProperty("jdk.tls.disabledAlgorithms", "");
-
         cmdArgs = args;
         main(new ClientJSSEServerJSSE());
     }
 
     public void main(Provider p) throws Exception {
-        // MD5 is used in this test case, don't disable MD5 algorithm.
-        Security.setProperty(
-                "jdk.certpath.disabledAlgorithms", "MD2, RSA keySize < 1024");
+        // reset security properties to make sure that the algorithms
+        // and keys used in this test are not disabled.
+        Security.setProperty("jdk.tls.disabledAlgorithms", "");
+        Security.setProperty("jdk.certpath.disabledAlgorithms", "");
 
         if (p.getService("KeyFactory", "EC") == null) {
             System.out.println("Provider does not support EC, skipping");
--- a/jdk/test/sun/security/ssl/DHKeyExchange/DHEKeySizing.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/test/sun/security/ssl/DHKeyExchange/DHEKeySizing.java	Wed Apr 22 05:09:54 2015 +0000
@@ -377,9 +377,10 @@
     }
 
     public static void main(String args[]) throws Exception {
-        // reset the security property to make sure that the algorithms
+        // reset security properties to make sure that the algorithms
         // and keys used in this test are not disabled.
         Security.setProperty("jdk.tls.disabledAlgorithms", "");
+        Security.setProperty("jdk.certpath.disabledAlgorithms", "");
 
         if (args.length != 4) {
             System.out.println(
--- a/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java	Tue Apr 21 20:33:34 2015 +0100
+++ b/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java	Wed Apr 22 05:09:54 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, 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
@@ -21,19 +21,22 @@
  * questions.
  */
 
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
 /*
  * @test
  * @bug 4392475
  * @summary Calling setWantClientAuth(true) disables anonymous suites
  * @run main/othervm/timeout=180 AnonCipherWithWantClientAuth
- *
- *     SunJSSE does not support dynamic system properties, no way to re-use
- *     system properties in samevm/agentvm mode.
  */
 
 import java.io.*;
 import java.net.*;
 import javax.net.ssl.*;
+import java.security.Security;
 
 public class AnonCipherWithWantClientAuth {
 
@@ -156,6 +159,11 @@
     volatile Exception clientException = null;
 
     public static void main(String[] args) throws Exception {
+        // reset security properties to make sure that the algorithms
+        // and keys used in this test are not disabled.
+        Security.setProperty("jdk.tls.disabledAlgorithms", "");
+        Security.setProperty("jdk.certpath.disabledAlgorithms", "");
+
         String keyFilename =
             System.getProperty("test.src", "./") + "/" + pathToStores +
                 "/" + keyStoreFile;