Botan 3.11.1
Crypto and TLS for C&
ctr_simd32.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_4x32.h>
11
12namespace Botan {
13
14BOTAN_FN_ISA_SIMD_4X32
15size_t CTR_BE::ctr_proc_bs16_ctr4_simd32(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 // Load the starting counter as big-endian 32-bit words.
27 // Word 3 (bytes 12-15) contains the counter value in native form.
28 const SIMD_4x32 starting_ctr = SIMD_4x32::load_be(m_counter.data());
29
30 const uint32_t N = static_cast<uint32_t>(ctr_blocks);
31
32 // Initialize 4 counter registers for 4-way unrolled processing
33 SIMD_4x32 ctr0 = starting_ctr + SIMD_4x32(0, 0, 0, N);
34 SIMD_4x32 ctr1 = starting_ctr + SIMD_4x32(0, 0, 0, N + 1);
35 SIMD_4x32 ctr2 = starting_ctr + SIMD_4x32(0, 0, 0, N + 2);
36 SIMD_4x32 ctr3 = starting_ctr + SIMD_4x32(0, 0, 0, N + 3);
37 const SIMD_4x32 inc4 = SIMD_4x32(0, 0, 0, 4);
38
39 const uint8_t* pad_buf = m_pad.data();
40 uint8_t* ctr_buf = m_counter.data();
41
42 const size_t ctr_block_quads = ctr_blocks / 4;
43
44 size_t processed = 0;
45
46 while(length >= pad_size) {
47 for(size_t i = 0; i != ctr_block_quads; ++i) {
48 const size_t off = i * 64;
49
50 // Store and update the counter
51 ctr0.store_be(ctr_buf + off);
52 ctr1.store_be(ctr_buf + off + 16);
53 ctr2.store_be(ctr_buf + off + 32);
54 ctr3.store_be(ctr_buf + off + 48);
55 ctr0 += inc4;
56 ctr1 += inc4;
57 ctr2 += inc4;
58 ctr3 += inc4;
59
60 // Load and XOR the pad with the input blocks
61 auto p0 = SIMD_4x32::load_le(pad_buf + off);
62 auto p1 = SIMD_4x32::load_le(pad_buf + off + 16);
63 auto p2 = SIMD_4x32::load_le(pad_buf + off + 32);
64 auto p3 = SIMD_4x32::load_le(pad_buf + off + 48);
65
66 p0 ^= SIMD_4x32::load_le(in + off);
67 p1 ^= SIMD_4x32::load_le(in + off + 16);
68 p2 ^= SIMD_4x32::load_le(in + off + 32);
69 p3 ^= SIMD_4x32::load_le(in + off + 48);
70
71 p0.store_le(out + off);
72 p1.store_le(out + off + 16);
73 p2.store_le(out + off + 32);
74 p3.store_le(out + off + 48);
75 }
76
77 in += pad_size;
78 out += pad_size;
79 length -= pad_size;
80 processed += pad_size;
81
82 // Regenerate the pad buffer
83 m_cipher->encrypt_n(m_counter.data(), m_pad.data(), ctr_blocks);
84 }
85
86 return processed;
87}
88
89} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 load_be(const void *in) noexcept
Definition simd_4x32.h:189
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 load_le(const void *in) noexcept
Definition simd_4x32.h:162