11/*
2- * Copyright (c) 1996, 2016 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 1996, 2017 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -148,6 +148,10 @@ final class ClientHandshaker extends Handshaker {
148148 private static final boolean enableMFLExtension =
149149 Debug .getBooleanProperty ("jsse.enableMFLExtension" , false );
150150
151+ // To switch off the supported_groups extension for DHE cipher suite.
152+ private static final boolean enableFFDHE =
153+ Debug .getBooleanProperty ("jsse.enableFFDHE" , true );
154+
151155 // Whether an ALPN extension was sent in the ClientHello
152156 private boolean alpnActive = false ;
153157
@@ -613,11 +617,6 @@ private void serverHello(ServerHello mesg) throws IOException {
613617
614618 // -- token binding etc. changes begin --
615619 setConnectionRandoms ();
616-
617- HelloExtension emsx = mesg .extensions .get (ExtensionType .EXT_EXTENDED_MASTER_SECRET );
618- if (emsx != null ) {
619- isExtendedMasterSecretExtension = true ;
620- }
621620 // -- token binding etc. changes end --
622621
623622 if (isNegotiable (mesg .cipherSuite ) == false ) {
@@ -637,22 +636,6 @@ private void serverHello(ServerHello mesg) throws IOException {
637636 // NOTREACHED
638637 }
639638
640- // -- token binding etc. changes begin --
641- TokenBindingExtension tbx = (TokenBindingExtension ) mesg .extensions .get (ExtensionType .EXT_TOKEN_BINDING );
642- if (tbx != null ) {
643- byte [] requestedKeyParamsList = getConnectionSupportedTokenBindingKeyParams ();
644-
645- try {
646- byte serverChosenKeyParams = tbx .processServerHello (isExtendedMasterSecretExtension ,
647- secureRenegotiation , requestedKeyParamsList );
648- setConnectionNegotiatedTokenBindingKeyParams (serverChosenKeyParams );
649- }
650- catch (SSLHandshakeException e ) {
651- fatalSE (Alerts .alert_unsupported_extension , e .getMessage (), e );
652- }
653- }
654- // -- token binding etc. changes end --
655-
656639 // so far so good, let's look at the session
657640 if (session != null ) {
658641 // we tried to resume, let's see what the server decided
@@ -676,16 +659,18 @@ private void serverHello(ServerHello mesg) throws IOException {
676659
677660 // validate subject identity
678661 ClientKeyExchangeService p =
679- ClientKeyExchangeService .find (sessionSuite .keyExchange .name );
662+ ClientKeyExchangeService .find (
663+ sessionSuite .keyExchange .name );
680664 if (p != null ) {
681665 Principal localPrincipal = session .getLocalPrincipal ();
682666
683667 if (p .isRelated (true , getAccSE (), localPrincipal )) {
684668 if (debug != null && Debug .isOn ("session" ))
685669 System .out .println ("Subject identity is same" );
686670 } else {
687- throw new SSLProtocolException ("Server resumed" +
688- " session with wrong subject identity or no subject" );
671+ throw new SSLProtocolException (
672+ "Server resumed session with " +
673+ "wrong subject identity or no subject" );
689674 }
690675 }
691676
@@ -728,6 +713,70 @@ private void serverHello(ServerHello mesg) throws IOException {
728713 } // Otherwise, using the value negotiated during the original
729714 // session initiation
730715
716+ // check the "extended_master_secret" extension
717+ ExtendedMasterSecretExtension extendedMasterSecretExt =
718+ (ExtendedMasterSecretExtension )mesg .extensions .get (
719+ ExtensionType .EXT_EXTENDED_MASTER_SECRET );
720+ if (extendedMasterSecretExt != null ) {
721+ // Is it the expected server extension?
722+ if (!useExtendedMasterSecret ||
723+ !mesgVersion .useTLS10PlusSpec () || !requestedToUseEMS ) {
724+ fatalSE (Alerts .alert_unsupported_extension ,
725+ "Server sent the extended_master_secret " +
726+ "extension improperly" );
727+ }
728+
729+ // For abbreviated handshake, if the original session did not use
730+ // the "extended_master_secret" extension but the new ServerHello
731+ // contains the extension, the client MUST abort the handshake.
732+ if (resumingSession && (session != null ) &&
733+ !session .getUseExtendedMasterSecret ()) {
734+ fatalSE (Alerts .alert_unsupported_extension ,
735+ "Server sent an unexpected extended_master_secret " +
736+ "extension on session resumption" );
737+ }
738+ } else {
739+ if (useExtendedMasterSecret && !allowLegacyMasterSecret ) {
740+ // For full handshake, if a client receives a ServerHello
741+ // without the extension, it SHOULD abort the handshake if
742+ // it does not wish to interoperate with legacy servers.
743+ fatalSE (Alerts .alert_handshake_failure ,
744+ "Extended Master Secret extension is required" );
745+ }
746+
747+ if (resumingSession && (session != null )) {
748+ if (session .getUseExtendedMasterSecret ()) {
749+ // For abbreviated handshake, if the original session used
750+ // the "extended_master_secret" extension but the new
751+ // ServerHello does not contain the extension, the client
752+ // MUST abort the handshake.
753+ fatalSE (Alerts .alert_handshake_failure ,
754+ "Missing Extended Master Secret extension " +
755+ "on session resumption" );
756+ } else if (useExtendedMasterSecret && !allowLegacyResumption ) {
757+ // Unlikely, abbreviated handshake should be discarded.
758+ fatalSE (Alerts .alert_handshake_failure ,
759+ "Extended Master Secret extension is required" );
760+ }
761+ }
762+ }
763+
764+ // -- token binding etc. changes begin --
765+ TokenBindingExtension tbx = (TokenBindingExtension ) mesg .extensions .get (ExtensionType .EXT_TOKEN_BINDING );
766+ if (tbx != null ) {
767+ byte [] requestedKeyParamsList = getConnectionSupportedTokenBindingKeyParams ();
768+
769+ try {
770+ byte serverChosenKeyParams = tbx .processServerHello (extendedMasterSecretExt != null ,
771+ secureRenegotiation , requestedKeyParamsList );
772+ setConnectionNegotiatedTokenBindingKeyParams (serverChosenKeyParams );
773+ }
774+ catch (SSLHandshakeException e ) {
775+ fatalSE (Alerts .alert_unsupported_extension , e .getMessage (), e );
776+ }
777+ }
778+ // -- token binding etc. changes end --
779+
731780 // check the ALPN extension
732781 ALPNExtension serverHelloALPN =
733782 (ALPNExtension ) mesg .extensions .get (ExtensionType .EXT_ALPN );
@@ -792,17 +841,19 @@ private void serverHello(ServerHello mesg) throws IOException {
792841 fatalSE (Alerts .alert_unexpected_message , "Server set " +
793842 type + " extension when not requested by client" );
794843 }
795- } else if ((type != ExtensionType .EXT_ELLIPTIC_CURVES )
844+ } else if ((type != ExtensionType .EXT_SUPPORTED_GROUPS )
796845 && (type != ExtensionType .EXT_EC_POINT_FORMATS )
797846 && (type != ExtensionType .EXT_SERVER_NAME )
798847 && (type != ExtensionType .EXT_ALPN )
799848 && (type != ExtensionType .EXT_RENEGOTIATION_INFO )
849+ && (type != ExtensionType .EXT_STATUS_REQUEST )
850+ && (type != ExtensionType .EXT_STATUS_REQUEST_V2 )
800851 // -- token binding etc. changes begin --
801852 && (type != ExtensionType .EXT_TOKEN_BINDING )
802- && (type != ExtensionType .EXT_EXTENDED_MASTER_SECRET )
803853 // -- token binding etc. changes end --
804- && (type != ExtensionType .EXT_STATUS_REQUEST )
805- && (type != ExtensionType .EXT_STATUS_REQUEST_V2 )) {
854+ && (type != ExtensionType .EXT_EXTENDED_MASTER_SECRET )) {
855+ // Note: Better to check client requested extensions rather
856+ // than all supported extensions.
806857 fatalSE (Alerts .alert_unsupported_extension ,
807858 "Server sent an unsupported extension: " + type );
808859 }
@@ -811,7 +862,8 @@ private void serverHello(ServerHello mesg) throws IOException {
811862 // Create a new session, we need to do the full handshake
812863 session = new SSLSessionImpl (protocolVersion , cipherSuite ,
813864 getLocalSupportedSignAlgs (),
814- mesg .sessionId , getHostSE (), getPortSE ());
865+ mesg .sessionId , getHostSE (), getPortSE (),
866+ (extendedMasterSecretExt != null ));
815867 session .setRequestedServerNames (requestedServerNames );
816868 session .setNegotiatedMaxFragSize (requestedMFLength );
817869 session .setMaximumPacketSize (maximumPacketSize );
@@ -852,6 +904,17 @@ private void serverKeyExchange(RSA_ServerKeyExchange mesg)
852904 * our own D-H algorithm object so we can defer key calculations
853905 * until after we've sent the client key exchange message (which
854906 * gives client and server some useful parallelism).
907+ *
908+ * Note per section 3 of RFC 7919, if the server is not compatible with
909+ * FFDHE specification, the client MAY decide to continue the connection
910+ * if the selected DHE group is acceptable under local policy, or it MAY
911+ * decide to terminate the connection with a fatal insufficient_security
912+ * (71) alert. The algorithm constraints mechanism is JDK local policy
913+ * used for additional DHE parameters checking. So this implementation
914+ * does not check the server compatibility and just pass to the local
915+ * algorithm constraints checking. The client will continue the
916+ * connection if the server selected DHE group is acceptable by the
917+ * specified algorithm constraints.
855918 */
856919 private void serverKeyExchange (DH_ServerKeyExchange mesg )
857920 throws IOException {
@@ -1442,6 +1505,44 @@ HandshakeMessage getKickstartMessage() throws SSLException {
14421505 session = null ;
14431506 }
14441507
1508+ if ((session != null ) && useExtendedMasterSecret ) {
1509+ boolean isTLS10Plus = sessionVersion .useTLS10PlusSpec ();
1510+ if (isTLS10Plus && !session .getUseExtendedMasterSecret ()) {
1511+ if (!allowLegacyResumption ) {
1512+ // perform full handshake instead
1513+ //
1514+ // The client SHOULD NOT offer an abbreviated handshake
1515+ // to resume a session that does not use an extended
1516+ // master secret. Instead, it SHOULD offer a full
1517+ // handshake.
1518+ session = null ;
1519+ }
1520+ }
1521+
1522+ if ((session != null ) && !allowUnsafeServerCertChange ) {
1523+ // It is fine to move on with abbreviate handshake if
1524+ // endpoint identification is enabled.
1525+ String identityAlg = getEndpointIdentificationAlgorithmSE ();
1526+ if ((identityAlg == null || identityAlg .length () == 0 )) {
1527+ if (isTLS10Plus ) {
1528+ if (!session .getUseExtendedMasterSecret ()) {
1529+ // perform full handshake instead
1530+ session = null ;
1531+ } // Otherwise, use extended master secret.
1532+ } else {
1533+ // The extended master secret extension does not
1534+ // apply to SSL 3.0. Perform a full handshake
1535+ // instead.
1536+ //
1537+ // Note that the useExtendedMasterSecret is
1538+ // extended to protect SSL 3.0 connections,
1539+ // by discarding abbreviate handshake.
1540+ session = null ;
1541+ }
1542+ }
1543+ }
1544+ }
1545+
14451546 if (session != null ) {
14461547 if (debug != null ) {
14471548 if (Debug .isOn ("handshake" ) || Debug .isOn ("session" )) {
@@ -1524,14 +1625,17 @@ HandshakeMessage getKickstartMessage() throws SSLException {
15241625 sslContext .getSecureRandom (), maxProtocolVersion ,
15251626 sessionId , cipherSuites , isDTLS );
15261627
1527- // add elliptic curves and point format extensions
1528- if (cipherSuites .containsEC ()) {
1529- EllipticCurvesExtension ece =
1530- EllipticCurvesExtension .createExtension (algorithmConstraints );
1531- if (ece != null ) {
1532- clientHelloMessage .extensions .add (ece );
1628+ // Add named groups extension for ECDHE and FFDHE if necessary.
1629+ SupportedGroupsExtension sge =
1630+ SupportedGroupsExtension .createExtension (
1631+ algorithmConstraints ,
1632+ cipherSuites , enableFFDHE );
1633+ if (sge != null ) {
1634+ clientHelloMessage .extensions .add (sge );
1635+ // Add elliptic point format extensions
1636+ if (cipherSuites .contains (NamedGroupType .NAMED_GROUP_ECDHE )) {
15331637 clientHelloMessage .extensions .add (
1534- EllipticPointFormatsExtension .DEFAULT );
1638+ EllipticPointFormatsExtension .DEFAULT );
15351639 }
15361640 }
15371641
@@ -1548,6 +1652,14 @@ HandshakeMessage getKickstartMessage() throws SSLException {
15481652 clientHelloMessage .addSignatureAlgorithmsExtension (localSignAlgs );
15491653 }
15501654
1655+ // add Extended Master Secret extension
1656+ if (useExtendedMasterSecret && maxProtocolVersion .useTLS10PlusSpec ()) {
1657+ if ((session == null ) || session .getUseExtendedMasterSecret ()) {
1658+ clientHelloMessage .addExtendedMasterSecretExtension ();
1659+ requestedToUseEMS = true ;
1660+ }
1661+ }
1662+
15511663 // add server_name extension
15521664 if (enableSNIExtension ) {
15531665 if (session != null ) {
@@ -1626,8 +1738,7 @@ HandshakeMessage getKickstartMessage() throws SSLException {
16261738 // -- token binding etc. changes begin --
16271739 byte [] supportedTokenBindingKeyParams = getConnectionSupportedTokenBindingKeyParams ();
16281740
1629- if (supportedTokenBindingKeyParams != null && supportedTokenBindingKeyParams .length > 0 ) {
1630- clientHelloMessage .extensions .add (new ExtendedMasterSecretExtension ());
1741+ if (supportedTokenBindingKeyParams != null && supportedTokenBindingKeyParams .length > 0 && requestedToUseEMS ) {
16311742 clientHelloMessage .extensions .add (new TokenBindingExtension (1 , 0 , supportedTokenBindingKeyParams ));
16321743 }
16331744 // -- token binding etc. changes end --
@@ -1672,10 +1783,14 @@ private void serverCertificate(CertificateMsg mesg) throws IOException {
16721783 // Allow server certificate change in client side during renegotiation
16731784 // after a session-resumption abbreviated initial handshake?
16741785 //
1675- // DO NOT need to check allowUnsafeServerCertChange here. We only
1786+ // DO NOT need to check allowUnsafeServerCertChange here. We only
16761787 // reserve server certificates when allowUnsafeServerCertChange is
16771788 // flase.
1678- if (reservedServerCerts != null ) {
1789+ //
1790+ // Allow server certificate change if it is negotiated to use the
1791+ // extended master secret.
1792+ if ((reservedServerCerts != null ) &&
1793+ !session .getUseExtendedMasterSecret ()) {
16791794 // It is not necessary to check the certificate update if endpoint
16801795 // identification is enabled.
16811796 String identityAlg = getEndpointIdentificationAlgorithmSE ();
0 commit comments