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