Skip to contentSkip to conversation

Refactor AES Instructions

PATCH Superseded Tom Musta 2 participants 10 messages Mar 10, 2014 – Mar 13, 2014

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Tom Musta

author
#0 lore raw

cover Refactor AES Instructions

This patch series addresses concerns raised by Richard Henderson regarding redundant copies of Advanced Encryption Standard (AES) data and code (see
http://lists.nongnu.org/archive/html/qemu-devel/2014-02/msg04391.html).

The patches declare commonly used AES tables in the include/qemu/aes.h header file and define the tables in util/aes.c, thus eliminating redundant copies.

Minor refactorization of the i386 and ARM instruction models are made to utilize this common support. The newly added PowerPC instructions are completely rewritten and look much more like the i386 equivalents; a substantial amount of code is eliminated.

Tom Musta (6):
util: Add S-Box and InvS-Box Arrays to Common AES Utils
util: Add AES ShiftRows and InvShiftRows Tables
util: Add InvMixColumns
target-i386: Use Common ShiftRows and InvShiftRows Tables
target-arm: Use Common Tables in AES Instructions
target-ppc: Refactor AES Instructions

 include/qemu/aes.h         |   14 ++
 target-arm/crypto_helper.c |   79 +----------
 target-i386/ops_sse.h      |   32 ++---
 target-ppc/int_helper.c    |  292 +++++--------------------------------
 util/aes.c                 |  343 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 412 insertions(+), 348 deletions(-)
author
#1 lore raw

PATCH 1/6 util: Add S-Box and InvS-Box Arrays to Common AES Utils

This patch adds tables for the S-Box and InvS-Box transformations commonly used by various Advanced Encription Standard (AES) instruction models.

include/qemu/aes.h +3 -0
index e79c707..a4044f5 100644
@@ -23,6 +23,9 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
 		     const unsigned long length, const AES_KEY *key,
 		     unsigned char *ivec, const int enc);
 
