jdk/test/com/sun/crypto/provider/Cipher/AEAD/Encrypt.java
changeset 31874 734897b86adf
equal deleted inserted replaced
31873:87b015c2cd36 31874:734897b86adf
       
     1 /*
       
     2  * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 import java.nio.ByteBuffer;
       
    25 import java.security.AlgorithmParameters;
       
    26 import java.security.Provider;
       
    27 import java.security.Security;
       
    28 import java.util.ArrayList;
       
    29 import java.util.Arrays;
       
    30 import java.util.List;
       
    31 import javax.crypto.SecretKey;
       
    32 import javax.crypto.Cipher;
       
    33 import javax.crypto.KeyGenerator;
       
    34 
       
    35 /*
       
    36  * @test
       
    37  * @bug 8048596
       
    38  * @summary AEAD encryption/decryption test
       
    39  */
       
    40 
       
    41 /*
       
    42  * The test does the following:
       
    43  *   - create an input text and additional data
       
    44  *   - generate a secret key
       
    45  *   - instantiate a cipher according to the GCM transformation
       
    46  *   - generate an outputText using a single-part encryption/decryption
       
    47  *     in AEAD mode
       
    48  *   - perform 16 different combinations of multiple-part encryption/decryption
       
    49  *     operation in AEAD mode (in encryption mode new Cipher object is created
       
    50  *     and initialized with the same secret key and parameters)
       
    51  *   - check that all 17 results are equal
       
    52  *
       
    53  * Combinations:
       
    54  *
       
    55  * combination #1
       
    56  *   updateAAD(byte[] src)
       
    57  *   update(byte[], int, int)
       
    58  *   doFinal(byte[], int, int)
       
    59  *
       
    60  * combination #2
       
    61  *   updateAAD(byte[] src)
       
    62  *   update(byte[], int, int)
       
    63  *   doFinal(byte[], int, int, byte[], int)
       
    64  *
       
    65  * combination #3
       
    66  *   updateAAD(byte[] src)
       
    67  *   update(byte[], int, int, byte[], int)
       
    68  *   doFinal(byte[], int, int)
       
    69  *
       
    70  * combination #4
       
    71  *   updateAAD(byte[] src)
       
    72  *   update(byte[], int, int, byte[], int)
       
    73  *   doFinal(byte[], int, int, byte[], int)
       
    74  *
       
    75  * combination #5 - #8 are similar to #1 -#4,
       
    76  * but with updateAAD(byte[] src, int offset, int len)
       
    77  *
       
    78  * combination #9 - #12 are similar to #1 - #4,
       
    79  * but with updateAAD(ByteBuffer src)
       
    80  *
       
    81  * combination #13 - #16 are similar to #9 - #12 but with directly allocated
       
    82  * ByteBuffer and update(ByteBuffer input, ByteBuffer output)
       
    83  *
       
    84  */
       
    85 public class Encrypt {
       
    86 
       
    87     private static final String ALGORITHMS[] = { "AES", "Rijndael" };
       
    88     private static final int KEY_STRENGTHS[] = { 128, 192, 256 };
       
    89     private static final int TEXT_LENGTHS[] = { 0, 256, 1024 };
       
    90     private static final int AAD_LENGTHS[] = { 0, 8, 128, 256, 1024 };
       
    91     private static final int ARRAY_OFFSET = 8;
       
    92 
       
    93     private final String transformation;
       
    94     private final Provider provider;
       
    95     private final SecretKey key;
       
    96     private final int textLength;
       
    97     private final int AADLength;
       
    98 
       
    99     /**
       
   100      * @param provider Security provider
       
   101      * @param algorithm Security algorithm to test
       
   102      * @param mode The mode (GCM is only expected)
       
   103      * @param padding Algorithm padding
       
   104      * @param keyStrength key length
       
   105      * @param textLength Plain text length
       
   106      * @param AADLength Additional data length
       
   107      */
       
   108     public Encrypt(Provider provider, String algorithm, String mode,
       
   109             String padding, int keyStrength, int textLength, int AADLength)
       
   110             throws Exception {
       
   111 
       
   112         // init a secret Key
       
   113         KeyGenerator kg = KeyGenerator.getInstance(algorithm, provider);
       
   114         kg.init(keyStrength);
       
   115         key = kg.generateKey();
       
   116 
       
   117         this.provider = provider;
       
   118         this.transformation = algorithm + "/" + mode + "/" + padding;
       
   119         this.textLength = textLength;
       
   120         this.AADLength = AADLength;
       
   121     }
       
   122 
       
   123     public static void main(String[] args) throws Exception {
       
   124         Provider p = Security.getProvider("SunJCE");
       
   125         for (String alg : ALGORITHMS) {
       
   126             for (int keyStrength : KEY_STRENGTHS) {
       
   127                 if (keyStrength > Cipher.getMaxAllowedKeyLength(alg)) {
       
   128                     // skip this if this key length is larger than what's
       
   129                     // configured in the JCE jurisdiction policy files
       
   130                     continue;
       
   131                 }
       
   132                 for (int textLength : TEXT_LENGTHS) {
       
   133                     for (int AADLength : AAD_LENGTHS) {
       
   134                         Encrypt test = new Encrypt(p, alg,
       
   135                                 "GCM", "NoPadding", keyStrength, textLength,
       
   136                                 AADLength);
       
   137                         Cipher cipher = test.createCipher(Cipher.ENCRYPT_MODE,
       
   138                                 null);
       
   139                         AlgorithmParameters params = cipher.getParameters();
       
   140                         test.doTest(params);
       
   141                         System.out.println("Test " + alg + ":"
       
   142                                 + keyStrength + ":" + textLength + ":"
       
   143                                 + AADLength + " passed");
       
   144                     }
       
   145                 }
       
   146             }
       
   147         }
       
   148     }
       
   149 
       
   150     public void doTest(AlgorithmParameters params) throws Exception {
       
   151         System.out.println("Test transformation = " + transformation
       
   152                 + ", textLength = " + textLength
       
   153                 + ", AADLength = " + AADLength);
       
   154         byte[] input = Helper.generateBytes(textLength);
       
   155         byte[] AAD = Helper.generateBytes(AADLength);
       
   156         byte[] result = execute(Cipher.ENCRYPT_MODE, AAD, input, params);
       
   157         result = execute(Cipher.DECRYPT_MODE, AAD, result, params);
       
   158         if (!Arrays.equals(input, result)) {
       
   159             throw new RuntimeException("Test failed");
       
   160         }
       
   161         System.out.println("Test passed");
       
   162     }
       
   163 
       
   164     /**
       
   165      * Create a Cipher object for the requested encryption/decryption mode.
       
   166      *
       
   167      * @param mode encryption or decryption mode
       
   168      * @return Cipher object initiated to perform requested mode operation
       
   169      */
       
   170     private Cipher createCipher(int mode, AlgorithmParameters params)
       
   171             throws Exception {
       
   172         Cipher ci;
       
   173         if (Cipher.ENCRYPT_MODE == mode) {
       
   174             // create a new Cipher object for encryption
       
   175             ci = Cipher.getInstance(transformation, provider);
       
   176 
       
   177             // initiate it with the saved parameters
       
   178             if (params != null) {
       
   179                 ci.init(Cipher.ENCRYPT_MODE, key, params);
       
   180             } else {
       
   181                 // initiate the cipher without parameters
       
   182                 ci.init(Cipher.ENCRYPT_MODE, key);
       
   183             }
       
   184         } else {
       
   185             // it is expected that parameters already generated
       
   186             // before decryption
       
   187             ci = Cipher.getInstance(transformation, provider);
       
   188             ci.init(Cipher.DECRYPT_MODE, key, params);
       
   189         }
       
   190 
       
   191         return ci;
       
   192     }
       
   193 
       
   194     /**
       
   195      * Test AEAD combinations
       
   196      *
       
   197      * @param mode decryption or encryption
       
   198      * @param AAD additional data for AEAD operations
       
   199      * @param inputText plain text to decrypt/encrypt
       
   200      * @return output text after encrypt/decrypt
       
   201      */
       
   202     public byte[] execute(int mode, byte[] AAD, byte[] inputText,
       
   203             AlgorithmParameters params) throws Exception {
       
   204 
       
   205         Cipher cipher = createCipher(mode, params);
       
   206 
       
   207         // results of each combination will be saved in the outputTexts
       
   208         List<byte[]> outputTexts = new ArrayList<>();
       
   209 
       
   210         // generate a standard outputText using a single-part en/de-cryption
       
   211         cipher.updateAAD(AAD);
       
   212         byte[] output = cipher.doFinal(inputText);
       
   213 
       
   214         // execute multiple-part encryption/decryption combinations
       
   215         combination_1(outputTexts, mode, AAD, inputText, params);
       
   216         combination_2(outputTexts, mode, AAD, inputText, params);
       
   217         combination_3(outputTexts, mode, AAD, inputText, params);
       
   218         combination_4(outputTexts, mode, AAD, inputText, params);
       
   219         combination_5(outputTexts, mode, AAD, inputText, params);
       
   220         combination_6(outputTexts, mode, AAD, inputText, params);
       
   221         combination_7(outputTexts, mode, AAD, inputText, params);
       
   222         combination_8(outputTexts, mode, AAD, inputText, params);
       
   223         combination_9(outputTexts, mode, AAD, inputText, params);
       
   224         combination_10(outputTexts, mode, AAD, inputText, params);
       
   225         combination_11(outputTexts, mode, AAD, inputText, params);
       
   226         combination_12(outputTexts, mode, AAD, inputText, params);
       
   227         combination_13(outputTexts, mode, AAD, inputText, params);
       
   228         combination_14(outputTexts, mode, AAD, inputText, params);
       
   229         combination_15(outputTexts, mode, AAD, inputText, params);
       
   230         combination_16(outputTexts, mode, AAD, inputText, params);
       
   231 
       
   232         for (int k = 0; k < outputTexts.size(); k++) {
       
   233             if (!Arrays.equals(output, outputTexts.get(k))) {
       
   234                 throw new RuntimeException("Combination #" + k + " failed");
       
   235             }
       
   236         }
       
   237         return output;
       
   238     }
       
   239 
       
   240     /*
       
   241      * Execute multiple-part encryption/decryption combination #1:
       
   242      *   updateAAD(byte[] src)
       
   243      *   update(byte[], int, int)
       
   244      *   doFinal(byte[], int, int)
       
   245      */
       
   246     private void combination_1(List<byte[]> results, int mode, byte[] AAD,
       
   247             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   248         Cipher c = createCipher(mode, params);
       
   249         c.updateAAD(AAD);
       
   250         byte[] part11 = c.update(plainText, 0, plainText.length);
       
   251         int part11_length = part11 == null ? 0 : part11.length;
       
   252         byte[] part12 = c.doFinal();
       
   253         byte[] outputText1 = new byte[part11_length + part12.length];
       
   254         if (part11 != null) {
       
   255             System.arraycopy(part11, 0, outputText1, 0, part11_length);
       
   256         }
       
   257         System.arraycopy(part12, 0, outputText1, part11_length, part12.length);
       
   258         results.add(outputText1);
       
   259     }
       
   260 
       
   261     /*
       
   262      * Execute multiple-part encryption/decryption combination #2:
       
   263      *   updateAAD(byte[] src)
       
   264      *   update(byte[], int, int)
       
   265      *   doFinal(byte[], int, int, byte[], int)
       
   266      */
       
   267     private void combination_2(List<byte[]> results, int mode, byte[] AAD,
       
   268             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   269         Cipher c = createCipher(mode, params);
       
   270         c.updateAAD(AAD);
       
   271         int t = 0;
       
   272         int offset = 0;
       
   273         if (plainText.length > ARRAY_OFFSET) {
       
   274             t = plainText.length - ARRAY_OFFSET;
       
   275             offset = ARRAY_OFFSET;
       
   276         }
       
   277         byte[] part21 = c.update(plainText, 0, t);
       
   278         byte[] part22 = new byte[c.getOutputSize(plainText.length)];
       
   279         int len2 = c.doFinal(plainText, t, offset, part22, 0);
       
   280         int part21Length = part21 != null ? part21.length : 0;
       
   281         byte[] outputText2 = new byte[part21Length + len2];
       
   282         if (part21 != null) {
       
   283             System.arraycopy(part21, 0, outputText2, 0, part21Length);
       
   284         }
       
   285         System.arraycopy(part22, 0, outputText2, part21Length, len2);
       
   286         results.add(outputText2);
       
   287     }
       
   288 
       
   289     /*
       
   290      * Execute multiple-part encryption/decryption combination #3
       
   291      *   updateAAD(byte[] src)
       
   292      *   update(byte[], int, int, byte[], int)
       
   293      *   doFinal(byte[], int, int)
       
   294      */
       
   295     private void combination_3(List<byte[]> results, int mode, byte[] AAD,
       
   296             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   297         Cipher ci = createCipher(mode, params);
       
   298         ci.updateAAD(AAD);
       
   299         byte[] part31 = new byte[ci.getOutputSize(plainText.length)];
       
   300         int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
       
   301         int len = ci.update(plainText, 0, plainText.length - offset, part31, 0);
       
   302         byte[] part32 = ci.doFinal(plainText, plainText.length - offset,
       
   303                 offset);
       
   304         byte[] outputText3 = new byte[len + part32.length];
       
   305         System.arraycopy(part31, 0, outputText3, 0, len);
       
   306         System.arraycopy(part32, 0, outputText3, len, part32.length);
       
   307         results.add(outputText3);
       
   308     }
       
   309 
       
   310     /*
       
   311      * Execute multiple-part encryption/decryption combination #4:
       
   312      *   updateAAD(byte[] src)
       
   313      *   update(byte[], int, int, byte[], int)
       
   314      *   doFinal(byte[], int, int, byte[], int)
       
   315      */
       
   316     private void combination_4(List<byte[]> results, int mode, byte[] AAD,
       
   317             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   318         Cipher ci = createCipher(mode, params);
       
   319         ci.updateAAD(AAD);
       
   320         byte[] part41 = new byte[ci.getOutputSize(plainText.length)];
       
   321         int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
       
   322         int len = ci.update(plainText, 0, plainText.length - offset, part41, 0);
       
   323         int rest4 = ci.doFinal(plainText, plainText.length - offset, offset,
       
   324                 part41, len);
       
   325         byte[] outputText4 = new byte[len + rest4];
       
   326         System.arraycopy(part41, 0, outputText4, 0, outputText4.length);
       
   327         results.add(outputText4);
       
   328     }
       
   329 
       
   330     /*
       
   331      * Execute multiple-part encryption/decryption combination #5:
       
   332      *   updateAAD(byte[] src, int offset, int len)
       
   333      *   update(byte[], int, int)
       
   334      *   doFinal(byte[], int, int)
       
   335      */
       
   336     private void combination_5(List<byte[]> results, int mode, byte[] AAD,
       
   337             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   338         Cipher c = createCipher(mode, params);
       
   339         c.updateAAD(AAD, 0, AAD.length);
       
   340         byte[] part51 = c.update(plainText, 0, plainText.length);
       
   341         byte[] part52 = c.doFinal();
       
   342         int part51Length = part51 != null ? part51.length : 0;
       
   343         byte[] outputText5 = new byte[part51Length + part52.length];
       
   344         if (part51 != null) {
       
   345             System.arraycopy(part51, 0, outputText5, 0, part51Length);
       
   346         }
       
   347         System.arraycopy(part52, 0, outputText5, part51Length, part52.length);
       
   348         results.add(outputText5);
       
   349     }
       
   350 
       
   351     /*
       
   352      * Execute multiple-part encryption/decryption combination #6:
       
   353      *   updateAAD(byte[] src, int offset, int len)
       
   354      *   updateAAD(byte[] src, int offset, int len)
       
   355      *   update(byte[], int, int) doFinal(byte[], int, int, byte[], int)
       
   356      */
       
   357     private void combination_6(List<byte[]> results, int mode, byte[] AAD,
       
   358             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   359         Cipher c = createCipher(mode, params);
       
   360         c.updateAAD(AAD, 0, AAD.length / 2);
       
   361         c.updateAAD(AAD, AAD.length / 2, AAD.length - AAD.length / 2);
       
   362         int t = 0;
       
   363         int offset = 0;
       
   364         if (plainText.length > ARRAY_OFFSET) {
       
   365             t = plainText.length - ARRAY_OFFSET;
       
   366             offset = ARRAY_OFFSET;
       
   367         }
       
   368         byte[] part61 = c.update(plainText, 0, t);
       
   369         byte[] part62 = new byte[c.getOutputSize(plainText.length)];
       
   370         int len = c.doFinal(plainText, t, offset, part62, 0);
       
   371         int part61Length = part61 != null ? part61.length : 0;
       
   372         byte[] outputText6 = new byte[part61Length + len];
       
   373         if (part61 != null) {
       
   374             System.arraycopy(part61, 0, outputText6, 0, part61Length);
       
   375         }
       
   376         System.arraycopy(part62, 0, outputText6, part61Length, len);
       
   377         results.add(outputText6);
       
   378     }
       
   379 
       
   380     /*
       
   381      * Execute multiple-part encryption/decryption combination #7
       
   382      *   updateAAD(byte[] src, int offset, int len)
       
   383      *   updateAAD(byte[] src, src.length, 0)
       
   384      *   update(byte[], int, int, byte[], int) doFinal(byte[],int, int)
       
   385      */
       
   386     private void combination_7(List<byte[]> results, int mode, byte[] AAD,
       
   387             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   388         Cipher ci = createCipher(mode, params);
       
   389         ci.updateAAD(AAD, 0, AAD.length);
       
   390         ci.updateAAD(AAD, AAD.length, 0);
       
   391         byte[] part71 = new byte[ci.getOutputSize(plainText.length)];
       
   392         int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
       
   393         int len = ci.update(plainText, 0, plainText.length - offset, part71, 0);
       
   394         byte[] part72 = ci.doFinal(plainText, plainText.length - offset, offset);
       
   395         byte[] outputText7 = new byte[len + part72.length];
       
   396         System.arraycopy(part71, 0, outputText7, 0, len);
       
   397         System.arraycopy(part72, 0, outputText7, len, part72.length);
       
   398         results.add(outputText7);
       
   399     }
       
   400 
       
   401     /*
       
   402      * Execute multiple-part encryption/decryption combination #8:
       
   403      *   updateAAD(byte[] src, 0, 0)
       
   404      *   updateAAD(byte[] src, 0, src.length)
       
   405      *   update(byte[], int, int, byte[], int)
       
   406      *   doFinal(byte[], int, int, byte[], int)
       
   407      */
       
   408     private void combination_8(List<byte[]> results, int mode, byte[] AAD,
       
   409             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   410         Cipher ci = createCipher(mode, params);
       
   411         ci.updateAAD(AAD, 0, 0);
       
   412         ci.updateAAD(AAD, 0, AAD.length);
       
   413         byte[] part81 = new byte[ci.getOutputSize(plainText.length)];
       
   414         int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
       
   415         int len = ci.update(plainText, 0, plainText.length - offset, part81, 0);
       
   416         int rest = ci.doFinal(plainText, plainText.length - offset, offset,
       
   417                 part81, len);
       
   418         byte[] outputText8 = new byte[len + rest];
       
   419         System.arraycopy(part81, 0, outputText8, 0, outputText8.length);
       
   420         results.add(outputText8);
       
   421     }
       
   422 
       
   423     /*
       
   424      * Execute multiple-part encryption/decryption combination #9:
       
   425      *   updateAAD(ByteBuffer src)
       
   426      *   update(byte[], int, int) doFinal(byte[], int, int)
       
   427      */
       
   428     private void combination_9(List<byte[]> results, int mode, byte[] AAD,
       
   429             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   430 
       
   431         // prepare ByteBuffer to test
       
   432         ByteBuffer buf = ByteBuffer.allocate(AAD.length);
       
   433         buf.put(AAD);
       
   434         buf.position(0);
       
   435         buf.limit(AAD.length);
       
   436 
       
   437         // Get Cipher object and do the combination
       
   438         Cipher c = createCipher(mode, params);
       
   439         c.updateAAD(buf);
       
   440         byte[] part91 = c.update(plainText, 0, plainText.length);
       
   441         int part91_length = part91 == null ? 0 : part91.length;
       
   442         byte[] part92 = c.doFinal();
       
   443         byte[] outputText9 = new byte[part91_length + part92.length];
       
   444 
       
   445         // form result of the combination
       
   446         if (part91 != null) {
       
   447             System.arraycopy(part91, 0, outputText9, 0, part91_length);
       
   448         }
       
   449         System.arraycopy(part92, 0, outputText9, part91_length, part92.length);
       
   450         results.add(outputText9);
       
   451     }
       
   452 
       
   453     /*
       
   454      * Execute multiple-part encryption/decryption combination #10:
       
   455      *   updateAAD(ByteBuffer src)
       
   456      *   updateAAD(ByteBuffer src) update(byte[], int, int)
       
   457      *   doFinal(byte[], int, int, byte[], int)
       
   458      */
       
   459     private void combination_10(List<byte[]> results, int mode, byte[] AAD,
       
   460             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   461 
       
   462         // prepare ByteBuffer to test
       
   463         ByteBuffer buf = ByteBuffer.allocate(AAD.length);
       
   464         buf.put(AAD);
       
   465         buf.position(0);
       
   466         buf.limit(AAD.length / 2);
       
   467 
       
   468         // get a Cipher object and do the combination
       
   469         Cipher c = createCipher(mode, params);
       
   470 
       
   471         // process the first half of AAD data
       
   472         c.updateAAD(buf);
       
   473 
       
   474         // process the rest of AAD data
       
   475         buf.limit(AAD.length);
       
   476         c.updateAAD(buf);
       
   477 
       
   478         // prapare variables for the combination
       
   479         int t = 0;
       
   480         int offset = 0;
       
   481         if (plainText.length > ARRAY_OFFSET) {
       
   482             t = plainText.length - ARRAY_OFFSET;
       
   483             offset = ARRAY_OFFSET;
       
   484         }
       
   485 
       
   486         // encrypt the text
       
   487         byte[] part10_1 = c.update(plainText, 0, t);
       
   488         int part10_1_Length = part10_1 != null ? part10_1.length : 0;
       
   489         byte[] part10_2 = new byte[c.getOutputSize(plainText.length)];
       
   490         int len2 = c.doFinal(plainText, t, offset, part10_2, 0);
       
   491 
       
   492         // form the combination's result
       
   493         byte[] outputText10 = new byte[part10_1_Length + len2];
       
   494         if (part10_1 != null) {
       
   495             System.arraycopy(part10_1, 0, outputText10, 0, part10_1_Length);
       
   496         }
       
   497         System.arraycopy(part10_2, 0, outputText10, part10_1_Length, len2);
       
   498         results.add(outputText10);
       
   499     }
       
   500 
       
   501     /*
       
   502      * Execute multiple-part encryption/decryption combination #11
       
   503      *   updateAAD(ByteBuffer src1)
       
   504      *   updateAAD(ByteBuffer src2)
       
   505      *   update(byte[],int, int, byte[], int)
       
   506      *   doFinal(byte[], int, int)
       
   507      */
       
   508     private void combination_11(List<byte[]> results, int mode, byte[] AAD,
       
   509             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   510 
       
   511         // prepare ByteBuffer1 to test
       
   512         ByteBuffer buf1 = ByteBuffer.allocate(AAD.length / 2);
       
   513         buf1.put(AAD, 0, AAD.length / 2);
       
   514         buf1.position(0);
       
   515         buf1.limit(AAD.length / 2);
       
   516 
       
   517         // get a Cipher object and do combination
       
   518         Cipher ci = createCipher(mode, params);
       
   519 
       
   520         // process the first half of AAD data
       
   521         ci.updateAAD(buf1);
       
   522 
       
   523         // prepare ByteBuffer2 to test
       
   524         ByteBuffer buf2 = ByteBuffer.allocate(AAD.length - AAD.length / 2);
       
   525         buf2.put(AAD, AAD.length / 2, AAD.length - AAD.length / 2);
       
   526         buf2.position(0);
       
   527         buf2.limit(AAD.length - AAD.length / 2);
       
   528 
       
   529         // process the rest of AAD data
       
   530         ci.updateAAD(buf2);
       
   531 
       
   532         // encrypt plain text
       
   533         byte[] part11_1 = new byte[ci.getOutputSize(plainText.length)];
       
   534         int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
       
   535         int len_11 = ci.update(plainText, 0, plainText.length - offset,
       
   536                 part11_1, 0);
       
   537         byte[] part11_2 = ci.doFinal(plainText, plainText.length - offset,
       
   538                 offset);
       
   539         byte[] outputText11 = new byte[len_11 + part11_2.length];
       
   540         System.arraycopy(part11_1, 0, outputText11, 0, len_11);
       
   541         System.arraycopy(part11_2, 0, outputText11, len_11, part11_2.length);
       
   542         results.add(outputText11);
       
   543     }
       
   544 
       
   545     /*
       
   546      * Execute multiple-part encryption/decryption combination #12:
       
   547      *   updateAAD(ByteBuffer src)
       
   548      *   updateAAD(ByteBuffer emptyByteBuffer)
       
   549      *   update(byte[], int, int, byte[], int)
       
   550      *   doFinal(byte[], int, int, byte[], int)
       
   551      */
       
   552     private void combination_12(List<byte[]> results, int mode, byte[] AAD,
       
   553             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   554 
       
   555         // prepare ByteBuffer to test
       
   556         ByteBuffer buf = ByteBuffer.allocate(AAD.length);
       
   557         buf.put(AAD);
       
   558         buf.position(0);
       
   559         buf.limit(AAD.length);
       
   560         Cipher ci = createCipher(mode, params);
       
   561         ci.updateAAD(buf);
       
   562 
       
   563         // prepare an empty ByteBuffer
       
   564         ByteBuffer emptyBuf = ByteBuffer.allocate(0);
       
   565         emptyBuf.put(new byte[0]);
       
   566         ci.updateAAD(emptyBuf);
       
   567         byte[] part12_1 = new byte[ci.getOutputSize(plainText.length)];
       
   568         int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;
       
   569         int len12 = ci.update(plainText, 0, plainText.length - offset,
       
   570                 part12_1, 0);
       
   571         int rest12 = ci.doFinal(plainText, plainText.length - offset, offset,
       
   572                 part12_1, len12);
       
   573         byte[] outputText12 = new byte[len12 + rest12];
       
   574         System.arraycopy(part12_1, 0, outputText12, 0, outputText12.length);
       
   575         results.add(outputText12);
       
   576     }
       
   577 
       
   578     /*
       
   579      * Execute multiple-part encryption/decryption combination #13:
       
   580      *   updateAAD(ByteBuffer src), where src is directly allocated
       
   581      *   update(ByteBuffer input, ByteBuffer out)
       
   582      *   doFinal(ByteBuffer input, ByteBuffer out)
       
   583      */
       
   584     private void combination_13(List<byte[]> results, int mode, byte[] AAD,
       
   585             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   586         Cipher c = createCipher(mode, params);
       
   587 
       
   588         // prepare ByteBuffer to test
       
   589         ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);
       
   590         buf.put(AAD);
       
   591         buf.position(0);
       
   592         buf.limit(AAD.length);
       
   593         c.updateAAD(buf);
       
   594 
       
   595         // prepare buffers to encrypt/decrypt
       
   596         ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);
       
   597         in.put(plainText);
       
   598         in.position(0);
       
   599         in.limit(plainText.length);
       
   600         ByteBuffer output = ByteBuffer.allocateDirect(
       
   601                 c.getOutputSize(in.limit()));
       
   602         output.position(0);
       
   603         output.limit(c.getOutputSize(in.limit()));
       
   604 
       
   605         // process input text
       
   606         c.update(in, output);
       
   607         c.doFinal(in, output);
       
   608         int resultSize = output.position();
       
   609         byte[] result13 = new byte[resultSize];
       
   610         output.position(0);
       
   611         output.limit(resultSize);
       
   612         output.get(result13, 0, resultSize);
       
   613         results.add(result13);
       
   614     }
       
   615 
       
   616     /*
       
   617      * Execute multiple-part encryption/decryption combination #14:
       
   618      *   updateAAD(ByteBuffer src) updateAAD(ByteBuffer src),
       
   619      *       where src is directly allocated
       
   620      *   update(ByteBuffer input, ByteBuffer out)
       
   621      *   doFinal(ByteBuffer input, ByteBuffer out)
       
   622      */
       
   623     private void combination_14(List<byte[]> results, int mode, byte[] AAD,
       
   624             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   625         Cipher c = createCipher(mode, params);
       
   626         // prepare ByteBuffer to test
       
   627         ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);
       
   628         buf.put(AAD);
       
   629 
       
   630         // process the first half of AAD data
       
   631         buf.position(0);
       
   632         buf.limit(AAD.length / 2);
       
   633         c.updateAAD(buf);
       
   634 
       
   635         // process the rest of AAD data
       
   636         buf.limit(AAD.length);
       
   637         c.updateAAD(buf);
       
   638 
       
   639         // prepare buffers to encrypt/decrypt
       
   640         ByteBuffer in = ByteBuffer.allocate(plainText.length);
       
   641         in.put(plainText);
       
   642         in.position(0);
       
   643         in.limit(plainText.length);
       
   644         ByteBuffer out = ByteBuffer.allocate(c.getOutputSize(in.limit()));
       
   645         out.position(0);
       
   646         out.limit(c.getOutputSize(in.limit()));
       
   647 
       
   648         // process input text
       
   649         c.update(in, out);
       
   650         c.doFinal(in, out);
       
   651         int resultSize = out.position();
       
   652         byte[] result14 = new byte[resultSize];
       
   653         out.position(0);
       
   654         out.limit(resultSize);
       
   655         out.get(result14, 0, resultSize);
       
   656         results.add(result14);
       
   657     }
       
   658 
       
   659     /*
       
   660      * Execute multiple-part encryption/decryption combination #15
       
   661      *   updateAAD(ByteBuffer src1), where src1 is directly allocated
       
   662      *   updateAAD(ByteBuffer src2), where src2 is directly allocated
       
   663      *   doFinal(ByteBuffer input, ByteBuffer out)
       
   664      */
       
   665     private void combination_15(List<byte[]> results, int mode, byte[] AAD,
       
   666             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   667         Cipher c = createCipher(mode, params);
       
   668 
       
   669         // prepare ByteBuffer1 to test
       
   670         ByteBuffer buf1 = ByteBuffer.allocateDirect(AAD.length / 2);
       
   671         buf1.put(AAD, 0, AAD.length / 2);
       
   672         buf1.position(0);
       
   673         buf1.limit(AAD.length / 2);
       
   674 
       
   675         // process the first half of AAD data
       
   676         c.updateAAD(buf1);
       
   677 
       
   678         // prepare ByteBuffer2 to test
       
   679         ByteBuffer buf2 = ByteBuffer.allocateDirect(
       
   680                 AAD.length - AAD.length / 2);
       
   681         buf2.put(AAD, AAD.length / 2, AAD.length - AAD.length / 2);
       
   682         buf2.position(0);
       
   683         buf2.limit(AAD.length - AAD.length / 2);
       
   684 
       
   685         // process the rest of AAD data
       
   686         c.updateAAD(buf2);
       
   687 
       
   688         // prepare buffers to encrypt/decrypt
       
   689         ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);
       
   690         in.put(plainText);
       
   691         in.position(0);
       
   692         in.limit(plainText.length);
       
   693         ByteBuffer output = ByteBuffer.allocateDirect(
       
   694                 c.getOutputSize(in.limit()));
       
   695         output.position(0);
       
   696         output.limit(c.getOutputSize(in.limit()));
       
   697 
       
   698         // process input text
       
   699         c.doFinal(in, output);
       
   700         int resultSize = output.position();
       
   701         byte[] result15 = new byte[resultSize];
       
   702         output.position(0);
       
   703         output.limit(resultSize);
       
   704         output.get(result15, 0, resultSize);
       
   705         results.add(result15);
       
   706     }
       
   707 
       
   708     /*
       
   709      * Execute multiple-part encryption/decryption combination #16:
       
   710      *   updateAAD(ByteBuffer src)
       
   711      *   updateAAD(ByteBuffer emptyByteBuffer)
       
   712      *   update(ByteBuffer input, ByteBuffer out)
       
   713      *   doFinal(EmptyByteBuffer, ByteBuffer out)
       
   714      */
       
   715     private void combination_16(List<byte[]> results, int mode, byte[] AAD,
       
   716             byte[] plainText, AlgorithmParameters params) throws Exception {
       
   717         Cipher c = createCipher(mode, params);
       
   718 
       
   719         // prepare ByteBuffer to test
       
   720         ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);
       
   721         buf.put(AAD);
       
   722         buf.position(0);
       
   723         buf.limit(AAD.length);
       
   724         c.updateAAD(buf);
       
   725 
       
   726         // prepare empty ByteBuffer
       
   727         ByteBuffer emptyBuf = ByteBuffer.allocateDirect(0);
       
   728         emptyBuf.put(new byte[0]);
       
   729         c.updateAAD(emptyBuf);
       
   730 
       
   731         // prepare buffers to encrypt/decrypt
       
   732         ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);
       
   733         in.put(plainText);
       
   734         in.position(0);
       
   735         in.limit(plainText.length);
       
   736         ByteBuffer output = ByteBuffer.allocateDirect(
       
   737                 c.getOutputSize(in.limit()));
       
   738         output.position(0);
       
   739         output.limit(c.getOutputSize(in.limit()));
       
   740 
       
   741         // process input text with an empty buffer
       
   742         c.update(in, output);
       
   743         ByteBuffer emptyBuf2 = ByteBuffer.allocate(0);
       
   744         emptyBuf2.put(new byte[0]);
       
   745         c.doFinal(emptyBuf2, output);
       
   746         int resultSize = output.position();
       
   747         byte[] result16 = new byte[resultSize];
       
   748         output.position(0);
       
   749         output.limit(resultSize);
       
   750         output.get(result16, 0, resultSize);
       
   751         results.add(result16);
       
   752     }
       
   753 }