mirror of
https://github.com/QuasarApp/Qt-AES.git
synced 2025-04-28 06:34:33 +00:00
* Pass expKey parameter of addRoundKey() by const reference to avoid unnecessary copy. * Use C++11 nullptr instead of NULL, make it clear that default value of iv parameter in encode() and decode() is empty QByteArray instead of implicit conversion from null pointer via QByteArray(const char *, int = -1) constructor. * Change parameter names in declarations of cipher(), invCipher() and byteXor() to match definitions. * Convert AES-NI-related files to headers, place functions with internal linkage to anonymous namespace to avoid exporting them, don't use inline specifier (inline keyword have different meaning in C++ rather than in C). * Use char literals instead of implementation-defined int-to-signed-char conversions where possible. * Set default value for padding argument in static RemovePadding() to match sample in README.
200 lines
7.1 KiB
C
200 lines
7.1 KiB
C
#ifndef AESNIKEYEXP_H
|
|
#define AESNIKEYEXP_H
|
|
|
|
#include <wmmintrin.h>
|
|
|
|
#define cpuid(func, ax, bx, cx, dx)\
|
|
__asm__ __volatile__("cpuid": "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
|
|
|
|
namespace {
|
|
|
|
bool check_aesni_support()
|
|
{
|
|
unsigned int a,b,c,d;
|
|
cpuid(1, a,b,c,d);
|
|
return (c & 0x2000000);
|
|
}
|
|
|
|
__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;
|
|
}
|
|
|
|
void AES_128_Key_Expansion (const unsigned char *userkey,
|
|
unsigned char *key)
|
|
{
|
|
__m128i temp1, temp2;
|
|
__m128i *Key_Schedule = (__m128i*)key;
|
|
temp1 = _mm_loadu_si128((__m128i*)userkey);
|
|
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;
|
|
}
|
|
|
|
void KEY_192_ASSIST(__m128i* temp1, __m128i * temp2, __m128i * temp3)
|
|
{
|
|
__m128i temp4;
|
|
*temp2 = _mm_shuffle_epi32 (*temp2, 0x55);
|
|
temp4 = _mm_slli_si128 (*temp1, 0x4);
|
|
*temp1 = _mm_xor_si128 (*temp1, temp4);
|
|
temp4 = _mm_slli_si128 (temp4, 0x4);
|
|
*temp1 = _mm_xor_si128 (*temp1, temp4);
|
|
temp4 = _mm_slli_si128 (temp4, 0x4);
|
|
*temp1 = _mm_xor_si128 (*temp1, temp4);
|
|
*temp1 = _mm_xor_si128 (*temp1, *temp2);
|
|
*temp2 = _mm_shuffle_epi32(*temp1, 0xff);
|
|
temp4 = _mm_slli_si128 (*temp3, 0x4);
|
|
*temp3 = _mm_xor_si128 (*temp3, temp4);
|
|
*temp3 = _mm_xor_si128 (*temp3, *temp2);
|
|
}
|
|
|
|
void AES_192_Key_Expansion (const unsigned char *userkey, unsigned char *key)
|
|
{
|
|
__m128i temp1, temp2, temp3;
|
|
__m128i *Key_Schedule = (__m128i*)key;
|
|
temp1 = _mm_loadu_si128((__m128i*)userkey);
|
|
temp3 = _mm_loadu_si128((__m128i*)(userkey+16));
|
|
Key_Schedule[0]=temp1; Key_Schedule[1]=temp3;
|
|
temp2=_mm_aeskeygenassist_si128 (temp3,0x1);
|
|
KEY_192_ASSIST(&temp1, &temp2, &temp3);
|
|
Key_Schedule[1] = (__m128i)_mm_shuffle_pd((__m128d)Key_Schedule[1], (__m128d)temp1,0);
|
|
Key_Schedule[2] = (__m128i)_mm_shuffle_pd((__m128d)temp1,(__m128d)temp3,1);
|
|
temp2=_mm_aeskeygenassist_si128 (temp3,0x2);
|
|
KEY_192_ASSIST(&temp1, &temp2, &temp3);
|
|
Key_Schedule[3]=temp1;
|
|
Key_Schedule[4]=temp3;
|
|
temp2=_mm_aeskeygenassist_si128 (temp3,0x4);
|
|
KEY_192_ASSIST(&temp1, &temp2, &temp3);
|
|
Key_Schedule[4] = (__m128i)_mm_shuffle_pd((__m128d)Key_Schedule[4], (__m128d)temp1,0);
|
|
Key_Schedule[5] = (__m128i)_mm_shuffle_pd((__m128d)temp1,(__m128d)temp3,1);
|
|
temp2=_mm_aeskeygenassist_si128 (temp3,0x8);
|
|
KEY_192_ASSIST(&temp1, &temp2, &temp3);
|
|
Key_Schedule[6]=temp1;
|
|
Key_Schedule[7]=temp3;
|
|
temp2=_mm_aeskeygenassist_si128 (temp3,0x10);
|
|
KEY_192_ASSIST(&temp1, &temp2, &temp3);
|
|
Key_Schedule[7] = (__m128i)_mm_shuffle_pd((__m128d)Key_Schedule[7], (__m128d)temp1,0);
|
|
Key_Schedule[8] = (__m128i)_mm_shuffle_pd((__m128d)temp1,(__m128d)temp3,1);
|
|
temp2=_mm_aeskeygenassist_si128 (temp3,0x20);
|
|
KEY_192_ASSIST(&temp1, &temp2, &temp3);
|
|
Key_Schedule[9]=temp1;
|
|
Key_Schedule[10]=temp3;
|
|
temp2=_mm_aeskeygenassist_si128 (temp3,0x40);
|
|
KEY_192_ASSIST(&temp1, &temp2, &temp3);
|
|
Key_Schedule[10] = (__m128i)_mm_shuffle_pd((__m128d)Key_Schedule[10], (__m128d)temp1,0);
|
|
Key_Schedule[11] = (__m128i)_mm_shuffle_pd((__m128d)temp1,(__m128d)temp3,1);
|
|
temp2=_mm_aeskeygenassist_si128 (temp3,0x80);
|
|
KEY_192_ASSIST(&temp1, &temp2, &temp3);
|
|
Key_Schedule[12]=temp1;
|
|
}
|
|
|
|
void KEY_256_ASSIST_1(__m128i* temp1, __m128i * temp2)
|
|
{
|
|
__m128i temp4;
|
|
*temp2 = _mm_shuffle_epi32(*temp2, 0xff);
|
|
temp4 = _mm_slli_si128 (*temp1, 0x4);
|
|
*temp1 = _mm_xor_si128 (*temp1, temp4);
|
|
temp4 = _mm_slli_si128 (temp4, 0x4);
|
|
*temp1 = _mm_xor_si128 (*temp1, temp4);
|
|
temp4 = _mm_slli_si128 (temp4, 0x4);
|
|
*temp1 = _mm_xor_si128 (*temp1, temp4);
|
|
*temp1 = _mm_xor_si128 (*temp1, *temp2);
|
|
}
|
|
|
|
void KEY_256_ASSIST_2(__m128i* temp1, __m128i * temp3)
|
|
{
|
|
__m128i temp2,temp4;
|
|
temp4 = _mm_aeskeygenassist_si128 (*temp1, 0x0);
|
|
temp2 = _mm_shuffle_epi32(temp4, 0xaa);
|
|
temp4 = _mm_slli_si128 (*temp3, 0x4);
|
|
*temp3 = _mm_xor_si128 (*temp3, temp4);
|
|
temp4 = _mm_slli_si128 (temp4, 0x4);
|
|
*temp3 = _mm_xor_si128 (*temp3, temp4);
|
|
temp4 = _mm_slli_si128 (temp4, 0x4);
|
|
*temp3 = _mm_xor_si128 (*temp3, temp4);
|
|
*temp3 = _mm_xor_si128 (*temp3, temp2);
|
|
}
|
|
|
|
void AES_256_Key_Expansion (const unsigned char *userkey, unsigned char *key)
|
|
{
|
|
__m128i temp1, temp2, temp3;
|
|
__m128i *Key_Schedule = (__m128i*)key;
|
|
temp1 = _mm_loadu_si128((__m128i*)userkey);
|
|
temp3 = _mm_loadu_si128((__m128i*)(userkey+16));
|
|
Key_Schedule[0] = temp1; Key_Schedule[1] = temp3;
|
|
temp2 = _mm_aeskeygenassist_si128 (temp3,0x01);
|
|
KEY_256_ASSIST_1(&temp1, &temp2);
|
|
Key_Schedule[2]=temp1;
|
|
KEY_256_ASSIST_2(&temp1, &temp3);
|
|
Key_Schedule[3]=temp3;
|
|
temp2 = _mm_aeskeygenassist_si128 (temp3,0x02);
|
|
KEY_256_ASSIST_1(&temp1, &temp2);
|
|
Key_Schedule[4]=temp1;
|
|
KEY_256_ASSIST_2(&temp1, &temp3);
|
|
Key_Schedule[5]=temp3;
|
|
temp2 = _mm_aeskeygenassist_si128 (temp3,0x04);
|
|
KEY_256_ASSIST_1(&temp1, &temp2);
|
|
Key_Schedule[6]=temp1;
|
|
KEY_256_ASSIST_2(&temp1, &temp3);
|
|
Key_Schedule[7]=temp3;
|
|
temp2 = _mm_aeskeygenassist_si128 (temp3,0x08);
|
|
KEY_256_ASSIST_1(&temp1, &temp2);
|
|
Key_Schedule[8]=temp1;
|
|
KEY_256_ASSIST_2(&temp1, &temp3);
|
|
Key_Schedule[9]=temp3;
|
|
temp2 = _mm_aeskeygenassist_si128 (temp3,0x10);
|
|
KEY_256_ASSIST_1(&temp1, &temp2);
|
|
Key_Schedule[10]=temp1;
|
|
KEY_256_ASSIST_2(&temp1, &temp3);
|
|
Key_Schedule[11]=temp3;
|
|
temp2 = _mm_aeskeygenassist_si128 (temp3,0x20);
|
|
KEY_256_ASSIST_1(&temp1, &temp2);
|
|
Key_Schedule[12]=temp1;
|
|
KEY_256_ASSIST_2(&temp1, &temp3);
|
|
Key_Schedule[13]=temp3;
|
|
temp2 = _mm_aeskeygenassist_si128 (temp3,0x40);
|
|
KEY_256_ASSIST_1(&temp1, &temp2);
|
|
Key_Schedule[14]=temp1;
|
|
}
|
|
|
|
}
|
|
|
|
#endif // AESNIKEYEXP_H
|