target/mips: add Octeon AES COP2 helpers
Add helper support for the Octeon AES operation selectors. Direct register-transfer selectors do not need helpers; the ECB/CBC encrypt and decrypt operations consume the AES input, key, IV, and key-length state. AESRESINP is modeled as one architectural register bank; operation helpers consume the current AESRESINP block and write the result back to the same bank. Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-8-daef7a0d8b04@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
James Hilliard committed
Jun 8, 2026 at 12:59 UTC
9bf93903f715d1188d0a9640f727ffe554fc5b7d
2 files changed
+149
target/mips/helper.h
+4
@@ -52,6 +52,10 @@ DEF_HELPER_2(octeon_cp2_mt_zuc_start, void, env, i64)
52
DEF_HELPER_2(octeon_cp2_mt_zuc_more, void, env, i64)
53
DEF_HELPER_2(octeon_cp2_mt_snow3g_start, void, env, i64)
54
DEF_HELPER_2(octeon_cp2_mt_snow3g_more, void, env, i64)
55
+DEF_HELPER_2(octeon_cp2_mt_aes_enc_cbc1, void, env, i64)
56
+DEF_HELPER_2(octeon_cp2_mt_aes_enc1, void, env, i64)
57
+DEF_HELPER_2(octeon_cp2_mt_aes_dec_cbc1, void, env, i64)
58
+DEF_HELPER_2(octeon_cp2_mt_aes_dec1, void, env, i64)
59
60
/* microMIPS functions */
61
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
target/mips/tcg/octeon_crypto.c
+145
@@ -840,6 +840,151 @@ static void octeon_snow3g_more(MIPSOcteonCryptoState *crypto)
840
octeon_snow3g_queue_result(crypto);
841
}
842
843
+static int octeon_aes_key_bits(const MIPSOcteonCryptoState *crypto)
844
+{
845
+ enum {
846
+ OCTEON_AES_KEYLEN_128 = 1,
847
+ OCTEON_AES_KEYLEN_192 = 2,
848
+ OCTEON_AES_KEYLEN_256 = 3,
849
+ };
850
+
851
+ switch (crypto->aes_keylen) {
852
+ case OCTEON_AES_KEYLEN_128:
853
+ return 128;
854
+ case OCTEON_AES_KEYLEN_192:
855
+ return 192;
856
+ case OCTEON_AES_KEYLEN_256:
857
+ return 256;
858
+ default:
859
+ return 0;
860
+ }
861
+}
862
+
863
+static void octeon_aes_load_key(const MIPSOcteonCryptoState *crypto,
864
+ uint8_t *key, size_t keylen)
865
+{
866
+ stq_be_p(key, crypto->aes_key[0]);
867
+ stq_be_p(key + 8, crypto->aes_key[1]);
868
+ if (keylen > 16) {
869
+ stq_be_p(key + 16, crypto->aes_key[2]);
870
+ }
871
+ if (keylen > 24) {
872
+ stq_be_p(key + 24, crypto->aes_key[3]);
873
+ }
874
+}
875
+
876
+static void octeon_aes_load_block(const uint64_t regs[2], uint8_t *block)
877
+{
878
+ stq_be_p(block, regs[0]);
879
+ stq_be_p(block + 8, regs[1]);
880
+}
881
+
882
+static void octeon_aes_store_block(uint64_t regs[2], const uint8_t *block)
883
+{
884
+ regs[0] = ldq_be_p(block);
885
+ regs[1] = ldq_be_p(block + 8);
886
+}
887
+
888
+static void octeon_aes_encrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)
889
+{
890
+ AES_KEY key;
891
+ uint8_t in[16];
892
+ uint8_t out[16];
893
+ uint8_t iv[16];
894
+ uint8_t raw_key[32] = {};
895
+ int bits = octeon_aes_key_bits(crypto);
896
+
897
+ if (!bits) {
898
+ return;
899
+ }
900
+
901
+ octeon_aes_load_key(crypto, raw_key, bits / 8);
902
+ octeon_aes_load_block(crypto->aes_resinp, in);
903
+ if (cbc) {
904
+ int i;
905
+
906
+ octeon_aes_load_block(crypto->aes_iv, iv);
907
+ for (i = 0; i < sizeof(in); i++) {
908
+ in[i] ^= iv[i];
909
+ }
910
+ }
911
+
912
+ AES_set_encrypt_key(raw_key, bits, &key);
913
+ AES_encrypt(in, out, &key);
914
+ octeon_aes_store_block(crypto->aes_resinp, out);
915
+ if (cbc) {
916
+ octeon_aes_store_block(crypto->aes_iv, out);
917
+ }
918
+}
919
+
920
+static void octeon_aes_decrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)
921
+{
922
+ AES_KEY key;
923
+ uint8_t in[16];
924
+ uint8_t out[16];
925
+ uint8_t iv[16];
926
+ uint8_t next_iv[16];
927
+ uint8_t raw_key[32] = {};
928
+ int bits = octeon_aes_key_bits(crypto);
929
+ int i;
930
+
931
+ if (!bits) {
932
+ return;
933
+ }
934
+
935
+ octeon_aes_load_key(crypto, raw_key, bits / 8);
936
+ octeon_aes_load_block(crypto->aes_resinp, in);
937
+ if (cbc) {
938
+ memcpy(next_iv, in, sizeof(next_iv));
939
+ octeon_aes_load_block(crypto->aes_iv, iv);
940
+ }
941
+
942
+ AES_set_decrypt_key(raw_key, bits, &key);
943
+ AES_decrypt(in, out, &key);
944
+ if (cbc) {
945
+ for (i = 0; i < sizeof(out); i++) {
946
+ out[i] ^= iv[i];
947
+ }
948
+ }
949
+
950
+ octeon_aes_store_block(crypto->aes_resinp, out);
951
+ if (cbc) {
952
+ octeon_aes_store_block(crypto->aes_iv, next_iv);
953
+ }
954
+}
955
+
956
+void helper_octeon_cp2_mt_aes_enc_cbc1(CPUMIPSState *env, uint64_t value)
957
+{
958
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
959
+
960
+ crypto->aes_resinp[1] = value;
961
+ octeon_aes_encrypt_common(crypto, true);
962
+}
963
+
964
+void helper_octeon_cp2_mt_aes_enc1(CPUMIPSState *env, uint64_t value)
965
+{
966
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
967
+
968
+ crypto->aes_resinp[1] = value;
969
+ octeon_aes_encrypt_common(crypto, false);
970
+}
971
+
972
+void helper_octeon_cp2_mt_aes_dec_cbc1(CPUMIPSState *env, uint64_t value)
973
+{
974
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
975
+
976
+ crypto->aes_resinp[1] = value;
977
+ octeon_aes_decrypt_common(crypto, true);
978
+}
979
+
980
+void helper_octeon_cp2_mt_aes_dec1(CPUMIPSState *env, uint64_t value)
981
+{
982
+ MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
983
+
984
+ crypto->aes_resinp[1] = value;
985
+ octeon_aes_decrypt_common(crypto, false);
986
+}
987
+
988
void helper_octeon_cp2_mt_snow3g_start(CPUMIPSState *env, uint64_t value)
989
{
990
octeon_snow3g_start(&env->octeon_crypto, value);