8297379: Enable the ByteBuffer path of Poly1305 optimizations
Reviewed-by: sviswanathan, ascarpino, jnimeh
This commit is contained in:
parent
1e468320dc
commit
203251ffc0
@ -124,10 +124,10 @@ final class Poly1305 {
|
||||
BLOCK_LENGTH - blockOffset);
|
||||
|
||||
if (bytesToWrite >= BLOCK_LENGTH) {
|
||||
// If bytes to write == BLOCK_LENGTH, then we have no
|
||||
// left-over data from previous updates and we can create
|
||||
// the IntegerModuloP directly from the input buffer.
|
||||
processBlock(buf, bytesToWrite);
|
||||
// Have at least one full block in the buf, process all full blocks
|
||||
int blockMultipleLength = remaining & (~(BLOCK_LENGTH-1));
|
||||
processMultipleBlocks(buf, blockMultipleLength);
|
||||
remaining -= blockMultipleLength;
|
||||
} else {
|
||||
// We have some left-over data from previous updates, so
|
||||
// copy that into the holding block until we get a full block.
|
||||
@ -138,9 +138,8 @@ final class Poly1305 {
|
||||
processBlock(block, 0, BLOCK_LENGTH);
|
||||
blockOffset = 0;
|
||||
}
|
||||
remaining -= bytesToWrite;
|
||||
}
|
||||
|
||||
remaining -= bytesToWrite;
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,6 +254,24 @@ final class Poly1305 {
|
||||
}
|
||||
}
|
||||
|
||||
private void processMultipleBlocks(ByteBuffer buf, int blockMultipleLength) {
|
||||
if (buf.hasArray()) {
|
||||
byte[] input = buf.array();
|
||||
int offset = buf.arrayOffset() + buf.position();
|
||||
long[] aLimbs = a.getLimbs();
|
||||
long[] rLimbs = r.getLimbs();
|
||||
|
||||
processMultipleBlocksCheck(input, offset, blockMultipleLength, aLimbs, rLimbs);
|
||||
processMultipleBlocks(input, offset, blockMultipleLength, aLimbs, rLimbs);
|
||||
buf.position(offset + blockMultipleLength);
|
||||
} else {
|
||||
while (blockMultipleLength >= BLOCK_LENGTH) {
|
||||
processBlock(buf, BLOCK_LENGTH);
|
||||
blockMultipleLength -= BLOCK_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processMultipleBlocksCheck(byte[] input, int offset, int length, long[] aLimbs, long[] rLimbs) {
|
||||
Objects.checkFromIndexSize(offset, length, input.length);
|
||||
final int numLimbs = 5; // Intrinsic expects exactly 5 limbs
|
||||
|
@ -26,6 +26,7 @@ package com.sun.crypto.provider;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
@ -36,7 +37,7 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
public class Poly1305IntrinsicFuzzTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
//Note: it might be useful to increase this number during development of new Poly1305 intrinsics
|
||||
final int repeat = 100;
|
||||
final int repeat = 1000;
|
||||
for (int i = 0; i < repeat; i++) {
|
||||
run();
|
||||
}
|
||||
@ -44,7 +45,7 @@ public class Poly1305IntrinsicFuzzTest {
|
||||
}
|
||||
|
||||
public static void run() throws Exception {
|
||||
java.util.Random rnd = new java.util.Random();
|
||||
Random rnd = new Random();
|
||||
long seed = rnd.nextLong();
|
||||
rnd.setSeed(seed);
|
||||
|
||||
@ -52,6 +53,7 @@ public class Poly1305IntrinsicFuzzTest {
|
||||
rnd.nextBytes(key);
|
||||
int msgLen = rnd.nextInt(128, 4096); // x86_64 intrinsic requires 256 bytes minimum
|
||||
byte[] message = new byte[msgLen];
|
||||
rnd.nextBytes(message);
|
||||
|
||||
Poly1305 authenticator = new Poly1305();
|
||||
Poly1305 authenticatorSlow = new Poly1305();
|
||||
@ -62,20 +64,22 @@ public class Poly1305IntrinsicFuzzTest {
|
||||
authenticator.engineInit(new SecretKeySpec(key, 0, 32, "Poly1305"), null);
|
||||
authenticatorSlow.engineInit(new SecretKeySpec(key, 0, 32, "Poly1305"), null);
|
||||
|
||||
if (rnd.nextBoolean()) {
|
||||
if (rnd.nextBoolean() && message.length > 16) {
|
||||
// Prime just the buffer and/or accumulator (buffer can keep at most 16 bytes from previous engineUpdate)
|
||||
int initDataLen = rnd.nextInt(8, 24);
|
||||
authenticator.engineUpdate(message, 0, initDataLen);
|
||||
slowUpdate(authenticatorSlow, message, 0, initDataLen);
|
||||
int initDataLen = rnd.nextInt(1, 16);
|
||||
int initDataOffset = rnd.nextInt(0, message.length - initDataLen);
|
||||
fastUpdate(authenticator, rnd, message, initDataOffset, initDataLen);
|
||||
slowUpdate(authenticatorSlow, message, initDataOffset, initDataLen);
|
||||
}
|
||||
|
||||
if (rnd.nextBoolean()) {
|
||||
// Multiple calls to engineUpdate
|
||||
authenticator.engineUpdate(message, 0, message.length);
|
||||
slowUpdate(authenticatorSlow, message, 0, message.length);
|
||||
int initDataOffset = rnd.nextInt(0, message.length);
|
||||
fastUpdate(authenticator, rnd, message, initDataOffset, message.length - initDataOffset);
|
||||
slowUpdate(authenticatorSlow, message, initDataOffset, message.length - initDataOffset);
|
||||
}
|
||||
|
||||
authenticator.engineUpdate(message, 0, message.length);
|
||||
fastUpdate(authenticator, rnd, message, 0, message.length);
|
||||
slowUpdate(authenticatorSlow, message, 0, message.length);
|
||||
|
||||
byte[] tag = authenticator.engineDoFinal();
|
||||
@ -87,9 +91,34 @@ public class Poly1305IntrinsicFuzzTest {
|
||||
}
|
||||
|
||||
static void slowUpdate(Poly1305 authenticator, byte[] message, int offset, int len) {
|
||||
len = Math.min(message.length, offset + len);
|
||||
for (int i = offset; i < len; i++) {
|
||||
for (int i = offset; i < offset + len; i++) {
|
||||
authenticator.engineUpdate(message[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void fastUpdate(Poly1305 authenticator, Random rnd, byte[] message, int offset, int len) {
|
||||
ByteBuffer buf;
|
||||
switch(rnd.nextInt(4)) {
|
||||
case 0: // byte[]
|
||||
authenticator.engineUpdate(message, offset, len);
|
||||
break;
|
||||
case 1: // ByteArray with backing array
|
||||
buf = ByteBuffer.wrap(message, offset, len)
|
||||
.order(java.nio.ByteOrder.LITTLE_ENDIAN);
|
||||
authenticator.engineUpdate(buf);
|
||||
break;
|
||||
case 2: // ByteArray with backing array (non-zero position)
|
||||
buf = ByteBuffer.wrap(message, 0, len+offset)
|
||||
.order(java.nio.ByteOrder.LITTLE_ENDIAN)
|
||||
.position(offset);
|
||||
authenticator.engineUpdate(buf);
|
||||
break;
|
||||
case 3: // ByteArray without backing array (wont be sent to intrinsic)
|
||||
buf = ByteBuffer.wrap(message, offset, len)
|
||||
.asReadOnlyBuffer()
|
||||
.order(java.nio.ByteOrder.LITTLE_ENDIAN);
|
||||
authenticator.engineUpdate(buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@Measurement(iterations = 3, time = 10)
|
||||
@Warmup(iterations = 3, time = 10)
|
||||
@ -49,7 +50,7 @@ public class Poly1305DigestBench extends CryptoBase {
|
||||
|
||||
private byte[][] data;
|
||||
int index = 0;
|
||||
private static MethodHandle polyEngineInit, polyEngineUpdate, polyEngineFinal;
|
||||
private static MethodHandle polyEngineInit, polyEngineUpdate, polyEngineUpdateBuf, polyEngineFinal;
|
||||
private static Object polyObj;
|
||||
|
||||
static {
|
||||
@ -68,6 +69,10 @@ public class Poly1305DigestBench extends CryptoBase {
|
||||
m.setAccessible(true);
|
||||
polyEngineUpdate = lookup.unreflect(m);
|
||||
|
||||
m = polyClazz.getDeclaredMethod("engineUpdate", ByteBuffer.class);
|
||||
m.setAccessible(true);
|
||||
polyEngineUpdateBuf = lookup.unreflect(m);
|
||||
|
||||
m = polyClazz.getDeclaredMethod("engineDoFinal");
|
||||
m.setAccessible(true);
|
||||
polyEngineFinal = lookup.unreflect(m);
|
||||
@ -83,7 +88,7 @@ public class Poly1305DigestBench extends CryptoBase {
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public byte[] digest() {
|
||||
public byte[] digestBytes() {
|
||||
try {
|
||||
byte[] d = data[index];
|
||||
index = (index +1) % SET_SIZE;
|
||||
@ -94,4 +99,17 @@ public class Poly1305DigestBench extends CryptoBase {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public byte[] digestBuffer() {
|
||||
try {
|
||||
byte[] d = data[index];
|
||||
index = (index +1) % SET_SIZE;
|
||||
polyEngineInit.invoke(polyObj, new SecretKeySpec(d, 0, 32, "Poly1305"), null);
|
||||
polyEngineUpdateBuf.invoke(polyObj, ByteBuffer.wrap(d, 0, d.length));
|
||||
return (byte[])polyEngineFinal.invoke(polyObj);
|
||||
} catch (Throwable ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user