Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: AlignmentBuffer<> helper for block-oriented Hashes #3693

Merged
merged 6 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 28 additions & 56 deletions src/lib/hash/blake2/blake2b.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,26 @@
#include <botan/internal/loadstor.h>
#include <botan/internal/rotate.h>
#include <botan/internal/stl_util.h>

#include <algorithm>
#include <array>

namespace Botan {

namespace {

enum blake2b_constant { BLAKE2B_BLOCKBYTES = 128, BLAKE2B_IVU64COUNT = 8 };

const uint64_t blake2b_IV[BLAKE2B_IVU64COUNT] = {0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1,
0x510e527fade682d1,
0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b,
0x5be0cd19137e2179};
constexpr std::array<uint64_t, 8> blake2b_IV{0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1,
0x510e527fade682d1,
0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b,
0x5be0cd19137e2179};

} // namespace

BLAKE2b::BLAKE2b(size_t output_bits) :
m_output_bits(output_bits),
m_buffer(BLAKE2B_BLOCKBYTES),
m_bufpos(0),
m_H(BLAKE2B_IVU64COUNT),
m_T(),
m_F(),
m_key_size(0) {
BLAKE2b::BLAKE2b(size_t output_bits) : m_output_bits(output_bits), m_H(blake2b_IV.size()), m_T(), m_F(), m_key_size(0) {
if(output_bits == 0 || output_bits > 512 || output_bits % 8 != 0) {
throw Invalid_Argument("Bad output bits size for BLAKE2b");
}
Expand All @@ -49,17 +42,14 @@ BLAKE2b::BLAKE2b(size_t output_bits) :
}

void BLAKE2b::state_init() {
copy_mem(m_H.data(), blake2b_IV, BLAKE2B_IVU64COUNT);
copy_mem(m_H.data(), blake2b_IV.data(), blake2b_IV.size());
m_H[0] ^= (0x01010000 | (static_cast<uint8_t>(m_key_size) << 8) | static_cast<uint8_t>(output_length()));
m_T[0] = m_T[1] = 0;
m_F = 0;

if(m_key_size == 0) {
m_bufpos = 0;
} else {
BOTAN_ASSERT_NOMSG(m_padded_key_buffer.size() == m_buffer.size());
copy_mem(m_buffer.data(), m_padded_key_buffer.data(), m_padded_key_buffer.size());
m_bufpos = m_padded_key_buffer.size();
m_buffer.clear();
if(m_key_size > 0) {
m_buffer.append(m_padded_key_buffer);
}
}

Expand Down Expand Up @@ -149,45 +139,28 @@ void BLAKE2b::compress(const uint8_t* input, size_t blocks, uint64_t increment)
}

void BLAKE2b::add_data(std::span<const uint8_t> input) {
if(input.empty()) {
return;
}

BufferSlicer in(input);

if(m_bufpos > 0) {
if(m_bufpos < BLAKE2B_BLOCKBYTES) {
const auto part = in.take(std::min(BLAKE2B_BLOCKBYTES - m_bufpos, in.remaining()));
copy_mem(&m_buffer[m_bufpos], part.data(), part.size());
m_bufpos += part.size();
while(!in.empty()) {
if(const auto one_block = m_buffer.handle_unaligned_data(in)) {
compress(one_block->data(), 1, BLAKE2B_BLOCKBYTES);
}

if(m_bufpos == m_buffer.size() && !in.empty()) {
compress(m_buffer.data(), 1, BLAKE2B_BLOCKBYTES);
m_bufpos = 0;
if(m_buffer.in_alignment()) {
const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in);
if(full_blocks > 0) {
compress(aligned_data.data(), full_blocks, BLAKE2B_BLOCKBYTES);
}
}
}

if(in.remaining() > BLAKE2B_BLOCKBYTES) {
const size_t full_blocks = ((in.remaining() - 1) / BLAKE2B_BLOCKBYTES);
compress(in.take(BLAKE2B_BLOCKBYTES * full_blocks).data(), full_blocks, BLAKE2B_BLOCKBYTES);
}

if(!in.empty()) {
const auto take = in.remaining();
copy_mem(&m_buffer[m_bufpos], in.take(take).data(), take);
m_bufpos += take;
}

BOTAN_ASSERT_NOMSG(in.empty());
}

void BLAKE2b::final_result(std::span<uint8_t> output) {
if(m_bufpos != BLAKE2B_BLOCKBYTES) {
clear_mem(&m_buffer[m_bufpos], BLAKE2B_BLOCKBYTES - m_bufpos);
}
const auto pos = m_buffer.elements_in_buffer();
m_buffer.fill_up_with_zeros();
randombit marked this conversation as resolved.
Show resolved Hide resolved

m_F = 0xFFFFFFFFFFFFFFFF;
compress(m_buffer.data(), 1, m_bufpos);
compress(m_buffer.consume().data(), 1, pos);
copy_out_vec_le(output.data(), output_length(), m_H);
state_init();
}
Expand Down Expand Up @@ -229,9 +202,8 @@ void BLAKE2b::key_schedule(std::span<const uint8_t> key) {

void BLAKE2b::clear() {
zeroise(m_H);
zeroise(m_buffer);
m_buffer.clear();
zeroise(m_padded_key_buffer);
m_bufpos = 0;
m_key_size = 0;
state_init();
}
Expand Down
6 changes: 4 additions & 2 deletions src/lib/hash/blake2/blake2b.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@

#include <botan/hash.h>
#include <botan/sym_algo.h>
#include <botan/internal/alignment_buffer.h>
#include <memory>
#include <string>

namespace Botan {

class BLAKE2bMAC;

constexpr size_t BLAKE2B_BLOCKBYTES = 128;

/**
* BLAKE2B
*/
Expand Down Expand Up @@ -57,8 +60,7 @@ class BLAKE2b final : public HashFunction,

const size_t m_output_bits;

secure_vector<uint8_t> m_buffer;
size_t m_bufpos;
AlignmentBuffer<uint8_t, BLAKE2B_BLOCKBYTES, AlignmentBufferFinalBlock::must_be_deferred> m_buffer;

secure_vector<uint64_t> m_H;
uint64_t m_T[2];
Expand Down
39 changes: 16 additions & 23 deletions src/lib/hash/gost_3411/gost_3411.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ namespace Botan {
/**
* GOST 34.11 Constructor
*/
GOST_34_11::GOST_34_11() : m_cipher(GOST_28147_89_Params("R3411_CryptoPro")), m_buffer(32), m_sum(32), m_hash(32) {
GOST_34_11::GOST_34_11() : m_cipher(GOST_28147_89_Params("R3411_CryptoPro")), m_sum(32), m_hash(32) {
m_count = 0;
m_position = 0;
}

void GOST_34_11::clear() {
m_cipher.clear();
zeroise(m_sum);
zeroise(m_hash);
m_count = 0;
m_position = 0;
m_buffer.clear();
}

std::unique_ptr<HashFunction> GOST_34_11::copy_state() const {
Expand All @@ -36,28 +35,22 @@ std::unique_ptr<HashFunction> GOST_34_11::copy_state() const {
* Hash additional inputs
*/
void GOST_34_11::add_data(std::span<const uint8_t> input) {
m_count += input.size();

if(m_position) {
buffer_insert(m_buffer, m_position, input.data(), input.size());
BufferSlicer in(input);

if(m_position + input.size() >= hash_block_size()) {
compress_n(m_buffer.data(), 1);
input = input.last(input.size() - hash_block_size() + m_position);
m_position = 0;
while(!in.empty()) {
if(const auto one_block = m_buffer.handle_unaligned_data(in)) {
compress_n(one_block->data(), 1);
}
}

BufferSlicer in(input);
const size_t full_blocks = in.remaining() / hash_block_size();

if(full_blocks) {
compress_n(in.take(full_blocks * hash_block_size()).data(), full_blocks);
if(m_buffer.in_alignment()) {
const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in);
if(full_blocks > 0) {
compress_n(aligned_data.data(), full_blocks);
}
}
}

const auto remaining = in.take(in.remaining());
buffer_insert(m_buffer, m_position, remaining.data(), remaining.size());
m_position += remaining.size();
m_count += input.size();
}

/**
Expand Down Expand Up @@ -208,9 +201,9 @@ void GOST_34_11::compress_n(const uint8_t input[], size_t blocks) {
* Produce the final GOST 34.11 output
*/
void GOST_34_11::final_result(std::span<uint8_t> out) {
if(m_position) {
clear_mem(m_buffer.data() + m_position, m_buffer.size() - m_position);
compress_n(m_buffer.data(), 1);
if(!m_buffer.in_alignment()) {
m_buffer.fill_up_with_zeros();
compress_n(m_buffer.consume().data(), 1);
}

secure_vector<uint8_t> length_buf(32);
Expand Down
5 changes: 3 additions & 2 deletions src/lib/hash/gost_3411/gost_3411.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define BOTAN_GOST_3411_H_

#include <botan/hash.h>
#include <botan/internal/alignment_buffer.h>
#include <botan/internal/gost_28147.h>

namespace Botan {
Expand Down Expand Up @@ -39,8 +40,8 @@ class GOST_34_11 final : public HashFunction {
void final_result(std::span<uint8_t>) override;

GOST_28147_89 m_cipher;
secure_vector<uint8_t> m_buffer, m_sum, m_hash;
size_t m_position;
AlignmentBuffer<uint8_t, 32> m_buffer;
secure_vector<uint8_t> m_sum, m_hash;
uint64_t m_count;
};

Expand Down
3 changes: 3 additions & 0 deletions src/lib/hash/mdx_hash/mdx_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ void MDx_HashFunction::clear() {
void MDx_HashFunction::add_data(std::span<const uint8_t> input) {
const size_t block_len = static_cast<size_t>(1) << m_block_bits;

// TODO: Use AlignmentBuffer<> once MDx_HashFunction is not a base class
// anymore. See: https://github.com/randombit/botan/pull/3550

m_count += input.size();

if(m_position) {
Expand Down
48 changes: 15 additions & 33 deletions src/lib/hash/skein/skein_512.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ Skein_512::Skein_512(size_t arg_output_bits, std::string_view arg_personalizatio
m_personalization(arg_personalization),
m_output_bits(arg_output_bits),
m_threefish(std::make_unique<Threefish_512>()),
m_T(2),
m_buffer(64),
m_buf_pos(0) {
m_T(2) {
if(m_output_bits == 0 || m_output_bits % 8 != 0 || m_output_bits > 512) {
throw Invalid_Argument("Bad output bits size for Skein-512");
}
Expand All @@ -46,13 +44,11 @@ std::unique_ptr<HashFunction> Skein_512::copy_state() const {
copy->m_threefish->m_K = this->m_threefish->m_K;
copy->m_T = this->m_T;
copy->m_buffer = this->m_buffer;
copy->m_buf_pos = this->m_buf_pos;
return copy;
}

void Skein_512::clear() {
zeroise(m_buffer);
m_buf_pos = 0;
m_buffer.clear();

initial_block();
}
Expand Down Expand Up @@ -120,41 +116,28 @@ void Skein_512::ubi_512(const uint8_t msg[], size_t msg_len) {
}

void Skein_512::add_data(std::span<const uint8_t> input) {
if(input.empty()) {
return;
}

if(m_buf_pos) {
buffer_insert(m_buffer, m_buf_pos, input.data(), input.size());
if(m_buf_pos + input.size() > 64) {
ubi_512(m_buffer.data(), m_buffer.size());
BufferSlicer in(input);

input = input.last(input.size() - 64 + m_buf_pos);
m_buf_pos = 0;
while(!in.empty()) {
if(const auto one_block = m_buffer.handle_unaligned_data(in)) {
ubi_512(one_block->data(), one_block->size());
}
}

const size_t full_blocks = (input.size() - 1) / 64;
BufferSlicer in(input);

if(full_blocks) {
const auto blocks = in.take(64 * full_blocks);
ubi_512(blocks.data(), blocks.size());
if(m_buffer.in_alignment()) {
const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in);
if(full_blocks > 0) {
ubi_512(aligned_data.data(), aligned_data.size());
}
}
}

const auto remaining = in.take(in.remaining());
buffer_insert(m_buffer, m_buf_pos, remaining.data(), remaining.size());
m_buf_pos += remaining.size();
}

void Skein_512::final_result(std::span<uint8_t> out) {
m_T[1] |= (static_cast<uint64_t>(1) << 63); // final block flag

for(size_t i = m_buf_pos; i != m_buffer.size(); ++i) {
m_buffer[i] = 0;
}

ubi_512(m_buffer.data(), m_buf_pos);
const auto pos = m_buffer.elements_in_buffer();
m_buffer.fill_up_with_zeros();
ubi_512(m_buffer.consume().data(), pos);

const uint8_t counter[8] = {0};

Expand All @@ -163,7 +146,6 @@ void Skein_512::final_result(std::span<uint8_t> out) {

copy_out_vec_le(out.data(), m_output_bits / 8, m_threefish->m_K);

m_buf_pos = 0;
initial_block();
}

Expand Down
5 changes: 3 additions & 2 deletions src/lib/hash/skein/skein_512.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#define BOTAN_SKEIN_512_H_

#include <botan/hash.h>
#include <botan/internal/alignment_buffer.h>
#include <botan/internal/threefish_512.h>

#include <memory>
#include <string>

Expand Down Expand Up @@ -61,8 +63,7 @@ class Skein_512 final : public HashFunction {

std::unique_ptr<Threefish_512> m_threefish;
secure_vector<uint64_t> m_T;
secure_vector<uint8_t> m_buffer;
size_t m_buf_pos;
AlignmentBuffer<uint8_t, 64, AlignmentBufferFinalBlock::must_be_deferred> m_buffer;
};

} // namespace Botan
Expand Down
Loading