< prev index next >

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

Print this page


   1 /*
   2  * Copyright (c) 1996, 2015, 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 
  27 package sun.security.ssl;
  28 
  29 import java.io.ByteArrayInputStream;
  30 import java.io.IOException;
  31 import java.util.Hashtable;








  32 import java.util.Arrays;
  33 
  34 import java.security.*;
  35 import javax.crypto.*;
  36 import javax.crypto.spec.IvParameterSpec;



  37 import javax.crypto.spec.GCMParameterSpec;
















































































































































































































































































































  38 
  39 import java.nio.*;
  40 
  41 import sun.security.ssl.CipherSuite.*;
  42 import static sun.security.ssl.CipherSuite.*;
  43 import static sun.security.ssl.CipherSuite.CipherType.*;
  44 
  45 import sun.security.util.HexDumpEncoder;
  46 
  47 
  48 /**
  49  * This class handles bulk data enciphering/deciphering for each SSLv3
  50  * message.  This provides data confidentiality.  Stream ciphers (such
  51  * as RC4) don't need to do padding; block ciphers (e.g. DES) need it.
  52  *
  53  * Individual instances are obtained by calling the static method
  54  * newCipherBox(), which should only be invoked by BulkCipher.newCipher().
  55  *
  56  * In RFC 2246, with bock ciphers in CBC mode, the Initialization
  57  * Vector (IV) for the first record is generated with the other keys
  58  * and secrets when the security parameters are set.  The IV for
  59  * subsequent records is the last ciphertext block from the previous
  60  * record.
  61  *
  62  * In RFC 4346, the implicit Initialization Vector (IV) is replaced
  63  * with an explicit IV to protect against CBC attacks.  RFC 4346
  64  * recommends two algorithms used to generated the per-record IV.
  65  * The implementation uses the algorithm (2)(b), as described at
  66  * section 6.2.3.2 of RFC 4346.
  67  *
  68  * The usage of IV in CBC block cipher can be illustrated in
  69  * the following diagrams.
  70  *
  71  *   (random)
  72  *        R         P1                    IV        C1
  73  *        |          |                     |         |
  74  *  SIV---+    |-----+    |-...            |-----    |------
  75  *        |    |     |    |                |    |    |     |
  76  *     +----+  |  +----+  |             +----+  |  +----+  |
  77  *     | Ek |  |  + Ek +  |             | Dk |  |  | Dk |  |
  78  *     +----+  |  +----+  |             +----+  |  +----+  |
  79  *        |    |     |    |                |    |    |     |
  80  *        |----|     |----|           SIV--+    |----|     |-...
  81  *        |          |                     |       |
  82  *       IV         C1                     R      P1
  83  *                                     (discard)
  84  *
  85  *       CBC Encryption                    CBC Decryption
  86  *
  87  * NOTE that any ciphering involved in key exchange (e.g. with RSA) is
  88  * handled separately.
  89  *
  90  * @author David Brownell
  91  * @author Andreas Sterbenz
  92  */
  93 final class CipherBox {
  94 
  95     // A CipherBox that implements the identity operation
  96     static final CipherBox NULL = new CipherBox();
  97 
  98     /* Class and subclass dynamic debugging support */
  99     private static final Debug debug = Debug.getInstance("ssl");
 100 
 101     // the protocol version this cipher conforms to
 102     private final ProtocolVersion protocolVersion;
 103 
 104     // cipher object
 105     private final Cipher cipher;


 106 
 107     /**
 108      * secure random
 109      */
 110     private SecureRandom random;
 111 
 112     /**
 113      * fixed IV, the implicit nonce of AEAD cipher suite, only apply to
 114      * AEAD cipher suites
 115      */
 116     private final byte[] fixedIv;
 117 
 118     /**
 119      * the key, reserved only for AEAD cipher initialization
 120      */
 121     private final Key key;


































 122 
 123     /**
 124      * the operation mode, reserved for AEAD cipher initialization
 125      */
 126     private final int mode;





 127 
 128     /**
 129      * the authentication tag size, only apply to AEAD cipher suites
 130      */
 131     private final int tagSize;























 132 
 133     /**
 134      * the record IV length, only apply to AEAD cipher suites
 135      */
 136     private final int recordIvSize;













 137 
 138     /**
 139      * cipher type
 140      */
 141     private final CipherType cipherType;
 142 
 143     /**
 144      * Fixed masks of various block size, as the initial decryption IVs
 145      * for TLS 1.1 or later.
 146      *
 147      * For performance, we do not use random IVs. As the initial decryption
 148      * IVs will be discarded by TLS decryption processes, so the fixed masks
 149      * do not hurt cryptographic strength.
 150      */
 151     private static Hashtable<Integer, IvParameterSpec> masks;
 152 
 153     /**
 154      * NULL cipherbox. Identity operation, no encryption.
 155      */
 156     private CipherBox() {
 157         this.protocolVersion = ProtocolVersion.DEFAULT_TLS;
 158         this.cipher = null;
 159         this.cipherType = NULL_CIPHER;
 160         this.fixedIv = new byte[0];
 161         this.key = null;
 162         this.mode = Cipher.ENCRYPT_MODE;    // choose at random
 163         this.random = null;
 164         this.tagSize = 0;
 165         this.recordIvSize = 0;
 166     }
 167 
 168     /**
 169      * Construct a new CipherBox using the cipher transformation.
 170      *
 171      * @exception NoSuchAlgorithmException if no appropriate JCE Cipher
 172      * implementation could be found.
 173      */
 174     private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
 175             SecretKey key, IvParameterSpec iv, SecureRandom random,
 176             boolean encrypt) throws NoSuchAlgorithmException {
 177         try {
 178             this.protocolVersion = protocolVersion;
 179             this.cipher = JsseJce.getCipher(bulkCipher.transformation);
 180             this.mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
 181 
 182             if (random == null) {
 183                 random = JsseJce.getSecureRandom();
 184             }
 185             this.random = random;
 186             this.cipherType = bulkCipher.cipherType;
 187 
 188             /*
 189              * RFC 4346 recommends two algorithms used to generated the
 190              * per-record IV. The implementation uses the algorithm (2)(b),
 191              * as described at section 6.2.3.2 of RFC 4346.
 192              *
 193              * As we don't care about the initial IV value for TLS 1.1 or
 194              * later, so if the "iv" parameter is null, we use the default
 195              * value generated by Cipher.init() for encryption, and a fixed
 196              * mask for decryption.
 197              */
 198             if (iv == null && bulkCipher.ivSize != 0 &&
 199                     mode == Cipher.DECRYPT_MODE &&
 200                     protocolVersion.useTLS11PlusSpec()) {
 201                 iv = getFixedMask(bulkCipher.ivSize);
 202             }
 203 
 204             if (cipherType == AEAD_CIPHER) {
 205                 // AEAD must completely initialize the cipher for each packet,
 206                 // and so we save initialization parameters for packet
 207                 // processing time.
 208 
 209                 // Set the tag size for AEAD cipher
 210                 tagSize = bulkCipher.tagSize;
 211 
 212                 // Reserve the key for AEAD cipher initialization
 213                 this.key = key;
 214 
 215                 fixedIv = iv.getIV();
 216                 if (fixedIv == null ||
 217                         fixedIv.length != bulkCipher.fixedIvSize) {
 218                     throw new RuntimeException("Improper fixed IV for AEAD");
 219                 }
 220 
 221                 // Set the record IV length for AEAD cipher
 222                 recordIvSize = bulkCipher.ivSize - bulkCipher.fixedIvSize;




 223 
 224                 // DON'T initialize the cipher for AEAD!
 225             } else {
 226                 // CBC only requires one initialization during its lifetime
 227                 // (future packets/IVs set the proper CBC state), so we can
 228                 // initialize now.
 229 
 230                 // Zeroize the variables that only apply to AEAD cipher
 231                 this.tagSize = 0;
 232                 this.fixedIv = new byte[0];
 233                 this.recordIvSize = 0;
 234                 this.key = null;
 235 
 236                 // Initialize the cipher
 237                 cipher.init(mode, key, iv, random);




 238             }
 239         } catch (NoSuchAlgorithmException e) {
 240             throw e;
 241         } catch (Exception e) {
 242             throw new NoSuchAlgorithmException
 243                     ("Could not create cipher " + bulkCipher, e);
 244         } catch (ExceptionInInitializerError e) {
 245             throw new NoSuchAlgorithmException
 246                     ("Could not create cipher " + bulkCipher, e);
 247         }
 248     }
 249 
 250     /*
 251      * Factory method to obtain a new CipherBox object.
 252      */
 253     static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
 254             SecretKey key, IvParameterSpec iv, SecureRandom random,
 255             boolean encrypt) throws NoSuchAlgorithmException {
 256         if (cipher.allowed == false) {
 257             throw new NoSuchAlgorithmException("Unsupported cipher " + cipher);
 258         }
 259 
 260         if (cipher == BulkCipher.B_NULL) {
 261             return NULL;
 262         } else {
 263             return new CipherBox(version, cipher, key, iv, random, encrypt);


 264         }


 265     }
 266 
 267     /*
 268      * Get a fixed mask, as the initial decryption IVs for TLS 1.1 or later.
 269      */
 270     private static IvParameterSpec getFixedMask(int ivSize) {
 271         if (masks == null) {
 272             masks = new Hashtable<Integer, IvParameterSpec>(5);
 273         }
 274 
 275         IvParameterSpec iv = masks.get(ivSize);
 276         if (iv == null) {
 277             iv = new IvParameterSpec(new byte[ivSize]);
 278             masks.put(ivSize, iv);








 279         }
 280 
 281         return iv;
 282     }
 283 
 284     /*
 285      * Encrypts a block of data, returning the size of the
 286      * resulting block.
 287      */
 288     int encrypt(byte[] buf, int offset, int len) {
 289         if (cipher == null) {
 290             return len;
 291         }
 292 
 293         try {
 294             int blockSize = cipher.getBlockSize();
 295             if (cipherType == BLOCK_CIPHER) {
 296                 len = addPadding(buf, offset, len, blockSize);


 297             }
 298 
 299             if (debug != null && Debug.isOn("plaintext")) {
 300                 try {
 301                     HexDumpEncoder hd = new HexDumpEncoder();

 302 
 303                     System.out.println(
 304                         "Padded plaintext before ENCRYPTION:  len = "
 305                         + len);
 306                     hd.encodeBuffer(
 307                         new ByteArrayInputStream(buf, offset, len),
 308                         System.out);
 309                 } catch (IOException e) { }
 310             }
 311 
 312 
 313             if (cipherType == AEAD_CIPHER) {
 314                 try {
 315                     return cipher.doFinal(buf, offset, len, buf, offset);
 316                 } catch (IllegalBlockSizeException | BadPaddingException ibe) {
 317                     // unlikely to happen
 318                     throw new RuntimeException(
 319                         "Cipher error in AEAD mode in JCE provider " +
 320                         cipher.getProvider().getName(), ibe);
 321                 }
 322             } else {
 323                 int newLen = cipher.update(buf, offset, len, buf, offset);
 324                 if (newLen != len) {
 325                     // catch BouncyCastle buffering error
 326                     throw new RuntimeException("Cipher buffering error " +
 327                         "in JCE provider " + cipher.getProvider().getName());
 328                 }
 329                 return newLen;








 330             }
 331         } catch (ShortBufferException e) {
 332             // unlikely to happen, we should have enough buffer space here
 333             throw new ArrayIndexOutOfBoundsException(e.toString());
 334         }






 335     }
 336 
 337     /*
 338      * Encrypts a ByteBuffer block of data, returning the size of the
 339      * resulting block.
 340      *
 341      * The byte buffers position and limit initially define the amount
 342      * to encrypt.  On return, the position and limit are
 343      * set to last position padded/encrypted.  The limit may have changed
 344      * because of the added padding bytes.
 345      */
 346     int encrypt(ByteBuffer bb, int outLimit) {
 347 
 348         int len = bb.remaining();



 349 
 350         if (cipher == null) {
 351             bb.position(bb.limit());
 352             return len;
















 353         }
 354 
 355         int pos = bb.position();
 356 
 357         int blockSize = cipher.getBlockSize();
 358         if (cipherType == BLOCK_CIPHER) {
 359             // addPadding adjusts pos/limit
 360             len = addPadding(bb, blockSize);
 361             bb.position(pos);





 362         }
 363 
 364         if (debug != null && Debug.isOn("plaintext")) {
 365             try {
 366                 HexDumpEncoder hd = new HexDumpEncoder();












 367 
 368                 System.out.println(
 369                     "Padded plaintext before ENCRYPTION:  len = "
 370                     + len);
 371                 hd.encodeBuffer(bb.duplicate(), System.out);
 372 
 373             } catch (IOException e) { }

 374         }
 375 
 376         /*
 377          * Encrypt "in-place".  This does not add its own padding.
 378          */
 379         ByteBuffer dup = bb.duplicate();
 380         if (cipherType == AEAD_CIPHER) {
 381             try {
 382                 int outputSize = cipher.getOutputSize(dup.remaining());
 383                 if (outputSize > bb.remaining()) {
 384                     // need to expand the limit of the output buffer for
 385                     // the authentication tag.
 386                     //
 387                     // DON'T worry about the buffer's capacity, we have
 388                     // reserved space for the authentication tag.
 389                     if (outLimit < pos + outputSize) {
 390                         // unlikely to happen
 391                         throw new ShortBufferException(
 392                                     "need more space in output buffer");
 393                     }
 394                     bb.limit(pos + outputSize);







 395                 }
 396                 int newLen = cipher.doFinal(dup, bb);
 397                 if (newLen != outputSize) {
 398                     throw new RuntimeException(
 399                             "Cipher buffering error in JCE provider " +
 400                             cipher.getProvider().getName());
 401                 }
 402                 return newLen;
 403             } catch (IllegalBlockSizeException |
 404                            BadPaddingException | ShortBufferException ibse) {
 405                 // unlikely to happen
 406                 throw new RuntimeException(
 407                         "Cipher error in AEAD mode in JCE provider " +
 408                         cipher.getProvider().getName(), ibse);
 409             }
























 410         } else {
 411             int newLen;
 412             try {
 413                 newLen = cipher.update(dup, bb);
 414             } catch (ShortBufferException sbe) {
 415                 // unlikely to happen
 416                 throw new RuntimeException("Cipher buffering error " +
 417                     "in JCE provider " + cipher.getProvider().getName());
 418             }
 419 
 420             if (bb.position() != dup.position()) {
 421                 throw new RuntimeException("bytebuffer padding error");

 422             }
 423 
 424             if (newLen != len) {
 425                 // catch BouncyCastle buffering error
 426                 throw new RuntimeException("Cipher buffering error " +
 427                     "in JCE provider " + cipher.getProvider().getName());





 428             }
 429             return newLen;
 430         }
 431     }
 432 
 433 
 434     /*
 435      * Decrypts a block of data, returning the size of the
 436      * resulting block if padding was required.
 437      *
 438      * For SSLv3 and TLSv1.0, with block ciphers in CBC mode the
 439      * Initialization Vector (IV) for the first record is generated by
 440      * the handshake protocol, the IV for subsequent records is the
 441      * last ciphertext block from the previous record.
 442      *
 443      * From TLSv1.1, the implicit IV is replaced with an explicit IV to
 444      * protect against CBC attacks.
 445      *
 446      * Differentiating between bad_record_mac and decryption_failed alerts
 447      * may permit certain attacks against CBC mode. It is preferable to
 448      * uniformly use the bad_record_mac alert to hide the specific type of
 449      * the error.
 450      */
 451     int decrypt(byte[] buf, int offset, int len,
 452             int tagLen) throws BadPaddingException {
 453         if (cipher == null) {
 454             return len;
 455         }
 456 
 457         try {
 458             int newLen;
 459             if (cipherType == AEAD_CIPHER) {
 460                 try {
 461                     newLen = cipher.doFinal(buf, offset, len, buf, offset);
 462                 } catch (IllegalBlockSizeException ibse) {
 463                     // unlikely to happen
 464                     throw new RuntimeException(
 465                         "Cipher error in AEAD mode in JCE provider " +
 466                         cipher.getProvider().getName(), ibse);
 467                 }







 468             } else {
 469                 newLen = cipher.update(buf, offset, len, buf, offset);
 470                 if (newLen != len) {
 471                     // catch BouncyCastle buffering error
 472                     throw new RuntimeException("Cipher buffering error " +
 473                         "in JCE provider " + cipher.getProvider().getName());
 474                 }
 475             }
 476             if (debug != null && Debug.isOn("plaintext")) {
 477                 try {
 478                     HexDumpEncoder hd = new HexDumpEncoder();
 479 
 480                     System.out.println(
 481                         "Padded plaintext after DECRYPTION:  len = "
 482                         + newLen);
 483                     hd.encodeBuffer(
 484                         new ByteArrayInputStream(buf, offset, newLen),
 485                         System.out);
 486                 } catch (IOException e) { }
 487             }
 488 
 489             if (cipherType == BLOCK_CIPHER) {
 490                 int blockSize = cipher.getBlockSize();
 491                 newLen = removePadding(
 492                     buf, offset, newLen, tagLen, blockSize, protocolVersion);
 493 
 494                 if (protocolVersion.useTLS11PlusSpec()) {
 495                     if (newLen < blockSize) {
 496                         throw new BadPaddingException("The length after " +
 497                         "padding removal (" + newLen + ") should be larger " +
 498                         "than <" + blockSize + "> since explicit IV used");




 499                     }





 500                 }




 501             }
 502             return newLen;
 503         } catch (ShortBufferException e) {
 504             // unlikely to happen, we should have enough buffer space here
 505             throw new ArrayIndexOutOfBoundsException(e.toString());
 506         }
 507     }
 508 
 509     /*
 510      * Decrypts a block of data, returning the size of the
 511      * resulting block if padding was required.  position and limit
 512      * point to the end of the decrypted/depadded data.  The initial
 513      * limit and new limit may be different, given we may
 514      * have stripped off some padding bytes.
 515      *
 516      *  @see decrypt(byte[], int, int)
 517      */
 518     int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException {

 519 
 520         int len = bb.remaining();

 521 
 522         if (cipher == null) {
 523             bb.position(bb.limit());
 524             return len;




 525         }
 526 
 527         try {
 528             /*
 529              * Decrypt "in-place".
 530              */
 531             int pos = bb.position();
 532             ByteBuffer dup = bb.duplicate();
 533             int newLen;
 534             if (cipherType == AEAD_CIPHER) {
 535                 try {
 536                     newLen = cipher.doFinal(dup, bb);
 537                 } catch (IllegalBlockSizeException ibse) {
 538                     // unlikely to happen
 539                     throw new RuntimeException(
 540                         "Cipher error in AEAD mode \"" + ibse.getMessage() +
 541                         " \"in JCE provider " + cipher.getProvider().getName());
 542                 }
 543             } else {
 544                 newLen = cipher.update(dup, bb);
 545                 if (newLen != len) {


 546                     // catch BouncyCastle buffering error
 547                     throw new RuntimeException("Cipher buffering error " +
 548                         "in JCE provider " + cipher.getProvider().getName());
 549                 }




 550             }
 551 
 552             // reset the limit to the end of the decryted data
 553             bb.limit(pos + newLen);
 554 
 555             if (debug != null && Debug.isOn("plaintext")) {
 556                 try {
 557                     HexDumpEncoder hd = new HexDumpEncoder();
 558 
 559                     System.out.println(
 560                         "Padded plaintext after DECRYPTION:  len = "
 561                         + newLen);
 562 
 563                     hd.encodeBuffer(
 564                         bb.duplicate().position(pos), System.out);
 565                 } catch (IOException e) { }
 566             }
 567 
 568             /*
 569              * Remove the block padding.
 570              */
 571             if (cipherType == BLOCK_CIPHER) {
 572                 int blockSize = cipher.getBlockSize();
 573                 bb.position(pos);
 574                 newLen = removePadding(bb, tagLen, blockSize, protocolVersion);
 575 
 576                 // check the explicit IV of TLS v1.1 or later
 577                 if (protocolVersion.useTLS11PlusSpec()) {
 578                     if (newLen < blockSize) {
 579                         throw new BadPaddingException("The length after " +
 580                         "padding removal (" + newLen + ") should be larger " +
 581                         "than <" + blockSize + "> since explicit IV used");



 582                     }
 583 
 584                     // reset the position to the end of the decrypted data
 585                     bb.position(bb.limit());


 586                 }
 587             }
 588             return newLen;
 589         } catch (ShortBufferException e) {
 590             // unlikely to happen, we should have enough buffer space here
 591             throw new ArrayIndexOutOfBoundsException(e.toString());
 592         }











 593     }
 594 
 595     private static int addPadding(byte[] buf, int offset, int len,
 596             int blockSize) {
 597         int     newlen = len + 1;
 598         byte    pad;
 599         int     i;
 600 
 601         if ((newlen % blockSize) != 0) {
 602             newlen += blockSize - 1;
 603             newlen -= newlen % blockSize;




 604         }
 605         pad = (byte) (newlen - len);
 606 
 607         if (buf.length < (newlen + offset)) {
 608             throw new IllegalArgumentException("no space to pad buffer");






 609         }
 610 
 611         /*
 612          * TLS version of the padding works for both SSLv3 and TLSv1
 613          */
 614         for (i = 0, offset += len; i < pad; i++) {
 615             buf [offset++] = (byte) (pad - 1);
 616         }
 617         return newlen;
















 618     }
 619 
 620     /*
 621      * Apply the padding to the buffer.
 622      *
 623      * Limit is advanced to the new buffer length.
 624      * Position is equal to limit.
 625      */
 626     private static int addPadding(ByteBuffer bb, int blockSize) {
 627 
 628         int     len = bb.remaining();
 629         int     offset = bb.position();








 630 
 631         int     newlen = len + 1;
 632         byte    pad;
 633         int     i;

 634 
 635         if ((newlen % blockSize) != 0) {
 636             newlen += blockSize - 1;
 637             newlen -= newlen % blockSize;

 638         }
 639         pad = (byte) (newlen - len);
 640 
 641         /*
 642          * Update the limit to what will be padded.
 643          */
 644         bb.limit(newlen + offset);



 645 
 646         /*
 647          * TLS version of the padding works for both SSLv3 and TLSv1
 648          */
 649         for (i = 0, offset += len; i < pad; i++) {
 650             bb.put(offset++, (byte) (pad - 1));





 651         }
 652 
 653         bb.position(offset);
 654         bb.limit(offset);
 655 
 656         return newlen;






 657     }
 658 
 659     /*
 660      * A constant-time check of the padding.
 661      *
 662      * NOTE that we are checking both the padding and the padLen bytes here.
 663      *
 664      * The caller MUST ensure that the len parameter is a positive number.
 665      */
 666     private static int[] checkPadding(
 667             byte[] buf, int offset, int len, byte pad) {


























 668 
 669         if (len <= 0) {
 670             throw new RuntimeException("padding len must be positive");


 671         }
 672 
 673         // An array of hits is used to prevent Hotspot optimization for
 674         // the purpose of a constant-time check.
 675         int[] results = {0, 0};    // {missed #, matched #}
 676         for (int i = 0; i <= 256;) {
 677             for (int j = 0; j < len && i <= 256; j++, i++) {     // j <= i
 678                 if (buf[offset + j] != pad) {
 679                     results[0]++;       // mismatched padding data










 680                 } else {
 681                     results[1]++;       // matched padding data
 682                 }



 683             }
 684         }
 685 
 686         return results;


 687     }
 688 
 689     /*
 690      * A constant-time check of the padding.


























 691      *
 692      * NOTE that we are checking both the padding and the padLen bytes here.




 693      *
 694      * The caller MUST ensure that the bb parameter has remaining.




 695      */
 696     private static int[] checkPadding(ByteBuffer bb, byte pad) {




 697 
 698         if (!bb.hasRemaining()) {
 699             throw new RuntimeException("hasRemaining() must be positive");
 700         }
 701 
 702         // An array of hits is used to prevent Hotspot optimization for
 703         // the purpose of a constant-time check.
 704         int[] results = {0, 0};    // {missed #, matched #}
 705         bb.mark();
 706         for (int i = 0; i <= 256; bb.reset()) {
 707             for (; bb.hasRemaining() && i <= 256; i++) {
 708                 if (bb.get() != pad) {
 709                     results[0]++;       // mismatched padding data
 710                 } else {
 711                     results[1]++;       // matched padding data
 712                 }
 713             }
 714         }
 715 
 716         return results;









 717     }
 718 
 719     /*
 720      * Typical TLS padding format for a 64 bit block cipher is as follows:
 721      *   xx xx xx xx xx xx xx 00
 722      *   xx xx xx xx xx xx 01 01
 723      *   ...
 724      *   xx 06 06 06 06 06 06 06
 725      *   07 07 07 07 07 07 07 07
 726      * TLS also allows any amount of padding from 1 and 256 bytes as long
 727      * as it makes the data a multiple of the block size
 728      */
 729     private static int removePadding(byte[] buf, int offset, int len,
 730             int tagLen, int blockSize,
 731             ProtocolVersion protocolVersion) throws BadPaddingException {
 732 
 733         // last byte is length byte (i.e. actual padding length - 1)
 734         int padOffset = offset + len - 1;
 735         int padLen = buf[padOffset] & 0xFF;





 736 
 737         int newLen = len - (padLen + 1);
 738         if ((newLen - tagLen) < 0) {
 739             // If the buffer is not long enough to contain the padding plus
 740             // a MAC tag, do a dummy constant-time padding check.
 741             //
 742             // Note that it is a dummy check, so we won't care about what is
 743             // the actual padding data.
 744             checkPadding(buf, offset, len, (byte)(padLen & 0xFF));
 745 
 746             throw new BadPaddingException("Invalid Padding length: " + padLen);





 747         }
 748 
 749         // The padding data should be filled with the padding length value.
 750         int[] results = checkPadding(buf, offset + newLen,
 751                         padLen + 1, (byte)(padLen & 0xFF));
 752         if (protocolVersion.useTLS10PlusSpec()) {
 753             if (results[0] != 0) {          // padding data has invalid bytes
 754                 throw new BadPaddingException("Invalid TLS padding data");


 755             }
 756         } else { // SSLv3
 757             // SSLv3 requires 0 <= length byte < block size
 758             // some implementations do 1 <= length byte <= block size,
 759             // so accept that as well
 760             // v3 does not require any particular value for the other bytes
 761             if (padLen > blockSize) {
 762                 throw new BadPaddingException("Padding length (" +
 763                 padLen + ") of SSLv3 message should not be bigger " +
 764                 "than the block size (" + blockSize + ")");
 765             }




 766         }
 767         return newLen;



 768     }
 769 
 770     /*
 771      * Position/limit is equal the removed padding.
 772      */
 773     private static int removePadding(ByteBuffer bb,
 774             int tagLen, int blockSize,
 775             ProtocolVersion protocolVersion) throws BadPaddingException {
 776 
 777         int len = bb.remaining();
 778         int offset = bb.position();








 779 
 780         // last byte is length byte (i.e. actual padding length - 1)
 781         int padOffset = offset + len - 1;
 782         int padLen = bb.get(padOffset) & 0xFF;

 783 
 784         int newLen = len - (padLen + 1);
 785         if ((newLen - tagLen) < 0) {
 786             // If the buffer is not long enough to contain the padding plus
 787             // a MAC tag, do a dummy constant-time padding check.
 788             //
 789             // Note that it is a dummy check, so we won't care about what is
 790             // the actual padding data.
 791             checkPadding(bb.duplicate(), (byte)(padLen & 0xFF));



 792 
 793             throw new BadPaddingException("Invalid Padding length: " + padLen);







 794         }
 795 
 796         // The padding data should be filled with the padding length value.
 797         int[] results = checkPadding(
 798                 bb.duplicate().position(offset + newLen),
 799                 (byte)(padLen & 0xFF));
 800         if (protocolVersion.useTLS10PlusSpec()) {
 801             if (results[0] != 0) {          // padding data has invalid bytes
 802                 throw new BadPaddingException("Invalid TLS padding data");
 803             }
 804         } else { // SSLv3
 805             // SSLv3 requires 0 <= length byte < block size
 806             // some implementations do 1 <= length byte <= block size,
 807             // so accept that as well
 808             // v3 does not require any particular value for the other bytes
 809             if (padLen > blockSize) {
 810                 throw new BadPaddingException("Padding length (" +
 811                 padLen + ") of SSLv3 message should not be bigger " +
 812                 "than the block size (" + blockSize + ")");








































































































































































































































































































































































































































































































































































































































































































































































































 813             }









 814         }
 815 
 816         /*
 817          * Reset buffer limit to remove padding.
 818          */
 819         bb.position(offset + newLen);
 820         bb.limit(offset + newLen);
 821 
 822         return newLen;



 823     }
 824 
 825     /*
 826      * Dispose of any intermediate state in the underlying cipher.
 827      * For PKCS11 ciphers, this will release any attached sessions, and
 828      * thus make finalization faster.
 829      */
 830     void dispose() {
 831         try {
 832             if (cipher != null) {
 833                 // ignore return value.
 834                 cipher.doFinal();
 835             }
 836         } catch (Exception e) {
 837             // swallow all types of exceptions.
 838         }
 839     }

 840 
 841     /*
 842      * Does the cipher use CBC mode?
 843      *
 844      * @return true if the cipher use CBC mode, false otherwise.
 845      */
 846     boolean isCBCMode() {
 847         return cipherType == BLOCK_CIPHER;
 848     }
 849 
 850     /*
 851      * Does the cipher use AEAD mode?
 852      *
 853      * @return true if the cipher use AEAD mode, false otherwise.
 854      */
 855     boolean isAEADMode() {
 856         return cipherType == AEAD_CIPHER;
 857     }
 858 
 859     /*
 860      * Is the cipher null?
 861      *
 862      * @return true if the cipher is null, false otherwise.
 863      */
 864     boolean isNullCipher() {
 865         return cipher == null;
 866     }







 867 
 868     /*
 869      * Gets the explicit nonce/IV size of the cipher.
 870      *
 871      * The returned value is the SecurityParameters.record_iv_length in
 872      * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
 873      * size of explicit nonce for AEAD mode.
 874      *
 875      * @return the explicit nonce size of the cipher.
 876      */
 877     int getExplicitNonceSize() {
 878         switch (cipherType) {
 879             case BLOCK_CIPHER:
 880                 // For block ciphers, the explicit IV length is of length
 881                 // SecurityParameters.record_iv_length, which is equal to
 882                 // the SecurityParameters.block_size.
 883                 if (protocolVersion.useTLS11PlusSpec()) {
 884                     return cipher.getBlockSize();
 885                 }
 886                 break;
 887             case AEAD_CIPHER:
 888                 return recordIvSize;
 889                         // It is also the length of sequence number, which is
 890                         // used as the nonce_explicit for AEAD cipher suites.
 891         }
 892 
 893         return 0;
 894     }


 895 
 896     /*
 897      * Applies the explicit nonce/IV to this cipher. This method is used to
 898      * decrypt an SSL/TLS input record.
 899      *
 900      * The returned value is the SecurityParameters.record_iv_length in
 901      * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
 902      * size of explicit nonce for AEAD mode.
 903      *
 904      * @param  authenticator the authenticator to get the additional
 905      *         authentication data
 906      * @param  contentType the content type of the input record
 907      * @param  bb the byte buffer to get the explicit nonce from
 908      *
 909      * @return the explicit nonce size of the cipher.
 910      */
 911     int applyExplicitNonce(Authenticator authenticator, byte contentType,
 912             ByteBuffer bb, byte[] sequence) throws BadPaddingException {
 913         switch (cipherType) {
 914             case BLOCK_CIPHER:
 915                 // sanity check length of the ciphertext
 916                 int tagLen = (authenticator instanceof MAC) ?
 917                                     ((MAC)authenticator).MAClen() : 0;
 918                 if (tagLen != 0) {
 919                     if (!sanityCheck(tagLen, bb.remaining())) {
 920                         throw new BadPaddingException(
 921                                 "ciphertext sanity check failed");
 922                     }
 923                 }
 924 
 925                 // For block ciphers, the explicit IV length is of length
 926                 // SecurityParameters.record_iv_length, which is equal to
 927                 // the SecurityParameters.block_size.
 928                 if (protocolVersion.useTLS11PlusSpec()) {
 929                     return cipher.getBlockSize();
 930                 }
 931                 break;
 932             case AEAD_CIPHER:
 933                 if (bb.remaining() < (recordIvSize + tagSize)) {
 934                     throw new BadPaddingException(
 935                         "Insufficient buffer remaining for AEAD cipher " +
 936                         "fragment (" + bb.remaining() + "). Needs to be " +
 937                         "more than or equal to IV size (" + recordIvSize +
 938                          ") + tag size (" + tagSize + ")");
 939                 }
 940 
 941                 // initialize the AEAD cipher for the unique IV
 942                 byte[] iv = Arrays.copyOf(fixedIv,
 943                                     fixedIv.length + recordIvSize);
 944                 bb.get(iv, fixedIv.length, recordIvSize);
 945                 bb.position(bb.position() - recordIvSize);
 946                 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
 947                 try {
 948                     cipher.init(mode, key, spec, random);
 949                 } catch (InvalidKeyException |
 950                             InvalidAlgorithmParameterException ikae) {
 951                     // unlikely to happen
 952                     throw new RuntimeException(
 953                                 "invalid key or spec in GCM mode", ikae);
 954                 }
 955 
 956                 // update the additional authentication data
 957                 byte[] aad = authenticator.acquireAuthenticationBytes(
 958                         contentType, bb.remaining() - recordIvSize - tagSize,
 959                         sequence);
 960                 cipher.updateAAD(aad);


 961 
 962                 return recordIvSize;
 963                         // It is also the length of sequence number, which is
 964                         // used as the nonce_explicit for AEAD cipher suites.





 965         }
 966 
 967        return 0;







 968     }
 969 
 970     /*
 971      * Creates the explicit nonce/IV to this cipher. This method is used to
 972      * encrypt an SSL/TLS output record.
 973      *
 974      * The size of the returned array is the SecurityParameters.record_iv_length
 975      * in RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
 976      * size of explicit nonce for AEAD mode.
 977      *
 978      * @param  authenticator the authenticator to get the additional
 979      *         authentication data
 980      * @param  contentType the content type of the input record
 981      * @param  fragmentLength the fragment length of the output record, it is
 982      *         the TLSCompressed.length in RFC 4346/5246.
 983      *
 984      * @return the explicit nonce of the cipher.
 985      */
 986     byte[] createExplicitNonce(Authenticator authenticator,
 987             byte contentType, int fragmentLength) {
 988 
 989         byte[] nonce = new byte[0];
 990         switch (cipherType) {
 991             case BLOCK_CIPHER:
 992                 if (protocolVersion.useTLS11PlusSpec()) {
 993                     // For block ciphers, the explicit IV length is of length
 994                     // SecurityParameters.record_iv_length, which is equal to
 995                     // the SecurityParameters.block_size.
 996                     //
 997                     // Generate a random number as the explicit IV parameter.
 998                     nonce = new byte[cipher.getBlockSize()];
 999                     random.nextBytes(nonce);
1000                 }
1001                 break;
1002             case AEAD_CIPHER:
1003                 // To be unique and aware of overflow-wrap, sequence number
1004                 // is used as the nonce_explicit of AEAD cipher suites.
1005                 nonce = authenticator.sequenceNumber();
1006 
1007                 // initialize the AEAD cipher for the unique IV
1008                 byte[] iv = Arrays.copyOf(fixedIv,
1009                                             fixedIv.length + nonce.length);
1010                 System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
1011                 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
1012                 try {
1013                     cipher.init(mode, key, spec, random);
1014                 } catch (InvalidKeyException |
1015                             InvalidAlgorithmParameterException ikae) {
1016                     // unlikely to happen
1017                     throw new RuntimeException(
1018                                 "invalid key or spec in GCM mode", ikae);
1019                 }
1020 
1021                 // Update the additional authentication data, using the
1022                 // implicit sequence number of the authenticator.
1023                 byte[] aad = authenticator.acquireAuthenticationBytes(
1024                                         contentType, fragmentLength, null);
1025                 cipher.updateAAD(aad);
1026                 break;
1027         }











1028 
1029         return nonce;




1030     }
1031 
1032     // See also CipherSuite.calculatePacketSize().
1033     int calculatePacketSize(int fragmentSize, int macLen, int headerSize) {
1034         int packetSize = fragmentSize;
1035         if (cipher != null) {
1036             int blockSize = cipher.getBlockSize();
1037             switch (cipherType) {
1038                 case BLOCK_CIPHER:
1039                     packetSize += macLen;
1040                     packetSize += 1;        // 1 byte padding length field
1041                     packetSize +=           // use the minimal padding
1042                             (blockSize - (packetSize % blockSize)) % blockSize;
1043                     if (protocolVersion.useTLS11PlusSpec()) {
1044                         packetSize += blockSize;        // explicit IV
1045                     }
1046 
1047                     break;
1048                 case AEAD_CIPHER:
1049                     packetSize += recordIvSize;
1050                     packetSize += tagSize;





1051 
1052                     break;
1053                 default:    // NULL_CIPHER or STREAM_CIPHER
1054                     packetSize += macLen;




1055             }
1056         }
1057 
1058         return packetSize + headerSize;
1059     }
1060 
1061     // See also CipherSuite.calculateFragSize().
1062     int calculateFragmentSize(int packetLimit, int macLen, int headerSize) {
1063         int fragLen = packetLimit - headerSize;
1064         if (cipher != null) {
1065             int blockSize = cipher.getBlockSize();
1066             switch (cipherType) {
1067                 case BLOCK_CIPHER:
1068                     if (protocolVersion.useTLS11PlusSpec()) {
1069                         fragLen -= blockSize;           // explicit IV
















1070                     }
1071                     fragLen -= (fragLen % blockSize);   // cannot hold a block
1072                     // No padding for a maximum fragment.
1073                     fragLen -= 1;       // 1 byte padding length field: 0x00
1074                     fragLen -= macLen;
1075 
1076                     break;
1077                 case AEAD_CIPHER:
1078                     fragLen -= recordIvSize;
1079                     fragLen -= tagSize;
1080 
1081                     break;
1082                 default:    // NULL_CIPHER or STREAM_CIPHER
1083                     fragLen -= macLen;
1084             }






1085         }

1086 
1087         return fragLen;









1088     }
1089 
1090     // Estimate the maximum fragment size of a received packet.
1091     int estimateFragmentSize(int packetSize, int macLen, int headerSize) {
1092         int fragLen = packetSize - headerSize;
1093         if (cipher != null) {
1094             int blockSize = cipher.getBlockSize();
1095             switch (cipherType) {
1096                 case BLOCK_CIPHER:
1097                     if (protocolVersion.useTLS11PlusSpec()) {
1098                         fragLen -= blockSize;       // explicit IV
1099                     }
1100                     // No padding for a maximum fragment.
1101                     fragLen -= 1;       // 1 byte padding length field: 0x00
1102                     fragLen -= macLen;
1103 
1104                     break;
1105                 case AEAD_CIPHER:
1106                     fragLen -= recordIvSize;
1107                     fragLen -= tagSize;





1108 
1109                     break;
1110                 default:    // NULL_CIPHER or STREAM_CIPHER
1111                     fragLen -= macLen;


























1112             }
1113         }
1114 
1115         return fragLen;



1116     }
1117 
1118     /**
1119      * Sanity check the length of a fragment before decryption.
1120      *
1121      * In CBC mode, check that the fragment length is one or multiple times
1122      * of the block size of the cipher suite, and is at least one (one is the
1123      * smallest size of padding in CBC mode) bigger than the tag size of the
1124      * MAC algorithm except the explicit IV size for TLS 1.1 or later.
1125      *
1126      * In non-CBC mode, check that the fragment length is not less than the
1127      * tag size of the MAC algorithm.
1128      *
1129      * @return true if the length of a fragment matches above requirements
1130      */
1131     private boolean sanityCheck(int tagLen, int fragmentLen) {
1132         if (!isCBCMode()) {
1133             return fragmentLen >= tagLen;
1134         }
1135 
1136         int blockSize = cipher.getBlockSize();
1137         if ((fragmentLen % blockSize) == 0) {
1138             int minimal = tagLen + 1;
1139             minimal = (minimal >= blockSize) ? minimal : blockSize;
1140             if (protocolVersion.useTLS11PlusSpec()) {
1141                 minimal += blockSize;   // plus the size of the explicit IV




1142             }
1143 
1144             return (fragmentLen >= minimal);
1145         }
1146 
1147         return false;
1148     }
1149 


