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 */ Encrypt(Provider provider, String algorithm, String mode, String padding, int keyStrength, int textLength, int AADLength)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 main(String[] args)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 doTest(AlgorithmParameters params)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 */ createCipher(int mode, AlgorithmParameters params)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 */ execute(int mode, byte[] AAD, byte[] inputText, AlgorithmParameters params)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 */ combination_1(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_2(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_3(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_4(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_5(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_6(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_7(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_8(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_9(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_10(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_11(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_12(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_13(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_14(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_15(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 */ combination_16(List<byte[]> results, int mode, byte[] AAD, byte[] plainText, AlgorithmParameters params)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 } 754