Projects
Mega:24.09
openjdk-1.8.0
_service:tar_scm:8308682-Enhance-AES-performanc...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:8308682-Enhance-AES-performance.patch of Package openjdk-1.8.0
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2