@samitouri / QOSamiQemu / commits / c75e3503c8

target/mips: add Octeon Camellia COP2 helpers

Add helper support for the Octeon Camellia ROUND, FL, and FLINV selectors. The engine reuses the AES RESINP bank, and guest-managed key schedules drive the Camellia F-function and FL layers through these COP2 operations. Implement the Camellia F-function and FL layers directly from RFC 3713. Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-11-daef7a0d8b04@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

James Hilliard committed Jun 8, 2026 at 12:59 UTC c75e3503c814802a23785fce0df9258b2b83f3cb
2 files changed +129
target/mips/helper.h
+3
@@ -66,6 +66,9 @@ DEF_HELPER_2(octeon_cp2_mt_des3_enc, void, env, i64)
66 DEF_HELPER_2(octeon_cp2_mt_kas_enc, void, env, i64)
67 DEF_HELPER_2(octeon_cp2_mt_des3_dec_cbc, void, env, i64)
68 DEF_HELPER_2(octeon_cp2_mt_des3_dec, void, env, i64)
69 +DEF_HELPER_2(octeon_cp2_mt_camellia_fl, void, env, i64)
70 +DEF_HELPER_2(octeon_cp2_mt_camellia_flinv, void, env, i64)
71 +DEF_HELPER_2(octeon_cp2_mt_camellia_round, void, env, i64)
72
73 /* microMIPS functions */
74 DEF_HELPER_4(lwm, void, env, tl, tl, i32)
target/mips/tcg/octeon_crypto.c
+126
@@ -1566,6 +1566,132 @@ void helper_octeon_cp2_mt_des3_dec(CPUMIPSState *env, uint64_t value)
1566 octeon_3des_crypt_common(&env->octeon_crypto, value, false, false);
1567 }
1568
1569 +static const uint8_t camellia_sbox1[256] = {
1570 + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12,
1571 + 174, 65, 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78,
1572 + 29, 101, 146, 189, 134, 184, 175, 143, 124, 235, 31, 206, 62, 48,
1573 + 220, 95, 94, 197, 11, 26, 166, 225, 57, 202, 213, 71, 93, 61,
1574 + 217, 1, 90, 214, 81, 86, 108, 77, 139, 13, 154, 102, 251, 204,
1575 + 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, 223, 76, 203, 194,
1576 + 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, 20, 88,
1577 + 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34,
1578 + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252,
1579 + 105, 80, 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149,
1580 + 224, 255, 100, 210, 16, 196, 0, 72, 163, 247, 117, 219, 138, 3,
1581 + 230, 218, 9, 63, 221, 148, 135, 92, 131, 2, 205, 74, 144, 51,
1582 + 115, 103, 246, 243, 157, 127, 191, 226, 82, 155, 216, 38, 200, 55,
1583 + 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, 233, 121, 167, 140,
1584 + 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, 120, 152,
1585 + 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250,
1586 + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56,
1587 + 241, 164, 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244,
1588 + 119, 199, 128, 158,
1589 +};
1590 +
1591 +static uint8_t camellia_rotl8(uint8_t v, unsigned int shift)
1592 +{
1593 + return (v << shift) | (v >> (8 - shift));
1594 +}
1595 +
1596 +static uint8_t camellia_sbox2(uint8_t x)
1597 +{
1598 + return camellia_rotl8(camellia_sbox1[x], 1);
1599 +}
1600 +
1601 +static uint8_t camellia_sbox3(uint8_t x)
1602 +{
1603 + return camellia_rotl8(camellia_sbox1[x], 7);
1604 +}
1605 +
1606 +static uint8_t camellia_sbox4(uint8_t x)
1607 +{
1608 + return camellia_sbox1[camellia_rotl8(x, 1)];
1609 +}
1610 +
1611 +static uint64_t camellia_f(uint64_t input, uint64_t key)
1612 +{
1613 + uint64_t x = input ^ key;
1614 + uint8_t t1 = camellia_sbox1[x >> 56];
1615 + uint8_t t2 = camellia_sbox2((x >> 48) & 0xff);
1616 + uint8_t t3 = camellia_sbox3((x >> 40) & 0xff);
1617 + uint8_t t4 = camellia_sbox4((x >> 32) & 0xff);
1618 + uint8_t t5 = camellia_sbox2((x >> 24) & 0xff);
1619 + uint8_t t6 = camellia_sbox3((x >> 16) & 0xff);
1620 + uint8_t t7 = camellia_sbox4((x >> 8) & 0xff);
1621 + uint8_t t8 = camellia_sbox1[x & 0xff];
1622 + uint8_t y1 = t1 ^ t3 ^ t4 ^ t6 ^ t7 ^ t8;
1623 + uint8_t y2 = t1 ^ t2 ^ t4 ^ t5 ^ t7 ^ t8;
1624 + uint8_t y3 = t1 ^ t2 ^ t3 ^ t5 ^ t6 ^ t8;
1625 + uint8_t y4 = t2 ^ t3 ^ t4 ^ t5 ^ t6 ^ t7;
1626 + uint8_t y5 = t1 ^ t2 ^ t6 ^ t7 ^ t8;
1627 + uint8_t y6 = t2 ^ t3 ^ t5 ^ t7 ^ t8;
1628 + uint8_t y7 = t3 ^ t4 ^ t5 ^ t6 ^ t8;
1629 + uint8_t y8 = t1 ^ t4 ^ t5 ^ t6 ^ t7;
1630 +
1631 + return ((uint64_t)y1 << 56) | ((uint64_t)y2 << 48) |
1632 + ((uint64_t)y3 << 40) | ((uint64_t)y4 << 32) |
1633 + ((uint64_t)y5 << 24) | ((uint64_t)y6 << 16) |
1634 + ((uint64_t)y7 << 8) | y8;
1635 +}
1636 +
1637 +static uint64_t camellia_fl(uint64_t input, uint64_t key)
1638 +{
1639 + uint32_t x1 = input >> 32;
1640 + uint32_t x2 = input;
1641 + uint32_t k1 = key >> 32;
1642 + uint32_t k2 = key;
1643 +
1644 + x2 ^= rol32(x1 & k1, 1);
1645 + x1 ^= x2 | k2;
1646 + return ((uint64_t)x1 << 32) | x2;
1647 +}
1648 +
1649 +static uint64_t camellia_flinv(uint64_t input, uint64_t key)
1650 +{
1651 + uint32_t y1 = input >> 32;
1652 + uint32_t y2 = input;
1653 + uint32_t k1 = key >> 32;
1654 + uint32_t k2 = key;
1655 +
1656 + y1 ^= y2 | k2;
1657 + y2 ^= rol32(y1 & k1, 1);
1658 + return ((uint64_t)y1 << 32) | y2;
1659 +}
1660 +
1661 +static void octeon_camellia_round(MIPSOcteonCryptoState *crypto, uint64_t key)
1662 +{
1663 + uint64_t left = crypto->aes_resinp[0];
1664 + uint64_t right = crypto->aes_resinp[1];
1665 +
1666 + crypto->aes_resinp[0] = right ^ camellia_f(left, key);
1667 + crypto->aes_resinp[1] = left;
1668 +}
1669 +
1670 +static void octeon_camellia_fl_layer(MIPSOcteonCryptoState *crypto,
1671 + uint64_t key, bool inverse)
1672 +{
1673 + uint64_t state = crypto->aes_resinp[inverse ? 1 : 0];
1674 +
1675 + crypto->aes_resinp[inverse ? 1 : 0] = inverse ?
1676 + camellia_flinv(state, key) :
1677 + camellia_fl(state, key);
1678 +}
1679 +
1680 +void helper_octeon_cp2_mt_camellia_fl(CPUMIPSState *env, uint64_t value)
1681 +{
1682 + octeon_camellia_fl_layer(&env->octeon_crypto, value, false);
1683 +}
1684 +
1685 +void helper_octeon_cp2_mt_camellia_flinv(CPUMIPSState *env, uint64_t value)
1686 +{
1687 + octeon_camellia_fl_layer(&env->octeon_crypto, value, true);
1688 +}
1689 +
1690 +void helper_octeon_cp2_mt_camellia_round(CPUMIPSState *env, uint64_t value)
1691 +{
1692 + octeon_camellia_round(&env->octeon_crypto, value);
1693 +}
1694 +
1695 void helper_octeon_cp2_mt_snow3g_start(CPUMIPSState *env, uint64_t value)
1696 {
1697 octeon_snow3g_start(&env->octeon_crypto, value);