Path: blob/master/test/jdk/com/sun/crypto/provider/Cipher/AEAD/Encrypt.java
41161 views
/*1* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.nio.ByteBuffer;24import java.security.AlgorithmParameters;25import java.security.Provider;26import java.security.Security;27import java.util.ArrayList;28import java.util.Arrays;29import java.util.List;30import javax.crypto.SecretKey;31import javax.crypto.Cipher;32import javax.crypto.KeyGenerator;3334/*35* @test36* @bug 804859637* @summary AEAD encryption/decryption test38*/3940/*41* The test does the following:42* - create an input text and additional data43* - generate a secret key44* - instantiate a cipher according to the GCM transformation45* - generate an outputText using a single-part encryption/decryption46* in AEAD mode47* - perform 16 different combinations of multiple-part encryption/decryption48* operation in AEAD mode (in encryption mode new Cipher object is created49* and initialized with the same secret key and parameters)50* - check that all 17 results are equal51*52* Combinations:53*54* combination #155* updateAAD(byte[] src)56* update(byte[], int, int)57* doFinal(byte[], int, int)58*59* combination #260* updateAAD(byte[] src)61* update(byte[], int, int)62* doFinal(byte[], int, int, byte[], int)63*64* combination #365* updateAAD(byte[] src)66* update(byte[], int, int, byte[], int)67* doFinal(byte[], int, int)68*69* combination #470* updateAAD(byte[] src)71* update(byte[], int, int, byte[], int)72* doFinal(byte[], int, int, byte[], int)73*74* combination #5 - #8 are similar to #1 -#4,75* but with updateAAD(byte[] src, int offset, int len)76*77* combination #9 - #12 are similar to #1 - #4,78* but with updateAAD(ByteBuffer src)79*80* combination #13 - #16 are similar to #9 - #12 but with directly allocated81* ByteBuffer and update(ByteBuffer input, ByteBuffer output)82*83*/84public class Encrypt {8586private static final String ALGORITHMS[] = { "AES", "Rijndael" };87private static final int KEY_STRENGTHS[] = { 128, 192, 256 };88private static final int TEXT_LENGTHS[] = { 0, 256, 1024 };89private static final int AAD_LENGTHS[] = { 0, 8, 128, 256, 1024 };90private static final int ARRAY_OFFSET = 8;9192private final String transformation;93private final Provider provider;94private final SecretKey key;95private final int textLength;96private final int AADLength;9798/**99* @param provider Security provider100* @param algorithm Security algorithm to test101* @param mode The mode (GCM is only expected)102* @param padding Algorithm padding103* @param keyStrength key length104* @param textLength Plain text length105* @param AADLength Additional data length106*/107public Encrypt(Provider provider, String algorithm, String mode,108String padding, int keyStrength, int textLength, int AADLength)109throws Exception {110111// init a secret Key112KeyGenerator kg = KeyGenerator.getInstance(algorithm, provider);113kg.init(keyStrength);114key = kg.generateKey();115116this.provider = provider;117this.transformation = algorithm + "/" + mode + "/" + padding;118this.textLength = textLength;119this.AADLength = AADLength;120}121122public static void main(String[] args) throws Exception {123Provider p = Security.getProvider("SunJCE");124for (String alg : ALGORITHMS) {125for (int keyStrength : KEY_STRENGTHS) {126if (keyStrength > Cipher.getMaxAllowedKeyLength(alg)) {127// skip this if this key length is larger than what's128// configured in the JCE jurisdiction policy files129continue;130}131for (int textLength : TEXT_LENGTHS) {132for (int AADLength : AAD_LENGTHS) {133Encrypt test = new Encrypt(p, alg,134"GCM", "NoPadding", keyStrength, textLength,135AADLength);136Cipher cipher = test.createCipher(Cipher.ENCRYPT_MODE,137null);138AlgorithmParameters params = cipher.getParameters();139test.doTest(params);140System.out.println("Test " + alg + ":"141+ keyStrength + ":" + textLength + ":"142+ AADLength + " passed");143}144}145}146}147}148149public void doTest(AlgorithmParameters params) throws Exception {150System.out.println("Test transformation = " + transformation151+ ", textLength = " + textLength152+ ", AADLength = " + AADLength);153byte[] input = Helper.generateBytes(textLength);154byte[] AAD = Helper.generateBytes(AADLength);155byte[] result = execute(Cipher.ENCRYPT_MODE, AAD, input, params);156result = execute(Cipher.DECRYPT_MODE, AAD, result, params);157if (!Arrays.equals(input, result)) {158throw new RuntimeException("Test failed");159}160System.out.println("Test passed");161}162163/**164* Create a Cipher object for the requested encryption/decryption mode.165*166* @param mode encryption or decryption mode167* @return Cipher object initiated to perform requested mode operation168*/169private Cipher createCipher(int mode, AlgorithmParameters params)170throws Exception {171Cipher ci;172if (Cipher.ENCRYPT_MODE == mode) {173// create a new Cipher object for encryption174ci = Cipher.getInstance(transformation, provider);175176// initiate it with the saved parameters177if (params != null) {178ci.init(Cipher.ENCRYPT_MODE, key, params);179} else {180// initiate the cipher without parameters181ci.init(Cipher.ENCRYPT_MODE, key);182}183} else {184// it is expected that parameters already generated185// before decryption186ci = Cipher.getInstance(transformation, provider);187ci.init(Cipher.DECRYPT_MODE, key, params);188}189190return ci;191}192193/**194* Test AEAD combinations195*196* @param mode decryption or encryption197* @param AAD additional data for AEAD operations198* @param inputText plain text to decrypt/encrypt199* @return output text after encrypt/decrypt200*/201public byte[] execute(int mode, byte[] AAD, byte[] inputText,202AlgorithmParameters params) throws Exception {203204Cipher cipher = createCipher(mode, params);205206// results of each combination will be saved in the outputTexts207List<byte[]> outputTexts = new ArrayList<>();208209// generate a standard outputText using a single-part en/de-cryption210cipher.updateAAD(AAD);211byte[] output = cipher.doFinal(inputText);212213// execute multiple-part encryption/decryption combinations214combination_1(outputTexts, mode, AAD, inputText, params);215combination_2(outputTexts, mode, AAD, inputText, params);216combination_3(outputTexts, mode, AAD, inputText, params);217combination_4(outputTexts, mode, AAD, inputText, params);218combination_5(outputTexts, mode, AAD, inputText, params);219combination_6(outputTexts, mode, AAD, inputText, params);220combination_7(outputTexts, mode, AAD, inputText, params);221combination_8(outputTexts, mode, AAD, inputText, params);222combination_9(outputTexts, mode, AAD, inputText, params);223combination_10(outputTexts, mode, AAD, inputText, params);224combination_11(outputTexts, mode, AAD, inputText, params);225combination_12(outputTexts, mode, AAD, inputText, params);226combination_13(outputTexts, mode, AAD, inputText, params);227combination_14(outputTexts, mode, AAD, inputText, params);228combination_15(outputTexts, mode, AAD, inputText, params);229combination_16(outputTexts, mode, AAD, inputText, params);230231for (int k = 0; k < outputTexts.size(); k++) {232if (!Arrays.equals(output, outputTexts.get(k))) {233throw new RuntimeException("Combination #" + k + " failed");234}235}236return output;237}238239/*240* Execute multiple-part encryption/decryption combination #1:241* updateAAD(byte[] src)242* update(byte[], int, int)243* doFinal(byte[], int, int)244*/245private void combination_1(List<byte[]> results, int mode, byte[] AAD,246byte[] plainText, AlgorithmParameters params) throws Exception {247Cipher c = createCipher(mode, params);248c.updateAAD(AAD);249byte[] part11 = c.update(plainText, 0, plainText.length);250int part11_length = part11 == null ? 0 : part11.length;251byte[] part12 = c.doFinal();252byte[] outputText1 = new byte[part11_length + part12.length];253if (part11 != null) {254System.arraycopy(part11, 0, outputText1, 0, part11_length);255}256System.arraycopy(part12, 0, outputText1, part11_length, part12.length);257results.add(outputText1);258}259260/*261* Execute multiple-part encryption/decryption combination #2:262* updateAAD(byte[] src)263* update(byte[], int, int)264* doFinal(byte[], int, int, byte[], int)265*/266private void combination_2(List<byte[]> results, int mode, byte[] AAD,267byte[] plainText, AlgorithmParameters params) throws Exception {268Cipher c = createCipher(mode, params);269c.updateAAD(AAD);270int t = 0;271int offset = 0;272if (plainText.length > ARRAY_OFFSET) {273t = plainText.length - ARRAY_OFFSET;274offset = ARRAY_OFFSET;275}276byte[] part21 = c.update(plainText, 0, t);277byte[] part22 = new byte[c.getOutputSize(plainText.length)];278int len2 = c.doFinal(plainText, t, offset, part22, 0);279int part21Length = part21 != null ? part21.length : 0;280byte[] outputText2 = new byte[part21Length + len2];281if (part21 != null) {282System.arraycopy(part21, 0, outputText2, 0, part21Length);283}284System.arraycopy(part22, 0, outputText2, part21Length, len2);285results.add(outputText2);286}287288/*289* Execute multiple-part encryption/decryption combination #3290* updateAAD(byte[] src)291* update(byte[], int, int, byte[], int)292* doFinal(byte[], int, int)293*/294private void combination_3(List<byte[]> results, int mode, byte[] AAD,295byte[] plainText, AlgorithmParameters params) throws Exception {296Cipher ci = createCipher(mode, params);297ci.updateAAD(AAD);298byte[] part31 = new byte[ci.getOutputSize(plainText.length)];299int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;300int len = ci.update(plainText, 0, plainText.length - offset, part31, 0);301byte[] part32 = ci.doFinal(plainText, plainText.length - offset,302offset);303byte[] outputText3 = new byte[len + part32.length];304System.arraycopy(part31, 0, outputText3, 0, len);305System.arraycopy(part32, 0, outputText3, len, part32.length);306results.add(outputText3);307}308309/*310* Execute multiple-part encryption/decryption combination #4:311* updateAAD(byte[] src)312* update(byte[], int, int, byte[], int)313* doFinal(byte[], int, int, byte[], int)314*/315private void combination_4(List<byte[]> results, int mode, byte[] AAD,316byte[] plainText, AlgorithmParameters params) throws Exception {317Cipher ci = createCipher(mode, params);318ci.updateAAD(AAD);319byte[] part41 = new byte[ci.getOutputSize(plainText.length)];320int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;321int len = ci.update(plainText, 0, plainText.length - offset, part41, 0);322int rest4 = ci.doFinal(plainText, plainText.length - offset, offset,323part41, len);324byte[] outputText4 = new byte[len + rest4];325System.arraycopy(part41, 0, outputText4, 0, outputText4.length);326results.add(outputText4);327}328329/*330* Execute multiple-part encryption/decryption combination #5:331* updateAAD(byte[] src, int offset, int len)332* update(byte[], int, int)333* doFinal(byte[], int, int)334*/335private void combination_5(List<byte[]> results, int mode, byte[] AAD,336byte[] plainText, AlgorithmParameters params) throws Exception {337Cipher c = createCipher(mode, params);338c.updateAAD(AAD, 0, AAD.length);339byte[] part51 = c.update(plainText, 0, plainText.length);340byte[] part52 = c.doFinal();341int part51Length = part51 != null ? part51.length : 0;342byte[] outputText5 = new byte[part51Length + part52.length];343if (part51 != null) {344System.arraycopy(part51, 0, outputText5, 0, part51Length);345}346System.arraycopy(part52, 0, outputText5, part51Length, part52.length);347results.add(outputText5);348}349350/*351* Execute multiple-part encryption/decryption combination #6:352* updateAAD(byte[] src, int offset, int len)353* updateAAD(byte[] src, int offset, int len)354* update(byte[], int, int) doFinal(byte[], int, int, byte[], int)355*/356private void combination_6(List<byte[]> results, int mode, byte[] AAD,357byte[] plainText, AlgorithmParameters params) throws Exception {358Cipher c = createCipher(mode, params);359c.updateAAD(AAD, 0, AAD.length / 2);360c.updateAAD(AAD, AAD.length / 2, AAD.length - AAD.length / 2);361int t = 0;362int offset = 0;363if (plainText.length > ARRAY_OFFSET) {364t = plainText.length - ARRAY_OFFSET;365offset = ARRAY_OFFSET;366}367byte[] part61 = c.update(plainText, 0, t);368byte[] part62 = new byte[c.getOutputSize(plainText.length)];369int len = c.doFinal(plainText, t, offset, part62, 0);370int part61Length = part61 != null ? part61.length : 0;371byte[] outputText6 = new byte[part61Length + len];372if (part61 != null) {373System.arraycopy(part61, 0, outputText6, 0, part61Length);374}375System.arraycopy(part62, 0, outputText6, part61Length, len);376results.add(outputText6);377}378379/*380* Execute multiple-part encryption/decryption combination #7381* updateAAD(byte[] src, int offset, int len)382* updateAAD(byte[] src, src.length, 0)383* update(byte[], int, int, byte[], int) doFinal(byte[],int, int)384*/385private void combination_7(List<byte[]> results, int mode, byte[] AAD,386byte[] plainText, AlgorithmParameters params) throws Exception {387Cipher ci = createCipher(mode, params);388ci.updateAAD(AAD, 0, AAD.length);389ci.updateAAD(AAD, AAD.length, 0);390byte[] part71 = new byte[ci.getOutputSize(plainText.length)];391int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;392int len = ci.update(plainText, 0, plainText.length - offset, part71, 0);393byte[] part72 = ci.doFinal(plainText, plainText.length - offset, offset);394byte[] outputText7 = new byte[len + part72.length];395System.arraycopy(part71, 0, outputText7, 0, len);396System.arraycopy(part72, 0, outputText7, len, part72.length);397results.add(outputText7);398}399400/*401* Execute multiple-part encryption/decryption combination #8:402* updateAAD(byte[] src, 0, 0)403* updateAAD(byte[] src, 0, src.length)404* update(byte[], int, int, byte[], int)405* doFinal(byte[], int, int, byte[], int)406*/407private void combination_8(List<byte[]> results, int mode, byte[] AAD,408byte[] plainText, AlgorithmParameters params) throws Exception {409Cipher ci = createCipher(mode, params);410ci.updateAAD(AAD, 0, 0);411ci.updateAAD(AAD, 0, AAD.length);412byte[] part81 = new byte[ci.getOutputSize(plainText.length)];413int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;414int len = ci.update(plainText, 0, plainText.length - offset, part81, 0);415int rest = ci.doFinal(plainText, plainText.length - offset, offset,416part81, len);417byte[] outputText8 = new byte[len + rest];418System.arraycopy(part81, 0, outputText8, 0, outputText8.length);419results.add(outputText8);420}421422/*423* Execute multiple-part encryption/decryption combination #9:424* updateAAD(ByteBuffer src)425* update(byte[], int, int) doFinal(byte[], int, int)426*/427private void combination_9(List<byte[]> results, int mode, byte[] AAD,428byte[] plainText, AlgorithmParameters params) throws Exception {429430// prepare ByteBuffer to test431ByteBuffer buf = ByteBuffer.allocate(AAD.length);432buf.put(AAD);433buf.position(0);434buf.limit(AAD.length);435436// Get Cipher object and do the combination437Cipher c = createCipher(mode, params);438c.updateAAD(buf);439byte[] part91 = c.update(plainText, 0, plainText.length);440int part91_length = part91 == null ? 0 : part91.length;441byte[] part92 = c.doFinal();442byte[] outputText9 = new byte[part91_length + part92.length];443444// form result of the combination445if (part91 != null) {446System.arraycopy(part91, 0, outputText9, 0, part91_length);447}448System.arraycopy(part92, 0, outputText9, part91_length, part92.length);449results.add(outputText9);450}451452/*453* Execute multiple-part encryption/decryption combination #10:454* updateAAD(ByteBuffer src)455* updateAAD(ByteBuffer src) update(byte[], int, int)456* doFinal(byte[], int, int, byte[], int)457*/458private void combination_10(List<byte[]> results, int mode, byte[] AAD,459byte[] plainText, AlgorithmParameters params) throws Exception {460461// prepare ByteBuffer to test462ByteBuffer buf = ByteBuffer.allocate(AAD.length);463buf.put(AAD);464buf.position(0);465buf.limit(AAD.length / 2);466467// get a Cipher object and do the combination468Cipher c = createCipher(mode, params);469470// process the first half of AAD data471c.updateAAD(buf);472473// process the rest of AAD data474buf.limit(AAD.length);475c.updateAAD(buf);476477// prapare variables for the combination478int t = 0;479int offset = 0;480if (plainText.length > ARRAY_OFFSET) {481t = plainText.length - ARRAY_OFFSET;482offset = ARRAY_OFFSET;483}484485// encrypt the text486byte[] part10_1 = c.update(plainText, 0, t);487int part10_1_Length = part10_1 != null ? part10_1.length : 0;488byte[] part10_2 = new byte[c.getOutputSize(plainText.length)];489int len2 = c.doFinal(plainText, t, offset, part10_2, 0);490491// form the combination's result492byte[] outputText10 = new byte[part10_1_Length + len2];493if (part10_1 != null) {494System.arraycopy(part10_1, 0, outputText10, 0, part10_1_Length);495}496System.arraycopy(part10_2, 0, outputText10, part10_1_Length, len2);497results.add(outputText10);498}499500/*501* Execute multiple-part encryption/decryption combination #11502* updateAAD(ByteBuffer src1)503* updateAAD(ByteBuffer src2)504* update(byte[],int, int, byte[], int)505* doFinal(byte[], int, int)506*/507private void combination_11(List<byte[]> results, int mode, byte[] AAD,508byte[] plainText, AlgorithmParameters params) throws Exception {509510// prepare ByteBuffer1 to test511ByteBuffer buf1 = ByteBuffer.allocate(AAD.length / 2);512buf1.put(AAD, 0, AAD.length / 2);513buf1.position(0);514buf1.limit(AAD.length / 2);515516// get a Cipher object and do combination517Cipher ci = createCipher(mode, params);518519// process the first half of AAD data520ci.updateAAD(buf1);521522// prepare ByteBuffer2 to test523ByteBuffer buf2 = ByteBuffer.allocate(AAD.length - AAD.length / 2);524buf2.put(AAD, AAD.length / 2, AAD.length - AAD.length / 2);525buf2.position(0);526buf2.limit(AAD.length - AAD.length / 2);527528// process the rest of AAD data529ci.updateAAD(buf2);530531// encrypt plain text532byte[] part11_1 = new byte[ci.getOutputSize(plainText.length)];533int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;534int len_11 = ci.update(plainText, 0, plainText.length - offset,535part11_1, 0);536byte[] part11_2 = ci.doFinal(plainText, plainText.length - offset,537offset);538byte[] outputText11 = new byte[len_11 + part11_2.length];539System.arraycopy(part11_1, 0, outputText11, 0, len_11);540System.arraycopy(part11_2, 0, outputText11, len_11, part11_2.length);541results.add(outputText11);542}543544/*545* Execute multiple-part encryption/decryption combination #12:546* updateAAD(ByteBuffer src)547* updateAAD(ByteBuffer emptyByteBuffer)548* update(byte[], int, int, byte[], int)549* doFinal(byte[], int, int, byte[], int)550*/551private void combination_12(List<byte[]> results, int mode, byte[] AAD,552byte[] plainText, AlgorithmParameters params) throws Exception {553554// prepare ByteBuffer to test555ByteBuffer buf = ByteBuffer.allocate(AAD.length);556buf.put(AAD);557buf.position(0);558buf.limit(AAD.length);559Cipher ci = createCipher(mode, params);560ci.updateAAD(buf);561562// prepare an empty ByteBuffer563ByteBuffer emptyBuf = ByteBuffer.allocate(0);564emptyBuf.put(new byte[0]);565ci.updateAAD(emptyBuf);566byte[] part12_1 = new byte[ci.getOutputSize(plainText.length)];567int offset = plainText.length > ARRAY_OFFSET ? ARRAY_OFFSET : 0;568int len12 = ci.update(plainText, 0, plainText.length - offset,569part12_1, 0);570int rest12 = ci.doFinal(plainText, plainText.length - offset, offset,571part12_1, len12);572byte[] outputText12 = new byte[len12 + rest12];573System.arraycopy(part12_1, 0, outputText12, 0, outputText12.length);574results.add(outputText12);575}576577/*578* Execute multiple-part encryption/decryption combination #13:579* updateAAD(ByteBuffer src), where src is directly allocated580* update(ByteBuffer input, ByteBuffer out)581* doFinal(ByteBuffer input, ByteBuffer out)582*/583private void combination_13(List<byte[]> results, int mode, byte[] AAD,584byte[] plainText, AlgorithmParameters params) throws Exception {585Cipher c = createCipher(mode, params);586587// prepare ByteBuffer to test588ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);589buf.put(AAD);590buf.position(0);591buf.limit(AAD.length);592c.updateAAD(buf);593594// prepare buffers to encrypt/decrypt595ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);596in.put(plainText);597in.position(0);598in.limit(plainText.length);599ByteBuffer output = ByteBuffer.allocateDirect(600c.getOutputSize(in.limit()));601output.position(0);602output.limit(c.getOutputSize(in.limit()));603604// process input text605c.update(in, output);606c.doFinal(in, output);607int resultSize = output.position();608byte[] result13 = new byte[resultSize];609output.position(0);610output.limit(resultSize);611output.get(result13, 0, resultSize);612results.add(result13);613}614615/*616* Execute multiple-part encryption/decryption combination #14:617* updateAAD(ByteBuffer src) updateAAD(ByteBuffer src),618* where src is directly allocated619* update(ByteBuffer input, ByteBuffer out)620* doFinal(ByteBuffer input, ByteBuffer out)621*/622private void combination_14(List<byte[]> results, int mode, byte[] AAD,623byte[] plainText, AlgorithmParameters params) throws Exception {624Cipher c = createCipher(mode, params);625// prepare ByteBuffer to test626ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);627buf.put(AAD);628629// process the first half of AAD data630buf.position(0);631buf.limit(AAD.length / 2);632c.updateAAD(buf);633634// process the rest of AAD data635buf.limit(AAD.length);636c.updateAAD(buf);637638// prepare buffers to encrypt/decrypt639ByteBuffer in = ByteBuffer.allocate(plainText.length);640in.put(plainText);641in.position(0);642in.limit(plainText.length);643ByteBuffer out = ByteBuffer.allocate(c.getOutputSize(in.limit()));644out.position(0);645out.limit(c.getOutputSize(in.limit()));646647// process input text648c.update(in, out);649c.doFinal(in, out);650int resultSize = out.position();651byte[] result14 = new byte[resultSize];652out.position(0);653out.limit(resultSize);654out.get(result14, 0, resultSize);655results.add(result14);656}657658/*659* Execute multiple-part encryption/decryption combination #15660* updateAAD(ByteBuffer src1), where src1 is directly allocated661* updateAAD(ByteBuffer src2), where src2 is directly allocated662* doFinal(ByteBuffer input, ByteBuffer out)663*/664private void combination_15(List<byte[]> results, int mode, byte[] AAD,665byte[] plainText, AlgorithmParameters params) throws Exception {666Cipher c = createCipher(mode, params);667668// prepare ByteBuffer1 to test669ByteBuffer buf1 = ByteBuffer.allocateDirect(AAD.length / 2);670buf1.put(AAD, 0, AAD.length / 2);671buf1.position(0);672buf1.limit(AAD.length / 2);673674// process the first half of AAD data675c.updateAAD(buf1);676677// prepare ByteBuffer2 to test678ByteBuffer buf2 = ByteBuffer.allocateDirect(679AAD.length - AAD.length / 2);680buf2.put(AAD, AAD.length / 2, AAD.length - AAD.length / 2);681buf2.position(0);682buf2.limit(AAD.length - AAD.length / 2);683684// process the rest of AAD data685c.updateAAD(buf2);686687// prepare buffers to encrypt/decrypt688ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);689in.put(plainText);690in.position(0);691in.limit(plainText.length);692ByteBuffer output = ByteBuffer.allocateDirect(693c.getOutputSize(in.limit()));694output.position(0);695output.limit(c.getOutputSize(in.limit()));696697// process input text698c.doFinal(in, output);699int resultSize = output.position();700byte[] result15 = new byte[resultSize];701output.position(0);702output.limit(resultSize);703output.get(result15, 0, resultSize);704results.add(result15);705}706707/*708* Execute multiple-part encryption/decryption combination #16:709* updateAAD(ByteBuffer src)710* updateAAD(ByteBuffer emptyByteBuffer)711* update(ByteBuffer input, ByteBuffer out)712* doFinal(EmptyByteBuffer, ByteBuffer out)713*/714private void combination_16(List<byte[]> results, int mode, byte[] AAD,715byte[] plainText, AlgorithmParameters params) throws Exception {716Cipher c = createCipher(mode, params);717718// prepare ByteBuffer to test719ByteBuffer buf = ByteBuffer.allocateDirect(AAD.length);720buf.put(AAD);721buf.position(0);722buf.limit(AAD.length);723c.updateAAD(buf);724725// prepare empty ByteBuffer726ByteBuffer emptyBuf = ByteBuffer.allocateDirect(0);727emptyBuf.put(new byte[0]);728c.updateAAD(emptyBuf);729730// prepare buffers to encrypt/decrypt731ByteBuffer in = ByteBuffer.allocateDirect(plainText.length);732in.put(plainText);733in.position(0);734in.limit(plainText.length);735ByteBuffer output = ByteBuffer.allocateDirect(736c.getOutputSize(in.limit()));737output.position(0);738output.limit(c.getOutputSize(in.limit()));739740// process input text with an empty buffer741c.update(in, output);742ByteBuffer emptyBuf2 = ByteBuffer.allocate(0);743emptyBuf2.put(new byte[0]);744c.doFinal(emptyBuf2, output);745int resultSize = output.position();746byte[] result16 = new byte[resultSize];747output.position(0);748output.limit(resultSize);749output.get(result16, 0, resultSize);750results.add(result16);751}752}753754755