Botan 3.11.1
Crypto and TLS for C&
aria_hwaes.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/aria.h>
8
9#include <botan/mem_ops.h>
10#include <botan/internal/isa_extn.h>
11#include <botan/internal/simd_4x32.h>
12#include <botan/internal/simd_hwaes.h>
13
14namespace Botan {
15
16namespace ARIA_HWAES {
17
18namespace {
19
20// ARIA S1 is just the AES sbox
21BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES SIMD_4x32 aria_s1(SIMD_4x32 v) {
22 return hw_aes_sbox(v);
23}
24
25BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES SIMD_4x32 aria_s2(SIMD_4x32 v) {
26 constexpr uint64_t AFF_S2 = gfni_matrix(R"(
27 0 1 0 1 0 1 1 1
28 0 0 1 1 1 1 1 1
29 1 1 1 0 1 1 0 1
30 1 1 0 0 0 0 1 1
31 0 1 0 0 0 0 1 1
32 1 1 0 0 1 1 1 0
33 0 1 1 0 0 0 1 1
34 1 1 1 1 0 1 1 0)");
35
36 constexpr auto POST_S2 = Gf2AffineTransformation::post_sbox(AFF_S2, 0xE2);
37 return POST_S2.affine_transform(hw_aes_sbox(v));
38}
39
40// ARIA X1 is just the AES inverse sbox
41BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES SIMD_4x32 aria_x1(SIMD_4x32 v) {
42 return hw_aes_inv_sbox(v);
43}
44
45BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES SIMD_4x32 aria_x2(SIMD_4x32 v) {
46 constexpr uint64_t AFF_X2 = gfni_matrix(R"(
47 0 0 0 1 1 0 0 0
48 0 0 1 0 0 1 1 0
49 0 0 0 0 1 0 1 0
50 1 1 1 0 0 0 1 1
51 1 1 1 0 1 1 0 0
52 0 1 1 0 1 0 1 1
53 1 0 1 1 1 1 0 1
54 1 0 0 1 0 0 1 1)");
55 constexpr auto PRE_X2D = Gf2AffineTransformation::post_inv_sbox(AFF_X2, 0x2C);
56
57 return hw_aes_inv_sbox(PRE_X2D.affine_transform(v));
58}
59
60BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES SIMD_4x32 aria_fo_m(SIMD_4x32 x) {
61 return x.rotl<8>() ^ x.rotl<16>() ^ x.rotl<24>();
62}
63
64BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES SIMD_4x32 aria_fe_m(SIMD_4x32 x) {
65 return x ^ x.rotl<8>() ^ x.rotl<24>();
66}
67
68BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES void aria_mix(SIMD_4x32& B0, SIMD_4x32& B1, SIMD_4x32& B2, SIMD_4x32& B3) {
69 B1 ^= B2;
70 B2 ^= B3;
71 B0 ^= B1;
72 B3 ^= B1;
73 B2 ^= B0;
74 B1 ^= B2;
75}
76
77BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES SIMD_4x32 swap_abcd_badc(SIMD_4x32 x) {
78 const auto shuf = SIMD_4x32(0x02030001, 0x06070405, 0x0A0B0809, 0x0E0F0C0D);
79 return SIMD_4x32::byte_shuffle(x, shuf);
80}
81
82BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES SIMD_4x32 byte_transpose(SIMD_4x32 v) {
83 const SIMD_4x32 tbl(0x0C080400, 0x0D090501, 0x0E0A0602, 0x0F0B0703);
84 return SIMD_4x32::byte_shuffle(v, tbl);
85}
86
87BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES void aria_fo_sbox(SIMD_4x32& B0, SIMD_4x32& B1, SIMD_4x32& B2, SIMD_4x32& B3) {
88 B0 = byte_transpose(B0);
89 B1 = byte_transpose(B1);
90 B2 = byte_transpose(B2);
91 B3 = byte_transpose(B3);
92 SIMD_4x32::transpose(B0, B1, B2, B3);
93
94 B3 = aria_s1(B3);
95 B2 = aria_s2(B2);
96 B1 = aria_x1(B1);
97 B0 = aria_x2(B0);
98
99 SIMD_4x32::transpose(B0, B1, B2, B3);
100 B0 = byte_transpose(B0);
101 B1 = byte_transpose(B1);
102 B2 = byte_transpose(B2);
103 B3 = byte_transpose(B3);
104}
105
106BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES void aria_fe_sbox(SIMD_4x32& B0, SIMD_4x32& B1, SIMD_4x32& B2, SIMD_4x32& B3) {
107 B0 = byte_transpose(B0);
108 B1 = byte_transpose(B1);
109 B2 = byte_transpose(B2);
110 B3 = byte_transpose(B3);
111 SIMD_4x32::transpose(B0, B1, B2, B3);
112
113 B3 = aria_x1(B3);
114 B2 = aria_x2(B2);
115 B1 = aria_s1(B1);
116 B0 = aria_s2(B0);
117
118 SIMD_4x32::transpose(B0, B1, B2, B3);
119 B0 = byte_transpose(B0);
120 B1 = byte_transpose(B1);
121 B2 = byte_transpose(B2);
122 B3 = byte_transpose(B3);
123}
124
125BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES void aria_fo(SIMD_4x32& B0, SIMD_4x32& B1, SIMD_4x32& B2, SIMD_4x32& B3) {
126 aria_fo_sbox(B0, B1, B2, B3);
127
128 B0 = aria_fo_m(B0);
129 B1 = aria_fo_m(B1);
130 B2 = aria_fo_m(B2);
131 B3 = aria_fo_m(B3);
132
133 aria_mix(B0, B1, B2, B3);
134
135 B1 = swap_abcd_badc(B1);
136 B2 = B2.rotl<16>();
137 B3 = B3.bswap();
138
139 aria_mix(B0, B1, B2, B3);
140}
141
142BOTAN_FORCE_INLINE BOTAN_FN_ISA_HWAES void aria_fe(SIMD_4x32& B0, SIMD_4x32& B1, SIMD_4x32& B2, SIMD_4x32& B3) {
143 aria_fe_sbox(B0, B1, B2, B3);
144
145 B0 = aria_fe_m(B0);
146 B1 = aria_fe_m(B1);
147 B2 = aria_fe_m(B2);
148 B3 = aria_fe_m(B3);
149
150 aria_mix(B0, B1, B2, B3);
151
152 B3 = swap_abcd_badc(B3);
153 B0 = B0.rotl<16>();
154 B1 = B1.bswap();
155
156 aria_mix(B0, B1, B2, B3);
157}
158
159BOTAN_FN_ISA_HWAES void transform_4(const uint8_t in[], uint8_t out[], std::span<const uint32_t> KS) {
160 const size_t ROUNDS = (KS.size() / 4) - 1;
161
162 auto B0 = SIMD_4x32::load_be(in);
163 auto B1 = SIMD_4x32::load_be(in + 16);
164 auto B2 = SIMD_4x32::load_be(in + 32);
165 auto B3 = SIMD_4x32::load_be(in + 48);
166
167 SIMD_4x32::transpose(B0, B1, B2, B3);
168
169 for(size_t r = 0; r != ROUNDS; r += 2) {
170 B0 ^= SIMD_4x32::splat(KS[4 * r]);
171 B1 ^= SIMD_4x32::splat(KS[4 * r + 1]);
172 B2 ^= SIMD_4x32::splat(KS[4 * r + 2]);
173 B3 ^= SIMD_4x32::splat(KS[4 * r + 3]);
174
175 aria_fo(B0, B1, B2, B3);
176
177 B0 ^= SIMD_4x32::splat(KS[4 * r + 4]);
178 B1 ^= SIMD_4x32::splat(KS[4 * r + 5]);
179 B2 ^= SIMD_4x32::splat(KS[4 * r + 6]);
180 B3 ^= SIMD_4x32::splat(KS[4 * r + 7]);
181
182 if(r != ROUNDS - 2) {
183 aria_fe(B0, B1, B2, B3);
184 }
185 }
186
187 // Last half-round: FE sbox only
188 aria_fe_sbox(B0, B1, B2, B3);
189
190 B0 ^= SIMD_4x32::splat(KS[4 * ROUNDS]);
191 B1 ^= SIMD_4x32::splat(KS[4 * ROUNDS + 1]);
192 B2 ^= SIMD_4x32::splat(KS[4 * ROUNDS + 2]);
193 B3 ^= SIMD_4x32::splat(KS[4 * ROUNDS + 3]);
194
195 SIMD_4x32::transpose(B0, B1, B2, B3);
196
197 B0.store_be(out);
198 B1.store_be(out + 16);
199 B2.store_be(out + 32);
200 B3.store_be(out + 48);
201}
202
203void BOTAN_FN_ISA_HWAES aria_transform(const uint8_t in[], uint8_t out[], size_t blocks, std::span<const uint32_t> KS) {
204 while(blocks >= 4) {
205 transform_4(in, out, KS);
206 in += 4 * 16;
207 out += 4 * 16;
208 blocks -= 4;
209 }
210
211 if(blocks > 0) {
212 uint8_t ibuf[4 * 16] = {0};
213 uint8_t obuf[4 * 16] = {0};
214 copy_mem(ibuf, in, blocks * 16);
215 transform_4(ibuf, obuf, KS);
216 copy_mem(out, obuf, blocks * 16);
217 }
218}
219
220} // namespace
221
222} // namespace ARIA_HWAES
223
224void BOTAN_FN_ISA_HWAES ARIA_128::aria_hwaes_encrypt(const uint8_t in[], uint8_t out[], size_t blocks) const {
225 ARIA_HWAES::aria_transform(in, out, blocks, m_ERK);
226}
227
228void BOTAN_FN_ISA_HWAES ARIA_128::aria_hwaes_decrypt(const uint8_t in[], uint8_t out[], size_t blocks) const {
229 ARIA_HWAES::aria_transform(in, out, blocks, m_DRK);
230}
231
232void BOTAN_FN_ISA_HWAES ARIA_192::aria_hwaes_encrypt(const uint8_t in[], uint8_t out[], size_t blocks) const {
233 ARIA_HWAES::aria_transform(in, out, blocks, m_ERK);
234}
235
236void BOTAN_FN_ISA_HWAES ARIA_192::aria_hwaes_decrypt(const uint8_t in[], uint8_t out[], size_t blocks) const {
237 ARIA_HWAES::aria_transform(in, out, blocks, m_DRK);
238}
239
240void BOTAN_FN_ISA_HWAES ARIA_256::aria_hwaes_encrypt(const uint8_t in[], uint8_t out[], size_t blocks) const {
241 ARIA_HWAES::aria_transform(in, out, blocks, m_ERK);
242}
243
244void BOTAN_FN_ISA_HWAES ARIA_256::aria_hwaes_decrypt(const uint8_t in[], uint8_t out[], size_t blocks) const {
245 ARIA_HWAES::aria_transform(in, out, blocks, m_DRK);
246}
247
248} // namespace Botan
static consteval Gf2AffineTransformation post_sbox(uint64_t M, uint8_t c)
Definition simd_hwaes.h:139
static consteval Gf2AffineTransformation post_inv_sbox(uint64_t M, uint8_t c)
Definition simd_hwaes.h:149
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 byte_shuffle(const SIMD_4x32 &tbl, const SIMD_4x32 &idx)
Definition simd_4x32.h:803
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
void BOTAN_FN_ISA_SIMD_4X32 store_be(uint32_t out[4]) const noexcept
Definition simd_4x32.h:223
BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 bswap() const noexcept
Definition simd_4x32.h:576
BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 rotl() const noexcept
Definition simd_4x32.h:329
#define BOTAN_FORCE_INLINE
Definition compiler.h:87
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
consteval uint64_t gfni_matrix(std::string_view s)
Definition gfni_utils.h:17
SIMD_4x32 BOTAN_FN_ISA_HWAES hw_aes_inv_sbox(SIMD_4x32 x)
Definition simd_hwaes.h:37
SIMD_4x32 BOTAN_FN_ISA_HWAES hw_aes_sbox(SIMD_4x32 x)
Definition simd_hwaes.h:19