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 }