diff options
Diffstat (limited to '')
-rw-r--r-- | src/ui/aes/qaesencryption.cpp | 626 |
1 files changed, 0 insertions, 626 deletions
diff --git a/src/ui/aes/qaesencryption.cpp b/src/ui/aes/qaesencryption.cpp deleted file mode 100644 index 9103fb8e..00000000 --- a/src/ui/aes/qaesencryption.cpp +++ /dev/null @@ -1,626 +0,0 @@ -#include "qaesencryption.h" -#include <QDebug> -#include <QVector> - -#ifdef USE_INTEL_AES_IF_AVAILABLE -#include "aesni/aesni-key-exp.h" -#include "aesni/aesni-enc-ecb.h" -#include "aesni/aesni-enc-cbc.h" -#endif - -/* - * Static Functions - * */ -QByteArray QAESEncryption::Crypt(QAESEncryption::Aes level, QAESEncryption::Mode mode, const QByteArray &rawText, - const QByteArray &key, const QByteArray &iv, QAESEncryption::Padding padding) -{ - return QAESEncryption(level, mode, padding).encode(rawText, key, iv); -} - -QByteArray QAESEncryption::Decrypt(QAESEncryption::Aes level, QAESEncryption::Mode mode, const QByteArray &rawText, - const QByteArray &key, const QByteArray &iv, QAESEncryption::Padding padding) -{ - return QAESEncryption(level, mode, padding).decode(rawText, key, iv); -} - -QByteArray QAESEncryption::ExpandKey(QAESEncryption::Aes level, QAESEncryption::Mode mode, const QByteArray &key) -{ - return QAESEncryption(level, mode).expandKey(key); -} - -QByteArray QAESEncryption::RemovePadding(const QByteArray &rawText, QAESEncryption::Padding padding) -{ - if (rawText.isEmpty()) - return rawText; - - QByteArray ret(rawText); - switch (padding) - { - case Padding::ZERO: - //Works only if the last byte of the decoded array is not zero - while (ret.at(ret.length()-1) == 0x00) - ret.remove(ret.length()-1, 1); - break; - case Padding::PKCS7: -#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - ret.remove(ret.length() - ret.back(), ret.back()); -#else - ret.remove(ret.length() - ret.at(ret.length() - 1), ret.at(ret.length() - 1)); -#endif - break; - case Padding::ISO: - { - // Find the last byte which is not zero - int marker_index = ret.length() - 1; - for (; marker_index >= 0; --marker_index) - { - if (ret.at(marker_index) != 0x00) - { - break; - } - } - - // And check if it's the byte for marking padding - if (ret.at(marker_index) == '\x80') - { - ret.truncate(marker_index); - } - break; - } - default: - //do nothing - break; - } - return ret; -} -/* - * End Static function declarations - * */ - -/* - * Local Functions - * */ - -namespace { - -quint8 xTime(quint8 x) -{ - return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); -} - -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 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_state(nullptr) -{ -#ifdef USE_INTEL_AES_IF_AVAILABLE - m_aesNIAvailable = check_aesni_support(); -#endif - - switch (level) - { - case AES_128: { - AES128 aes; - m_nk = aes.nk; - m_keyLen = aes.keylen; - m_nr = aes.nr; - m_expandedKey = aes.expandedKey; - } - break; - case AES_192: { - AES192 aes; - m_nk = aes.nk; - m_keyLen = aes.keylen; - m_nr = aes.nr; - m_expandedKey = aes.expandedKey; - } - break; - case AES_256: { - AES256 aes; - m_nk = aes.nk; - m_keyLen = aes.keylen; - m_nr = aes.nr; - m_expandedKey = aes.expandedKey; - } - break; - default: { - AES128 aes; - m_nk = aes.nk; - m_keyLen = aes.keylen; - m_nr = aes.nr; - m_expandedKey = aes.expandedKey; - } - break; - } - -} -QByteArray QAESEncryption::getPadding(int currSize, int alignment) -{ - int size = (alignment - currSize % alignment) % alignment; - switch(m_padding) - { - case Padding::ZERO: - return QByteArray(size, 0x00); - break; - case Padding::PKCS7: - if (size == 0) - size = alignment; - return QByteArray(size, size); - break; - case Padding::ISO: - if (size > 0) - return QByteArray (size - 1, 0x00).prepend('\x80'); - break; - default: - return QByteArray(size, 0x00); - break; - } - return QByteArray(); -} - -QByteArray QAESEncryption::expandKey(const QByteArray &key) -{ - -#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()); - - 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 - { - - int i, k; - quint8 tempa[4]; // Used for the column/row operations - QByteArray roundKey(key); // The first round key is the key itself. - - // 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); - - 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] - - // 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; - } -} - -// 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) -{ - QByteArray::iterator it = m_state->begin(); - for(int i=0; i < 16; ++i) - it[i] = (quint8) it[i] ^ (quint8) expKey.at(round * m_nb * 4 + (i/4) * m_nb + (i%4)); -} - -// The SubBytes Function Substitutes the values in the -// state matrix with values in an S-box. -void QAESEncryption::subBytes() -{ - QByteArray::iterator it = m_state->begin(); - for(int i = 0; i < 16; i++) - it[i] = getSBoxValue((quint8) it[i]); -} - -// The ShiftRows() function shifts the rows in the state to the left. -// Each row is shifted with different offset. -// Offset = Row number. So the first row is not shifted. -void QAESEncryption::shiftRows() -{ - QByteArray::iterator it = m_state->begin(); - quint8 temp; - //Keep in mind that QByteArray is column-driven!! - - //Shift 1 to left - temp = (quint8)it[1]; - it[1] = (quint8)it[5]; - it[5] = (quint8)it[9]; - it[9] = (quint8)it[13]; - it[13] = (quint8)temp; - - //Shift 2 to left - temp = (quint8)it[2]; - it[2] = (quint8)it[10]; - it[10] = (quint8)temp; - temp = (quint8)it[6]; - it[6] = (quint8)it[14]; - it[14] = (quint8)temp; - - //Shift 3 to left - temp = (quint8)it[3]; - it[3] = (quint8)it[15]; - it[15] = (quint8)it[11]; - it[11] = (quint8)it[7]; - it[7] = (quint8)temp; -} - -// MixColumns function mixes the columns of the state matrix -//optimized!! -void QAESEncryption::mixColumns() -{ - QByteArray::iterator it = m_state->begin(); - quint8 tmp, tm, t; - - for(int i = 0; i < 16; i += 4){ - t = (quint8)it[i]; - tmp = (quint8)it[i] ^ (quint8)it[i+1] ^ (quint8)it[i+2] ^ (quint8)it[i+3] ; - - tm = xTime( (quint8)it[i] ^ (quint8)it[i+1] ); - it[i] = (quint8)it[i] ^ (quint8)tm ^ (quint8)tmp; - - tm = xTime( (quint8)it[i+1] ^ (quint8)it[i+2]); - it[i+1] = (quint8)it[i+1] ^ (quint8)tm ^ (quint8)tmp; - - tm = xTime( (quint8)it[i+2] ^ (quint8)it[i+3]); - it[i+2] =(quint8)it[i+2] ^ (quint8)tm ^ (quint8)tmp; - - tm = xTime((quint8)it[i+3] ^ (quint8)t); - it[i+3] =(quint8)it[i+3] ^ (quint8)tm ^ (quint8)tmp; - } -} - -// MixColumns function mixes the columns of the state matrix. -// The method used to multiply may be difficult to understand for the inexperienced. -// Please use the references to gain more information. -void QAESEncryption::invMixColumns() -{ - QByteArray::iterator it = m_state->begin(); - quint8 a,b,c,d; - for(int i = 0; i < 16; i+=4){ - a = (quint8) it[i]; - b = (quint8) it[i+1]; - c = (quint8) it[i+2]; - d = (quint8) it[i+3]; - - it[i] = (quint8) (multiply(a, 0x0e) ^ multiply(b, 0x0b) ^ multiply(c, 0x0d) ^ multiply(d, 0x09)); - it[i+1] = (quint8) (multiply(a, 0x09) ^ multiply(b, 0x0e) ^ multiply(c, 0x0b) ^ multiply(d, 0x0d)); - it[i+2] = (quint8) (multiply(a, 0x0d) ^ multiply(b, 0x09) ^ multiply(c, 0x0e) ^ multiply(d, 0x0b)); - it[i+3] = (quint8) (multiply(a, 0x0b) ^ multiply(b, 0x0d) ^ multiply(c, 0x09) ^ multiply(d, 0x0e)); - } -} - -// The SubBytes Function Substitutes the values in the -// state matrix with values in an S-box. -void QAESEncryption::invSubBytes() -{ - QByteArray::iterator it = m_state->begin(); - for(int i = 0; i < 16; ++i) - it[i] = getSBoxInvert((quint8) it[i]); -} - -void QAESEncryption::invShiftRows() -{ - QByteArray::iterator it = m_state->begin(); - uint8_t temp; - - //Keep in mind that QByteArray is column-driven!! - - //Shift 1 to right - temp = (quint8)it[13]; - it[13] = (quint8)it[9]; - it[9] = (quint8)it[5]; - it[5] = (quint8)it[1]; - it[1] = (quint8)temp; - - //Shift 2 - temp = (quint8)it[10]; - it[10] = (quint8)it[2]; - it[2] = (quint8)temp; - temp = (quint8)it[14]; - it[14] = (quint8)it[6]; - it[6] = (quint8)temp; - - //Shift 3 - temp = (quint8)it[7]; - it[7] = (quint8)it[11]; - it[11] = (quint8)it[15]; - it[15] = (quint8)it[3]; - it[3] = (quint8)temp; -} - -QByteArray QAESEncryption::byteXor(const QByteArray &a, const QByteArray &b) -{ - QByteArray::const_iterator it_a = a.begin(); - QByteArray::const_iterator it_b = b.begin(); - QByteArray ret; - - //for(int i = 0; i < m_blocklen; i++) - for(int i = 0; i < std::min(a.size(), b.size()); i++) - ret.insert(i,it_a[i] ^ it_b[i]); - - return ret; -} - -// Cipher is the main function that encrypts the PlainText. -QByteArray QAESEncryption::cipher(const QByteArray &expKey, const QByteArray &in) -{ - - //m_state is the input buffer... - QByteArray output(in); - m_state = &output; - - // Add the First round key to the state before starting the rounds. - addRoundKey(0, expKey); - - // There will be Nr rounds. - // The first Nr-1 rounds are identical. - // These Nr-1 rounds are executed in the loop below. - for(quint8 round = 1; round < m_nr; ++round){ - subBytes(); - shiftRows(); - mixColumns(); - addRoundKey(round, expKey); - } - - // The last round is given below. - // The MixColumns function is not here in the last round. - subBytes(); - shiftRows(); - addRoundKey(m_nr, expKey); - - return output; -} - -QByteArray QAESEncryption::invCipher(const QByteArray &expKey, const QByteArray &in) -{ - //m_state is the input buffer.... handle it! - QByteArray output(in); - m_state = &output; - - // Add the First round key to the state before starting the rounds. - addRoundKey(m_nr, expKey); - - // There will be Nr rounds. - // The first Nr-1 rounds are identical. - // These Nr-1 rounds are executed in the loop below. - for(quint8 round=m_nr-1; round>0 ; round--){ - invShiftRows(); - invSubBytes(); - addRoundKey(round, expKey); - invMixColumns(); - } - - // The last round is given below. - // The MixColumns function is not here in the last round. - invShiftRows(); - invSubBytes(); - addRoundKey(0, expKey); - - 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.isEmpty() || iv.size() != m_blocklen)) - return QByteArray(); - - QByteArray expandedKey = expandKey(key); - QByteArray alignedText(rawText); - - //Fill array with padding - alignedText.append(getPadding(rawText.size(), m_blocklen)); - - switch(m_mode) - { - 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))); - return ret; - } - break; - case CBC: { -#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()); - } -#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: { - 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)))); - } - return ret; - } - break; - case OFB: { - 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))); - } - ret.append(byteXor(alignedText, ofbTemp)); - return ret; - } - break; - default: break; - } - return QByteArray(); -} - -QByteArray QAESEncryption::decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv) -{ - if (m_mode >= CBC && (iv.isEmpty() || iv.size() != m_blocklen)) - return QByteArray(); - - QByteArray ret; - QByteArray expandedKey = expandKey(key); - - switch(m_mode) - { - case ECB: - for(int i=0; i < rawText.size(); i+= m_blocklen) - ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen))); - break; - case CBC: { - QByteArray ivTemp(iv); - for(int i=0; i < rawText.size(); i+= m_blocklen){ - ret.append(invCipher(expandedKey, rawText.mid(i, m_blocklen))); - ret.replace(i, m_blocklen, byteXor(ret.mid(i, m_blocklen),ivTemp)); - ivTemp = rawText.mid(i, m_blocklen); - } - } - break; - case CFB: { - ret.append(byteXor(rawText.mid(0, m_blocklen), cipher(expandedKey, iv))); - for(int i=0; i < rawText.size(); i+= m_blocklen){ - if (i+m_blocklen < rawText.size()) { - ret.append(byteXor(rawText.mid(i+m_blocklen, m_blocklen), - cipher(expandedKey, rawText.mid(i, m_blocklen)))); - } - } - } - break; - case OFB: { - QByteArray ofbTemp; - ofbTemp.append(cipher(expandedKey, iv)); - for (int i=m_blocklen; i < rawText.size(); i += m_blocklen){ - ofbTemp.append(cipher(expandedKey, ofbTemp.right(m_blocklen))); - } - ret.append(byteXor(rawText, ofbTemp)); - } - break; - default: - //do nothing - break; - } - return ret; -} - -QByteArray QAESEncryption::removePadding(const QByteArray &rawText) -{ - return RemovePadding(rawText, (Padding) m_padding); -} |