fix: AES ECB mode in Data processor not working at all (#1986)
Fix the AES ECB mode in the data processor along with some other misc fixes: - Fixed nullpointer node not working - Fixed crypto module incorrectly using mbedtls api - Fixed crypto module ignoring mbedtls errors - Fixed silently ignoring of errors in AES node
This commit is contained in:
parent
8acdc19be4
commit
3c73f88a52
@ -2,10 +2,15 @@
|
|||||||
|
|
||||||
#include <hex.hpp>
|
#include <hex.hpp>
|
||||||
|
|
||||||
|
#include <wolv/utils/expected.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#define CRYPTO_ERROR_INVALID_KEY_LENGTH (-1)
|
||||||
|
#define CRYPTO_ERROR_INVALID_MODE (-2)
|
||||||
|
|
||||||
namespace hex::prv {
|
namespace hex::prv {
|
||||||
class Provider;
|
class Provider;
|
||||||
}
|
}
|
||||||
@ -60,5 +65,5 @@ namespace hex::crypt {
|
|||||||
Key256Bits = 2
|
Key256Bits = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<u8> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input);
|
wolv::util::Expected<std::vector<u8>, int> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input);
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,6 @@ namespace hex::dp {
|
|||||||
|
|
||||||
auto &outputData = attribute->getOutputData();
|
auto &outputData = attribute->getOutputData();
|
||||||
|
|
||||||
if (outputData.empty())
|
|
||||||
throwNodeError("No data available at connected attribute");
|
|
||||||
|
|
||||||
return outputData;
|
return outputData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
#include <algorithm>
|
||||||
#include <hex/helpers/crypto.hpp>
|
#include <hex/helpers/crypto.hpp>
|
||||||
|
|
||||||
#include <hex/providers/provider.hpp>
|
#include <hex/providers/provider.hpp>
|
||||||
|
|
||||||
#include <wolv/utils/guards.hpp>
|
#include <wolv/utils/guards.hpp>
|
||||||
|
#include <wolv/utils/expected.hpp>
|
||||||
|
|
||||||
#include <mbedtls/version.h>
|
#include <mbedtls/version.h>
|
||||||
#include <mbedtls/base64.h>
|
#include <mbedtls/base64.h>
|
||||||
@ -496,8 +498,8 @@ namespace hex::crypt {
|
|||||||
return encodeLeb128<i128>(value);
|
return encodeLeb128<i128>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<u8> aes(mbedtls_cipher_type_t type, mbedtls_operation_t operation, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input) {
|
static wolv::util::Expected<std::vector<u8>, int> aes(mbedtls_cipher_type_t type, mbedtls_operation_t operation, const std::vector<u8> &key,
|
||||||
std::vector<u8> output;
|
std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::span<const u8> &input) {
|
||||||
|
|
||||||
if (input.empty())
|
if (input.empty())
|
||||||
return {};
|
return {};
|
||||||
@ -507,38 +509,65 @@ namespace hex::crypt {
|
|||||||
mbedtls_cipher_context_t ctx;
|
mbedtls_cipher_context_t ctx;
|
||||||
auto cipherInfo = mbedtls_cipher_info_from_type(type);
|
auto cipherInfo = mbedtls_cipher_info_from_type(type);
|
||||||
|
|
||||||
|
if (cipherInfo == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
mbedtls_cipher_setup(&ctx, cipherInfo);
|
int setupResult = mbedtls_cipher_setup(&ctx, cipherInfo);
|
||||||
mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, operation);
|
if (setupResult != 0)
|
||||||
|
return wolv::util::Unexpected(setupResult);
|
||||||
|
|
||||||
|
int setKeyResult = mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, operation);
|
||||||
|
if (setKeyResult != 0)
|
||||||
|
return wolv::util::Unexpected(setKeyResult);
|
||||||
|
|
||||||
std::array<u8, 16> nonceCounter = { 0 };
|
std::array<u8, 16> nonceCounter = { 0 };
|
||||||
std::copy(nonce.begin(), nonce.end(), nonceCounter.begin());
|
|
||||||
std::copy(iv.begin(), iv.end(), nonceCounter.begin() + 8);
|
auto mode = mbedtls_cipher_get_cipher_mode(&ctx);
|
||||||
|
|
||||||
|
// if we are in ECB mode, we don't need to set the nonce
|
||||||
|
if (mode != MBEDTLS_MODE_ECB) {
|
||||||
|
std::ranges::copy(nonce, nonceCounter.begin());
|
||||||
|
std::ranges::copy(iv, nonceCounter.begin() + 8);
|
||||||
|
}
|
||||||
|
|
||||||
size_t outputSize = input.size() + mbedtls_cipher_get_block_size(&ctx);
|
size_t outputSize = input.size() + mbedtls_cipher_get_block_size(&ctx);
|
||||||
output.resize(outputSize, 0x00);
|
std::vector<u8> output(outputSize, 0x00);
|
||||||
mbedtls_cipher_crypt(&ctx, nonceCounter.data(), nonceCounter.size(), input.data(), input.size(), output.data(), &outputSize);
|
|
||||||
|
|
||||||
|
int cryptResult = 0;
|
||||||
|
if (mode == MBEDTLS_MODE_ECB) {
|
||||||
|
cryptResult = mbedtls_cipher_crypt(&ctx, nullptr, 0, input.data(), input.size(), output.data(), &outputSize);
|
||||||
|
} else {
|
||||||
|
cryptResult = mbedtls_cipher_crypt(&ctx, nonceCounter.data(), nonceCounter.size(), input.data(), input.size(), output.data(), &outputSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// free regardless of the result
|
||||||
mbedtls_cipher_free(&ctx);
|
mbedtls_cipher_free(&ctx);
|
||||||
|
|
||||||
|
if (cryptResult != 0) {
|
||||||
|
return wolv::util::Unexpected(cryptResult);
|
||||||
|
}
|
||||||
|
|
||||||
output.resize(input.size());
|
output.resize(input.size());
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<u8> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input) {
|
wolv::util::Expected<std::vector<u8>, int> aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector<u8> &key, std::array<u8, 8> nonce, std::array<u8, 8> iv, const std::vector<u8> &input) {
|
||||||
switch (keyLength) {
|
switch (keyLength) {
|
||||||
case KeyLength::Key128Bits:
|
case KeyLength::Key128Bits:
|
||||||
if (key.size() != 128 / 8) return {};
|
if (key.size() != 128 / 8)
|
||||||
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||||
break;
|
break;
|
||||||
case KeyLength::Key192Bits:
|
case KeyLength::Key192Bits:
|
||||||
if (key.size() != 192 / 8) return {};
|
if (key.size() != 192 / 8)
|
||||||
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||||
break;
|
break;
|
||||||
case KeyLength::Key256Bits:
|
case KeyLength::Key256Bits:
|
||||||
if (key.size() != 256 / 8) return {};
|
if (key.size() != 256 / 8)
|
||||||
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return {};
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_cipher_type_t type;
|
mbedtls_cipher_type_t type;
|
||||||
@ -568,7 +597,7 @@ namespace hex::crypt {
|
|||||||
type = MBEDTLS_CIPHER_AES_128_XTS;
|
type = MBEDTLS_CIPHER_AES_128_XTS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return {};
|
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
type = mbedtls_cipher_type_t(type + u8(keyLength));
|
type = mbedtls_cipher_type_t(type + u8(keyLength));
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
|
#include <algorithm>
|
||||||
#include <hex/api/content_registry.hpp>
|
#include <hex/api/content_registry.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
#include <hex/helpers/utils.hpp>
|
#include <hex/helpers/utils.hpp>
|
||||||
#include <hex/helpers/crypto.hpp>
|
#include <hex/helpers/crypto.hpp>
|
||||||
#include <hex/data_processor/node.hpp>
|
#include <hex/data_processor/node.hpp>
|
||||||
|
|
||||||
|
#include <mbedtls/cipher.h>
|
||||||
|
#include <mbedtls/error.h>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
@ -25,6 +29,9 @@ namespace hex::plugin::builtin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void process() override {
|
void process() override {
|
||||||
|
const auto mode = static_cast<crypt::AESMode>(m_mode);
|
||||||
|
const auto keyLength = static_cast<crypt::KeyLength>(m_keyLength);
|
||||||
|
|
||||||
const auto &key = this->getBufferOnInput(0);
|
const auto &key = this->getBufferOnInput(0);
|
||||||
const auto &iv = this->getBufferOnInput(1);
|
const auto &iv = this->getBufferOnInput(1);
|
||||||
const auto &nonce = this->getBufferOnInput(2);
|
const auto &nonce = this->getBufferOnInput(2);
|
||||||
@ -38,12 +45,34 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
std::array<u8, 8> ivData = { 0 }, nonceData = { 0 };
|
std::array<u8, 8> ivData = { 0 }, nonceData = { 0 };
|
||||||
|
|
||||||
std::copy(iv.begin(), iv.end(), ivData.begin());
|
if (mode != crypt::AESMode::ECB) {
|
||||||
std::copy(nonce.begin(), nonce.end(), nonceData.begin());
|
if (iv.empty())
|
||||||
|
throwNodeError("IV cannot be empty");
|
||||||
|
|
||||||
auto output = crypt::aesDecrypt(static_cast<crypt::AESMode>(m_mode), static_cast<crypt::KeyLength>(m_keyLength), key, nonceData, ivData, input);
|
if (nonce.empty())
|
||||||
|
throwNodeError("Nonce cannot be empty");
|
||||||
|
|
||||||
this->setBufferOnOutput(4, output);
|
std::ranges::copy(iv, ivData.begin());
|
||||||
|
std::ranges::copy(nonce, nonceData.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto output = crypt::aesDecrypt(mode, keyLength, key, nonceData, ivData, input);
|
||||||
|
if (!output) {
|
||||||
|
switch (output.error()) {
|
||||||
|
case CRYPTO_ERROR_INVALID_KEY_LENGTH:
|
||||||
|
throwNodeError("Invalid key length");
|
||||||
|
case CRYPTO_ERROR_INVALID_MODE:
|
||||||
|
throwNodeError("Invalid mode");
|
||||||
|
default: {
|
||||||
|
std::array<char, 128> errorBuffer = { 0 };
|
||||||
|
mbedtls_strerror(output.error(), errorBuffer.data(), errorBuffer.size());
|
||||||
|
|
||||||
|
throwNodeError(std::string(errorBuffer.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setBufferOnOutput(4, output.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void store(nlohmann::json &j) const override {
|
void store(nlohmann::json &j) const override {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user