Botan 3.10.0
Crypto and TLS for C&
ascon_perm.cpp
Go to the documentation of this file.
1/*
2* Permutation Ascon_p[rounds] as specified in NIST SP.800-232, Section 3
3* (C) 2025 Jack Lloyd
4* 2025 René Meusel
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/internal/ascon_perm.h>
10
11#include <botan/internal/loadstor.h>
12#include <botan/internal/rotate.h>
13#include <botan/internal/sponge_processing.h>
14#include <botan/internal/stl_util.h>
15
16namespace Botan {
17
18void Ascon_p::absorb(std::span<const uint8_t> input, std::optional<uint8_t> permutation_rounds) {
19 const auto rounds = permutation_rounds.value_or(m_processing_rounds);
20 absorb_into_sponge(*this, input, [this, rounds] { permute(rounds); });
21}
22
23void Ascon_p::squeeze(std::span<uint8_t> output) {
24 squeeze_from_sponge(*this, output);
25}
26
27void Ascon_p::percolate_in(std::span<uint8_t> data) {
28 BufferSlicer input_slicer(data);
29 BufferStuffer output_stuffer(data);
30
31 process_bytes_in_sponge(*this, data.size(), [&](uint64_t state_word, auto bounds) {
32 state_word ^= bounds.read_from(input_slicer);
33 bounds.write_into(output_stuffer, state_word);
34 return state_word;
35 });
36
37 BOTAN_ASSERT_NOMSG(input_slicer.empty());
38 BOTAN_ASSERT_NOMSG(output_stuffer.full());
39}
40
41void Ascon_p::percolate_out(std::span<uint8_t> data) {
42 BufferSlicer input_slicer(data);
43 BufferStuffer output_stuffer(data);
44
45 process_bytes_in_sponge(*this, data.size(), [&](uint64_t state_word, auto bounds) {
46 const auto input_word = bounds.read_from(input_slicer);
47 bounds.write_into(output_stuffer, state_word ^ input_word);
48 return bounds.masked_assignment(state_word, input_word);
49 });
50
51 BOTAN_ASSERT_NOMSG(input_slicer.empty());
52 BOTAN_ASSERT_NOMSG(output_stuffer.full());
53}
54
55void Ascon_p::finish(uint8_t rounds) {
56 // NIST SP.800-232, Section 2.1 (Algorithm 2 "pad()")
57
58 // The padding is defined as:
59 // 1. The first padding bit is set to 1
60 // 2. The remaining bits are set to 0
61 constexpr std::array<uint8_t, state_bytes()> padding{0x01};
62
63 // We must always add a padded final input block, if the last verbatim
64 // input block aligned with the byte rate, the final block may be just
65 // padding bytes, otherwise the final block is padded as needed.
66
67 absorb(std::span{padding}.first(byte_rate() - cursor()), rounds);
69}
70
71void Ascon_p::permute(uint8_t rounds) {
72 BOTAN_DEBUG_ASSERT(rounds <= 16);
73
74 auto& S = state();
75
76 // NIST SP.800-232, Table 5
77 constexpr std::array<uint64_t, 16> round_constants = {
78 0x3c, 0x2d, 0x1e, 0x0f, 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69, 0x5a, 0x4b};
79
80 for(uint8_t i = 0; i < rounds; ++i) {
81 // Constant addition layer p_C
82 // NIST SP.800-232, Section 3.2
83 S[2] ^= round_constants[16 - rounds + i];
84
85 // Substitution layer p_S
86 // NIST SP.800-232, Section 3.3, most notably Figure 3
87 S[0] ^= S[4];
88 S[4] ^= S[3];
89 S[2] ^= S[1];
90 auto tmp = S;
91 tmp[0] = ~tmp[0] & S[1];
92 tmp[1] = ~tmp[1] & S[2];
93 tmp[2] = ~tmp[2] & S[3];
94 tmp[3] = ~tmp[3] & S[4];
95 tmp[4] = ~tmp[4] & S[0];
96 S[0] ^= tmp[1];
97 S[1] ^= tmp[2];
98 S[2] ^= tmp[3];
99 S[3] ^= tmp[4];
100 S[4] ^= tmp[0];
101 S[1] ^= S[0];
102 S[0] ^= S[4];
103 S[3] ^= S[2];
104 S[2] = ~S[2];
105
106 // Linear diffusion layer p_L
107 // NIST SP.800-232, Section 3.4
108 S[0] = S[0] ^ rotr<19>(S[0]) ^ rotr<28>(S[0]);
109 S[1] = S[1] ^ rotr<61>(S[1]) ^ rotr<39>(S[1]);
110 S[2] = S[2] ^ rotr<1>(S[2]) ^ rotr<6>(S[2]);
111 S[3] = S[3] ^ rotr<10>(S[3]) ^ rotr<17>(S[3]);
112 S[4] = S[4] ^ rotr<7>(S[4]) ^ rotr<41>(S[4]);
113 }
114}
115
116} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
void squeeze(std::span< uint8_t > output)
void absorb(std::span< const uint8_t > input, std::optional< uint8_t > permutation_rounds=std::nullopt)
void percolate_in(std::span< uint8_t > data)
void percolate_out(std::span< uint8_t > data)
bool empty() const
Definition stl_util.h:120
Helper class to ease in-place marshalling of concatenated fixed-length values.
Definition stl_util.h:133
constexpr bool full() const
Definition stl_util.h:178
static constexpr size_t state_bytes()
Definition sponge.h:44
constexpr auto & state()
Definition sponge.h:56
constexpr size_t byte_rate() const
Definition sponge.h:50
size_t cursor() const
Definition sponge.h:58
BOTAN_FORCE_INLINE void process_bytes_in_sponge(SpongeT &sponge, size_t bytes_to_process, const detail::PermutationFn auto &permutation_fn, const detail::ModifierFn< SpongeT > auto &modifier_fn)
BOTAN_FORCE_INLINE constexpr T rotr(T input)
Definition rotate.h:35
void squeeze_from_sponge(SpongeT &sponge, std::span< uint8_t > output, const detail::PermutationFn auto &permutation_fn)
void absorb_into_sponge(SpongeT &sponge, std::span< const uint8_t > input, const detail::PermutationFn auto &permutation_fn)