< prev index next >

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

Print this page

        

*** 34,49 **** import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPublicKeySpec; import sun.security.action.GetPropertyAction; ! import sun.security.ssl.NamedGroup.NamedGroupType; import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.X509Authentication.X509Possession; import sun.security.util.KeyUtil; final class DHKeyExchange { --- 34,56 ---- 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.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,80 **** static final SSLPossessionGenerator poExportableGenerator = new DHEPossessionGenerator(true); static final SSLKeyAgreementGenerator kaGenerator = new DHEKAGenerator(); ! static final class DHECredentials implements NamedGroupCredentials { 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( --- 59,77 ---- static final SSLPossessionGenerator poExportableGenerator = new DHEPossessionGenerator(true); static final SSLKeyAgreementGenerator kaGenerator = new DHEKAGenerator(); ! static final class DHECredentials implements SSLCredentials { final DHPublicKey popPublicKey; final NamedGroup namedGroup; DHECredentials(DHPublicKey popPublicKey, NamedGroup namedGroup) { this.popPublicKey = popPublicKey; this.namedGroup = namedGroup; } static DHECredentials valueOf(NamedGroup ng, byte[] encodedPublic) throws IOException, GeneralSecurityException { if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) { throw new RuntimeException(
*** 99,109 **** return new DHECredentials(publicKey, ng); } } ! static final class DHEPossession implements NamedGroupPossession { final PrivateKey privateKey; final DHPublicKey publicKey; final NamedGroup namedGroup; DHEPossession(NamedGroup namedGroup, SecureRandom random) { --- 96,106 ---- return new DHECredentials(publicKey, ng); } } ! static final class DHEPossession implements SSLPossession { final PrivateKey privateKey; final DHPublicKey publicKey; final NamedGroup namedGroup; DHEPossession(NamedGroup namedGroup, SecureRandom random) {
*** 175,191 **** } // Generate and validate DHPublicKeySpec private KeyPair generateDHKeyPair( KeyPairGenerator kpg) throws GeneralSecurityException { ! boolean doExtraValidation = (!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) { DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); try { KeyUtil.validate(spec); } catch (InvalidKeyException ivke) { if (isRecovering) { --- 172,188 ---- } // Generate and validate DHPublicKeySpec private KeyPair generateDHKeyPair( KeyPairGenerator kpg) throws GeneralSecurityException { ! 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 (doExtraValiadtion) { DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic()); try { KeyUtil.validate(spec); } catch (InvalidKeyException ivke) { if (isRecovering) {
*** 232,256 **** 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 --- 229,238 ----
*** 314,333 **** } // Used for ServerKeyExchange, TLS 1.2 and prior versions. @Override public SSLPossession createPossession(HandshakeContext context) { ! NamedGroup preferableNamedGroup; if (!useLegacyEphemeralDHKeys && (context.clientRequestedNamedGroups != null) && (!context.clientRequestedNamedGroups.isEmpty())) { preferableNamedGroup = SupportedGroups.getPreferredGroup( context.negotiatedProtocol, context.algorithmConstraints, ! new NamedGroupType [] { ! NamedGroupType.NAMED_GROUP_FFDHE }, context.clientRequestedNamedGroups); if (preferableNamedGroup != null) { return new DHEPossession(preferableNamedGroup, context.sslContext.getSecureRandom()); } --- 296,314 ---- } // Used for ServerKeyExchange, TLS 1.2 and prior versions. @Override public SSLPossession createPossession(HandshakeContext context) { ! NamedGroup preferableNamedGroup = null; if (!useLegacyEphemeralDHKeys && (context.clientRequestedNamedGroups != null) && (!context.clientRequestedNamedGroups.isEmpty())) { preferableNamedGroup = SupportedGroups.getPreferredGroup( context.negotiatedProtocol, context.algorithmConstraints, ! NamedGroupType.NAMED_GROUP_FFDHE, context.clientRequestedNamedGroups); if (preferableNamedGroup != null) { return new DHEPossession(preferableNamedGroup, context.sslContext.getSecureRandom()); }
*** 409,419 **** } } private static final class DHEKAGenerator implements SSLKeyAgreementGenerator { ! private static final DHEKAGenerator instance = new DHEKAGenerator(); // Prevent instantiation of this class. private DHEKAGenerator() { // blank } --- 390,400 ---- } } private static final class DHEKAGenerator implements SSLKeyAgreementGenerator { ! static private DHEKAGenerator instance = new DHEKAGenerator(); // Prevent instantiation of this class. private DHEKAGenerator() { // blank }
*** 459,468 **** if (dhePossession == null || dheCredentials == null) { throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No sufficient DHE key agreement parameters negotiated"); } ! return new KAKeyDerivation("DiffieHellman", context, dhePossession.privateKey, dheCredentials.popPublicKey); } } } --- 440,534 ---- if (dhePossession == null || dheCredentials == null) { throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No sufficient DHE key agreement parameters negotiated"); } ! 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 >