1150 }

   1 /*
   2  * Copyright (c) 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.nio.ByteBuffer;
  29 import java.security.AccessController;
  30 import java.security.GeneralSecurityException;
  31 import java.security.InvalidAlgorithmParameterException;
  32 import java.security.InvalidKeyException;
  33 import java.security.Key;
  34 import java.security.PrivilegedAction;
  35 import java.security.SecureRandom;
  36 import java.security.Security;
  37 import java.security.spec.AlgorithmParameterSpec;
  38 import java.util.AbstractMap.SimpleImmutableEntry;
  39 import java.util.Arrays;
  40 import java.util.HashMap;
  41 import java.util.Map;
  42 import javax.crypto.BadPaddingException;
  43 import javax.crypto.Cipher;
  44 import javax.crypto.IllegalBlockSizeException;
  45 import javax.crypto.SecretKey;
  46 import javax.crypto.ShortBufferException;
  47 import javax.crypto.spec.GCMParameterSpec;
  48 import javax.crypto.spec.IvParameterSpec;
  49 import sun.security.ssl.Authenticator.MAC;
  50 import static sun.security.ssl.CipherType.*;
  51 import static sun.security.ssl.JsseJce.*;
  52 
  53 enum SSLCipher {
  54     // exportable ciphers
  55     @SuppressWarnings({"unchecked", "rawtypes"})
  56     B_NULL("NULL", NULL_CIPHER, 0, 0, 0, 0, true, true,
  57         (Map.Entry<ReadCipherGenerator,
  58                 ProtocolVersion[]>[])(new Map.Entry[] {
  59             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
  60                 new NullReadCipherGenerator(),
  61                 ProtocolVersion.PROTOCOLS_OF_NONE
  62             ),
  63             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
  64                 new NullReadCipherGenerator(),
  65                 ProtocolVersion.PROTOCOLS_TO_13
  66             )
  67         }),
  68         (Map.Entry<WriteCipherGenerator,
  69                 ProtocolVersion[]>[])(new Map.Entry[] {
  70             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
  71                 new NullWriteCipherGenerator(),
  72                 ProtocolVersion.PROTOCOLS_OF_NONE
  73             ),
  74             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
  75                 new NullWriteCipherGenerator(),
  76                 ProtocolVersion.PROTOCOLS_TO_13
  77             )
  78         })),
  79 
  80     @SuppressWarnings({"unchecked", "rawtypes"})
  81     B_RC4_40(CIPHER_RC4, STREAM_CIPHER, 5, 16, 0, 0, true, true,
  82         (Map.Entry<ReadCipherGenerator,
  83                 ProtocolVersion[]>[])(new Map.Entry[] {
  84             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
  85                 new StreamReadCipherGenerator(),
  86                 ProtocolVersion.PROTOCOLS_TO_10
  87             )
  88         }),
  89         (Map.Entry<WriteCipherGenerator,
  90                 ProtocolVersion[]>[])(new Map.Entry[] {
  91             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
  92                 new StreamWriteCipherGenerator(),
  93                 ProtocolVersion.PROTOCOLS_TO_10
  94             )
  95         })),
  96 
  97     @SuppressWarnings({"unchecked", "rawtypes"})
  98     B_RC2_40("RC2", BLOCK_CIPHER, 5, 16, 8, 0, false, true,
  99         (Map.Entry<ReadCipherGenerator,
 100                 ProtocolVersion[]>[])(new Map.Entry[] {
 101             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 102                 new StreamReadCipherGenerator(),
 103                 ProtocolVersion.PROTOCOLS_TO_10
 104             )
 105         }),
 106         (Map.Entry<WriteCipherGenerator,
 107                 ProtocolVersion[]>[])(new Map.Entry[] {
 108             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 109                 new StreamWriteCipherGenerator(),
 110                 ProtocolVersion.PROTOCOLS_TO_10
 111             )
 112         })),
 113 
 114     @SuppressWarnings({"unchecked", "rawtypes"})
 115     B_DES_40(CIPHER_DES,  BLOCK_CIPHER, 5, 8, 8, 0, true, true,
 116         (Map.Entry<ReadCipherGenerator,
 117                 ProtocolVersion[]>[])(new Map.Entry[] {
 118             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 119                 new T10BlockReadCipherGenerator(),
 120                 ProtocolVersion.PROTOCOLS_TO_10
 121             )
 122         }),
 123         (Map.Entry<WriteCipherGenerator,
 124                 ProtocolVersion[]>[])(new Map.Entry[] {
 125             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 126                 new T10BlockWriteCipherGenerator(),
 127                 ProtocolVersion.PROTOCOLS_TO_10
 128             )
 129         })),
 130 
 131     // domestic strength ciphers
 132     @SuppressWarnings({"unchecked", "rawtypes"})
 133     B_RC4_128(CIPHER_RC4, STREAM_CIPHER, 16, 16, 0, 0, true, false,
 134         (Map.Entry<ReadCipherGenerator,
 135                 ProtocolVersion[]>[])(new Map.Entry[] {
 136             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 137                 new StreamReadCipherGenerator(),
 138                 ProtocolVersion.PROTOCOLS_TO_12
 139             )
 140         }),
 141         (Map.Entry<WriteCipherGenerator,
 142                 ProtocolVersion[]>[])(new Map.Entry[] {
 143             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 144                 new StreamWriteCipherGenerator(),
 145                 ProtocolVersion.PROTOCOLS_TO_12
 146             )
 147         })),
 148 
 149     @SuppressWarnings({"unchecked", "rawtypes"})
 150     B_DES(CIPHER_DES, BLOCK_CIPHER, 8, 8, 8, 0, true, false,
 151         (Map.Entry<ReadCipherGenerator,
 152                 ProtocolVersion[]>[])(new Map.Entry[] {
 153             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 154                 new T10BlockReadCipherGenerator(),
 155                 ProtocolVersion.PROTOCOLS_TO_10
 156             ),
 157             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 158                 new T11BlockReadCipherGenerator(),
 159                 ProtocolVersion.PROTOCOLS_OF_11
 160             )
 161         }),
 162         (Map.Entry<WriteCipherGenerator,
 163                 ProtocolVersion[]>[])(new Map.Entry[] {
 164             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 165                 new T10BlockWriteCipherGenerator(),
 166                 ProtocolVersion.PROTOCOLS_TO_10
 167             ),
 168             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 169                 new T11BlockWriteCipherGenerator(),
 170                 ProtocolVersion.PROTOCOLS_OF_11
 171             )
 172         })),
 173 
 174     @SuppressWarnings({"unchecked", "rawtypes"})
 175     B_3DES(CIPHER_3DES, BLOCK_CIPHER, 24, 24, 8, 0, true, false,
 176         (Map.Entry<ReadCipherGenerator,
 177                 ProtocolVersion[]>[])(new Map.Entry[] {
 178             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 179                 new T10BlockReadCipherGenerator(),
 180                 ProtocolVersion.PROTOCOLS_TO_10
 181             ),
 182             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 183                 new T11BlockReadCipherGenerator(),
 184                 ProtocolVersion.PROTOCOLS_11_12
 185             )
 186         }),
 187         (Map.Entry<WriteCipherGenerator,
 188                 ProtocolVersion[]>[])(new Map.Entry[] {
 189             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 190                 new T10BlockWriteCipherGenerator(),
 191                 ProtocolVersion.PROTOCOLS_TO_10
 192             ),
 193             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 194                 new T11BlockWriteCipherGenerator(),
 195                 ProtocolVersion.PROTOCOLS_11_12
 196             )
 197         })),
 198 
 199     @SuppressWarnings({"unchecked", "rawtypes"})
 200     B_IDEA("IDEA", BLOCK_CIPHER, 16, 16, 8, 0, false, false,
 201         (Map.Entry<ReadCipherGenerator,
 202                 ProtocolVersion[]>[])(new Map.Entry[] {
 203             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 204                 null,
 205                 ProtocolVersion.PROTOCOLS_TO_12
 206             )
 207         }),
 208         (Map.Entry<WriteCipherGenerator,
 209                 ProtocolVersion[]>[])(new Map.Entry[] {
 210             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 211                 null,
 212                 ProtocolVersion.PROTOCOLS_TO_12
 213             )
 214         })),
 215 
 216     @SuppressWarnings({"unchecked", "rawtypes"})
 217     B_AES_128(CIPHER_AES, BLOCK_CIPHER, 16, 16, 16, 0, true, false,
 218         (Map.Entry<ReadCipherGenerator,
 219                 ProtocolVersion[]>[])(new Map.Entry[] {
 220             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 221                 new T10BlockReadCipherGenerator(),
 222                 ProtocolVersion.PROTOCOLS_TO_10
 223             ),
 224             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 225                 new T11BlockReadCipherGenerator(),
 226                 ProtocolVersion.PROTOCOLS_11_12
 227             )
 228         }),
 229         (Map.Entry<WriteCipherGenerator,
 230                 ProtocolVersion[]>[])(new Map.Entry[] {
 231             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 232                 new T10BlockWriteCipherGenerator(),
 233                 ProtocolVersion.PROTOCOLS_TO_10
 234             ),
 235             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 236                 new T11BlockWriteCipherGenerator(),
 237                 ProtocolVersion.PROTOCOLS_11_12
 238             )
 239         })),
 240 
 241     @SuppressWarnings({"unchecked", "rawtypes"})
 242     B_AES_256(CIPHER_AES, BLOCK_CIPHER, 32, 32, 16, 0, true, false,
 243         (Map.Entry<ReadCipherGenerator,
 244                 ProtocolVersion[]>[])(new Map.Entry[] {
 245             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 246                 new T10BlockReadCipherGenerator(),
 247                 ProtocolVersion.PROTOCOLS_TO_10
 248             ),
 249             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 250                 new T11BlockReadCipherGenerator(),
 251                 ProtocolVersion.PROTOCOLS_11_12
 252             )
 253         }),
 254         (Map.Entry<WriteCipherGenerator,
 255                 ProtocolVersion[]>[])(new Map.Entry[] {
 256             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 257                 new T10BlockWriteCipherGenerator(),
 258                 ProtocolVersion.PROTOCOLS_TO_10
 259             ),
 260             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 261                 new T11BlockWriteCipherGenerator(),
 262                 ProtocolVersion.PROTOCOLS_11_12
 263             )
 264         })),
 265 
 266     @SuppressWarnings({"unchecked", "rawtypes"})
 267     B_AES_128_GCM(CIPHER_AES_GCM, AEAD_CIPHER, 16, 16, 12, 4, true, false,
 268         (Map.Entry<ReadCipherGenerator,
 269                 ProtocolVersion[]>[])(new Map.Entry[] {
 270             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 271                 new T12GcmReadCipherGenerator(),
 272                 ProtocolVersion.PROTOCOLS_OF_12
 273             )
 274         }),
 275         (Map.Entry<WriteCipherGenerator,
 276                 ProtocolVersion[]>[])(new Map.Entry[] {
 277             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 278                 new T12GcmWriteCipherGenerator(),
 279                 ProtocolVersion.PROTOCOLS_OF_12
 280             )
 281         })),
 282 
 283     @SuppressWarnings({"unchecked", "rawtypes"})
 284     B_AES_256_GCM(CIPHER_AES_GCM, AEAD_CIPHER, 32, 32, 12, 4, true, false,
 285         (Map.Entry<ReadCipherGenerator,
 286                 ProtocolVersion[]>[])(new Map.Entry[] {
 287             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 288                 new T12GcmReadCipherGenerator(),
 289                 ProtocolVersion.PROTOCOLS_OF_12
 290             )
 291         }),
 292         (Map.Entry<WriteCipherGenerator,
 293                 ProtocolVersion[]>[])(new Map.Entry[] {
 294             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 295                 new T12GcmWriteCipherGenerator(),
 296                 ProtocolVersion.PROTOCOLS_OF_12
 297             )
 298         })),
 299 
 300     @SuppressWarnings({"unchecked", "rawtypes"})
 301     B_AES_128_GCM_IV(CIPHER_AES_GCM, AEAD_CIPHER, 16, 16, 12, 0, true, false,
 302         (Map.Entry<ReadCipherGenerator,
 303                 ProtocolVersion[]>[])(new Map.Entry[] {
 304             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 305                 new T13GcmReadCipherGenerator(),
 306                 ProtocolVersion.PROTOCOLS_OF_13
 307             )
 308         }),
 309         (Map.Entry<WriteCipherGenerator,
 310                 ProtocolVersion[]>[])(new Map.Entry[] {
 311             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 312                 new T13GcmWriteCipherGenerator(),
 313                 ProtocolVersion.PROTOCOLS_OF_13
 314             )
 315         })),
 316 
 317     @SuppressWarnings({"unchecked", "rawtypes"})
 318     B_AES_256_GCM_IV(CIPHER_AES_GCM, AEAD_CIPHER, 32, 32, 12, 0, true, false,
 319         (Map.Entry<ReadCipherGenerator,
 320                 ProtocolVersion[]>[])(new Map.Entry[] {
 321             new SimpleImmutableEntry<ReadCipherGenerator, ProtocolVersion[]>(
 322                 new T13GcmReadCipherGenerator(),
 323                 ProtocolVersion.PROTOCOLS_OF_13
 324             )
 325         }),
 326         (Map.Entry<WriteCipherGenerator,
 327                 ProtocolVersion[]>[])(new Map.Entry[] {
 328             new SimpleImmutableEntry<WriteCipherGenerator, ProtocolVersion[]>(
 329                 new T13GcmWriteCipherGenerator(),
 330                 ProtocolVersion.PROTOCOLS_OF_13
 331             )
 332         }));
 333 
 334     // descriptive name including key size, e.g. AES/128
 335     final String description;
 336 
 337     // JCE cipher transformation string, e.g. AES/CBC/NoPadding
 338     final String transformation;
 339 
 340     // algorithm name, e.g. AES
 341     final String algorithm;
 342 
 343     // supported and compile time enabled. Also see isAvailable()
 344     final boolean allowed;
 345 
 346     // number of bytes of entropy in the key
 347     final int keySize;
 348 
 349     // length of the actual cipher key in bytes.
 350     // for non-exportable ciphers, this is the same as keySize
 351     final int expandedKeySize;
 352 
 353     // size of the IV
 354     final int ivSize;






























































 355 
 356     // size of fixed IV
 357     //
 358     // record_iv_length = ivSize - fixedIvSize
 359     final int fixedIvSize;
 360 
 361     // exportable under 512/40 bit rules
 362     final boolean exportable;


 363 
 364     // Is the cipher algorithm of Cipher Block Chaining (CBC) mode?
 365     final CipherType cipherType;



 366 
 367     // size of the authentication tag, only applicable to cipher suites in
 368     // Galois Counter Mode (GCM)
 369     //
 370     // As far as we know, all supported GCM cipher suites use 128-bits
 371     // authentication tags.
 372     final int tagSize = 16;
 373 
 374     // runtime availability
 375     private final boolean isAvailable;
 376 
 377     private final Map.Entry<ReadCipherGenerator,
 378             ProtocolVersion[]>[] readCipherGenerators;
 379     private final Map.Entry<WriteCipherGenerator,
 380             ProtocolVersion[]>[] writeCipherGenerators;
 381 
 382     // Map of Ciphers listed in jdk.tls.KeyLimit
 383     private static final HashMap<String, Long> cipherLimits = new HashMap<>();
 384 
 385     // Keywords found on the jdk.tls.KeyLimit security property.
 386     final static String tag[] = {"KEYUPDATE"};
 387 
 388     static  {
 389         final long max = 4611686018427387904L; // 2^62
 390         String prop = AccessController.doPrivileged(
 391                 new PrivilegedAction<String>() {
 392             @Override
 393             public String run() {
 394                 return Security.getProperty("jdk.tls.keyLimits");
 395             }
 396         });
 397 
 398         if (prop != null) {
 399             String propvalue[] = prop.split(",");
 400 
 401             for (String entry : propvalue) {
 402                 int index;
 403                 // If this is not a UsageLimit, goto to next entry.
 404                 String values[] = entry.trim().toUpperCase().split(" ");
 405 
 406                 if (values[1].contains(tag[0])) {
 407                     index = 0;
 408                 } else {
 409                     if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 410                         SSLLogger.fine("jdk.net.keyLimits:  Unknown action:  " +
 411                                 entry);
 412                     }
 413                     continue;
 414                 }
 415 
 416                 long size;
 417                 int i = values[2].indexOf("^");
 418                 try {
 419                     if (i >= 0) {
 420                         size = (long) Math.pow(2,
 421                                 Integer.parseInt(values[2].substring(i + 1)));
 422                     } else {
 423                         size = Long.parseLong(values[2]);
 424                     }
 425                     if (size < 1 || size > max) {
 426                         throw new NumberFormatException("Length exceeded limits");
 427                     }
 428                 } catch (NumberFormatException e) {
 429                     if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 430                         SSLLogger.fine("jdk.net.keyLimits:  " + e.getMessage() +
 431                                 ":  " +  entry);
 432                     }
 433                     continue;
 434                 }
 435                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
 436                     SSLLogger.fine("jdk.net.keyLimits:  entry = " + entry +
 437                             ". " + values[0] + ":" + tag[index] + " = " + size);
 438                 }
 439                 cipherLimits.put(values[0] + ":" + tag[index], size);
 440             }
 441         }
 442     }
 443 
 444     private SSLCipher(String transformation,
 445             CipherType cipherType, int keySize,
 446             int expandedKeySize, int ivSize,
 447             int fixedIvSize, boolean allowed, boolean exportable,
 448             Map.Entry<ReadCipherGenerator,
 449                     ProtocolVersion[]>[] readCipherGenerators,
 450             Map.Entry<WriteCipherGenerator,
 451                     ProtocolVersion[]>[] writeCipherGenerators) {
 452         this.transformation = transformation;
 453         String[] splits = transformation.split("/");
 454         this.algorithm = splits[0];
 455         this.cipherType = cipherType;
 456         this.description = this.algorithm + "/" + (keySize << 3);
 457         this.keySize = keySize;
 458         this.ivSize = ivSize;
 459         this.fixedIvSize = fixedIvSize;
 460         this.allowed = allowed;
 461 
 462         this.expandedKeySize = expandedKeySize;
 463         this.exportable = exportable;


 464 
 465         // availability of this bulk cipher
 466         //
 467         // We assume all supported ciphers are always available since they are
 468         // shipped with the SunJCE  provider.  However, AES/256 is unavailable
 469         // when the default JCE policy jurisdiction files are installed because
 470         // of key length restrictions.
 471         this.isAvailable =
 472                 allowed ? isUnlimited(keySize, transformation) : false;

 473 
 474         this.readCipherGenerators = readCipherGenerators;
 475         this.writeCipherGenerators = writeCipherGenerators;











 476     }
 477 
 478     SSLReadCipher createReadCipher(Authenticator authenticator,
 479             ProtocolVersion protocolVersion,
 480             SecretKey key, IvParameterSpec iv,
 481             SecureRandom random) throws GeneralSecurityException {
 482         if (readCipherGenerators.length == 0) {
 483             return null;










 484         }


 485 
 486         ReadCipherGenerator rcg = null;
 487         for (Map.Entry<ReadCipherGenerator,
 488                 ProtocolVersion[]> me : readCipherGenerators) {
 489             for (ProtocolVersion pv : me.getValue()) {
 490                 if (protocolVersion == pv) {
 491                     rcg = me.getKey();
 492                 }







 493             }
















 494         }
 495 
 496         if (rcg != null) {
 497             return rcg.createCipher(this, authenticator,
 498                     protocolVersion, transformation, key, iv, random);
 499         }
 500         return null;
 501     }
 502 
 503     SSLWriteCipher createWriteCipher(Authenticator authenticator,
 504             ProtocolVersion protocolVersion,
 505             SecretKey key, IvParameterSpec iv,
 506             SecureRandom random) throws GeneralSecurityException {
 507         if (readCipherGenerators.length == 0) {
 508             return null;
 509         }




 510 
 511         WriteCipherGenerator rcg = null;
 512         for (Map.Entry<WriteCipherGenerator,
 513                 ProtocolVersion[]> me : writeCipherGenerators) {
 514             for (ProtocolVersion pv : me.getValue()) {
 515                 if (protocolVersion == pv) {
 516                     rcg = me.getKey();
 517                 }








 518             }
 519         }
 520 
 521         if (rcg != null) {
 522             return rcg.createCipher(this, authenticator,
 523                     protocolVersion, transformation, key, iv, random);
 524         }
 525         return null;



 526     }
 527 
 528     public static final String getDefaultType() {
 529         String prop = AccessController.doPrivileged(
 530                 new PrivilegedAction<String>() {
 531             @Override
 532             public String run() {
 533                 return Security.getProperty("jdk.tls.KeyLimits");
 534             }
 535         });
 536         return prop;
 537     }
 538 
 539     /**
 540      * Test if this bulk cipher is available. For use by CipherSuite.
 541      */
 542     boolean isAvailable() {
 543         return this.isAvailable;

 544     }
 545 
 546     private static boolean isUnlimited(int keySize, String transformation) {
 547         int keySizeInBits = keySize * 8;
 548         if (keySizeInBits > 128) {    // need the JCE unlimited
 549                                       // strength jurisdiction policy
 550             try {
 551                 if (Cipher.getMaxAllowedKeyLength(
 552                         transformation) < keySizeInBits) {
 553                     return false;
 554                 }
 555             } catch (Exception e) {
 556                 return false;
 557             }
 558         }
 559 
 560         return true;
 561     }
 562 
 563     @Override
 564     public String toString() {
 565         return description;




 566     }
 567 
 568     interface ReadCipherGenerator {
 569         SSLReadCipher createCipher(SSLCipher sslCipher,
 570                 Authenticator authenticator,
 571                 ProtocolVersion protocolVersion, String algorithm,
 572                 Key key, AlgorithmParameterSpec params,
 573                 SecureRandom random) throws GeneralSecurityException;
 574     }
 575 
 576     abstract static class SSLReadCipher {
 577         final Authenticator authenticator;
 578         final ProtocolVersion protocolVersion;
 579         SecretKey baseSecret;
 580 
 581         SSLReadCipher(Authenticator authenticator,
 582                 ProtocolVersion protocolVersion) {
 583             this.authenticator = authenticator;
 584             this.protocolVersion = protocolVersion;



 585         }
 586 
 587         static final SSLReadCipher nullTlsReadCipher() {

 588             try {
 589                 return B_NULL.createReadCipher(
 590                         Authenticator.nullTlsMac(),
 591                         ProtocolVersion.NONE, null, null, null);
 592             } catch (GeneralSecurityException gse) {
 593                 // unlikely
 594                 throw new RuntimeException("Cannot create NULL SSLCipher", gse);
 595             }






 596         }
 597 
 598         static final SSLReadCipher nullDTlsReadCipher() {
 599             try {
 600                 return B_NULL.createReadCipher(
 601                         Authenticator.nullDtlsMac(),
 602                         ProtocolVersion.NONE, null, null, null);
 603             } catch (GeneralSecurityException gse) {
 604                 // unlikely
 605                 throw new RuntimeException("Cannot create NULL SSLCipher", gse);
 606             }



 607         }
 608 
 609         abstract Plaintext decrypt(byte contentType, ByteBuffer bb,
 610                     byte[] sequence) throws GeneralSecurityException;
 611 
 612         void dispose() {
 613             // blank
 614         }
 615 
 616         abstract int estimateFragmentSize(int packetSize, int headerSize);









 617 
 618         boolean isNullCipher() {
 619             return false;
 620         }
 621     }
 622 
 623     interface WriteCipherGenerator {
 624         SSLWriteCipher createCipher(SSLCipher sslCipher,
 625                 Authenticator authenticator,
 626                 ProtocolVersion protocolVersion, String algorithm,
 627                 Key key, AlgorithmParameterSpec params,
 628                 SecureRandom random) throws GeneralSecurityException;
 629     }
 630 
 631     abstract static class SSLWriteCipher {
 632         final Authenticator authenticator;
 633         final ProtocolVersion protocolVersion;
 634         boolean keyLimitEnabled = false;
 635         long keyLimitCountdown = 0;
 636         SecretKey baseSecret;
 637 
 638         SSLWriteCipher(Authenticator authenticator,
 639                 ProtocolVersion protocolVersion) {
 640             this.authenticator = authenticator;
 641             this.protocolVersion = protocolVersion;
 642         }
 643 
 644         abstract int encrypt(byte contentType, ByteBuffer bb);
 645 
 646         static final SSLWriteCipher nullTlsWriteCipher() {
 647             try {
 648                 return B_NULL.createWriteCipher(
 649                         Authenticator.nullTlsMac(),
 650                         ProtocolVersion.NONE, null, null, null);
 651             } catch (GeneralSecurityException gse) {
 652                 // unlikely
 653                 throw new RuntimeException(
 654                         "Cannot create NULL SSL write Cipher", gse);
 655             }
 656         }
 657 
 658         static final SSLWriteCipher nullDTlsWriteCipher() {
 659             try {
 660                 return B_NULL.createWriteCipher(
 661                         Authenticator.nullDtlsMac(),
 662                         ProtocolVersion.NONE, null, null, null);
 663             } catch (GeneralSecurityException gse) {
 664                 // unlikely
 665                 throw new RuntimeException(
 666                         "Cannot create NULL SSL write Cipher", gse);
 667             }
 668         }
 669 
 670         void dispose() {
 671             // blank
 672         }
 673 
 674         abstract int getExplicitNonceSize();
 675         abstract int calculateFragmentSize(int packetLimit, int headerSize);
 676         abstract int calculatePacketSize(int fragmentSize, int headerSize);

 677 
 678         boolean isCBCMode() {
 679             return false;
 680         }
 681 
 682         boolean isNullCipher() {
 683             return false;















 684         }
 685 
 686         /**
 687          * Check if processed bytes have reached the key usage limit.
 688          * If key usage limit is not be monitored, return false.
 689          */
 690         public boolean atKeyLimit() {
 691             if (keyLimitCountdown >= 0) {
 692                 return false;
 693             }
 694 
 695             // Turn off limit checking as KeyUpdate will be occurring
 696             keyLimitEnabled = false;
 697             return true;

 698         }







 699     }
 700 
 701     private static final
 702             class NullReadCipherGenerator implements ReadCipherGenerator {
 703         @Override
 704         public SSLReadCipher createCipher(SSLCipher sslCipher,
 705                 Authenticator authenticator,
 706                 ProtocolVersion protocolVersion, String algorithm,
 707                 Key key, AlgorithmParameterSpec params,
 708                 SecureRandom random) throws GeneralSecurityException {
 709             return new NullReadCipher(authenticator, protocolVersion);
 710         }
 711 
 712         static final class NullReadCipher extends SSLReadCipher {
 713             NullReadCipher(Authenticator authenticator,
 714                     ProtocolVersion protocolVersion) {
 715                 super(authenticator, protocolVersion);
 716             }
 717 
 718             @Override
 719             public Plaintext decrypt(byte contentType, ByteBuffer bb,
 720                     byte[] sequence) throws GeneralSecurityException {
 721                 MAC signer = (MAC)authenticator;
 722                 if (signer.macAlg().size != 0) {
 723                     checkStreamMac(signer, bb, contentType, sequence);
 724                 } else {
 725                     authenticator.increaseSequenceNumber();






 726                 }
 727 
 728                 return new Plaintext(contentType,
 729                         ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
 730                         -1, -1L, bb.slice());
 731             }
 732 
 733             @Override
 734             int estimateFragmentSize(int packetSize, int headerSize) {
 735                 int macLen = ((MAC)authenticator).macAlg().size;
 736                 return packetSize - headerSize - macLen;
 737             }
 738 
 739             @Override
 740             boolean isNullCipher() {
 741                 return true;
 742             }

 743         }
 744     }
 745 
 746     private static final
 747             class NullWriteCipherGenerator implements WriteCipherGenerator {
 748         @Override
 749         public SSLWriteCipher createCipher(SSLCipher sslCipher,
 750                 Authenticator authenticator,
 751                 ProtocolVersion protocolVersion, String algorithm,
 752                 Key key, AlgorithmParameterSpec params,
 753                 SecureRandom random) throws GeneralSecurityException {
 754             return new NullWriteCipher(authenticator, protocolVersion);













 755         }
 756 
 757         static final class NullWriteCipher extends SSLWriteCipher {
 758             NullWriteCipher(Authenticator authenticator,
 759                     ProtocolVersion protocolVersion) {
 760                 super(authenticator, protocolVersion);






 761             }
 762 
 763             @Override
 764             public int encrypt(byte contentType, ByteBuffer bb) {
 765                 // add message authentication code
 766                 MAC signer = (MAC)authenticator;
 767                 if (signer.macAlg().size != 0) {
 768                     addMac(signer, bb, contentType);
 769                 } else {
 770                     authenticator.increaseSequenceNumber();





 771                 }



 772 
 773                 int len = bb.remaining();
 774                 bb.position(bb.limit());
 775                 return len;




 776             }
 777 




 778 
 779             @Override
 780             int getExplicitNonceSize() {
 781                 return 0;
 782             }
 783 
 784             @Override
 785             int calculateFragmentSize(int packetLimit, int headerSize) {
 786                 int macLen = ((MAC)authenticator).macAlg().size;
 787                 return packetLimit - headerSize - macLen;
 788             }
 789 
 790             @Override
 791             int calculatePacketSize(int fragmentSize, int headerSize) {
 792                 int macLen = ((MAC)authenticator).macAlg().size;
 793                 return fragmentSize + headerSize + macLen;
 794             }
 795 
 796             @Override
 797             boolean isNullCipher() {
 798                 return true;
 799             }




 800         }
 801     }
 802 
 803     private static final
 804             class StreamReadCipherGenerator implements ReadCipherGenerator {
 805         @Override
 806         public SSLReadCipher createCipher(SSLCipher sslCipher,
 807                 Authenticator authenticator,
 808                 ProtocolVersion protocolVersion, String algorithm,
 809                 Key key, AlgorithmParameterSpec params,
 810                 SecureRandom random) throws GeneralSecurityException {
 811             return new StreamReadCipher(authenticator, protocolVersion,
 812                     algorithm, key, params, random);
 813         }
 814 
 815         static final class StreamReadCipher extends SSLReadCipher {
 816             private final Cipher cipher;
 817 
 818             StreamReadCipher(Authenticator authenticator,
 819                     ProtocolVersion protocolVersion, String algorithm,
 820                     Key key, AlgorithmParameterSpec params,
 821                     SecureRandom random) throws GeneralSecurityException {
 822                 super(authenticator, protocolVersion);
 823                 this.cipher = JsseJce.getCipher(algorithm);
 824                 cipher.init(Cipher.DECRYPT_MODE, key, params, random);
 825             }
 826 
 827             @Override
 828             public Plaintext decrypt(byte contentType, ByteBuffer bb,
 829                     byte[] sequence) throws GeneralSecurityException {
 830                 int len = bb.remaining();
 831                 int pos = bb.position();
 832                 ByteBuffer dup = bb.duplicate();


 833                 try {
 834                     if (len != cipher.update(dup, bb)) {
 835                         // catch BouncyCastle buffering error

 836                         throw new RuntimeException(
 837                                 "Unexpected number of plaintext bytes");

 838                     }
 839                     if (bb.position() != dup.position()) {
 840                         throw new RuntimeException(
 841                                 "Unexpected Bytebuffer position");
 842                     }
 843                 } catch (ShortBufferException sbe) {
 844                     // catch BouncyCastle buffering error
 845                     throw new RuntimeException("Cipher buffering error in " +
 846                         "JCE provider " + cipher.getProvider().getName(), sbe);
 847                 }
 848                 bb.position(pos);
 849                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
 850                     SSLLogger.fine(
 851                             "Plaintext after DECRYPTION", bb.duplicate());
 852                 }
 853 
 854                 MAC signer = (MAC)authenticator;
 855                 if (signer.macAlg().size != 0) {
 856                     checkStreamMac(signer, bb, contentType, sequence);
 857                 } else {
 858                     authenticator.increaseSequenceNumber();









 859                 }
 860 
 861                 return new Plaintext(contentType,
 862                         ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
 863                         -1, -1L, bb.slice());
 864             }



 865 
 866             @Override
 867             void dispose() {
 868                 if (cipher != null) {
 869                     try {
 870                         cipher.doFinal();
 871                     } catch (Exception e) {
 872                         // swallow all types of exceptions.
 873                     }
 874                 }
 875             }
 876 
 877             @Override
 878             int estimateFragmentSize(int packetSize, int headerSize) {
 879                 int macLen = ((MAC)authenticator).macAlg().size;
 880                 return packetSize - headerSize - macLen;
 881             }
 882         }




 883     }
 884 
 885     private static final
 886             class StreamWriteCipherGenerator implements WriteCipherGenerator {
 887         @Override
 888         public SSLWriteCipher createCipher(SSLCipher sslCipher,
 889                 Authenticator authenticator,
 890                 ProtocolVersion protocolVersion, String algorithm,
 891                 Key key, AlgorithmParameterSpec params,
 892                 SecureRandom random) throws GeneralSecurityException {
 893             return new StreamWriteCipher(authenticator,
 894                     protocolVersion, algorithm, key, params, random);
 895         }
 896 
 897         static final class StreamWriteCipher extends SSLWriteCipher {
 898             private final Cipher cipher;



 899 
 900             StreamWriteCipher(Authenticator authenticator,
 901                     ProtocolVersion protocolVersion, String algorithm,
 902                     Key key, AlgorithmParameterSpec params,
 903                     SecureRandom random) throws GeneralSecurityException {
 904                 super(authenticator, protocolVersion);
 905                 this.cipher = JsseJce.getCipher(algorithm);
 906                 cipher.init(Cipher.ENCRYPT_MODE, key, params, random);
 907             }

 908 
 909             @Override
 910             public int encrypt(byte contentType, ByteBuffer bb) {
 911                 // add message authentication code
 912                 MAC signer = (MAC)authenticator;
 913                 if (signer.macAlg().size != 0) {
 914                     addMac(signer, bb, contentType);
 915                 } else {
 916                     authenticator.increaseSequenceNumber();
 917                 }
 918 
 919                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
 920                     SSLLogger.finest(
 921                         "Padded plaintext before ENCRYPTION", bb.duplicate());


 922                 }
 923 
 924                 int len = bb.remaining();
 925                 ByteBuffer dup = bb.duplicate();
 926                 try {
 927                     if (len != cipher.update(dup, bb)) {
 928                         // catch BouncyCastle buffering error
 929                         throw new RuntimeException(
 930                                 "Unexpected number of plaintext bytes");
 931                     }
 932                     if (bb.position() != dup.position()) {
 933                         throw new RuntimeException(
 934                                 "Unexpected Bytebuffer position");
 935                     }
 936                 } catch (ShortBufferException sbe) {
 937                     // catch BouncyCastle buffering error
 938                     throw new RuntimeException("Cipher buffering error in " +
 939                         "JCE provider " + cipher.getProvider().getName(), sbe);
 940                 }
 941 
 942                 return len;
 943             }





 944 
 945             @Override
 946             void dispose() {
 947                 if (cipher != null) {
 948                     try {
 949                         cipher.doFinal();
 950                     } catch (Exception e) {
 951                         // swallow all types of exceptions.
 952                     }
 953                 }
 954             }
 955 
 956             @Override
 957             int getExplicitNonceSize() {
 958                 return 0;
 959             }
 960 
 961             @Override
 962             int calculateFragmentSize(int packetLimit, int headerSize) {
 963                 int macLen = ((MAC)authenticator).macAlg().size;
 964                 return packetLimit - headerSize - macLen;
 965             }

 966 
 967             @Override
 968             int calculatePacketSize(int fragmentSize, int headerSize) {
 969                 int macLen = ((MAC)authenticator).macAlg().size;
 970                 return fragmentSize + headerSize + macLen;
 971             }
 972         }
 973     }
 974 
 975     private static final
 976             class T10BlockReadCipherGenerator implements ReadCipherGenerator {
 977         @Override
 978         public SSLReadCipher createCipher(SSLCipher sslCipher,
 979                 Authenticator authenticator,
 980                 ProtocolVersion protocolVersion, String algorithm,
 981                 Key key, AlgorithmParameterSpec params,
 982                 SecureRandom random) throws GeneralSecurityException {
 983             return new BlockReadCipher(authenticator,
 984                     protocolVersion, algorithm, key, params, random);
 985         }
 986 
 987         static final class BlockReadCipher extends SSLReadCipher {
 988             private final Cipher cipher;
 989 
 990             BlockReadCipher(Authenticator authenticator,
 991                     ProtocolVersion protocolVersion, String algorithm,
 992                     Key key, AlgorithmParameterSpec params,
 993                     SecureRandom random) throws GeneralSecurityException {
 994                 super(authenticator, protocolVersion);
 995                 this.cipher = JsseJce.getCipher(algorithm);
 996                 cipher.init(Cipher.DECRYPT_MODE, key, params, random);
 997             }
 998 
 999             @Override
1000             public Plaintext decrypt(byte contentType, ByteBuffer bb,
1001                     byte[] sequence) throws GeneralSecurityException {
1002                 BadPaddingException reservedBPE = null;
1003 
1004                 // sanity check length of the ciphertext
1005                 MAC signer = (MAC)authenticator;
1006                 int cipheredLength = bb.remaining();
1007                 int tagLen = signer.macAlg().size;
1008                 if (tagLen != 0) {
1009                     if (!sanityCheck(tagLen, bb.remaining())) {
1010                         reservedBPE = new BadPaddingException(
1011                                 "ciphertext sanity check failed");
1012                     }
1013                 }
1014                 // decryption
1015                 int len = bb.remaining();
1016                 int pos = bb.position();
1017                 ByteBuffer dup = bb.duplicate();
1018                 try {
1019                     if (len != cipher.update(dup, bb)) {
1020                         // catch BouncyCastle buffering error
1021                         throw new RuntimeException(
1022                                 "Unexpected number of plaintext bytes");
1023                     }
1024 
1025                     if (bb.position() != dup.position()) {
1026                         throw new RuntimeException(
1027                                 "Unexpected Bytebuffer position");
1028                     }
1029                 } catch (ShortBufferException sbe) {
1030                     // catch BouncyCastle buffering error
1031                     throw new RuntimeException("Cipher buffering error in " +
1032                         "JCE provider " + cipher.getProvider().getName(), sbe);
1033                 }
1034 
1035                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
1036                     SSLLogger.fine(
1037                             "Padded plaintext after DECRYPTION",
1038                             bb.duplicate().position(pos));
1039                 }
1040 
1041                 // remove the block padding
1042                 int blockSize = cipher.getBlockSize();
1043                 bb.position(pos);
1044                 try {
1045                     removePadding(bb, tagLen, blockSize, protocolVersion);
1046                 } catch (BadPaddingException bpe) {
1047                     if (reservedBPE == null) {
1048                         reservedBPE = bpe;
1049                     }
1050                 }
1051 
1052                 // Requires message authentication code for null, stream and
1053                 // block cipher suites.
1054                 try {
1055                     if (tagLen != 0) {
1056                         checkCBCMac(signer, bb,
1057                                 contentType, cipheredLength, sequence);
1058                     } else {
1059                         authenticator.increaseSequenceNumber();
1060                     }
1061                 } catch (BadPaddingException bpe) {
1062                     if (reservedBPE == null) {
1063                         reservedBPE = bpe;
1064                     }
1065                 }
1066 
1067                 // Is it a failover?
1068                 if (reservedBPE != null) {
1069                     throw reservedBPE;
1070                 }
1071 
1072                 return new Plaintext(contentType,
1073                         ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
1074                         -1, -1L, bb.slice());
1075             }
1076 
1077             @Override
1078             void dispose() {
1079                 if (cipher != null) {
1080                     try {
1081                         cipher.doFinal();
1082                     } catch (Exception e) {
1083                         // swallow all types of exceptions.
1084                     }
1085                 }
1086             }
1087 
1088             @Override
1089             int estimateFragmentSize(int packetSize, int headerSize) {
1090                 int macLen = ((MAC)authenticator).macAlg().size;
1091 
1092                 // No padding for a maximum fragment.
1093                 //
1094                 // 1 byte padding length field: 0x00
1095                 return packetSize - headerSize - macLen - 1;
1096             }
1097 
1098             /**
1099              * Sanity check the length of a fragment before decryption.
1100              *
1101              * In CBC mode, check that the fragment length is one or multiple
1102              * times of the block size of the cipher suite, and is at least
1103              * one (one is the smallest size of padding in CBC mode) bigger
1104              * than the tag size of the MAC algorithm except the explicit IV
1105              * size for TLS 1.1 or later.
1106              *
1107              * In non-CBC mode, check that the fragment length is not less than
1108              * the tag size of the MAC algorithm.
1109              *
1110              * @return true if the length of a fragment matches above
1111              *         requirements
1112              */
1113             private boolean sanityCheck(int tagLen, int fragmentLen) {
1114                 int blockSize = cipher.getBlockSize();
1115                 if ((fragmentLen % blockSize) == 0) {
1116                     int minimal = tagLen + 1;
1117                     minimal = (minimal >= blockSize) ? minimal : blockSize;
1118 
1119                     return (fragmentLen >= minimal);

1120                 }
1121 
1122                 return false;









1123             }
1124         }
1125     }
1126 
1127     private static final
1128             class T10BlockWriteCipherGenerator implements WriteCipherGenerator {
1129         @Override
1130         public SSLWriteCipher createCipher(SSLCipher sslCipher,
1131                 Authenticator authenticator,
1132                 ProtocolVersion protocolVersion, String algorithm,
1133                 Key key, AlgorithmParameterSpec params,
1134                 SecureRandom random) throws GeneralSecurityException {
1135             return new BlockWriteCipher(authenticator,
1136                     protocolVersion, algorithm, key, params, random);
1137         }
1138 
1139         static final class BlockWriteCipher extends SSLWriteCipher {
1140             private final Cipher cipher;











1141 
1142             BlockWriteCipher(Authenticator authenticator,
1143                     ProtocolVersion protocolVersion, String algorithm,
1144                     Key key, AlgorithmParameterSpec params,
1145                     SecureRandom random) throws GeneralSecurityException {
1146                 super(authenticator, protocolVersion);
1147                 this.cipher = JsseJce.getCipher(algorithm);
1148                 cipher.init(Cipher.ENCRYPT_MODE, key, params, random);
1149             }
1150 
1151             @Override
1152             public int encrypt(byte contentType, ByteBuffer bb) {
1153                 int pos = bb.position();





1154 
1155                 // add message authentication code
1156                 MAC signer = (MAC)authenticator;
1157                 if (signer.macAlg().size != 0) {
1158                     addMac(signer, bb, contentType);
1159                 } else {
1160                     authenticator.increaseSequenceNumber();
1161                 }
1162 
1163                 int blockSize = cipher.getBlockSize();
1164                 int len = addPadding(bb, blockSize);
1165                 bb.position(pos);
1166 
1167                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
1168                     SSLLogger.fine(
1169                             "Padded plaintext before ENCRYPTION",
1170                             bb.duplicate());
1171                 }
1172 
1173                 ByteBuffer dup = bb.duplicate();
1174                 try {
1175                     if (len != cipher.update(dup, bb)) {
1176                         // catch BouncyCastle buffering error
1177                         throw new RuntimeException(
1178                                 "Unexpected number of plaintext bytes");


1179                     }
1180 
1181                     if (bb.position() != dup.position()) {
1182                         throw new RuntimeException(
1183                                 "Unexpected Bytebuffer position");
1184                     }
1185                 } catch (ShortBufferException sbe) {
1186                     // catch BouncyCastle buffering error
1187                     throw new RuntimeException("Cipher buffering error in " +
1188                         "JCE provider " + cipher.getProvider().getName(), sbe);
1189                 }
1190 
1191                 return len;
1192             }




1193 
1194             @Override
1195             void dispose() {
1196                 if (cipher != null) {
1197                     try {
1198                         cipher.doFinal();
1199                     } catch (Exception e) {
1200                         // swallow all types of exceptions.
1201                     }
1202                 }
1203             }
1204 
1205             @Override
1206             int getExplicitNonceSize() {
1207                 return 0;
1208             }
1209 
1210             @Override
1211             int calculateFragmentSize(int packetLimit, int headerSize) {
1212                 int macLen = ((MAC)authenticator).macAlg().size;
1213                 int blockSize = cipher.getBlockSize();
1214                 int fragLen = packetLimit - headerSize;
1215                 fragLen -= (fragLen % blockSize);   // cannot hold a block
1216                 // No padding for a maximum fragment.
1217                 fragLen -= 1;       // 1 byte padding length field: 0x00
1218                 fragLen -= macLen;
1219                 return fragLen;
1220             }
1221 
1222             @Override
1223             int calculatePacketSize(int fragmentSize, int headerSize) {
1224                 int macLen = ((MAC)authenticator).macAlg().size;
1225                 int blockSize = cipher.getBlockSize();
1226                 int paddedLen = fragmentSize + macLen + 1;
1227                 if ((paddedLen % blockSize)  != 0) {
1228                     paddedLen += blockSize - 1;
1229                     paddedLen -= paddedLen % blockSize;
1230                 }
1231 
1232                 return headerSize + paddedLen;






1233             }
1234 
1235             @Override
1236             boolean isCBCMode() {
1237                 return true;
1238             }
1239         }
1240     }
1241 
1242     // For TLS 1.1 and 1.2
1243     private static final
1244             class T11BlockReadCipherGenerator implements ReadCipherGenerator {
1245         @Override
1246         public SSLReadCipher createCipher(SSLCipher sslCipher,
1247                 Authenticator authenticator, ProtocolVersion protocolVersion,
1248                 String algorithm, Key key, AlgorithmParameterSpec params,
1249                 SecureRandom random) throws GeneralSecurityException {
1250             return new BlockReadCipher(authenticator, protocolVersion,
1251                     sslCipher, algorithm, key, params, random);
1252         }
1253 
1254         static final class BlockReadCipher extends SSLReadCipher {
1255             private final Cipher cipher;
1256 
1257             BlockReadCipher(Authenticator authenticator,
1258                     ProtocolVersion protocolVersion,
1259                     SSLCipher sslCipher, String algorithm,
1260                     Key key, AlgorithmParameterSpec params,
1261                     SecureRandom random) throws GeneralSecurityException {
1262                 super(authenticator, protocolVersion);
1263                 this.cipher = JsseJce.getCipher(algorithm);
1264                 if (params == null) {
1265                     params = new IvParameterSpec(new byte[sslCipher.ivSize]);
1266                 }
1267                 cipher.init(Cipher.DECRYPT_MODE, key, params, random);
1268             }
1269 
1270             @Override
1271             public Plaintext decrypt(byte contentType, ByteBuffer bb,
1272                     byte[] sequence) throws GeneralSecurityException {
1273                 BadPaddingException reservedBPE = null;
1274 
1275                 // sanity check length of the ciphertext
1276                 MAC signer = (MAC)authenticator;
1277                 int cipheredLength = bb.remaining();
1278                 int tagLen = signer.macAlg().size;
1279                 if (tagLen != 0) {
1280                     if (!sanityCheck(tagLen, bb.remaining())) {
1281                         reservedBPE = new BadPaddingException(
1282                                 "ciphertext sanity check failed");
1283                     }
1284                 }
1285 
1286                 // decryption
1287                 int len = bb.remaining();
1288                 int pos = bb.position();
1289                 ByteBuffer dup = bb.duplicate();
1290                 try {
1291                     if (len != cipher.update(dup, bb)) {
1292                         // catch BouncyCastle buffering error
1293                         throw new RuntimeException(
1294                                 "Unexpected number of plaintext bytes");
1295                     }
1296 
1297                     if (bb.position() != dup.position()) {
1298                         throw new RuntimeException(
1299                                 "Unexpected Bytebuffer position");
1300                     }
1301                 } catch (ShortBufferException sbe) {
1302                     // catch BouncyCastle buffering error
1303                     throw new RuntimeException("Cipher buffering error in " +
1304                         "JCE provider " + cipher.getProvider().getName(), sbe);
1305                 }
1306 
1307                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
1308                     SSLLogger.fine(
1309                             "Padded plaintext after DECRYPTION",
1310                             bb.duplicate().position(pos));
1311                 }
1312 
1313                 // Ignore the explicit nonce.
1314                 bb.position(pos + cipher.getBlockSize());
1315                 pos = bb.position();
1316 
1317                 // remove the block padding
1318                 int blockSize = cipher.getBlockSize();
1319                 bb.position(pos);
1320                 try {
1321                     removePadding(bb, tagLen, blockSize, protocolVersion);
1322                 } catch (BadPaddingException bpe) {
1323                     if (reservedBPE == null) {
1324                         reservedBPE = bpe;
1325                     }
1326                 }
1327 
1328                 // Requires message authentication code for null, stream and
1329                 // block cipher suites.
1330                 try {
1331                     if (tagLen != 0) {
1332                         checkCBCMac(signer, bb,
1333                                 contentType, cipheredLength, sequence);
1334                     } else {
1335                         authenticator.increaseSequenceNumber();
1336                     }
1337                 } catch (BadPaddingException bpe) {
1338                     if (reservedBPE == null) {
1339                         reservedBPE = bpe;
1340                     }
1341                 }
1342 
1343                 // Is it a failover?
1344                 if (reservedBPE != null) {
1345                     throw reservedBPE;
1346                 }
1347 
1348                 return new Plaintext(contentType,
1349                         ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
1350                         -1, -1L, bb.slice());
1351             }
1352 
1353             @Override
1354             void dispose() {
1355                 if (cipher != null) {
1356                     try {
1357                         cipher.doFinal();
1358                     } catch (Exception e) {
1359                         // swallow all types of exceptions.
1360                     }
1361                 }
1362             }
1363 
1364             @Override
1365             int estimateFragmentSize(int packetSize, int headerSize) {
1366                 int macLen = ((MAC)authenticator).macAlg().size;
1367 
1368                 // No padding for a maximum fragment.
1369                 //
1370                 // 1 byte padding length field: 0x00
1371                 int nonceSize = cipher.getBlockSize();
1372                 return packetSize - headerSize - nonceSize - macLen - 1;
1373             }
1374 
1375             /**
1376              * Sanity check the length of a fragment before decryption.
1377              *
1378              * In CBC mode, check that the fragment length is one or multiple
1379              * times of the block size of the cipher suite, and is at least
1380              * one (one is the smallest size of padding in CBC mode) bigger
1381              * than the tag size of the MAC algorithm except the explicit IV
1382              * size for TLS 1.1 or later.
1383              *
1384              * In non-CBC mode, check that the fragment length is not less than
1385              * the tag size of the MAC algorithm.
1386              *
1387              * @return true if the length of a fragment matches above
1388              *         requirements
1389              */
1390             private boolean sanityCheck(int tagLen, int fragmentLen) {
1391                 int blockSize = cipher.getBlockSize();
1392                 if ((fragmentLen % blockSize) == 0) {
1393                     int minimal = tagLen + 1;
1394                     minimal = (minimal >= blockSize) ? minimal : blockSize;
1395                     minimal += blockSize;
1396 
1397                     return (fragmentLen >= minimal);
1398                 }
1399 
1400                 return false;
1401             }
1402         }
1403     }
1404 
1405     // For TLS 1.1 and 1.2
1406     private static final
1407             class T11BlockWriteCipherGenerator implements WriteCipherGenerator {
1408         @Override
1409         public SSLWriteCipher createCipher(SSLCipher sslCipher,
1410                 Authenticator authenticator, ProtocolVersion protocolVersion,
1411                 String algorithm, Key key, AlgorithmParameterSpec params,
1412                 SecureRandom random) throws GeneralSecurityException {
1413             return new BlockWriteCipher(authenticator, protocolVersion,
1414                     sslCipher, algorithm, key, params, random);
1415         }
1416 
1417         static final class BlockWriteCipher extends SSLWriteCipher {
1418             private final Cipher cipher;
1419             private final SecureRandom random;
1420 
1421             BlockWriteCipher(Authenticator authenticator,
1422                     ProtocolVersion protocolVersion,
1423                     SSLCipher sslCipher, String algorithm,
1424                     Key key, AlgorithmParameterSpec params,
1425                     SecureRandom random) throws GeneralSecurityException {
1426                 super(authenticator, protocolVersion);
1427                 this.cipher = JsseJce.getCipher(algorithm);
1428                 this.random = random;
1429                 if (params == null) {
1430                     params = new IvParameterSpec(new byte[sslCipher.ivSize]);
1431                 }
1432                 cipher.init(Cipher.ENCRYPT_MODE, key, params, random);
1433             }
1434 
1435             @Override
1436             public int encrypt(byte contentType, ByteBuffer bb) {
1437                 // To be unique and aware of overflow-wrap, sequence number
1438                 // is used as the nonce_explicit of block cipher suites.
1439                 int pos = bb.position();
1440 
1441                 // add message authentication code
1442                 MAC signer = (MAC)authenticator;
1443                 if (signer.macAlg().size != 0) {
1444                     addMac(signer, bb, contentType);
1445                 } else {
1446                     authenticator.increaseSequenceNumber();
1447                 }
1448 
1449                 // DON'T WORRY, the nonce spaces are considered already.
1450                 byte[] nonce = new byte[cipher.getBlockSize()];
1451                 random.nextBytes(nonce);
1452                 pos = pos - nonce.length;
1453                 bb.position(pos);
1454                 bb.put(nonce);
1455                 bb.position(pos);
1456 
1457                 int blockSize = cipher.getBlockSize();
1458                 int len = addPadding(bb, blockSize);
1459                 bb.position(pos);
1460 
1461                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
1462                     SSLLogger.fine(
1463                             "Padded plaintext before ENCRYPTION",
1464                             bb.duplicate());
1465                 }
1466 
1467                 ByteBuffer dup = bb.duplicate();
1468                 try {
1469                     if (len != cipher.update(dup, bb)) {
1470                         // catch BouncyCastle buffering error
1471                         throw new RuntimeException(
1472                                 "Unexpected number of plaintext bytes");
1473                     }
1474 
1475                     if (bb.position() != dup.position()) {
1476                         throw new RuntimeException(
1477                                 "Unexpected Bytebuffer position");
1478                     }
1479                 } catch (ShortBufferException sbe) {
1480                     // catch BouncyCastle buffering error
1481                     throw new RuntimeException("Cipher buffering error in " +
1482                         "JCE provider " + cipher.getProvider().getName(), sbe);
1483                 }
1484 
1485                 return len;
1486             }
1487 
1488             @Override
1489             void dispose() {
1490                 if (cipher != null) {
1491                     try {
1492                         cipher.doFinal();
1493                     } catch (Exception e) {
1494                         // swallow all types of exceptions.
1495                     }
1496                 }
1497             }
1498 
1499             @Override
1500             int getExplicitNonceSize() {
1501                 return cipher.getBlockSize();
1502             }
1503 
1504             @Override
1505             int calculateFragmentSize(int packetLimit, int headerSize) {
1506                 int macLen = ((MAC)authenticator).macAlg().size;
1507                 int blockSize = cipher.getBlockSize();
1508                 int fragLen = packetLimit - headerSize - blockSize;
1509                 fragLen -= (fragLen % blockSize);   // cannot hold a block
1510                 // No padding for a maximum fragment.
1511                 fragLen -= 1;       // 1 byte padding length field: 0x00
1512                 fragLen -= macLen;
1513                 return fragLen;
1514             }
1515 
1516             @Override
1517             int calculatePacketSize(int fragmentSize, int headerSize) {
1518                 int macLen = ((MAC)authenticator).macAlg().size;
1519                 int blockSize = cipher.getBlockSize();
1520                 int paddedLen = fragmentSize + macLen + 1;
1521                 if ((paddedLen % blockSize)  != 0) {
1522                     paddedLen += blockSize - 1;
1523                     paddedLen -= paddedLen % blockSize;
1524                 }
1525 
1526                 return headerSize + blockSize + paddedLen;
1527             }
1528 
1529             @Override
1530             boolean isCBCMode() {
1531                 return true;
1532             }
1533         }
1534     }
1535 
1536     private static final
1537             class T12GcmReadCipherGenerator implements ReadCipherGenerator {
1538         @Override
1539         public SSLReadCipher createCipher(SSLCipher sslCipher,
1540                 Authenticator authenticator,
1541                 ProtocolVersion protocolVersion, String algorithm,
1542                 Key key, AlgorithmParameterSpec params,
1543                 SecureRandom random) throws GeneralSecurityException {
1544             return new GcmReadCipher(authenticator, protocolVersion, sslCipher,
1545                     algorithm, key, params, random);
1546         }
1547 
1548         static final class GcmReadCipher extends SSLReadCipher {
1549             private final Cipher cipher;
1550             private final int tagSize;
1551             private final Key key;
1552             private final byte[] fixedIv;
1553             private final int recordIvSize;
1554             private final SecureRandom random;
1555 
1556             GcmReadCipher(Authenticator authenticator,
1557                     ProtocolVersion protocolVersion,
1558                     SSLCipher sslCipher, String algorithm,
1559                     Key key, AlgorithmParameterSpec params,
1560                     SecureRandom random) throws GeneralSecurityException {
1561                 super(authenticator, protocolVersion);
1562                 this.cipher = JsseJce.getCipher(algorithm);
1563                 this.tagSize = sslCipher.tagSize;
1564                 this.key = key;
1565                 this.fixedIv = ((IvParameterSpec)params).getIV();
1566                 this.recordIvSize = sslCipher.ivSize - sslCipher.fixedIvSize;
1567                 this.random = random;
1568 
1569                 // DON'T initialize the cipher for AEAD!
1570             }
1571 
1572             @Override
1573             public Plaintext decrypt(byte contentType, ByteBuffer bb,
1574                     byte[] sequence) throws GeneralSecurityException {
1575                 if (bb.remaining() < (recordIvSize + tagSize)) {
1576                     throw new BadPaddingException(
1577                         "Insufficient buffer remaining for AEAD cipher " +
1578                         "fragment (" + bb.remaining() + "). Needs to be " +
1579                         "more than or equal to IV size (" + recordIvSize +
1580                          ") + tag size (" + tagSize + ")");
1581                 }
1582 
1583                 // initialize the AEAD cipher for the unique IV
1584                 byte[] iv = Arrays.copyOf(fixedIv,
1585                                     fixedIv.length + recordIvSize);
1586                 bb.get(iv, fixedIv.length, recordIvSize);
1587                 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
1588                 try {
1589                     cipher.init(Cipher.DECRYPT_MODE, key, spec, random);
1590                 } catch (InvalidKeyException |
1591                             InvalidAlgorithmParameterException ikae) {
1592                     // unlikely to happen
1593                     throw new RuntimeException(
1594                                 "invalid key or spec in GCM mode", ikae);
1595                 }
1596 
1597                 // update the additional authentication data
1598                 byte[] aad = authenticator.acquireAuthenticationBytes(
1599                         contentType, bb.remaining() - tagSize,
1600                         sequence);
1601                 cipher.updateAAD(aad);
1602 
1603                 // DON'T decrypt the nonce_explicit for AEAD mode. The buffer
1604                 // position has moved out of the nonce_explicit range.
1605                 int len = bb.remaining();
1606                 int pos = bb.position();
1607                 ByteBuffer dup = bb.duplicate();
1608                 try {
1609                     len = cipher.doFinal(dup, bb);
1610                 } catch (IllegalBlockSizeException ibse) {
1611                     // unlikely to happen
1612                     throw new RuntimeException(
1613                         "Cipher error in AEAD mode \"" + ibse.getMessage() +
1614                         " \"in JCE provider " + cipher.getProvider().getName());
1615                 } catch (ShortBufferException sbe) {
1616                     // catch BouncyCastle buffering error
1617                     throw new RuntimeException("Cipher buffering error in " +
1618                         "JCE provider " + cipher.getProvider().getName(), sbe);
1619                 }
1620                 // reset the limit to the end of the decryted data
1621                 bb.position(pos);
1622                 bb.limit(pos + len);
1623 
1624                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
1625                     SSLLogger.fine(
1626                             "Plaintext after DECRYPTION", bb.duplicate());
1627                 }
1628 
1629                 return new Plaintext(contentType,
1630                         ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
1631                         -1, -1L, bb.slice());
1632             }
1633 
1634             @Override
1635             void dispose() {
1636                 if (cipher != null) {
1637                     try {
1638                         cipher.doFinal();
1639                     } catch (Exception e) {
1640                         // swallow all types of exceptions.
1641                     }
1642                 }
1643             }
1644 
1645             @Override
1646             int estimateFragmentSize(int packetSize, int headerSize) {
1647                 return packetSize - headerSize - recordIvSize - tagSize;
1648             }
1649         }
1650     }
1651 
1652     private static final
1653             class T12GcmWriteCipherGenerator implements WriteCipherGenerator {
1654         @Override
1655         public SSLWriteCipher createCipher(SSLCipher sslCipher,
1656                 Authenticator authenticator,
1657                 ProtocolVersion protocolVersion, String algorithm,
1658                 Key key, AlgorithmParameterSpec params,
1659                 SecureRandom random) throws GeneralSecurityException {
1660             return new GcmWriteCipher(authenticator, protocolVersion, sslCipher,
1661                     algorithm, key, params, random);
1662         }
1663 
1664         private static final class GcmWriteCipher extends SSLWriteCipher {
1665             private final Cipher cipher;
1666             private final int tagSize;
1667             private final Key key;
1668             private final byte[] fixedIv;
1669             private final int recordIvSize;
1670             private final SecureRandom random;
1671 
1672             GcmWriteCipher(Authenticator authenticator,
1673                     ProtocolVersion protocolVersion,
1674                     SSLCipher sslCipher, String algorithm,
1675                     Key key, AlgorithmParameterSpec params,
1676                     SecureRandom random) throws GeneralSecurityException {
1677                 super(authenticator, protocolVersion);
1678                 this.cipher = JsseJce.getCipher(algorithm);
1679                 this.tagSize = sslCipher.tagSize;
1680                 this.key = key;
1681                 this.fixedIv = ((IvParameterSpec)params).getIV();
1682                 this.recordIvSize = sslCipher.ivSize - sslCipher.fixedIvSize;
1683                 this.random = random;
1684 
1685                 // DON'T initialize the cipher for AEAD!
1686             }
1687 
1688             @Override
1689             public int encrypt(byte contentType,
1690                     ByteBuffer bb) {
1691                 // To be unique and aware of overflow-wrap, sequence number
1692                 // is used as the nonce_explicit of AEAD cipher suites.
1693                 byte[] nonce = authenticator.sequenceNumber();
1694 
1695                 // initialize the AEAD cipher for the unique IV
1696                 byte[] iv = Arrays.copyOf(fixedIv,
1697                                             fixedIv.length + nonce.length);
1698                 System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
1699 
1700                 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
1701                 try {
1702                     cipher.init(Cipher.ENCRYPT_MODE, key, spec, random);
1703                 } catch (InvalidKeyException |
1704                             InvalidAlgorithmParameterException ikae) {
1705                     // unlikely to happen
1706                     throw new RuntimeException(
1707                                 "invalid key or spec in GCM mode", ikae);
1708                 }
1709 
1710                 // Update the additional authentication data, using the
1711                 // implicit sequence number of the authenticator.
1712                 byte[] aad = authenticator.acquireAuthenticationBytes(
1713                                         contentType, bb.remaining(), null);
1714                 cipher.updateAAD(aad);
1715 
1716                 // DON'T WORRY, the nonce spaces are considered already.
1717                 bb.position(bb.position() - nonce.length);
1718                 bb.put(nonce);
1719 
1720                 // DON'T encrypt the nonce for AEAD mode.
1721                 int len = bb.remaining();
1722                 int pos = bb.position();
1723                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
1724                     SSLLogger.fine(
1725                             "Plaintext before ENCRYPTION",
1726                             bb.duplicate());
1727                 }
1728 
1729                 ByteBuffer dup = bb.duplicate();
1730                 int outputSize = cipher.getOutputSize(dup.remaining());
1731                 if (outputSize > bb.remaining()) {
1732                     // Need to expand the limit of the output buffer for
1733                     // the authentication tag.
1734                     //
1735                     // DON'T worry about the buffer's capacity, we have
1736                     // reserved space for the authentication tag.
1737                     bb.limit(pos + outputSize);
1738                 }
1739 
1740                 try {
1741                     len = cipher.doFinal(dup, bb);
1742                 } catch (IllegalBlockSizeException |
1743                             BadPaddingException | ShortBufferException ibse) {
1744                     // unlikely to happen
1745                     throw new RuntimeException(
1746                             "Cipher error in AEAD mode in JCE provider " +
1747                             cipher.getProvider().getName(), ibse);
1748                 }
1749 
1750                 if (len != outputSize) {
1751                     throw new RuntimeException(
1752                             "Cipher buffering error in JCE provider " +
1753                             cipher.getProvider().getName());
1754                 }
1755 
1756                 return len + nonce.length;
1757             }
1758 
1759             @Override
1760             void dispose() {
1761                 if (cipher != null) {
1762                     try {
1763                         cipher.doFinal();
1764                     } catch (Exception e) {
1765                         // swallow all types of exceptions.
1766                     }
1767                 }
1768             }
1769 
1770             @Override
1771             int getExplicitNonceSize() {
1772                 return recordIvSize;
1773             }
1774 
1775             @Override
1776             int calculateFragmentSize(int packetLimit, int headerSize) {
1777                 return packetLimit - headerSize - recordIvSize - tagSize;
1778             }
1779 
1780             @Override
1781             int calculatePacketSize(int fragmentSize, int headerSize) {
1782                 return fragmentSize + headerSize + recordIvSize + tagSize;
1783             }
1784         }
1785     }
1786 
1787     private static final
1788             class T13GcmReadCipherGenerator implements ReadCipherGenerator {
1789 
1790         @Override
1791         public SSLReadCipher createCipher(SSLCipher sslCipher,
1792                 Authenticator authenticator, ProtocolVersion protocolVersion,
1793                 String algorithm, Key key, AlgorithmParameterSpec params,
1794                 SecureRandom random) throws GeneralSecurityException {
1795             return new GcmReadCipher(authenticator, protocolVersion, sslCipher,
1796                     algorithm, key, params, random);
1797         }
1798 
1799         static final class GcmReadCipher extends SSLReadCipher {
1800             private final Cipher cipher;
1801             private final int tagSize;
1802             private final Key key;
1803             private final byte[] iv;
1804             private final SecureRandom random;
1805 
1806             GcmReadCipher(Authenticator authenticator,
1807                     ProtocolVersion protocolVersion,
1808                     SSLCipher sslCipher, String algorithm,
1809                     Key key, AlgorithmParameterSpec params,
1810                     SecureRandom random) throws GeneralSecurityException {
1811                 super(authenticator, protocolVersion);
1812                 this.cipher = JsseJce.getCipher(algorithm);
1813                 this.tagSize = sslCipher.tagSize;
1814                 this.key = key;
1815                 this.iv = ((IvParameterSpec)params).getIV();
1816                 this.random = random;
1817 
1818                 // DON'T initialize the cipher for AEAD!
1819             }
1820 
1821             @Override
1822             public Plaintext decrypt(byte contentType, ByteBuffer bb,
1823                     byte[] sequence) throws GeneralSecurityException {
1824                 // An implementation may receive an unencrypted record of type
1825                 // change_cipher_spec consisting of the single byte value 0x01
1826                 // at any time after the first ClientHello message has been
1827                 // sent or received and before the peer's Finished message has
1828                 // been received and MUST simply drop it without further
1829                 // processing.
1830                 if (contentType == ContentType.CHANGE_CIPHER_SPEC.id) {
1831                     return new Plaintext(contentType,
1832                         ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
1833                         -1, -1L, bb.slice());
1834                 }
1835 
1836                 if (bb.remaining() <= tagSize) {
1837                     throw new BadPaddingException(
1838                         "Insufficient buffer remaining for AEAD cipher " +
1839                         "fragment (" + bb.remaining() + "). Needs to be " +
1840                         "more than tag size (" + tagSize + ")");
1841                 }
1842 
1843                 byte[] sn = sequence;
1844                 if (sn == null) {
1845                     sn = authenticator.sequenceNumber();
1846                 }
1847                 byte[] nonce = iv.clone();
1848                 int offset = nonce.length - sn.length;
1849                 for (int i = 0; i < sn.length; i++) {
1850                     nonce[offset + i] ^= sn[i];
1851                 }
1852 
1853                 // initialize the AEAD cipher for the unique IV
1854                 GCMParameterSpec spec =
1855                         new GCMParameterSpec(tagSize * 8, nonce);
1856                 try {
1857                     cipher.init(Cipher.DECRYPT_MODE, key, spec, random);
1858                 } catch (InvalidKeyException |
1859                             InvalidAlgorithmParameterException ikae) {
1860                     // unlikely to happen
1861                     throw new RuntimeException(
1862                                 "invalid key or spec in GCM mode", ikae);
1863                 }
1864 
1865                 // Update the additional authentication data, using the
1866                 // implicit sequence number of the authenticator.
1867                 byte[] aad = authenticator.acquireAuthenticationBytes(
1868                                         contentType, bb.remaining(), sn);
1869                 cipher.updateAAD(aad);
1870 
1871                 int len = bb.remaining();
1872                 int pos = bb.position();
1873                 ByteBuffer dup = bb.duplicate();
1874                 try {
1875                     len = cipher.doFinal(dup, bb);
1876                 } catch (IllegalBlockSizeException ibse) {
1877                     // unlikely to happen
1878                     throw new RuntimeException(
1879                         "Cipher error in AEAD mode \"" + ibse.getMessage() +
1880                         " \"in JCE provider " + cipher.getProvider().getName());
1881                 } catch (ShortBufferException sbe) {
1882                     // catch BouncyCastle buffering error
1883                     throw new RuntimeException("Cipher buffering error in " +
1884                         "JCE provider " + cipher.getProvider().getName(), sbe);
1885                 }
1886                 // reset the limit to the end of the decryted data
1887                 bb.position(pos);
1888                 bb.limit(pos + len);
1889 
1890                 // remove inner plaintext padding
1891                 int i = bb.limit() - 1;
1892                 for (; i > 0 && bb.get(i) == 0; i--) {
1893                     // blank
1894                 }
1895                 if (i < (pos + 1)) {
1896                     throw new BadPaddingException(
1897                             "Incorrect inner plaintext: no content type");
1898                 }
1899                 contentType = bb.get(i);
1900                 bb.limit(i);
1901 
1902                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
1903                     SSLLogger.fine(
1904                             "Plaintext after DECRYPTION", bb.duplicate());
1905                 }
1906 
1907                 return new Plaintext(contentType,
1908                         ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor,
1909                         -1, -1L, bb.slice());
1910             }
1911 
1912             @Override
1913             void dispose() {
1914                 if (cipher != null) {
1915                     try {
1916                         cipher.doFinal();
1917                     } catch (Exception e) {
1918                         // swallow all types of exceptions.
1919                     }
1920                 }
1921             }
1922 
1923             @Override
1924             int estimateFragmentSize(int packetSize, int headerSize) {
1925                 return packetSize - headerSize - tagSize;
1926             }
1927         }
1928     }
1929 
1930     private static final
1931             class T13GcmWriteCipherGenerator implements WriteCipherGenerator {
1932         @Override
1933         public SSLWriteCipher createCipher(SSLCipher sslCipher,
1934                 Authenticator authenticator, ProtocolVersion protocolVersion,
1935                 String algorithm, Key key, AlgorithmParameterSpec params,
1936                 SecureRandom random) throws GeneralSecurityException {
1937             return new GcmWriteCipher(authenticator, protocolVersion, sslCipher,
1938                     algorithm, key, params, random);
1939         }
1940 
1941         private static final class GcmWriteCipher extends SSLWriteCipher {
1942             private final Cipher cipher;
1943             private final int tagSize;
1944             private final Key key;
1945             private final byte[] iv;
1946             private final SecureRandom random;
1947 
1948             GcmWriteCipher(Authenticator authenticator,
1949                     ProtocolVersion protocolVersion,
1950                     SSLCipher sslCipher, String algorithm,
1951                     Key key, AlgorithmParameterSpec params,
1952                     SecureRandom random) throws GeneralSecurityException {
1953                 super(authenticator, protocolVersion);
1954                 this.cipher = JsseJce.getCipher(algorithm);
1955                 this.tagSize = sslCipher.tagSize;
1956                 this.key = key;
1957                 this.iv = ((IvParameterSpec)params).getIV();
1958                 this.random = random;
1959 
1960                 keyLimitCountdown = cipherLimits.getOrDefault(
1961                         algorithm.toUpperCase() + ":" + tag[0], 0L);
1962                 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
1963                     SSLLogger.fine("algorithm = " + algorithm.toUpperCase() +
1964                             ":" + tag[0] + "\ncountdown value = " +
1965                             keyLimitCountdown);
1966                 }
1967                 if (keyLimitCountdown > 0) {
1968                     keyLimitEnabled = true;
1969                 }
1970 
1971                 // DON'T initialize the cipher for AEAD!
1972             }
1973 
1974             @Override
1975             public int encrypt(byte contentType,
1976                     ByteBuffer bb) {
1977                 byte[] sn = authenticator.sequenceNumber();
1978                 byte[] nonce = iv.clone();
1979                 int offset = nonce.length - sn.length;
1980                 for (int i = 0; i < sn.length; i++) {
1981                     nonce[offset + i] ^= sn[i];
1982                 }
1983 
1984                 // initialize the AEAD cipher for the unique IV
1985                 GCMParameterSpec spec =
1986                         new GCMParameterSpec(tagSize * 8, nonce);
1987                 try {
1988                     cipher.init(Cipher.ENCRYPT_MODE, key, spec, random);
1989                 } catch (InvalidKeyException |
1990                             InvalidAlgorithmParameterException ikae) {
1991                     // unlikely to happen
1992                     throw new RuntimeException(
1993                                 "invalid key or spec in GCM mode", ikae);
1994                 }
1995 
1996                 // Update the additional authentication data, using the
1997                 // implicit sequence number of the authenticator.
1998                 int outputSize = cipher.getOutputSize(bb.remaining());
1999                 byte[] aad = authenticator.acquireAuthenticationBytes(
2000                                         contentType, outputSize, sn);
2001                 cipher.updateAAD(aad);
2002 
2003                 int len = bb.remaining();
2004                 int pos = bb.position();
2005                 if (SSLLogger.isOn && SSLLogger.isOn("plaintext")) {
2006                     SSLLogger.fine(
2007                             "Plaintext before ENCRYPTION",
2008                             bb.duplicate());
2009                 }
2010 
2011                 ByteBuffer dup = bb.duplicate();
2012                 if (outputSize > bb.remaining()) {
2013                     // Need to expand the limit of the output buffer for
2014                     // the authentication tag.
2015                     //
2016                     // DON'T worry about the buffer's capacity, we have
2017                     // reserved space for the authentication tag.
2018                     bb.limit(pos + outputSize);
2019                 }
2020 
2021                 try {
2022                     len = cipher.doFinal(dup, bb);
2023                 } catch (IllegalBlockSizeException |
2024                             BadPaddingException | ShortBufferException ibse) {
2025                     // unlikely to happen
2026                     throw new RuntimeException(
2027                             "Cipher error in AEAD mode in JCE provider " +
2028                             cipher.getProvider().getName(), ibse);
2029                 }
2030 
2031                 if (len != outputSize) {
2032                     throw new RuntimeException(
2033                             "Cipher buffering error in JCE provider " +
2034                             cipher.getProvider().getName());
2035                 }
2036 
2037                 if (keyLimitEnabled) {
2038                     keyLimitCountdown -= len;
2039                 }
2040                 return len;
2041             }
2042 
2043             @Override




2044             void dispose() {

2045                 if (cipher != null) {
2046                     try {
2047                         cipher.doFinal();

2048                     } catch (Exception e) {
2049                         // swallow all types of exceptions.
2050                     }
2051                 }
2052             }
2053 
2054             @Override
2055             int getExplicitNonceSize() {
2056                 return 0;




2057             }
2058 
2059             @Override
2060             int calculateFragmentSize(int packetLimit, int headerSize) {
2061                 return packetLimit - headerSize - tagSize;




2062             }
2063 
2064             @Override
2065             int calculatePacketSize(int fragmentSize, int headerSize) {
2066                 return fragmentSize + headerSize + tagSize;
2067             }



2068         }
2069     }
2070 
2071     private static void addMac(MAC signer,
2072             ByteBuffer destination, byte contentType) {
2073         if (signer.macAlg().size != 0) {
2074             int dstContent = destination.position();
2075             byte[] hash = signer.compute(contentType, destination, false);
2076 
2077             /*
2078              * position was advanced to limit in MAC compute above.
2079              *
2080              * Mark next area as writable (above layers should have
2081              * established that we have plenty of room), then write
2082              * out the hash.


2083              */
2084             destination.limit(destination.limit() + hash.length);
2085             destination.put(hash);
2086 
2087             // reset the position and limit
2088             destination.position(dstContent);



2089         }





2090     }
2091 
2092     // for null and stream cipher
2093     private static void checkStreamMac(MAC signer, ByteBuffer bb,
2094             byte contentType,  byte[] sequence) throws BadPaddingException {
2095         int tagLen = signer.macAlg().size;
2096 
2097         // Requires message authentication code for null, stream and
2098         // block cipher suites.




















2099         if (tagLen != 0) {
2100             int contentLen = bb.remaining() - tagLen;
2101             if (contentLen < 0) {
2102                 throw new BadPaddingException("bad record");

2103             }
2104 
2105             // Run MAC computation and comparison on the payload.
2106             //
2107             // MAC data would be stripped off during the check.
2108             if (checkMacTags(contentType, bb, signer, sequence, false)) {
2109                 throw new BadPaddingException("bad record MAC");
2110             }








2111         }














2112     }
2113 
2114     // for CBC cipher
2115     private static void checkCBCMac(MAC signer, ByteBuffer bb,
2116             byte contentType, int cipheredLength,
2117             byte[] sequence) throws BadPaddingException {
2118         BadPaddingException reservedBPE = null;
2119         int tagLen = signer.macAlg().size;
2120         int pos = bb.position();
2121 
2122         if (tagLen != 0) {
2123             int contentLen = bb.remaining() - tagLen;
2124             if (contentLen < 0) {
2125                 reservedBPE = new BadPaddingException("bad record");
2126 
2127                 // set offset of the dummy MAC
2128                 contentLen = cipheredLength - tagLen;
2129                 bb.limit(pos + cipheredLength);
2130             }
2131 
2132             // Run MAC computation and comparison on the payload.
2133             //
2134             // MAC data would be stripped off during the check.
2135             if (checkMacTags(contentType, bb, signer, sequence, false)) {
2136                 if (reservedBPE == null) {
2137                     reservedBPE =
2138                             new BadPaddingException("bad record MAC");
2139                 }
2140             }
2141 
2142             // Run MAC computation and comparison on the remainder.
2143             int remainingLen = calculateRemainingLen(
2144                     signer, cipheredLength, contentLen);















2145 
2146             // NOTE: remainingLen may be bigger (less than 1 block of the
2147             // hash algorithm of the MAC) than the cipheredLength.





2148             //
2149             // Is it possible to use a static buffer, rather than allocate
2150             // it dynamically?
2151             remainingLen += signer.macAlg().size;
2152             ByteBuffer temporary = ByteBuffer.allocate(remainingLen);





2153 
2154             // Won't need to worry about the result on the remainder. And
2155             // then we won't need to worry about what's actual data to
2156             // check MAC tag on.  We start the check from the header of the
2157             // buffer so that we don't need to construct a new byte buffer.
2158             checkMacTags(contentType, temporary, signer, sequence, true);







2159         }
2160 
2161         // Is it a failover?
2162         if (reservedBPE != null) {
2163             throw reservedBPE;



2164         }
2165     }
2166 
2167     /*
2168      * Run MAC computation and comparison
2169      */
2170     private static boolean checkMacTags(byte contentType, ByteBuffer bb,
2171             MAC signer, byte[] sequence, boolean isSimulated) {
2172         int tagLen = signer.macAlg().size;
2173         int position = bb.position();
2174         int lim = bb.limit();
2175         int macOffset = lim - tagLen;
2176 
2177         bb.limit(macOffset);
2178         byte[] hash = signer.compute(contentType, bb, sequence, isSimulated);
2179         if (hash == null || tagLen != hash.length) {
2180             // Something is wrong with MAC implementation.
2181             throw new RuntimeException("Internal MAC error");
2182         }
2183 
2184         bb.position(macOffset);
2185         bb.limit(lim);
2186         try {
2187             int[] results = compareMacTags(bb, hash);
2188             return (results[0] != 0);
2189         } finally {
2190             // reset to the data
2191             bb.position(position);
2192             bb.limit(macOffset);
2193         }



2194     }
2195 
2196     /*
2197      * A constant-time comparison of the MAC tags.
2198      *
2199      * Please DON'T change the content of the ByteBuffer parameter!
2200      */
2201     private static int[] compareMacTags(ByteBuffer bb, byte[] tag) {
2202         // An array of hits is used to prevent Hotspot optimization for
2203         // the purpose of a constant-time check.
2204         int[] results = {0, 0};     // {missed #, matched #}
2205 
2206         // The caller ensures there are enough bytes available in the buffer.
2207         // So we won't need to check the remaining of the buffer.
2208         for (int i = 0; i < tag.length; i++) {
2209             if (bb.get() != tag[i]) {
2210                 results[0]++;       // mismatched bytes
2211             } else {
2212                 results[1]++;       // matched bytes
2213             }
2214         }
2215 
2216         return results;
2217     }
2218 
2219     /*
2220      * Calculate the length of a dummy buffer to run MAC computation
2221      * and comparison on the remainder.
2222      *
2223      * The caller MUST ensure that the fullLen is not less than usedLen.
2224      */
2225     private static int calculateRemainingLen(
2226             MAC signer, int fullLen, int usedLen) {
2227 
2228         int blockLen = signer.macAlg().hashBlockSize;
2229         int minimalPaddingLen = signer.macAlg().minimalPaddingSize;
2230 
2231         // (blockLen - minimalPaddingLen) is the maximum message size of
2232         // the last block of hash function operation. See FIPS 180-4, or
2233         // MD5 specification.
2234         fullLen += 13 - (blockLen - minimalPaddingLen);
2235         usedLen += 13 - (blockLen - minimalPaddingLen);
2236 
2237         // Note: fullLen is always not less than usedLen, and blockLen
2238         // is always bigger than minimalPaddingLen, so we don't worry
2239         // about negative values. 0x01 is added to the result to ensure
2240         // that the return value is positive.  The extra one byte does
2241         // not impact the overall MAC compression function evaluations.
2242         return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) -
2243                 Math.ceil(usedLen/(1.0d * blockLen))) * blockLen;
2244     }




