Skip to content

Commit

Permalink
feat!: AES blackbox (#6016)
Browse files Browse the repository at this point in the history
Closes #5866

Adds AES128 as a blackbox function, exposing the existing functionality
from barretenberg.

Data is padded using PKCS#7

---------

Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
  • Loading branch information
Thunkar and TomAFrench authored May 7, 2024
1 parent ead54c4 commit e4b97a8
Show file tree
Hide file tree
Showing 51 changed files with 773 additions and 65 deletions.
7 changes: 7 additions & 0 deletions avm-transpiler/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions barretenberg/cpp/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ if(WASM)
$<TARGET_OBJECTS:common_objects>
$<TARGET_OBJECTS:numeric_objects>
$<TARGET_OBJECTS:ecc_objects>
$<TARGET_OBJECTS:crypto_aes128_objects>
$<TARGET_OBJECTS:crypto_blake2s_objects>
$<TARGET_OBJECTS:crypto_keccak_objects>
$<TARGET_OBJECTS:crypto_schnorr_objects>
Expand Down
1 change: 1 addition & 0 deletions barretenberg/cpp/src/barretenberg/dsl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ barretenberg_module(
dsl
plonk
stdlib_sha256
stdlib_aes128
stdlib_keccak
stdlib_poseidon2
crypto_merkle_tree
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ void build_constraints(Builder& builder, AcirFormat const& constraint_system, bo
builder.create_range_constraint(constraint.witness, constraint.num_bits, "");
}

// Add aes128 constraints
for (const auto& constraint : constraint_system.aes128_constraints) {
create_aes128_constraints(builder, constraint);
}

// Add sha256 constraints
for (const auto& constraint : constraint_system.sha256_constraints) {
create_sha256_constraints(builder, constraint);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "aes128_constraint.hpp"
#include "barretenberg/common/slab_allocator.hpp"
#include "barretenberg/serialize/msgpack.hpp"
#include "bigint_constraint.hpp"
Expand Down Expand Up @@ -35,6 +36,7 @@ struct AcirFormat {

std::vector<LogicConstraint> logic_constraints;
std::vector<RangeConstraint> range_constraints;
std::vector<AES128Constraint> aes128_constraints;
std::vector<Sha256Constraint> sha256_constraints;
std::vector<Sha256Compression> sha256_compression;
std::vector<SchnorrConstraint> schnorr_constraints;
Expand Down Expand Up @@ -69,6 +71,7 @@ struct AcirFormat {
public_inputs,
logic_constraints,
range_constraints,
aes128_constraints,
sha256_constraints,
sha256_compression,
schnorr_constraints,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ TEST_F(AcirFormatTests, TestASingleConstraintNoPubInputs)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -151,6 +152,7 @@ TEST_F(AcirFormatTests, TestLogicGateFromNoirCircuit)
.public_inputs = { 1 },
.logic_constraints = { logic_constraint },
.range_constraints = { range_a, range_b },
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -219,6 +221,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifyPass)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = range_constraints,
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = { schnorr_constraint },
Expand Down Expand Up @@ -314,6 +317,7 @@ TEST_F(AcirFormatTests, TestSchnorrVerifySmallRange)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = range_constraints,
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = { schnorr_constraint },
Expand Down Expand Up @@ -428,6 +432,7 @@ TEST_F(AcirFormatTests, TestVarKeccak)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = { range_a, range_b, range_c, range_d },
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -475,6 +480,7 @@ TEST_F(AcirFormatTests, TestKeccakPermutation)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "acir_format.hpp"
#include "barretenberg/common/container.hpp"
#include "barretenberg/common/throw_or_abort.hpp"
#include "barretenberg/dsl/acir_format/aes128_constraint.hpp"
#include "barretenberg/dsl/acir_format/bigint_constraint.hpp"
#include "barretenberg/dsl/acir_format/blake2s_constraint.hpp"
#include "barretenberg/dsl/acir_format/blake3_constraint.hpp"
Expand Down Expand Up @@ -222,6 +223,31 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci
.witness = arg.input.witness.value,
.num_bits = arg.input.num_bits,
});
} else if constexpr (std::is_same_v<T, Program::BlackBoxFuncCall::AES128Encrypt>) {
af.aes128_constraints.push_back(AES128Constraint{
.inputs = map(arg.inputs,
[](auto& e) {
return AES128Input{
.witness = e.witness.value,
.num_bits = e.num_bits,
};
}),
.iv = map(arg.iv,
[](auto& e) {
return AES128Input{
.witness = e.witness.value,
.num_bits = e.num_bits,
};
}),
.key = map(arg.key,
[](auto& e) {
return AES128Input{
.witness = e.witness.value,
.num_bits = e.num_bits,
};
}),
.outputs = map(arg.outputs, [](auto& e) { return e.value; }),
});
} else if constexpr (std::is_same_v<T, Program::BlackBoxFuncCall::SHA256>) {
af.sha256_constraints.push_back(Sha256Constraint{
.inputs = map(arg.inputs,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include "aes128_constraint.hpp"
#include "barretenberg/stdlib/encryption/aes128/aes128.hpp"
#include <cstdint>
#include <cstdio>
#include <span>

namespace acir_format {

template <typename Builder> void create_aes128_constraints(Builder& builder, const AES128Constraint& constraint)
{

using field_ct = bb::stdlib::field_t<Builder>;

// Packs 16 bytes from the inputs (plaintext, iv, key) into a field element
const auto convert_input = [&](std::span<const AES128Input, std::dynamic_extent> inputs, size_t padding) {
field_ct converted = 0;
for (size_t i = 0; i < 16 - padding; ++i) {
converted *= 256;
field_ct byte = field_ct::from_witness_index(&builder, inputs[i].witness);
converted += byte;
}
for (size_t i = 0; i < padding; ++i) {
converted *= 256;
field_ct byte = padding;
converted += byte;
}
return converted;
};

// Packs 16 bytes from the outputs (witness indexes) into a field element for comparison
const auto convert_output = [&](std::span<const uint32_t, 16> outputs) {
field_ct converted = 0;
for (const auto& output : outputs) {
converted *= 256;
field_ct byte = field_ct::from_witness_index(&builder, output);
converted += byte;
}
return converted;
};

const size_t padding_size = 16 - constraint.inputs.size() % 16;

// Perform the conversions from array of bytes to field elements
std::vector<field_ct> converted_inputs;
for (size_t i = 0; i < constraint.inputs.size(); i += 16) {
field_ct to_add;
if (i + 16 > constraint.inputs.size()) {
to_add = convert_input(
std::span<const AES128Input, std::dynamic_extent>{ &constraint.inputs[i], 16 - padding_size },
padding_size);
} else {
to_add = convert_input(std::span<const AES128Input, 16>{ &constraint.inputs[i], 16 }, 0);
}
converted_inputs.emplace_back(to_add);
}

std::vector<field_ct> converted_outputs;
for (size_t i = 0; i < constraint.outputs.size(); i += 16) {
std::span<const uint32_t, 16> outputs{ &constraint.outputs[i], 16 };
converted_outputs.emplace_back(convert_output(outputs));
}

const std::vector<field_ct> output_bytes = bb::stdlib::aes128::encrypt_buffer_cbc<Builder>(
converted_inputs, convert_input(constraint.iv, 0), convert_input(constraint.key, 0));

for (size_t i = 0; i < output_bytes.size(); ++i) {
builder.assert_equal(output_bytes[i].normalize().witness_index, converted_outputs[i].normalize().witness_index);
}
}

template void create_aes128_constraints<UltraCircuitBuilder>(UltraCircuitBuilder& builder,
const AES128Constraint& constraint);

template void create_aes128_constraints<GoblinUltraCircuitBuilder>(GoblinUltraCircuitBuilder& builder,
const AES128Constraint& constraint);

} // namespace acir_format
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once
#include "barretenberg/dsl/types.hpp"
#include "barretenberg/serialize/msgpack.hpp"
#include <cstdint>
#include <vector>

namespace acir_format {

struct AES128Input {
uint32_t witness;
uint32_t num_bits;

// For serialization, update with any new fields
MSGPACK_FIELDS(witness, num_bits);
friend bool operator==(AES128Input const& lhs, AES128Input const& rhs) = default;
};

struct AES128Constraint {
std::vector<AES128Input> inputs;
std::array<AES128Input, 16> iv;
std::array<AES128Input, 16> key;
std::vector<uint32_t> outputs;

// For serialization, update with any new fields
MSGPACK_FIELDS(inputs, iv, key, outputs);
friend bool operator==(AES128Constraint const& lhs, AES128Constraint const& rhs) = default;
};

template <typename Builder> void create_aes128_constraints(Builder& builder, const AES128Constraint& constraint);

} // namespace acir_format
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ TEST_F(BigIntTests, TestBigIntConstraintMultiple)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -240,6 +241,7 @@ TEST_F(BigIntTests, TestBigIntConstraintSimple)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -293,6 +295,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -350,6 +353,7 @@ TEST_F(BigIntTests, TestBigIntConstraintReuse2)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -428,6 +432,7 @@ TEST_F(BigIntTests, TestBigIntDIV)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ TEST_F(UltraPlonkRAM, TestBlockConstraint)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ TEST_F(EcOperations, TestECOperations)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintSucceed)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -143,6 +144,7 @@ TEST_F(ECDSASecp256k1, TestECDSACompilesForVerifier)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -187,6 +189,7 @@ TEST_F(ECDSASecp256k1, TestECDSAConstraintFail)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ TEST(ECDSASecp256r1, test_hardcoded)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -179,6 +180,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintSucceed)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -228,6 +230,7 @@ TEST(ECDSASecp256r1, TestECDSACompilesForVerifier)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down Expand Up @@ -272,6 +275,7 @@ TEST(ECDSASecp256r1, TestECDSAConstraintFail)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ TEST_F(Poseidon2Tests, TestPoseidon2Permutation)
.public_inputs = {},
.logic_constraints = {},
.range_constraints = {},
.aes128_constraints = {},
.sha256_constraints = {},
.sha256_compression = {},
.schnorr_constraints = {},
Expand Down
Loading

0 comments on commit e4b97a8

Please sign in to comment.