src/java.base/share/classes/sun/security/ssl/SSLCipher.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47216 71c04702a3d5
child 56715 b152d06ed6a9
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
       
     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