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:
Matteo B 2020-05-15 16:45:35 -07:00 committed by GitHub
parent f5ef736a7f
commit 78efdb4f3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 512 additions and 73 deletions

60
aesni/aesni-enc-cbc.c Executable file
View 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
View 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
View 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

View File

@ -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;

View File

@ -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)

View File

@ -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{

View File

@ -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

View File

@ -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]);
}
}