AuroraRuntime/Source/Crypto/AES/Aes.cpp

292 lines
8.5 KiB
C++
Raw Normal View History

2021-06-27 21:25:29 +00:00
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Aes.cpp
Date: 2021-6-12
Author: Reece
***/
#include <RuntimeInternal.hpp>
#include "../Crypto.hpp"
#include "Aes.hpp"
#include <tomcrypt.h>
#include <Crypto.hpp>
namespace Aurora::Crypto::AES
{
AUKN_SYM AuUInt GetSafeCipherPadding(const void *plainText, AuUInt plainTextLength)
{
auto tptr = reinterpret_cast<const unsigned char *>(plainText);
auto overhang = plainTextLength & (128 - 1);
auto primaryLength = plainTextLength - overhang;
if (overhang == 0)
{
auto lastbyte = tptr[primaryLength - 1];
if (lastbyte <= 128)
{
return plainTextLength + 128;
}
else
{
return plainTextLength;
}
}
else
{
return 128 - overhang;
}
}
static bool EncryptCoolCodePadding(const void *plainText, AuUInt plainTextLength,
const void *iv, void *outIv, AuUInt ivLength,
const void *key, AuUInt keyLength,
AuList<AuUInt8> &out,
symmetric_CBC &cbc)
{
auto overhang = plainTextLength & (128 - 1) /* || fast_rng_bool */;
auto padding = 128 - overhang;
auto primaryLength = plainTextLength - overhang;
int ret;
auto tptr = reinterpret_cast<const unsigned char *>(plainText);
unsigned char pad[128] =
{
0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x01, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x80
};
if (overhang == 0)
{
auto lastbyte = tptr[primaryLength - 1];
if (lastbyte <= 128)
{
2021-09-06 10:58:08 +00:00
if (!AuTryResize(out, primaryLength + 128))
2021-06-27 21:25:29 +00:00
{
SysPushErrorMem();
return false;
}
// encrypt plain text
ret = cbc_encrypt(tptr, out.data(), primaryLength, &cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypto("{}", ret);
return false;
}
// encrypt another 128 bytes of trash :( 50/50 chance
ret = cbc_encrypt(pad, out.data() + primaryLength, 128, &cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypto("{}", ret);
return false;
}
}
else
{
2021-09-06 10:58:08 +00:00
if (!AuTryResize(out, primaryLength))
2021-06-27 21:25:29 +00:00
{
SysPushErrorMem();
return false;
}
ret = cbc_encrypt(tptr, out.data(), primaryLength, &cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypto("{}", ret);
return false;
}
}
}
else
{
2021-09-06 10:58:08 +00:00
if (!AuTryResize(out, primaryLength + 128))
2021-06-27 21:25:29 +00:00
{
SysPushErrorMem();
return false;
}
ret = cbc_encrypt(tptr, out.data(), primaryLength, &cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypto("{}", ret);
return false;
}
std::memcpy(pad, tptr + primaryLength, overhang);
pad[127] = padding;
ret = cbc_encrypt(pad, out.data() + primaryLength, 128, &cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypto("{}", ret);
return false;
}
}
return true;
}
AUKN_SYM bool Encrypt(const void *plainText, AuUInt plainTextLength,
const void *iv, void *outIv, AuUInt ivLength,
const void *key, AuUInt keyLength,
AuList<AuUInt8> &out,
bool safe)
{
symmetric_CBC cbc;
if (ivLength != 16)
{
SysPushErrorCrypt("{}", ivLength);
return false;
}
if ((keyLength != 16) &&
(keyLength != 24) &&
(keyLength != 32))
{
SysPushErrorCrypt("{}", keyLength);
return false;
}
auto ret = cbc_start(::Crypto::gAesCipher,
reinterpret_cast<const unsigned char *>(iv),
reinterpret_cast<const unsigned char *>(key),
keyLength,
0,
&cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
auto tptr = reinterpret_cast<const unsigned char *>(plainText);
if (safe)
{
if (!EncryptCoolCodePadding(plainText, plainTextLength, iv, outIv, ivLength, key, keyLength, out, cbc))
{
return false;
}
}
else
{
if ((plainTextLength & (16 - 1)) != 0)
{
SysPushErrorArg("{}", keyLength);
return false;
}
ret = cbc_encrypt(tptr, out.data(), plainTextLength, &cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
}
if (outIv)
{
unsigned long ivLength = 16;
ret = cbc_getiv(reinterpret_cast<unsigned char *>(outIv), &ivLength, &cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
}
return true;
}
AUKN_SYM bool Decrypt(const void *cipherText, AuUInt cipherTextLength,
const void *iv, void *outIv, AuUInt ivLength,
const void *key, AuUInt keyLength,
AuList<AuUInt8> &plainText,
bool safe)
{
symmetric_CBC cbc;
if (ivLength != 16)
{
SysPushErrorArg("{}", ivLength);
return false;
}
if ((keyLength != 16) &&
(keyLength != 24) &&
(keyLength != 32))
{
SysPushErrorArg("{}", keyLength);
return false;
}
auto ret = cbc_start(::Crypto::gAesCipher,
reinterpret_cast<const unsigned char *>(iv),
reinterpret_cast<const unsigned char *>(key),
keyLength,
0,
&cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
auto tptr = reinterpret_cast<const unsigned char *>(cipherText);
2021-09-06 10:58:08 +00:00
if (!AuTryResize(plainText, cipherTextLength))
2021-06-27 21:25:29 +00:00
{
SysPushErrorMem();
return false;
}
ret = cbc_decrypt(tptr, plainText.data(), cipherTextLength, &cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
if (safe)
{
auto magic = plainText[cipherTextLength - 1];
if (magic <= 128)
{
plainText.resize(cipherTextLength - magic);
}
}
if (outIv)
{
unsigned long ivLength = 16;
ret = cbc_getiv(reinterpret_cast<unsigned char *>(outIv), &ivLength, &cbc);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
}
return true;
}
}