|
1 | 1 | /* |
2 | | -* Copyright (c) 2019, 2025, Intel Corporation. All rights reserved. |
| 2 | +* Copyright (c) 2019, 2026, Intel Corporation. All rights reserved. |
3 | 3 | * |
4 | 4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
5 | 5 | * |
@@ -218,6 +218,8 @@ void StubGenerator::generate_aes_stubs() { |
218 | 218 | StubRoutines::_galoisCounterMode_AESCrypt = generate_galoisCounterMode_AESCrypt(); |
219 | 219 | } else { |
220 | 220 | StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel(); |
| 221 | + StubRoutines::_electronicCodeBook_encryptAESCrypt = generate_electronicCodeBook_encryptAESCrypt_Parallel(); |
| 222 | + StubRoutines::_electronicCodeBook_decryptAESCrypt = generate_electronicCodeBook_decryptAESCrypt_Parallel(); |
221 | 223 | if (VM_Version::supports_avx2()) { |
222 | 224 | StubRoutines::_galoisCounterMode_AESCrypt = generate_avx2_galoisCounterMode_AESCrypt(); |
223 | 225 | } |
@@ -1399,6 +1401,200 @@ address StubGenerator::generate_cipherBlockChaining_encryptAESCrypt() { |
1399 | 1401 | return start; |
1400 | 1402 | } |
1401 | 1403 |
|
| 1404 | +// This is a version of ECB/AES Encrypt/Decrypt which does 4 blocks in a loop |
| 1405 | +// at a time to hide instruction latency. |
| 1406 | +// |
| 1407 | +// For encryption (is_encrypt=true): |
| 1408 | +// pxor key[0], aesenc key[1..rounds-1], aesenclast key[rounds] |
| 1409 | +// For decryption (is_encrypt=false): |
| 1410 | +// pxor key[1], aesdec key[2..rounds], aesdeclast key[0] |
| 1411 | +// |
| 1412 | +// Arguments: |
| 1413 | +// |
| 1414 | +// Inputs: |
| 1415 | +// c_rarg0 - source byte array address |
| 1416 | +// c_rarg1 - destination byte array address |
| 1417 | +// c_rarg2 - session key (Ke/Kd) in little endian int array |
| 1418 | +// c_rarg3 - input length (must be multiple of blocksize 16) |
| 1419 | +// |
| 1420 | +// Output: |
| 1421 | +// rax - input length |
| 1422 | +// |
| 1423 | +address StubGenerator::generate_electronicCodeBook_AESCrypt_Parallel(bool is_encrypt) { |
| 1424 | + assert(UseAES, "need AES instructions and misaligned SSE support"); |
| 1425 | + __ align(CodeEntryAlignment); |
| 1426 | + StubId stub_id = is_encrypt ? StubId::stubgen_electronicCodeBook_encryptAESCrypt_id |
| 1427 | + : StubId::stubgen_electronicCodeBook_decryptAESCrypt_id; |
| 1428 | + StubCodeMark mark(this, stub_id); |
| 1429 | + address start = __ pc(); |
| 1430 | + |
| 1431 | + const Register from = c_rarg0; // source array address |
| 1432 | + const Register to = c_rarg1; // destination array address |
| 1433 | + const Register key = c_rarg2; // key array address |
| 1434 | + const Register len_reg = c_rarg3; // src len (must be multiple of blocksize 16) |
| 1435 | + const Register pos = rax; |
| 1436 | + const Register keylen = r11; |
| 1437 | + |
| 1438 | + const XMMRegister xmm_result0 = xmm0; |
| 1439 | + const XMMRegister xmm_result1 = xmm1; |
| 1440 | + const XMMRegister xmm_result2 = xmm2; |
| 1441 | + const XMMRegister xmm_result3 = xmm3; |
| 1442 | + const XMMRegister xmm_key_shuf_mask = xmm4; |
| 1443 | + const XMMRegister xmm_key_tmp = xmm5; |
| 1444 | + // keys 0-9 pre-loaded into xmm6-xmm15 |
| 1445 | + const int XMM_REG_NUM_KEY_FIRST = 6; |
| 1446 | + const int XMM_REG_NUM_KEY_LAST = 15; |
| 1447 | + const XMMRegister xmm_key_first = as_XMMRegister(XMM_REG_NUM_KEY_FIRST); |
| 1448 | + |
| 1449 | + // for key_128, key_192, key_256 |
| 1450 | + const int ROUNDS[3] = {10, 12, 14}; |
| 1451 | + |
| 1452 | + Label L_exit; |
| 1453 | + Label L_loop4[3], L_single[3], L_done[3]; |
| 1454 | + |
| 1455 | +#ifdef DoFour |
| 1456 | +#undef DoFour |
| 1457 | +#endif |
| 1458 | +#ifdef DoOne |
| 1459 | +#undef DoOne |
| 1460 | +#endif |
| 1461 | + |
| 1462 | +#define DoFour(opc, reg) \ |
| 1463 | +__ opc(xmm_result0, reg); \ |
| 1464 | +__ opc(xmm_result1, reg); \ |
| 1465 | +__ opc(xmm_result2, reg); \ |
| 1466 | +__ opc(xmm_result3, reg); |
| 1467 | + |
| 1468 | +#define DoOne(opc, reg) \ |
| 1469 | +__ opc(xmm_result0, reg); |
| 1470 | + |
| 1471 | + __ enter(); // required for proper stackwalking of RuntimeStub frame |
| 1472 | + __ push(len_reg); // save original length for return value |
| 1473 | + |
| 1474 | + __ movl(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); |
| 1475 | + |
| 1476 | + __ movdqu(xmm_key_shuf_mask, ExternalAddress(key_shuffle_mask_addr()), r10 /*rscratch*/); |
| 1477 | + // load up xmm regs 6 thru 15 with keys 0x00 - 0x90 |
| 1478 | + for (int rnum = XMM_REG_NUM_KEY_FIRST, offset = 0x00; rnum <= XMM_REG_NUM_KEY_LAST; rnum++, offset += 0x10) { |
| 1479 | + load_key(as_XMMRegister(rnum), key, offset, xmm_key_shuf_mask); |
| 1480 | + } |
| 1481 | + __ xorptr(pos, pos); |
| 1482 | + |
| 1483 | + // key length could be only {11, 13, 15} * 4 = {44, 52, 60} |
| 1484 | + __ cmpl(keylen, 52); |
| 1485 | + __ jcc(Assembler::equal, L_loop4[1]); |
| 1486 | + __ cmpl(keylen, 60); |
| 1487 | + __ jcc(Assembler::equal, L_loop4[2]); |
| 1488 | + |
| 1489 | + // k == 0: generate code for key_128 |
| 1490 | + // k == 1: generate code for key_192 |
| 1491 | + // k == 2: generate code for key_256 |
| 1492 | + for (int k = 0; k < 3; ++k) { |
| 1493 | + __ align(OptoLoopAlignment); |
| 1494 | + __ BIND(L_loop4[k]); |
| 1495 | + __ cmpptr(len_reg, 4 * AESBlockSize); |
| 1496 | + __ jcc(Assembler::less, L_single[k]); |
| 1497 | + |
| 1498 | + __ movdqu(xmm_result0, Address(from, pos, Address::times_1, 0 * AESBlockSize)); |
| 1499 | + __ movdqu(xmm_result1, Address(from, pos, Address::times_1, 1 * AESBlockSize)); |
| 1500 | + __ movdqu(xmm_result2, Address(from, pos, Address::times_1, 2 * AESBlockSize)); |
| 1501 | + __ movdqu(xmm_result3, Address(from, pos, Address::times_1, 3 * AESBlockSize)); |
| 1502 | + |
| 1503 | + if (is_encrypt) { |
| 1504 | + DoFour(pxor, xmm_key_first); |
| 1505 | + for (int rnum = 1; rnum < 10; rnum++) { |
| 1506 | + DoFour(aesenc, as_XMMRegister(rnum + XMM_REG_NUM_KEY_FIRST)); |
| 1507 | + } |
| 1508 | + for (int i = 10; i < ROUNDS[k]; i++) { |
| 1509 | + load_key(xmm_key_tmp, key, i * 0x10, xmm_key_shuf_mask); |
| 1510 | + DoFour(aesenc, xmm_key_tmp); |
| 1511 | + } |
| 1512 | + load_key(xmm_key_tmp, key, ROUNDS[k] * 0x10, xmm_key_shuf_mask); |
| 1513 | + DoFour(aesenclast, xmm_key_tmp); |
| 1514 | + } else { |
| 1515 | + DoFour(pxor, as_XMMRegister(1 + XMM_REG_NUM_KEY_FIRST)); |
| 1516 | + for (int rnum = 2; rnum < 10; rnum++) { |
| 1517 | + DoFour(aesdec, as_XMMRegister(rnum + XMM_REG_NUM_KEY_FIRST)); |
| 1518 | + } |
| 1519 | + for (int i = 10; i <= ROUNDS[k]; i++) { |
| 1520 | + load_key(xmm_key_tmp, key, i * 0x10, xmm_key_shuf_mask); |
| 1521 | + DoFour(aesdec, xmm_key_tmp); |
| 1522 | + } |
| 1523 | + DoFour(aesdeclast, xmm_key_first); |
| 1524 | + } |
| 1525 | + |
| 1526 | + __ movdqu(Address(to, pos, Address::times_1, 0 * AESBlockSize), xmm_result0); |
| 1527 | + __ movdqu(Address(to, pos, Address::times_1, 1 * AESBlockSize), xmm_result1); |
| 1528 | + __ movdqu(Address(to, pos, Address::times_1, 2 * AESBlockSize), xmm_result2); |
| 1529 | + __ movdqu(Address(to, pos, Address::times_1, 3 * AESBlockSize), xmm_result3); |
| 1530 | + |
| 1531 | + __ addptr(pos, 4 * AESBlockSize); |
| 1532 | + __ subptr(len_reg, 4 * AESBlockSize); |
| 1533 | + __ jmp(L_loop4[k]); |
| 1534 | + |
| 1535 | + __ align(OptoLoopAlignment); |
| 1536 | + __ BIND(L_single[k]); |
| 1537 | + __ cmpptr(len_reg, AESBlockSize); |
| 1538 | + __ jcc(Assembler::less, L_done[k]); |
| 1539 | + |
| 1540 | + __ movdqu(xmm_result0, Address(from, pos, Address::times_1, 0)); |
| 1541 | + |
| 1542 | + if (is_encrypt) { |
| 1543 | + DoOne(pxor, xmm_key_first); |
| 1544 | + for (int rnum = 1; rnum < 10; rnum++) { |
| 1545 | + DoOne(aesenc, as_XMMRegister(rnum + XMM_REG_NUM_KEY_FIRST)); |
| 1546 | + } |
| 1547 | + for (int i = 10; i < ROUNDS[k]; i++) { |
| 1548 | + load_key(xmm_key_tmp, key, i * 0x10, xmm_key_shuf_mask); |
| 1549 | + DoOne(aesenc, xmm_key_tmp); |
| 1550 | + } |
| 1551 | + load_key(xmm_key_tmp, key, ROUNDS[k] * 0x10, xmm_key_shuf_mask); |
| 1552 | + DoOne(aesenclast, xmm_key_tmp); |
| 1553 | + } else { |
| 1554 | + DoOne(pxor, as_XMMRegister(1 + XMM_REG_NUM_KEY_FIRST)); |
| 1555 | + for (int rnum = 2; rnum < 10; rnum++) { |
| 1556 | + DoOne(aesdec, as_XMMRegister(rnum + XMM_REG_NUM_KEY_FIRST)); |
| 1557 | + } |
| 1558 | + for (int i = 10; i <= ROUNDS[k]; i++) { |
| 1559 | + load_key(xmm_key_tmp, key, i * 0x10, xmm_key_shuf_mask); |
| 1560 | + DoOne(aesdec, xmm_key_tmp); |
| 1561 | + } |
| 1562 | + DoOne(aesdeclast, xmm_key_first); |
| 1563 | + } |
| 1564 | + |
| 1565 | + __ movdqu(Address(to, pos, Address::times_1, 0), xmm_result0); |
| 1566 | + __ addptr(pos, AESBlockSize); |
| 1567 | + __ subptr(len_reg, AESBlockSize); |
| 1568 | + __ jmp(L_single[k]); |
| 1569 | + |
| 1570 | + __ BIND(L_done[k]); |
| 1571 | + if (k < 2) __ jmp(L_exit); |
| 1572 | + } //for key_128/192/256 |
| 1573 | + |
| 1574 | + __ BIND(L_exit); |
| 1575 | + // Clear all XMM registers holding sensitive key material before returning |
| 1576 | + __ pxor(xmm_key_tmp, xmm_key_tmp); |
| 1577 | + for (int rnum = XMM_REG_NUM_KEY_FIRST; rnum <= XMM_REG_NUM_KEY_LAST; rnum++) { |
| 1578 | + __ pxor(as_XMMRegister(rnum), as_XMMRegister(rnum)); |
| 1579 | + } |
| 1580 | + __ pop(rax); |
| 1581 | + __ leave(); // required for proper stackwalking of RuntimeStub frame |
| 1582 | + __ ret(0); |
| 1583 | + |
| 1584 | + return start; |
| 1585 | + |
| 1586 | +#undef DoFour |
| 1587 | +#undef DoOne |
| 1588 | +} |
| 1589 | + |
| 1590 | +address StubGenerator::generate_electronicCodeBook_encryptAESCrypt_Parallel() { |
| 1591 | + return generate_electronicCodeBook_AESCrypt_Parallel(true); |
| 1592 | +} |
| 1593 | + |
| 1594 | +address StubGenerator::generate_electronicCodeBook_decryptAESCrypt_Parallel() { |
| 1595 | + return generate_electronicCodeBook_AESCrypt_Parallel(false); |
| 1596 | +} |
| 1597 | + |
1402 | 1598 | // This is a version of CBC/AES Decrypt which does 4 blocks in a loop at a time |
1403 | 1599 | // to hide instruction latency |
1404 | 1600 | // |
@@ -1493,7 +1689,7 @@ address StubGenerator::generate_cipherBlockChaining_decryptAESCrypt_Parallel() { |
1493 | 1689 | __ opc(xmm_result0, src_reg); \ |
1494 | 1690 | __ opc(xmm_result1, src_reg); \ |
1495 | 1691 | __ opc(xmm_result2, src_reg); \ |
1496 | | -__ opc(xmm_result3, src_reg); \ |
| 1692 | +__ opc(xmm_result3, src_reg); |
1497 | 1693 |
|
1498 | 1694 | for (int k = 0; k < 3; ++k) { |
1499 | 1695 | __ BIND(L_multiBlock_loopTopHead[k]); |
|
0 commit comments