mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
updated additional Cipher tests for MemorySegment-backed ByteBuffers
This commit is contained in:
parent
aa8738447d
commit
e7e2dc05a2
@ -37,6 +37,7 @@ import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.lang.foreign.Arena;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
@ -48,7 +49,7 @@ import java.util.List;
|
||||
public class AEADBufferTest implements Cloneable {
|
||||
|
||||
// Data type for the operation
|
||||
enum dtype { BYTE, HEAP, DIRECT };
|
||||
enum dtype { BYTE, HEAP, DIRECT, MEMORY_SEGMENT };
|
||||
// Data map
|
||||
static HashMap<String, List<Data>> datamap = new HashMap<>();
|
||||
// List of enum values for order of operation
|
||||
@ -60,6 +61,7 @@ public class AEADBufferTest implements Cloneable {
|
||||
static final int REMAINDER = -1;
|
||||
|
||||
String algo;
|
||||
Arena arena;
|
||||
boolean same = true;
|
||||
int[] sizes;
|
||||
boolean incremental = false;
|
||||
@ -153,6 +155,14 @@ public class AEADBufferTest implements Cloneable {
|
||||
* specified, the last is a doFinal, the others are updates.
|
||||
*/
|
||||
AEADBufferTest(String algo, List<dtype> ops) {
|
||||
this(algo, ops, null);
|
||||
}
|
||||
|
||||
AEADBufferTest(String algo, List<dtype> ops, Arena arena) {
|
||||
if (arena == null && ops.contains(dtype.MEMORY_SEGMENT)) {
|
||||
throw new RuntimeException("Arena must not be null if ops contains MEMORY_SEGMENT");
|
||||
}
|
||||
this.arena = arena;
|
||||
this.algo = algo;
|
||||
this.ops = ops;
|
||||
theoreticalCheck = true;
|
||||
@ -433,6 +443,21 @@ public class AEADBufferTest implements Cloneable {
|
||||
rlen = cipher.update(b, out);
|
||||
ba.write(out.array(), outOfs, rlen);
|
||||
}
|
||||
case MEMORY_SEGMENT -> {
|
||||
ByteBuffer b = arena.allocate(plen + outOfs).asByteBuffer();
|
||||
b.position(outOfs);
|
||||
b.put(pt, dataoffset + inOfs, plen);
|
||||
b.flip();
|
||||
b.position(outOfs);
|
||||
ByteBuffer out = arena.allocate(olen).asByteBuffer();
|
||||
out.position(outOfs);
|
||||
rlen = cipher.update(b, out);
|
||||
byte[] o = new byte[rlen];
|
||||
out.flip();
|
||||
out.position(outOfs);
|
||||
out.get(o, 0, rlen);
|
||||
ba.write(o);
|
||||
}
|
||||
case DIRECT -> {
|
||||
ByteBuffer b = ByteBuffer.allocateDirect(plen + outOfs);
|
||||
b.position(outOfs);
|
||||
@ -488,6 +513,23 @@ public class AEADBufferTest implements Cloneable {
|
||||
rlen = cipher.doFinal(b, out);
|
||||
ba.write(out.array(), outOfs, rlen);
|
||||
}
|
||||
case MEMORY_SEGMENT -> {
|
||||
ByteBuffer b = arena.allocate(plen+inOfs).asByteBuffer();
|
||||
b.limit(b.capacity());
|
||||
b.position(inOfs);
|
||||
b.put(pt, dataoffset + inOfs, plen);
|
||||
b.flip();
|
||||
b.position(inOfs);
|
||||
ByteBuffer out = arena.allocate(olen).asByteBuffer();
|
||||
out.limit(out.capacity());
|
||||
out.position(outOfs);
|
||||
rlen = cipher.doFinal(b, out);
|
||||
byte[] o = new byte[rlen];
|
||||
out.flip();
|
||||
out.position(outOfs);
|
||||
out.get(o, 0, rlen);
|
||||
ba.write(o);
|
||||
}
|
||||
case DIRECT -> {
|
||||
ByteBuffer b = ByteBuffer.allocateDirect(plen + inOfs);
|
||||
b.limit(b.capacity());
|
||||
@ -577,6 +619,12 @@ public class AEADBufferTest implements Cloneable {
|
||||
bbin.put(data, 0, input.length + inOfs);
|
||||
bbin.flip();
|
||||
}
|
||||
case MEMORY_SEGMENT -> {
|
||||
bbin = arena.allocate(data.length).asByteBuffer();
|
||||
bbout = bbin.duplicate();
|
||||
bbin.put(data, 0, input.length + inOfs);
|
||||
bbin.flip();
|
||||
}
|
||||
}
|
||||
|
||||
// Set data limits for bytebuffers
|
||||
@ -594,7 +642,7 @@ public class AEADBufferTest implements Cloneable {
|
||||
rlen = cipher.update(data, dataoffset + inOfs, plen,
|
||||
data, len + outOfs);
|
||||
}
|
||||
case HEAP, DIRECT -> {
|
||||
case HEAP, DIRECT, MEMORY_SEGMENT -> {
|
||||
theorticallen = bbin.remaining() - (d.blockSize > 0 ?
|
||||
bbin.remaining() % d.blockSize : 0);
|
||||
rlen = cipher.update(bbin, bbout);
|
||||
@ -623,7 +671,7 @@ public class AEADBufferTest implements Cloneable {
|
||||
plen, data, len + outOfs);
|
||||
out = Arrays.copyOfRange(data, 0,len + rlen + outOfs);
|
||||
}
|
||||
case HEAP, DIRECT -> {
|
||||
case HEAP, DIRECT, MEMORY_SEGMENT -> {
|
||||
rlen = cipher.doFinal(bbin, bbout);
|
||||
bbout.flip();
|
||||
out = new byte[bbout.remaining()];
|
||||
@ -660,193 +708,252 @@ public class AEADBufferTest implements Cloneable {
|
||||
|
||||
initTest();
|
||||
|
||||
// **** GCM Tests
|
||||
try(Arena arena = Arena.ofConfined()) {
|
||||
// **** GCM Tests
|
||||
|
||||
// Test single byte array
|
||||
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE)));
|
||||
// Test update-doFinal with byte arrays
|
||||
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE, dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE, dtype.BYTE)));
|
||||
// Test update-update-doFinal with byte arrays
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)));
|
||||
// Test single byte array
|
||||
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE)));
|
||||
// Test update-doFinal with byte arrays
|
||||
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE, dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE, dtype.BYTE)));
|
||||
// Test update-update-doFinal with byte arrays
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)));
|
||||
|
||||
// Test single heap bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP)));
|
||||
// Test update-doFinal with heap bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.HEAP, dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP, dtype.HEAP)));
|
||||
// Test update-update-doFinal with heap bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)));
|
||||
// Test single heap bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP)));
|
||||
// Test update-doFinal with heap bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.HEAP, dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP, dtype.HEAP)));
|
||||
// Test update-update-doFinal with heap bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)));
|
||||
|
||||
// Test single direct bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.DIRECT)));
|
||||
// Test update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT)));
|
||||
// Test update-update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)));
|
||||
// Test single direct bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.DIRECT)));
|
||||
// Test update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT)));
|
||||
// Test update-update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)));
|
||||
|
||||
// Test update-update-doFinal with byte arrays and preset data sizes
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).dataSegments(
|
||||
new int[] { 1, 1, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test single memory segment bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.MEMORY_SEGMENT), arena).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding", List.of(dtype.MEMORY_SEGMENT), arena));
|
||||
// Test update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT), arena).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT), arena));
|
||||
// Test update-update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT), arena).test();
|
||||
offsetTests(new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT), arena));
|
||||
|
||||
// Test update-doFinal with a byte array and a direct bytebuffer
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.DIRECT)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-doFinal with a byte array and heap and direct bytebuffer
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.HEAP, dtype.DIRECT)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-update-doFinal with byte arrays and preset data sizes
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).dataSegments(
|
||||
new int[]{1, 1, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
// Test update-doFinal with a direct bytebuffer and a byte array.
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-doFinal with a byte array and a direct bytebuffer
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.DIRECT)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-doFinal with a byte array and heap and direct bytebuffer
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.HEAP, dtype.DIRECT)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-doFinal with a byte array and heap and direct and memory segment bytebuffer
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.HEAP, dtype.DIRECT, dtype.MEMORY_SEGMENT), arena).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
// Test update-doFinal with a direct bytebuffer and a byte array with
|
||||
// preset data sizes.
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly().
|
||||
dataSegments(new int[] { 20, AEADBufferTest.REMAINDER });
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-update-doFinal with a direct and heap bytebuffer and a
|
||||
// byte array with preset data sizes.
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.BYTE, dtype.HEAP)).
|
||||
differentBufferOnly().dataSet(5).
|
||||
dataSegments(new int[] { 5000, 1000, AEADBufferTest.REMAINDER });
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-doFinal with a direct bytebuffer and a byte array.
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
// Test update-update-doFinal with byte arrays, incrementing through
|
||||
// every data size combination for the Data set 0
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).incrementalSegments().
|
||||
dataSet(0).test();
|
||||
// Test update-update-doFinal with direct bytebuffers, incrementing through
|
||||
// every data size combination for the Data set 0
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
|
||||
incrementalSegments().dataSet(0).test();
|
||||
// Test update-doFinal with a direct bytebuffer and a byte array with
|
||||
// preset data sizes.
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly().
|
||||
dataSegments(new int[]{20, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-update-doFinal with a direct and heap bytebuffer and a
|
||||
// byte array with preset data sizes.
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.BYTE, dtype.HEAP)).
|
||||
differentBufferOnly().dataSet(5).
|
||||
dataSegments(new int[]{5000, 1000, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-update-doFinal with a direct and heap and memory segment
|
||||
// bytebuffer and a byte array with preset data sizes.
|
||||
t = new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.BYTE, dtype.HEAP, dtype.MEMORY_SEGMENT), arena).
|
||||
differentBufferOnly().dataSet(5).
|
||||
dataSegments(new int[]{5000, 1000, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
|
||||
dataSegments(new int[] { 49, 0, 2 }).dataSet(0).test();
|
||||
// Test update-update-doFinal with byte arrays, incrementing through
|
||||
// every data size combination for the Data set 0
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).incrementalSegments().
|
||||
dataSet(0).test();
|
||||
// Test update-update-doFinal with direct bytebuffers, incrementing through
|
||||
// every data size combination for the Data set 0
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
|
||||
incrementalSegments().dataSet(0).test();
|
||||
|
||||
// **** CC20P1305 Tests
|
||||
new AEADBufferTest("AES/GCM/NoPadding",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
|
||||
dataSegments(new int[]{49, 0, 2}).dataSet(0).test();
|
||||
|
||||
// Test single byte array
|
||||
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE)));
|
||||
// Test update-doFinal with byte arrays
|
||||
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE, dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE, dtype.BYTE)));
|
||||
// Test update-update-doFinal with byte arrays
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)));
|
||||
// **** CC20P1305 Tests
|
||||
|
||||
// Test single heap bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP)));
|
||||
// Test update-doFinal with heap bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.HEAP, dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP, dtype.HEAP)));
|
||||
// Test update-update-doFinal with heap bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)));
|
||||
// Test single byte array
|
||||
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE)));
|
||||
// Test update-doFinal with byte arrays
|
||||
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE, dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE, dtype.BYTE)));
|
||||
// Test update-update-doFinal with byte arrays
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)));
|
||||
|
||||
// Test single direct bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.DIRECT)));
|
||||
// Test update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT)));
|
||||
// Test update-update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)));
|
||||
// Test single heap bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP)));
|
||||
// Test update-doFinal with heap bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.HEAP, dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP, dtype.HEAP)));
|
||||
// Test update-update-doFinal with heap bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.HEAP, dtype.HEAP, dtype.HEAP)));
|
||||
|
||||
// Test update-update-doFinal with byte arrays and preset data sizes
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).dataSegments(
|
||||
new int[] { 1, 1, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test single direct bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.DIRECT)));
|
||||
// Test update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT)));
|
||||
// Test update-update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)));
|
||||
|
||||
// Test update-doFinal with a byte array and a direct bytebuffer
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.DIRECT)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-doFinal with a byte array and heap and direct bytebuffer
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.HEAP, dtype.DIRECT)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test single direct bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.MEMORY_SEGMENT), arena).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305", List.of(dtype.MEMORY_SEGMENT), arena));
|
||||
// Test update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT), arena).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT), arena));
|
||||
// Test update-update-doFinal with direct bytebuffer
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT), arena).test();
|
||||
offsetTests(new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT, dtype.MEMORY_SEGMENT), arena));
|
||||
|
||||
// Test update-doFinal with a direct bytebuffer and a byte array.
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-update-doFinal with byte arrays and preset data sizes
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).dataSegments(
|
||||
new int[]{1, 1, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
// Test update-doFinal with a direct bytebuffer and a byte array with
|
||||
// preset data sizes.
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly().
|
||||
dataSegments(new int[] { 20, AEADBufferTest.REMAINDER });
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-update-doFinal with a direct and heap bytebuffer and a
|
||||
// byte array with preset data sizes.
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.BYTE, dtype.HEAP)).
|
||||
differentBufferOnly().dataSet(1).
|
||||
dataSegments(new int[] { 5000, 1000, AEADBufferTest.REMAINDER });
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-doFinal with a byte array and a direct bytebuffer
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.DIRECT)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-doFinal with a byte array and heap and direct bytebuffer
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.HEAP, dtype.DIRECT)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
// Test update-update-doFinal with byte arrays, incrementing through
|
||||
// every data size combination for the Data set 0
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).incrementalSegments().
|
||||
dataSet(0).test();
|
||||
// Test update-update-doFinal with direct bytebuffers, incrementing through
|
||||
// every data size combination for the Data set 0
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
|
||||
incrementalSegments().dataSet(0).test();
|
||||
// Test update-doFinal with a byte array and heap and direct and memory segment bytebuffer
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.HEAP, dtype.DIRECT, dtype.MEMORY_SEGMENT), arena).
|
||||
differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
|
||||
dataSegments(new int[] { 49, 0, 2 }).dataSet(0).test();
|
||||
// Test update-doFinal with a direct bytebuffer and a byte array.
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly();
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
// Test update-doFinal with a direct bytebuffer and a byte array with
|
||||
// preset data sizes.
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.BYTE)).differentBufferOnly().
|
||||
dataSegments(new int[]{20, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
// Test update-update-doFinal with a direct and heap bytebuffer and a
|
||||
// byte array with preset data sizes.
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.BYTE, dtype.HEAP)).
|
||||
differentBufferOnly().dataSet(1).
|
||||
dataSegments(new int[]{5000, 1000, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
// Test update-update-doFinal with a direct and heap and memory segment
|
||||
// bytebuffer and a byte array with preset data sizes.
|
||||
t = new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.BYTE, dtype.HEAP, dtype.MEMORY_SEGMENT), arena).
|
||||
differentBufferOnly().dataSet(1).
|
||||
dataSegments(new int[]{5000, 1000, AEADBufferTest.REMAINDER});
|
||||
t.clone().test();
|
||||
offsetTests(t.clone());
|
||||
|
||||
// Test update-update-doFinal with byte arrays, incrementing through
|
||||
// every data size combination for the Data set 0
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.BYTE, dtype.BYTE, dtype.BYTE)).incrementalSegments().
|
||||
dataSet(0).test();
|
||||
// Test update-update-doFinal with direct bytebuffers, incrementing through
|
||||
// every data size combination for the Data set 0
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
|
||||
incrementalSegments().dataSet(0).test();
|
||||
|
||||
new AEADBufferTest("ChaCha20-Poly1305",
|
||||
List.of(dtype.DIRECT, dtype.DIRECT, dtype.DIRECT)).
|
||||
dataSegments(new int[]{49, 0, 2}).dataSet(0).test();
|
||||
}
|
||||
}
|
||||
|
||||
// Test data
|
||||
|
||||
@ -25,6 +25,7 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.ShortBufferException;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.lang.foreign.Arena;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HexFormat;
|
||||
@ -117,6 +118,10 @@ public class GCMShortBuffer {
|
||||
new GCMShortBuffer(new byte[50]);
|
||||
new GCMShortBuffer(ByteBuffer.allocate(13));
|
||||
new GCMShortBuffer(ByteBuffer.allocate(50));
|
||||
try(Arena arena = Arena.ofConfined()) {
|
||||
new GCMShortBuffer(arena.allocate(13).asByteBuffer());
|
||||
new GCMShortBuffer(arena.allocate(50).asByteBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
* @summary ArithmeticException in GaloisCounterMode
|
||||
*/
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.crypto.AEADBadTagException;
|
||||
@ -50,6 +51,9 @@ public class GCMShortInput {
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, params);
|
||||
try {
|
||||
cipher.doFinal(ByteBuffer.allocate(0), ByteBuffer.allocate(0));
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
cipher.doFinal(arena.allocate(0).asByteBuffer(), arena.allocate(0).asByteBuffer());
|
||||
}
|
||||
throw new AssertionError("AEADBadTagException expected");
|
||||
} catch (AEADBadTagException e) {
|
||||
// expected
|
||||
|
||||
@ -25,6 +25,7 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.lang.foreign.Arena;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
|
||||
@ -77,97 +78,115 @@ public class OverlapByteBuffer {
|
||||
|
||||
void test() throws Exception {
|
||||
// Output offset from the baseBuf
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (outOfs = -1; outOfs <= 1; outOfs++) {
|
||||
try(Arena arena = Arena.ofConfined()) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (outOfs = -1; outOfs <= 1; outOfs++) {
|
||||
|
||||
Cipher cipher = Cipher.getInstance(algorithm);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, params);
|
||||
Cipher cipher = Cipher.getInstance(algorithm);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, params);
|
||||
|
||||
// Offset on the particular ByteBuffer (aka position())
|
||||
int inOfsInBuf = 1;
|
||||
int outOfsInBuf = inOfsInBuf + outOfs;
|
||||
int sliceLen = cipher.getOutputSize(baseBuf.length);
|
||||
int bufferSize = sliceLen + Math.max(inOfsInBuf, outOfsInBuf);
|
||||
byte[] buffer;
|
||||
// Create overlapping input and output buffers
|
||||
switch (i) {
|
||||
case 0 -> {
|
||||
buffer = new byte[bufferSize];
|
||||
output = ByteBuffer.wrap(buffer, outOfsInBuf, sliceLen).
|
||||
slice();
|
||||
input = ByteBuffer.wrap(buffer, inOfsInBuf, sliceLen).
|
||||
slice();
|
||||
System.out.println("Using array-backed ByteBuffer");
|
||||
in = input.duplicate();
|
||||
// Offset on the particular ByteBuffer (aka position())
|
||||
int inOfsInBuf = 1;
|
||||
int outOfsInBuf = inOfsInBuf + outOfs;
|
||||
int sliceLen = cipher.getOutputSize(baseBuf.length);
|
||||
int bufferSize = sliceLen + Math.max(inOfsInBuf, outOfsInBuf);
|
||||
byte[] buffer;
|
||||
// Create overlapping input and output buffers
|
||||
switch (i) {
|
||||
case 0 -> {
|
||||
buffer = new byte[bufferSize];
|
||||
output = ByteBuffer.wrap(buffer, outOfsInBuf, sliceLen).
|
||||
slice();
|
||||
input = ByteBuffer.wrap(buffer, inOfsInBuf, sliceLen).
|
||||
slice();
|
||||
System.out.println("Using array-backed ByteBuffer");
|
||||
in = input.duplicate();
|
||||
}
|
||||
case 1 -> {
|
||||
buffer = new byte[bufferSize];
|
||||
output = ByteBuffer.wrap(buffer, outOfsInBuf, sliceLen).
|
||||
slice();
|
||||
input = ByteBuffer.wrap(buffer, inOfsInBuf, sliceLen).
|
||||
slice();
|
||||
|
||||
System.out.println("Using read-only array-backed " +
|
||||
"ByteBuffer");
|
||||
in = input.asReadOnlyBuffer();
|
||||
}
|
||||
case 2 -> {
|
||||
System.out.println("Using direct ByteBuffer");
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize);
|
||||
output = buf.duplicate();
|
||||
output.position(outOfsInBuf);
|
||||
output.limit(sliceLen + outOfsInBuf);
|
||||
output = output.slice();
|
||||
|
||||
input = buf.duplicate();
|
||||
input.position(inOfsInBuf);
|
||||
input.limit(sliceLen + inOfsInBuf);
|
||||
input = input.slice();
|
||||
|
||||
in = input.duplicate();
|
||||
}
|
||||
|
||||
case 3 -> {
|
||||
System.out.println("Using memory-segment ByteBuffer");
|
||||
ByteBuffer buf = arena.allocate(bufferSize).asByteBuffer();
|
||||
output = buf.duplicate();
|
||||
output.position(outOfsInBuf);
|
||||
output.limit(sliceLen + outOfsInBuf);
|
||||
output = output.slice();
|
||||
|
||||
input = buf.duplicate();
|
||||
input.position(inOfsInBuf);
|
||||
input.limit(sliceLen + inOfsInBuf);
|
||||
input = input.slice();
|
||||
|
||||
in = input.duplicate();
|
||||
}
|
||||
default -> throw new Exception("Unknown index " + i);
|
||||
}
|
||||
case 1 -> {
|
||||
buffer = new byte[bufferSize];
|
||||
output = ByteBuffer.wrap(buffer, outOfsInBuf, sliceLen).
|
||||
slice();
|
||||
input = ByteBuffer.wrap(buffer, inOfsInBuf, sliceLen).
|
||||
slice();
|
||||
|
||||
System.out.println("Using read-only array-backed " +
|
||||
"ByteBuffer");
|
||||
in = input.asReadOnlyBuffer();
|
||||
}
|
||||
case 2 -> {
|
||||
System.out.println("Using direct ByteBuffer");
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize);
|
||||
output = buf.duplicate();
|
||||
output.position(outOfsInBuf);
|
||||
output.limit(sliceLen + outOfsInBuf);
|
||||
output = output.slice();
|
||||
System.out.println("inOfsInBuf = " + inOfsInBuf);
|
||||
System.out.println("outOfsInBuf = " + outOfsInBuf);
|
||||
|
||||
input = buf.duplicate();
|
||||
input.position(inOfsInBuf);
|
||||
input.limit(sliceLen + inOfsInBuf);
|
||||
input = input.slice();
|
||||
|
||||
in = input.duplicate();
|
||||
}
|
||||
default -> throw new Exception("Unknown index " + i);
|
||||
}
|
||||
|
||||
System.out.println("inOfsInBuf = " + inOfsInBuf);
|
||||
System.out.println("outOfsInBuf = " + outOfsInBuf);
|
||||
|
||||
// Copy data into shared buffer
|
||||
input.put(baseBuf);
|
||||
input.flip();
|
||||
in.limit(input.limit());
|
||||
|
||||
try {
|
||||
int ctSize = cipher.doFinal(in, output);
|
||||
|
||||
// Get ready to decrypt
|
||||
byte[] tmp = new byte[ctSize];
|
||||
output.flip();
|
||||
output.get(tmp);
|
||||
output.clear();
|
||||
|
||||
input.clear();
|
||||
input.put(tmp);
|
||||
// Copy data into shared buffer
|
||||
input.put(baseBuf);
|
||||
input.flip();
|
||||
|
||||
in.clear();
|
||||
in.limit(input.limit());
|
||||
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, params);
|
||||
cipher.doFinal(in, output);
|
||||
try {
|
||||
int ctSize = cipher.doFinal(in, output);
|
||||
|
||||
output.flip();
|
||||
ByteBuffer b = ByteBuffer.wrap(baseBuf);
|
||||
if (b.compareTo(output) != 0) {
|
||||
System.err.println(
|
||||
"\nresult (" + output + "):\n" +
|
||||
byteToHex(output) +
|
||||
"\nexpected (" + b + "):\n" +
|
||||
byteToHex(b));
|
||||
throw new Exception("Mismatch");
|
||||
// Get ready to decrypt
|
||||
byte[] tmp = new byte[ctSize];
|
||||
output.flip();
|
||||
output.get(tmp);
|
||||
output.clear();
|
||||
|
||||
input.clear();
|
||||
input.put(tmp);
|
||||
input.flip();
|
||||
|
||||
in.clear();
|
||||
in.limit(input.limit());
|
||||
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, params);
|
||||
cipher.doFinal(in, output);
|
||||
|
||||
output.flip();
|
||||
ByteBuffer b = ByteBuffer.wrap(baseBuf);
|
||||
if (b.compareTo(output) != 0) {
|
||||
System.err.println(
|
||||
"\nresult (" + output + "):\n" +
|
||||
byteToHex(output) +
|
||||
"\nexpected (" + b + "):\n" +
|
||||
byteToHex(b));
|
||||
throw new Exception("Mismatch");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Error with base offset " + outOfs, e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Error with base offset " + outOfs, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.Provider;
|
||||
@ -217,17 +218,27 @@ public class SameBuffer {
|
||||
// prepare byte buffer contained AAD and plain text
|
||||
int bufSize = AADLength + offset + outputLength;
|
||||
byte[] AAD_and_Text = Helper.generateBytes(bufSize);
|
||||
ByteBuffer AAD_and_Text_Buf = ByteBuffer.allocate(bufSize);
|
||||
AAD_and_Text_Buf.put(AAD_and_Text, 0, AAD_and_Text.length);
|
||||
|
||||
// do test
|
||||
runGCMWithSameBuffer(Cipher.ENCRYPT_MODE, AAD_and_Text_Buf, offset,
|
||||
textLength, params);
|
||||
int tagLength = c.getParameters()
|
||||
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
|
||||
AAD_and_Text_Buf.limit(AADLength + offset + textLength + tagLength);
|
||||
runGCMWithSameBuffer(Cipher.DECRYPT_MODE, AAD_and_Text_Buf, offset,
|
||||
textLength + tagLength, params);
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
ByteBuffer AAD_and_Text_Buf = switch (i) {
|
||||
case 0 -> ByteBuffer.allocate(bufSize);
|
||||
case 1 -> arena.allocate(bufSize).asByteBuffer();
|
||||
default -> throw new RuntimeException("Unknown test case");
|
||||
};
|
||||
|
||||
AAD_and_Text_Buf.put(AAD_and_Text, 0, AAD_and_Text.length);
|
||||
|
||||
// do test
|
||||
runGCMWithSameBuffer(Cipher.ENCRYPT_MODE, AAD_and_Text_Buf, offset,
|
||||
textLength, params);
|
||||
int tagLength = c.getParameters()
|
||||
.getParameterSpec(GCMParameterSpec.class).getTLen() / 8;
|
||||
AAD_and_Text_Buf.limit(AADLength + offset + textLength + tagLength);
|
||||
runGCMWithSameBuffer(Cipher.DECRYPT_MODE, AAD_and_Text_Buf, offset,
|
||||
textLength + tagLength, params);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
*/
|
||||
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.*;
|
||||
import javax.crypto.*;
|
||||
@ -43,6 +44,8 @@ import java.util.*;
|
||||
|
||||
public class TestKATForGCM {
|
||||
|
||||
enum BufferType { DIRECT, HEAP, MEMORY_SEGMENT };
|
||||
|
||||
// Utility methods
|
||||
private static byte[] HexToBytes(String hexVal) {
|
||||
if (hexVal == null) return new byte[0];
|
||||
@ -320,7 +323,7 @@ public class TestKATForGCM {
|
||||
}
|
||||
}
|
||||
|
||||
void executeByteBuffer(TestVector tv, boolean direct, int offset) throws Exception {
|
||||
void executeByteBuffer(TestVector tv, BufferType bufferType, int offset) throws Exception {
|
||||
Cipher c = Cipher.getInstance("AES/GCM/NoPadding",
|
||||
System.getProperty("test.provider.name", "SunJCE"));
|
||||
|
||||
@ -328,76 +331,92 @@ public class TestKATForGCM {
|
||||
ByteBuffer ctdst;
|
||||
ByteBuffer ptdst;
|
||||
|
||||
if (direct) {
|
||||
System.out.print("Test #" + tv.id + ": ByteBuffer Direct.");
|
||||
src = ByteBuffer.allocateDirect(tv.plainText.length + offset);
|
||||
ctdst = ByteBuffer.allocateDirect(tv.cipherText.length + tv.tag.length + offset);
|
||||
ptdst = ByteBuffer.allocateDirect(tv.plainText.length + offset);
|
||||
} else {
|
||||
System.out.print("Test #" + tv.id + ": ByteBuffer Heap.");
|
||||
src = ByteBuffer.allocate(tv.plainText.length + offset);
|
||||
ctdst = ByteBuffer.allocate(tv.cipherText.length + tv.tag.length + offset);
|
||||
ptdst = ByteBuffer.allocate(tv.plainText.length + offset);
|
||||
}
|
||||
|
||||
byte[] plainText;
|
||||
|
||||
if (offset > 0) {
|
||||
System.out.println(" offset = " + offset);
|
||||
plainText = new byte[tv.plainText.length + offset];
|
||||
System.arraycopy(tv.plainText, 0, plainText, offset,
|
||||
tv.plainText.length);
|
||||
} else {
|
||||
System.out.println();
|
||||
plainText = tv.plainText;
|
||||
}
|
||||
|
||||
src.put(plainText);
|
||||
src.position(offset);
|
||||
ctdst.position(offset);
|
||||
ctdst.mark();
|
||||
ptdst.position(offset);
|
||||
ptdst.mark();
|
||||
|
||||
try {
|
||||
c.init(Cipher.ENCRYPT_MODE, tv.key, tv.spec);
|
||||
c.updateAAD(tv.aad);
|
||||
c.doFinal(src, ctdst);
|
||||
|
||||
ctdst.reset();
|
||||
ByteBuffer tag = ctdst.duplicate();
|
||||
tag.position(tag.limit() - tv.tag.length);
|
||||
|
||||
c.init(Cipher.DECRYPT_MODE, tv.key, tv.spec);
|
||||
c.updateAAD(tv.aad);
|
||||
c.doFinal(ctdst, ptdst); // should fail if tag mismatched
|
||||
|
||||
ptdst.reset();
|
||||
// check encryption/decryption results just to be sure
|
||||
if (ptdst.compareTo(ByteBuffer.wrap(tv.plainText)) != 0) {
|
||||
System.out.println("\t PlainText diff failed for test# " + tv.id);
|
||||
testFailed = true;
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
switch (bufferType) {
|
||||
case DIRECT: {
|
||||
System.out.print("Test #" + tv.id + ": ByteBuffer Direct.");
|
||||
src = ByteBuffer.allocateDirect(tv.plainText.length + offset);
|
||||
ctdst = ByteBuffer.allocateDirect(tv.cipherText.length + tv.tag.length + offset);
|
||||
ptdst = ByteBuffer.allocateDirect(tv.plainText.length + offset);
|
||||
}
|
||||
break;
|
||||
case HEAP: {
|
||||
System.out.print("Test #" + tv.id + ": ByteBuffer Heap.");
|
||||
src = ByteBuffer.allocate(tv.plainText.length + offset);
|
||||
ctdst = ByteBuffer.allocate(tv.cipherText.length + tv.tag.length + offset);
|
||||
ptdst = ByteBuffer.allocate(tv.plainText.length + offset);
|
||||
}
|
||||
break;
|
||||
case MEMORY_SEGMENT: {
|
||||
System.out.print("Test #" + tv.id + ": ByteBuffer MemorySegment.");
|
||||
src = arena.allocate(tv.plainText.length + offset).asByteBuffer();
|
||||
ctdst = arena.allocate(tv.cipherText.length + tv.tag.length + offset).asByteBuffer();
|
||||
ptdst = arena.allocate(tv.plainText.length + offset).asByteBuffer();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unsupported buffer type " + bufferType);
|
||||
}
|
||||
|
||||
ctdst.reset();
|
||||
ctdst.limit(ctdst.limit() - tv.tag.length);
|
||||
if (ctdst.compareTo(ByteBuffer.wrap(tv.cipherText)) != 0) {
|
||||
System.out.println("\t CipherText diff failed for test# " + tv.id);
|
||||
testFailed = true;
|
||||
byte[] plainText;
|
||||
|
||||
if (offset > 0) {
|
||||
System.out.println(" offset = " + offset);
|
||||
plainText = new byte[tv.plainText.length + offset];
|
||||
System.arraycopy(tv.plainText, 0, plainText, offset,
|
||||
tv.plainText.length);
|
||||
} else {
|
||||
System.out.println();
|
||||
plainText = tv.plainText;
|
||||
}
|
||||
|
||||
int mismatch = 0;
|
||||
for (int i = 0; i < tv.tag.length; i++) {
|
||||
mismatch |= tag.get() ^ tv.tag[i];
|
||||
src.put(plainText);
|
||||
src.position(offset);
|
||||
ctdst.position(offset);
|
||||
ctdst.mark();
|
||||
ptdst.position(offset);
|
||||
ptdst.mark();
|
||||
|
||||
try {
|
||||
c.init(Cipher.ENCRYPT_MODE, tv.key, tv.spec);
|
||||
c.updateAAD(tv.aad);
|
||||
c.doFinal(src, ctdst);
|
||||
|
||||
ctdst.reset();
|
||||
ByteBuffer tag = ctdst.duplicate();
|
||||
tag.position(tag.limit() - tv.tag.length);
|
||||
|
||||
c.init(Cipher.DECRYPT_MODE, tv.key, tv.spec);
|
||||
c.updateAAD(tv.aad);
|
||||
c.doFinal(ctdst, ptdst); // should fail if tag mismatched
|
||||
|
||||
ptdst.reset();
|
||||
// check encryption/decryption results just to be sure
|
||||
if (ptdst.compareTo(ByteBuffer.wrap(tv.plainText)) != 0) {
|
||||
System.out.println("\t PlainText diff failed for test# " + tv.id);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
ctdst.reset();
|
||||
ctdst.limit(ctdst.limit() - tv.tag.length);
|
||||
if (ctdst.compareTo(ByteBuffer.wrap(tv.cipherText)) != 0) {
|
||||
System.out.println("\t CipherText diff failed for test# " + tv.id);
|
||||
testFailed = true;
|
||||
}
|
||||
|
||||
int mismatch = 0;
|
||||
for (int i = 0; i < tv.tag.length; i++) {
|
||||
mismatch |= tag.get() ^ tv.tag[i];
|
||||
}
|
||||
if (mismatch != 0) {
|
||||
System.out.println("\t Tag diff failed for test# " + tv.id);
|
||||
testFailed = true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// continue testing other test vectors
|
||||
System.out.println("\t Failed Test Vector ( #" + tv.id + ") : " + tv);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
if (mismatch != 0) {
|
||||
System.out.println("\t Tag diff failed for test# " + tv.id);
|
||||
testFailed = true;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// continue testing other test vectors
|
||||
System.out.println("\t Failed Test Vector ( #" + tv.id + ") : " + tv);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@ -405,10 +424,12 @@ public class TestKATForGCM {
|
||||
TestKATForGCM test = new TestKATForGCM();
|
||||
for (TestVector tv : testValues) {
|
||||
test.executeArray(tv);
|
||||
test.executeByteBuffer(tv, false, 0);
|
||||
test.executeByteBuffer(tv, true, 0);
|
||||
test.executeByteBuffer(tv, false, 2);
|
||||
test.executeByteBuffer(tv, true, 2);
|
||||
test.executeByteBuffer(tv, BufferType.HEAP, 0);
|
||||
test.executeByteBuffer(tv, BufferType.DIRECT, 0);
|
||||
test.executeByteBuffer(tv, BufferType.MEMORY_SEGMENT, 0);
|
||||
test.executeByteBuffer(tv, BufferType.HEAP, 2);
|
||||
test.executeByteBuffer(tv, BufferType.DIRECT, 2);
|
||||
test.executeByteBuffer(tv, BufferType.MEMORY_SEGMENT, 2);
|
||||
}
|
||||
if (!testFailed) {
|
||||
System.out.println("Tests passed");
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
* @summary ChaCha20 Cipher Implementation (KAT)
|
||||
*/
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.util.*;
|
||||
import java.security.GeneralSecurityException;
|
||||
import javax.crypto.Cipher;
|
||||
@ -200,7 +201,13 @@ public class ChaCha20KAT {
|
||||
for (TestData test : testList) {
|
||||
System.out.println("*** Test " + ++testNumber + ": " +
|
||||
test.testName);
|
||||
if (runByteBuffer(test)) {
|
||||
if (runByteBuffer(test, true)) {
|
||||
testsPassed++;
|
||||
}
|
||||
|
||||
System.out.println("*** Test " + ++testNumber + ": " +
|
||||
test.testName);
|
||||
if (runByteBuffer(test, false)) {
|
||||
testsPassed++;
|
||||
}
|
||||
}
|
||||
@ -360,7 +367,7 @@ public class ChaCha20KAT {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private static boolean runByteBuffer(TestData testData)
|
||||
private static boolean runByteBuffer(TestData testData, boolean heap)
|
||||
throws GeneralSecurityException {
|
||||
boolean encRes = false;
|
||||
boolean decRes = false;
|
||||
@ -372,48 +379,63 @@ public class ChaCha20KAT {
|
||||
testData.nonce, testData.counter);
|
||||
mambo.init(Cipher.ENCRYPT_MODE, mamboKey, mamboSpec);
|
||||
|
||||
ByteBuffer bbIn = ByteBuffer.wrap(testData.input);
|
||||
ByteBuffer bbEncOut = ByteBuffer.allocate(
|
||||
mambo.getOutputSize(testData.input.length));
|
||||
ByteBuffer bbExpOut = ByteBuffer.wrap(testData.expOutput);
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
ByteBuffer bbIn = ByteBuffer.wrap(testData.input);
|
||||
ByteBuffer bbEncOut;
|
||||
ByteBuffer bbExpOut = ByteBuffer.wrap(testData.expOutput);
|
||||
if (heap) {
|
||||
bbEncOut = ByteBuffer.allocate(
|
||||
mambo.getOutputSize(testData.input.length));
|
||||
} else {
|
||||
bbEncOut = arena.allocate(
|
||||
mambo.getOutputSize(testData.input.length))
|
||||
.asByteBuffer();
|
||||
}
|
||||
|
||||
mambo.doFinal(bbIn, bbEncOut);
|
||||
bbIn.rewind();
|
||||
bbEncOut.rewind();
|
||||
mambo.doFinal(bbIn, bbEncOut);
|
||||
bbIn.rewind();
|
||||
bbEncOut.rewind();
|
||||
|
||||
if (bbEncOut.compareTo(bbExpOut) != 0) {
|
||||
System.out.println("ERROR - Output Mismatch!");
|
||||
System.out.println("Expected:\n" +
|
||||
dumpHexBytes(bbExpOut, 16, "\n", " "));
|
||||
System.out.println("Actual:\n" +
|
||||
dumpHexBytes(bbEncOut, 16, "\n", " "));
|
||||
System.out.println();
|
||||
} else {
|
||||
encRes = true;
|
||||
if (bbEncOut.compareTo(bbExpOut) != 0) {
|
||||
System.out.println("ERROR - Output Mismatch!");
|
||||
System.out.println("Expected:\n" +
|
||||
dumpHexBytes(bbExpOut, 16, "\n", " "));
|
||||
System.out.println("Actual:\n" +
|
||||
dumpHexBytes(bbEncOut, 16, "\n", " "));
|
||||
System.out.println();
|
||||
} else {
|
||||
encRes = true;
|
||||
}
|
||||
|
||||
// Decrypt the result of the encryption operation
|
||||
mambo = Cipher.getInstance("ChaCha20");
|
||||
mambo.init(Cipher.DECRYPT_MODE, mamboKey, mamboSpec);
|
||||
System.out.print("Decrypt - ");
|
||||
ByteBuffer bbDecOut;
|
||||
if (heap) {
|
||||
bbDecOut = ByteBuffer.allocate(
|
||||
mambo.getOutputSize(bbEncOut.remaining()));
|
||||
} else {
|
||||
bbDecOut = arena.allocate(
|
||||
mambo.getOutputSize(bbEncOut.remaining()))
|
||||
.asByteBuffer();
|
||||
}
|
||||
|
||||
mambo.doFinal(bbEncOut, bbDecOut);
|
||||
bbEncOut.rewind();
|
||||
bbDecOut.rewind();
|
||||
|
||||
if (bbDecOut.compareTo(bbIn) != 0) {
|
||||
System.out.println("ERROR - Output Mismatch!");
|
||||
System.out.println("Expected:\n" +
|
||||
dumpHexBytes(bbIn, 16, "\n", " "));
|
||||
System.out.println("Actual:\n" +
|
||||
dumpHexBytes(bbDecOut, 16, "\n", " "));
|
||||
System.out.println();
|
||||
} else {
|
||||
decRes = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypt the result of the encryption operation
|
||||
mambo = Cipher.getInstance("ChaCha20");
|
||||
mambo.init(Cipher.DECRYPT_MODE, mamboKey, mamboSpec);
|
||||
System.out.print("Decrypt - ");
|
||||
ByteBuffer bbDecOut = ByteBuffer.allocate(
|
||||
mambo.getOutputSize(bbEncOut.remaining()));
|
||||
|
||||
mambo.doFinal(bbEncOut, bbDecOut);
|
||||
bbEncOut.rewind();
|
||||
bbDecOut.rewind();
|
||||
|
||||
if (bbDecOut.compareTo(bbIn) != 0) {
|
||||
System.out.println("ERROR - Output Mismatch!");
|
||||
System.out.println("Expected:\n" +
|
||||
dumpHexBytes(bbIn, 16, "\n", " "));
|
||||
System.out.println("Actual:\n" +
|
||||
dumpHexBytes(bbDecOut, 16, "\n", " "));
|
||||
System.out.println();
|
||||
} else {
|
||||
decRes = true;
|
||||
}
|
||||
|
||||
return (encRes && decRes);
|
||||
}
|
||||
|
||||
|
||||
@ -21,12 +21,14 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Random;
|
||||
import java.util.function.Function;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
@ -119,17 +121,33 @@ public class PBMacBuffer {
|
||||
theMac.init(key);
|
||||
|
||||
// Do large ByteBuffer test case
|
||||
if (!largeByteBufferTest(theMac)) {
|
||||
if (!largeByteBufferTest(theMac, this::generateRandomByteBuffer)) {
|
||||
System.out.println("Large ByteBuffer test case failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do empty ByteBuffer test case
|
||||
if (!emptyByteBufferTest(theMac)) {
|
||||
if (!emptyByteBufferTest(theMac, this::generateRandomByteBuffer)) {
|
||||
System.out.println("Empty ByteBuffer test case failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
try(Arena arena = Arena.ofConfined()) {
|
||||
// Do large ByteBuffer test case
|
||||
if (!largeByteBufferTest(theMac,
|
||||
(size) -> arena.allocate(size).asByteBuffer())) {
|
||||
System.out.println("Large MemorySegment ByteBuffer test case failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do empty ByteBuffer test case
|
||||
if (!emptyByteBufferTest(theMac,
|
||||
(size) -> arena.allocate(size).asByteBuffer())) {
|
||||
System.out.println("Empty MemorySegment ByteBuffer test case failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Do null ByteBuffer test case
|
||||
if (!nullByteBufferTest(theMac)) {
|
||||
System.out.println("NULL ByteBuffer test case failed.");
|
||||
@ -148,8 +166,9 @@ public class PBMacBuffer {
|
||||
* @param theMac MAC object to test.
|
||||
* @return true - test case passed; false - otherwise;
|
||||
*/
|
||||
protected boolean largeByteBufferTest(Mac theMac) {
|
||||
ByteBuffer buf = generateRandomByteBuffer(LARGE_SIZE);
|
||||
protected boolean largeByteBufferTest(Mac theMac,
|
||||
Function<Integer, ByteBuffer> createBuffer) {
|
||||
ByteBuffer buf = createBuffer.apply(LARGE_SIZE);
|
||||
int limitBefore = buf.limit();
|
||||
|
||||
theMac.update(buf);
|
||||
@ -179,8 +198,8 @@ public class PBMacBuffer {
|
||||
* @param theMac
|
||||
* @return true - test case pass; exception otherwise
|
||||
*/
|
||||
protected boolean emptyByteBufferTest(Mac theMac) {
|
||||
ByteBuffer buf = generateRandomByteBuffer(0);
|
||||
protected boolean emptyByteBufferTest(Mac theMac, Function<Integer, ByteBuffer> createBuffer) {
|
||||
ByteBuffer buf = createBuffer.apply(0);
|
||||
theMac.update(buf);
|
||||
theMac.doFinal();
|
||||
return true;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user