kkAyataka / plusaes

Header only C++ AES cipher library
https://kkayataka.github.io/plusaes/doc/index.html
Boost Software License 1.0
183 stars 41 forks source link

Wrong GCM Tag on 32-bit build #43

Closed Sainan closed 2 months ago

Sainan commented 1 year ago

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.

Sainan commented 1 year ago

Did some classic print debugging and it seems this expression is the culprit:

image

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

kkAyataka commented 2 months ago

Merged.