mirror of
https://github.com/QuasarApp/Qt-AES.git
synced 2025-04-26 21:54:32 +00:00
Adding ECB and CBC modes via AES-NI (#32)
Added ECB and CBC modes via AES-NI, only is enabled and supported
This commit is contained in:
parent
f5ef736a7f
commit
78efdb4f3f
60
aesni/aesni-enc-cbc.c
Executable file
60
aesni/aesni-enc-cbc.c
Executable file
@ -0,0 +1,60 @@
|
||||
#include <wmmintrin.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void AES_CBC_encrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
unsigned char ivec[16],
|
||||
unsigned long length,
|
||||
const char *key,
|
||||
int number_of_rounds)
|
||||
{
|
||||
__m128i feedback,data;
|
||||
unsigned long i;
|
||||
int j;
|
||||
if (length%16)
|
||||
length = length/16+1;
|
||||
else length /=16;
|
||||
feedback=_mm_loadu_si128 ((__m128i*)ivec);
|
||||
for(i=0; i < length; i++) {
|
||||
data = _mm_loadu_si128 (&((__m128i*)in)[i]);
|
||||
feedback = _mm_xor_si128 (data,feedback);
|
||||
feedback = _mm_xor_si128 (feedback,((__m128i*)key)[0]);
|
||||
for(j=1; j <number_of_rounds; j++)
|
||||
feedback = _mm_aesenc_si128 (feedback,((__m128i*)key)[j]);
|
||||
feedback = _mm_aesenclast_si128 (feedback,((__m128i*)key)[j]); _mm_storeu_si128 (&((__m128i*)out)[i],feedback);
|
||||
}
|
||||
}
|
||||
|
||||
void AES_CBC_decrypt(const unsigned char *in,
|
||||
unsigned char *out,
|
||||
unsigned char ivec[16],
|
||||
unsigned long length,
|
||||
const char *key,
|
||||
int number_of_rounds)
|
||||
{
|
||||
__m128i data,feedback,last_in;
|
||||
unsigned long i;
|
||||
int j;
|
||||
if (length%16)
|
||||
length = length/16+1;
|
||||
else length /=16;
|
||||
feedback=_mm_loadu_si128 ((__m128i*)ivec);
|
||||
for(i=0; i < length; i++) {
|
||||
last_in=_mm_loadu_si128 (&((__m128i*)in)[i]);
|
||||
data = _mm_xor_si128 (last_in,((__m128i*)key)[0]);
|
||||
for(j=1; j <number_of_rounds; j++) {
|
||||
data = _mm_aesdec_si128 (data,((__m128i*)key)[j]);
|
||||
}
|
||||
data = _mm_aesdeclast_si128 (data,((__m128i*)key)[j]);
|
||||
data = _mm_xor_si128 (data,feedback);
|
||||
_mm_storeu_si128 (&((__m128i*)out)[i],data);
|
||||
feedback=last_in;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
58
aesni/aesni-enc-ecb.c
Executable file
58
aesni/aesni-enc-ecb.c
Executable file
@ -0,0 +1,58 @@
|
||||
#include <wmmintrin.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Note – the length of the output buffer is assumed to be a multiple of 16 bytes */
|
||||
void AES_ECB_encrypt(const unsigned char *in, //pointer to the PLAINTEXT
|
||||
unsigned char *out, //pointer to the CIPHERTEXT buffer
|
||||
unsigned long length, //text length in bytes
|
||||
const char *key, //pointer to the expanded key schedule
|
||||
int number_of_rounds) //number of AES rounds 10,12 or 14
|
||||
{
|
||||
__m128i tmp;
|
||||
unsigned long i;
|
||||
int j;
|
||||
if(length%16)
|
||||
length = length/16+1;
|
||||
else
|
||||
length = length/16;
|
||||
for(i = 0; i < length; i++) {
|
||||
tmp = _mm_loadu_si128 (&((__m128i*)in)[i]);
|
||||
tmp = _mm_xor_si128 (tmp,((__m128i*)key)[0]);
|
||||
for(j=1; j <number_of_rounds; j++) {
|
||||
tmp = _mm_aesenc_si128 (tmp, ((__m128i*)key)[j]);
|
||||
}
|
||||
tmp = _mm_aesenclast_si128 (tmp,((__m128i*)key)[j]);
|
||||
_mm_storeu_si128 (&((__m128i*)out)[i],tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void AES_ECB_decrypt(const unsigned char *in, //pointer to the CIPHERTEXT
|
||||
unsigned char *out, //pointer to the DECRYPTED TEXT buffer
|
||||
unsigned long length, //text length in bytes
|
||||
const char *key, //pointer to the expanded key schedule
|
||||
int number_of_rounds) //number of AES rounds 10,12 or 14
|
||||
{
|
||||
__m128i tmp;
|
||||
unsigned long i;
|
||||
int j;
|
||||
if(length%16)
|
||||
length = length/16+1;
|
||||
else
|
||||
length = length/16;
|
||||
for(i = 0; i < length; i++) {
|
||||
tmp = _mm_loadu_si128 (&((__m128i*)in)[i]);
|
||||
tmp = _mm_xor_si128 (tmp,((__m128i*)key)[0]);
|
||||
for(j = 1; j < number_of_rounds; j++) {
|
||||
tmp = _mm_aesdec_si128 (tmp,((__m128i*)key)[j]);
|
||||
}
|
||||
tmp = _mm_aesdeclast_si128 (tmp,((__m128i*)key)[j]);
|
||||
_mm_storeu_si128 (&((__m128i*)out)[i],tmp);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
196
aesni/aesni-key-exp.c
Executable file
196
aesni/aesni-key-exp.c
Executable file
@ -0,0 +1,196 @@
|
||||
#include <wmmintrin.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define cpuid(func, ax, bx, cx, dx)\
|
||||
__asm__ __volatile__("cpuid": "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
|
||||
|
||||
inline bool check_aesni_support()
|
||||
{
|
||||
unsigned int a,b,c,d;
|
||||
cpuid(1, a,b,c,d);
|
||||
return (c & 0x2000000);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
inline 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;
|
||||
}
|
||||
|
||||
inline 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);
|
||||
}
|
||||
|
||||
inline 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;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
4
main.cpp
4
main.cpp
@ -1,11 +1,13 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QTest>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "unit_test/aestest.h"
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
|
||||
AesTest test1;
|
||||
QTest::qExec(&test1);
|
||||
return 0;
|
||||
|
@ -1,4 +1,12 @@
|
||||
#include "qaesencryption.h"
|
||||
#include <QDebug>
|
||||
#include <QVector>
|
||||
|
||||
#ifdef USE_INTEL_AES_IF_AVAILABLE
|
||||
#include "aesni/aesni-key-exp.c"
|
||||
#include "aesni/aesni-enc-ecb.c"
|
||||
#include "aesni/aesni-enc-cbc.c"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Static Functions
|
||||
@ -90,9 +98,14 @@ inline quint8 multiply(quint8 x, quint8 y){
|
||||
QAESEncryption::QAESEncryption(Aes level, Mode mode,
|
||||
Padding padding)
|
||||
: m_nb(4), m_blocklen(16), m_level(level), m_mode(mode), m_padding(padding)
|
||||
, m_aesNIAvailable(false)
|
||||
{
|
||||
m_state = NULL;
|
||||
|
||||
#ifdef USE_INTEL_AES_IF_AVAILABLE
|
||||
m_aesNIAvailable = check_aesni_support();
|
||||
#endif
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case AES_128: {
|
||||
@ -156,56 +169,99 @@ QByteArray QAESEncryption::getPadding(int currSize, int alignment)
|
||||
|
||||
QByteArray QAESEncryption::expandKey(const QByteArray &key)
|
||||
{
|
||||
int i, k;
|
||||
quint8 tempa[4]; // Used for the column/row operations
|
||||
QByteArray roundKey(key);
|
||||
|
||||
// The first round key is the key itself.
|
||||
// ...
|
||||
#ifdef USE_INTEL_AES_IF_AVAILABLE
|
||||
if (true){
|
||||
switch(m_level) {
|
||||
case AES_128: {
|
||||
AES128 aes128;
|
||||
quint8 ret[aes128.expandedKey];
|
||||
memset(ret, 0x00, sizeof(ret));
|
||||
quint8 uchar_key[key.size()];
|
||||
memcpy(uchar_key, key.data(), key.size());
|
||||
AES_128_Key_Expansion(uchar_key, ret);
|
||||
return QByteArray((char*) ret, aes128.expandedKey);
|
||||
}
|
||||
break;
|
||||
case AES_192: {
|
||||
AES192 aes192;
|
||||
quint8 ret[aes192.expandedKey];
|
||||
memset(ret, 0x00, sizeof(ret));
|
||||
quint8 uchar_key[key.size()];
|
||||
memcpy(uchar_key, key.data(), key.size());
|
||||
|
||||
// All other round keys are found from the previous round keys.
|
||||
//i == Nk
|
||||
for(i = m_nk; i < m_nb * (m_nr + 1); i++)
|
||||
AES_192_Key_Expansion(uchar_key, ret);
|
||||
return QByteArray((char*) ret, aes192.expandedKey);
|
||||
}
|
||||
break;
|
||||
case AES_256: {
|
||||
AES256 aes256;
|
||||
quint8 ret[aes256.expandedKey];
|
||||
memset(ret, 0x00, sizeof(ret));
|
||||
quint8 uchar_key[key.size()];
|
||||
memcpy(uchar_key, key.data(), key.size());
|
||||
|
||||
AES_256_Key_Expansion(uchar_key, ret);
|
||||
return QByteArray((char*) ret, aes256.expandedKey);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return QByteArray();
|
||||
break;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
tempa[0] = (quint8) roundKey.at((i-1) * 4 + 0);
|
||||
tempa[1] = (quint8) roundKey.at((i-1) * 4 + 1);
|
||||
tempa[2] = (quint8) roundKey.at((i-1) * 4 + 2);
|
||||
tempa[3] = (quint8) roundKey.at((i-1) * 4 + 3);
|
||||
|
||||
if (i % m_nk == 0)
|
||||
{
|
||||
// This function shifts the 4 bytes in a word to the left once.
|
||||
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
|
||||
int i, k;
|
||||
quint8 tempa[4]; // Used for the column/row operations
|
||||
QByteArray roundKey(key); // The first round key is the key itself.
|
||||
|
||||
// Function RotWord()
|
||||
k = tempa[0];
|
||||
tempa[0] = tempa[1];
|
||||
tempa[1] = tempa[2];
|
||||
tempa[2] = tempa[3];
|
||||
tempa[3] = k;
|
||||
// All other round keys are found from the previous round keys.
|
||||
//i == Nk
|
||||
for(i = m_nk; i < m_nb * (m_nr + 1); i++)
|
||||
{
|
||||
tempa[0] = (quint8) roundKey.at((i-1) * 4 + 0);
|
||||
tempa[1] = (quint8) roundKey.at((i-1) * 4 + 1);
|
||||
tempa[2] = (quint8) roundKey.at((i-1) * 4 + 2);
|
||||
tempa[3] = (quint8) roundKey.at((i-1) * 4 + 3);
|
||||
|
||||
// Function Subword()
|
||||
tempa[0] = getSBoxValue(tempa[0]);
|
||||
tempa[1] = getSBoxValue(tempa[1]);
|
||||
tempa[2] = getSBoxValue(tempa[2]);
|
||||
tempa[3] = getSBoxValue(tempa[3]);
|
||||
if (i % m_nk == 0)
|
||||
{
|
||||
// This function shifts the 4 bytes in a word to the left once.
|
||||
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
|
||||
|
||||
tempa[0] = tempa[0] ^ Rcon[i/m_nk];
|
||||
}
|
||||
if (m_level == AES_256 && i % m_nk == 4)
|
||||
{
|
||||
// Function Subword()
|
||||
tempa[0] = getSBoxValue(tempa[0]);
|
||||
tempa[1] = getSBoxValue(tempa[1]);
|
||||
tempa[2] = getSBoxValue(tempa[2]);
|
||||
tempa[3] = getSBoxValue(tempa[3]);
|
||||
}
|
||||
roundKey.insert(i * 4 + 0, (quint8) roundKey.at((i - m_nk) * 4 + 0) ^ tempa[0]);
|
||||
roundKey.insert(i * 4 + 1, (quint8) roundKey.at((i - m_nk) * 4 + 1) ^ tempa[1]);
|
||||
roundKey.insert(i * 4 + 2, (quint8) roundKey.at((i - m_nk) * 4 + 2) ^ tempa[2]);
|
||||
roundKey.insert(i * 4 + 3, (quint8) roundKey.at((i - m_nk) * 4 + 3) ^ tempa[3]);
|
||||
// Function RotWord()
|
||||
k = tempa[0];
|
||||
tempa[0] = tempa[1];
|
||||
tempa[1] = tempa[2];
|
||||
tempa[2] = tempa[3];
|
||||
tempa[3] = k;
|
||||
|
||||
// Function Subword()
|
||||
tempa[0] = getSBoxValue(tempa[0]);
|
||||
tempa[1] = getSBoxValue(tempa[1]);
|
||||
tempa[2] = getSBoxValue(tempa[2]);
|
||||
tempa[3] = getSBoxValue(tempa[3]);
|
||||
|
||||
tempa[0] = tempa[0] ^ Rcon[i/m_nk];
|
||||
}
|
||||
|
||||
if (m_level == AES_256 && i % m_nk == 4)
|
||||
{
|
||||
// Function Subword()
|
||||
tempa[0] = getSBoxValue(tempa[0]);
|
||||
tempa[1] = getSBoxValue(tempa[1]);
|
||||
tempa[2] = getSBoxValue(tempa[2]);
|
||||
tempa[3] = getSBoxValue(tempa[3]);
|
||||
}
|
||||
roundKey.insert(i * 4 + 0, (quint8) roundKey.at((i - m_nk) * 4 + 0) ^ tempa[0]);
|
||||
roundKey.insert(i * 4 + 1, (quint8) roundKey.at((i - m_nk) * 4 + 1) ^ tempa[1]);
|
||||
roundKey.insert(i * 4 + 2, (quint8) roundKey.at((i - m_nk) * 4 + 2) ^ tempa[2]);
|
||||
roundKey.insert(i * 4 + 3, (quint8) roundKey.at((i - m_nk) * 4 + 3) ^ tempa[3]);
|
||||
}
|
||||
return roundKey;
|
||||
}
|
||||
return roundKey;
|
||||
}
|
||||
|
||||
// This function adds the round key to state.
|
||||
@ -413,12 +469,20 @@ QByteArray QAESEncryption::invCipher(const QByteArray &expKey, const QByteArray
|
||||
return output;
|
||||
}
|
||||
|
||||
QByteArray QAESEncryption::printArray(uchar* arr, int size)
|
||||
{
|
||||
QByteArray print("");
|
||||
for(int i=0; i<size; i++)
|
||||
print.append(arr[i]);
|
||||
|
||||
return print.toHex();
|
||||
}
|
||||
|
||||
QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv)
|
||||
{
|
||||
if (m_mode >= CBC && (iv.isNull() || iv.size() != m_blocklen))
|
||||
return QByteArray();
|
||||
|
||||
QByteArray ret;
|
||||
QByteArray expandedKey = expandKey(key);
|
||||
QByteArray alignedText(rawText);
|
||||
|
||||
@ -427,40 +491,81 @@ QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &k
|
||||
|
||||
switch(m_mode)
|
||||
{
|
||||
case ECB:
|
||||
case ECB: {
|
||||
#ifdef USE_INTEL_AES_IF_AVAILABLE
|
||||
if (m_aesNIAvailable){
|
||||
unsigned char in[alignedText.size()];
|
||||
memcpy(in, alignedText.data(), alignedText.size());
|
||||
unsigned char out[alignedText.size()];
|
||||
memcpy(out, alignedText.data(), alignedText.size());
|
||||
char expKey[expandedKey.size()];
|
||||
memcpy(expKey, expandedKey.data(), expandedKey.size());
|
||||
AES_ECB_encrypt(in, out, alignedText.size(),
|
||||
expKey, m_nr);
|
||||
return QByteArray((char*)out, alignedText.size());
|
||||
}
|
||||
#endif
|
||||
QByteArray ret;
|
||||
for(int i=0; i < alignedText.size(); i+= m_blocklen)
|
||||
ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen)));
|
||||
break;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case CBC: {
|
||||
QByteArray ivTemp(iv);
|
||||
for(int i=0; i < alignedText.size(); i+= m_blocklen) {
|
||||
alignedText.replace(i, m_blocklen, byteXor(alignedText.mid(i, m_blocklen),ivTemp));
|
||||
ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen)));
|
||||
ivTemp = ret.mid(i, m_blocklen);
|
||||
}
|
||||
#ifdef USE_INTEL_AES_IF_AVAILABLE
|
||||
if (m_aesNIAvailable){
|
||||
quint8 in[alignedText.size()];
|
||||
memcpy(in, alignedText.constData(), alignedText.size());
|
||||
quint8 ivec[iv.size()];
|
||||
memcpy(ivec, iv.data(), iv.size());
|
||||
char out[alignedText.size()];
|
||||
memset(out, 0x00, alignedText.size());
|
||||
char expKey[expandedKey.size()];
|
||||
memcpy(expKey, expandedKey.data(), expandedKey.size());
|
||||
AES_CBC_encrypt(in,
|
||||
(unsigned char*) out,
|
||||
ivec,
|
||||
alignedText.size(),
|
||||
expKey,
|
||||
m_nr);
|
||||
return QByteArray(out, alignedText.size());
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
QByteArray ret;
|
||||
QByteArray ivTemp(iv);
|
||||
for(int i=0; i < alignedText.size(); i+= m_blocklen) {
|
||||
alignedText.replace(i, m_blocklen, byteXor(alignedText.mid(i, m_blocklen),ivTemp));
|
||||
ret.append(cipher(expandedKey, alignedText.mid(i, m_blocklen)));
|
||||
ivTemp = ret.mid(i, m_blocklen);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case CFB: {
|
||||
ret.append(byteXor(alignedText.left(m_blocklen), cipher(expandedKey, iv)));
|
||||
for(int i=0; i < alignedText.size(); i+= m_blocklen) {
|
||||
if (i+m_blocklen < alignedText.size())
|
||||
ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen),
|
||||
cipher(expandedKey, ret.mid(i, m_blocklen))));
|
||||
}
|
||||
QByteArray ret;
|
||||
ret.append(byteXor(alignedText.left(m_blocklen), cipher(expandedKey, iv)));
|
||||
for(int i=0; i < alignedText.size(); i+= m_blocklen) {
|
||||
if (i+m_blocklen < alignedText.size())
|
||||
ret.append(byteXor(alignedText.mid(i+m_blocklen, m_blocklen),
|
||||
cipher(expandedKey, ret.mid(i, m_blocklen))));
|
||||
}
|
||||
break;
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case OFB: {
|
||||
QByteArray ofbTemp;
|
||||
ofbTemp.append(cipher(expandedKey, iv));
|
||||
for (int i=m_blocklen; i < alignedText.size(); i += m_blocklen){
|
||||
ofbTemp.append(cipher(expandedKey, ofbTemp.right(m_blocklen)));
|
||||
}
|
||||
ret.append(byteXor(alignedText, ofbTemp));
|
||||
QByteArray ret;
|
||||
QByteArray ofbTemp;
|
||||
ofbTemp.append(cipher(expandedKey, iv));
|
||||
for (int i=m_blocklen; i < alignedText.size(); i += m_blocklen){
|
||||
ofbTemp.append(cipher(expandedKey, ofbTemp.right(m_blocklen)));
|
||||
}
|
||||
break;
|
||||
ret.append(byteXor(alignedText, ofbTemp));
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return ret;
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray QAESEncryption::decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv)
|
||||
|
@ -4,6 +4,12 @@
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
|
||||
#ifdef __linux__
|
||||
#ifndef __LP64__
|
||||
#define do_rdtsc _do_rdtsc
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class QAESEncryption : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -42,6 +48,7 @@ public:
|
||||
QByteArray removePadding(const QByteArray &rawText);
|
||||
QByteArray expandKey(const QByteArray &key);
|
||||
|
||||
QByteArray printArray(uchar *arr, int size);
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
@ -56,6 +63,7 @@ private:
|
||||
int m_nr;
|
||||
int m_expandedKey;
|
||||
int m_padding;
|
||||
bool m_aesNIAvailable;
|
||||
QByteArray* m_state;
|
||||
|
||||
struct AES256{
|
||||
|
@ -9,16 +9,15 @@ CONFIG -= app_bundle
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
SOURCES += main.cpp \
|
||||
qaesencryption.cpp \
|
||||
unit_test/aestest.cpp
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which as been marked deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
DEFINES += USE_INTEL_AES_IF_AVAILABLE
|
||||
QMAKE_CXXFLAGS += -maes
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
@ -26,7 +25,14 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
HEADERS += \
|
||||
qaesencryption.h \
|
||||
unit_test/aestest.h
|
||||
unit_test/aestest.h \
|
||||
|
||||
SOURCES += main.cpp \
|
||||
qaesencryption.cpp \
|
||||
unit_test/aestest.cpp \
|
||||
aesni/aesni-key-exp.c \
|
||||
aesni/aesni-enc-ecb.c \
|
||||
aesni/aesni-enc-cbc.c
|
||||
|
||||
DISTFILES += \
|
||||
unit_test/longText.txt
|
||||
|
@ -8,6 +8,9 @@
|
||||
|
||||
void AesTest::initTestCase()
|
||||
{
|
||||
#ifdef USE_INTEL_AES_IF_AVAILABLE
|
||||
qDebug() << "AESNI Enabled";
|
||||
#endif
|
||||
quint8 key_16[16] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
|
||||
for (int i=0; i<16; i++)
|
||||
key16.append(key_16[i]);
|
||||
@ -54,6 +57,7 @@ void AesTest::initTestCase()
|
||||
inCBC128.append(text_cbc[i]);
|
||||
outCBC128.append(output_cbc[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user