77 constexpr uint8_t round_constants[11] = { 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
79 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[0]))),
80 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[1]))),
81 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[2]))),
82 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[3]))),
83 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[4]))),
84 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[5]))),
85 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[6]))),
86 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[7]))),
87 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[8]))),
88 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[9]))),
89 field_t(ctx,
fr(numeric::map_into_sparse_form<AES128_BASE>(round_constants[10]))),
96 uint64_t temp_add_counts[4]{};
97 uint64_t add_counts[176]{};
98 for (
size_t i = 0; i < 176; ++i) {
101 for (
size_t i = 0; i < 16; ++i) {
102 round_key[i] = sparse_key[i];
105 for (
size_t i = 4; i < 44; ++i) {
106 size_t k = (i - 1) * 4;
108 temp_add_counts[0] = add_counts[k + 0];
109 temp_add_counts[1] = add_counts[k + 1];
110 temp_add_counts[2] = add_counts[k + 2];
111 temp_add_counts[3] = add_counts[k + 3];
113 temp[0] = round_key[k];
114 temp[1] = round_key[k + 1];
115 temp[2] = round_key[k + 2];
116 temp[3] = round_key[k + 3];
118 if ((i & 0x03) == 0) {
119 const auto t = temp[0];
130 temp[0] = temp[0] + sparse_round_constants[i >> 2];
132 ++temp_add_counts[0];
137 round_key[j] = round_key[k] + temp[0];
138 round_key[j + 1] = round_key[k + 1] + temp[1];
139 round_key[j + 2] = round_key[k + 2] + temp[2];
140 round_key[j + 3] = round_key[k + 3] + temp[3];
142 add_counts[j] = add_counts[k] + temp_add_counts[0];
143 add_counts[j + 1] = add_counts[k + 1] + temp_add_counts[1];
144 add_counts[j + 2] = add_counts[k + 2] + temp_add_counts[2];
145 add_counts[j + 3] = add_counts[k + 3] + temp_add_counts[3];
147 constexpr uint64_t target = 3;
148 if (add_counts[j] > target || (add_counts[j] > 1 && (j & 12) == 12)) {
152 if (add_counts[j + 1] > target || (add_counts[j + 1] > 1 && ((j + 1) & 12) == 12)) {
154 add_counts[j + 1] = 1;
156 if (add_counts[j + 2] > target || (add_counts[j + 2] > 1 && ((j + 2) & 12) == 12)) {
158 add_counts[j + 2] = 1;
160 if (add_counts[j + 3] > target || (add_counts[j + 3] > 1 && ((j + 3) & 12) == 12)) {
162 add_counts[j + 3] = 1;
195 auto t0 = column_pairs[0].first.add_two(column_pairs[3].first, column_pairs[1].second);
196 auto t1 = column_pairs[1].first.add_two(column_pairs[2].first, column_pairs[3].second);
198 auto r0 = t0.add_two(column_pairs[2].first, column_pairs[0].second);
199 auto r1 = t0.add_two(column_pairs[1].first, column_pairs[2].second);
200 auto r2 = t1.add_two(column_pairs[0].first, column_pairs[2].second);
201 auto r3 = t1.add_two(column_pairs[0].second, column_pairs[3].first);
203 column_pairs[0].first = r0 + round_key[(round * 16U)];
204 column_pairs[1].first = r1 + round_key[(round * 16U) + 1];
205 column_pairs[2].first = r2 + round_key[(round * 16U) + 2];
206 column_pairs[3].first = r3 + round_key[(round * 16U) + 3];
271 for (
const auto& input_block : input) {
272 if (!input_block.is_constant()) {
273 all_constants =
false;
281 std::vector<uint8_t> key_bytes(16);
282 std::vector<uint8_t> iv_bytes(16);
283 std::vector<uint8_t> input_bytes(input.size() * 16);
287 for (
size_t i = 0; i < 16; ++i) {
288 key_bytes[15 - i] =
static_cast<uint8_t
>((key_value >> (i * 8)) & 0xFF);
293 for (
size_t i = 0; i < 16; ++i) {
294 iv_bytes[15 - i] =
static_cast<uint8_t
>((iv_value >> (i * 8)) & 0xFF);
298 for (
size_t block_idx = 0; block_idx < input.size(); ++block_idx) {
299 uint256_t block_value = input[block_idx].get_value();
300 for (
size_t i = 0; i < 16; ++i) {
301 input_bytes[block_idx * 16 + 15 - i] =
static_cast<uint8_t
>((block_value >> (i * 8)) & 0xFF);
309 for (
size_t block_idx = 0; block_idx < input.size(); ++block_idx) {
311 for (
size_t i = 0; i < 16; ++i) {
313 result_value += input_bytes[block_idx * 16 + i];
323 if (!
key.is_constant()) {
324 ctx =
key.get_context();
328 for (
const auto& input_block : input) {
329 if (!input_block.is_constant()) {
330 ctx = input_block.get_context();
340 const size_t num_blocks = input.size();
343 for (
size_t i = 0; i < num_blocks; ++i) {
345 for (
const auto&
byte : bytes) {
346 sparse_state.push_back({ byte,
field_t(ctx,
fr(0)) });
352 for (
size_t i = 0; i < num_blocks; ++i) {
357 for (
size_t j = 0; j < 16; ++j) {
358 sparse_iv[j] = round_state[j].first;
363 for (
auto&
element : sparse_state) {
368 for (
size_t i = 0; i < num_blocks; ++i) {