Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
aes128.fuzzer.cpp
Go to the documentation of this file.
1#include "aes128.hpp"
5#include <cassert>
6#include <cstdint>
7#include <vector>
8
9using namespace bb;
10using namespace bb::stdlib;
11
12// Helper function to create field element as either constant or witness
21
22extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size)
23{
24 if (Size < 33) // Need at least 16 bytes for key + 16 bytes for IV + 1 byte for config
25 return 0;
26
28
29 // Use first byte to determine configuration for key/IV
30 uint8_t config = Data[0];
31 bool key_as_witness = (config & 0x01) != 0;
32 bool iv_as_witness = (config & 0x02) != 0;
33
34 // Extract key (bytes 1-16)
35 std::vector<uint8_t> key_vec(Data + 1, Data + 17);
36
37 // Extract IV (bytes 17-32)
38 std::vector<uint8_t> iv_vec(Data + 17, Data + 33);
39
40 // Remaining data: per-block config + input data
41 size_t data_offset = 33;
42 size_t num_blocks = (Size > data_offset) ? (Size - data_offset) / 17 : 1;
43 if (num_blocks == 0)
44 num_blocks = 1;
45 // Per-block config (num_blocks bytes)
46 std::vector<uint8_t> block_config;
47 for (size_t i = 0; i < num_blocks; ++i) {
48 if (data_offset + i < Size) {
49 block_config.push_back(Data[data_offset + i]);
50 } else {
51 block_config.push_back(0); // Default to constant
52 }
53 }
54 // Input data (after per-block config)
55 std::vector<uint8_t> input_vec;
56 size_t input_start = data_offset + num_blocks;
57 for (size_t i = 0; i < num_blocks * 16; ++i) {
58 if (input_start + i < Size) {
59 input_vec.push_back(Data[input_start + i]);
60 } else {
61 input_vec.push_back(0);
62 }
63 }
64 // Convert bytes to field elements for circuit with per-block config
65 const auto convert_bytes = [](const std::vector<uint8_t>& data) {
66 uint256_t converted(0);
67 for (uint64_t i = 0; i < 16; ++i) {
68 uint256_t to_add = uint256_t((uint64_t)(data[i])) << uint256_t((15 - i) * 8);
69 converted += to_add;
70 }
71 return converted;
72 };
74 for (size_t i = 0; i < num_blocks; ++i) {
75 auto block_start = std::next(input_vec.begin(), static_cast<ptrdiff_t>(i * 16));
76 auto block_end = std::next(input_vec.begin(), static_cast<ptrdiff_t>((i + 1) * 16));
77 std::vector<uint8_t> block(block_start, block_end);
78 bool as_witness = (block_config[i] & 0x01) != 0;
79 input_field.push_back(create_field_element(builder, convert_bytes(block), as_witness));
80 }
81 field_t<UltraCircuitBuilder> key_field = create_field_element(builder, convert_bytes(key_vec), key_as_witness);
82 field_t<UltraCircuitBuilder> iv_field = create_field_element(builder, convert_bytes(iv_vec), iv_as_witness);
83
84 // Run circuit
85 auto circuit_output = stdlib::aes128::encrypt_buffer_cbc(input_field, iv_field, key_field);
86
87 // Convert circuit output to bytes
88 std::vector<uint8_t> circuit_bytes;
89 for (const auto& field_elem : circuit_output) {
90 uint256_t value = field_elem.get_value();
91 std::vector<uint8_t> block_bytes;
92 for (uint64_t i = 15; i != static_cast<uint64_t>(-1); --i) {
93 block_bytes.push_back(static_cast<uint8_t>((value >> (i * 8)) & 0xFF));
94 }
95 circuit_bytes.insert(circuit_bytes.end(), block_bytes.begin(), block_bytes.end());
96 }
97
98 // Run reference implementation
99 std::vector<uint8_t> ref_input = input_vec;
100 std::vector<uint8_t> ref_iv = iv_vec;
101 crypto::aes128_encrypt_buffer_cbc(ref_input.data(), ref_iv.data(), key_vec.data(), ref_input.size());
102
103 // Compare outputs - ref_input now contains the encrypted data
104 if (circuit_bytes.size() != ref_input.size()) {
105 // This should never happen if our padding logic is correct
106 assert(false && "Circuit and reference output sizes don't match");
107 return 1;
108 }
109
110 for (size_t i = 0; i < circuit_bytes.size(); ++i) {
111 if (circuit_bytes[i] != ref_input[i]) {
112 // This should never happen if our circuit is correct
113 assert(false && "Circuit output doesn't match reference implementation");
114 return 1;
115 }
116 }
117
118 // Verify circuit is valid
120
121 return 0;
122}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
field_t< UltraCircuitBuilder > create_field_element(UltraCircuitBuilder &builder, const uint256_t &value, bool as_witness)
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
AluTraceBuilder builder
Definition alu.test.cpp:123
const std::vector< FF > data
void aes128_encrypt_buffer_cbc(uint8_t *buffer, uint8_t *iv, const uint8_t *key, const size_t length)
Definition aes128.cpp:233
std::vector< field_t< Builder > > encrypt_buffer_cbc(const std::vector< field_t< Builder > > &input, const field_t< Builder > &iv, const field_t< Builder > &key)
Definition aes128.cpp:265
Entry point for Barretenberg command-line interface.
field< Bn254FrParams > fr
Definition fr.hpp:174
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13