plusaes
plusaes copied to clipboard
Wrong GCM Tag on 32-bit build
Steps to reproduce:
#include <iostream>
#include <string>
#include <plusaes.hpp>
[[nodiscard]] static std::string bin2hexImpl(const std::string& str, const char* map)
{
std::string res{};
res.reserve(str.size() * 2);
for (const auto& c : str)
{
res.push_back(map[(unsigned char)c >> 4]);
res.push_back(map[c & 0b1111]);
}
return res;
}
[[nodiscard]] static std::string bin2hex(const std::string& str)
{
return bin2hexImpl(str, "0123456789ABCDEF");
}
int main()
{
std::string data = "Hello, world!";
std::string ad = "ABCDEFGHIJKLM";
std::string key = "ABCDEFGHIJKLMNOP";
std::string iv = "ABCDEFGHIJKLMNOP";
uint8_t tag[16];
if (plusaes::encrypt_gcm(
(uint8_t*)data.data(), data.size(),
(uint8_t*)ad.data(), ad.size(),
(uint8_t*)key.data(), key.size(),
(const uint8_t(*)[12])iv.data(),
&tag
) == plusaes::kErrorOk)
{
std::cout << bin2hex(std::string(&tag[0], &tag[16]));
}
else
{
std::cout << "encrypt failed\r\n";
}
}
Notice that the printed tag will differ between 32-bit and 64-bit build. Tested with clang on Windows.
Did some classic print debugging and it seems this expression is the culprit:
But this expression works fine; it seems the (implicit) conversion to a Block is breaking on the least-significant byte:
J0_bitset = 01000001010000100100001101000100010001010100011001000111010010000100100101001010010010110100110000000000000000000000000000000001
J0 = 01000001010000100100001101000100010001010100011001000111000000000100100101001010010010110100110000000000000000000000000001001000
I've added a print statement to the bitset-to-Block conversion and it seems now it works... I think this is a compiler bug, so I'm moving this issue to LLVM: https://github.com/llvm/llvm-project/issues/64109
Merged.