Skip to content

Commit

Permalink
Remove heap allocations from aes::calcJ0
Browse files Browse the repository at this point in the history
  • Loading branch information
Sainan committed Dec 1, 2024
1 parent 2d17371 commit fbf8227
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 14 deletions.
19 changes: 19 additions & 0 deletions CLI/cli_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,25 @@ static void unit_crypto()
aes::ecbDecrypt(reinterpret_cast<uint8_t*>(data.data()), data.size(), reinterpret_cast<const uint8_t*>(key), 32);
assert(data == "The quick brown fox jumps over the lazy dog.");
});
test("calcJ0", []
{
const uint8_t bytes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
{
uint8_t res[16];
aes::calcJ0(res, bytes, bytes, 15);
assert(string::bin2hex((const char*)res, 16) == "C53CC6D5A2EEBC3F3FF12D420285FC8C");
}
{
uint8_t res[16];
aes::calcJ0(res, bytes, bytes, 16);
assert(string::bin2hex((const char*)res, 16) == "67144FBCDC0E6262B92502D7DA99CE72");
}
{
uint8_t res[16];
aes::calcJ0(res, bytes, bytes, 17);
assert(string::bin2hex((const char*)res, 16) == "B85388BE5704F782153B4FDCC1F16FF7");
}
});
}

test("SegWitAddress", []
Expand Down
41 changes: 31 additions & 10 deletions soup/aes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ NAMESPACE_SOUP
aes::encryptBlock(h, h, roundKeys, Nr);
}

void aes::calcJ0(uint8_t j0[16], const uint8_t h[16], const uint8_t* iv, size_t iv_len) SOUP_EXCAL
void aes::calcJ0(uint8_t j0[16], const uint8_t h[16], const uint8_t* iv, size_t iv_len) noexcept
{
if (iv_len == 12)
{
Expand All @@ -962,15 +962,21 @@ NAMESPACE_SOUP
}
else
{
const auto len_iv = iv_len * 8;
const auto s = 128 * plusaes::detail::gcm::ceil(len_iv / 128.0) - len_iv;
std::vector<uint8_t> ghash_in;
ghash_in.reserve(32);
plusaes::detail::gcm::push_back(ghash_in, iv, iv_len);
plusaes::detail::gcm::push_back_zero_bits(ghash_in, s + 64);
plusaes::detail::gcm::push_back(ghash_in, std::bitset<64>(len_iv));

return ghash(j0, h, ghash_in.data(), ghash_in.size());
GhashState state(j0, h);
state.append(iv, iv_len);

const auto iv_bits = iv_len * 8;
auto padding = (128 * static_cast<unsigned long>(std::ceil(iv_bits / 128.0) + 0.5) - iv_bits) / 8;
while (padding--)
{
state.appendByte(0);
}

memset(state.buffer, 0, 16);
reinterpret_cast<uint64_t*>(state.buffer)[1] = Endianness::invert(iv_bits); static_assert(ENDIAN_NATIVE == ENDIAN_LITTLE);
state.transform();

SOUP_DEBUG_ASSERT(state.buffer_counter == 0);
}
}

Expand Down Expand Up @@ -1029,4 +1035,19 @@ NAMESPACE_SOUP
ghash(tag, h, ghash_in.data(), ghash_in.size());
gctr(tag, 16, roundKeys, Nr, j0);
}

aes::GhashState::GhashState(uint8_t res[16], const uint8_t h[16]) noexcept
: res(res), h(h), buffer_counter(0)
{
memset(res, 0, 16);
}

void aes::GhashState::transform() noexcept
{
xorBlocks(res, buffer);

uint8_t tmp[16];
memcpy(tmp, res, 16);
mulBlocks(res, tmp, h);
}
}
37 changes: 33 additions & 4 deletions soup/aes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@

NAMESPACE_SOUP
{
class aes
struct aes
{
public:
// Input size should be a multiple of 16 bytes.
// GCM can deal with unaligned data, other methods will simply ignore the trailing bytes -> they will not be encrypted.
// You may use a padding scheme such as PKCS#7 for padding.
Expand All @@ -27,7 +26,7 @@ NAMESPACE_SOUP
static void gcmEncrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, uint8_t tag[16]) SOUP_EXCAL;
static bool gcmDecrypt(uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t* key, size_t key_len, const uint8_t* iv, size_t iv_len, const uint8_t tag[16]) SOUP_EXCAL;

private:

static void expandKey(uint8_t w[240], const uint8_t* key, size_t key_len) noexcept;
static void expandKeyForDecryption(uint8_t w[240], const uint8_t* key, size_t key_len) noexcept;
[[nodiscard]] static int getNk(size_t key_len) noexcept;
Expand Down Expand Up @@ -56,9 +55,39 @@ NAMESPACE_SOUP
static void mulBlocks(uint8_t res[16], const uint8_t x[16], const uint8_t y[16]) noexcept;
static void ghash(uint8_t res[16], const uint8_t h[16], const uint8_t x[], size_t x_bytes) noexcept;
static void calcH(uint8_t h[16], uint8_t roundKeys[240], const int Nr) noexcept;
static void calcJ0(uint8_t j0[16], const uint8_t h[16], const uint8_t* iv, size_t iv_len) SOUP_EXCAL;
static void calcJ0(uint8_t j0[16], const uint8_t h[16], const uint8_t* iv, size_t iv_len) noexcept;
static void inc32(uint8_t block[16]) noexcept;
static void gctr(uint8_t* data, size_t data_len, const uint8_t roundKeys[240], const int Nr, const uint8_t icb[8]) noexcept;
static void calcGcmTag(uint8_t tag[16], uint8_t* data, size_t data_len, const uint8_t* aadata, size_t aadata_len, const uint8_t roundKeys[16], const int Nr, const uint8_t h[16], const uint8_t j0[16]) SOUP_EXCAL;

struct GhashState
{
uint8_t* const res;
const uint8_t* const h;
uint8_t buffer[16];
uint8_t buffer_counter;

GhashState(uint8_t res[16], const uint8_t h[16]) noexcept;

void append(const uint8_t data[], size_t size) noexcept
{
for (size_t i = 0; i != size; ++i)
{
appendByte(data[i]);
}
}

void appendByte(uint8_t byte) noexcept
{
buffer[buffer_counter] = byte;
if (++buffer_counter == 16)
{
buffer_counter = 0;
transform();
}
}

void transform() noexcept;
};
};
}

0 comments on commit fbf8227

Please sign in to comment.