Path: blob/master/test/jdk/com/sun/crypto/provider/Cipher/AEAD/OverlapByteBuffer.java
41161 views
/*1* Copyright (c) 2020, 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 javax.crypto.Cipher;24import javax.crypto.spec.GCMParameterSpec;25import javax.crypto.spec.SecretKeySpec;26import java.nio.ByteBuffer;2728/*29* @test30* @summary This tests overlapping buffers using ByteBuffer.slice() with31* array-backed ByteBuffer, read only array-backed, ByteBuffer, and direct32* ByteBuffer.33*/3435/*36* This tests overlapping buffers created with ByteBuffer.slice(). That is37* when the input and output ByteBuffers have shared memory (use the same38* underlying buffer space, commonly used for in-place crypto). The39* complication is the Cipher object specifies that it must be copy-safe. That40* means the output buffer will not overwrite any input data that has not been41* processed. If the output buffer's position or offset is greater than the42* input's overwriting will occur.43*/4445public class OverlapByteBuffer {4647public static void main(String[] args) throws Exception {48byte[] baseBuf = new byte[8192];49ByteBuffer output, input, in;50// Output offset from the baseBuf51int outOfs;5253for (int i = 0; i < 3; i++) {54for (outOfs = -1; outOfs <= 1; outOfs++) {5556SecretKeySpec key = new SecretKeySpec(new byte[16], "AES");57GCMParameterSpec params =58new GCMParameterSpec(128, new byte[12]);59Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");60cipher.init(Cipher.ENCRYPT_MODE, key, params);6162// Offset on the particular ByteBuffer (aka position())63int inOfsInBuf = 1;64int outOfsInBuf = inOfsInBuf + outOfs;65int sliceLen = cipher.getOutputSize(baseBuf.length);66int bufferSize = sliceLen + Math.max(inOfsInBuf, outOfsInBuf);67byte[] buffer;68// Create overlapping input and output buffers69switch (i) {70case 0 -> {71buffer = new byte[bufferSize];72output = ByteBuffer.wrap(buffer, outOfsInBuf, sliceLen).73slice();74input = ByteBuffer.wrap(buffer, inOfsInBuf, sliceLen).75slice();76System.out.println("Using array-backed ByteBuffer");77in = input.duplicate();78}79case 1 -> {80buffer = new byte[bufferSize];81output = ByteBuffer.wrap(buffer, outOfsInBuf, sliceLen).82slice();83input = ByteBuffer.wrap(buffer, inOfsInBuf, sliceLen).84slice();8586System.out.println("Using read-only array-backed " + "ByteBuffer");87in = input.asReadOnlyBuffer();88}89case 2 -> {90System.out.println("Using direct ByteBuffer");91ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize);92output = buf.duplicate();93output.position(outOfsInBuf);94output.limit(sliceLen + outOfsInBuf);95output = output.slice();9697input = buf.duplicate();98input.position(inOfsInBuf);99input.limit(sliceLen + inOfsInBuf);100input = input.slice();101102in = input.duplicate();103}104default -> {105throw new Exception("Unknown index " + i);106}107}108109// Copy data into shared buffer110input.put(baseBuf);111input.flip();112in.limit(input.limit());113114try {115int ctSize = cipher.doFinal(in, output);116117// Get ready to decrypt118byte[] tmp = new byte[ctSize];119output.flip();120output.get(tmp);121output.clear();122123input.clear();124input.put(tmp);125input.flip();126127in.clear();128in.limit(input.limit());129130cipher.init(Cipher.DECRYPT_MODE, key, params);131cipher.doFinal(in, output);132133output.flip();134System.out.println("inOfsInBuf = " + inOfsInBuf);135System.out.println("outOfsInBuf = " + outOfsInBuf);136ByteBuffer b = ByteBuffer.wrap(baseBuf);137if (b.compareTo(output) != 0) {138System.err.println(139"\nresult (" + output + "):\n" +140byteToHex(output) +141"\nexpected (" + b + "):\n" +142byteToHex(b));143throw new Exception("Mismatch");144}145} catch (Exception e) {146throw new Exception("Error with base offset " + outOfs, e);147}148}149}150}151private static String byteToHex(ByteBuffer bb) {152StringBuilder s = new StringBuilder();153while (bb.remaining() > 0) {154s.append(String.format("%02x", bb.get()));155}156return s.toString();157}158}159160161