2245 
2246     private static int addPadding(ByteBuffer bb, int blockSize) {



2247 
2248         int     len = bb.remaining();
2249         int     offset = bb.position();
2250 
2251         int     newlen = len + 1;
2252         byte    pad;
2253         int     i;
2254 
2255         if ((newlen % blockSize) != 0) {
2256             newlen += blockSize - 1;
2257             newlen -= newlen % blockSize;
2258         }
2259         pad = (byte) (newlen - len);
2260 
2261         /*
2262          * Update the limit to what will be padded.
2263          */
2264         bb.limit(newlen + offset);
2265 
2266         /*
2267          * TLS version of the padding works for both SSLv3 and TLSv1
2268          */
2269         for (i = 0, offset += len; i < pad; i++) {
2270             bb.put(offset++, (byte) (pad - 1));
2271         }
2272 
2273         bb.position(offset);
2274         bb.limit(offset);
2275 
2276         return newlen;





2277     }



2278 
2279     private static int removePadding(ByteBuffer bb,
2280             int tagLen, int blockSize,
2281             ProtocolVersion protocolVersion) throws BadPaddingException {
2282         int len = bb.remaining();
2283         int offset = bb.position();
2284 
2285         // last byte is length byte (i.e. actual padding length - 1)
2286         int padOffset = offset + len - 1;
2287         int padLen = bb.get(padOffset) & 0xFF;
2288 
2289         int newLen = len - (padLen + 1);
2290         if ((newLen - tagLen) < 0) {
2291             // If the buffer is not long enough to contain the padding plus
2292             // a MAC tag, do a dummy constant-time padding check.
2293             //
2294             // Note that it is a dummy check, so we won't care about what is
2295             // the actual padding data.
2296             checkPadding(bb.duplicate(), (byte)(padLen & 0xFF));
2297 
2298             throw new BadPaddingException("Invalid Padding length: " + padLen);
2299         }
2300 
2301         // The padding data should be filled with the padding length value.
2302         int[] results = checkPadding(
2303                 bb.duplicate().position(offset + newLen),
2304                 (byte)(padLen & 0xFF));
2305         if (protocolVersion.useTLS10PlusSpec()) {
2306             if (results[0] != 0) {          // padding data has invalid bytes
2307                 throw new BadPaddingException("Invalid TLS padding data");
2308             }
2309         } else { // SSLv3
2310             // SSLv3 requires 0 <= length byte < block size
2311             // some implementations do 1 <= length byte <= block size,
2312             // so accept that as well
2313             // v3 does not require any particular value for the other bytes
2314             if (padLen > blockSize) {
2315                 throw new BadPaddingException("Padding length (" +
2316                 padLen + ") of SSLv3 message should not be bigger " +
2317                 "than the block size (" + blockSize + ")");
2318             }
2319         }
2320 
2321         // Reset buffer limit to remove padding.
2322         bb.limit(offset + newLen);
2323 
2324         return newLen;
2325     }
2326 
2327     /*
2328      * A constant-time check of the padding.





2329      *
2330      * NOTE that we are checking both the padding and the padLen bytes here.

2331      *
2332      * The caller MUST ensure that the bb parameter has remaining.
2333      */
2334     private static int[] checkPadding(ByteBuffer bb, byte pad) {
2335         if (!bb.hasRemaining()) {
2336             throw new RuntimeException("hasRemaining() must be positive");
2337         }
2338 
2339         // An array of hits is used to prevent Hotspot optimization for
2340         // the purpose of a constant-time check.
2341         int[] results = {0, 0};    // {missed #, matched #}
2342         bb.mark();
2343         for (int i = 0; i <= 256; bb.reset()) {
2344             for (; bb.hasRemaining() && i <= 256; i++) {
2345                 if (bb.get() != pad) {
2346                     results[0]++;       // mismatched padding data
2347                 } else {
2348                     results[1]++;       // matched padding data
2349                 }


2350             }


2351         }
2352 
2353         return results;
2354     }
2355 }
2356 
< prev index next >