1 Star 0 Fork 82

xuyuchao/openjdk-1.8.0

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
8308682-Enhance-AES-performance.patch 25.35 KB
一键复制 编辑 原始数据 按行查看 历史
kuen 提交于 2023-10-20 10:33 . upgrade to jdk8u392
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
From 6926e9b83bc3f9b785d5298786a5c41e247b2a3f Mon Sep 17 00:00:00 2001
Date: Mon, 16 Oct 2023 10:56:30 +0800
Subject: [PATCH 1/5] 8308682: Enhance AES performance
Bug url: https://bugs.openjdk.org/browse/JDK-8308682
---
.../src/cpu/aarch64/vm/assembler_aarch64.hpp | 2 +
.../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 451 +++++++++---------
.../compiler/codegen/aes/CTR_Wraparound.java | 169 +++++++
3 files changed, 406 insertions(+), 216 deletions(-)
create mode 100644 hotspot/test/compiler/codegen/aes/CTR_Wraparound.java
diff --git a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
index 9202e61f8..b12095aca 100644
--- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
@@ -2140,6 +2140,8 @@ public:
INSN(sshl, 0, 0b010001);
INSN(ushl, 1, 0b010001);
+ INSN(cmhi, 1, 0b001101); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
+
#undef INSN
#define INSN(NAME, opc, opc2) \
diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
index 565fe559c..f61028d50 100644
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
@@ -2804,265 +2804,284 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ // Big-endian 128-bit + 64-bit -> 128-bit addition.
+ // Inputs: 128-bits. in is preserved.
+ // The least-significant 64-bit word is in the upper dword of the vector
+ // inc (the 64-bit increment) is preserved. Its lower dword must be zero
+ // Output: result
+ void be_add_128_64(FloatRegister result, FloatRegister in,
+ FloatRegister inc, FloatRegister tmp) {
+ assert_different_registers(result, tmp, inc);
+
+ __ addv(result, __ T2D, in, inc); // Add inc to the least-significant dword of input
+ __ cmhi(tmp, __ T2D, inc, result); // Check for result overflowing
+ __ ins(tmp, __ D, tmp, 0, 1); // Move LSD of comparison result to MSD
+ __ ins(tmp, __ D, inc, 1, 0); // Move 0 to LSD of comparison result
+ __ subv(result, __ T2D, result, tmp); // Subtract -1 from MSD if there was an overflow
+ }
+
// CTR AES crypt.
- // Arguments:
- //
- // Inputs:
- // c_rarg0 - source byte array address
- // c_rarg1 - destination byte array address
- // c_rarg2 - K (key) in little endian int array
- // c_rarg3 - counter vector byte array address
- // c_rarg4 - input length
- // c_rarg5 - saved encryptedCounter start
- // c_rarg6 - saved used length
+ // Arguments:
+ //
+ // Inputs:
+ // c_rarg0 - source byte array address
+ // c_rarg1 - destination byte array address
+ // c_rarg2 - K (key) in little endian int array
+ // c_rarg3 - counter vector byte array address
+ // c_rarg4 - input length
+ // c_rarg5 - saved encryptedCounter start
+ // c_rarg6 - saved used length
+ //
+ // Output:
+ // r0 - input length
+ //
+ address generate_counterMode_AESCrypt() {
+ const Register in = c_rarg0;
+ const Register out = c_rarg1;
+ const Register key = c_rarg2;
+ const Register counter = c_rarg3;
+ const Register saved_len = c_rarg4, len = r10;
+ const Register saved_encrypted_ctr = c_rarg5;
+ const Register used_ptr = c_rarg6, used = r12;
+
+ const Register offset = r7;
+ const Register keylen = r11;
+
+ const unsigned char block_size = 16;
+ const int bulk_width = 4;
+ // NB: bulk_width can be 4 or 8. 8 gives slightly faster
+ // performance with larger data sizes, but it also means that the
+ // fast path isn't used until you have at least 8 blocks, and up
+ // to 127 bytes of data will be executed on the slow path. For
+ // that reason, and also so as not to blow away too much icache, 4
+ // blocks seems like a sensible compromise.
+
+ // Algorithm:
//
- // Output:
- // r0 - input length
+ // if (len == 0) {
+ // goto DONE;
+ // }
+ // int result = len;
+ // do {
+ // if (used >= blockSize) {
+ // if (len >= bulk_width * blockSize) {
+ // CTR_large_block();
+ // if (len == 0)
+ // goto DONE;
+ // }
+ // for (;;) {
+ // 16ByteVector v0 = counter;
+ // embeddedCipher.encryptBlock(v0, 0, encryptedCounter, 0);
+ // used = 0;
+ // if (len < blockSize)
+ // break; /* goto NEXT */
+ // 16ByteVector v1 = load16Bytes(in, offset);
+ // v1 = v1 ^ encryptedCounter;
+ // store16Bytes(out, offset);
+ // used = blockSize;
+ // offset += blockSize;
+ // len -= blockSize;
+ // if (len == 0)
+ // goto DONE;
+ // }
+ // }
+ // NEXT:
+ // out[outOff++] = (byte)(in[inOff++] ^ encryptedCounter[used++]);
+ // len--;
+ // } while (len != 0);
+ // DONE:
+ // return result;
//
- address generate_counterMode_AESCrypt() {
- const Register in = c_rarg0;
- const Register out = c_rarg1;
- const Register key = c_rarg2;
- const Register counter = c_rarg3;
- const Register saved_len = c_rarg4, len = r10;
- const Register saved_encrypted_ctr = c_rarg5;
- const Register used_ptr = c_rarg6, used = r12;
-
- const Register offset = r7;
- const Register keylen = r11;
-
- const unsigned char block_size = 16;
- const int bulk_width = 4;
- // NB: bulk_width can be 4 or 8. 8 gives slightly faster
- // performance with larger data sizes, but it also means that the
- // fast path isn't used until you have at least 8 blocks, and up
- // to 127 bytes of data will be executed on the slow path. For
- // that reason, and also so as not to blow away too much icache, 4
- // blocks seems like a sensible compromise.
-
- // Algorithm:
- //
- // if (len == 0) {
- // goto DONE;
- // }
- // int result = len;
- // do {
- // if (used >= blockSize) {
- // if (len >= bulk_width * blockSize) {
- // CTR_large_block();
- // if (len == 0)
- // goto DONE;
- // }
- // for (;;) {
- // 16ByteVector v0 = counter;
- // embeddedCipher.encryptBlock(v0, 0, encryptedCounter, 0);
- // used = 0;
- // if (len < blockSize)
- // break; /* goto NEXT */
- // 16ByteVector v1 = load16Bytes(in, offset);
- // v1 = v1 ^ encryptedCounter;
- // store16Bytes(out, offset);
- // used = blockSize;
- // offset += blockSize;
- // len -= blockSize;
- // if (len == 0)
- // goto DONE;
- // }
- // }
- // NEXT:
- // out[outOff++] = (byte)(in[inOff++] ^ encryptedCounter[used++]);
- // len--;
- // } while (len != 0);
- // DONE:
- // return result;
- //
- // CTR_large_block()
- // Wide bulk encryption of whole blocks.
+ // CTR_large_block()
+ // Wide bulk encryption of whole blocks.
- __ align(CodeEntryAlignment);
- StubCodeMark mark(this, "StubRoutines", "counterMode_AESCrypt");
- const address start = __ pc();
- __ enter();
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "counterMode_AESCrypt");
+ const address start = __ pc();
+ __ enter();
- Label DONE, CTR_large_block, large_block_return;
- __ ldrw(used, Address(used_ptr));
- __ cbzw(saved_len, DONE);
+ Label DONE, CTR_large_block, large_block_return;
+ __ ldrw(used, Address(used_ptr));
+ __ cbzw(saved_len, DONE);
- __ mov(len, saved_len);
- __ mov(offset, 0);
+ __ mov(len, saved_len);
+ __ mov(offset, 0);
- // Compute #rounds for AES based on the length of the key array
- __ ldrw(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
+ // Compute #rounds for AES based on the length of the key array
+ __ ldrw(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
- __ aesenc_loadkeys(key, keylen);
+ __ aesenc_loadkeys(key, keylen);
- {
- Label L_CTR_loop, NEXT;
+ {
+ Label L_CTR_loop, NEXT;
- __ bind(L_CTR_loop);
+ __ bind(L_CTR_loop);
- __ cmp(used, block_size);
- __ br(__ LO, NEXT);
+ __ cmp(used, block_size);
+ __ br(__ LO, NEXT);
- // Maybe we have a lot of data
- __ subsw(rscratch1, len, bulk_width * block_size);
- __ br(__ HS, CTR_large_block);
- __ BIND(large_block_return);
- __ cbzw(len, DONE);
+ // Maybe we have a lot of data
+ __ subsw(rscratch1, len, bulk_width * block_size);
+ __ br(__ HS, CTR_large_block);
+ __ BIND(large_block_return);
+ __ cbzw(len, DONE);
- // Setup the counter
- __ movi(v4, __ T4S, 0);
- __ movi(v5, __ T4S, 1);
- __ ins(v4, __ S, v5, 3, 3); // v4 contains { 0, 0, 0, 1 }
+ // Setup the counter
+ __ movi(v4, __ T4S, 0);
+ __ movi(v5, __ T4S, 1);
+ __ ins(v4, __ S, v5, 2, 2); // v4 contains { 0, 1 }
- __ ld1(v0, __ T16B, counter); // Load the counter into v0
- __ rev32(v16, __ T16B, v0);
- __ addv(v16, __ T4S, v16, v4);
- __ rev32(v16, __ T16B, v16);
- __ st1(v16, __ T16B, counter); // Save the incremented counter back
+ // 128-bit big-endian increment
+ __ ld1(v0, __ T16B, counter);
+ __ rev64(v16, __ T16B, v0);
+ be_add_128_64(v16, v16, v4, /*tmp*/v5);
+ __ rev64(v16, __ T16B, v16);
+ __ st1(v16, __ T16B, counter);
+ // Previous counter value is in v0
+ // v4 contains { 0, 1 }
- {
- // We have fewer than bulk_width blocks of data left. Encrypt
- // them one by one until there is less than a full block
- // remaining, being careful to save both the encrypted counter
- // and the counter.
-
- Label inner_loop;
- __ bind(inner_loop);
- // Counter to encrypt is in v0
- __ aesecb_encrypt(noreg, noreg, keylen);
- __ st1(v0, __ T16B, saved_encrypted_ctr);
-
- // Do we have a remaining full block?
-
- __ mov(used, 0);
- __ cmp(len, block_size);
- __ br(__ LO, NEXT);
-
- // Yes, we have a full block
- __ ldrq(v1, Address(in, offset));
- __ eor(v1, __ T16B, v1, v0);
- __ strq(v1, Address(out, offset));
- __ mov(used, block_size);
- __ add(offset, offset, block_size);
-
- __ subw(len, len, block_size);
- __ cbzw(len, DONE);
-
- // Increment the counter, store it back
- __ orr(v0, __ T16B, v16, v16);
- __ rev32(v16, __ T16B, v16);
- __ addv(v16, __ T4S, v16, v4);
- __ rev32(v16, __ T16B, v16);
- __ st1(v16, __ T16B, counter); // Save the incremented counter back
-
- __ b(inner_loop);
- }
+ {
+ // We have fewer than bulk_width blocks of data left. Encrypt
+ // them one by one until there is less than a full block
+ // remaining, being careful to save both the encrypted counter
+ // and the counter.
- __ BIND(NEXT);
-
- // Encrypt a single byte, and loop.
- // We expect this to be a rare event.
- __ ldrb(rscratch1, Address(in, offset));
- __ ldrb(rscratch2, Address(saved_encrypted_ctr, used));
- __ eor(rscratch1, rscratch1, rscratch2);
- __ strb(rscratch1, Address(out, offset));
- __ add(offset, offset, 1);
- __ add(used, used, 1);
- __ subw(len, len,1);
- __ cbnzw(len, L_CTR_loop);
- }
+ Label inner_loop;
+ __ bind(inner_loop);
+ // Counter to encrypt is in v0
+ __ aesecb_encrypt(noreg, noreg, keylen);
+ __ st1(v0, __ T16B, saved_encrypted_ctr);
- __ bind(DONE);
- __ strw(used, Address(used_ptr));
- __ mov(r0, saved_len);
+ // Do we have a remaining full block?
- __ leave(); // required for proper stackwalking of RuntimeStub frame
- __ ret(lr);
+ __ mov(used, 0);
+ __ cmp(len, block_size);
+ __ br(__ LO, NEXT);
- // Bulk encryption
+ // Yes, we have a full block
+ __ ldrq(v1, Address(in, offset));
+ __ eor(v1, __ T16B, v1, v0);
+ __ strq(v1, Address(out, offset));
+ __ mov(used, block_size);
+ __ add(offset, offset, block_size);
- __ BIND (CTR_large_block);
- assert(bulk_width == 4 || bulk_width == 8, "must be");
+ __ subw(len, len, block_size);
+ __ cbzw(len, DONE);
- if (bulk_width == 8) {
- __ sub(sp, sp, 4 * 16);
- __ st1(v12, v13, v14, v15, __ T16B, Address(sp));
+ // Increment the counter, store it back
+ __ orr(v0, __ T16B, v16, v16);
+ __ rev64(v16, __ T16B, v16);
+ be_add_128_64(v16, v16, v4, /*tmp*/v5);
+ __ rev64(v16, __ T16B, v16);
+ __ st1(v16, __ T16B, counter); // Save the incremented counter back
+
+ __ b(inner_loop);
}
- __ sub(sp, sp, 4 * 16);
- __ st1(v8, v9, v10, v11, __ T16B, Address(sp));
- RegSet saved_regs = (RegSet::of(in, out, offset)
- + RegSet::of(saved_encrypted_ctr, used_ptr, len));
- __ push(saved_regs, sp);
- __ andr(len, len, -16 * bulk_width); // 8/4 encryptions, 16 bytes per encryption
- __ add(in, in, offset);
- __ add(out, out, offset);
- // Keys should already be loaded into the correct registers
+ __ BIND(NEXT);
+
+ // Encrypt a single byte, and loop.
+ // We expect this to be a rare event.
+ __ ldrb(rscratch1, Address(in, offset));
+ __ ldrb(rscratch2, Address(saved_encrypted_ctr, used));
+ __ eor(rscratch1, rscratch1, rscratch2);
+ __ strb(rscratch1, Address(out, offset));
+ __ add(offset, offset, 1);
+ __ add(used, used, 1);
+ __ subw(len, len,1);
+ __ cbnzw(len, L_CTR_loop);
+ }
- __ ld1(v0, __ T16B, counter); // v0 contains the first counter
- __ rev32(v16, __ T16B, v0); // v16 contains byte-reversed counter
+ __ bind(DONE);
+ __ strw(used, Address(used_ptr));
+ __ mov(r0, saved_len);
- // AES/CTR loop
- {
- Label L_CTR_loop;
- __ BIND(L_CTR_loop);
+ __ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ ret(lr);
- // Setup the counters
- __ movi(v8, __ T4S, 0);
- __ movi(v9, __ T4S, 1);
- __ ins(v8, __ S, v9, 3, 3); // v8 contains { 0, 0, 0, 1 }
+ // Bulk encryption
- for (FloatRegister f = v0; f < v0 + bulk_width; f++) {
- __ rev32(f, __ T16B, v16);
- __ addv(v16, __ T4S, v16, v8);
- }
+ __ BIND (CTR_large_block);
+ assert(bulk_width == 4 || bulk_width == 8, "must be");
- __ ld1(v8, v9, v10, v11, __ T16B, __ post(in, 4 * 16));
+ if (bulk_width == 8) {
+ __ sub(sp, sp, 4 * 16);
+ __ st1(v12, v13, v14, v15, __ T16B, Address(sp));
+ }
+ __ sub(sp, sp, 4 * 16);
+ __ st1(v8, v9, v10, v11, __ T16B, Address(sp));
+ RegSet saved_regs = (RegSet::of(in, out, offset)
+ + RegSet::of(saved_encrypted_ctr, used_ptr, len));
+ __ push(saved_regs, sp);
+ __ andr(len, len, -16 * bulk_width); // 8/4 encryptions, 16 bytes per encryption
+ __ add(in, in, offset);
+ __ add(out, out, offset);
- // Encrypt the counters
- __ aesecb_encrypt(noreg, noreg, keylen, v0, bulk_width);
+ // Keys should already be loaded into the correct registers
- if (bulk_width == 8) {
- __ ld1(v12, v13, v14, v15, __ T16B, __ post(in, 4 * 16));
- }
+ __ ld1(v0, __ T16B, counter); // v0 contains the first counter
+ __ rev64(v16, __ T16B, v0); // v16 contains byte-reversed counter
- // XOR the encrypted counters with the inputs
- for (int i = 0; i < bulk_width; i++) {
- __ eor(v0 + i, __ T16B, v0 + i, v8 + i);
- }
+ // AES/CTR loop
+ {
+ Label L_CTR_loop;
+ __ BIND(L_CTR_loop);
- // Write the encrypted data
- __ st1(v0, v1, v2, v3, __ T16B, __ post(out, 4 * 16));
- if (bulk_width == 8) {
- __ st1(v4, v5, v6, v7, __ T16B, __ post(out, 4 * 16));
- }
+ // Setup the counters
+ __ movi(v8, __ T4S, 0);
+ __ movi(v9, __ T4S, 1);
+ __ ins(v8, __ S, v9, 2, 2); // v8 contains { 0, 1 }
- __ subw(len, len, 16 * bulk_width);
- __ cbnzw(len, L_CTR_loop);
+ for (FloatRegister f = v0; f < v0 + bulk_width; f++) {
+ __ rev64(f, __ T16B, v16);
+ be_add_128_64(v16, v16, v8, /*tmp*/v9);
}
- // Save the counter back where it goes
- __ rev32(v16, __ T16B, v16);
- __ st1(v16, __ T16B, counter);
+ __ ld1(v8, v9, v10, v11, __ T16B, __ post(in, 4 * 16));
- __ pop(saved_regs, sp);
+ // Encrypt the counters
+ __ aesecb_encrypt(noreg, noreg, keylen, v0, bulk_width);
- __ ld1(v8, v9, v10, v11, __ T16B, __ post(sp, 4 * 16));
if (bulk_width == 8) {
- __ ld1(v12, v13, v14, v15, __ T16B, __ post(sp, 4 * 16));
+ __ ld1(v12, v13, v14, v15, __ T16B, __ post(in, 4 * 16));
}
- __ andr(rscratch1, len, -16 * bulk_width);
- __ sub(len, len, rscratch1);
- __ add(offset, offset, rscratch1);
- __ mov(used, 16);
- __ strw(used, Address(used_ptr));
- __ b(large_block_return);
+ // XOR the encrypted counters with the inputs
+ for (int i = 0; i < bulk_width; i++) {
+ __ eor(v0 + i, __ T16B, v0 + i, v8 + i);
+ }
- return start;
+ // Write the encrypted data
+ __ st1(v0, v1, v2, v3, __ T16B, __ post(out, 4 * 16));
+ if (bulk_width == 8) {
+ __ st1(v4, v5, v6, v7, __ T16B, __ post(out, 4 * 16));
+ }
+
+ __ subw(len, len, 16 * bulk_width);
+ __ cbnzw(len, L_CTR_loop);
}
+ // Save the counter back where it goes
+ __ rev64(v16, __ T16B, v16);
+ __ st1(v16, __ T16B, counter);
+
+ __ pop(saved_regs, sp);
+
+ __ ld1(v8, v9, v10, v11, __ T16B, __ post(sp, 4 * 16));
+ if (bulk_width == 8) {
+ __ ld1(v12, v13, v14, v15, __ T16B, __ post(sp, 4 * 16));
+ }
+
+ __ andr(rscratch1, len, -16 * bulk_width);
+ __ sub(len, len, rscratch1);
+ __ add(offset, offset, rscratch1);
+ __ mov(used, 16);
+ __ strw(used, Address(used_ptr));
+ __ b(large_block_return);
+
+ return start;
+ }
+
// Arguments:
diff --git a/hotspot/test/compiler/codegen/aes/CTR_Wraparound.java b/hotspot/test/compiler/codegen/aes/CTR_Wraparound.java
new file mode 100644
index 000000000..f578b432c
--- /dev/null
+++ b/hotspot/test/compiler/codegen/aes/CTR_Wraparound.java
@@ -0,0 +1,169 @@
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.lang.reflect.Executable;
+import java.util.Arrays;
+import java.util.Random;
+import java.util.concurrent.Callable;
+
+/**
+ * @test
+ * @bug 8308682
+ * @summary Check for 128-bit AES/CTR wraparound
+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox /compiler/testlibrary
+ * @build CTR_Wraparound
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * CTR_Wraparound 32
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * CTR_Wraparound 1009
+ * @run main/othervm -Xbootclasspath/a:.
+ * -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI
+ * CTR_Wraparound 2048
+ */
+
+public class CTR_Wraparound extends CompilerWhiteBoxTest {
+ private static final String ALGO = "AES/CTR/NoPadding";
+ private static final int LOOPS = 100000;
+ private int length;
+ private int maxOffset;
+
+ public CTR_Wraparound(int len,int offset){
+ super(new CTR_WraparoundTestCase());
+ length = len;
+ maxOffset = offset;
+ }
+
+ public static class CTR_WraparoundTestCase implements TestCase {
+
+ public String name() {
+ return "CTR_WraparoundTestCase";
+ }
+
+ public Executable getExecutable(){
+ try {
+ return Class.forName("com.sun.crypto.provider.CounterMode").getDeclaredMethod("implCrypt", byte[].class, int.class, int.class, byte[].class, int.class);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Test bug, method unavailable. " + e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Test bug, class unavailable. " + e);
+ }
+ }
+
+ public Callable<Integer> getCallable() {
+ return null;
+ }
+
+ public boolean isOsr() {
+ return false;
+ }
+
+ }
+
+ private static boolean isServerVM(String VMName) { return VMName.toLowerCase().contains("server");}
+
+
+
+ protected static boolean checkIntrinsicForCompilationLevel(Executable method, int compLevel) {
+ boolean intrinsicEnabled = Boolean.valueOf(getVMOption("UseAESCTRIntrinsics"));
+ boolean intrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(method,
+ compLevel);
+ if(intrinsicAvailable && intrinsicEnabled){
+ return true;
+ }
+ return false;
+ }
+
+ public static void main(String[] args) throws Exception {
+ int length = Integer.parseInt(args[0]);
+ int maxOffset = 60;
+ if (args.length > 1) {
+ maxOffset = Integer.parseInt(args[1]);
+ System.out.println("InitialOffset = " + maxOffset);
+ }
+ new CTR_Wraparound(length,maxOffset).test();
+ }
+
+ @Override
+ protected void test() throws Exception {
+
+ String VMName = System.getProperty("java.vm.name");
+ Executable intrinsicMethod = testCase.getExecutable();
+ boolean isIntrinsicEnabled = false;
+ if (isServerVM(VMName)) {
+ if (TIERED_COMPILATION) {
+ isIntrinsicEnabled = checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE);
+ }
+ isIntrinsicEnabled = checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_FULL_OPTIMIZATION);
+ } else {
+ isIntrinsicEnabled = checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE);
+ }
+ if(!isIntrinsicEnabled){
+ return;
+ }
+
+
+ long SEED = Long.getLong("jdk.test.lib.random.seed", new Random().nextLong());
+ Random random = new Random(SEED);
+
+ byte[] keyBytes = new byte[32];
+ Arrays.fill(keyBytes, (byte)0xff);
+ SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
+
+ byte[] ivBytes = new byte[16];
+
+ Arrays.fill(ivBytes, (byte)0xff);
+
+ byte[][] plaintext = new byte[maxOffset][];
+ byte[][] ciphertext = new byte[maxOffset][];
+
+ for (int offset = 0; offset < maxOffset; offset++) {
+ ivBytes[ivBytes.length - 1] = (byte)-offset;
+ IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+ Cipher encryptCipher = Cipher.getInstance(ALGO);
+ Cipher decryptCipher = Cipher.getInstance(ALGO);
+
+ encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv);
+ decryptCipher.init(Cipher.DECRYPT_MODE, key, iv);
+
+ plaintext[offset] = new byte[length];
+ ciphertext[offset] = new byte[length];
+ random.nextBytes(plaintext[offset]);
+
+ byte[] decrypted = new byte[length];
+
+ encryptCipher.doFinal(plaintext[offset], 0, length, ciphertext[offset]);
+ decryptCipher.doFinal(ciphertext[offset], 0, length, decrypted);
+
+ if (!Arrays.equals(plaintext[offset], decrypted)) {
+ throw new Exception("mismatch in setup at offset " + offset);
+ }
+ }
+
+ for (int offset = 0; offset < maxOffset; offset++) {
+ ivBytes[ivBytes.length - 1] = (byte)-offset;
+ IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+ Cipher encryptCipher = Cipher.getInstance(ALGO);
+
+ encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv);
+
+ byte[] encrypted = new byte[length];
+
+ for (int i = 0; i < LOOPS; i++) {
+ encryptCipher.doFinal(plaintext[offset], 0, length, encrypted);
+ if (!Arrays.equals(ciphertext[offset], encrypted)) {
+ throw new Exception("array mismatch at offset " + offset
+ + " with length " + length);
+ }
+ }
+ }
+ }
+}
--
2.19.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/xuyuchao/openjdk-1.8.0.git
git@gitee.com:xuyuchao/openjdk-1.8.0.git
xuyuchao
openjdk-1.8.0
openjdk-1.8.0
master

搜索帮助