/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Aes.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "../Crypto.hpp" #include "Aes.hpp" #include #include namespace Aurora::Crypto::AES { AUKN_SYM AuUInt GetSafeCipherPadding(const void *plainText, AuUInt plainTextLength) { auto tptr = reinterpret_cast(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 &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(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) { if (!AuTryResize(out, primaryLength + 128)) { 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 { if (!AuTryResize(out, primaryLength)) { SysPushErrorMem(); return false; } ret = cbc_encrypt(tptr, out.data(), primaryLength, &cbc); if (ret != CRYPT_OK) { SysPushErrorCrypto("{}", ret); return false; } } } else { if (!AuTryResize(out, primaryLength + 128)) { 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 &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(iv), reinterpret_cast(key), keyLength, 0, &cbc); if (ret != CRYPT_OK) { SysPushErrorCrypt("{}", ret); return false; } auto tptr = reinterpret_cast(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(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 &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(iv), reinterpret_cast(key), keyLength, 0, &cbc); if (ret != CRYPT_OK) { SysPushErrorCrypt("{}", ret); return false; } auto tptr = reinterpret_cast(cipherText); if (!AuTryResize(plainText, cipherTextLength)) { 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(outIv), &ivLength, &cbc); if (ret != CRYPT_OK) { SysPushErrorCrypt("{}", ret); return false; } } return true; } }