Crypto/SHA1: Fix past-the-last-element std::array access and modernize code.

This commit is contained in:
Jordan Woyak
2025-05-08 01:36:29 -05:00
parent 8a9a082c69
commit a9ab0e979e

View File

@ -3,6 +3,7 @@
#include "SHA1.h" #include "SHA1.h"
#include <algorithm>
#include <array> #include <array>
#include <memory> #include <memory>
@ -67,75 +68,58 @@ protected:
virtual void ProcessBlock(const u8* msg) = 0; virtual void ProcessBlock(const u8* msg) = 0;
virtual Digest GetDigest() = 0; virtual Digest GetDigest() = 0;
virtual void Update(const u8* msg, size_t len) override void Update(const u8* msg, size_t len) override
{ {
if (len == 0) m_msg_length += len;
return;
msg_len += len;
if (block_used) size_t count_to_fill_block = m_block.size() - m_block_position;
while (len >= count_to_fill_block)
{ {
if (block_used + len >= block.size()) std::copy_n(msg, count_to_fill_block, m_block.data() + m_block_position);
{ ProcessBlock(m_block.data());
size_t rem = block.size() - block_used;
std::memcpy(&block[block_used], msg, rem); msg += count_to_fill_block;
ProcessBlock(&block[0]); len -= count_to_fill_block;
block_used = 0;
msg += rem; m_block_position = 0;
len -= rem; count_to_fill_block = m_block.size();
}
else
{
std::memcpy(&block[block_used], msg, len);
block_used += len;
return;
}
}
while (len >= BLOCK_LEN)
{
ProcessBlock(msg);
msg += BLOCK_LEN;
len -= BLOCK_LEN;
}
if (len)
{
std::memcpy(&block[0], msg, len);
block_used = len;
} }
std::copy_n(msg, len, m_block.data() + m_block_position);
m_block_position += len;
} }
virtual Digest Finish() override Digest Finish() override
{ {
// block_used is guaranteed < BLOCK_LEN // m_block_position is guaranteed < BLOCK_LEN
block[block_used++] = 0x80; m_block[m_block_position++] = 0x80;
constexpr size_t MSG_LEN_POS = BLOCK_LEN - sizeof(u64); constexpr size_t MSG_LEN_POS = BLOCK_LEN - sizeof(u64);
if (block_used > MSG_LEN_POS)
if (m_block_position > MSG_LEN_POS)
{ {
// Pad current block and process it // Pad current block and process it
std::memset(&block[block_used], 0, BLOCK_LEN - block_used); std::fill(m_block.begin() + m_block_position, m_block.end(), 0x00);
ProcessBlock(&block[0]); ProcessBlock(m_block.data());
m_block_position = 0;
// Pad a new block
std::memset(&block[0], 0, MSG_LEN_POS);
}
else
{
// Pad current block
std::memset(&block[block_used], 0, MSG_LEN_POS - block_used);
} }
Common::BigEndianValue<u64> msg_bitlen(msg_len * 8); // Pad block.
std::memcpy(&block[MSG_LEN_POS], &msg_bitlen, sizeof(msg_bitlen)); std::fill(m_block.data() + m_block_position, m_block.data() + MSG_LEN_POS, 0x00);
m_block_position = MSG_LEN_POS;
ProcessBlock(&block[0]); // Write the message length.
const Common::BigEndianValue<u64> msg_bit_length{m_msg_length * CHAR_BIT};
Update(reinterpret_cast<const u8*>(&msg_bit_length), sizeof(msg_bit_length));
return GetDigest(); return GetDigest();
} }
alignas(64) std::array<u8, BLOCK_LEN> block{}; private:
size_t block_used{}; alignas(64) std::array<u8, BLOCK_LEN> m_block{};
size_t msg_len{}; size_t m_block_position{};
size_t m_msg_length{};
}; };
template <typename ValueType, size_t Size> template <typename ValueType, size_t Size>