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 <wolv/utils/expected.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define CRYPTO_ERROR_INVALID_KEY_LENGTH (-1)
|
||||
#define CRYPTO_ERROR_INVALID_MODE (-2)
|
||||
|
||||
namespace hex::prv {
|
||||
class Provider;
|
||||
}
|
||||
@ -60,5 +65,5 @@ namespace hex::crypt {
|
||||
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();
|
||||
|
||||
if (outputData.empty())
|
||||
throwNodeError("No data available at connected attribute");
|
||||
|
||||
return outputData;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include <algorithm>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
#include <wolv/utils/guards.hpp>
|
||||
#include <wolv/utils/expected.hpp>
|
||||
|
||||
#include <mbedtls/version.h>
|
||||
#include <mbedtls/base64.h>
|
||||
@ -496,8 +498,8 @@ namespace hex::crypt {
|
||||
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) {
|
||||
std::vector<u8> output;
|
||||
static wolv::util::Expected<std::vector<u8>, int> 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::span<const u8> &input) {
|
||||
|
||||
if (input.empty())
|
||||
return {};
|
||||
@ -507,38 +509,65 @@ namespace hex::crypt {
|
||||
mbedtls_cipher_context_t ctx;
|
||||
auto cipherInfo = mbedtls_cipher_info_from_type(type);
|
||||
|
||||
if (cipherInfo == nullptr)
|
||||
return {};
|
||||
|
||||
mbedtls_cipher_setup(&ctx, cipherInfo);
|
||||
mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, operation);
|
||||
int setupResult = mbedtls_cipher_setup(&ctx, cipherInfo);
|
||||
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::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);
|
||||
output.resize(outputSize, 0x00);
|
||||
mbedtls_cipher_crypt(&ctx, nonceCounter.data(), nonceCounter.size(), input.data(), input.size(), output.data(), &outputSize);
|
||||
std::vector<u8> output(outputSize, 0x00);
|
||||
|
||||
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);
|
||||
|
||||
if (cryptResult != 0) {
|
||||
return wolv::util::Unexpected(cryptResult);
|
||||
}
|
||||
|
||||
output.resize(input.size());
|
||||
|
||||
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) {
|
||||
case KeyLength::Key128Bits:
|
||||
if (key.size() != 128 / 8) return {};
|
||||
if (key.size() != 128 / 8)
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||
break;
|
||||
case KeyLength::Key192Bits:
|
||||
if (key.size() != 192 / 8) return {};
|
||||
if (key.size() != 192 / 8)
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||
break;
|
||||
case KeyLength::Key256Bits:
|
||||
if (key.size() != 256 / 8) return {};
|
||||
if (key.size() != 256 / 8)
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||
break;
|
||||
default:
|
||||
return {};
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_KEY_LENGTH);
|
||||
}
|
||||
|
||||
mbedtls_cipher_type_t type;
|
||||
@ -568,7 +597,7 @@ namespace hex::crypt {
|
||||
type = MBEDTLS_CIPHER_AES_128_XTS;
|
||||
break;
|
||||
default:
|
||||
return {};
|
||||
return wolv::util::Unexpected(CRYPTO_ERROR_INVALID_MODE);
|
||||
}
|
||||
|
||||
type = mbedtls_cipher_type_t(type + u8(keyLength));
|
||||
|
@ -1,9 +1,13 @@
|
||||
#include <algorithm>
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/localization_manager.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/crypto.hpp>
|
||||
#include <hex/data_processor/node.hpp>
|
||||
|
||||
#include <mbedtls/cipher.h>
|
||||
#include <mbedtls/error.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
@ -25,6 +29,9 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
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 &iv = this->getBufferOnInput(1);
|
||||
const auto &nonce = this->getBufferOnInput(2);
|
||||
@ -38,12 +45,34 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::array<u8, 8> ivData = { 0 }, nonceData = { 0 };
|
||||
|
||||
std::copy(iv.begin(), iv.end(), ivData.begin());
|
||||
std::copy(nonce.begin(), nonce.end(), nonceData.begin());
|
||||
if (mode != crypt::AESMode::ECB) {
|
||||
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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user