src/java.base/share/classes/sun/security/ssl/MaxFragExtension.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47216 71c04702a3d5
child 56704 c3ee22c3a0f6
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
       
     1 /*
       
     2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.security.ssl;
       
    27 
       
    28 import java.io.IOException;
       
    29 import java.nio.ByteBuffer;
       
    30 import javax.net.ssl.SSLProtocolException;
       
    31 import static sun.security.ssl.SSLExtension.CH_MAX_FRAGMENT_LENGTH;
       
    32 import static sun.security.ssl.SSLExtension.EE_MAX_FRAGMENT_LENGTH;
       
    33 import sun.security.ssl.SSLExtension.ExtensionConsumer;
       
    34 import static sun.security.ssl.SSLExtension.SH_MAX_FRAGMENT_LENGTH;
       
    35 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
       
    36 import sun.security.ssl.SSLHandshake.HandshakeMessage;
       
    37 
       
    38 /**
       
    39  * Pack of the "max_fragment_length" extensions [RFC6066].
       
    40  */
       
    41 final class MaxFragExtension {
       
    42     static final HandshakeProducer chNetworkProducer =
       
    43             new CHMaxFragmentLengthProducer();
       
    44     static final ExtensionConsumer chOnLoadConcumer =
       
    45             new CHMaxFragmentLengthConsumer();
       
    46 
       
    47     static final HandshakeProducer shNetworkProducer =
       
    48             new SHMaxFragmentLengthProducer();
       
    49     static final ExtensionConsumer shOnLoadConcumer =
       
    50             new SHMaxFragmentLengthConsumer();
       
    51     static final HandshakeConsumer shOnTradeConsumer =
       
    52             new SHMaxFragmentLengthUpdate();
       
    53 
       
    54     static final HandshakeProducer eeNetworkProducer =
       
    55             new EEMaxFragmentLengthProducer();
       
    56     static final ExtensionConsumer eeOnLoadConcumer =
       
    57             new EEMaxFragmentLengthConsumer();
       
    58     static final HandshakeConsumer eeOnTradeConsumer =
       
    59             new EEMaxFragmentLengthUpdate();
       
    60 
       
    61     static final SSLStringize maxFragLenStringize =
       
    62             new MaxFragLenStringize();
       
    63 
       
    64     /**
       
    65      * The "max_fragment_length" extension [RFC 6066].
       
    66      */
       
    67     static final class MaxFragLenSpec implements SSLExtensionSpec {
       
    68         byte id;
       
    69 
       
    70         private MaxFragLenSpec(byte id) {
       
    71             this.id = id;
       
    72         }
       
    73 
       
    74         private MaxFragLenSpec(ByteBuffer buffer) throws IOException {
       
    75             if (buffer.remaining() != 1) {
       
    76                 throw new SSLProtocolException(
       
    77                     "Invalid max_fragment_length extension data");
       
    78             }
       
    79 
       
    80             this.id = buffer.get();
       
    81         }
       
    82 
       
    83         @Override
       
    84         public String toString() {
       
    85             return MaxFragLenEnum.nameOf(id);
       
    86         }
       
    87     }
       
    88 
       
    89     private static final class MaxFragLenStringize implements SSLStringize {
       
    90         @Override
       
    91         public String toString(ByteBuffer buffer) {
       
    92             try {
       
    93                 return (new MaxFragLenSpec(buffer)).toString();
       
    94             } catch (IOException ioe) {
       
    95                 // For debug logging only, so please swallow exceptions.
       
    96                 return ioe.getMessage();
       
    97             }
       
    98         }
       
    99     }
       
   100 
       
   101     static enum MaxFragLenEnum {
       
   102         MFL_512     ((byte)0x01,  512,  "2^9"),
       
   103         MFL_1024    ((byte)0x02, 1024,  "2^10"),
       
   104         MFL_2048    ((byte)0x03, 2048,  "2^11"),
       
   105         MFL_4096    ((byte)0x04, 4096,  "2^12");
       
   106 
       
   107         final byte id;
       
   108         final int fragmentSize;
       
   109         final String description;
       
   110 
       
   111         private MaxFragLenEnum(byte id, int fragmentSize, String description) {
       
   112             this.id = id;
       
   113             this.fragmentSize = fragmentSize;
       
   114             this.description = description;
       
   115         }
       
   116 
       
   117         private static MaxFragLenEnum valueOf(byte id) {
       
   118             for (MaxFragLenEnum mfl : MaxFragLenEnum.values()) {
       
   119                 if (mfl.id == id) {
       
   120                     return mfl;
       
   121                 }
       
   122             }
       
   123 
       
   124             return null;
       
   125         }
       
   126 
       
   127         private static String nameOf(byte id) {
       
   128             for (MaxFragLenEnum mfl : MaxFragLenEnum.values()) {
       
   129                 if (mfl.id == id) {
       
   130                     return mfl.description;
       
   131                 }
       
   132             }
       
   133 
       
   134             return "UNDEFINED-MAX-FRAGMENT-LENGTH(" + id + ")";
       
   135         }
       
   136 
       
   137         /**
       
   138          * Returns the best match enum constant of the specified
       
   139          * fragment size.
       
   140          */
       
   141         static MaxFragLenEnum valueOf(int fragmentSize) {
       
   142             if (fragmentSize <= 0) {
       
   143                 return null;
       
   144             } else if (fragmentSize < 1024) {
       
   145                 return MFL_512;
       
   146             } else if (fragmentSize < 2048) {
       
   147                 return MFL_1024;
       
   148             } else if (fragmentSize < 4096) {
       
   149                 return MFL_2048;
       
   150             } else if (fragmentSize == 4096) {
       
   151                 return MFL_4096;
       
   152             }
       
   153 
       
   154             return null;
       
   155         }
       
   156     }
       
   157 
       
   158     /**
       
   159      * Network data producer of a "max_fragment_length" extension in
       
   160      * the ClientHello handshake message.
       
   161      */
       
   162     private static final
       
   163             class CHMaxFragmentLengthProducer implements HandshakeProducer {
       
   164         // Prevent instantiation of this class.
       
   165         private CHMaxFragmentLengthProducer() {
       
   166             // blank
       
   167         }
       
   168 
       
   169         @Override
       
   170         public byte[] produce(ConnectionContext context,
       
   171                 HandshakeMessage message) throws IOException {
       
   172             // The producing happens in client side only.
       
   173             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   174 
       
   175             // Is it a supported and enabled extension?
       
   176             if (!chc.sslConfig.isAvailable(CH_MAX_FRAGMENT_LENGTH)) {
       
   177                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   178                     SSLLogger.fine(
       
   179                         "Ignore unavailable max_fragment_length extension");
       
   180                 }
       
   181                 return null;
       
   182             }
       
   183 
       
   184             // Produce the extension and update the context.
       
   185             int requestedMFLength;
       
   186             if (chc.isResumption && (chc.resumingSession != null)) {
       
   187                 // The same extension should be sent for resumption.
       
   188                 requestedMFLength =
       
   189                     chc.resumingSession.getNegotiatedMaxFragSize();
       
   190             } else if (chc.sslConfig.maximumPacketSize != 0) {
       
   191                 // Maybe we can calculate the fragment size more accurate
       
   192                 // by condering the enabled cipher suites in the future.
       
   193                 requestedMFLength = chc.sslConfig.maximumPacketSize;
       
   194                 if (chc.sslContext.isDTLS()) {
       
   195                     requestedMFLength -= DTLSRecord.maxPlaintextPlusSize;
       
   196                 } else {
       
   197                     requestedMFLength -= SSLRecord.maxPlaintextPlusSize;
       
   198                 }
       
   199             } else {
       
   200                 // Need no max_fragment_length extension.
       
   201                 requestedMFLength = -1;
       
   202             }
       
   203 
       
   204             MaxFragLenEnum mfl = MaxFragLenEnum.valueOf(requestedMFLength);
       
   205             if (mfl != null) {
       
   206                 // update the context.
       
   207                 chc.handshakeExtensions.put(
       
   208                         CH_MAX_FRAGMENT_LENGTH, new MaxFragLenSpec(mfl.id));
       
   209 
       
   210                 return new byte[] { mfl.id };
       
   211             } else {
       
   212                 // log and ignore, no MFL extension.
       
   213                 chc.maxFragmentLength = -1;
       
   214                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   215                     SSLLogger.fine(
       
   216                         "No available max_fragment_length extension can " +
       
   217                         "be used for fragment size of " +
       
   218                         requestedMFLength + "bytes");
       
   219                 }
       
   220             }
       
   221 
       
   222             return null;
       
   223         }
       
   224     }
       
   225 
       
   226     /**
       
   227      * Network data consumer of a "max_fragment_length" extension in
       
   228      * the ClientHello handshake message.
       
   229      */
       
   230     private static final
       
   231             class CHMaxFragmentLengthConsumer implements ExtensionConsumer {
       
   232         // Prevent instantiation of this class.
       
   233         private CHMaxFragmentLengthConsumer() {
       
   234             // blank
       
   235         }
       
   236 
       
   237         @Override
       
   238         public void consume(ConnectionContext context,
       
   239             HandshakeMessage message, ByteBuffer buffer) throws IOException {
       
   240             // The comsuming happens in server side only.
       
   241             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   242 
       
   243             if (!shc.sslConfig.isAvailable(CH_MAX_FRAGMENT_LENGTH)) {
       
   244                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   245                     SSLLogger.fine(
       
   246                         "Ignore unavailable max_fragment_length extension");
       
   247                 }
       
   248                 return;     // ignore the extension
       
   249             }
       
   250 
       
   251             // Parse the extension.
       
   252             MaxFragLenSpec spec;
       
   253             try {
       
   254                 spec = new MaxFragLenSpec(buffer);
       
   255             } catch (IOException ioe) {
       
   256                 shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
       
   257                 return;     // fatal() always throws, make the compiler happy.
       
   258             }
       
   259 
       
   260             MaxFragLenEnum mfle = MaxFragLenEnum.valueOf(spec.id);
       
   261             if (mfle == null) {
       
   262                 shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   263                     "the requested maximum fragment length is other " +
       
   264                     "than the allowed values");
       
   265             }
       
   266 
       
   267             // Update the context.
       
   268             shc.maxFragmentLength = mfle.fragmentSize;
       
   269             shc.handshakeExtensions.put(CH_MAX_FRAGMENT_LENGTH, spec);
       
   270 
       
   271             // No impact on session resumption.
       
   272         }
       
   273     }
       
   274 
       
   275     /**
       
   276      * Network data producer of a "max_fragment_length" extension in
       
   277      * the ServerHello handshake message.
       
   278      */
       
   279     private static final
       
   280             class SHMaxFragmentLengthProducer implements HandshakeProducer {
       
   281         // Prevent instantiation of this class.
       
   282         private SHMaxFragmentLengthProducer() {
       
   283             // blank
       
   284         }
       
   285 
       
   286         @Override
       
   287         public byte[] produce(ConnectionContext context,
       
   288                 HandshakeMessage message) throws IOException {
       
   289             // The producing happens in server side only.
       
   290             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   291 
       
   292             // In response to "max_fragment_length" extension request only
       
   293             MaxFragLenSpec spec = (MaxFragLenSpec)
       
   294                     shc.handshakeExtensions.get(CH_MAX_FRAGMENT_LENGTH);
       
   295             if (spec == null) {
       
   296                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   297                     SSLLogger.finest(
       
   298                         "Ignore unavailable max_fragment_length extension");
       
   299                 }
       
   300                 return null;        // ignore the extension
       
   301             }
       
   302 
       
   303             if ((shc.maxFragmentLength > 0) &&
       
   304                     (shc.sslConfig.maximumPacketSize != 0)) {
       
   305                 int estimatedMaxFragSize =
       
   306                         shc.negotiatedCipherSuite.calculatePacketSize(
       
   307                                 shc.maxFragmentLength, shc.negotiatedProtocol,
       
   308                                 shc.sslContext.isDTLS());
       
   309                 if (estimatedMaxFragSize > shc.sslConfig.maximumPacketSize) {
       
   310                     // For better interoperability, abort the maximum
       
   311                     // fragment length negotiation, rather than terminate
       
   312                     // the connection with a fatal alert.
       
   313                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   314                         SSLLogger.fine(
       
   315                             "Abort the maximum fragment length negotiation, " +
       
   316                             "may overflow the maximum packet size limit.");
       
   317                     }
       
   318                     shc.maxFragmentLength = -1;
       
   319                 }
       
   320             }
       
   321 
       
   322             // update the context
       
   323             if (shc.maxFragmentLength > 0) {
       
   324                 shc.handshakeSession.setNegotiatedMaxFragSize(
       
   325                         shc.maxFragmentLength);
       
   326                 shc.conContext.inputRecord.changeFragmentSize(
       
   327                         shc.maxFragmentLength);
       
   328                 shc.conContext.outputRecord.changeFragmentSize(
       
   329                         shc.maxFragmentLength);
       
   330 
       
   331                 // The response extension data is the same as the requested one.
       
   332                 shc.handshakeExtensions.put(SH_MAX_FRAGMENT_LENGTH, spec);
       
   333                 return new byte[] { spec.id };
       
   334             }
       
   335 
       
   336             return null;
       
   337         }
       
   338     }
       
   339 
       
   340     /**
       
   341      * Network data consumer of a "max_fragment_length" extension in
       
   342      * the ServerHello handshake message.
       
   343      */
       
   344     private static final
       
   345             class SHMaxFragmentLengthConsumer implements ExtensionConsumer {
       
   346         // Prevent instantiation of this class.
       
   347         private SHMaxFragmentLengthConsumer() {
       
   348             // blank
       
   349         }
       
   350 
       
   351         @Override
       
   352         public void consume(ConnectionContext context,
       
   353             HandshakeMessage message, ByteBuffer buffer) throws IOException {
       
   354 
       
   355             // The comsuming happens in client side only.
       
   356             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   357 
       
   358             // In response to "max_fragment_length" extension request only
       
   359             MaxFragLenSpec requestedSpec = (MaxFragLenSpec)
       
   360                     chc.handshakeExtensions.get(CH_MAX_FRAGMENT_LENGTH);
       
   361             if (requestedSpec == null) {
       
   362                 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
       
   363                     "Unexpected max_fragment_length extension in ServerHello");
       
   364             }
       
   365 
       
   366             // Parse the extension.
       
   367             MaxFragLenSpec spec;
       
   368             try {
       
   369                 spec = new MaxFragLenSpec(buffer);
       
   370             } catch (IOException ioe) {
       
   371                 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
       
   372                 return;     // fatal() always throws, make the compiler happy.
       
   373             }
       
   374 
       
   375             if (spec.id != requestedSpec.id) {
       
   376                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   377                     "The maximum fragment length response is not requested");
       
   378             }
       
   379 
       
   380             MaxFragLenEnum mfle = MaxFragLenEnum.valueOf(spec.id);
       
   381             if (mfle == null) {
       
   382                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   383                     "the requested maximum fragment length is other " +
       
   384                     "than the allowed values");
       
   385             }
       
   386 
       
   387             // update the context
       
   388             chc.maxFragmentLength = mfle.fragmentSize;
       
   389             chc.handshakeExtensions.put(SH_MAX_FRAGMENT_LENGTH, spec);
       
   390         }
       
   391     }
       
   392 
       
   393     /**
       
   394      * After session creation consuming of a "max_fragment_length"
       
   395      * extension in the ClientHello handshake message.
       
   396      */
       
   397     private static final class SHMaxFragmentLengthUpdate
       
   398             implements HandshakeConsumer {
       
   399 
       
   400         // Prevent instantiation of this class.
       
   401         private SHMaxFragmentLengthUpdate() {
       
   402             // blank
       
   403         }
       
   404 
       
   405         @Override
       
   406         public void consume(ConnectionContext context,
       
   407                 HandshakeMessage message) throws IOException {
       
   408             // The comsuming happens in client side only.
       
   409             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   410 
       
   411             MaxFragLenSpec spec = (MaxFragLenSpec)
       
   412                     chc.handshakeExtensions.get(SH_MAX_FRAGMENT_LENGTH);
       
   413             if (spec == null) {
       
   414                 // Ignore, no "max_fragment_length" extension response.
       
   415                 return;
       
   416             }
       
   417 
       
   418             if ((chc.maxFragmentLength > 0) &&
       
   419                     (chc.sslConfig.maximumPacketSize != 0)) {
       
   420                 int estimatedMaxFragSize =
       
   421                         chc.negotiatedCipherSuite.calculatePacketSize(
       
   422                                 chc.maxFragmentLength, chc.negotiatedProtocol,
       
   423                                 chc.sslContext.isDTLS());
       
   424                 if (estimatedMaxFragSize > chc.sslConfig.maximumPacketSize) {
       
   425                     // For better interoperability, abort the maximum
       
   426                     // fragment length negotiation, rather than terminate
       
   427                     // the connection with a fatal alert.
       
   428                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   429                         SSLLogger.fine(
       
   430                             "Abort the maximum fragment length negotiation, " +
       
   431                             "may overflow the maximum packet size limit.");
       
   432                     }
       
   433                     chc.maxFragmentLength = -1;
       
   434                 }
       
   435             }
       
   436 
       
   437             // update the context
       
   438             if (chc.maxFragmentLength > 0) {
       
   439                 chc.handshakeSession.setNegotiatedMaxFragSize(
       
   440                         chc.maxFragmentLength);
       
   441                 chc.conContext.inputRecord.changeFragmentSize(
       
   442                         chc.maxFragmentLength);
       
   443                 chc.conContext.outputRecord.changeFragmentSize(
       
   444                         chc.maxFragmentLength);
       
   445             }
       
   446         }
       
   447     }
       
   448 
       
   449     /**
       
   450      * Network data producer of a "max_fragment_length" extension in
       
   451      * the EncryptedExtensions handshake message.
       
   452      */
       
   453     private static final
       
   454             class EEMaxFragmentLengthProducer implements HandshakeProducer {
       
   455         // Prevent instantiation of this class.
       
   456         private EEMaxFragmentLengthProducer() {
       
   457             // blank
       
   458         }
       
   459 
       
   460         @Override
       
   461         public byte[] produce(ConnectionContext context,
       
   462                 HandshakeMessage message) throws IOException {
       
   463             // The producing happens in server side only.
       
   464             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   465 
       
   466             // In response to "max_fragment_length" extension request only
       
   467             MaxFragLenSpec spec = (MaxFragLenSpec)
       
   468                     shc.handshakeExtensions.get(CH_MAX_FRAGMENT_LENGTH);
       
   469             if (spec == null) {
       
   470                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   471                     SSLLogger.finest(
       
   472                         "Ignore unavailable max_fragment_length extension");
       
   473                 }
       
   474                 return null;        // ignore the extension
       
   475             }
       
   476 
       
   477             if ((shc.maxFragmentLength > 0) &&
       
   478                     (shc.sslConfig.maximumPacketSize != 0)) {
       
   479                 int estimatedMaxFragSize =
       
   480                         shc.negotiatedCipherSuite.calculatePacketSize(
       
   481                                 shc.maxFragmentLength, shc.negotiatedProtocol,
       
   482                                 shc.sslContext.isDTLS());
       
   483                 if (estimatedMaxFragSize > shc.sslConfig.maximumPacketSize) {
       
   484                     // For better interoperability, abort the maximum
       
   485                     // fragment length negotiation, rather than terminate
       
   486                     // the connection with a fatal alert.
       
   487                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   488                         SSLLogger.fine(
       
   489                             "Abort the maximum fragment length negotiation, " +
       
   490                             "may overflow the maximum packet size limit.");
       
   491                     }
       
   492                     shc.maxFragmentLength = -1;
       
   493                 }
       
   494             }
       
   495 
       
   496             // update the context
       
   497             if (shc.maxFragmentLength > 0) {
       
   498                 shc.handshakeSession.setNegotiatedMaxFragSize(
       
   499                         shc.maxFragmentLength);
       
   500                 shc.conContext.inputRecord.changeFragmentSize(
       
   501                         shc.maxFragmentLength);
       
   502                 shc.conContext.outputRecord.changeFragmentSize(
       
   503                         shc.maxFragmentLength);
       
   504 
       
   505                 // The response extension data is the same as the requested one.
       
   506                 shc.handshakeExtensions.put(EE_MAX_FRAGMENT_LENGTH, spec);
       
   507                 return new byte[] { spec.id };
       
   508             }
       
   509 
       
   510             return null;
       
   511         }
       
   512     }
       
   513 
       
   514     /**
       
   515      * Network data consumer of a "max_fragment_length" extension in the
       
   516      * EncryptedExtensions handshake message.
       
   517      */
       
   518     private static final
       
   519             class EEMaxFragmentLengthConsumer implements ExtensionConsumer {
       
   520         // Prevent instantiation of this class.
       
   521         private EEMaxFragmentLengthConsumer() {
       
   522             // blank
       
   523         }
       
   524 
       
   525         @Override
       
   526         public void consume(ConnectionContext context,
       
   527             HandshakeMessage message, ByteBuffer buffer) throws IOException {
       
   528             // The comsuming happens in client side only.
       
   529             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   530 
       
   531             // In response to "max_fragment_length" extension request only
       
   532             MaxFragLenSpec requestedSpec = (MaxFragLenSpec)
       
   533                     chc.handshakeExtensions.get(CH_MAX_FRAGMENT_LENGTH);
       
   534             if (requestedSpec == null) {
       
   535                 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
       
   536                     "Unexpected max_fragment_length extension in ServerHello");
       
   537             }
       
   538 
       
   539             // Parse the extension.
       
   540             MaxFragLenSpec spec;
       
   541             try {
       
   542                 spec = new MaxFragLenSpec(buffer);
       
   543             } catch (IOException ioe) {
       
   544                 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
       
   545                 return;     // fatal() always throws, make the compiler happy.
       
   546             }
       
   547 
       
   548             if (spec.id != requestedSpec.id) {
       
   549                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   550                     "The maximum fragment length response is not requested");
       
   551             }
       
   552 
       
   553             MaxFragLenEnum mfle = MaxFragLenEnum.valueOf(spec.id);
       
   554             if (mfle == null) {
       
   555                 chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   556                     "the requested maximum fragment length is other " +
       
   557                     "than the allowed values");
       
   558             }
       
   559 
       
   560             // update the context
       
   561             chc.maxFragmentLength = mfle.fragmentSize;
       
   562             chc.handshakeExtensions.put(EE_MAX_FRAGMENT_LENGTH, spec);
       
   563         }
       
   564     }
       
   565 
       
   566     /**
       
   567      * After session creation consuming of a "max_fragment_length"
       
   568      * extension in the EncryptedExtensions handshake message.
       
   569      */
       
   570     private static final
       
   571             class EEMaxFragmentLengthUpdate implements HandshakeConsumer {
       
   572         // Prevent instantiation of this class.
       
   573         private EEMaxFragmentLengthUpdate() {
       
   574             // blank
       
   575         }
       
   576 
       
   577         @Override
       
   578         public void consume(ConnectionContext context,
       
   579                 HandshakeMessage message) throws IOException {
       
   580             // The comsuming happens in client side only.
       
   581             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   582 
       
   583             MaxFragLenSpec spec = (MaxFragLenSpec)
       
   584                     chc.handshakeExtensions.get(EE_MAX_FRAGMENT_LENGTH);
       
   585             if (spec == null) {
       
   586                 // Ignore, no "max_fragment_length" extension response.
       
   587                 return;
       
   588             }
       
   589 
       
   590             if ((chc.maxFragmentLength > 0) &&
       
   591                     (chc.sslConfig.maximumPacketSize != 0)) {
       
   592                 int estimatedMaxFragSize =
       
   593                         chc.negotiatedCipherSuite.calculatePacketSize(
       
   594                                 chc.maxFragmentLength, chc.negotiatedProtocol,
       
   595                                 chc.sslContext.isDTLS());
       
   596                 if (estimatedMaxFragSize > chc.sslConfig.maximumPacketSize) {
       
   597                     // For better interoperability, abort the maximum
       
   598                     // fragment length negotiation, rather than terminate
       
   599                     // the connection with a fatal alert.
       
   600                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   601                         SSLLogger.fine(
       
   602                             "Abort the maximum fragment length negotiation, " +
       
   603                             "may overflow the maximum packet size limit.");
       
   604                     }
       
   605                     chc.maxFragmentLength = -1;
       
   606                 }
       
   607             }
       
   608 
       
   609             // update the context
       
   610             if (chc.maxFragmentLength > 0) {
       
   611                 chc.handshakeSession.setNegotiatedMaxFragSize(
       
   612                         chc.maxFragmentLength);
       
   613                 chc.conContext.inputRecord.changeFragmentSize(
       
   614                         chc.maxFragmentLength);
       
   615                 chc.conContext.outputRecord.changeFragmentSize(
       
   616                         chc.maxFragmentLength);
       
   617             }
       
   618         }
       
   619     }
       
   620 }