8259498: Reduce overhead of MD5 and SHA digests

Reviewed-by: valeriep
This commit is contained in:
Claes Redestad 2021-01-20 23:45:55 +00:00
parent 27cc62a5c7
commit 35c9da7031
8 changed files with 305 additions and 576 deletions
src/java.base/share/classes/sun/security/provider
test/micro/org/openjdk/bench/java

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,24 +25,14 @@
package sun.security.provider; package sun.security.provider;
import static java.lang.Integer.reverseBytes; import java.lang.invoke.MethodHandles;
import static java.lang.Long.reverseBytes; import java.lang.invoke.VarHandle;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import jdk.internal.misc.Unsafe;
/** /**
* Optimized methods for converting between byte[] and int[]/long[], both for * Optimized methods for converting between byte[] and int[]/long[], both for
* big endian and little endian byte orders. * big endian and little endian byte orders.
* *
* Currently, it includes a default code path plus two optimized code paths.
* One is for little endian architectures that support full speed int/long
* access at unaligned addresses (i.e. x86/amd64). The second is for big endian
* architectures (that only support correctly aligned access), such as SPARC.
* These are the only platforms we currently support, but other optimized
* variants could be added as needed.
*
* NOTE that ArrayIndexOutOfBoundsException will be thrown if the bounds checks * NOTE that ArrayIndexOutOfBoundsException will be thrown if the bounds checks
* failed. * failed.
* *
@ -59,408 +49,128 @@ final class ByteArrayAccess {
// empty // empty
} }
private static final Unsafe unsafe = Unsafe.getUnsafe(); static final class LE {
static final VarHandle INT_ARRAY
= MethodHandles.byteArrayViewVarHandle(int[].class,
ByteOrder.LITTLE_ENDIAN).withInvokeExactBehavior();
// whether to use the optimized path for little endian platforms that static final VarHandle LONG_ARRAY
// support full speed unaligned memory access. = MethodHandles.byteArrayViewVarHandle(long[].class,
private static final boolean littleEndianUnaligned; ByteOrder.LITTLE_ENDIAN).withInvokeExactBehavior();
// whether to use the optimzied path for big endian platforms that
// support only correctly aligned full speed memory access.
// (Note that on SPARC unaligned memory access is possible, but it is
// implemented using a software trap and therefore very slow)
private static final boolean bigEndian;
private static final int byteArrayOfs = unsafe.arrayBaseOffset(byte[].class);
static {
boolean scaleOK = ((unsafe.arrayIndexScale(byte[].class) == 1)
&& (unsafe.arrayIndexScale(int[].class) == 4)
&& (unsafe.arrayIndexScale(long[].class) == 8)
&& ((byteArrayOfs & 3) == 0));
ByteOrder byteOrder = ByteOrder.nativeOrder();
littleEndianUnaligned =
scaleOK && unaligned() && (byteOrder == ByteOrder.LITTLE_ENDIAN);
bigEndian =
scaleOK && (byteOrder == ByteOrder.BIG_ENDIAN);
} }
// Return whether this platform supports full speed int/long memory access static final class BE {
// at unaligned addresses. static final VarHandle INT_ARRAY
private static boolean unaligned() { = MethodHandles.byteArrayViewVarHandle(int[].class,
return unsafe.unalignedAccess(); ByteOrder.BIG_ENDIAN).withInvokeExactBehavior();
}
/** static final VarHandle LONG_ARRAY
* byte[] to int[] conversion, little endian byte order. = MethodHandles.byteArrayViewVarHandle(long[].class,
*/ ByteOrder.BIG_ENDIAN).withInvokeExactBehavior();
static void b2iLittle(byte[] in, int inOfs, int[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len) ||
(outOfs < 0) || ((out.length - outOfs) < len/4)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) {
inOfs += byteArrayOfs;
len += inOfs;
while (inOfs < len) {
out[outOfs++] = unsafe.getInt(in, (long)inOfs);
inOfs += 4;
}
} else if (bigEndian && ((inOfs & 3) == 0)) {
inOfs += byteArrayOfs;
len += inOfs;
while (inOfs < len) {
out[outOfs++] = reverseBytes(unsafe.getInt(in, (long)inOfs));
inOfs += 4;
}
} else {
len += inOfs;
while (inOfs < len) {
out[outOfs++] = ((in[inOfs ] & 0xff) )
| ((in[inOfs + 1] & 0xff) << 8)
| ((in[inOfs + 2] & 0xff) << 16)
| ((in[inOfs + 3] ) << 24);
inOfs += 4;
}
}
}
// Special optimization of b2iLittle(in, inOfs, out, 0, 64)
static void b2iLittle64(byte[] in, int inOfs, int[] out) {
if ((inOfs < 0) || ((in.length - inOfs) < 64) ||
(out.length < 16)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) {
inOfs += byteArrayOfs;
out[ 0] = unsafe.getInt(in, (long)(inOfs ));
out[ 1] = unsafe.getInt(in, (long)(inOfs + 4));
out[ 2] = unsafe.getInt(in, (long)(inOfs + 8));
out[ 3] = unsafe.getInt(in, (long)(inOfs + 12));
out[ 4] = unsafe.getInt(in, (long)(inOfs + 16));
out[ 5] = unsafe.getInt(in, (long)(inOfs + 20));
out[ 6] = unsafe.getInt(in, (long)(inOfs + 24));
out[ 7] = unsafe.getInt(in, (long)(inOfs + 28));
out[ 8] = unsafe.getInt(in, (long)(inOfs + 32));
out[ 9] = unsafe.getInt(in, (long)(inOfs + 36));
out[10] = unsafe.getInt(in, (long)(inOfs + 40));
out[11] = unsafe.getInt(in, (long)(inOfs + 44));
out[12] = unsafe.getInt(in, (long)(inOfs + 48));
out[13] = unsafe.getInt(in, (long)(inOfs + 52));
out[14] = unsafe.getInt(in, (long)(inOfs + 56));
out[15] = unsafe.getInt(in, (long)(inOfs + 60));
} else if (bigEndian && ((inOfs & 3) == 0)) {
inOfs += byteArrayOfs;
out[ 0] = reverseBytes(unsafe.getInt(in, (long)(inOfs )));
out[ 1] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 4)));
out[ 2] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 8)));
out[ 3] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 12)));
out[ 4] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 16)));
out[ 5] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 20)));
out[ 6] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 24)));
out[ 7] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 28)));
out[ 8] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 32)));
out[ 9] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 36)));
out[10] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 40)));
out[11] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 44)));
out[12] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 48)));
out[13] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 52)));
out[14] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 56)));
out[15] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 60)));
} else {
b2iLittle(in, inOfs, out, 0, 64);
}
} }
/** /**
* int[] to byte[] conversion, little endian byte order. * int[] to byte[] conversion, little endian byte order.
*/ */
static void i2bLittle(int[] in, int inOfs, byte[] out, int outOfs, int len) { static void i2bLittle(int[] in, int inOfs, byte[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len/4) || len += outOfs;
(outOfs < 0) || ((out.length - outOfs) < len)) { while (outOfs < len) {
throw new ArrayIndexOutOfBoundsException(); LE.INT_ARRAY.set(out, outOfs, in[inOfs++]);
} outOfs += 4;
if (littleEndianUnaligned) {
outOfs += byteArrayOfs;
len += outOfs;
while (outOfs < len) {
unsafe.putInt(out, (long)outOfs, in[inOfs++]);
outOfs += 4;
}
} else if (bigEndian && ((outOfs & 3) == 0)) {
outOfs += byteArrayOfs;
len += outOfs;
while (outOfs < len) {
unsafe.putInt(out, (long)outOfs, reverseBytes(in[inOfs++]));
outOfs += 4;
}
} else {
len += outOfs;
while (outOfs < len) {
int i = in[inOfs++];
out[outOfs++] = (byte)(i );
out[outOfs++] = (byte)(i >> 8);
out[outOfs++] = (byte)(i >> 16);
out[outOfs++] = (byte)(i >> 24);
}
} }
} }
// Store one 32-bit value into out[outOfs..outOfs+3] in little endian order. // Store one 32-bit value into out[outOfs..outOfs+3] in little endian order.
static void i2bLittle4(int val, byte[] out, int outOfs) { static void i2bLittle4(int val, byte[] out, int outOfs) {
if ((outOfs < 0) || ((out.length - outOfs) < 4)) { LE.INT_ARRAY.set(out, outOfs, val);
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) {
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), val);
} else if (bigEndian && ((outOfs & 3) == 0)) {
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), reverseBytes(val));
} else {
out[outOfs ] = (byte)(val );
out[outOfs + 1] = (byte)(val >> 8);
out[outOfs + 2] = (byte)(val >> 16);
out[outOfs + 3] = (byte)(val >> 24);
}
} }
/** /**
* byte[] to int[] conversion, big endian byte order. * byte[] to int[] conversion, big endian byte order.
*/ */
static void b2iBig(byte[] in, int inOfs, int[] out, int outOfs, int len) { static void b2iBig(byte[] in, int inOfs, int[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len) || len += inOfs;
(outOfs < 0) || ((out.length - outOfs) < len/4)) { while (inOfs < len) {
throw new ArrayIndexOutOfBoundsException(); out[outOfs++] = (int) BE.INT_ARRAY.get(in, inOfs);
} inOfs += 4;
if (littleEndianUnaligned) {
inOfs += byteArrayOfs;
len += inOfs;
while (inOfs < len) {
out[outOfs++] = reverseBytes(unsafe.getInt(in, (long)inOfs));
inOfs += 4;
}
} else if (bigEndian && ((inOfs & 3) == 0)) {
inOfs += byteArrayOfs;
len += inOfs;
while (inOfs < len) {
out[outOfs++] = unsafe.getInt(in, (long)inOfs);
inOfs += 4;
}
} else {
len += inOfs;
while (inOfs < len) {
out[outOfs++] = ((in[inOfs + 3] & 0xff) )
| ((in[inOfs + 2] & 0xff) << 8)
| ((in[inOfs + 1] & 0xff) << 16)
| ((in[inOfs ] ) << 24);
inOfs += 4;
}
} }
} }
// Special optimization of b2iBig(in, inOfs, out, 0, 64) // Special optimization of b2iBig(in, inOfs, out, 0, 64)
static void b2iBig64(byte[] in, int inOfs, int[] out) { static void b2iBig64(byte[] in, int inOfs, int[] out) {
if ((inOfs < 0) || ((in.length - inOfs) < 64) || out[ 0] = (int) BE.INT_ARRAY.get(in, inOfs );
(out.length < 16)) { out[ 1] = (int) BE.INT_ARRAY.get(in, inOfs + 4);
throw new ArrayIndexOutOfBoundsException(); out[ 2] = (int) BE.INT_ARRAY.get(in, inOfs + 8);
} out[ 3] = (int) BE.INT_ARRAY.get(in, inOfs + 12);
if (littleEndianUnaligned) { out[ 4] = (int) BE.INT_ARRAY.get(in, inOfs + 16);
inOfs += byteArrayOfs; out[ 5] = (int) BE.INT_ARRAY.get(in, inOfs + 20);
out[ 0] = reverseBytes(unsafe.getInt(in, (long)(inOfs ))); out[ 6] = (int) BE.INT_ARRAY.get(in, inOfs + 24);
out[ 1] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 4))); out[ 7] = (int) BE.INT_ARRAY.get(in, inOfs + 28);
out[ 2] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 8))); out[ 8] = (int) BE.INT_ARRAY.get(in, inOfs + 32);
out[ 3] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 12))); out[ 9] = (int) BE.INT_ARRAY.get(in, inOfs + 36);
out[ 4] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 16))); out[10] = (int) BE.INT_ARRAY.get(in, inOfs + 40);
out[ 5] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 20))); out[11] = (int) BE.INT_ARRAY.get(in, inOfs + 44);
out[ 6] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 24))); out[12] = (int) BE.INT_ARRAY.get(in, inOfs + 48);
out[ 7] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 28))); out[13] = (int) BE.INT_ARRAY.get(in, inOfs + 52);
out[ 8] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 32))); out[14] = (int) BE.INT_ARRAY.get(in, inOfs + 56);
out[ 9] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 36))); out[15] = (int) BE.INT_ARRAY.get(in, inOfs + 60);
out[10] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 40)));
out[11] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 44)));
out[12] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 48)));
out[13] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 52)));
out[14] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 56)));
out[15] = reverseBytes(unsafe.getInt(in, (long)(inOfs + 60)));
} else if (bigEndian && ((inOfs & 3) == 0)) {
inOfs += byteArrayOfs;
out[ 0] = unsafe.getInt(in, (long)(inOfs ));
out[ 1] = unsafe.getInt(in, (long)(inOfs + 4));
out[ 2] = unsafe.getInt(in, (long)(inOfs + 8));
out[ 3] = unsafe.getInt(in, (long)(inOfs + 12));
out[ 4] = unsafe.getInt(in, (long)(inOfs + 16));
out[ 5] = unsafe.getInt(in, (long)(inOfs + 20));
out[ 6] = unsafe.getInt(in, (long)(inOfs + 24));
out[ 7] = unsafe.getInt(in, (long)(inOfs + 28));
out[ 8] = unsafe.getInt(in, (long)(inOfs + 32));
out[ 9] = unsafe.getInt(in, (long)(inOfs + 36));
out[10] = unsafe.getInt(in, (long)(inOfs + 40));
out[11] = unsafe.getInt(in, (long)(inOfs + 44));
out[12] = unsafe.getInt(in, (long)(inOfs + 48));
out[13] = unsafe.getInt(in, (long)(inOfs + 52));
out[14] = unsafe.getInt(in, (long)(inOfs + 56));
out[15] = unsafe.getInt(in, (long)(inOfs + 60));
} else {
b2iBig(in, inOfs, out, 0, 64);
}
} }
/** /**
* int[] to byte[] conversion, big endian byte order. * int[] to byte[] conversion, big endian byte order.
*/ */
static void i2bBig(int[] in, int inOfs, byte[] out, int outOfs, int len) { static void i2bBig(int[] in, int inOfs, byte[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len/4) || len += outOfs;
(outOfs < 0) || ((out.length - outOfs) < len)) { while (outOfs < len) {
throw new ArrayIndexOutOfBoundsException(); BE.INT_ARRAY.set(out, outOfs, in[inOfs++]);
} outOfs += 4;
if (littleEndianUnaligned) {
outOfs += byteArrayOfs;
len += outOfs;
while (outOfs < len) {
unsafe.putInt(out, (long)outOfs, reverseBytes(in[inOfs++]));
outOfs += 4;
}
} else if (bigEndian && ((outOfs & 3) == 0)) {
outOfs += byteArrayOfs;
len += outOfs;
while (outOfs < len) {
unsafe.putInt(out, (long)outOfs, in[inOfs++]);
outOfs += 4;
}
} else {
len += outOfs;
while (outOfs < len) {
int i = in[inOfs++];
out[outOfs++] = (byte)(i >> 24);
out[outOfs++] = (byte)(i >> 16);
out[outOfs++] = (byte)(i >> 8);
out[outOfs++] = (byte)(i );
}
} }
} }
// Store one 32-bit value into out[outOfs..outOfs+3] in big endian order. // Store one 32-bit value into out[outOfs..outOfs+3] in big endian order.
static void i2bBig4(int val, byte[] out, int outOfs) { static void i2bBig4(int val, byte[] out, int outOfs) {
if ((outOfs < 0) || ((out.length - outOfs) < 4)) { BE.INT_ARRAY.set(out, outOfs, val);
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) {
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), reverseBytes(val));
} else if (bigEndian && ((outOfs & 3) == 0)) {
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), val);
} else {
out[outOfs ] = (byte)(val >> 24);
out[outOfs + 1] = (byte)(val >> 16);
out[outOfs + 2] = (byte)(val >> 8);
out[outOfs + 3] = (byte)(val );
}
} }
/** /**
* byte[] to long[] conversion, big endian byte order. * byte[] to long[] conversion, big endian byte order.
*/ */
static void b2lBig(byte[] in, int inOfs, long[] out, int outOfs, int len) { static void b2lBig(byte[] in, int inOfs, long[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len) || len += inOfs;
(outOfs < 0) || ((out.length - outOfs) < len/8)) { while (inOfs < len) {
throw new ArrayIndexOutOfBoundsException(); out[outOfs++] = (long) BE.LONG_ARRAY.get(in, inOfs);
} inOfs += 8;
if (littleEndianUnaligned) {
inOfs += byteArrayOfs;
len += inOfs;
while (inOfs < len) {
out[outOfs++] = reverseBytes(unsafe.getLong(in, (long)inOfs));
inOfs += 8;
}
} else if (bigEndian && ((inOfs & 3) == 0)) {
// In the current HotSpot memory layout, the first element of a
// byte[] is only 32-bit aligned, not 64-bit.
// That means we could use getLong() only for offset 4, 12, etc.,
// which would rarely occur in practice. Instead, we use an
// optimization that uses getInt() so that it works for offset 0.
inOfs += byteArrayOfs;
len += inOfs;
while (inOfs < len) {
out[outOfs++] =
((long)unsafe.getInt(in, (long)inOfs) << 32)
| (unsafe.getInt(in, (long)(inOfs + 4)) & 0xffffffffL);
inOfs += 8;
}
} else {
len += inOfs;
while (inOfs < len) {
int i1 = ((in[inOfs + 3] & 0xff) )
| ((in[inOfs + 2] & 0xff) << 8)
| ((in[inOfs + 1] & 0xff) << 16)
| ((in[inOfs ] ) << 24);
inOfs += 4;
int i2 = ((in[inOfs + 3] & 0xff) )
| ((in[inOfs + 2] & 0xff) << 8)
| ((in[inOfs + 1] & 0xff) << 16)
| ((in[inOfs ] ) << 24);
out[outOfs++] = ((long)i1 << 32) | (i2 & 0xffffffffL);
inOfs += 4;
}
} }
} }
// Special optimization of b2lBig(in, inOfs, out, 0, 128) // Special optimization of b2lBig(in, inOfs, out, 0, 128)
static void b2lBig128(byte[] in, int inOfs, long[] out) { static void b2lBig128(byte[] in, int inOfs, long[] out) {
if ((inOfs < 0) || ((in.length - inOfs) < 128) || out[ 0] = (long) BE.LONG_ARRAY.get(in, inOfs );
(out.length < 16)) { out[ 1] = (long) BE.LONG_ARRAY.get(in, inOfs + 8);
throw new ArrayIndexOutOfBoundsException(); out[ 2] = (long) BE.LONG_ARRAY.get(in, inOfs + 16);
} out[ 3] = (long) BE.LONG_ARRAY.get(in, inOfs + 24);
if (littleEndianUnaligned) { out[ 4] = (long) BE.LONG_ARRAY.get(in, inOfs + 32);
inOfs += byteArrayOfs; out[ 5] = (long) BE.LONG_ARRAY.get(in, inOfs + 40);
out[ 0] = reverseBytes(unsafe.getLong(in, (long)(inOfs ))); out[ 6] = (long) BE.LONG_ARRAY.get(in, inOfs + 48);
out[ 1] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 8))); out[ 7] = (long) BE.LONG_ARRAY.get(in, inOfs + 56);
out[ 2] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 16))); out[ 8] = (long) BE.LONG_ARRAY.get(in, inOfs + 64);
out[ 3] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 24))); out[ 9] = (long) BE.LONG_ARRAY.get(in, inOfs + 72);
out[ 4] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 32))); out[10] = (long) BE.LONG_ARRAY.get(in, inOfs + 80);
out[ 5] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 40))); out[11] = (long) BE.LONG_ARRAY.get(in, inOfs + 88);
out[ 6] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 48))); out[12] = (long) BE.LONG_ARRAY.get(in, inOfs + 96);
out[ 7] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 56))); out[13] = (long) BE.LONG_ARRAY.get(in, inOfs + 104);
out[ 8] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 64))); out[14] = (long) BE.LONG_ARRAY.get(in, inOfs + 112);
out[ 9] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 72))); out[15] = (long) BE.LONG_ARRAY.get(in, inOfs + 120);
out[10] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 80)));
out[11] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 88)));
out[12] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 96)));
out[13] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 104)));
out[14] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 112)));
out[15] = reverseBytes(unsafe.getLong(in, (long)(inOfs + 120)));
} else {
// no optimization for big endian, see comments in b2lBig
b2lBig(in, inOfs, out, 0, 128);
}
} }
/** /**
* long[] to byte[] conversion, big endian byte order. * long[] to byte[] conversion, big endian byte order.
*/ */
static void l2bBig(long[] in, int inOfs, byte[] out, int outOfs, int len) { static void l2bBig(long[] in, int inOfs, byte[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len/8) || len += outOfs;
(outOfs < 0) || ((out.length - outOfs) < len)) { while (outOfs < len) {
throw new ArrayIndexOutOfBoundsException(); BE.LONG_ARRAY.set(out, outOfs, in[inOfs++]);
} outOfs += 8;
if (littleEndianUnaligned) {
outOfs += byteArrayOfs;
len += outOfs;
while (outOfs < len) {
unsafe.putLong(out, (long)outOfs, reverseBytes(in[inOfs++]));
outOfs += 8;
}
} else {
len += outOfs;
while (outOfs < len) {
long i = in[inOfs++];
out[outOfs++] = (byte)(i >> 56);
out[outOfs++] = (byte)(i >> 48);
out[outOfs++] = (byte)(i >> 40);
out[outOfs++] = (byte)(i >> 32);
out[outOfs++] = (byte)(i >> 24);
out[outOfs++] = (byte)(i >> 16);
out[outOfs++] = (byte)(i >> 8);
out[outOfs++] = (byte)(i );
}
} }
} }
@ -468,30 +178,10 @@ final class ByteArrayAccess {
* byte[] to long[] conversion, little endian byte order * byte[] to long[] conversion, little endian byte order
*/ */
static void b2lLittle(byte[] in, int inOfs, long[] out, int outOfs, int len) { static void b2lLittle(byte[] in, int inOfs, long[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len) || len += inOfs;
((outOfs < 0) || (out.length - outOfs) < len/8)) { while (inOfs < len) {
throw new ArrayIndexOutOfBoundsException(); out[outOfs++] = (long) LE.LONG_ARRAY.get(in, inOfs);
} inOfs += 8;
if (littleEndianUnaligned) {
inOfs += byteArrayOfs;
len += inOfs;
while (inOfs < len) {
out[outOfs++] = unsafe.getLong(in, (long)inOfs);
inOfs += 8;
}
} else {
len += inOfs;
while (inOfs < len) {
out[outOfs++] = ((in[inOfs ] & 0xffL)
| ((in[inOfs + 1] & 0xffL) << 8)
| ((in[inOfs + 2] & 0xffL) << 16)
| ((in[inOfs + 3] & 0xffL) << 24)
| ((in[inOfs + 4] & 0xffL) << 32)
| ((in[inOfs + 5] & 0xffL) << 40)
| ((in[inOfs + 6] & 0xffL) << 48)
| ((in[inOfs + 7] & 0xffL) << 56));
inOfs += 8;
}
} }
} }
@ -500,30 +190,10 @@ final class ByteArrayAccess {
* long[] to byte[] conversion, little endian byte order * long[] to byte[] conversion, little endian byte order
*/ */
static void l2bLittle(long[] in, int inOfs, byte[] out, int outOfs, int len) { static void l2bLittle(long[] in, int inOfs, byte[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len/8) || len += outOfs;
(outOfs < 0) || ((out.length - outOfs) < len)) { while (outOfs < len) {
throw new ArrayIndexOutOfBoundsException(); LE.LONG_ARRAY.set(out, outOfs, in[inOfs++]);
} outOfs += 8;
if (littleEndianUnaligned) {
outOfs += byteArrayOfs;
len += outOfs;
while (outOfs < len) {
unsafe.putLong(out, (long)outOfs, in[inOfs++]);
outOfs += 8;
}
} else {
len += outOfs;
while (outOfs < len) {
long i = in[inOfs++];
out[outOfs++] = (byte)(i );
out[outOfs++] = (byte)(i >> 8);
out[outOfs++] = (byte)(i >> 16);
out[outOfs++] = (byte)(i >> 24);
out[outOfs++] = (byte)(i >> 32);
out[outOfs++] = (byte)(i >> 40);
out[outOfs++] = (byte)(i >> 48);
out[outOfs++] = (byte)(i >> 56);
}
} }
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -47,8 +47,6 @@ public final class MD4 extends DigestBase {
// state of this object // state of this object
private int[] state; private int[] state;
// temporary buffer, used by implCompress()
private int[] x;
// rotation constants // rotation constants
private static final int S11 = 3; private static final int S11 = 3;
@ -93,7 +91,6 @@ public final class MD4 extends DigestBase {
public MD4() { public MD4() {
super("MD4", 16, 64); super("MD4", 16, 64);
state = new int[4]; state = new int[4];
x = new int[16];
resetHashes(); resetHashes();
} }
@ -101,7 +98,6 @@ public final class MD4 extends DigestBase {
public Object clone() throws CloneNotSupportedException { public Object clone() throws CloneNotSupportedException {
MD4 copy = (MD4) super.clone(); MD4 copy = (MD4) super.clone();
copy.state = copy.state.clone(); copy.state = copy.state.clone();
copy.x = new int[16];
return copy; return copy;
} }
@ -111,8 +107,6 @@ public final class MD4 extends DigestBase {
void implReset() { void implReset() {
// Load magic initialization constants. // Load magic initialization constants.
resetHashes(); resetHashes();
// clear out old data
Arrays.fill(x, 0);
} }
private void resetHashes() { private void resetHashes() {
@ -162,7 +156,22 @@ public final class MD4 extends DigestBase {
* bytes from the buffer, beginning at the specified offset. * bytes from the buffer, beginning at the specified offset.
*/ */
void implCompress(byte[] buf, int ofs) { void implCompress(byte[] buf, int ofs) {
b2iLittle64(buf, ofs, x); int x0 = (int) LE.INT_ARRAY.get(buf, ofs);
int x1 = (int) LE.INT_ARRAY.get(buf, ofs + 4);
int x2 = (int) LE.INT_ARRAY.get(buf, ofs + 8);
int x3 = (int) LE.INT_ARRAY.get(buf, ofs + 12);
int x4 = (int) LE.INT_ARRAY.get(buf, ofs + 16);
int x5 = (int) LE.INT_ARRAY.get(buf, ofs + 20);
int x6 = (int) LE.INT_ARRAY.get(buf, ofs + 24);
int x7 = (int) LE.INT_ARRAY.get(buf, ofs + 28);
int x8 = (int) LE.INT_ARRAY.get(buf, ofs + 32);
int x9 = (int) LE.INT_ARRAY.get(buf, ofs + 36);
int x10 = (int) LE.INT_ARRAY.get(buf, ofs + 40);
int x11 = (int) LE.INT_ARRAY.get(buf, ofs + 44);
int x12 = (int) LE.INT_ARRAY.get(buf, ofs + 48);
int x13 = (int) LE.INT_ARRAY.get(buf, ofs + 52);
int x14 = (int) LE.INT_ARRAY.get(buf, ofs + 56);
int x15 = (int) LE.INT_ARRAY.get(buf, ofs + 60);
int a = state[0]; int a = state[0];
int b = state[1]; int b = state[1];
@ -170,58 +179,58 @@ public final class MD4 extends DigestBase {
int d = state[3]; int d = state[3];
/* Round 1 */ /* Round 1 */
a = FF (a, b, c, d, x[ 0], S11); /* 1 */ a = FF (a, b, c, d, x0, S11); /* 1 */
d = FF (d, a, b, c, x[ 1], S12); /* 2 */ d = FF (d, a, b, c, x1, S12); /* 2 */
c = FF (c, d, a, b, x[ 2], S13); /* 3 */ c = FF (c, d, a, b, x2, S13); /* 3 */
b = FF (b, c, d, a, x[ 3], S14); /* 4 */ b = FF (b, c, d, a, x3, S14); /* 4 */
a = FF (a, b, c, d, x[ 4], S11); /* 5 */ a = FF (a, b, c, d, x4, S11); /* 5 */
d = FF (d, a, b, c, x[ 5], S12); /* 6 */ d = FF (d, a, b, c, x5, S12); /* 6 */
c = FF (c, d, a, b, x[ 6], S13); /* 7 */ c = FF (c, d, a, b, x6, S13); /* 7 */
b = FF (b, c, d, a, x[ 7], S14); /* 8 */ b = FF (b, c, d, a, x7, S14); /* 8 */
a = FF (a, b, c, d, x[ 8], S11); /* 9 */ a = FF (a, b, c, d, x8, S11); /* 9 */
d = FF (d, a, b, c, x[ 9], S12); /* 10 */ d = FF (d, a, b, c, x9, S12); /* 10 */
c = FF (c, d, a, b, x[10], S13); /* 11 */ c = FF (c, d, a, b, x10, S13); /* 11 */
b = FF (b, c, d, a, x[11], S14); /* 12 */ b = FF (b, c, d, a, x11, S14); /* 12 */
a = FF (a, b, c, d, x[12], S11); /* 13 */ a = FF (a, b, c, d, x12, S11); /* 13 */
d = FF (d, a, b, c, x[13], S12); /* 14 */ d = FF (d, a, b, c, x13, S12); /* 14 */
c = FF (c, d, a, b, x[14], S13); /* 15 */ c = FF (c, d, a, b, x14, S13); /* 15 */
b = FF (b, c, d, a, x[15], S14); /* 16 */ b = FF (b, c, d, a, x15, S14); /* 16 */
/* Round 2 */ /* Round 2 */
a = GG (a, b, c, d, x[ 0], S21); /* 17 */ a = GG (a, b, c, d, x0, S21); /* 17 */
d = GG (d, a, b, c, x[ 4], S22); /* 18 */ d = GG (d, a, b, c, x4, S22); /* 18 */
c = GG (c, d, a, b, x[ 8], S23); /* 19 */ c = GG (c, d, a, b, x8, S23); /* 19 */
b = GG (b, c, d, a, x[12], S24); /* 20 */ b = GG (b, c, d, a, x12, S24); /* 20 */
a = GG (a, b, c, d, x[ 1], S21); /* 21 */ a = GG (a, b, c, d, x1, S21); /* 21 */
d = GG (d, a, b, c, x[ 5], S22); /* 22 */ d = GG (d, a, b, c, x5, S22); /* 22 */
c = GG (c, d, a, b, x[ 9], S23); /* 23 */ c = GG (c, d, a, b, x9, S23); /* 23 */
b = GG (b, c, d, a, x[13], S24); /* 24 */ b = GG (b, c, d, a, x13, S24); /* 24 */
a = GG (a, b, c, d, x[ 2], S21); /* 25 */ a = GG (a, b, c, d, x2, S21); /* 25 */
d = GG (d, a, b, c, x[ 6], S22); /* 26 */ d = GG (d, a, b, c, x6, S22); /* 26 */
c = GG (c, d, a, b, x[10], S23); /* 27 */ c = GG (c, d, a, b, x10, S23); /* 27 */
b = GG (b, c, d, a, x[14], S24); /* 28 */ b = GG (b, c, d, a, x14, S24); /* 28 */
a = GG (a, b, c, d, x[ 3], S21); /* 29 */ a = GG (a, b, c, d, x3, S21); /* 29 */
d = GG (d, a, b, c, x[ 7], S22); /* 30 */ d = GG (d, a, b, c, x7, S22); /* 30 */
c = GG (c, d, a, b, x[11], S23); /* 31 */ c = GG (c, d, a, b, x11, S23); /* 31 */
b = GG (b, c, d, a, x[15], S24); /* 32 */ b = GG (b, c, d, a, x15, S24); /* 32 */
/* Round 3 */ /* Round 3 */
a = HH (a, b, c, d, x[ 0], S31); /* 33 */ a = HH (a, b, c, d, x0, S31); /* 33 */
d = HH (d, a, b, c, x[ 8], S32); /* 34 */ d = HH (d, a, b, c, x8, S32); /* 34 */
c = HH (c, d, a, b, x[ 4], S33); /* 35 */ c = HH (c, d, a, b, x4, S33); /* 35 */
b = HH (b, c, d, a, x[12], S34); /* 36 */ b = HH (b, c, d, a, x12, S34); /* 36 */
a = HH (a, b, c, d, x[ 2], S31); /* 37 */ a = HH (a, b, c, d, x2, S31); /* 37 */
d = HH (d, a, b, c, x[10], S32); /* 38 */ d = HH (d, a, b, c, x10, S32); /* 38 */
c = HH (c, d, a, b, x[ 6], S33); /* 39 */ c = HH (c, d, a, b, x6, S33); /* 39 */
b = HH (b, c, d, a, x[14], S34); /* 40 */ b = HH (b, c, d, a, x14, S34); /* 40 */
a = HH (a, b, c, d, x[ 1], S31); /* 41 */ a = HH (a, b, c, d, x1, S31); /* 41 */
d = HH (d, a, b, c, x[ 9], S32); /* 42 */ d = HH (d, a, b, c, x9, S32); /* 42 */
c = HH (c, d, a, b, x[ 5], S33); /* 43 */ c = HH (c, d, a, b, x5, S33); /* 43 */
b = HH (b, c, d, a, x[13], S34); /* 44 */ b = HH (b, c, d, a, x13, S34); /* 44 */
a = HH (a, b, c, d, x[ 3], S31); /* 45 */ a = HH (a, b, c, d, x3, S31); /* 45 */
d = HH (d, a, b, c, x[11], S32); /* 46 */ d = HH (d, a, b, c, x11, S32); /* 46 */
c = HH (c, d, a, b, x[ 7], S33); /* 47 */ c = HH (c, d, a, b, x7, S33); /* 47 */
b = HH (b, c, d, a, x[15], S34); /* 48 */ b = HH (b, c, d, a, x15, S34); /* 48 */
state[0] += a; state[0] += a;
state[1] += b; state[1] += b;

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,9 @@
package sun.security.provider; package sun.security.provider;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
@ -44,8 +47,6 @@ public final class MD5 extends DigestBase {
// state of this object // state of this object
private int[] state; private int[] state;
// temporary buffer, used by implCompress()
private int[] x;
// rotation constants // rotation constants
private static final int S11 = 7; private static final int S11 = 7;
@ -69,15 +70,13 @@ public final class MD5 extends DigestBase {
public MD5() { public MD5() {
super("MD5", 16, 64); super("MD5", 16, 64);
state = new int[4]; state = new int[4];
x = new int[16]; implReset();
resetHashes();
} }
// clone this object // clone this object
public Object clone() throws CloneNotSupportedException { public Object clone() throws CloneNotSupportedException {
MD5 copy = (MD5) super.clone(); MD5 copy = (MD5) super.clone();
copy.state = copy.state.clone(); copy.state = copy.state.clone();
copy.x = new int[16];
return copy; return copy;
} }
@ -86,12 +85,6 @@ public final class MD5 extends DigestBase {
*/ */
void implReset() { void implReset() {
// Load magic initialization constants. // Load magic initialization constants.
resetHashes();
// clear out old data
Arrays.fill(x, 0);
}
private void resetHashes() {
state[0] = 0x67452301; state[0] = 0x67452301;
state[1] = 0xefcdab89; state[1] = 0xefcdab89;
state[2] = 0x98badcfe; state[2] = 0x98badcfe;
@ -156,11 +149,12 @@ public final class MD5 extends DigestBase {
private void implCompressCheck(byte[] buf, int ofs) { private void implCompressCheck(byte[] buf, int ofs) {
Objects.requireNonNull(buf); Objects.requireNonNull(buf);
// The checks performed by the method 'b2iBig64' // These checks are sufficient for the case when the method
// are sufficient for the case when the method
// 'implCompressImpl' is replaced with a compiler // 'implCompressImpl' is replaced with a compiler
// intrinsic. // intrinsic.
b2iLittle64(buf, ofs, x); if ((ofs < 0) || ((buf.length - ofs) < 64)) {
throw new ArrayIndexOutOfBoundsException();
}
} }
// The method 'implCompress0 seems not to use its parameters. // The method 'implCompress0 seems not to use its parameters.
@ -175,77 +169,94 @@ public final class MD5 extends DigestBase {
int c = state[2]; int c = state[2];
int d = state[3]; int d = state[3];
int x0 = (int) LE.INT_ARRAY.get(buf, ofs);
int x1 = (int) LE.INT_ARRAY.get(buf, ofs + 4);
int x2 = (int) LE.INT_ARRAY.get(buf, ofs + 8);
int x3 = (int) LE.INT_ARRAY.get(buf, ofs + 12);
int x4 = (int) LE.INT_ARRAY.get(buf, ofs + 16);
int x5 = (int) LE.INT_ARRAY.get(buf, ofs + 20);
int x6 = (int) LE.INT_ARRAY.get(buf, ofs + 24);
int x7 = (int) LE.INT_ARRAY.get(buf, ofs + 28);
int x8 = (int) LE.INT_ARRAY.get(buf, ofs + 32);
int x9 = (int) LE.INT_ARRAY.get(buf, ofs + 36);
int x10 = (int) LE.INT_ARRAY.get(buf, ofs + 40);
int x11 = (int) LE.INT_ARRAY.get(buf, ofs + 44);
int x12 = (int) LE.INT_ARRAY.get(buf, ofs + 48);
int x13 = (int) LE.INT_ARRAY.get(buf, ofs + 52);
int x14 = (int) LE.INT_ARRAY.get(buf, ofs + 56);
int x15 = (int) LE.INT_ARRAY.get(buf, ofs + 60);
/* Round 1 */ /* Round 1 */
a = FF ( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ a = FF ( a, b, c, d, x0, S11, 0xd76aa478); /* 1 */
d = FF ( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ d = FF ( d, a, b, c, x1, S12, 0xe8c7b756); /* 2 */
c = FF ( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ c = FF ( c, d, a, b, x2, S13, 0x242070db); /* 3 */
b = FF ( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ b = FF ( b, c, d, a, x3, S14, 0xc1bdceee); /* 4 */
a = FF ( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ a = FF ( a, b, c, d, x4, S11, 0xf57c0faf); /* 5 */
d = FF ( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ d = FF ( d, a, b, c, x5, S12, 0x4787c62a); /* 6 */
c = FF ( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ c = FF ( c, d, a, b, x6, S13, 0xa8304613); /* 7 */
b = FF ( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ b = FF ( b, c, d, a, x7, S14, 0xfd469501); /* 8 */
a = FF ( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ a = FF ( a, b, c, d, x8, S11, 0x698098d8); /* 9 */
d = FF ( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ d = FF ( d, a, b, c, x9, S12, 0x8b44f7af); /* 10 */
c = FF ( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ c = FF ( c, d, a, b, x10, S13, 0xffff5bb1); /* 11 */
b = FF ( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ b = FF ( b, c, d, a, x11, S14, 0x895cd7be); /* 12 */
a = FF ( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ a = FF ( a, b, c, d, x12, S11, 0x6b901122); /* 13 */
d = FF ( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ d = FF ( d, a, b, c, x13, S12, 0xfd987193); /* 14 */
c = FF ( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ c = FF ( c, d, a, b, x14, S13, 0xa679438e); /* 15 */
b = FF ( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ b = FF ( b, c, d, a, x15, S14, 0x49b40821); /* 16 */
/* Round 2 */ /* Round 2 */
a = GG ( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ a = GG ( a, b, c, d, x1, S21, 0xf61e2562); /* 17 */
d = GG ( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ d = GG ( d, a, b, c, x6, S22, 0xc040b340); /* 18 */
c = GG ( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ c = GG ( c, d, a, b, x11, S23, 0x265e5a51); /* 19 */
b = GG ( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ b = GG ( b, c, d, a, x0, S24, 0xe9b6c7aa); /* 20 */
a = GG ( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ a = GG ( a, b, c, d, x5, S21, 0xd62f105d); /* 21 */
d = GG ( d, a, b, c, x[10], S22, 0x2441453); /* 22 */ d = GG ( d, a, b, c, x10, S22, 0x2441453); /* 22 */
c = GG ( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ c = GG ( c, d, a, b, x15, S23, 0xd8a1e681); /* 23 */
b = GG ( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ b = GG ( b, c, d, a, x4, S24, 0xe7d3fbc8); /* 24 */
a = GG ( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ a = GG ( a, b, c, d, x9, S21, 0x21e1cde6); /* 25 */
d = GG ( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ d = GG ( d, a, b, c, x14, S22, 0xc33707d6); /* 26 */
c = GG ( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ c = GG ( c, d, a, b, x3, S23, 0xf4d50d87); /* 27 */
b = GG ( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ b = GG ( b, c, d, a, x8, S24, 0x455a14ed); /* 28 */
a = GG ( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ a = GG ( a, b, c, d, x13, S21, 0xa9e3e905); /* 29 */
d = GG ( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ d = GG ( d, a, b, c, x2, S22, 0xfcefa3f8); /* 30 */
c = GG ( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ c = GG ( c, d, a, b, x7, S23, 0x676f02d9); /* 31 */
b = GG ( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ b = GG ( b, c, d, a, x12, S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */ /* Round 3 */
a = HH ( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ a = HH ( a, b, c, d, x5, S31, 0xfffa3942); /* 33 */
d = HH ( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ d = HH ( d, a, b, c, x8, S32, 0x8771f681); /* 34 */
c = HH ( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ c = HH ( c, d, a, b, x11, S33, 0x6d9d6122); /* 35 */
b = HH ( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ b = HH ( b, c, d, a, x14, S34, 0xfde5380c); /* 36 */
a = HH ( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ a = HH ( a, b, c, d, x1, S31, 0xa4beea44); /* 37 */
d = HH ( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ d = HH ( d, a, b, c, x4, S32, 0x4bdecfa9); /* 38 */
c = HH ( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ c = HH ( c, d, a, b, x7, S33, 0xf6bb4b60); /* 39 */
b = HH ( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ b = HH ( b, c, d, a, x10, S34, 0xbebfbc70); /* 40 */
a = HH ( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ a = HH ( a, b, c, d, x13, S31, 0x289b7ec6); /* 41 */
d = HH ( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ d = HH ( d, a, b, c, x0, S32, 0xeaa127fa); /* 42 */
c = HH ( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ c = HH ( c, d, a, b, x3, S33, 0xd4ef3085); /* 43 */
b = HH ( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ b = HH ( b, c, d, a, x6, S34, 0x4881d05); /* 44 */
a = HH ( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ a = HH ( a, b, c, d, x9, S31, 0xd9d4d039); /* 45 */
d = HH ( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ d = HH ( d, a, b, c, x12, S32, 0xe6db99e5); /* 46 */
c = HH ( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ c = HH ( c, d, a, b, x15, S33, 0x1fa27cf8); /* 47 */
b = HH ( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ b = HH ( b, c, d, a, x2, S34, 0xc4ac5665); /* 48 */
/* Round 4 */ /* Round 4 */
a = II ( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ a = II ( a, b, c, d, x0, S41, 0xf4292244); /* 49 */
d = II ( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ d = II ( d, a, b, c, x7, S42, 0x432aff97); /* 50 */
c = II ( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ c = II ( c, d, a, b, x14, S43, 0xab9423a7); /* 51 */
b = II ( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ b = II ( b, c, d, a, x5, S44, 0xfc93a039); /* 52 */
a = II ( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ a = II ( a, b, c, d, x12, S41, 0x655b59c3); /* 53 */
d = II ( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ d = II ( d, a, b, c, x3, S42, 0x8f0ccc92); /* 54 */
c = II ( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ c = II ( c, d, a, b, x10, S43, 0xffeff47d); /* 55 */
b = II ( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ b = II ( b, c, d, a, x1, S44, 0x85845dd1); /* 56 */
a = II ( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ a = II ( a, b, c, d, x8, S41, 0x6fa87e4f); /* 57 */
d = II ( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ d = II ( d, a, b, c, x15, S42, 0xfe2ce6e0); /* 58 */
c = II ( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ c = II ( c, d, a, b, x6, S43, 0xa3014314); /* 59 */
b = II ( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ b = II ( b, c, d, a, x13, S44, 0x4e0811a1); /* 60 */
a = II ( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ a = II ( a, b, c, d, x4, S41, 0xf7537e82); /* 61 */
d = II ( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ d = II ( d, a, b, c, x11, S42, 0xbd3af235); /* 62 */
c = II ( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ c = II ( c, d, a, b, x2, S43, 0x2ad7d2bb); /* 63 */
b = II ( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ b = II ( b, c, d, a, x9, S44, 0xeb86d391); /* 64 */
state[0] += a; state[0] += a;
state[1] += b; state[1] += b;

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -62,7 +62,6 @@ public final class SHA extends DigestBase {
public SHA() { public SHA() {
super("SHA-1", 20, 64); super("SHA-1", 20, 64);
state = new int[5]; state = new int[5];
W = new int[80];
resetHashes(); resetHashes();
} }
@ -72,7 +71,7 @@ public final class SHA extends DigestBase {
public Object clone() throws CloneNotSupportedException { public Object clone() throws CloneNotSupportedException {
SHA copy = (SHA) super.clone(); SHA copy = (SHA) super.clone();
copy.state = copy.state.clone(); copy.state = copy.state.clone();
copy.W = new int[80]; copy.W = null;
return copy; return copy;
} }
@ -83,7 +82,9 @@ public final class SHA extends DigestBase {
// Load magic initialization constants. // Load magic initialization constants.
resetHashes(); resetHashes();
// clear out old data // clear out old data
Arrays.fill(W, 0); if (W != null) {
Arrays.fill(W, 0);
}
} }
private void resetHashes() { private void resetHashes() {
@ -132,11 +133,12 @@ public final class SHA extends DigestBase {
private void implCompressCheck(byte[] buf, int ofs) { private void implCompressCheck(byte[] buf, int ofs) {
Objects.requireNonNull(buf); Objects.requireNonNull(buf);
// The checks performed by the method 'b2iBig64' // Checks similar to those performed by the method 'b2iBig64'
// are sufficient for the case when the method // are sufficient for the case when the method 'implCompress0' is
// 'implCompress0' is replaced with a compiler // replaced with a compiler intrinsic.
// intrinsic. if (ofs < 0 || (buf.length - ofs) < 64) {
b2iBig64(buf, ofs, W); throw new ArrayIndexOutOfBoundsException();
}
} }
// The method 'implCompress0 seems not to use its parameters. // The method 'implCompress0 seems not to use its parameters.
@ -146,6 +148,10 @@ public final class SHA extends DigestBase {
// must be passed as parameter to the method. // must be passed as parameter to the method.
@IntrinsicCandidate @IntrinsicCandidate
private void implCompress0(byte[] buf, int ofs) { private void implCompress0(byte[] buf, int ofs) {
if (W == null) {
W = new int[80];
}
b2iBig64(buf, ofs, W);
// The first 16 ints have the byte stream, compute the rest of // The first 16 ints have the byte stream, compute the rest of
// the buffer // the buffer
for (int t = 16; t <= 79; t++) { for (int t = 16; t <= 79; t++) {

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -83,7 +83,6 @@ abstract class SHA2 extends DigestBase {
super(name, digestLength, 64); super(name, digestLength, 64);
this.initialHashes = initialHashes; this.initialHashes = initialHashes;
state = new int[8]; state = new int[8];
W = new int[64];
resetHashes(); resetHashes();
} }
@ -92,7 +91,9 @@ abstract class SHA2 extends DigestBase {
*/ */
void implReset() { void implReset() {
resetHashes(); resetHashes();
Arrays.fill(W, 0); if (W != null) {
Arrays.fill(W, 0);
}
} }
private void resetHashes() { private void resetHashes() {
@ -124,11 +125,12 @@ abstract class SHA2 extends DigestBase {
private void implCompressCheck(byte[] buf, int ofs) { private void implCompressCheck(byte[] buf, int ofs) {
Objects.requireNonNull(buf); Objects.requireNonNull(buf);
// The checks performed by the method 'b2iBig64' // Checks similar to those performed by the method 'b2iBig64'
// are sufficient for the case when the method // are sufficient for the case when the method 'implCompress0' is
// 'implCompressImpl' is replaced with a compiler // replaced with a compiler intrinsic.
// intrinsic. if (ofs < 0 || (buf.length - ofs) < 64) {
b2iBig64(buf, ofs, W); throw new ArrayIndexOutOfBoundsException();
}
} }
// The method 'implCompressImpl' seems not to use its parameters. // The method 'implCompressImpl' seems not to use its parameters.
@ -138,6 +140,10 @@ abstract class SHA2 extends DigestBase {
// must be passed as parameter to the method. // must be passed as parameter to the method.
@IntrinsicCandidate @IntrinsicCandidate
private void implCompress0(byte[] buf, int ofs) { private void implCompress0(byte[] buf, int ofs) {
if (W == null) {
W = new int[64];
}
b2iBig64(buf, ofs, W);
// The first 16 ints are from the byte stream, compute the rest of // The first 16 ints are from the byte stream, compute the rest of
// the W[]'s // the W[]'s
for (int t = 16; t < ITERATION; t++) { for (int t = 16; t < ITERATION; t++) {
@ -220,7 +226,7 @@ abstract class SHA2 extends DigestBase {
public Object clone() throws CloneNotSupportedException { public Object clone() throws CloneNotSupportedException {
SHA2 copy = (SHA2) super.clone(); SHA2 copy = (SHA2) super.clone();
copy.state = copy.state.clone(); copy.state = copy.state.clone();
copy.W = new int[64]; copy.W = null;
return copy; return copy;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -98,13 +98,14 @@ abstract class SHA5 extends DigestBase {
super(name, digestLength, 128); super(name, digestLength, 128);
this.initialHashes = initialHashes; this.initialHashes = initialHashes;
state = new long[8]; state = new long[8];
W = new long[80];
resetHashes(); resetHashes();
} }
final void implReset() { final void implReset() {
resetHashes(); resetHashes();
Arrays.fill(W, 0L); if (W != null) {
Arrays.fill(W, 0L);
}
} }
private void resetHashes() { private void resetHashes() {
@ -225,11 +226,12 @@ abstract class SHA5 extends DigestBase {
private void implCompressCheck(byte[] buf, int ofs) { private void implCompressCheck(byte[] buf, int ofs) {
Objects.requireNonNull(buf); Objects.requireNonNull(buf);
// The checks performed by the method 'b2iBig128' // Checks similar to those performed by the method 'b2lBig128'
// are sufficient for the case when the method // are sufficient for the case when the method 'implCompress0' is
// 'implCompressImpl' is replaced with a compiler // replaced with a compiler intrinsic.
// intrinsic. if (ofs < 0 || (buf.length - ofs) < 128) {
b2lBig128(buf, ofs, W); throw new ArrayIndexOutOfBoundsException();
}
} }
// The method 'implCompressImpl' seems not to use its parameters. // The method 'implCompressImpl' seems not to use its parameters.
@ -239,6 +241,10 @@ abstract class SHA5 extends DigestBase {
// must be passed as parameter to the method. // must be passed as parameter to the method.
@IntrinsicCandidate @IntrinsicCandidate
private final void implCompress0(byte[] buf, int ofs) { private final void implCompress0(byte[] buf, int ofs) {
if (W == null) {
W = new long[80];
}
b2lBig128(buf, ofs, W);
// The first 16 longs are from the byte stream, compute the rest of // The first 16 longs are from the byte stream, compute the rest of
// the W[]'s // the W[]'s
for (int t = 16; t < ITERATION; t++) { for (int t = 16; t < ITERATION; t++) {
@ -280,7 +286,7 @@ abstract class SHA5 extends DigestBase {
public Object clone() throws CloneNotSupportedException { public Object clone() throws CloneNotSupportedException {
SHA5 copy = (SHA5) super.clone(); SHA5 copy = (SHA5) super.clone();
copy.state = copy.state.clone(); copy.state = copy.state.clone();
copy.W = new long[80]; copy.W = null;
return copy; return copy;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -45,8 +45,8 @@ import org.openjdk.jmh.annotations.Warmup;
*/ */
@State(Scope.Thread) @State(Scope.Thread)
@OutputTimeUnit(TimeUnit.MILLISECONDS) @OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 5) @Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 10) @Measurement(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(jvmArgsAppend = {"-Xms1024m", "-Xmx1024m", "-Xmn768m", "-XX:+UseParallelGC"}, value = 5) @Fork(jvmArgsAppend = {"-Xms1024m", "-Xmx1024m", "-Xmn768m", "-XX:+UseParallelGC"}, value = 5)
public class MessageDigests { public class MessageDigests {
@ -77,4 +77,15 @@ public class MessageDigests {
public byte[] digest() throws DigestException { public byte[] digest() throws DigestException {
return digester.digest(inputBytes); return digester.digest(inputBytes);
} }
@Benchmark
public byte[] getAndDigest() throws DigestException, NoSuchAlgorithmException, NoSuchProviderException {
MessageDigest md;
if ("DEFAULT".equals(provider)) {
md = MessageDigest.getInstance(digesterName);
} else {
md = MessageDigest.getInstance(digesterName, provider);
}
return md.digest(inputBytes);
}
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -37,6 +37,8 @@ public class UUIDBench {
@Param("20000") @Param("20000")
private int size; private int size;
private byte[][] uuidBytes;
private UUID[] uuids; private UUID[] uuids;
private String[] uuidStrings; private String[] uuidStrings;
@ -45,11 +47,14 @@ public class UUIDBench {
@Setup @Setup
public void setup() { public void setup() {
uuidBytes = new byte[size][];
uuids = new UUID[size]; uuids = new UUID[size];
uuidStrings = new String[size]; uuidStrings = new String[size];
java.util.Random r = new java.util.Random(0);
for (int i = 0; i < this.uuidStrings.length; i++) { for (int i = 0; i < this.uuidStrings.length; i++) {
final UUID uuid = UUID.randomUUID(); final UUID uuid = UUID.randomUUID();
this.uuidBytes[i] = new byte[16];
r.nextBytes(this.uuidBytes[i]);
this.uuids[i] = uuid; this.uuids[i] = uuid;
this.uuidStrings[i] = uuid.toString(); this.uuidStrings[i] = uuid.toString();
} }
@ -72,4 +77,9 @@ public class UUIDBench {
public String toString() { public String toString() {
return uuids[index].toString(); return uuids[index].toString();
} }
@Benchmark
public UUID fromType3Bytes() {
return UUID.nameUUIDFromBytes(uuidBytes[index]);
}
} }