Botan 3.4.0
Crypto and TLS for C&
shake_cipher.cpp
Go to the documentation of this file.
1/*
2 * SHAKE-128 and SHAKE-256
3 * (C) 2016 Jack Lloyd
4 * 2022 René Meusel, Michael Boric - Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9#include <botan/internal/shake_cipher.h>
10
11#include <botan/exceptn.h>
12#include <botan/mem_ops.h>
13
14namespace Botan {
15
16SHAKE_Cipher::SHAKE_Cipher(size_t keccak_capacity) :
17 m_keccak(keccak_capacity, 0xF, 4),
18 m_has_keying_material(false),
19 m_keystream_buffer(buffer_size()),
20 m_bytes_generated(0) {}
21
22void SHAKE_Cipher::set_iv_bytes(const uint8_t /*iv*/[], size_t length) {
23 /*
24 * This could be supported in some way (say, by treating iv as
25 * a prefix or suffix of the key).
26 */
27 if(length != 0) {
28 throw Invalid_IV_Length(name(), length);
29 }
30}
31
32void SHAKE_Cipher::seek(uint64_t /*offset*/) {
33 throw Not_Implemented("SHAKE_Cipher::seek");
34}
35
37 m_keccak.clear();
38 m_has_keying_material = false;
39 zeroise(m_keystream_buffer);
40 m_bytes_generated = 0;
41}
42
43void SHAKE_Cipher::cipher_bytes(const uint8_t in[], uint8_t out[], size_t length) {
45
46 const auto block_size = m_keystream_buffer.size();
47
48 auto cipher_some = [&](size_t bytes) {
49 if(bytes > 0) {
50 BOTAN_ASSERT_NOMSG(bytes <= block_size);
51 BOTAN_ASSERT_NOMSG(bytes <= length);
52 generate_keystream_internal(std::span(m_keystream_buffer).first(bytes));
53 xor_buf(out, m_keystream_buffer.data(), in, bytes);
54 out += bytes;
55 in += bytes;
56 length -= bytes;
57 }
58 };
59
60 // Bring us back into alignment with the XOF's underlying blocks
61 if(length > block_size) {
62 const auto bytes_to_alignment = block_size - m_bytes_generated % block_size;
63 cipher_some(bytes_to_alignment);
64 }
65
66 // Consume the XOF's output stream block-wise as long as we can
67 while(length >= block_size) {
68 cipher_some(block_size);
69 }
70
71 // Process remaining data, potentially causing misalignment
72 cipher_some(length);
73}
74
75void SHAKE_Cipher::generate_keystream(uint8_t out[], size_t length) {
77 generate_keystream_internal({out, length});
78}
79
80void SHAKE_Cipher::generate_keystream_internal(std::span<uint8_t> out) {
81 m_keccak.squeeze(out);
82 m_bytes_generated += out.size();
83}
84
85void SHAKE_Cipher::key_schedule(std::span<const uint8_t> key) {
86 clear();
87 m_keccak.absorb(key);
88 m_keccak.finish();
89 m_has_keying_material = true;
90}
91
95
97
99
100} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
void squeeze(std::span< uint8_t > output)
Expand output data from the current Keccak state.
void absorb(std::span< const uint8_t > input)
Absorb input data into the Keccak sponge.
void finish()
Add final padding (as provided in the constructor) and permute.
Key_Length_Specification key_spec() const final
SHAKE_Cipher(size_t keccak_capacity)
void seek(uint64_t offset) final
virtual std::string name() const =0
void assert_key_material_set() const
Definition sym_algo.h:139
void zeroise(std::vector< T, Alloc > &vec)
Definition secmem.h:108
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
Definition mem_ops.h:343