Botan 3.11.1
Crypto and TLS for C&
ctr_avx2.cpp
Go to the documentation of this file.
1/*
2* (C) 2026 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#include <botan/internal/ctr.h>
8
9#include <botan/assert.h>
10#include <botan/internal/simd_avx2.h>
11
12namespace Botan {
13
14BOTAN_FN_ISA_AVX2
15size_t CTR_BE::ctr_proc_bs16_ctr4_avx2(const uint8_t* in, uint8_t* out, size_t length) {
16 BOTAN_ASSERT_NOMSG(m_pad.size() % 64 == 0);
17 BOTAN_DEBUG_ASSERT(m_counter.size() == m_pad.size());
18
19 const size_t pad_size = m_pad.size();
20 if(length < pad_size) {
21 return 0;
22 }
23
24 const size_t ctr_blocks = m_ctr_blocks;
25
26 /*
27 * Byte swap table that swaps only the counter bytes and not the nonce bytes
28 */
29 const SIMD_8x32 bswap_ctr(
30 0x03020100, 0x07060504, 0x0B0A0908, 0x0C0D0E0F, 0x03020100, 0x07060504, 0x0B0A0908, 0x0C0D0E0F);
31
32 // Load the starting counter value, bswap the counter field itself so we can add
33 const SIMD_8x32 starting_ctr = SIMD_8x32::byte_shuffle(SIMD_8x32::load_le128(m_counter.data()), bswap_ctr);
34
35 // Counter is incremented 4 blocks at a time (2 per register, 2 registers)
36 const SIMD_8x32 inc4(0, 0, 0, 4);
37
38 const uint32_t N = static_cast<uint32_t>(ctr_blocks);
39 SIMD_8x32 batch_ctr0 = starting_ctr + SIMD_8x32(0, 0, 0, N, 0, 0, 0, N + 1);
40 SIMD_8x32 batch_ctr1 = starting_ctr + SIMD_8x32(0, 0, 0, N + 2, 0, 0, 0, N + 3);
41 const uint8_t* pad_buf = m_pad.data();
42 uint8_t* ctr_buf = m_counter.data();
43
44 const size_t ctr_block_quads = ctr_blocks / 4;
45
46 size_t processed = 0;
47
48 while(length >= pad_size) {
49 for(size_t i = 0; i != ctr_block_quads; ++i) {
50 const size_t off = i * 64;
51
52 // Store and update the counters
53 SIMD_8x32::byte_shuffle(batch_ctr0, bswap_ctr).store_le(ctr_buf + off);
54 SIMD_8x32::byte_shuffle(batch_ctr1, bswap_ctr).store_le(ctr_buf + off + 32);
55 batch_ctr0 += inc4;
56 batch_ctr1 += inc4;
57
58 const auto p0 = SIMD_8x32::load_le(pad_buf + off);
59 const auto p1 = SIMD_8x32::load_le(pad_buf + off + 32);
60
61 auto i0 = SIMD_8x32::load_le(in + off);
62 auto i1 = SIMD_8x32::load_le(in + off + 32);
63
64 i0 ^= p0;
65 i1 ^= p1;
66
67 i0.store_le(out + off);
68 i1.store_le(out + off + 32);
69 }
70
71 in += pad_size;
72 out += pad_size;
73 length -= pad_size;
74 processed += pad_size;
75
76 // Regenerate the pad buffer
77 m_cipher->encrypt_n(m_counter.data(), m_pad.data(), ctr_blocks);
78 }
79
80 return processed;
81}
82
83} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
static BOTAN_FN_ISA_AVX2 SIMD_8x32 load_le128(const uint8_t *in) noexcept
Definition simd_avx2.h:71
static BOTAN_FN_ISA_AVX2 SIMD_8x32 load_le(const uint8_t *in) noexcept
Definition simd_avx2.h:61
static SIMD_8x32 BOTAN_FN_ISA_AVX2 byte_shuffle(const SIMD_8x32 &tbl, const SIMD_8x32 &idx)
Definition simd_avx2.h:330
BOTAN_FN_ISA_AVX2 void store_le(uint8_t out[]) const noexcept
Definition simd_avx2.h:84