From 0ddf76d59a415f2d65263296e48cefe4a6694383 Mon Sep 17 00:00:00 2001
From: Oleg Derevenetz <oleg-derevenetz@yandex.ru>
Date: Wed, 9 Sep 2020 22:39:11 +0300
Subject: [PATCH] Minor improvements (#33)

* 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.
---
 README.md                                  |   4 +-
 aesni/{aesni-enc-cbc.c => aesni-enc-cbc.h} | 123 +++----
 aesni/{aesni-enc-ecb.c => aesni-enc-ecb.h} | 119 ++++---
 aesni/{aesni-key-exp.c => aesni-key-exp.h} | 395 +++++++++++----------
 qaesencryption.cpp                         |  41 ++-
 qaesencryption.h                           |  18 +-
 qaesencryption.pro                         |  11 +-
 7 files changed, 361 insertions(+), 350 deletions(-)
 rename aesni/{aesni-enc-cbc.c => aesni-enc-cbc.h} (93%)
 mode change 100755 => 100644
 rename aesni/{aesni-enc-ecb.c => aesni-enc-ecb.h} (94%)
 mode change 100755 => 100644
 rename aesni/{aesni-key-exp.c => aesni-key-exp.h} (92%)
 mode change 100755 => 100644

diff --git a/README.md b/README.md
index 799114c..0a6d05a 100644
--- a/README.md
+++ b/README.md
@@ -10,12 +10,12 @@ AES-NI support for all key sizes - ECB, CBC modes
 // Encode of rawText with key
 // iv is used in CBC mode
 // return the encrypted byte array
-QByteArray encode(const QByteArray rawText, const QByteArray key, const QByteArray iv = NULL);
+QByteArray encode(const QByteArray rawText, const QByteArray key, const QByteArray iv = QByteArray());
 
 // Decode of rawText with key
 // iv is used in CBC mode
 // return the decrypted byte array
-QByteArray decode(const QByteArray rawText, const QByteArray key, const QByteArray iv = NULL);
+QByteArray decode(const QByteArray rawText, const QByteArray key, const QByteArray iv = QByteArray());
 
 // Key expansion in Rijndael schedule
 // return the new expanded key as byte array
diff --git a/aesni/aesni-enc-cbc.c b/aesni/aesni-enc-cbc.h
old mode 100755
new mode 100644
similarity index 93%
rename from aesni/aesni-enc-cbc.c
rename to aesni/aesni-enc-cbc.h
index 5efceb1..4328c66
--- a/aesni/aesni-enc-cbc.c
+++ b/aesni/aesni-enc-cbc.h
@@ -1,60 +1,63 @@
-#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
+#ifndef AESNIENCCBC_H
+#define AESNIENCCBC_H
+
+#include <wmmintrin.h>
+
+namespace {
+
+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);
+    }
+}
+
+#if 0
+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;
+    }
+}
+#endif
+
+}
+
+#endif // AESNIENCCBC_H
diff --git a/aesni/aesni-enc-ecb.c b/aesni/aesni-enc-ecb.h
old mode 100755
new mode 100644
similarity index 94%
rename from aesni/aesni-enc-ecb.c
rename to aesni/aesni-enc-ecb.h
index e07e0a9..42cb1bb
--- a/aesni/aesni-enc-ecb.c
+++ b/aesni/aesni-enc-ecb.h
@@ -1,58 +1,61 @@
-#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
+#ifndef AESNIENCECB_H
+#define AESNIENCECB_H
+
+#include <wmmintrin.h>
+
+namespace {
+
+/* 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);
+        }
+}
+
+#if 0
+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);
+    }
+}
+#endif
+
+}
+
+#endif // AESNIENCECB_H
diff --git a/aesni/aesni-key-exp.c b/aesni/aesni-key-exp.h
old mode 100755
new mode 100644
similarity index 92%
rename from aesni/aesni-key-exp.c
rename to aesni/aesni-key-exp.h
index e150b61..4816cca
--- a/aesni/aesni-key-exp.c
+++ b/aesni/aesni-key-exp.h
@@ -1,196 +1,199 @@
-#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
+#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
diff --git a/qaesencryption.cpp b/qaesencryption.cpp
index 4a3cd56..9103fb8 100644
--- a/qaesencryption.cpp
+++ b/qaesencryption.cpp
@@ -3,9 +3,9 @@
 #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"
+#include "aesni/aesni-key-exp.h"
+#include "aesni/aesni-enc-ecb.h"
+#include "aesni/aesni-enc-cbc.h"
 #endif
 
 /*
@@ -61,7 +61,7 @@ QByteArray QAESEncryption::RemovePadding(const QByteArray &rawText, QAESEncrypti
         }
 
         // And check if it's the byte for marking padding
-        if (ret.at(marker_index) == static_cast<char>(0x80))
+        if (ret.at(marker_index) == '\x80')
         {
             ret.truncate(marker_index);
         }
@@ -78,30 +78,33 @@ QByteArray QAESEncryption::RemovePadding(const QByteArray &rawText, QAESEncrypti
  * */
 
 /*
- * Inline Functions
+ * Local Functions
  * */
 
-inline quint8 xTime(quint8 x){
-  return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
+namespace {
+
+quint8 xTime(quint8 x)
+{
+    return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
 }
 
-inline quint8 multiply(quint8 x, quint8 y){
-  return (((y & 1) * x) ^ ((y>>1 & 1) * xTime(x)) ^ ((y>>2 & 1) * xTime(xTime(x))) ^ ((y>>3 & 1)
+quint8 multiply(quint8 x, quint8 y)
+{
+    return (((y & 1) * x) ^ ((y>>1 & 1) * xTime(x)) ^ ((y>>2 & 1) * xTime(xTime(x))) ^ ((y>>3 & 1)
             * xTime(xTime(xTime(x)))) ^ ((y>>4 & 1) * xTime(xTime(xTime(xTime(x))))));
 }
 
-/*
- * End Inline functions
- * */
+}
 
+/*
+ * End Local functions
+ * */
 
 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_aesNIAvailable(false), m_state(nullptr)
 {
-    m_state = NULL;
-
 #ifdef USE_INTEL_AES_IF_AVAILABLE
     m_aesNIAvailable = check_aesni_support();
 #endif
@@ -158,7 +161,7 @@ QByteArray QAESEncryption::getPadding(int currSize, int alignment)
         break;
     case Padding::ISO:
         if (size > 0)
-            return QByteArray (size - 1, 0x00).prepend(0x80);
+            return QByteArray (size - 1, 0x00).prepend('\x80');
         break;
     default:
         return QByteArray(size, 0x00);
@@ -266,7 +269,7 @@ QByteArray QAESEncryption::expandKey(const QByteArray &key)
 
 // This function adds the round key to state.
 // The round key is added to the state by an XOR function.
-void QAESEncryption::addRoundKey(const quint8 round, const QByteArray expKey)
+void QAESEncryption::addRoundKey(const quint8 round, const QByteArray &expKey)
 {
   QByteArray::iterator it = m_state->begin();
   for(int i=0; i < 16; ++i)
@@ -480,7 +483,7 @@ QByteArray QAESEncryption::printArray(uchar* arr, int size)
 
 QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv)
 {
-    if (m_mode >= CBC && (iv.isNull() || iv.size() != m_blocklen))
+    if (m_mode >= CBC && (iv.isEmpty() || iv.size() != m_blocklen))
        return QByteArray();
 
     QByteArray expandedKey = expandKey(key);
@@ -570,7 +573,7 @@ QByteArray QAESEncryption::encode(const QByteArray &rawText, const QByteArray &k
 
 QByteArray QAESEncryption::decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv)
 {
-    if (m_mode >= CBC && (iv.isNull() || iv.size() != m_blocklen))
+    if (m_mode >= CBC && (iv.isEmpty() || iv.size() != m_blocklen))
        return QByteArray();
 
     QByteArray ret;
diff --git a/qaesencryption.h b/qaesencryption.h
index 4f3165e..45ba570 100644
--- a/qaesencryption.h
+++ b/qaesencryption.h
@@ -34,17 +34,17 @@ public:
     };
 
     static QByteArray Crypt(QAESEncryption::Aes level, QAESEncryption::Mode mode, const QByteArray &rawText, const QByteArray &key,
-                            const QByteArray &iv = NULL, QAESEncryption::Padding padding = QAESEncryption::ISO);
+                            const QByteArray &iv = QByteArray(), QAESEncryption::Padding padding = QAESEncryption::ISO);
     static QByteArray Decrypt(QAESEncryption::Aes level, QAESEncryption::Mode mode, const QByteArray &rawText, const QByteArray &key,
-                              const QByteArray &iv = NULL, QAESEncryption::Padding padding = QAESEncryption::ISO);
+                              const QByteArray &iv = QByteArray(), QAESEncryption::Padding padding = QAESEncryption::ISO);
     static QByteArray ExpandKey(QAESEncryption::Aes level, QAESEncryption::Mode mode, const QByteArray &key);
-    static QByteArray RemovePadding(const QByteArray &rawText, QAESEncryption::Padding padding);
+    static QByteArray RemovePadding(const QByteArray &rawText, QAESEncryption::Padding padding = QAESEncryption::ISO);
 
     QAESEncryption(QAESEncryption::Aes level, QAESEncryption::Mode mode,
                    QAESEncryption::Padding padding = QAESEncryption::ISO);
 
-    QByteArray encode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv = NULL);
-    QByteArray decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv = NULL);
+    QByteArray encode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv = QByteArray());
+    QByteArray decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv = QByteArray());
     QByteArray removePadding(const QByteArray &rawText);
     QByteArray expandKey(const QByteArray &key);
 
@@ -90,7 +90,7 @@ private:
     quint8 getSBoxValue(quint8 num){return sbox[num];}
     quint8 getSBoxInvert(quint8 num){return rsbox[num];}
 
-    void addRoundKey(const quint8 round, const QByteArray expKey);
+    void addRoundKey(const quint8 round, const QByteArray &expKey);
     void subBytes();
     void shiftRows();
     void mixColumns();
@@ -98,9 +98,9 @@ private:
     void invSubBytes();
     void invShiftRows();
     QByteArray getPadding(int currSize, int alignment);
-    QByteArray cipher(const QByteArray &expKey, const QByteArray &plainText);
-    QByteArray invCipher(const QByteArray &expKey, const QByteArray &plainText);
-    QByteArray byteXor(const QByteArray &in, const QByteArray &iv);
+    QByteArray cipher(const QByteArray &expKey, const QByteArray &in);
+    QByteArray invCipher(const QByteArray &expKey, const QByteArray &in);
+    QByteArray byteXor(const QByteArray &a, const QByteArray &b);
 
     const quint8 sbox[256] = {
       //0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
diff --git a/qaesencryption.pro b/qaesencryption.pro
index d5d2ed1..16a1151 100644
--- a/qaesencryption.pro
+++ b/qaesencryption.pro
@@ -25,18 +25,17 @@ QMAKE_CXXFLAGS += -maes
 
 HEADERS += \
     qaesencryption.h \
-    unit_test/aestest.h \
+    aesni/aesni-key-exp.h \
+    aesni/aesni-enc-ecb.h \
+    aesni/aesni-enc-cbc.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
+    unit_test/aestest.cpp
 
 DISTFILES += \
     unit_test/longText.txt
 
 RESOURCES += \
     res.qrc
-