#ifndef __AES_HPP__ #define __AES_HPP__ /* Based on reference code from the Intel AES-NI whitepaper * http://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf */ /* Extracted from /usr/lib/gcc/x86_64-linux-gnu/11/include/emmintrin.h and /usr/lib/gcc/x86_64-linux-gnu/11/include/wmmintrin.h */ typedef int __v4si __attribute__ ((__vector_size__ (16))); typedef unsigned long long __v2du __attribute__ ((__vector_size__ (16))); typedef long long __v2di __attribute__ ((__vector_size__ (16))); typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__)); extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_shuffle_epi32 (__m128i __A, const int __mask) { return (__m128i)__builtin_ia32_pshufd ((__v4si)__A, __mask); } extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_slli_si128 (__m128i __A, const int __N) { return (__m128i)__builtin_ia32_pslldqi128 (__A, __N * 8); } extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_xor_si128 (__m128i __A, __m128i __B) { return (__m128i) ((__v2du)__A ^ (__v2du)__B); } extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_aeskeygenassist_si128 (__m128i __X, const int __C) { return (__m128i) __builtin_ia32_aeskeygenassist128 ((__v2di)__X, __C); } extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_aesenc_si128 (__m128i __X, __m128i __Y) { return (__m128i) __builtin_ia32_aesenc128 ((__v2di)__X, (__v2di)__Y); } extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_aesenclast_si128 (__m128i __X, __m128i __Y) { return (__m128i) __builtin_ia32_aesenclast128 ((__v2di)__X, (__v2di)__Y); } extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_set_epi64x (long long __q1, long long __q0) { return __extension__ (__m128i)(__v2di){ __q0, __q1 }; } using AESkey = __m128i[11]; static inline __m128i AES_128_ASSIST (__m128i temp1, __m128i temp2) { __m128i temp3; temp2 = _mm_shuffle_epi32 (temp2 ,0xff); temp3 = _mm_slli_si128 (temp1, 0x4); temp1 = _mm_xor_si128 (temp1, temp3); temp3 = _mm_slli_si128 (temp3, 0x4); temp1 = _mm_xor_si128 (temp1, temp3); temp3 = _mm_slli_si128 (temp3, 0x4); temp1 = _mm_xor_si128 (temp1, temp3); temp1 = _mm_xor_si128 (temp1, temp2); return temp1; } static inline void AES_128_Key_Expansion (AESkey &key, __m128i rawkey) { __m128i temp1, temp2; __m128i *Key_Schedule = key; temp1 = rawkey; Key_Schedule[0] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1 ,0x1); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[1] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1,0x2); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[2] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1,0x4); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[3] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1,0x8); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[4] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1,0x10); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[5] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1,0x20); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[6] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1,0x40); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[7] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1,0x80); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[8] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1,0x1b); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[9] = temp1; temp2 = _mm_aeskeygenassist_si128 (temp1,0x36); temp1 = AES_128_ASSIST(temp1, temp2); Key_Schedule[10] = temp1; } static inline void AES_ECB_encrypt(__m128i &ciphertext, __m128i plaintext, const AESkey &key) { __m128i tmp; int j; tmp = plaintext; tmp = _mm_xor_si128 (tmp,key[0]); for(j=1; j<10; j++){ tmp = _mm_aesenc_si128 (tmp,key[j]); } tmp = _mm_aesenclast_si128 (tmp,key[j]); ciphertext=tmp; } #endif