Refactor AES Instructions
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(-)
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
@@ -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
PATCH 2/6 util: Add AES ShiftRows and InvShiftRows Tables
In reply to Tom MustaThis 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
@@ -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
@@ -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
PATCH 3/6 util: Add InvMixColumns
In reply to Tom MustaThis 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
@@ -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
PATCH 4/6 target-i386: Use Common ShiftRows and InvShiftRows Tables
In reply to Tom MustaThis 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
@@ -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
PATCH 5/6 target-arm: Use Common Tables in AES Instructions
In reply to Tom MustaThis 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
@@ -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
Re: [Qemu-devel] [PATCH 5/6] target-arm: Use Common Tables in AES Instructions
Quoted 1 line · Tom Musta
+ static
uint8_tconst *sbox[2] = {AES_sbox,AES_isbox};
Missing const:
static uint8_t const * const sbox[2] = ...
r~
PATCH 6/6 target-ppc: Refactor AES Instructions
In reply to Tom MustaThis 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
@@ -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
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.hheader file and define the tables inutil/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~
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.hheader file and define the tables inutil/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,
Reviewed-by Richard Henderson <[email protected]>r~
Thanks. I will rework the nit and republish a V2.