Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
aes128.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Khashayar], commit: 21476601b111f046f023474465598843e4cfd8ac}
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#include "aes128.hpp"
8
10#include "memory.h"
11#include <array>
12#include <cstddef>
13#include <cstdint>
14
15namespace {
16
17static constexpr uint8_t round_constants[11] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
18
19inline void add_round_key(uint8_t* state, const uint8_t* round_key, const size_t round)
20{
21 for (size_t i = 0; i < 16; i += 4) {
22 for (size_t j = 0; j < 4; ++j) {
23 state[i + j] ^= round_key[(round * 16U) + i + j];
24 }
25 }
26}
27
28inline void xor_with_iv(uint8_t* state, const uint8_t* iv)
29{
30 for (size_t i = 0; i < 16; ++i) {
31 state[i] ^= iv[i];
32 }
33}
34
35void sub_bytes(uint8_t* input)
36{
37 uint8_t i, j;
38 for (i = 0; i < 4; ++i) {
39 for (j = 0; j < 4; ++j) {
40 input[j * 4 + i] = bb::crypto::aes128_sbox[input[j * 4 + i]];
41 }
42 }
43}
44
45void inverse_sub_bytes(uint8_t* input)
46{
47 for (size_t i = 0; i < 4; ++i) {
48 for (size_t j = 0; j < 4; ++j) {
49 input[j * 4 + i] = bb::crypto::aes128_sbox_inverse[input[j * 4 + i]];
50 }
51 }
52}
53
54void shift_rows(uint8_t* input)
55{
56 uint8_t temp;
57
58 temp = input[0 * 4 + 1];
59 input[0 * 4 + 1] = input[1 * 4 + 1];
60 input[1 * 4 + 1] = input[2 * 4 + 1];
61 input[2 * 4 + 1] = input[3 * 4 + 1];
62 input[3 * 4 + 1] = temp;
63
64 temp = input[0 * 4 + 2];
65 input[0 * 4 + 2] = input[2 * 4 + 2];
66 input[2 * 4 + 2] = temp;
67
68 temp = input[1 * 4 + 2];
69 input[1 * 4 + 2] = input[3 * 4 + 2];
70 input[3 * 4 + 2] = temp;
71
72 temp = input[0 * 4 + 3];
73 input[0 * 4 + 3] = input[3 * 4 + 3];
74 input[3 * 4 + 3] = input[2 * 4 + 3];
75 input[2 * 4 + 3] = input[1 * 4 + 3];
76 input[1 * 4 + 3] = temp;
77}
78
79static void inverse_shift_rows(uint8_t* input)
80{
81 uint8_t temp;
82
83 temp = input[3 * 4 + 1];
84 input[3 * 4 + 1] = input[2 * 4 + 1];
85 input[2 * 4 + 1] = input[1 * 4 + 1];
86 input[1 * 4 + 1] = input[0 * 4 + 1];
87 input[0 * 4 + 1] = temp;
88
89 temp = input[0 * 4 + 2];
90 input[0 * 4 + 2] = input[2 * 4 + 2];
91 input[2 * 4 + 2] = temp;
92
93 temp = input[1 * 4 + 2];
94 input[1 * 4 + 2] = input[3 * 4 + 2];
95 input[3 * 4 + 2] = temp;
96
97 temp = input[0 * 4 + 3];
98 input[0 * 4 + 3] = input[1 * 4 + 3];
99 input[1 * 4 + 3] = input[2 * 4 + 3];
100 input[2 * 4 + 3] = input[3 * 4 + 3];
101 input[3 * 4 + 3] = temp;
102}
103
104uint8_t xtime(const uint8_t x)
105{
106 return static_cast<uint8_t>((x << 1) ^ (((x >> 7) & 1) * 0x1b));
107}
108
109uint8_t gf2_8_mul(const uint8_t x, const uint8_t y)
110{
111 const uint8_t t0 = (uint8_t)((y & (uint8_t)1) * x);
112 const uint8_t t1 = (uint8_t)(((y >> (uint8_t)1) & (uint8_t)1) * xtime(x));
113 const uint8_t t2 = (uint8_t)(((y >> (uint8_t)2) & (uint8_t)1) * xtime(xtime(x)));
114 const uint8_t t3 = (uint8_t)(((y >> (uint8_t)3) & (uint8_t)1) * xtime(xtime(xtime(x))));
115 const uint8_t t4 = (uint8_t)(((y >> (uint8_t)4) & (uint8_t)1) * xtime(xtime(xtime(xtime(x)))));
116
117 uint8_t out = t0 ^ t1 ^ t2 ^ t3 ^ t4;
118 return out;
119}
120
121void mix_columns(uint8_t* input)
122{
123 for (uint8_t i = 0; i < 4; ++i) {
124 uint8_t t = input[i * 4 + 0];
125 uint8_t Tmp = input[i * 4 + 0] ^ input[i * 4 + 1] ^ input[i * 4 + 2] ^ input[i * 4 + 3];
126 uint8_t Tm = input[i * 4 + 0] ^ input[i * 4 + 1];
127 Tm = xtime(Tm);
128 input[i * 4 + 0] ^= Tm ^ Tmp;
129 Tm = input[i * 4 + 1] ^ input[i * 4 + 2];
130 Tm = xtime(Tm);
131 input[i * 4 + 1] ^= Tm ^ Tmp;
132 Tm = input[i * 4 + 2] ^ input[i * 4 + 3];
133 Tm = xtime(Tm);
134 input[i * 4 + 2] ^= Tm ^ Tmp;
135 Tm = input[i * 4 + 3] ^ t;
136 Tm = xtime(Tm);
137 input[i * 4 + 3] ^= Tm ^ Tmp;
138 }
139}
140
141void inverse_mix_columns(uint8_t* input)
142{
143 for (uint8_t i = 0; i < 4; ++i) {
144 uint8_t a = input[i * 4 + 0];
145 uint8_t b = input[i * 4 + 1];
146 uint8_t c = input[i * 4 + 2];
147 uint8_t d = input[i * 4 + 3];
148
149 input[i * 4 + 0] = gf2_8_mul(a, 0x0e) ^ gf2_8_mul(b, 0x0b) ^ gf2_8_mul(c, 0x0d) ^ gf2_8_mul(d, 0x09);
150 input[i * 4 + 1] = gf2_8_mul(a, 0x09) ^ gf2_8_mul(b, 0x0e) ^ gf2_8_mul(c, 0x0b) ^ gf2_8_mul(d, 0x0d);
151 input[i * 4 + 2] = gf2_8_mul(a, 0x0d) ^ gf2_8_mul(b, 0x09) ^ gf2_8_mul(c, 0x0e) ^ gf2_8_mul(d, 0x0b);
152 input[i * 4 + 3] = gf2_8_mul(a, 0x0b) ^ gf2_8_mul(b, 0x0d) ^ gf2_8_mul(c, 0x09) ^ gf2_8_mul(d, 0x0e);
153 }
154}
155} // namespace
156
157namespace bb::crypto {
158
159void aes128_expand_key(const uint8_t* key, uint8_t* round_key)
160{
161 uint8_t temp[4]{};
162
163 for (size_t i = 0; i < 16; i += 4) {
164 round_key[i] = key[i];
165 round_key[i + 1] = key[i + 1];
166 round_key[i + 2] = key[i + 2];
167 round_key[i + 3] = key[i + 3];
168 }
169
170 for (size_t i = 4; i < 44; ++i) {
171 size_t k = (i - 1) * 4;
172 temp[0] = round_key[k];
173 temp[1] = round_key[k + 1];
174 temp[2] = round_key[k + 2];
175 temp[3] = round_key[k + 3];
176
177 if ((i & 0x03) == 0) {
178 const uint8_t t = temp[0];
179 temp[0] = temp[1];
180 temp[1] = temp[2];
181 temp[2] = temp[3];
182 temp[3] = t;
183
184 temp[0] = aes128_sbox[temp[0]];
185 temp[1] = aes128_sbox[temp[1]];
186 temp[2] = aes128_sbox[temp[2]];
187 temp[3] = aes128_sbox[temp[3]];
188
189 temp[0] = temp[0] ^ round_constants[i >> 2];
190 }
191 size_t j = i * 4;
192 k = (i - 4) * 4;
193 round_key[j] = round_key[k] ^ temp[0];
194 round_key[j + 1] = round_key[k + 1] ^ temp[1];
195 round_key[j + 2] = round_key[k + 2] ^ temp[2];
196 round_key[j + 3] = round_key[k + 3] ^ temp[3];
197 }
198}
199
200void aes128_inverse_cipher(uint8_t* input, const uint8_t* round_key)
201{
202
203 add_round_key(input, round_key, 10);
204
205 for (size_t round = 9; round > 0; --round) {
206 inverse_shift_rows(input);
207 inverse_sub_bytes(input);
208 add_round_key(input, round_key, round);
209 inverse_mix_columns(input);
210 }
211 inverse_shift_rows(input);
212 inverse_sub_bytes(input);
213 add_round_key(input, round_key, 0);
214}
215
216void aes128_cipher(uint8_t* state, const uint8_t* round_key)
217{
218 add_round_key(state, round_key, 0);
219
220 for (uint8_t round = 1; round < 10; ++round) {
221 sub_bytes(state);
222 shift_rows(state);
223 mix_columns(state);
224 add_round_key(state, round_key, round);
225 }
226
227 sub_bytes(state);
228 shift_rows(state);
229 add_round_key(state, round_key, 10);
230}
231
232void aes128_encrypt_buffer_cbc(uint8_t* buffer, uint8_t* iv, const uint8_t* key, const size_t length)
233{
234 uint8_t round_key[176];
235 aes128_expand_key(key, round_key);
236
237 uint8_t block_state[16]{};
238
239 const size_t num_blocks = (length / 16);
240
241 for (size_t i = 0; i < num_blocks; ++i) {
242 memcpy((void*)block_state, (void*)(buffer + (i * 16)), 16);
243 xor_with_iv(block_state, iv);
244
245 aes128_cipher(block_state, round_key);
246
247 memcpy((void*)(buffer + (i * 16)), (void*)block_state, 16);
248 memcpy((void*)iv, (void*)block_state, 16);
249 }
250 secure_erase_bytes(round_key, sizeof(round_key));
251}
252
253void aes128_decrypt_buffer_cbc(uint8_t* buffer, uint8_t* iv, const uint8_t* key, const size_t length)
254{
255 uint8_t round_key[176];
256 aes128_expand_key(key, round_key);
257 uint8_t block_state[16]{};
258 const size_t num_blocks = (length / 16);
259
260 uint8_t next_iv[16]{};
261 for (size_t i = 0; i < num_blocks; ++i) {
262 memcpy((void*)block_state, (void*)(buffer + (i * 16)), 16);
263 memcpy((void*)next_iv, (void*)block_state, 16);
264 aes128_inverse_cipher(block_state, round_key);
265 xor_with_iv(block_state, iv);
266 memcpy((void*)(buffer + (i * 16)), (void*)block_state, 16);
267 memcpy((void*)iv, (void*)next_iv, 16);
268 }
269 secure_erase_bytes(round_key, sizeof(round_key));
270}
271
272} // namespace bb::crypto
FF a
FF b
uint8_t const size_t length
Definition data_store.hpp:9
std::unique_ptr< uint8_t[]> buffer
Definition engine.cpp:50
constexpr uint32_t round_constants[64]
void aes128_inverse_cipher(uint8_t *input, const uint8_t *round_key)
Definition aes128.cpp:200
void aes128_decrypt_buffer_cbc(uint8_t *buffer, uint8_t *iv, const uint8_t *key, const size_t length)
Definition aes128.cpp:253
void aes128_expand_key(const uint8_t *key, uint8_t *round_key)
Definition aes128.cpp:159
void aes128_cipher(uint8_t *state, const uint8_t *round_key)
Definition aes128.cpp:216
void aes128_encrypt_buffer_cbc(uint8_t *buffer, uint8_t *iv, const uint8_t *key, const size_t length)
Definition aes128.cpp:232
void secure_erase_bytes(void *ptr, size_t size)
Definition hmac.hpp:18
void sub_bytes(Builder *ctx, state_span< Builder > state_pairs)
Definition aes128.cpp:305
void shift_rows(state_span< Builder > state)
The SHIFTROW() operation as in FIPS 197, Section 5.1.2.
Definition aes128.cpp:213
void add_round_key(state_span< Builder > sparse_state, key_span< Builder > sparse_round_key, size_t round)
Definition aes128.cpp:313
void xor_with_iv(state_span< Builder > state, block_span< Builder > iv)
Definition aes128.cpp:323