< prev index next >

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

Print this page

        

@@ -34,16 +34,23 @@
 import java.security.KeyPairGenerator;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidKeySpecException;
+import javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
 import javax.crypto.interfaces.DHPublicKey;
 import javax.crypto.spec.DHParameterSpec;
 import javax.crypto.spec.DHPublicKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.SSLHandshakeException;
 import sun.security.action.GetPropertyAction;
-import sun.security.ssl.NamedGroup.NamedGroupType;
+import sun.security.ssl.CipherSuite.HashAlg;
+import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
+import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
 import sun.security.ssl.X509Authentication.X509Possession;
 import sun.security.util.KeyUtil;
 
 final class DHKeyExchange {

@@ -52,29 +59,19 @@
     static final SSLPossessionGenerator poExportableGenerator =
             new DHEPossessionGenerator(true);
     static final SSLKeyAgreementGenerator kaGenerator =
             new DHEKAGenerator();
 
-    static final class DHECredentials implements NamedGroupCredentials {
+    static final class DHECredentials implements SSLCredentials {
         final DHPublicKey popPublicKey;
         final NamedGroup namedGroup;
 
         DHECredentials(DHPublicKey popPublicKey, NamedGroup namedGroup) {
             this.popPublicKey = popPublicKey;
             this.namedGroup = namedGroup;
         }
 
-        @Override
-        public PublicKey getPublicKey() {
-            return popPublicKey;
-        }
-
-        @Override
-        public NamedGroup getNamedGroup() {
-            return namedGroup;
-        }
-
         static DHECredentials valueOf(NamedGroup ng,
             byte[] encodedPublic) throws IOException, GeneralSecurityException {
 
             if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
                 throw new RuntimeException(

@@ -99,11 +96,11 @@
 
             return new DHECredentials(publicKey, ng);
         }
     }
 
-    static final class DHEPossession implements NamedGroupPossession {
+    static final class DHEPossession implements SSLPossession {
         final PrivateKey privateKey;
         final DHPublicKey publicKey;
         final NamedGroup namedGroup;
 
         DHEPossession(NamedGroup namedGroup, SecureRandom random) {

@@ -175,17 +172,17 @@
         }
 
         // Generate and validate DHPublicKeySpec
         private KeyPair generateDHKeyPair(
                 KeyPairGenerator kpg) throws GeneralSecurityException {
-            boolean doExtraValidation =
+            boolean doExtraValiadtion =
                     (!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName()));
             boolean isRecovering = false;
             for (int i = 0; i <= 2; i++) {      // Try to recover from failure.
                 KeyPair kp = kpg.generateKeyPair();
                 // validate the Diffie-Hellman public key
-                if (doExtraValidation) {
+                if (doExtraValiadtion) {
                     DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
                     try {
                         KeyUtil.validate(spec);
                     } catch (InvalidKeyException ivke) {
                         if (isRecovering) {

@@ -232,25 +229,10 @@
                 encoded = buffer;
             }
 
             return encoded;
         }
-
-        @Override
-        public PublicKey getPublicKey() {
-            return publicKey;
-        }
-
-        @Override
-        public NamedGroup getNamedGroup() {
-            return namedGroup;
-        }
-
-        @Override
-        public PrivateKey getPrivateKey() {
-            return privateKey;
-        }
     }
 
     private static final class
             DHEPossessionGenerator implements SSLPossessionGenerator {
         // Flag to use smart ephemeral DH key which size matches the

@@ -314,20 +296,19 @@
         }
 
         // Used for ServerKeyExchange, TLS 1.2 and prior versions.
         @Override
         public SSLPossession createPossession(HandshakeContext context) {
-            NamedGroup preferableNamedGroup;
+            NamedGroup preferableNamedGroup = null;
             if (!useLegacyEphemeralDHKeys &&
                     (context.clientRequestedNamedGroups != null) &&
                     (!context.clientRequestedNamedGroups.isEmpty())) {
                 preferableNamedGroup =
                         SupportedGroups.getPreferredGroup(
                                 context.negotiatedProtocol,
                                 context.algorithmConstraints,
-                                new NamedGroupType [] {
-                                    NamedGroupType.NAMED_GROUP_FFDHE },
+                                NamedGroupType.NAMED_GROUP_FFDHE,
                                 context.clientRequestedNamedGroups);
                 if (preferableNamedGroup != null) {
                     return new DHEPossession(preferableNamedGroup,
                                 context.sslContext.getSecureRandom());
                 }

@@ -409,11 +390,11 @@
         }
     }
 
     private static final
             class DHEKAGenerator implements SSLKeyAgreementGenerator {
-        private static final DHEKAGenerator instance = new DHEKAGenerator();
+        static private DHEKAGenerator instance = new DHEKAGenerator();
 
         // Prevent instantiation of this class.
         private DHEKAGenerator() {
             // blank
         }

@@ -459,10 +440,95 @@
             if (dhePossession == null || dheCredentials == null) {
                 throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
                     "No sufficient DHE key agreement parameters negotiated");
             }
 
-            return new KAKeyDerivation("DiffieHellman", context,
+            return new DHEKAKeyDerivation(context,
                     dhePossession.privateKey, dheCredentials.popPublicKey);
         }
+
+        private static final
+                class DHEKAKeyDerivation implements SSLKeyDerivation {
+            private final HandshakeContext context;
+            private final PrivateKey localPrivateKey;
+            private final PublicKey peerPublicKey;
+
+            DHEKAKeyDerivation(HandshakeContext context,
+                    PrivateKey localPrivateKey,
+                    PublicKey peerPublicKey) {
+                this.context = context;
+                this.localPrivateKey = localPrivateKey;
+                this.peerPublicKey = peerPublicKey;
+            }
+
+            @Override
+            public SecretKey deriveKey(String algorithm,
+                    AlgorithmParameterSpec params) throws IOException {
+                if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
+                    return t12DeriveKey(algorithm, params);
+                } else {
+                    return t13DeriveKey(algorithm, params);
+                }
+            }
+
+            private SecretKey t12DeriveKey(String algorithm,
+                    AlgorithmParameterSpec params) throws IOException {
+                try {
+                    KeyAgreement ka = KeyAgreement.getInstance("DiffieHellman");
+                    ka.init(localPrivateKey);
+                    ka.doPhase(peerPublicKey, true);
+                    SecretKey preMasterSecret =
+                            ka.generateSecret("TlsPremasterSecret");
+                    SSLMasterKeyDerivation mskd =
+                            SSLMasterKeyDerivation.valueOf(
+                                    context.negotiatedProtocol);
+                    if (mskd == null) {
+                        // unlikely
+                        throw new SSLHandshakeException(
+                            "No expected master key derivation for protocol: " +
+                            context.negotiatedProtocol.name);
+                    }
+                    SSLKeyDerivation kd = mskd.createKeyDerivation(
+                            context, preMasterSecret);
+                    return kd.deriveKey("MasterSecret", params);
+                } catch (GeneralSecurityException gse) {
+                    throw (SSLHandshakeException) new SSLHandshakeException(
+                        "Could not generate secret").initCause(gse);
+                }
+            }
+
+            private SecretKey t13DeriveKey(String algorithm,
+                    AlgorithmParameterSpec params) throws IOException {
+                try {
+                    KeyAgreement ka = KeyAgreement.getInstance("DiffieHellman");
+                    ka.init(localPrivateKey);
+                    ka.doPhase(peerPublicKey, true);
+                    SecretKey sharedSecret =
+                            ka.generateSecret("TlsPremasterSecret");
+
+                    HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
+                    SSLKeyDerivation kd = context.handshakeKeyDerivation;
+                    HKDF hkdf = new HKDF(hashAlg.name);
+                    if (kd == null) {   // No PSK is in use.
+                        // If PSK is not in use Early Secret will still be
+                        // HKDF-Extract(0, 0).
+                        byte[] zeros = new byte[hashAlg.hashLength];
+                        SecretKeySpec ikm =
+                                new SecretKeySpec(zeros, "TlsPreSharedSecret");
+                        SecretKey earlySecret =
+                                hkdf.extract(zeros, ikm, "TlsEarlySecret");
+                        kd = new SSLSecretDerivation(context, earlySecret);
+                    }
+
+                    // derive salt secret
+                    SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
+
+                    // derive handshake secret
+                    return hkdf.extract(saltSecret, sharedSecret, algorithm);
+                } catch (GeneralSecurityException gse) {
+                    throw (SSLHandshakeException) new SSLHandshakeException(
+                        "Could not generate secret").initCause(gse);
+                }
+            }
+        }
     }
 }
< prev index next >