+extern const uint8_t AES_sbox[256];
+extern const uint8_t AES_isbox[256];
+
 /*
 AES_Te0[x] = S [x].[02, 01, 01, 03];
 AES_Te1[x] = S [x].[03, 02, 01, 01];
util/aes.c +70 -0

76 lines not on this page · raw message

Signature · 1 line
1.7.1
author
#2 lore raw

PATCH 2/6 util: Add AES ShiftRows and InvShiftRows Tables

In reply to Tom Musta

This patch adds tables that implement the Advanced Encryption Standard (AES) ShiftRows and InvShiftRows transformations. These are commonly used in instruction models.

include/qemu/aes.h +4 -0
index a4044f5..c45bc57 100644
@@ -26,6 +26,10 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
 extern const uint8_t AES_sbox[256];
 extern const uint8_t AES_isbox[256];
 
+/* AES ShiftRows and InvShiftRows */
+extern const uint8_t AES_shifts[16];
+extern const uint8_t AES_ishifts[16];
+
 /*
 AES_Te0[x] = S [x].[02, 01, 01, 03];
 AES_Te1[x] = S [x].[03, 02, 01, 01];
util/aes.c +8 -0
index eeb644b..c26cf55 100644
@@ -108,6 +108,14 @@ const uint8_t AES_isbox[256] = {
     0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D,
 };
 
+const uint8_t AES_shifts[16] = {
+    0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11
+};
+
+const uint8_t AES_ishifts[16] = {
+    0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
+};
+
 /*
 AES_Te0[x] = S [x].[02, 01, 01, 03];
 AES_Te1[x] = S [x].[03, 02, 01, 01];
Signature · 1 line
1.7.1
author
#3 lore raw

PATCH 3/6 util: Add InvMixColumns

In reply to Tom Musta

This patch adds the table implementation of the Advanced Encryption Standard (AES) InvMixColumns transformation.

The patch is intentionally asymmetrical -- the MixColumns table is not added because there is no known use for it at this time.

include/qemu/aes.h +7 -0
index c45bc57..c106660 100644
@@ -30,6 +30,13 @@ extern const uint8_t AES_isbox[256];
 extern const uint8_t AES_shifts[16];
 extern const uint8_t AES_ishifts[16];
 
+/* AES InvMixColumns */
+/* AES_imc[x][0] = [x].[0e, 09, 0d, 0b]; */
+/* AES_imc[x][1] = [x].[0b, 0e, 09, 0d]; */
+/* AES_imc[x][2] = [x].[0d, 0b, 0e, 09]; */
+/* AES_imc[x][3] = [x].[09, 0d, 0b, 0e]; */
+extern const uint32_t AES_imc[256][4];
+
 /*
 AES_Te0[x] = S [x].[02, 01, 01, 03];
 AES_Te1[x] = S [x].[03, 02, 01, 01];
util/aes.c +265 -0

271 lines not on this page · raw message

Signature · 1 line
1.7.1
author
#4 lore raw

PATCH 4/6 target-i386: Use Common ShiftRows and InvShiftRows Tables

In reply to Tom Musta

This patch eliminates the (now) redundant copy of the Advanced Encryption Standard (AES) ShiftRows and InvShiftRows tables; the code is updated to use the common tables declared in include/qemu/aes.h.

target-i386/ops_sse.h +13 -19
index eb24b5f..886e0a8 100644
@@ -17,6 +17,9 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
+
+#include "qemu/aes.h"
+
 #if SHIFT == 0
 #define Reg MMXReg
 #define XMM_ONLY(...)
@@ -2204,15 +2207,6 @@ void glue(helper_pclmulqdq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
     d->Q(1) = resh;
 }
 
-/* AES-NI op helpers */
-static const uint8_t aes_shifts[16] = {
-    0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11
-};
-
-static const uint8_t aes_ishifts[16] = {
-    0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
-};
-
 void glue(helper_aesdec, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
 {
     int i;
@@ -2220,10 +2214,10 @@ void glue(helper_aesdec, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
     Reg rk = *s;
 
     for (i = 0 ; i < 4 ; i++) {
-        d->L(i) = rk.L(i) ^ bswap32(AES_Td0[st.B(aes_ishifts[4*i+0])] ^
-                                    AES_Td1[st.B(aes_ishifts[4*i+1])] ^
-                                    AES_Td2[st.B(aes_ishifts[4*i+2])] ^
-                                    AES_Td3[st.B(aes_ishifts[4*i+3])]);
+        d->L(i) = rk.L(i) ^ bswap32(AES_Td0[st.B(AES_ishifts[4*i+0])] ^
+                                    AES_Td1[st.B(AES_ishifts[4*i+1])] ^
+                                    AES_Td2[st.B(AES_ishifts[4*i+2])] ^
+                                    AES_Td3[st.B(AES_ishifts[4*i+3])]);
     }
 }
 
@@ -2234,7 +2228,7 @@ void glue(helper_aesdeclast, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
     Reg rk = *s;
 
     for (i = 0; i < 16; i++) {
-        d->B(i) = rk.B(i) ^ (AES_Td4[st.B(aes_ishifts[i])] & 0xff);
+        d->B(i) = rk.B(i) ^ (AES_Td4[st.B(AES_ishifts[i])] & 0xff);
     }
 }
 
@@ -2245,10 +2239,10 @@ void glue(helper_aesenc, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
     Reg rk = *s;
 
     for (i = 0 ; i < 4 ; i++) {
-        d->L(i) = rk.L(i) ^ bswap32(AES_Te0[st.B(aes_shifts[4*i+0])] ^
-                                    AES_Te1[st.B(aes_shifts[4*i+1])] ^
-                                    AES_Te2[st.B(aes_shifts[4*i+2])] ^
-                                    AES_Te3[st.B(aes_shifts[4*i+3])]);
+        d->L(i) = rk.L(i) ^ bswap32(AES_Te0[st.B(AES_shifts[4*i+0])] ^
+                                    AES_Te1[st.B(AES_shifts[4*i+1])] ^
+                                    AES_Te2[st.B(AES_shifts[4*i+2])] ^
+                                    AES_Te3[st.B(AES_shifts[4*i+3])]);
     }
 }
 
@@ -2259,7 +2253,7 @@ void glue(helper_aesenclast, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
     Reg rk = *s;
 
     for (i = 0; i < 16; i++) {
-        d->B(i) = rk.B(i) ^ (AES_Te4[st.B(aes_shifts[i])] & 0xff);
+        d->B(i) = rk.B(i) ^ (AES_Te4[st.B(AES_shifts[i])] & 0xff);
     }
 
 }
Signature · 1 line
1.7.1
author
#5 lore raw

PATCH 5/6 target-arm: Use Common Tables in AES Instructions

In reply to Tom Musta

This patch refactors the ARM cryptographic instructions to use the (newly) added common tables from include/qemu/aes.h.

target-arm/crypto_helper.c +4 -75
index f94be69..9dc0c8e 100644
@@ -14,6 +14,7 @@
 #include "cpu.h"
 #include "exec/exec-all.h"
 #include "helper.h"
+#include "qemu/aes.h"
 
 union AES_STATE {
     uint8_t    bytes[16];
@@ -24,81 +25,9 @@ union AES_STATE {
 void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
                          uint32_t decrypt)
 {
-    static uint8_t const sbox[][256] = { {
-        /* S-box for encryption */
-        0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
-        0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
-        0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
-        0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
-        0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
-        0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
-        0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
-        0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
-        0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
-        0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
-        0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
-        0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
-        0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
-        0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
-        0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
-        0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
-        0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
-        0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
-        0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
-        0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
-        0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
-        0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
-        0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
-        0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
-        0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
-        0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
-        0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
-        0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
-        0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
-        0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
-        0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
-        0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
-    }, {
-        /* S-box for decryption */
-        0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
-        0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
-        0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
-        0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
-        0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
-        0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
-        0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
-        0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
-        0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
-        0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
-        0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
-        0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
-        0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
-        0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
-        0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
-        0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
-        0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
-        0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
-        0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
-        0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
-        0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
-        0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
-        0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
-        0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
-        0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
-        0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
-        0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
-        0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
-        0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
-        0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
-        0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
-        0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
-    } };
-    static uint8_t const shift[][16] = {
-        /* ShiftRows permutation vector for encryption */
-        { 0,  5, 10, 15, 4, 9, 14,  3, 8, 13, 2,  7, 12, 1, 6, 11 },
-        /* ShiftRows permutation vector for decryption */
-        { 0, 13, 10,  7, 4, 1, 14, 11, 8,  5, 2, 15, 12, 9, 6,  3 },
-    };
+    static uint8_t const *sbox[2] = { AES_sbox, AES_isbox };
+    static uint8_t const *shift[2] = { AES_shifts, AES_ishifts };
+
     union AES_STATE rk = { .l = {
         float64_val(env->vfp.regs[rm]),
         float64_val(env->vfp.regs[rm + 1])
Signature · 1 line
1.7.1
#6 lore raw

Re: [Qemu-devel] [PATCH 5/6] target-arm: Use Common Tables in AES Instructions

Quoted 1 line · Tom Musta

+ static uint8_t const *sbox[2] = { AES_sbox, AES_isbox };

Missing const:

static uint8_t const * const sbox[2] = ...

r~

author
#7 lore raw

PATCH 6/6 target-ppc: Refactor AES Instructions

In reply to Tom Musta

This patch refactors the PowerPC Advanced Encryption Standard (AES) instructions to use the common AES tables (include/qemu/aes.h).

Specifically:
- vsbox is recoded to use the AES_sbox table.
- vcipher, vcipherlast and vncipherlast are all recoded to use the optimized AES_t[ed][0-4] tables.
- vncipher is recoded to use a combination of InvS-Box, InvShiftRows and InvMixColumns tables. It was not possible to use AES_Td[0-4] due to a slight difference in how PowerPC implements vncipher.

target-ppc/int_helper.c +38 -254
index 582d8ac..c7d8cb6 100644
@@ -19,6 +19,7 @@
 #include "cpu.h"
 #include "qemu/host-utils.h"
 #include "helper.h"
+#include "qemu/aes.h"
 
 #include "helper_regs.h"
 /*****************************************************************************/
@@ -396,9 +397,13 @@ target_ulong helper_602_mfrom(target_ulong arg)
 #if defined(HOST_WORDS_BIGENDIAN)
 #define HI_IDX 0
 #define LO_IDX 1
+#define AVRB(i) u8[i]
+#define AVRW(i) u32[i]
 #else
 #define HI_IDX 1
 #define LO_IDX 0
+#define AVRB(i) u8[15-(i)]
+#define AVRW(i) u32[3-(i)]
 #endif
 
 #if defined(HOST_WORDS_BIGENDIAN)
@@ -2338,284 +2343,63 @@ uint32_t helper_bcdsub(ppc_avr_t *r,  ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
     return helper_bcdadd(r, a, &bcopy, ps);
 }
 
-static uint8_t SBOX[256] = {
-0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
-0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
-0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
-0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
-0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
-0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
-0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
-0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
-0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
-0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
-0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
-0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
-0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
-0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
-0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
-0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
-0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
-0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
-0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
-0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
-0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
-0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
-0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
-0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
-0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
-0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
-0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
-0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
-0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
-0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
-0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
-0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16,
-};
-
-static void SubBytes(ppc_avr_t *r, ppc_avr_t *a)
-{
-    int i;
-    VECTOR_FOR_INORDER_I(i, u8) {
-        r->u8[i] = SBOX[a->u8[i]];
-    }
-}
-
-static uint8_t InvSBOX[256] = {
-0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
-0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
-0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
-0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
-0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
-0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
-0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
-0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
-0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
-0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
-0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
-0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
-0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
-0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
-0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
-0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
-0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
-0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
-0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
-0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
-0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
-0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
-0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
-0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
-0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
-0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
-0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
-0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
-0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
-0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
-0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
-0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D,
-};
-
-static void InvSubBytes(ppc_avr_t *r, ppc_avr_t *a)
+void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
 {
     int i;
     VECTOR_FOR_INORDER_I(i, u8) {
-        r->u8[i] = InvSBOX[a->u8[i]];
+        r->u8[i] = AES_sbox[a->u8[i]];
     }
 }
 
-static uint8_t ROTL8(uint8_t x, int n)
-{
-    return (x << n) | (x >> (8-n));
-}
-
-static inline int BIT8(uint8_t x, int n)
-{
-    return (x & (0x80 >> n)) != 0;
-}
-
-static uint8_t GFx02(uint8_t x)
-{
-    return ROTL8(x, 1) ^ (BIT8(x, 0) ? 0x1A : 0);
-}
-
-static uint8_t GFx03(uint8_t x)
-{
-    return x ^ ROTL8(x, 1) ^ (BIT8(x, 0) ? 0x1A : 0);
-}
-
-static uint8_t GFx09(uint8_t x)
-{
-    uint8_t term2 = ROTL8(x, 3);
-    uint8_t term3 = (BIT8(x, 0) ? 0x68 : 0) | (BIT8(x, 1) ? 0x14 : 0) |
-                    (BIT8(x, 2) ? 0x02 : 0);
-    uint8_t term4 = (BIT8(x, 1) ? 0x20 : 0) | (BIT8(x, 2) ? 0x18 : 0);
-    return x ^ term2 ^ term3 ^ term4;
-}
-
-static uint8_t GFx0B(uint8_t x)
-{
-    uint8_t term2 = ROTL8(x, 1);
-    uint8_t term3 = (x << 3) | (BIT8(x, 0) ? 0x06 : 0) |
-                    (BIT8(x, 2) ? 0x01 : 0);
-    uint8_t term4 = (BIT8(x, 0) ? 0x70 : 0) | (BIT8(x, 1) ? 0x06 : 0) |
-                    (BIT8(x, 2) ? 0x08 : 0);
-    uint8_t term5 = (BIT8(x, 1) ? 0x30 : 0) | (BIT8(x, 2) ? 0x02 : 0);
-    uint8_t term6 = BIT8(x, 2) ? 0x10 : 0;
-    return x ^ term2 ^ term3 ^ term4 ^ term5 ^ term6;
-}
-
-static uint8_t GFx0D(uint8_t x)
-{
-    uint8_t term2 = ROTL8(x, 2);
-    uint8_t term3 = (x << 3) | (BIT8(x, 1) ? 0x04 : 0) |
-                    (BIT8(x, 2) ? 0x03 : 0);
-    uint8_t term4 = (BIT8(x, 0) ? 0x58 : 0) | (BIT8(x, 1) ? 0x20 : 0);
-    uint8_t term5 = (BIT8(x, 1) ? 0x08 : 0) | (BIT8(x, 2) ? 0x10 : 0);
-    uint8_t term6 = BIT8(x, 2) ? 0x08 : 0;
-    return x ^ term2 ^ term3 ^ term4 ^ term5 ^ term6;
-}
-
-static uint8_t GFx0E(uint8_t x)
-{
-    uint8_t term1 = ROTL8(x, 1);
-    uint8_t term2 = (x << 2) | (BIT8(x, 2) ? 0x02 : 0) |
-                    (BIT8(x, 1) ? 0x01 : 0);
-    uint8_t term3 = (x << 3) | (BIT8(x, 1) ? 0x04 : 0) |
-                    (BIT8(x, 2) ? 0x01 : 0);
-    uint8_t term4 = (BIT8(x, 0) ? 0x40 : 0) | (BIT8(x, 1) ? 0x28 : 0) |
-                    (BIT8(x, 2) ? 0x10 : 0);
-    uint8_t term5 = (BIT8(x, 2) ? 0x08 : 0);
-    return term1 ^ term2 ^ term3 ^ term4 ^ term5;
-}
-
-#if defined(HOST_WORDS_BIGENDIAN)
-#define MCB(x, i, b) ((x)->u8[(i)*4 + (b)])
-#else
-#define MCB(x, i, b) ((x)->u8[15 - ((i)*4 + (b))])
-#endif
-
-static void MixColumns(ppc_avr_t *r, ppc_avr_t *x)
+void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
     int i;
-    for (i = 0; i < 4; i++) {
-        MCB(r, i, 0) = GFx02(MCB(x, i, 0)) ^ GFx03(MCB(x, i, 1)) ^
-                       MCB(x, i, 2) ^ MCB(x, i, 3);
-        MCB(r, i, 1) = MCB(x, i, 0) ^ GFx02(MCB(x, i, 1)) ^
-                       GFx03(MCB(x, i, 2)) ^ MCB(x, i, 3);
-        MCB(r, i, 2) = MCB(x, i, 0) ^ MCB(x, i, 1) ^
-                       GFx02(MCB(x, i, 2)) ^ GFx03(MCB(x, i, 3));
-        MCB(r, i, 3) = GFx03(MCB(x, i, 0)) ^ MCB(x, i, 1) ^
-                       MCB(x, i, 2) ^ GFx02(MCB(x, i, 3));
-    }
-}
 
-static void InvMixColumns(ppc_avr_t *r, ppc_avr_t *x)
-{
-    int i;
-    for (i = 0; i < 4; i++) {
-        MCB(r, i, 0) = GFx0E(MCB(x, i, 0)) ^ GFx0B(MCB(x, i, 1)) ^
-                       GFx0D(MCB(x, i, 2)) ^ GFx09(MCB(x, i, 3));
-        MCB(r, i, 1) = GFx09(MCB(x, i, 0)) ^ GFx0E(MCB(x, i, 1)) ^
-                       GFx0B(MCB(x, i, 2)) ^ GFx0D(MCB(x, i, 3));
-        MCB(r, i, 2) = GFx0D(MCB(x, i, 0)) ^ GFx09(MCB(x, i, 1)) ^
-                       GFx0E(MCB(x, i, 2)) ^ GFx0B(MCB(x, i, 3));
-        MCB(r, i, 3) = GFx0B(MCB(x, i, 0)) ^ GFx0D(MCB(x, i, 1)) ^
-                       GFx09(MCB(x, i, 2)) ^ GFx0E(MCB(x, i, 3));
+    VECTOR_FOR_INORDER_I(i, u32) {
+        r->AVRW(i) = b->AVRW(i) ^
+            (AES_Te0[a->AVRB(AES_shifts[4*i + 0])] ^
+             AES_Te1[a->AVRB(AES_shifts[4*i + 1])] ^
+             AES_Te2[a->AVRB(AES_shifts[4*i + 2])] ^
+             AES_Te3[a->AVRB(AES_shifts[4*i + 3])]);
     }
 }
 
-static void ShiftRows(ppc_avr_t *r, ppc_avr_t *x)
-{
-    MCB(r, 0, 0) = MCB(x, 0, 0);
-    MCB(r, 1, 0) = MCB(x, 1, 0);
-    MCB(r, 2, 0) = MCB(x, 2, 0);
-    MCB(r, 3, 0) = MCB(x, 3, 0);
-
-    MCB(r, 0, 1) = MCB(x, 1, 1);
-    MCB(r, 1, 1) = MCB(x, 2, 1);
-    MCB(r, 2, 1) = MCB(x, 3, 1);
-    MCB(r, 3, 1) = MCB(x, 0, 1);
-
-    MCB(r, 0, 2) = MCB(x, 2, 2);
-    MCB(r, 1, 2) = MCB(x, 3, 2);
-    MCB(r, 2, 2) = MCB(x, 0, 2);
-    MCB(r, 3, 2) = MCB(x, 1, 2);
-
-    MCB(r, 0, 3) = MCB(x, 3, 3);
-    MCB(r, 1, 3) = MCB(x, 0, 3);
-    MCB(r, 2, 3) = MCB(x, 1, 3);
-    MCB(r, 3, 3) = MCB(x, 2, 3);
-}
-
-static void InvShiftRows(ppc_avr_t *r, ppc_avr_t *x)
-{
-    MCB(r, 0, 0) = MCB(x, 0, 0);
-    MCB(r, 1, 0) = MCB(x, 1, 0);
-    MCB(r, 2, 0) = MCB(x, 2, 0);
-    MCB(r, 3, 0) = MCB(x, 3, 0);
-
-    MCB(r, 0, 1) = MCB(x, 3, 1);
-    MCB(r, 1, 1) = MCB(x, 0, 1);
-    MCB(r, 2, 1) = MCB(x, 1, 1);
-    MCB(r, 3, 1) = MCB(x, 2, 1);
-
-    MCB(r, 0, 2) = MCB(x, 2, 2);
-    MCB(r, 1, 2) = MCB(x, 3, 2);
-    MCB(r, 2, 2) = MCB(x, 0, 2);
-    MCB(r, 3, 2) = MCB(x, 1, 2);
-
-    MCB(r, 0, 3) = MCB(x, 1, 3);
-    MCB(r, 1, 3) = MCB(x, 2, 3);
-    MCB(r, 2, 3) = MCB(x, 3, 3);
-    MCB(r, 3, 3) = MCB(x, 0, 3);
-}
-
-#undef MCB
-
-void helper_vsbox(ppc_avr_t *r, ppc_avr_t *a)
-{
-    SubBytes(r, a);
-}
-
-void helper_vcipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
-{
-    ppc_avr_t vtemp1, vtemp2, vtemp3;
-    SubBytes(&vtemp1, a);
-    ShiftRows(&vtemp2, &vtemp1);
-    MixColumns(&vtemp3, &vtemp2);
-    r->u64[0] = vtemp3.u64[0] ^ b->u64[0];
-    r->u64[1] = vtemp3.u64[1] ^ b->u64[1];
-}
-
 void helper_vcipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-    ppc_avr_t vtemp1, vtemp2;
-    SubBytes(&vtemp1, a);
-    ShiftRows(&vtemp2, &vtemp1);
-    r->u64[0] = vtemp2.u64[0] ^ b->u64[0];
-    r->u64[1] = vtemp2.u64[1] ^ b->u64[1];
+    int i;
+
+    VECTOR_FOR_INORDER_I(i, u8) {
+        r->AVRB(i) = b->AVRB(i) ^ (AES_Te4[a->AVRB(AES_shifts[i])] & 0xFF);
+    }
 }
 
 void helper_vncipher(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
     /* This differs from what is written in ISA V2.07.  The RTL is */
     /* incorrect and will be fixed in V2.07B.                      */
-    ppc_avr_t vtemp1, vtemp2, vtemp3;
-    InvShiftRows(&vtemp1, a);
-    InvSubBytes(&vtemp2, &vtemp1);
-    vtemp3.u64[0] = vtemp2.u64[0] ^ b->u64[0];
-    vtemp3.u64[1] = vtemp2.u64[1] ^ b->u64[1];
-    InvMixColumns(r, &vtemp3);
+    int i;
+    ppc_avr_t tmp;
+
+    VECTOR_FOR_INORDER_I(i, u8) {
+        tmp.AVRB(i) = b->AVRB(i) ^ AES_isbox[a->AVRB(AES_ishifts[i])];
+    }
+
+    VECTOR_FOR_INORDER_I(i, u32) {
+        r->AVRW(i) =
+            AES_imc[tmp.AVRB(4*i + 0)][0] ^
+            AES_imc[tmp.AVRB(4*i + 1)][1] ^
+            AES_imc[tmp.AVRB(4*i + 2)][2] ^
+            AES_imc[tmp.AVRB(4*i + 3)][3];
+    }
 }
 
 void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
 {
-    ppc_avr_t vtemp1, vtemp2;
-    InvShiftRows(&vtemp1, a);
-    InvSubBytes(&vtemp2, &vtemp1);
-    r->u64[0] = vtemp2.u64[0] ^ b->u64[0];
-    r->u64[1] = vtemp2.u64[1] ^ b->u64[1];
+    int i;
+
+    VECTOR_FOR_INORDER_I(i, u8) {
+        r->AVRB(i) = b->AVRB(i) ^ (AES_Td4[a->AVRB(AES_ishifts[i])] & 0xFF);
+    }
 }
 
 #define ROTRu32(v, n) (((v) >> (n)) | ((v) << (32-n)))
Signature · 1 line
1.7.1
Reviewed-by on the v1 series
#8 lore raw
In reply to Tom Musta
Quoted 12 lines · Tom Musta

This patch series addresses concerns raised by Richard Henderson regarding redundant copies of Advanced Encryption Standard (AES) data and code (see
http://lists.nongnu.org/archive/html/qemu-devel/2014-02/msg04391.html).

The patches declare commonly used AES tables in the include/qemu/aes.h header file and define the tables in util/aes.c, thus eliminating redundant copies.

Minor refactorization of the i386 and ARM instruction models are made to utilize this common support. The newly added PowerPC instructions are completely rewritten and look much more like the i386 equivalents; a substantial amount of code is eliminated.

Quoted 7 lines

Tom Musta (6):
util: Add S-Box and InvS-Box Arrays to Common AES Utils
util: Add AES ShiftRows and InvShiftRows Tables
util: Add InvMixColumns
target-i386: Use Common ShiftRows and InvShiftRows Tables
target-arm: Use Common Tables in AES Instructions
target-ppc: Refactor AES Instructions

Other than the one nit,

r~

author
#9 lore raw
Quoted 21 lines · Richard Henderson
Quoted 12 lines · Tom Musta

This patch series addresses concerns raised by Richard Henderson regarding redundant copies of Advanced Encryption Standard (AES) data and code (see
http://lists.nongnu.org/archive/html/qemu-devel/2014-02/msg04391.html).

The patches declare commonly used AES tables in the include/qemu/aes.h header file and define the tables in util/aes.c, thus eliminating redundant copies.

Minor refactorization of the i386 and ARM instruction models are made to utilize this common support. The newly added PowerPC instructions are completely rewritten and look much more like the i386 equivalents; a substantial amount of code is eliminated.

Quoted 7 lines

Tom Musta (6):
util: Add S-Box and InvS-Box Arrays to Common AES Utils
util: Add AES ShiftRows and InvShiftRows Tables
util: Add InvMixColumns
target-i386: Use Common ShiftRows and InvShiftRows Tables
target-arm: Use Common Tables in AES Instructions
target-ppc: Refactor AES Instructions

Quoted 7 lines

Other than the one nit,

r~

Thanks. I will rework the nit and republish a V2.