< prev index next >

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

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2003, 2018, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 23,138 **** * questions. */ package sun.security.ssl; - import sun.security.action.GetPropertyAction; - - import java.io.File; - import java.io.FilePermission; import java.io.IOException; ! import java.security.AccessControlContext; ! import java.security.AccessController; ! import java.security.Principal; ! import java.security.PrivilegedAction; ! import java.security.SecureRandom; ! import java.util.*; ! ! /** ! * Models a service that provides support for a particular client key exchange ! * mode. Currently used to implement Kerberos-related cipher suites. ! * ! * @since 9 ! */ ! public interface ClientKeyExchangeService { ! static class Loader { ! private static final Map<String,ClientKeyExchangeService> ! providers = new HashMap<>(); ! static { ! String path = GetPropertyAction.privilegedGetProperty("java.home"); ! ServiceLoader<ClientKeyExchangeService> sc = ! AccessController.doPrivileged( ! (PrivilegedAction<ServiceLoader<ClientKeyExchangeService>>) ! () -> ServiceLoader.loadInstalled(ClientKeyExchangeService.class), ! null, ! new FilePermission(new File(path, "-").toString(), "read")); ! Iterator<ClientKeyExchangeService> iter = sc.iterator(); ! while (iter.hasNext()) { ! ClientKeyExchangeService cs = iter.next(); ! for (String ex: cs.supported()) { ! providers.put(ex, cs); } } } } ! public static ClientKeyExchangeService find(String ex) { ! return Loader.providers.get(ex); } ! /** ! * Returns the supported key exchange modes by this provider. ! * @return the supported key exchange modes ! */ ! String[] supported(); ! /** ! * Returns a generalized credential object on the server side. The server ! * side can use the info to determine if a cipher suite can be enabled. ! * @param acc the AccessControlContext of the SSL session ! * @return the credential object ! */ ! Object getServiceCreds(AccessControlContext acc); ! /** ! * Returns the host name for a service principal. The info can be used in ! * SNI or host name verifier. ! * @param principal the principal of a service ! * @return the string formed host name ! */ ! String getServiceHostName(Principal principal); ! /** ! * Returns whether the specified principal is related to the current ! * SSLSession. The info can be used to verify a SSL resume. ! * @param isClient if true called from client side, otherwise from server ! * @param acc the AccessControlContext of the SSL session ! * @param p the specified principal ! * @return true if related ! */ ! boolean isRelated(boolean isClient, AccessControlContext acc, Principal p); ! /** ! * Creates the ClientKeyExchange object on the client side. ! * @param serverName the intented peer name ! * @param acc the AccessControlContext of the SSL session ! * @param protocolVersion the TLS protocol version ! * @param rand the SecureRandom that will used to generate the premaster ! * @return the new Exchanger object ! * @throws IOException if there is an error ! */ ! ClientKeyExchange createClientExchange(String serverName, AccessControlContext acc, ! ProtocolVersion protocolVersion, SecureRandom rand) throws IOException; ! /** ! * Create the ClientKeyExchange on the server side. ! * @param protocolVersion the protocol version ! * @param clientVersion the input protocol version ! * @param rand a SecureRandom object used to generate premaster ! * (if the server has to create one) ! * @param encodedTicket the ticket from client ! * @param encrypted the encrypted premaster secret from client ! * @param acc the AccessControlContext of the SSL session ! * @param ServiceCreds the service side credentials object as retrived from ! * {@link #getServiceCreds} ! * @return the new Exchanger object ! * @throws IOException if there is an error ! */ ! ClientKeyExchange createServerExchange( ! ProtocolVersion protocolVersion, ProtocolVersion clientVersion, ! SecureRandom rand, byte[] encodedTicket, byte[] encrypted, ! AccessControlContext acc, Object ServiceCreds) throws IOException; } --- 23,584 ---- * questions. */ package sun.security.ssl; import java.io.IOException; ! import java.util.AbstractMap.SimpleImmutableEntry; ! import java.util.Arrays; ! import java.util.HashMap; ! import java.util.Map; ! import sun.security.ssl.DHKeyExchange.DHEPossession; ! import sun.security.ssl.ECDHKeyExchange.ECDHEPossession; ! import sun.security.ssl.SupportedGroupsExtension.NamedGroup; ! import sun.security.ssl.SupportedGroupsExtension.NamedGroupType; ! import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; ! import sun.security.ssl.X509Authentication.X509Possession; ! ! final class SSLKeyExchange implements SSLKeyAgreement { ! private final SSLAuthentication authentication; ! private final SSLKeyAgreement keyAgreement; ! ! SSLKeyExchange(X509Authentication authentication, ! SSLKeyAgreement keyAgreement) { ! this.authentication = authentication; ! this.keyAgreement = keyAgreement; ! } ! SSLPossession[] createPossessions(HandshakeContext context) { ! // authentication ! SSLPossession authPossession = null; ! if (authentication != null) { ! authPossession = authentication.createPossession(context); ! if (authPossession == null) { ! return new SSLPossession[0]; ! } else if (context instanceof ServerHandshakeContext) { ! // The authentication information may be used further for ! // key agreement parameters negotiation. ! ServerHandshakeContext shc = (ServerHandshakeContext)context; ! shc.interimAuthn = authPossession; ! } ! } ! // key agreement ! SSLPossession kaPossession; ! if (keyAgreement == T12KeyAgreement.RSA_EXPORT) { ! // a special case ! X509Possession x509Possession = (X509Possession)authPossession; ! if (JsseJce.getRSAKeyLength( ! x509Possession.popCerts[0].getPublicKey()) > 512) { ! kaPossession = keyAgreement.createPossession(context); ! ! if (kaPossession == null) { ! return new SSLPossession[0]; ! } else { ! return authentication != null ? ! new SSLPossession[] {authPossession, kaPossession} : ! new SSLPossession[] {kaPossession}; ! } ! } else { ! return authentication != null ? ! new SSLPossession[] {authPossession} : ! new SSLPossession[0]; ! } ! } else { ! kaPossession = keyAgreement.createPossession(context); ! if (kaPossession == null) { ! // special cases ! if (keyAgreement == T12KeyAgreement.RSA || ! keyAgreement == T12KeyAgreement.ECDH) { ! return authentication != null ? ! new SSLPossession[] {authPossession} : ! new SSLPossession[0]; ! } else { ! return new SSLPossession[0]; ! } ! } else { ! return authentication != null ? ! new SSLPossession[] {authPossession, kaPossession} : ! new SSLPossession[] {kaPossession}; } } } + @Override + public SSLPossession createPossession(HandshakeContext handshakeContext) { + // Please call createPossessions() so that the SSLAuthentication + // is counted. + throw new UnsupportedOperationException( + "SSLKeyExchange.createPossessions() should be used instead"); } ! @Override ! public SSLKeyDerivation createKeyDerivation( ! HandshakeContext handshakeContext) throws IOException { ! return keyAgreement.createKeyDerivation(handshakeContext); } + @Override + public SSLHandshake[] getRelatedHandshakers( + HandshakeContext handshakeContext) { + SSLHandshake[] auHandshakes; + if (authentication != null) { + auHandshakes = + authentication.getRelatedHandshakers(handshakeContext); + } else { + auHandshakes = null; + } ! SSLHandshake[] kaHandshakes = ! keyAgreement.getRelatedHandshakers(handshakeContext); ! if (auHandshakes == null || auHandshakes.length == 0) { ! return kaHandshakes; ! } else if (kaHandshakes == null || kaHandshakes.length == 0) { ! return auHandshakes; ! } else { ! SSLHandshake[] producers = Arrays.copyOf( ! auHandshakes, auHandshakes.length + kaHandshakes.length); ! System.arraycopy(kaHandshakes, 0, ! producers, auHandshakes.length, kaHandshakes.length); ! return producers; ! } ! } ! @Override ! public Map.Entry<Byte, HandshakeProducer>[] getHandshakeProducers( ! HandshakeContext handshakeContext) { ! Map.Entry<Byte, HandshakeProducer>[] auProducers; ! if (authentication != null) { ! auProducers = ! authentication.getHandshakeProducers(handshakeContext); ! } else { ! auProducers = null; ! } ! Map.Entry<Byte, HandshakeProducer>[] kaProducers = ! keyAgreement.getHandshakeProducers(handshakeContext); ! if (auProducers == null || auProducers.length == 0) { ! return kaProducers; ! } else if (kaProducers == null || kaProducers.length == 0) { ! return auProducers; ! } else { ! Map.Entry<Byte, HandshakeProducer>[] producers = Arrays.copyOf( ! auProducers, auProducers.length + kaProducers.length); ! System.arraycopy(kaProducers, 0, ! producers, auProducers.length, kaProducers.length); ! return producers; ! } ! } ! @Override ! public Map.Entry<Byte, SSLConsumer>[] getHandshakeConsumers( ! HandshakeContext handshakeContext) { ! Map.Entry<Byte, SSLConsumer>[] auConsumers; ! if (authentication != null) { ! auConsumers = ! authentication.getHandshakeConsumers(handshakeContext); ! } else { ! auConsumers = null; ! } ! ! Map.Entry<Byte, SSLConsumer>[] kaConsumers = ! keyAgreement.getHandshakeConsumers(handshakeContext); ! ! if (auConsumers == null || auConsumers.length == 0) { ! return kaConsumers; ! } else if (kaConsumers == null || kaConsumers.length == 0) { ! return auConsumers; ! } else { ! Map.Entry<Byte, SSLConsumer>[] producers = Arrays.copyOf( ! auConsumers, auConsumers.length + kaConsumers.length); ! System.arraycopy(kaConsumers, 0, ! producers, auConsumers.length, kaConsumers.length); ! return producers; ! } ! } ! ! // SSL 3.0 - (D)TLS 1.2 ! static SSLKeyExchange valueOf( ! CipherSuite.KeyExchange keyExchange) { ! if (keyExchange == null) { ! return null; ! } ! ! switch (keyExchange) { ! case K_RSA: ! return SSLKeyExRSA.KE; ! case K_RSA_EXPORT: ! return SSLKeyExRSAExport.KE; ! case K_DHE_DSS: ! return SSLKeyExDHEDSS.KE; ! case K_DHE_DSS_EXPORT: ! return SSLKeyExDHEDSSExport.KE; ! case K_DHE_RSA: ! return SSLKeyExDHERSA.KE; ! case K_DHE_RSA_EXPORT: ! return SSLKeyExDHERSAExport.KE; ! case K_DH_ANON: ! return SSLKeyExDHANON.KE; ! case K_DH_ANON_EXPORT: ! return SSLKeyExDHANONExport.KE; ! case K_ECDH_ECDSA: ! return SSLKeyExECDHECDSA.KE; ! case K_ECDH_RSA: ! return SSLKeyExECDHRSA.KE; ! case K_ECDHE_ECDSA: ! return SSLKeyExECDHEECDSA.KE; ! case K_ECDHE_RSA: ! return SSLKeyExECDHERSA.KE; ! case K_ECDH_ANON: ! return SSLKeyExECDHANON.KE; ! } ! ! return null; ! } ! ! // TLS 1.3 ! static SSLKeyExchange valueOf(NamedGroup namedGroup) { ! SSLKeyAgreement ka = T13KeyAgreement.valueOf(namedGroup); ! if (ka != null) { ! return new SSLKeyExchange( ! null, T13KeyAgreement.valueOf(namedGroup)); ! } ! ! return null; ! } ! ! private static class SSLKeyExRSA { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.RSA, T12KeyAgreement.RSA); ! } ! ! private static class SSLKeyExRSAExport { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.RSA, T12KeyAgreement.RSA_EXPORT); ! } ! ! private static class SSLKeyExDHEDSS { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.DSA, T12KeyAgreement.DHE); ! } ! ! private static class SSLKeyExDHEDSSExport { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.DSA, T12KeyAgreement.DHE_EXPORT); ! } ! ! private static class SSLKeyExDHERSA { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.RSA, T12KeyAgreement.DHE); ! } ! ! private static class SSLKeyExDHERSAExport { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.RSA, T12KeyAgreement.DHE_EXPORT); ! } ! ! private static class SSLKeyExDHANON { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! null, T12KeyAgreement.DHE); ! } ! ! private static class SSLKeyExDHANONExport { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! null, T12KeyAgreement.DHE_EXPORT); ! } ! ! private static class SSLKeyExECDHECDSA { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.EC, T12KeyAgreement.ECDH); ! } ! ! private static class SSLKeyExECDHRSA { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.EC, T12KeyAgreement.ECDH); ! } ! ! private static class SSLKeyExECDHEECDSA { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.EC, T12KeyAgreement.ECDHE); ! } ! ! private static class SSLKeyExECDHERSA { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! X509Authentication.RSA, T12KeyAgreement.ECDHE); ! } ! ! private static class SSLKeyExECDHANON { ! private static SSLKeyExchange KE = new SSLKeyExchange( ! null, T12KeyAgreement.ECDHE); ! } ! ! private enum T12KeyAgreement implements SSLKeyAgreement { ! RSA ("rsa", null, ! RSAKeyExchange.kaGenerator), ! RSA_EXPORT ("rsa_export", RSAKeyExchange.poGenerator, ! RSAKeyExchange.kaGenerator), ! DHE ("dhe", DHKeyExchange.poGenerator, ! DHKeyExchange.kaGenerator), ! DHE_EXPORT ("dhe_export", DHKeyExchange.poExportableGenerator, ! DHKeyExchange.kaGenerator), ! ECDH ("ecdh", null, ! ECDHKeyExchange.ecdhKAGenerator), ! ECDHE ("ecdhe", ECDHKeyExchange.poGenerator, ! ECDHKeyExchange.ecdheKAGenerator); ! ! final String name; ! final SSLPossessionGenerator possessionGenerator; ! final SSLKeyAgreementGenerator keyAgreementGenerator; ! ! T12KeyAgreement(String name, ! SSLPossessionGenerator possessionGenerator, ! SSLKeyAgreementGenerator keyAgreementGenerator) { ! this.name = name; ! this.possessionGenerator = possessionGenerator; ! this.keyAgreementGenerator = keyAgreementGenerator; ! } ! ! @Override ! public SSLPossession createPossession(HandshakeContext context) { ! if (possessionGenerator != null) { ! return possessionGenerator.createPossession(context); ! } ! ! return null; ! } ! ! @Override ! public SSLKeyDerivation createKeyDerivation( ! HandshakeContext context) throws IOException { ! return keyAgreementGenerator.createKeyDerivation(context); ! } ! ! @Override ! public SSLHandshake[] getRelatedHandshakers( ! HandshakeContext handshakeContext) { ! if (!handshakeContext.negotiatedProtocol.useTLS13PlusSpec()) { ! if (this.possessionGenerator != null) { ! return new SSLHandshake[] { ! SSLHandshake.SERVER_KEY_EXCHANGE ! }; ! } ! } ! ! return new SSLHandshake[0]; ! } ! ! @Override ! @SuppressWarnings({"unchecked", "rawtypes"}) ! public Map.Entry<Byte, HandshakeProducer>[] getHandshakeProducers( ! HandshakeContext handshakeContext) { ! if (handshakeContext.negotiatedProtocol.useTLS13PlusSpec()) { ! return (Map.Entry<Byte, HandshakeProducer>[])(new Map.Entry[0]); ! } ! ! if (handshakeContext.sslConfig.isClientMode) { ! switch (this) { ! case RSA: ! case RSA_EXPORT: ! return (Map.Entry<Byte, ! HandshakeProducer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.CLIENT_KEY_EXCHANGE.id, ! RSAClientKeyExchange.rsaHandshakeProducer ! ) ! }); ! ! case DHE: ! case DHE_EXPORT: ! return (Map.Entry<Byte, ! HandshakeProducer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<Byte, HandshakeProducer>( ! SSLHandshake.CLIENT_KEY_EXCHANGE.id, ! DHClientKeyExchange.dhHandshakeProducer ! ) ! }); ! ! case ECDH: ! return (Map.Entry<Byte, ! HandshakeProducer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.CLIENT_KEY_EXCHANGE.id, ! ECDHClientKeyExchange.ecdhHandshakeProducer ! ) ! }); ! ! case ECDHE: ! return (Map.Entry<Byte, ! HandshakeProducer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.CLIENT_KEY_EXCHANGE.id, ! ECDHClientKeyExchange.ecdheHandshakeProducer ! ) ! }); ! } ! } else { ! switch (this) { ! case RSA_EXPORT: ! return (Map.Entry<Byte, ! HandshakeProducer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.SERVER_KEY_EXCHANGE.id, ! RSAServerKeyExchange.rsaHandshakeProducer ! ) ! }); ! ! case DHE: ! case DHE_EXPORT: ! return (Map.Entry<Byte, ! HandshakeProducer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.SERVER_KEY_EXCHANGE.id, ! DHServerKeyExchange.dhHandshakeProducer ! ) ! }); ! ! case ECDHE: ! return (Map.Entry<Byte, ! HandshakeProducer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.SERVER_KEY_EXCHANGE.id, ! ECDHServerKeyExchange.ecdheHandshakeProducer ! ) ! }); ! } ! } ! ! return (Map.Entry<Byte, HandshakeProducer>[])(new Map.Entry[0]); ! } ! ! @Override ! @SuppressWarnings({"unchecked", "rawtypes"}) ! public Map.Entry<Byte, SSLConsumer>[] getHandshakeConsumers( ! HandshakeContext handshakeContext) { ! if (handshakeContext.negotiatedProtocol.useTLS13PlusSpec()) { ! return (Map.Entry<Byte, SSLConsumer>[])(new Map.Entry[0]); ! } ! ! if (handshakeContext.sslConfig.isClientMode) { ! switch (this) { ! case RSA_EXPORT: ! return (Map.Entry<Byte, ! SSLConsumer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.SERVER_KEY_EXCHANGE.id, ! RSAServerKeyExchange.rsaHandshakeConsumer ! ) ! }); ! ! case DHE: ! case DHE_EXPORT: ! return (Map.Entry<Byte, ! SSLConsumer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.SERVER_KEY_EXCHANGE.id, ! DHServerKeyExchange.dhHandshakeConsumer ! ) ! }); ! ! case ECDHE: ! return (Map.Entry<Byte, ! SSLConsumer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.SERVER_KEY_EXCHANGE.id, ! ECDHServerKeyExchange.ecdheHandshakeConsumer ! ) ! }); ! } ! } else { ! switch (this) { ! case RSA: ! case RSA_EXPORT: ! return (Map.Entry<Byte, ! SSLConsumer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.CLIENT_KEY_EXCHANGE.id, ! RSAClientKeyExchange.rsaHandshakeConsumer ! ) ! }); ! ! case DHE: ! case DHE_EXPORT: ! return (Map.Entry<Byte, ! SSLConsumer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.CLIENT_KEY_EXCHANGE.id, ! DHClientKeyExchange.dhHandshakeConsumer ! ) ! }); ! ! case ECDH: ! return (Map.Entry<Byte, ! SSLConsumer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.CLIENT_KEY_EXCHANGE.id, ! ECDHClientKeyExchange.ecdhHandshakeConsumer ! ) ! }); ! ! case ECDHE: ! return (Map.Entry<Byte, ! SSLConsumer>[])(new Map.Entry[] { ! new SimpleImmutableEntry<>( ! SSLHandshake.CLIENT_KEY_EXCHANGE.id, ! ECDHClientKeyExchange.ecdheHandshakeConsumer ! ) ! }); ! } ! } ! ! return (Map.Entry<Byte, SSLConsumer>[])(new Map.Entry[0]); ! } ! } ! ! private static final class T13KeyAgreement implements SSLKeyAgreement { ! private final NamedGroup namedGroup; ! static final Map<NamedGroup, T13KeyAgreement> ! supportedKeyShares = new HashMap<>(); ! ! static { ! for (NamedGroup namedGroup : ! SupportedGroups.supportedNamedGroups) { ! supportedKeyShares.put( ! namedGroup, new T13KeyAgreement(namedGroup)); ! } ! } ! ! private T13KeyAgreement(NamedGroup namedGroup) { ! this.namedGroup = namedGroup; ! } ! ! static T13KeyAgreement valueOf(NamedGroup namedGroup) { ! return supportedKeyShares.get(namedGroup); ! } ! ! @Override ! public SSLPossession createPossession(HandshakeContext hc) { ! if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) { ! return new ECDHEPossession( ! namedGroup, hc.sslContext.getSecureRandom()); ! } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) { ! return new DHEPossession( ! namedGroup, hc.sslContext.getSecureRandom()); ! } ! ! return null; ! } ! ! @Override ! public SSLKeyDerivation createKeyDerivation( ! HandshakeContext hc) throws IOException { ! if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) { ! return ECDHKeyExchange.ecdheKAGenerator.createKeyDerivation(hc); ! } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) { ! return DHKeyExchange.kaGenerator.createKeyDerivation(hc); ! } ! ! return null; ! } ! } }
< prev index next >