< prev index next >

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

Print this page

        

*** 34,92 **** import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.interfaces.ECPublicKey; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPublicKeySpec; import java.util.EnumSet; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; import javax.net.ssl.SSLHandshakeException; ! import sun.security.ssl.NamedGroup.NamedGroupType; import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.X509Authentication.X509Credentials; import sun.security.ssl.X509Authentication.X509Possession; - import sun.security.ssl.XDHKeyExchange.XDHECredentials; - import sun.security.ssl.XDHKeyExchange.XDHEPossession; import sun.security.util.ECUtil; final class ECDHKeyExchange { static final SSLPossessionGenerator poGenerator = new ECDHEPossessionGenerator(); - static final SSLKeyAgreementGenerator ecdhKAGenerator = - new ECDHKAGenerator(); - - // TLSv1.3 static final SSLKeyAgreementGenerator ecdheKAGenerator = new ECDHEKAGenerator(); ! // TLSv1-1.2, the KA gets more difficult with EC/XEC keys ! static final SSLKeyAgreementGenerator ecdheXdhKAGenerator = ! new ECDHEXDHKAGenerator(); ! ! static final class ECDHECredentials implements NamedGroupCredentials { final ECPublicKey popPublicKey; final NamedGroup namedGroup; ECDHECredentials(ECPublicKey popPublicKey, NamedGroup namedGroup) { this.popPublicKey = popPublicKey; this.namedGroup = namedGroup; } - @Override - public PublicKey getPublicKey() { - return popPublicKey; - } - - @Override - public NamedGroup getNamedGroup() { - return namedGroup; - } - static ECDHECredentials valueOf(NamedGroup namedGroup, byte[] encodedPoint) throws IOException, GeneralSecurityException { if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) { throw new RuntimeException( --- 34,78 ---- import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.interfaces.ECPublicKey; + import java.security.spec.AlgorithmParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPublicKeySpec; import java.util.EnumSet; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; + import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.SSLHandshakeException; ! 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.X509Credentials; import sun.security.ssl.X509Authentication.X509Possession; import sun.security.util.ECUtil; final class ECDHKeyExchange { static final SSLPossessionGenerator poGenerator = new ECDHEPossessionGenerator(); static final SSLKeyAgreementGenerator ecdheKAGenerator = new ECDHEKAGenerator(); + static final SSLKeyAgreementGenerator ecdhKAGenerator = + new ECDHKAGenerator(); ! static final class ECDHECredentials implements SSLCredentials { final ECPublicKey popPublicKey; final NamedGroup namedGroup; ECDHECredentials(ECPublicKey popPublicKey, NamedGroup namedGroup) { this.popPublicKey = popPublicKey; this.namedGroup = namedGroup; } static ECDHECredentials valueOf(NamedGroup namedGroup, byte[] encodedPoint) throws IOException, GeneralSecurityException { if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) { throw new RuntimeException(
*** 110,120 **** new ECPublicKeySpec(point, parameters)); return new ECDHECredentials(publicKey, namedGroup); } } ! static final class ECDHEPossession implements NamedGroupPossession { final PrivateKey privateKey; final ECPublicKey publicKey; final NamedGroup namedGroup; ECDHEPossession(NamedGroup namedGroup, SecureRandom random) { --- 96,106 ---- new ECPublicKeySpec(point, parameters)); return new ECDHECredentials(publicKey, namedGroup); } } ! static final class ECDHEPossession implements SSLPossession { final PrivateKey privateKey; final ECPublicKey publicKey; final NamedGroup namedGroup; ECDHEPossession(NamedGroup namedGroup, SecureRandom random) {
*** 211,235 **** } catch (GeneralSecurityException | java.io.IOException e) { throw (SSLHandshakeException) new SSLHandshakeException( "Could not generate ECPublicKey").initCause(e); } } - - @Override - public PublicKey getPublicKey() { - return publicKey; - } - - @Override - public NamedGroup getNamedGroup() { - return namedGroup; - } - - @Override - public PrivateKey getPrivateKey() { - return privateKey; - } } private static final class ECDHEPossessionGenerator implements SSLPossessionGenerator { // Prevent instantiation of this class. --- 197,206 ----
*** 237,271 **** // blank } @Override public SSLPossession createPossession(HandshakeContext context) { ! ! NamedGroup preferableNamedGroup; ! ! // Find most preferred EC or XEC groups if ((context.clientRequestedNamedGroups != null) && (!context.clientRequestedNamedGroups.isEmpty())) { preferableNamedGroup = SupportedGroups.getPreferredGroup( context.negotiatedProtocol, context.algorithmConstraints, ! new NamedGroupType[] { ! NamedGroupType.NAMED_GROUP_ECDHE, ! NamedGroupType.NAMED_GROUP_XDH }, context.clientRequestedNamedGroups); } else { preferableNamedGroup = SupportedGroups.getPreferredGroup( context.negotiatedProtocol, context.algorithmConstraints, ! new NamedGroupType[] { ! NamedGroupType.NAMED_GROUP_ECDHE, ! NamedGroupType.NAMED_GROUP_XDH }); } if (preferableNamedGroup != null) { ! return preferableNamedGroup.createPossession( ! context.sslContext.getSecureRandom()); } // no match found, cannot use this cipher suite. // return null; --- 208,235 ---- // blank } @Override public SSLPossession createPossession(HandshakeContext context) { ! NamedGroup preferableNamedGroup = null; if ((context.clientRequestedNamedGroups != null) && (!context.clientRequestedNamedGroups.isEmpty())) { preferableNamedGroup = SupportedGroups.getPreferredGroup( context.negotiatedProtocol, context.algorithmConstraints, ! NamedGroupType.NAMED_GROUP_ECDHE, context.clientRequestedNamedGroups); } else { preferableNamedGroup = SupportedGroups.getPreferredGroup( context.negotiatedProtocol, context.algorithmConstraints, ! NamedGroupType.NAMED_GROUP_ECDHE); } if (preferableNamedGroup != null) { ! return new ECDHEPossession(preferableNamedGroup, ! context.sslContext.getSecureRandom()); } // no match found, cannot use this cipher suite. // return null;
*** 332,342 **** if (x509Possession == null || ecdheCredentials == null) { throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No sufficient ECDHE key agreement parameters negotiated"); } ! return new KAKeyDerivation("ECDH", shc, x509Possession.popPrivateKey, ecdheCredentials.popPublicKey); } private SSLKeyDerivation createClientKeyDerivation( ClientHandshakeContext chc) throws IOException { --- 296,306 ---- if (x509Possession == null || ecdheCredentials == null) { throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No sufficient ECDHE key agreement parameters negotiated"); } ! return new ECDHEKAKeyDerivation(shc, x509Possession.popPrivateKey, ecdheCredentials.popPublicKey); } private SSLKeyDerivation createClientKeyDerivation( ClientHandshakeContext chc) throws IOException {
*** 381,391 **** if (ecdhePossession == null || x509Credentials == null) { throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No sufficient ECDH key agreement parameters negotiated"); } ! return new KAKeyDerivation("ECDH", chc, ecdhePossession.privateKey, x509Credentials.popPublicKey); } } private static final --- 345,355 ---- if (ecdhePossession == null || x509Credentials == null) { throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No sufficient ECDH key agreement parameters negotiated"); } ! return new ECDHEKAKeyDerivation(chc, ecdhePossession.privateKey, x509Credentials.popPublicKey); } } private static final
*** 425,499 **** if (ecdhePossession == null || ecdheCredentials == null) { throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No sufficient ECDHE key agreement parameters negotiated"); } ! return new KAKeyDerivation("ECDH", context, ecdhePossession.privateKey, ecdheCredentials.popPublicKey); } } - /* - * A Generator for TLSv1-1.2 to create a ECDHE or a XDH KeyDerivation - * object depending on the negotiated group. - */ private static final ! class ECDHEXDHKAGenerator implements SSLKeyAgreementGenerator { ! // Prevent instantiation of this class. ! private ECDHEXDHKAGenerator() { ! // blank } @Override ! public SSLKeyDerivation createKeyDerivation( ! HandshakeContext context) throws IOException { ! NamedGroupPossession namedGroupPossession = null; ! NamedGroupCredentials namedGroupCredentials = null; ! NamedGroup namedGroup = null; ! // Find a possession/credential combo using the same named group ! search: ! for (SSLPossession poss : context.handshakePossessions) { ! for (SSLCredentials cred : context.handshakeCredentials) { ! if (((poss instanceof ECDHEPossession) && ! (cred instanceof ECDHECredentials)) || ! (((poss instanceof XDHEPossession) && ! (cred instanceof XDHECredentials)))) { ! NamedGroupPossession p = (NamedGroupPossession)poss; ! NamedGroupCredentials c = (NamedGroupCredentials)cred; ! if (p.getNamedGroup() != c.getNamedGroup()) { ! continue; ! } else { ! namedGroup = p.getNamedGroup(); ! } ! namedGroupPossession = p; ! namedGroupCredentials = c; ! break search; ! } } } ! if (namedGroupPossession == null || namedGroupCredentials == null) { ! throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE, ! "No sufficient ECDHE/XDH key agreement " + ! "parameters negotiated"); ! } ! String alg; ! switch (namedGroup.type) { ! case NAMED_GROUP_ECDHE: ! alg = "ECDH"; ! break; ! case NAMED_GROUP_XDH: ! alg = "XDH"; ! break; ! default: ! throw new RuntimeException("Unexpected named group type"); } - - return new KAKeyDerivation(alg, context, - namedGroupPossession.getPrivateKey(), - namedGroupCredentials.getPublicKey()); } } } --- 389,484 ---- if (ecdhePossession == null || ecdheCredentials == null) { throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE, "No sufficient ECDHE key agreement parameters negotiated"); } ! return new ECDHEKAKeyDerivation(context, ecdhePossession.privateKey, ecdheCredentials.popPublicKey); } } private static final ! class ECDHEKAKeyDerivation implements SSLKeyDerivation { ! private final HandshakeContext context; ! private final PrivateKey localPrivateKey; ! private final PublicKey peerPublicKey; ! ! ECDHEKAKeyDerivation(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("ECDH"); ! 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("ECDH"); ! 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 >