Skip to content

Commit

Permalink
Merge pull request #3693 from Rohde-Schwarz/refactor/alignment_buffer
Browse files Browse the repository at this point in the history
Refactor: AlignmentBuffer<> helper for block-oriented Hashes
  • Loading branch information
randombit committed Sep 19, 2023
2 parents a8d4d18 + 66438aa commit 1f26e75
Show file tree
Hide file tree
Showing 12 changed files with 672 additions and 151 deletions.
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();

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

0 comments on commit 1f26e75

Please sign in to comment.