8225625: AES Electronic Codebook (ECB) encryption and decryption optimization using AVX512 + VAES instructions
AES-ECB encryption and decryption optimization for x86_64 architectures supporting AVX3+VAES Co-authored-by: Smita Kamath <smita.kamath@intel.com> Reviewed-by: kvn, valeriep
This commit is contained in:
parent
0b9a90e0d1
commit
793585b494
@ -1380,6 +1380,15 @@ void Assembler::aesenc(XMMRegister dst, XMMRegister src) {
|
||||
emit_int8(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::vaesenc(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_vaes(), "requires vaes support/enabling");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
|
||||
emit_int8((unsigned char)0xDC);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::aesenclast(XMMRegister dst, Address src) {
|
||||
assert(VM_Version::supports_aes(), "");
|
||||
InstructionMark im(this);
|
||||
@ -1397,6 +1406,15 @@ void Assembler::aesenclast(XMMRegister dst, XMMRegister src) {
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::vaesenclast(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_vaes(), "requires vaes support/enabling");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes);
|
||||
emit_int8((unsigned char)0xDD);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::andl(Address dst, int32_t imm32) {
|
||||
InstructionMark im(this);
|
||||
prefix(dst);
|
||||
|
@ -968,6 +968,9 @@ private:
|
||||
void aesenc(XMMRegister dst, XMMRegister src);
|
||||
void aesenclast(XMMRegister dst, Address src);
|
||||
void aesenclast(XMMRegister dst, XMMRegister src);
|
||||
// Vector AES instructions
|
||||
void vaesenc(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
|
||||
void vaesenclast(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
|
||||
void vaesdec(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
|
||||
void vaesdeclast(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
|
||||
|
||||
|
@ -982,6 +982,17 @@ class MacroAssembler: public Assembler {
|
||||
XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4,
|
||||
Register buf, Register state, Register ofs, Register limit, Register rsp, bool multi_block,
|
||||
XMMRegister shuf_mask);
|
||||
private:
|
||||
void roundEnc(XMMRegister key, int rnum);
|
||||
void lastroundEnc(XMMRegister key, int rnum);
|
||||
void roundDec(XMMRegister key, int rnum);
|
||||
void lastroundDec(XMMRegister key, int rnum);
|
||||
void ev_load_key(XMMRegister xmmdst, Register key, int offset, XMMRegister xmm_shuf_mask);
|
||||
|
||||
public:
|
||||
void aesecb_encrypt(Register source_addr, Register dest_addr, Register key, Register len);
|
||||
void aesecb_decrypt(Register source_addr, Register dest_addr, Register key, Register len);
|
||||
|
||||
#endif
|
||||
|
||||
void fast_sha1(XMMRegister abcd, XMMRegister e0, XMMRegister e1, XMMRegister msg0,
|
||||
|
@ -30,6 +30,463 @@
|
||||
#include "macroAssembler_x86.hpp"
|
||||
|
||||
#ifdef _LP64
|
||||
|
||||
void MacroAssembler::roundEnc(XMMRegister key, int rnum) {
|
||||
for (int xmm_reg_no = 0; xmm_reg_no <=rnum; xmm_reg_no++) {
|
||||
vaesenc(as_XMMRegister(xmm_reg_no), as_XMMRegister(xmm_reg_no), key, Assembler::AVX_512bit);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::lastroundEnc(XMMRegister key, int rnum) {
|
||||
for (int xmm_reg_no = 0; xmm_reg_no <=rnum; xmm_reg_no++) {
|
||||
vaesenclast(as_XMMRegister(xmm_reg_no), as_XMMRegister(xmm_reg_no), key, Assembler::AVX_512bit);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::roundDec(XMMRegister key, int rnum) {
|
||||
for (int xmm_reg_no = 0; xmm_reg_no <=rnum; xmm_reg_no++) {
|
||||
vaesdec(as_XMMRegister(xmm_reg_no), as_XMMRegister(xmm_reg_no), key, Assembler::AVX_512bit);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::lastroundDec(XMMRegister key, int rnum) {
|
||||
for (int xmm_reg_no = 0; xmm_reg_no <=rnum; xmm_reg_no++) {
|
||||
vaesdeclast(as_XMMRegister(xmm_reg_no), as_XMMRegister(xmm_reg_no), key, Assembler::AVX_512bit);
|
||||
}
|
||||
}
|
||||
|
||||
// Load key and shuffle operation
|
||||
void MacroAssembler::ev_load_key(XMMRegister xmmdst, Register key, int offset, XMMRegister xmm_shuf_mask=NULL) {
|
||||
movdqu(xmmdst, Address(key, offset));
|
||||
if (xmm_shuf_mask != NULL) {
|
||||
pshufb(xmmdst, xmm_shuf_mask);
|
||||
} else {
|
||||
pshufb(xmmdst, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
||||
}
|
||||
evshufi64x2(xmmdst, xmmdst, xmmdst, 0x0, Assembler::AVX_512bit);
|
||||
}
|
||||
|
||||
// AES-ECB Encrypt Operation
|
||||
void MacroAssembler::aesecb_encrypt(Register src_addr, Register dest_addr, Register key, Register len) {
|
||||
|
||||
const Register pos = rax;
|
||||
const Register rounds = r12;
|
||||
|
||||
Label NO_PARTS, LOOP, Loop_start, LOOP2, AES192, END_LOOP, AES256, REMAINDER, LAST2, END, KEY_192, KEY_256, EXIT;
|
||||
push(r13);
|
||||
push(r12);
|
||||
|
||||
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
|
||||
// context for the registers used, where all instructions below are using 128-bit mode
|
||||
// On EVEX without VL and BW, these instructions will all be AVX.
|
||||
if (VM_Version::supports_avx512vlbw()) {
|
||||
movl(rax, 0xffff);
|
||||
kmovql(k1, rax);
|
||||
}
|
||||
push(len); // Save
|
||||
push(rbx);
|
||||
|
||||
vzeroupper();
|
||||
|
||||
xorptr(pos, pos);
|
||||
|
||||
// Calculate number of rounds based on key length(128, 192, 256):44 for 10-rounds, 52 for 12-rounds, 60 for 14-rounds
|
||||
movl(rounds, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||
|
||||
// Load Key shuf mask
|
||||
const XMMRegister xmm_key_shuf_mask = xmm31; // used temporarily to swap key bytes up front
|
||||
movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
||||
|
||||
// Load and shuffle key based on number of rounds
|
||||
ev_load_key(xmm8, key, 0 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm9, key, 1 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm10, key, 2 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm23, key, 3 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm12, key, 4 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm13, key, 5 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm14, key, 6 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm15, key, 7 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm16, key, 8 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm17, key, 9 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm24, key, 10 * 16, xmm_key_shuf_mask);
|
||||
cmpl(rounds, 52);
|
||||
jcc(Assembler::greaterEqual, KEY_192);
|
||||
jmp(Loop_start);
|
||||
|
||||
bind(KEY_192);
|
||||
ev_load_key(xmm19, key, 11 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm20, key, 12 * 16, xmm_key_shuf_mask);
|
||||
cmpl(rounds, 60);
|
||||
jcc(Assembler::equal, KEY_256);
|
||||
jmp(Loop_start);
|
||||
|
||||
bind(KEY_256);
|
||||
ev_load_key(xmm21, key, 13 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm22, key, 14 * 16, xmm_key_shuf_mask);
|
||||
|
||||
bind(Loop_start);
|
||||
movq(rbx, len);
|
||||
// Divide length by 16 to convert it to number of blocks
|
||||
shrq(len, 4);
|
||||
shlq(rbx, 60);
|
||||
jcc(Assembler::equal, NO_PARTS);
|
||||
addq(len, 1);
|
||||
// Check if number of blocks is greater than or equal to 32
|
||||
// If true, 512 bytes are processed at a time (code marked by label LOOP)
|
||||
// If not, 16 bytes are processed (code marked by REMAINDER label)
|
||||
bind(NO_PARTS);
|
||||
movq(rbx, len);
|
||||
shrq(len, 5);
|
||||
jcc(Assembler::equal, REMAINDER);
|
||||
movl(r13, len);
|
||||
// Compute number of blocks that will be processed 512 bytes at a time
|
||||
// Subtract this from the total number of blocks which will then be processed by REMAINDER loop
|
||||
shlq(r13, 5);
|
||||
subq(rbx, r13);
|
||||
//Begin processing 512 bytes
|
||||
bind(LOOP);
|
||||
// Move 64 bytes of PT data into a zmm register, as a result 512 bytes of PT loaded in zmm0-7
|
||||
evmovdquq(xmm0, Address(src_addr, pos, Address::times_1, 0 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm1, Address(src_addr, pos, Address::times_1, 1 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm2, Address(src_addr, pos, Address::times_1, 2 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm3, Address(src_addr, pos, Address::times_1, 3 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm4, Address(src_addr, pos, Address::times_1, 4 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm5, Address(src_addr, pos, Address::times_1, 5 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm6, Address(src_addr, pos, Address::times_1, 6 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm7, Address(src_addr, pos, Address::times_1, 7 * 64), Assembler::AVX_512bit);
|
||||
// Xor with the first round key
|
||||
evpxorq(xmm0, xmm0, xmm8, Assembler::AVX_512bit);
|
||||
evpxorq(xmm1, xmm1, xmm8, Assembler::AVX_512bit);
|
||||
evpxorq(xmm2, xmm2, xmm8, Assembler::AVX_512bit);
|
||||
evpxorq(xmm3, xmm3, xmm8, Assembler::AVX_512bit);
|
||||
evpxorq(xmm4, xmm4, xmm8, Assembler::AVX_512bit);
|
||||
evpxorq(xmm5, xmm5, xmm8, Assembler::AVX_512bit);
|
||||
evpxorq(xmm6, xmm6, xmm8, Assembler::AVX_512bit);
|
||||
evpxorq(xmm7, xmm7, xmm8, Assembler::AVX_512bit);
|
||||
// 9 Aes encode round operations
|
||||
roundEnc(xmm9, 7);
|
||||
roundEnc(xmm10, 7);
|
||||
roundEnc(xmm23, 7);
|
||||
roundEnc(xmm12, 7);
|
||||
roundEnc(xmm13, 7);
|
||||
roundEnc(xmm14, 7);
|
||||
roundEnc(xmm15, 7);
|
||||
roundEnc(xmm16, 7);
|
||||
roundEnc(xmm17, 7);
|
||||
cmpl(rounds, 52);
|
||||
jcc(Assembler::aboveEqual, AES192);
|
||||
// Aesenclast round operation for keysize = 128
|
||||
lastroundEnc(xmm24, 7);
|
||||
jmp(END_LOOP);
|
||||
//Additional 2 rounds of Aesenc operation for keysize = 192
|
||||
bind(AES192);
|
||||
roundEnc(xmm24, 7);
|
||||
roundEnc(xmm19, 7);
|
||||
cmpl(rounds, 60);
|
||||
jcc(Assembler::aboveEqual, AES256);
|
||||
// Aesenclast round for keysize = 192
|
||||
lastroundEnc(xmm20, 7);
|
||||
jmp(END_LOOP);
|
||||
// 2 rounds of Aesenc operation and Aesenclast for keysize = 256
|
||||
bind(AES256);
|
||||
roundEnc(xmm20, 7);
|
||||
roundEnc(xmm21, 7);
|
||||
lastroundEnc(xmm22, 7);
|
||||
|
||||
bind(END_LOOP);
|
||||
// Move 512 bytes of CT to destination
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 0 * 64), xmm0, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 1 * 64), xmm1, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 2 * 64), xmm2, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 3 * 64), xmm3, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 4 * 64), xmm4, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 5 * 64), xmm5, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 6 * 64), xmm6, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 7 * 64), xmm7, Assembler::AVX_512bit);
|
||||
|
||||
addq(pos, 512);
|
||||
decq(len);
|
||||
jcc(Assembler::notEqual, LOOP);
|
||||
|
||||
bind(REMAINDER);
|
||||
vzeroupper();
|
||||
cmpq(rbx, 0);
|
||||
jcc(Assembler::equal, END);
|
||||
// Process 16 bytes at a time
|
||||
bind(LOOP2);
|
||||
movdqu(xmm1, Address(src_addr, pos, Address::times_1, 0));
|
||||
vpxor(xmm1, xmm1, xmm8, Assembler::AVX_128bit);
|
||||
// xmm2 contains shuffled key for Aesenclast operation.
|
||||
vmovdqu(xmm2, xmm24);
|
||||
|
||||
vaesenc(xmm1, xmm1, xmm9, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm10, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm23, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm12, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm13, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm14, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm15, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm16, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm17, Assembler::AVX_128bit);
|
||||
|
||||
cmpl(rounds, 52);
|
||||
jcc(Assembler::below, LAST2);
|
||||
vmovdqu(xmm2, xmm20);
|
||||
vaesenc(xmm1, xmm1, xmm24, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm19, Assembler::AVX_128bit);
|
||||
cmpl(rounds, 60);
|
||||
jcc(Assembler::below, LAST2);
|
||||
vmovdqu(xmm2, xmm22);
|
||||
vaesenc(xmm1, xmm1, xmm20, Assembler::AVX_128bit);
|
||||
vaesenc(xmm1, xmm1, xmm21, Assembler::AVX_128bit);
|
||||
|
||||
bind(LAST2);
|
||||
// Aesenclast round
|
||||
vaesenclast(xmm1, xmm1, xmm2, Assembler::AVX_128bit);
|
||||
// Write 16 bytes of CT to destination
|
||||
movdqu(Address(dest_addr, pos, Address::times_1, 0), xmm1);
|
||||
addq(pos, 16);
|
||||
decq(rbx);
|
||||
jcc(Assembler::notEqual, LOOP2);
|
||||
|
||||
bind(END);
|
||||
// Zero out the round keys
|
||||
evpxorq(xmm8, xmm8, xmm8, Assembler::AVX_512bit);
|
||||
evpxorq(xmm9, xmm9, xmm9, Assembler::AVX_512bit);
|
||||
evpxorq(xmm10, xmm10, xmm10, Assembler::AVX_512bit);
|
||||
evpxorq(xmm23, xmm23, xmm23, Assembler::AVX_512bit);
|
||||
evpxorq(xmm12, xmm12, xmm12, Assembler::AVX_512bit);
|
||||
evpxorq(xmm13, xmm13, xmm13, Assembler::AVX_512bit);
|
||||
evpxorq(xmm14, xmm14, xmm14, Assembler::AVX_512bit);
|
||||
evpxorq(xmm15, xmm15, xmm15, Assembler::AVX_512bit);
|
||||
evpxorq(xmm16, xmm16, xmm16, Assembler::AVX_512bit);
|
||||
evpxorq(xmm17, xmm17, xmm17, Assembler::AVX_512bit);
|
||||
evpxorq(xmm24, xmm24, xmm24, Assembler::AVX_512bit);
|
||||
cmpl(rounds, 44);
|
||||
jcc(Assembler::belowEqual, EXIT);
|
||||
evpxorq(xmm19, xmm19, xmm19, Assembler::AVX_512bit);
|
||||
evpxorq(xmm20, xmm20, xmm20, Assembler::AVX_512bit);
|
||||
cmpl(rounds, 52);
|
||||
jcc(Assembler::belowEqual, EXIT);
|
||||
evpxorq(xmm21, xmm21, xmm21, Assembler::AVX_512bit);
|
||||
evpxorq(xmm22, xmm22, xmm22, Assembler::AVX_512bit);
|
||||
bind(EXIT);
|
||||
pop(rbx);
|
||||
pop(rax); // return length
|
||||
pop(r12);
|
||||
pop(r13);
|
||||
}
|
||||
|
||||
// AES-ECB Decrypt Operation
|
||||
void MacroAssembler::aesecb_decrypt(Register src_addr, Register dest_addr, Register key, Register len) {
|
||||
|
||||
Label NO_PARTS, LOOP, Loop_start, LOOP2, AES192, END_LOOP, AES256, REMAINDER, LAST2, END, KEY_192, KEY_256, EXIT;
|
||||
const Register pos = rax;
|
||||
const Register rounds = r12;
|
||||
push(r13);
|
||||
push(r12);
|
||||
|
||||
// For EVEX with VL and BW, provide a standard mask, VL = 128 will guide the merge
|
||||
// context for the registers used, where all instructions below are using 128-bit mode
|
||||
// On EVEX without VL and BW, these instructions will all be AVX.
|
||||
if (VM_Version::supports_avx512vlbw()) {
|
||||
movl(rax, 0xffff);
|
||||
kmovql(k1, rax);
|
||||
}
|
||||
|
||||
push(len); // Save
|
||||
push(rbx);
|
||||
|
||||
vzeroupper();
|
||||
|
||||
xorptr(pos, pos);
|
||||
// Calculate number of rounds i.e. based on key length(128, 192, 256):44 for 10-rounds, 52 for 12-rounds, 60 for 14-rounds
|
||||
movl(rounds, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
|
||||
|
||||
// Load Key shuf mask
|
||||
const XMMRegister xmm_key_shuf_mask = xmm31; // used temporarily to swap key bytes up front
|
||||
movdqu(xmm_key_shuf_mask, ExternalAddress(StubRoutines::x86::key_shuffle_mask_addr()));
|
||||
|
||||
// Load and shuffle round keys. The java expanded key ordering is rotated one position in decryption.
|
||||
// So the first round key is loaded from 1*16 here and last round key is loaded from 0*16
|
||||
ev_load_key(xmm9, key, 1 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm10, key, 2 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm11, key, 3 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm12, key, 4 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm13, key, 5 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm14, key, 6 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm15, key, 7 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm16, key, 8 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm17, key, 9 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm18, key, 10 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm27, key, 0 * 16, xmm_key_shuf_mask);
|
||||
cmpl(rounds, 52);
|
||||
jcc(Assembler::greaterEqual, KEY_192);
|
||||
jmp(Loop_start);
|
||||
|
||||
bind(KEY_192);
|
||||
ev_load_key(xmm19, key, 11 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm20, key, 12 * 16, xmm_key_shuf_mask);
|
||||
cmpl(rounds, 60);
|
||||
jcc(Assembler::equal, KEY_256);
|
||||
jmp(Loop_start);
|
||||
|
||||
bind(KEY_256);
|
||||
ev_load_key(xmm21, key, 13 * 16, xmm_key_shuf_mask);
|
||||
ev_load_key(xmm22, key, 14 * 16, xmm_key_shuf_mask);
|
||||
bind(Loop_start);
|
||||
movq(rbx, len);
|
||||
// Convert input length to number of blocks
|
||||
shrq(len, 4);
|
||||
shlq(rbx, 60);
|
||||
jcc(Assembler::equal, NO_PARTS);
|
||||
addq(len, 1);
|
||||
// Check if number of blocks is greater than/ equal to 32
|
||||
// If true, blocks then 512 bytes are processed at a time (code marked by label LOOP)
|
||||
// If not, 16 bytes are processed (code marked by label REMAINDER)
|
||||
bind(NO_PARTS);
|
||||
movq(rbx, len);
|
||||
shrq(len, 5);
|
||||
jcc(Assembler::equal, REMAINDER);
|
||||
movl(r13, len);
|
||||
// Compute number of blocks that will be processed as 512 bytes at a time
|
||||
// Subtract this from the total number of blocks, which will then be processed by REMAINDER loop.
|
||||
shlq(r13, 5);
|
||||
subq(rbx, r13);
|
||||
|
||||
bind(LOOP);
|
||||
// Move 64 bytes of CT data into a zmm register, as a result 512 bytes of CT loaded in zmm0-7
|
||||
evmovdquq(xmm0, Address(src_addr, pos, Address::times_1, 0 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm1, Address(src_addr, pos, Address::times_1, 1 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm2, Address(src_addr, pos, Address::times_1, 2 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm3, Address(src_addr, pos, Address::times_1, 3 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm4, Address(src_addr, pos, Address::times_1, 4 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm5, Address(src_addr, pos, Address::times_1, 5 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm6, Address(src_addr, pos, Address::times_1, 6 * 64), Assembler::AVX_512bit);
|
||||
evmovdquq(xmm7, Address(src_addr, pos, Address::times_1, 7 * 64), Assembler::AVX_512bit);
|
||||
// Xor with the first round key
|
||||
evpxorq(xmm0, xmm0, xmm9, Assembler::AVX_512bit);
|
||||
evpxorq(xmm1, xmm1, xmm9, Assembler::AVX_512bit);
|
||||
evpxorq(xmm2, xmm2, xmm9, Assembler::AVX_512bit);
|
||||
evpxorq(xmm3, xmm3, xmm9, Assembler::AVX_512bit);
|
||||
evpxorq(xmm4, xmm4, xmm9, Assembler::AVX_512bit);
|
||||
evpxorq(xmm5, xmm5, xmm9, Assembler::AVX_512bit);
|
||||
evpxorq(xmm6, xmm6, xmm9, Assembler::AVX_512bit);
|
||||
evpxorq(xmm7, xmm7, xmm9, Assembler::AVX_512bit);
|
||||
// 9 rounds of Aesdec
|
||||
roundDec(xmm10, 7);
|
||||
roundDec(xmm11, 7);
|
||||
roundDec(xmm12, 7);
|
||||
roundDec(xmm13, 7);
|
||||
roundDec(xmm14, 7);
|
||||
roundDec(xmm15, 7);
|
||||
roundDec(xmm16, 7);
|
||||
roundDec(xmm17, 7);
|
||||
roundDec(xmm18, 7);
|
||||
cmpl(rounds, 52);
|
||||
jcc(Assembler::aboveEqual, AES192);
|
||||
// Aesdeclast round for keysize = 128
|
||||
lastroundDec(xmm27, 7);
|
||||
jmp(END_LOOP);
|
||||
|
||||
bind(AES192);
|
||||
// 2 Additional rounds for keysize = 192
|
||||
roundDec(xmm19, 7);
|
||||
roundDec(xmm20, 7);
|
||||
cmpl(rounds, 60);
|
||||
jcc(Assembler::aboveEqual, AES256);
|
||||
// Aesdeclast round for keysize = 192
|
||||
lastroundDec(xmm27, 7);
|
||||
jmp(END_LOOP);
|
||||
bind(AES256);
|
||||
// 2 Additional rounds and Aesdeclast for keysize = 256
|
||||
roundDec(xmm21, 7);
|
||||
roundDec(xmm22, 7);
|
||||
lastroundDec(xmm27, 7);
|
||||
|
||||
bind(END_LOOP);
|
||||
// Write 512 bytes of PT to the destination
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 0 * 64), xmm0, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 1 * 64), xmm1, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 2 * 64), xmm2, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 3 * 64), xmm3, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 4 * 64), xmm4, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 5 * 64), xmm5, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 6 * 64), xmm6, Assembler::AVX_512bit);
|
||||
evmovdquq(Address(dest_addr, pos, Address::times_1, 7 * 64), xmm7, Assembler::AVX_512bit);
|
||||
|
||||
addq(pos, 512);
|
||||
decq(len);
|
||||
jcc(Assembler::notEqual, LOOP);
|
||||
|
||||
bind(REMAINDER);
|
||||
vzeroupper();
|
||||
cmpq(rbx, 0);
|
||||
jcc(Assembler::equal, END);
|
||||
// Process 16 bytes at a time
|
||||
bind(LOOP2);
|
||||
movdqu(xmm1, Address(src_addr, pos, Address::times_1, 0));
|
||||
vpxor(xmm1, xmm1, xmm9, Assembler::AVX_128bit);
|
||||
// xmm2 contains shuffled key for Aesdeclast operation.
|
||||
vmovdqu(xmm2, xmm27);
|
||||
|
||||
vaesdec(xmm1, xmm1, xmm10, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm11, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm12, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm13, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm14, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm15, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm16, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm17, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm18, Assembler::AVX_128bit);
|
||||
|
||||
cmpl(rounds, 52);
|
||||
jcc(Assembler::below, LAST2);
|
||||
vaesdec(xmm1, xmm1, xmm19, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm20, Assembler::AVX_128bit);
|
||||
cmpl(rounds, 60);
|
||||
jcc(Assembler::below, LAST2);
|
||||
vaesdec(xmm1, xmm1, xmm21, Assembler::AVX_128bit);
|
||||
vaesdec(xmm1, xmm1, xmm22, Assembler::AVX_128bit);
|
||||
|
||||
bind(LAST2);
|
||||
// Aesdeclast round
|
||||
vaesdeclast(xmm1, xmm1, xmm2, Assembler::AVX_128bit);
|
||||
// Write 16 bytes of PT to destination
|
||||
movdqu(Address(dest_addr, pos, Address::times_1, 0), xmm1);
|
||||
addq(pos, 16);
|
||||
decq(rbx);
|
||||
jcc(Assembler::notEqual, LOOP2);
|
||||
|
||||
bind(END);
|
||||
// Zero out the round keys
|
||||
evpxorq(xmm8, xmm8, xmm8, Assembler::AVX_512bit);
|
||||
evpxorq(xmm9, xmm9, xmm9, Assembler::AVX_512bit);
|
||||
evpxorq(xmm10, xmm10, xmm10, Assembler::AVX_512bit);
|
||||
evpxorq(xmm11, xmm11, xmm11, Assembler::AVX_512bit);
|
||||
evpxorq(xmm12, xmm12, xmm12, Assembler::AVX_512bit);
|
||||
evpxorq(xmm13, xmm13, xmm13, Assembler::AVX_512bit);
|
||||
evpxorq(xmm14, xmm14, xmm14, Assembler::AVX_512bit);
|
||||
evpxorq(xmm15, xmm15, xmm15, Assembler::AVX_512bit);
|
||||
evpxorq(xmm16, xmm16, xmm16, Assembler::AVX_512bit);
|
||||
evpxorq(xmm17, xmm17, xmm17, Assembler::AVX_512bit);
|
||||
evpxorq(xmm18, xmm18, xmm18, Assembler::AVX_512bit);
|
||||
evpxorq(xmm27, xmm27, xmm27, Assembler::AVX_512bit);
|
||||
cmpl(rounds, 44);
|
||||
jcc(Assembler::belowEqual, EXIT);
|
||||
evpxorq(xmm19, xmm19, xmm19, Assembler::AVX_512bit);
|
||||
evpxorq(xmm20, xmm20, xmm20, Assembler::AVX_512bit);
|
||||
cmpl(rounds, 52);
|
||||
jcc(Assembler::belowEqual, EXIT);
|
||||
evpxorq(xmm21, xmm21, xmm21, Assembler::AVX_512bit);
|
||||
evpxorq(xmm22, xmm22, xmm22, Assembler::AVX_512bit);
|
||||
bind(EXIT);
|
||||
pop(rbx);
|
||||
pop(rax); // return length
|
||||
pop(r12);
|
||||
pop(r13);
|
||||
}
|
||||
|
||||
// Multiply 128 x 128 bits, using 4 pclmulqdq operations
|
||||
void MacroAssembler::schoolbookAAD(int i, Register htbl, XMMRegister data,
|
||||
XMMRegister tmp0, XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3) {
|
||||
|
@ -3685,6 +3685,36 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return start;
|
||||
}
|
||||
|
||||
address generate_electronicCodeBook_encryptAESCrypt() {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", "electronicCodeBook_encryptAESCrypt");
|
||||
address start = __ pc();
|
||||
const Register from = c_rarg0; // source array address
|
||||
const Register to = c_rarg1; // destination array address
|
||||
const Register key = c_rarg2; // key array address
|
||||
const Register len = c_rarg3; // src len (must be multiple of blocksize 16)
|
||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ aesecb_encrypt(from, to, key, len);
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
return start;
|
||||
}
|
||||
|
||||
address generate_electronicCodeBook_decryptAESCrypt() {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", "electronicCodeBook_decryptAESCrypt");
|
||||
address start = __ pc();
|
||||
const Register from = c_rarg0; // source array address
|
||||
const Register to = c_rarg1; // destination array address
|
||||
const Register key = c_rarg2; // key array address
|
||||
const Register len = c_rarg3; // src len (must be multiple of blocksize 16)
|
||||
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ aesecb_decrypt(from, to, key, len);
|
||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||
__ ret(0);
|
||||
return start;
|
||||
}
|
||||
|
||||
address generate_upper_word_mask() {
|
||||
__ align(64);
|
||||
StubCodeMark mark(this, "StubRoutines", "upper_word_mask");
|
||||
@ -5979,6 +6009,8 @@ address generate_avx_ghash_processBlocks() {
|
||||
StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
|
||||
if (VM_Version::supports_vaes() && VM_Version::supports_avx512vl() && VM_Version::supports_avx512dq() ) {
|
||||
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptVectorAESCrypt();
|
||||
StubRoutines::_electronicCodeBook_encryptAESCrypt = generate_electronicCodeBook_encryptAESCrypt();
|
||||
StubRoutines::_electronicCodeBook_decryptAESCrypt = generate_electronicCodeBook_decryptAESCrypt();
|
||||
} else {
|
||||
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
|
||||
}
|
||||
|
@ -532,6 +532,8 @@ void AOTCodeHeap::link_stub_routines_symbols() {
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_aescrypt_decryptBlock", address, StubRoutines::_aescrypt_decryptBlock);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_cipherBlockChaining_encryptAESCrypt", address, StubRoutines::_cipherBlockChaining_encryptAESCrypt);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_cipherBlockChaining_decryptAESCrypt", address, StubRoutines::_cipherBlockChaining_decryptAESCrypt);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_electronicCodeBook_encryptAESCrypt", address, StubRoutines::_electronicCodeBook_encryptAESCrypt);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_electronicCodeBook_decryptAESCrypt", address, StubRoutines::_electronicCodeBook_decryptAESCrypt);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_update_bytes_crc32", address, StubRoutines::_updateBytesCRC32);
|
||||
SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_stub_routines_crc_table_adr", address, StubRoutines::_crc_table_adr);
|
||||
|
||||
|
@ -463,6 +463,8 @@ int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) {
|
||||
switch (id) {
|
||||
case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
|
||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||
case vmIntrinsics::_electronicCodeBook_encryptAESCrypt:
|
||||
case vmIntrinsics::_electronicCodeBook_decryptAESCrypt:
|
||||
case vmIntrinsics::_counterMode_AESCrypt:
|
||||
return 1;
|
||||
case vmIntrinsics::_digestBase_implCompressMB:
|
||||
@ -736,6 +738,10 @@ bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) {
|
||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||
if (!UseAESIntrinsics) return true;
|
||||
break;
|
||||
case vmIntrinsics::_electronicCodeBook_encryptAESCrypt:
|
||||
case vmIntrinsics::_electronicCodeBook_decryptAESCrypt:
|
||||
if (!UseAESIntrinsics) return true;
|
||||
break;
|
||||
case vmIntrinsics::_counterMode_AESCrypt:
|
||||
if (!UseAESCTRIntrinsics) return true;
|
||||
break;
|
||||
|
@ -1020,6 +1020,12 @@
|
||||
do_name( decrypt_name, "implDecrypt") \
|
||||
do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \
|
||||
\
|
||||
do_class(com_sun_crypto_provider_electronicCodeBook, "com/sun/crypto/provider/ElectronicCodeBook") \
|
||||
do_intrinsic(_electronicCodeBook_encryptAESCrypt, com_sun_crypto_provider_electronicCodeBook, ecb_encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \
|
||||
do_intrinsic(_electronicCodeBook_decryptAESCrypt, com_sun_crypto_provider_electronicCodeBook, ecb_decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \
|
||||
do_name(ecb_encrypt_name, "implECBEncrypt") \
|
||||
do_name(ecb_decrypt_name, "implECBDecrypt") \
|
||||
\
|
||||
do_class(com_sun_crypto_provider_counterMode, "com/sun/crypto/provider/CounterMode") \
|
||||
do_intrinsic(_counterMode_AESCrypt, com_sun_crypto_provider_counterMode, crypt_name, byteArray_int_int_byteArray_int_signature, F_R) \
|
||||
do_name( crypt_name, "implCrypt") \
|
||||
|
@ -301,6 +301,8 @@
|
||||
static_field(StubRoutines, _aescrypt_decryptBlock, address) \
|
||||
static_field(StubRoutines, _cipherBlockChaining_encryptAESCrypt, address) \
|
||||
static_field(StubRoutines, _cipherBlockChaining_decryptAESCrypt, address) \
|
||||
static_field(StubRoutines, _electronicCodeBook_encryptAESCrypt, address) \
|
||||
static_field(StubRoutines, _electronicCodeBook_decryptAESCrypt, address) \
|
||||
static_field(StubRoutines, _counterMode_AESCrypt, address) \
|
||||
static_field(StubRoutines, _base64_encodeBlock, address) \
|
||||
static_field(StubRoutines, _ghash_processBlocks, address) \
|
||||
|
@ -602,6 +602,8 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
|
||||
case vmIntrinsics::_aescrypt_decryptBlock:
|
||||
case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
|
||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||
case vmIntrinsics::_electronicCodeBook_encryptAESCrypt:
|
||||
case vmIntrinsics::_electronicCodeBook_decryptAESCrypt:
|
||||
case vmIntrinsics::_counterMode_AESCrypt:
|
||||
case vmIntrinsics::_sha_implCompress:
|
||||
case vmIntrinsics::_sha2_implCompress:
|
||||
|
@ -990,6 +990,8 @@ void ConnectionGraph::process_call_arguments(CallNode *call) {
|
||||
strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "electronicCodeBook_encryptAESCrypt") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "electronicCodeBook_decryptAESCrypt") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "counterMode_AESCrypt") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "ghash_processBlocks") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "encodeBlock") == 0 ||
|
||||
|
@ -293,8 +293,10 @@ class LibraryCallKit : public GraphKit {
|
||||
bool inline_Class_cast();
|
||||
bool inline_aescrypt_Block(vmIntrinsics::ID id);
|
||||
bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id);
|
||||
bool inline_electronicCodeBook_AESCrypt(vmIntrinsics::ID id);
|
||||
bool inline_counterMode_AESCrypt(vmIntrinsics::ID id);
|
||||
Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting);
|
||||
Node* inline_electronicCodeBook_AESCrypt_predicate(bool decrypting);
|
||||
Node* inline_counterMode_AESCrypt_predicate();
|
||||
Node* get_key_start_from_aescrypt_object(Node* aescrypt_object);
|
||||
Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object);
|
||||
@ -807,6 +809,10 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||
return inline_cipherBlockChaining_AESCrypt(intrinsic_id());
|
||||
|
||||
case vmIntrinsics::_electronicCodeBook_encryptAESCrypt:
|
||||
case vmIntrinsics::_electronicCodeBook_decryptAESCrypt:
|
||||
return inline_electronicCodeBook_AESCrypt(intrinsic_id());
|
||||
|
||||
case vmIntrinsics::_counterMode_AESCrypt:
|
||||
return inline_counterMode_AESCrypt(intrinsic_id());
|
||||
|
||||
@ -912,6 +918,10 @@ Node* LibraryCallKit::try_to_predicate(int predicate) {
|
||||
return inline_cipherBlockChaining_AESCrypt_predicate(false);
|
||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||
return inline_cipherBlockChaining_AESCrypt_predicate(true);
|
||||
case vmIntrinsics::_electronicCodeBook_encryptAESCrypt:
|
||||
return inline_electronicCodeBook_AESCrypt_predicate(false);
|
||||
case vmIntrinsics::_electronicCodeBook_decryptAESCrypt:
|
||||
return inline_electronicCodeBook_AESCrypt_predicate(true);
|
||||
case vmIntrinsics::_counterMode_AESCrypt:
|
||||
return inline_counterMode_AESCrypt_predicate();
|
||||
case vmIntrinsics::_digestBase_implCompressMB:
|
||||
@ -6019,6 +6029,94 @@ bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------inline_electronicCodeBook_AESCrypt-----------------------
|
||||
bool LibraryCallKit::inline_electronicCodeBook_AESCrypt(vmIntrinsics::ID id) {
|
||||
address stubAddr = NULL;
|
||||
const char *stubName = NULL;
|
||||
|
||||
assert(UseAES, "need AES instruction support");
|
||||
|
||||
switch (id) {
|
||||
case vmIntrinsics::_electronicCodeBook_encryptAESCrypt:
|
||||
stubAddr = StubRoutines::electronicCodeBook_encryptAESCrypt();
|
||||
stubName = "electronicCodeBook_encryptAESCrypt";
|
||||
break;
|
||||
case vmIntrinsics::_electronicCodeBook_decryptAESCrypt:
|
||||
stubAddr = StubRoutines::electronicCodeBook_decryptAESCrypt();
|
||||
stubName = "electronicCodeBook_decryptAESCrypt";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (stubAddr == NULL) return false;
|
||||
|
||||
Node* electronicCodeBook_object = argument(0);
|
||||
Node* src = argument(1);
|
||||
Node* src_offset = argument(2);
|
||||
Node* len = argument(3);
|
||||
Node* dest = argument(4);
|
||||
Node* dest_offset = argument(5);
|
||||
|
||||
// (1) src and dest are arrays.
|
||||
const Type* src_type = src->Value(&_gvn);
|
||||
const Type* dest_type = dest->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
|
||||
assert(top_src != NULL && top_src->klass() != NULL
|
||||
&& top_dest != NULL && top_dest->klass() != NULL, "args are strange");
|
||||
|
||||
// checks are the responsibility of the caller
|
||||
Node* src_start = src;
|
||||
Node* dest_start = dest;
|
||||
if (src_offset != NULL || dest_offset != NULL) {
|
||||
assert(src_offset != NULL && dest_offset != NULL, "");
|
||||
src_start = array_element_address(src, src_offset, T_BYTE);
|
||||
dest_start = array_element_address(dest, dest_offset, T_BYTE);
|
||||
}
|
||||
|
||||
// if we are in this set of code, we "know" the embeddedCipher is an AESCrypt object
|
||||
// (because of the predicated logic executed earlier).
|
||||
// so we cast it here safely.
|
||||
// this requires a newer class file that has this array as littleEndian ints, otherwise we revert to java
|
||||
|
||||
Node* embeddedCipherObj = load_field_from_object(electronicCodeBook_object, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false);
|
||||
if (embeddedCipherObj == NULL) return false;
|
||||
|
||||
// cast it to what we know it will be at runtime
|
||||
const TypeInstPtr* tinst = _gvn.type(electronicCodeBook_object)->isa_instptr();
|
||||
assert(tinst != NULL, "ECB obj is null");
|
||||
assert(tinst->klass()->is_loaded(), "ECB obj is not loaded");
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
|
||||
|
||||
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
||||
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type();
|
||||
Node* aescrypt_object = new CheckCastPPNode(control(), embeddedCipherObj, xtype);
|
||||
aescrypt_object = _gvn.transform(aescrypt_object);
|
||||
|
||||
// we need to get the start of the aescrypt_object's expanded key array
|
||||
Node* k_start = get_key_start_from_aescrypt_object(aescrypt_object);
|
||||
if (k_start == NULL) return false;
|
||||
|
||||
Node* ecbCrypt;
|
||||
if (Matcher::pass_original_key_for_aes()) {
|
||||
// no SPARC version for AES/ECB intrinsics now.
|
||||
return false;
|
||||
}
|
||||
// Call the stub, passing src_start, dest_start, k_start, r_start and src_len
|
||||
ecbCrypt = make_runtime_call(RC_LEAF | RC_NO_FP,
|
||||
OptoRuntime::electronicCodeBook_aescrypt_Type(),
|
||||
stubAddr, stubName, TypePtr::BOTTOM,
|
||||
src_start, dest_start, k_start, len);
|
||||
|
||||
// return cipher length (int)
|
||||
Node* retvalue = _gvn.transform(new ProjNode(ecbCrypt, TypeFunc::Parms));
|
||||
set_result(retvalue);
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------inline_counterMode_AESCrypt-----------------------
|
||||
bool LibraryCallKit::inline_counterMode_AESCrypt(vmIntrinsics::ID id) {
|
||||
assert(UseAES, "need AES instruction support");
|
||||
@ -6215,6 +6313,65 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt
|
||||
return _gvn.transform(region);
|
||||
}
|
||||
|
||||
//----------------------------inline_electronicCodeBook_AESCrypt_predicate----------------------------
|
||||
// Return node representing slow path of predicate check.
|
||||
// the pseudo code we want to emulate with this predicate is:
|
||||
// for encryption:
|
||||
// if (embeddedCipherObj instanceof AESCrypt) do_intrinsic, else do_javapath
|
||||
// for decryption:
|
||||
// if ((embeddedCipherObj instanceof AESCrypt) && (cipher!=plain)) do_intrinsic, else do_javapath
|
||||
// note cipher==plain is more conservative than the original java code but that's OK
|
||||
//
|
||||
Node* LibraryCallKit::inline_electronicCodeBook_AESCrypt_predicate(bool decrypting) {
|
||||
// The receiver was checked for NULL already.
|
||||
Node* objECB = argument(0);
|
||||
|
||||
// Load embeddedCipher field of ElectronicCodeBook object.
|
||||
Node* embeddedCipherObj = load_field_from_object(objECB, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false);
|
||||
|
||||
// get AESCrypt klass for instanceOf check
|
||||
// AESCrypt might not be loaded yet if some other SymmetricCipher got us to this compile point
|
||||
// will have same classloader as ElectronicCodeBook object
|
||||
const TypeInstPtr* tinst = _gvn.type(objECB)->isa_instptr();
|
||||
assert(tinst != NULL, "ECBobj is null");
|
||||
assert(tinst->klass()->is_loaded(), "ECBobj is not loaded");
|
||||
|
||||
// we want to do an instanceof comparison against the AESCrypt class
|
||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||
if (!klass_AESCrypt->is_loaded()) {
|
||||
// if AESCrypt is not even loaded, we never take the intrinsic fast path
|
||||
Node* ctrl = control();
|
||||
set_control(top()); // no regular fast path
|
||||
return ctrl;
|
||||
}
|
||||
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
||||
|
||||
Node* instof = gen_instanceof(embeddedCipherObj, makecon(TypeKlassPtr::make(instklass_AESCrypt)));
|
||||
Node* cmp_instof = _gvn.transform(new CmpINode(instof, intcon(1)));
|
||||
Node* bool_instof = _gvn.transform(new BoolNode(cmp_instof, BoolTest::ne));
|
||||
|
||||
Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);
|
||||
|
||||
// for encryption, we are done
|
||||
if (!decrypting)
|
||||
return instof_false; // even if it is NULL
|
||||
|
||||
// for decryption, we need to add a further check to avoid
|
||||
// taking the intrinsic path when cipher and plain are the same
|
||||
// see the original java code for why.
|
||||
RegionNode* region = new RegionNode(3);
|
||||
region->init_req(1, instof_false);
|
||||
Node* src = argument(1);
|
||||
Node* dest = argument(4);
|
||||
Node* cmp_src_dest = _gvn.transform(new CmpPNode(src, dest));
|
||||
Node* bool_src_dest = _gvn.transform(new BoolNode(cmp_src_dest, BoolTest::eq));
|
||||
Node* src_dest_conjoint = generate_guard(bool_src_dest, NULL, PROB_MIN);
|
||||
region->init_req(2, src_dest_conjoint);
|
||||
|
||||
record_for_igvn(region);
|
||||
return _gvn.transform(region);
|
||||
}
|
||||
|
||||
//----------------------------inline_counterMode_AESCrypt_predicate----------------------------
|
||||
// Return node representing slow path of predicate check.
|
||||
// the pseudo code we want to emulate with this predicate is:
|
||||
|
@ -900,6 +900,33 @@ const TypeFunc* OptoRuntime::cipherBlockChaining_aescrypt_Type() {
|
||||
return TypeFunc::make(domain, range);
|
||||
}
|
||||
|
||||
// for electronicCodeBook calls of aescrypt encrypt/decrypt, three pointers and a length, returning int
|
||||
const TypeFunc* OptoRuntime::electronicCodeBook_aescrypt_Type() {
|
||||
// create input type (domain)
|
||||
int num_args = 4;
|
||||
if (Matcher::pass_original_key_for_aes()) {
|
||||
num_args = 5;
|
||||
}
|
||||
int argcnt = num_args;
|
||||
const Type** fields = TypeTuple::fields(argcnt);
|
||||
int argp = TypeFunc::Parms;
|
||||
fields[argp++] = TypePtr::NOTNULL; // src
|
||||
fields[argp++] = TypePtr::NOTNULL; // dest
|
||||
fields[argp++] = TypePtr::NOTNULL; // k array
|
||||
fields[argp++] = TypeInt::INT; // src len
|
||||
if (Matcher::pass_original_key_for_aes()) {
|
||||
fields[argp++] = TypePtr::NOTNULL; // original k array
|
||||
}
|
||||
assert(argp == TypeFunc::Parms + argcnt, "correct decoding");
|
||||
const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + argcnt, fields);
|
||||
|
||||
// returning cipher len (int)
|
||||
fields = TypeTuple::fields(1);
|
||||
fields[TypeFunc::Parms + 0] = TypeInt::INT;
|
||||
const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 1, fields);
|
||||
return TypeFunc::make(domain, range);
|
||||
}
|
||||
|
||||
//for counterMode calls of aescrypt encrypt/decrypt, four pointers and a length, returning int
|
||||
const TypeFunc* OptoRuntime::counterMode_aescrypt_Type() {
|
||||
// create input type (domain)
|
||||
|
@ -275,6 +275,7 @@ private:
|
||||
|
||||
static const TypeFunc* aescrypt_block_Type();
|
||||
static const TypeFunc* cipherBlockChaining_aescrypt_Type();
|
||||
static const TypeFunc* electronicCodeBook_aescrypt_Type();
|
||||
static const TypeFunc* counterMode_aescrypt_Type();
|
||||
|
||||
static const TypeFunc* sha_implCompress_Type();
|
||||
|
@ -129,6 +129,8 @@ address StubRoutines::_aescrypt_encryptBlock = NULL;
|
||||
address StubRoutines::_aescrypt_decryptBlock = NULL;
|
||||
address StubRoutines::_cipherBlockChaining_encryptAESCrypt = NULL;
|
||||
address StubRoutines::_cipherBlockChaining_decryptAESCrypt = NULL;
|
||||
address StubRoutines::_electronicCodeBook_encryptAESCrypt = NULL;
|
||||
address StubRoutines::_electronicCodeBook_decryptAESCrypt = NULL;
|
||||
address StubRoutines::_counterMode_AESCrypt = NULL;
|
||||
address StubRoutines::_ghash_processBlocks = NULL;
|
||||
address StubRoutines::_base64_encodeBlock = NULL;
|
||||
|
@ -210,6 +210,8 @@ class StubRoutines: AllStatic {
|
||||
static address _aescrypt_decryptBlock;
|
||||
static address _cipherBlockChaining_encryptAESCrypt;
|
||||
static address _cipherBlockChaining_decryptAESCrypt;
|
||||
static address _electronicCodeBook_encryptAESCrypt;
|
||||
static address _electronicCodeBook_decryptAESCrypt;
|
||||
static address _counterMode_AESCrypt;
|
||||
static address _ghash_processBlocks;
|
||||
static address _base64_encodeBlock;
|
||||
@ -376,6 +378,8 @@ class StubRoutines: AllStatic {
|
||||
static address aescrypt_decryptBlock() { return _aescrypt_decryptBlock; }
|
||||
static address cipherBlockChaining_encryptAESCrypt() { return _cipherBlockChaining_encryptAESCrypt; }
|
||||
static address cipherBlockChaining_decryptAESCrypt() { return _cipherBlockChaining_decryptAESCrypt; }
|
||||
static address electronicCodeBook_encryptAESCrypt() { return _electronicCodeBook_encryptAESCrypt; }
|
||||
static address electronicCodeBook_decryptAESCrypt() { return _electronicCodeBook_decryptAESCrypt; }
|
||||
static address counterMode_AESCrypt() { return _counterMode_AESCrypt; }
|
||||
static address ghash_processBlocks() { return _ghash_processBlocks; }
|
||||
static address base64_encodeBlock() { return _base64_encodeBlock; }
|
||||
|
@ -592,6 +592,8 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
|
||||
static_field(StubRoutines, _aescrypt_decryptBlock, address) \
|
||||
static_field(StubRoutines, _cipherBlockChaining_encryptAESCrypt, address) \
|
||||
static_field(StubRoutines, _cipherBlockChaining_decryptAESCrypt, address) \
|
||||
static_field(StubRoutines, _electronicCodeBook_encryptAESCrypt, address) \
|
||||
static_field(StubRoutines, _electronicCodeBook_decryptAESCrypt, address) \
|
||||
static_field(StubRoutines, _counterMode_AESCrypt, address) \
|
||||
static_field(StubRoutines, _ghash_processBlocks, address) \
|
||||
static_field(StubRoutines, _base64_encodeBlock, address) \
|
||||
|
@ -28,6 +28,8 @@ package com.sun.crypto.provider;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.ProviderException;
|
||||
import sun.security.util.ArrayUtil;
|
||||
import java.util.Objects;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
|
||||
/**
|
||||
* This class represents ciphers in electronic codebook (ECB) mode.
|
||||
@ -95,6 +97,16 @@ final class ElectronicCodeBook extends FeedbackCipher {
|
||||
embeddedCipher.init(decrypting, algorithm, key);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
private int implECBEncrypt(byte [] in, int inOff, int len, byte[] out, int outOff) {
|
||||
for (int i = len; i >= blockSize; i -= blockSize) {
|
||||
embeddedCipher.encryptBlock(in, inOff, out, outOff);
|
||||
inOff += blockSize;
|
||||
outOff += blockSize;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs encryption operation.
|
||||
*
|
||||
@ -116,9 +128,13 @@ final class ElectronicCodeBook extends FeedbackCipher {
|
||||
ArrayUtil.blockSizeCheck(len, blockSize);
|
||||
ArrayUtil.nullAndBoundsCheck(in, inOff, len);
|
||||
ArrayUtil.nullAndBoundsCheck(out, outOff, len);
|
||||
return implECBEncrypt(in, inOff, len, out, outOff);
|
||||
}
|
||||
|
||||
@HotSpotIntrinsicCandidate
|
||||
private int implECBDecrypt(byte [] in, int inOff, int len, byte[] out, int outOff) {
|
||||
for (int i = len; i >= blockSize; i -= blockSize) {
|
||||
embeddedCipher.encryptBlock(in, inOff, out, outOff);
|
||||
embeddedCipher.decryptBlock(in, inOff, out, outOff);
|
||||
inOff += blockSize;
|
||||
outOff += blockSize;
|
||||
}
|
||||
@ -146,12 +162,6 @@ final class ElectronicCodeBook extends FeedbackCipher {
|
||||
ArrayUtil.blockSizeCheck(len, blockSize);
|
||||
ArrayUtil.nullAndBoundsCheck(in, inOff, len);
|
||||
ArrayUtil.nullAndBoundsCheck(out, outOff, len);
|
||||
|
||||
for (int i = len; i >= blockSize; i -= blockSize) {
|
||||
embeddedCipher.decryptBlock(in, inOff, out, outOff);
|
||||
inOff += blockSize;
|
||||
outOff += blockSize;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
return implECBDecrypt(in, inOff, len, out, outOff);
|
||||
}
|
||||
}
|
||||
|
@ -203,6 +203,8 @@ public final class BinaryContainer implements SymbolTable {
|
||||
{"StubRoutines::_aescrypt_decryptBlock", "_aot_stub_routines_aescrypt_decryptBlock"},
|
||||
{"StubRoutines::_cipherBlockChaining_encryptAESCrypt", "_aot_stub_routines_cipherBlockChaining_encryptAESCrypt"},
|
||||
{"StubRoutines::_cipherBlockChaining_decryptAESCrypt", "_aot_stub_routines_cipherBlockChaining_decryptAESCrypt"},
|
||||
{"StubRoutines::_electronicCodeBook_encryptAESCrypt", "_aot_stub_routines_electronicCodeBook_encryptAESCrypt"},
|
||||
{"StubRoutines::_electronicCodeBook_decryptAESCrypt", "_aot_stub_routines_electronicCodeBook_decryptAESCrypt"},
|
||||
{"StubRoutines::_updateBytesCRC32", "_aot_stub_routines_update_bytes_crc32"},
|
||||
{"StubRoutines::_crc_table_adr", "_aot_stub_routines_crc_table_adr"},
|
||||
|
||||
|
@ -43,7 +43,7 @@ public class AESBench extends CryptoBase {
|
||||
@Param({"AES/ECB/NoPadding", "AES/ECB/PKCS5Padding", "AES/CBC/NoPadding", "AES/CBC/PKCS5Padding"})
|
||||
private String algorithm;
|
||||
|
||||
@Param({"128"})
|
||||
@Param({"128", "192", "256"})
|
||||
private int keyLength;
|
||||
|
||||
@Param({"" + 16 * 1024})
|
||||
|
Loading…
x
Reference in New Issue
Block a user