Path: blob/master/test/jdk/javax/crypto/CipherSpi/TestGCMWithByteBuffer.java
41152 views
/*1* Copyright (c) 2018, 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*/2223/**24* @test25* @bug 817837426* @summary Test GCM decryption with various types of input/output27* ByteBuffer objects28* @key randomness29*/3031import java.nio.ByteBuffer;32import java.security.*;33import java.util.Random;3435import javax.crypto.Cipher;36import javax.crypto.SecretKey;37import javax.crypto.AEADBadTagException;38import javax.crypto.spec.*;3940public class TestGCMWithByteBuffer {4142private static Random random = new SecureRandom();43private static int dataSize = 4096; // see javax.crypto.CipherSpi44private static int multiples = 3;4546public static void main(String args[]) throws Exception {47Provider[] provs = Security.getProviders();48for (Provider p : provs) {49try {50Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", p);51test(cipher);52} catch (NoSuchAlgorithmException nsae) {53// skip testing due to no support54continue;55}56}57}5859private static void test(Cipher cipher) throws Exception {60System.out.println("Testing " + cipher.getProvider());6162boolean failedOnce = false;63Exception failedReason = null;6465int tagLen = 96; // in bits66byte[] keyBytes = new byte[16];67random.nextBytes(keyBytes);68byte[] dataChunk = new byte[dataSize];69random.nextBytes(dataChunk);7071SecretKey key = new SecretKeySpec(keyBytes, "AES");72// re-use key bytes as IV as the real test is buffer calculation73GCMParameterSpec s = new GCMParameterSpec(tagLen, keyBytes);7475/*76* Iterate through various sizes to make sure that the code works with77* internal temp buffer size 4096.78*/79for (int t = 1; t <= multiples; t++) {80int size = t * dataSize;8182System.out.println("\nTesting data size: " + size);8384try {85decrypt(cipher, key, s, dataChunk, t,86ByteBuffer.allocate(dataSize),87ByteBuffer.allocate(size),88ByteBuffer.allocateDirect(dataSize),89ByteBuffer.allocateDirect(size));90} catch (Exception e) {91System.out.println("\tFailed with data size " + size);92failedOnce = true;93failedReason = e;94}95}96if (failedOnce) {97throw failedReason;98}99System.out.println("\n=> Passed...");100}101102private enum TestVariant {103HEAP_HEAP, HEAP_DIRECT, DIRECT_HEAP, DIRECT_DIRECT104};105106private static void decrypt(Cipher cipher, SecretKey key,107GCMParameterSpec s, byte[] dataChunk, int multiples,108ByteBuffer heapIn, ByteBuffer heapOut, ByteBuffer directIn,109ByteBuffer directOut) throws Exception {110111ByteBuffer inBB = null;112ByteBuffer outBB = null;113114// try various combinations of input/output115for (TestVariant tv : TestVariant.values()) {116System.out.println(" " + tv);117118switch (tv) {119case HEAP_HEAP:120inBB = heapIn;121outBB = heapOut;122break;123case HEAP_DIRECT:124inBB = heapIn;125outBB = directOut;126break;127case DIRECT_HEAP:128inBB = directIn;129outBB = heapOut;130break;131case DIRECT_DIRECT:132inBB = directIn;133outBB = directOut;134break;135}136137// prepare input and output buffers138inBB.clear();139inBB.put(dataChunk);140141outBB.clear();142143try {144// Always re-init the Cipher object so cipher is in145// a good state for future testing146cipher.init(Cipher.DECRYPT_MODE, key, s);147148for (int i = 0; i < multiples; i++) {149inBB.flip();150cipher.update(inBB, outBB);151if (inBB.hasRemaining()) {152throw new Exception("buffer not empty");153}154}155// finish decryption and process all data buffered156cipher.doFinal(inBB, outBB);157throw new RuntimeException("Error: doFinal completed without exception");158} catch (AEADBadTagException ex) {159System.out.println("Expected AEADBadTagException thrown");160continue;161}162}163}164}165166167