< prev index next >

src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java

Print this page

        

@@ -25,25 +25,36 @@
 
 package sun.security.ssl;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.security.GeneralSecurityException;
+import java.security.CryptoPrimitive;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.Key;
+import java.security.KeyFactory;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.Signature;
 import java.security.SignatureException;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
 import java.text.MessageFormat;
+import java.util.EnumSet;
 import java.util.Locale;
+import sun.security.ssl.ECDHKeyExchange.ECDHECredentials;
+import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
 import sun.security.ssl.SSLHandshake.HandshakeMessage;
+import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
 import sun.security.ssl.X509Authentication.X509Credentials;
 import sun.security.ssl.X509Authentication.X509Possession;
+import sun.security.util.ECUtil;
 import sun.security.util.HexDumpEncoder;
 
 /**
  * Pack of the ServerKeyExchange handshake message.
  */

@@ -67,58 +78,58 @@
         private final byte[] publicPoint;
 
         // signature bytes, or null if anonymous
         private final byte[] paramsSignature;
 
+        // public key object encapsulated in this message
+        private final ECPublicKey publicKey;
+
         private final boolean useExplicitSigAlgorithm;
 
         // the signature algorithm used by this ServerKeyExchange message
         private final SignatureScheme signatureScheme;
 
-        // the parsed credential object
-        private SSLCredentials sslCredentials;
-
         ECDHServerKeyExchangeMessage(
                 HandshakeContext handshakeContext) throws IOException {
             super(handshakeContext);
 
             // This happens in server side only.
             ServerHandshakeContext shc =
                     (ServerHandshakeContext)handshakeContext;
 
-            // Find the Possessions needed
-            NamedGroupPossession namedGroupPossession = null;
+            ECDHEPossession ecdhePossession = null;
             X509Possession x509Possession = null;
             for (SSLPossession possession : shc.handshakePossessions) {
-                if (possession instanceof NamedGroupPossession) {
-                    namedGroupPossession = (NamedGroupPossession)possession;
+                if (possession instanceof ECDHEPossession) {
+                    ecdhePossession = (ECDHEPossession)possession;
                     if (x509Possession != null) {
                         break;
                     }
                 } else if (possession instanceof X509Possession) {
                     x509Possession = (X509Possession)possession;
-                    if (namedGroupPossession != null) {
+                    if (ecdhePossession != null) {
                         break;
                     }
                 }
             }
 
-            if (namedGroupPossession == null) {
+            if (ecdhePossession == null) {
                 // unlikely
                 throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
                     "No ECDHE credentials negotiated for server key exchange");
             }
 
-            // Find the NamedGroup used for the ephemeral keys.
-            namedGroup = namedGroupPossession.getNamedGroup();
-            publicPoint = namedGroup.encodePossessionPublicKey(
-                    namedGroupPossession);
+            publicKey = ecdhePossession.publicKey;
+            ECParameterSpec params = publicKey.getParams();
+            ECPoint point = publicKey.getW();
+            publicPoint = ECUtil.encodePoint(point, params.getCurve());
 
+            this.namedGroup = NamedGroup.valueOf(params);
             if ((namedGroup == null) || (namedGroup.oid == null) ) {
                 // unlikely
                 throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
-                    "Missing Named Group");
+                    "Unnamed EC parameter spec: " + params);
             }
 
             if (x509Possession == null) {
                 // anonymous, no authentication, no signature
                 paramsSignature = null;

@@ -203,27 +214,43 @@
             if (!SupportedGroups.isSupported(namedGroup)) {
                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
                     "Unsupported named group: " + namedGroup);
             }
 
+            if (namedGroup.oid == null) {
+                throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
+                    "Unknown named EC curve: " + namedGroup);
+            }
+
+            ECParameterSpec parameters =
+                    ECUtil.getECParameterSpec(null, namedGroup.oid);
+            if (parameters == null) {
+                throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
+                    "No supported EC parameter: " + namedGroup);
+            }
+
             publicPoint = Record.getBytes8(m);
             if (publicPoint.length == 0) {
                 throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
-                    "Insufficient Point data: " + namedGroup);
+                    "Insufficient ECPoint data: " + namedGroup);
             }
 
+            ECPublicKey ecPublicKey = null;
             try {
-                sslCredentials = namedGroup.decodeCredentials(
-                    publicPoint, handshakeContext.algorithmConstraints,
-                     s -> chc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
-                     "ServerKeyExchange " + namedGroup + ": " + (s)));
-            } catch (GeneralSecurityException ex) {
-                throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
-                        "Cannot decode named group: " +
-                        NamedGroup.nameOf(namedGroupId));
+                ECPoint point =
+                        ECUtil.decodePoint(publicPoint, parameters.getCurve());
+                KeyFactory factory = KeyFactory.getInstance("EC");
+                ecPublicKey = (ECPublicKey)factory.generatePublic(
+                    new ECPublicKeySpec(point, parameters));
+            } catch (NoSuchAlgorithmException |
+                    InvalidKeySpecException | IOException ex) {
+                throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
+                    "Invalid ECPoint: " + namedGroup, ex);
             }
 
+            publicKey = ecPublicKey;
+
             X509Credentials x509Credentials = null;
             for (SSLCredentials cd : chc.handshakeCredentials) {
                 if (cd instanceof X509Credentials) {
                     x509Credentials = (X509Credentials)cd;
                     break;

@@ -500,22 +527,34 @@
         public void consume(ConnectionContext context,
                 ByteBuffer message) throws IOException {
             // The consuming happens in client side only.
             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 
-            // AlgorithmConstraints are checked during decoding
             ECDHServerKeyExchangeMessage skem =
                     new ECDHServerKeyExchangeMessage(chc, message);
             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                 SSLLogger.fine(
                     "Consuming ECDH ServerKeyExchange handshake message", skem);
             }
 
             //
+            // validate
+            //
+            // check constraints of EC PublicKey
+            if (!chc.algorithmConstraints.permits(
+                    EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
+                    skem.publicKey)) {
+                throw chc.conContext.fatal(Alert.INSUFFICIENT_SECURITY,
+                        "ECDH ServerKeyExchange does not comply " +
+                        "to algorithm constraints");
+            }
+
+            //
             // update
             //
-            chc.handshakeCredentials.add(skem.sslCredentials);
+            chc.handshakeCredentials.add(
+                    new ECDHECredentials(skem.publicKey, skem.namedGroup));
 
             //
             // produce
             //
             // Need no new handshake message producers here.
< prev index next >