Botan 3.13.0
Crypto and TLS for C&
salsa20_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/salsa20.h>
8
9#include <botan/assert.h>
10#include <botan/internal/simd_4x32.h>
11
12namespace Botan {
13
14//static
15void BOTAN_FN_ISA_SIMD_4X32 Salsa20::salsa20_simd32_x4(uint8_t output[64 * 4], uint32_t state[16], size_t rounds) {
16 BOTAN_ASSERT(rounds % 2 == 0, "Valid rounds");
17
18 const SIMD_4x32 CTR_LO = SIMD_4x32::splat(state[8]) + SIMD_4x32(0, 1, 2, 3);
19 // Carry into the high counter word for lanes whose low word wrapped
20 const SIMD_4x32 CTR_HI = SIMD_4x32::splat(state[9]) - CTR_LO.unsigned_lt(SIMD_4x32::splat(state[8]));
21
22 SIMD_4x32 R00 = SIMD_4x32::splat(state[0]);
23 SIMD_4x32 R01 = SIMD_4x32::splat(state[1]);
24 SIMD_4x32 R02 = SIMD_4x32::splat(state[2]);
25 SIMD_4x32 R03 = SIMD_4x32::splat(state[3]);
26 SIMD_4x32 R04 = SIMD_4x32::splat(state[4]);
27 SIMD_4x32 R05 = SIMD_4x32::splat(state[5]);
28 SIMD_4x32 R06 = SIMD_4x32::splat(state[6]);
29 SIMD_4x32 R07 = SIMD_4x32::splat(state[7]);
30 SIMD_4x32 R08 = CTR_LO;
31 SIMD_4x32 R09 = CTR_HI;
32 SIMD_4x32 R10 = SIMD_4x32::splat(state[10]);
33 SIMD_4x32 R11 = SIMD_4x32::splat(state[11]);
34 SIMD_4x32 R12 = SIMD_4x32::splat(state[12]);
35 SIMD_4x32 R13 = SIMD_4x32::splat(state[13]);
36 SIMD_4x32 R14 = SIMD_4x32::splat(state[14]);
37 SIMD_4x32 R15 = SIMD_4x32::splat(state[15]);
38
39 for(size_t r = 0; r != rounds / 2; ++r) {
40 R04 ^= (R00 + R12).rotl<7>();
41 R09 ^= (R05 + R01).rotl<7>();
42 R14 ^= (R10 + R06).rotl<7>();
43 R03 ^= (R15 + R11).rotl<7>();
44
45 R08 ^= (R04 + R00).rotl<9>();
46 R13 ^= (R09 + R05).rotl<9>();
47 R02 ^= (R14 + R10).rotl<9>();
48 R07 ^= (R03 + R15).rotl<9>();
49
50 R12 ^= (R08 + R04).rotl<13>();
51 R01 ^= (R13 + R09).rotl<13>();
52 R06 ^= (R02 + R14).rotl<13>();
53 R11 ^= (R07 + R03).rotl<13>();
54
55 R00 ^= (R12 + R08).rotl<18>();
56 R05 ^= (R01 + R13).rotl<18>();
57 R10 ^= (R06 + R02).rotl<18>();
58 R15 ^= (R11 + R07).rotl<18>();
59
60 R01 ^= (R00 + R03).rotl<7>();
61 R06 ^= (R05 + R04).rotl<7>();
62 R11 ^= (R10 + R09).rotl<7>();
63 R12 ^= (R15 + R14).rotl<7>();
64
65 R02 ^= (R01 + R00).rotl<9>();
66 R07 ^= (R06 + R05).rotl<9>();
67 R08 ^= (R11 + R10).rotl<9>();
68 R13 ^= (R12 + R15).rotl<9>();
69
70 R03 ^= (R02 + R01).rotl<13>();
71 R04 ^= (R07 + R06).rotl<13>();
72 R09 ^= (R08 + R11).rotl<13>();
73 R14 ^= (R13 + R12).rotl<13>();
74
75 R00 ^= (R03 + R02).rotl<18>();
76 R05 ^= (R04 + R07).rotl<18>();
77 R10 ^= (R09 + R08).rotl<18>();
78 R15 ^= (R14 + R13).rotl<18>();
79 }
80
81 R00 += SIMD_4x32::splat(state[0]);
82 R01 += SIMD_4x32::splat(state[1]);
83 R02 += SIMD_4x32::splat(state[2]);
84 R03 += SIMD_4x32::splat(state[3]);
85 R04 += SIMD_4x32::splat(state[4]);
86 R05 += SIMD_4x32::splat(state[5]);
87 R06 += SIMD_4x32::splat(state[6]);
88 R07 += SIMD_4x32::splat(state[7]);
89 R08 += CTR_LO;
90 R09 += CTR_HI;
91 R10 += SIMD_4x32::splat(state[10]);
92 R11 += SIMD_4x32::splat(state[11]);
93 R12 += SIMD_4x32::splat(state[12]);
94 R13 += SIMD_4x32::splat(state[13]);
95 R14 += SIMD_4x32::splat(state[14]);
96 R15 += SIMD_4x32::splat(state[15]);
97
98 SIMD_4x32::transpose(R00, R01, R02, R03);
99 SIMD_4x32::transpose(R04, R05, R06, R07);
100 SIMD_4x32::transpose(R08, R09, R10, R11);
101 SIMD_4x32::transpose(R12, R13, R14, R15);
102
103 R00.store_le(output + 0 * 16);
104 R04.store_le(output + 1 * 16);
105 R08.store_le(output + 2 * 16);
106 R12.store_le(output + 3 * 16);
107 R01.store_le(output + 4 * 16);
108 R05.store_le(output + 5 * 16);
109 R09.store_le(output + 6 * 16);
110 R13.store_le(output + 7 * 16);
111 R02.store_le(output + 8 * 16);
112 R06.store_le(output + 9 * 16);
113 R10.store_le(output + 10 * 16);
114 R14.store_le(output + 11 * 16);
115 R03.store_le(output + 12 * 16);
116 R07.store_le(output + 13 * 16);
117 R11.store_le(output + 14 * 16);
118 R15.store_le(output + 15 * 16);
119
120 state[8] += 4;
121 if(state[8] < 4) {
122 state[9]++;
123 }
124}
125
126} // namespace Botan
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 splat(uint32_t B) noexcept
Definition simd_4x32.h:127
static void BOTAN_FN_ISA_SIMD_4X32 transpose(SIMD_4x32 &B0, SIMD_4x32 &B1, SIMD_4x32 &B2, SIMD_4x32 &B3) noexcept
Definition simd_4x32.h:681
SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 unsigned_lt(const SIMD_4x32 &other) const noexcept
Definition simd_4x32.h:754
BOTAN_FORCE_INLINE constexpr T rotl(T input)
Definition rotate.h:23