From 7d170f9939a0ec8354e621a06b71dae2768cbb02 Mon Sep 17 00:00:00 2001 From: Justin Traglia <95511699+jtraglia@users.noreply.github.com> Date: Mon, 13 Mar 2023 10:45:02 +0000 Subject: [PATCH] Add coverage-guided C fuzzers (#203) * Start to add fuzzers * Update path to trusted setup in gen_corpus * Update path one more time * Add support for two more targets * Add fuzzers for remaining targets * Clean up a little * Add README * Fix typos * De-dup fuzzing files * Add newline at the end of base_fuzz * Make generic rule for displaying targets * Use regular make command * Remove duplicate targets * Update .gitignore file --- fuzz/.gitignore | 2 + fuzz/Makefile | 91 +++++++++++ fuzz/README.md | 116 ++++++++++++++ fuzz/base_fuzz.h | 34 ++++ fuzz/blob_to_kzg_commitment/fuzz.c | 17 ++ fuzz/compute_blob_kzg_proof/fuzz.c | 19 +++ fuzz/compute_kzg_proof/fuzz.c | 21 +++ fuzz/gen_corpus/go.mod | 8 + fuzz/gen_corpus/go.sum | 10 ++ fuzz/gen_corpus/main.go | 196 ++++++++++++++++++++++++ fuzz/verify_blob_kzg_proof/fuzz.c | 21 +++ fuzz/verify_blob_kzg_proof_batch/fuzz.c | 21 +++ fuzz/verify_kzg_proof/fuzz.c | 23 +++ 13 files changed, 579 insertions(+) create mode 100644 fuzz/.gitignore create mode 100644 fuzz/Makefile create mode 100644 fuzz/README.md create mode 100644 fuzz/base_fuzz.h create mode 100644 fuzz/blob_to_kzg_commitment/fuzz.c create mode 100644 fuzz/compute_blob_kzg_proof/fuzz.c create mode 100644 fuzz/compute_kzg_proof/fuzz.c create mode 100644 fuzz/gen_corpus/go.mod create mode 100644 fuzz/gen_corpus/go.sum create mode 100644 fuzz/gen_corpus/main.go create mode 100644 fuzz/verify_blob_kzg_proof/fuzz.c create mode 100644 fuzz/verify_blob_kzg_proof_batch/fuzz.c create mode 100644 fuzz/verify_kzg_proof/fuzz.c diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 0000000..120f485 --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,2 @@ +* +!/.gitignore diff --git a/fuzz/Makefile b/fuzz/Makefile new file mode 100644 index 0000000..242ec2c --- /dev/null +++ b/fuzz/Makefile @@ -0,0 +1,91 @@ +############################################################################### +# Configuration Options +############################################################################### + +CC = clang + +FIELD_ELEMENTS_PER_BLOB ?= 4096 + +CFLAGS += -I../inc +CFLAGS += -Wall -Wextra -Werror -O0 +CFLAGS += -DFIELD_ELEMENTS_PER_BLOB=$(FIELD_ELEMENTS_PER_BLOB) +CFLAGS += -g -fsanitize=fuzzer + +BLST = -L../lib -lblst +LIBBLST = ../lib/libblst.a + +# Default to no threads, to use all cores specify -1. +THREADS ?= 0 +ifeq ($(THREADS), -1) +override THREADS = $(shell nproc --all) +endif + +# On macOS, you need to use clang from the llvm package. +ifneq ($(OS),Windows_NT) +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Darwin) +ENV_OPTS += PATH=$(shell brew --prefix llvm)/bin:$(PATH) +endif +endif + +############################################################################### +# Helper targets +############################################################################### + +.PHONY: targets +targets: + @echo Available targets: + @# List targets | filter fuzz targets | remove deps | add prefix + @make -qp | grep "^fuzz_" | sed 's/:.*//' | sed 's/^/ - /' | sort | uniq + +$(LIBBLST): + @echo [+] Building blst + @make -C../src blst + +.PRECIOUS: %/corpus +%/corpus: + @echo [+] Generating corpus + @cd gen_corpus && go run . + +.PRECIOUS: %/fuzz +%/fuzz: %/fuzz.c ../src/c_kzg_4844.c %/corpus $(LIBBLST) + @echo [+] Compiling $* fuzzer + @$(ENV_OPTS) $(CC) $(CFLAGS) -o $@ $< $(BLST) + +.PHONY: run_fuzz_% +run_fuzz_%: %/fuzz + @echo [+] Starting $* fuzzer + @-./$< \ + -artifact_prefix=./$*/ \ + -workers=$(THREADS) \ + -jobs=$(THREADS) \ + -max_len=$(LEN) \ + ./$*/corpus + +############################################################################### +# Fuzzing targets +############################################################################### + +# Length is (4096 * 32). +fuzz_blob_to_kzg_commitment: LEN=131072 +fuzz_blob_to_kzg_commitment: run_fuzz_blob_to_kzg_commitment + +# Length is (4096 * 32) + 32. +fuzz_compute_kzg_proof: LEN=131104 +fuzz_compute_kzg_proof: run_fuzz_compute_kzg_proof + +# Length is (4096 * 32) + 48. +fuzz_compute_blob_kzg_proof: LEN=131120 +fuzz_compute_blob_kzg_proof: run_fuzz_compute_blob_kzg_proof + +# Length is 48 + 32 + 32 + 48. +fuzz_verify_kzg_proof: LEN=160 +fuzz_verify_kzg_proof: run_fuzz_verify_kzg_proof + +# Length is (4096 * 32) + 48 + 48. +fuzz_verify_blob_kzg_proof: LEN=131168 +fuzz_verify_blob_kzg_proof: run_fuzz_verify_blob_kzg_proof + +# Length is (3 * 4096 * 32) + (3 * 48) + (3 * 48). +fuzz_verify_blob_kzg_proof_batch: LEN=393504 +fuzz_verify_blob_kzg_proof_batch: run_fuzz_verify_blob_kzg_proof_batch diff --git a/fuzz/README.md b/fuzz/README.md new file mode 100644 index 0000000..5c649bc --- /dev/null +++ b/fuzz/README.md @@ -0,0 +1,116 @@ +# Fuzzing + +This directory contains coverage-guided fuzzers for KZG functions. It uses +LLVM's [libFuzzer](https://llvm.org/docs/LibFuzzer.html) for the heavy lifting. +Each directory is named after a target and contains a single file (`fuzz.c`) +that implements a `LLVMFuzzerTestOneInput` function. These are relatively +simple; if the input matches the size requirements, it passes the data to the +target function. There is a Makefile that compiles and starts the fuzzer, which +means it should be pretty easy. + +## Dependencies + +This is expected to run on Linux/macOS, it is not expected to work on Windows. +In additional to `build-essentials` and `clang`, this requires `llvm` be +installed: + +### Linux + +``` +sudo apt install llvm +``` + +### macOS + +``` +brew install llvm +``` + +## Targets + +Currently, only the public KZG interface functions are fuzzable: +``` +$ make +Available targets: + - fuzz_blob_to_kzg_commitment + - fuzz_compute_blob_kzg_proof + - fuzz_compute_kzg_proof + - fuzz_verify_blob_kzg_proof + - fuzz_verify_blob_kzg_proof_batch + - fuzz_verify_kzg_proof +``` + +To run a fuzzer, run `make fuzz_` like: + +``` +$ make fuzz_verify_kzg_proof +[+] Building blst ++ cc -O2 -fno-builtin -fPIC -Wall -Wextra -Werror -c ./src/server.c ++ cc -O2 -fno-builtin -fPIC -Wall -Wextra -Werror -c ./build/assembly.S ++ ar rc libblst.a assembly.o server.o +[+] Generating corpus +[+] Compiling verify_kzg_proof fuzzer +[+] Starting verify_kzg_proof fuzzer +INFO: Running with entropic power schedule (0xFF, 100). +INFO: Seed: 855755358 +INFO: Loaded 1 modules (228 inline 8-bit counters): 228 [0x1025a00f8, 0x1025a01dc), +INFO: Loaded 1 PC tables (228 PCs): 228 [0x1025a01e0,0x1025a1020), +INFO: 1 files found in ./verify_kzg_proof/corpus +INFO: seed corpus: files: 1 min: 160b max: 160b total: 160b rss: 28Mb +#2 pulse ft: 17 exec/s: 1 rss: 29Mb +#2 INITED cov: 17 ft: 17 corp: 1/160b exec/s: 1 rss: 29Mb +#4 pulse cov: 17 ft: 17 corp: 1/160b lim: 160 exec/s: 2 rss: 29Mb +#5 NEW cov: 19 ft: 20 corp: 2/320b lim: 160 exec/s: 2 rss: 29Mb L: 160/160 MS: 3 ChangeASCIIInt-ChangeBit-ChangeBit- +#7 NEW cov: 20 ft: 21 corp: 3/477b lim: 160 exec/s: 3 rss: 29Mb L: 157/160 MS: 2 ChangeByte-EraseBytes- +#8 pulse cov: 20 ft: 21 corp: 3/477b lim: 160 exec/s: 4 rss: 29Mb +#13 NEW cov: 21 ft: 23 corp: 4/637b lim: 160 exec/s: 6 rss: 29Mb L: 160/160 MS: 1 ChangeBit- +#16 pulse cov: 21 ft: 23 corp: 4/637b lim: 160 exec/s: 8 rss: 29Mb +... +``` + +There are a few steps: + +* Build the blst library. +* Generate initial corpora files. +* Compile the fuzzer. +* Start the fuzzer. + +Reference [this page](https://llvm.org/docs/LibFuzzer.html#output) for a guide on reading the output. + +To stop the fuzzer, press ctrl-C on your keyboard. It will print something like: + +``` +... +#65536 pulse cov: 25 ft: 29 corp: 7/961b lim: 160 exec/s: 16384 rss: 29Mb +#131072 pulse cov: 25 ft: 29 corp: 7/961b lim: 160 exec/s: 18724 rss: 29Mb +^C==11616== libFuzzer: run interrupted; exiting +make: [run_fuzz_verify_kzg_proof] Error 72 (ignored) +``` + +If your system has multiple cores, it's easy to run fuzzers on multiple threads. +Append `THREADS=` where `n` is the number of threads you would like there to +be. If you wish to use all available CPU cores, specify `-1` as the count. + +``` +$ make fuzz_verify_kzg_proof THREADS=4 +[+] Starting verify_kzg_proof fuzzer +./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-0.log 2>&1 +./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-2.log 2>&1 +./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-1.log 2>&1 +./verify_kzg_proof/fuzz -artifact_prefix=./verify_kzg_proof/ -max_len=160 ./verify_kzg_proof/corpus >fuzz-3.log 2>&1 +``` + +When you press ctrl-C it will stop all the fuzzers and print their output to +your console sequentially. You will most likely need to scroll up to see their +outputs. + +When operating in parallel (threads) the fuzzers use a shared corpus and are +intelligent enough to learn from other threads that have progressed further. +When you see a line that starts with "RELOAD" that fuzzer process is updating +its corpus with findings from other threads. + +### Findings + +If there is a crash or timeout, the fuzzer will write a file to the target +directory containing the input data associated with that crash/timeout. If this +happens, please report the finding via an issue on GitHub. \ No newline at end of file diff --git a/fuzz/base_fuzz.h b/fuzz/base_fuzz.h new file mode 100644 index 0000000..890d715 --- /dev/null +++ b/fuzz/base_fuzz.h @@ -0,0 +1,34 @@ +/* + * This file contains fuzzing tests for C-KZG-4844. + */ +#pragma once +#include "../src/c_kzg_4844.c" + +/////////////////////////////////////////////////////////////////////////////// +// Globals +/////////////////////////////////////////////////////////////////////////////// + +KZGSettings s; + +/////////////////////////////////////////////////////////////////////////////// +// Trusted setup configuration +/////////////////////////////////////////////////////////////////////////////// + +static void initialize(void) { + static bool initialized = false; + if (!initialized) { + FILE *fp; + C_KZG_RET ret; + + /* Open the mainnet trusted setup file */ + fp = fopen("../src/trusted_setup.txt", "r"); + assert(fp != NULL); + + /* Load that trusted setup file */ + ret = load_trusted_setup_file(&s, fp); + assert(ret == C_KZG_OK); + + fclose(fp); + initialized = true; + } +} diff --git a/fuzz/blob_to_kzg_commitment/fuzz.c b/fuzz/blob_to_kzg_commitment/fuzz.c new file mode 100644 index 0000000..b11d64f --- /dev/null +++ b/fuzz/blob_to_kzg_commitment/fuzz.c @@ -0,0 +1,17 @@ +#include "../base_fuzz.h" + +static const size_t BLOB_OFFSET = 0; +static const size_t INPUT_SIZE = BLOB_OFFSET + BYTES_PER_BLOB; + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + initialize(); + if (size == INPUT_SIZE) { + KZGCommitment commitment; + blob_to_kzg_commitment( + &commitment, + (const Blob *)(data + BLOB_OFFSET), + &s + ); + } + return 0; +} diff --git a/fuzz/compute_blob_kzg_proof/fuzz.c b/fuzz/compute_blob_kzg_proof/fuzz.c new file mode 100644 index 0000000..6386e3e --- /dev/null +++ b/fuzz/compute_blob_kzg_proof/fuzz.c @@ -0,0 +1,19 @@ +#include "../base_fuzz.h" + +static const size_t BLOB_OFFSET = 0; +static const size_t COMMITMENT_OFFSET = BYTES_PER_BLOB; +static const size_t INPUT_SIZE = COMMITMENT_OFFSET + BYTES_PER_COMMITMENT; + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + initialize(); + if (size == INPUT_SIZE) { + KZGProof proof; + compute_blob_kzg_proof( + &proof, + (const Blob *)(data + BLOB_OFFSET), + (const Bytes48 *)(data + COMMITMENT_OFFSET), + &s + ); + } + return 0; +} diff --git a/fuzz/compute_kzg_proof/fuzz.c b/fuzz/compute_kzg_proof/fuzz.c new file mode 100644 index 0000000..e61a9b0 --- /dev/null +++ b/fuzz/compute_kzg_proof/fuzz.c @@ -0,0 +1,21 @@ +#include "../base_fuzz.h" + +static const size_t BLOB_OFFSET = 0; +static const size_t Z_OFFSET = BLOB_OFFSET + BYTES_PER_BLOB; +static const size_t INPUT_SIZE = Z_OFFSET + BYTES_PER_FIELD_ELEMENT; + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + initialize(); + if (size == INPUT_SIZE) { + KZGProof proof; + Bytes32 y; + compute_kzg_proof( + &proof, + &y, + (const Blob *)(data + BLOB_OFFSET), + (const Bytes32 *)(data + Z_OFFSET), + &s + ); + } + return 0; +} diff --git a/fuzz/gen_corpus/go.mod b/fuzz/gen_corpus/go.mod new file mode 100644 index 0000000..ab8f36a --- /dev/null +++ b/fuzz/gen_corpus/go.mod @@ -0,0 +1,8 @@ +module gen_corpus + +go 1.19 + +require ( + github.com/ethereum/c-kzg-4844 v0.0.0-20230310094217-da83e45e9cef // indirect + github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2 // indirect +) diff --git a/fuzz/gen_corpus/go.sum b/fuzz/gen_corpus/go.sum new file mode 100644 index 0000000..6cb9410 --- /dev/null +++ b/fuzz/gen_corpus/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/ethereum/c-kzg-4844 v0.0.0-20230310094217-da83e45e9cef h1:o/RGxt4PuTHLxwOBS30DFdADBwOZV7J5zoT9CTG/mBU= +github.com/ethereum/c-kzg-4844 v0.0.0-20230310094217-da83e45e9cef/go.mod h1:ECrzdyCNp8d5bLD8Id8Y0mZ8+HDZ0LIdshCrDDTO944= +github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4 h1:B2mpK+MNqgPqk2/KNi1LbqwtZDy5F7iy0mynQiBr8VA= +github.com/ethereum/c-kzg-4844/bindings/go v0.0.0-20230126171313-363c7d7593b4/go.mod h1:y4GA2JbAUama1S4QwYjC2hefgGLU8Ul0GMtL/ADMF1c= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2 h1:wh1wzwAhZBNiZO37uWS/nDaKiIwHz4mDo4pnA+fqTO0= +github.com/supranational/blst v0.3.11-0.20230124161941-ca03e11a3ff2/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/fuzz/gen_corpus/main.go b/fuzz/gen_corpus/main.go new file mode 100644 index 0000000..a2a6b71 --- /dev/null +++ b/fuzz/gen_corpus/main.go @@ -0,0 +1,196 @@ +package main + +import ( + "bytes" + "math/rand" + "os" + "path" + + ckzg "github.com/ethereum/c-kzg-4844/bindings/go" +) + +/////////////////////////////////////////////////////////////////////////////// +// Helper functions +/////////////////////////////////////////////////////////////////////////////// + +func GetRandFieldElement(seed int64) ckzg.Bytes32 { + rand.Seed(seed) + bytes := make([]byte, 31) + _, err := rand.Read(bytes) + if err != nil { + panic("failed to get random field element") + } + + // This leaves the last byte in fieldElementBytes as + // zero, which guarantees it's a canonical field element. + var fieldElementBytes ckzg.Bytes32 + copy(fieldElementBytes[:], bytes) + return fieldElementBytes +} + +func GetRandCommitment(seed int64) ckzg.KZGCommitment { + commitment, ret := ckzg.BlobToKZGCommitment(GetRandBlob(seed)) + if ret != ckzg.C_KZG_OK { + panic("failed to get random commitment") + } + return commitment +} + +func GetRandProof(seed int64) ckzg.KZGProof { + commitment := ckzg.Bytes48(GetRandCommitment(seed)) + proof, ret := ckzg.ComputeBlobKZGProof(GetRandBlob(seed), commitment) + if ret != ckzg.C_KZG_OK { + panic("failed to get random proof") + } + return proof +} + +func GetRandBlob(seed int64) ckzg.Blob { + var blob ckzg.Blob + for i := 0; i < ckzg.BytesPerBlob; i += ckzg.BytesPerFieldElement { + fieldElementBytes := GetRandFieldElement(seed + int64(i)) + copy(blob[i:i+ckzg.BytesPerFieldElement], fieldElementBytes[:]) + } + return blob +} + +/////////////////////////////////////////////////////////////////////////////// +// Generators +/////////////////////////////////////////////////////////////////////////////// + +func GenerateCorpus_BlobToKZGCommitment() { + blob := GetRandBlob(0) + + dir := "../blob_to_kzg_commitment/corpus" + err := os.MkdirAll(dir, os.ModePerm) + if err != nil { + panic(err) + } + + err = os.WriteFile(path.Join(dir, "init"), blob[:], 0644) + if err != nil { + panic(err) + } +} + +func GenerateCorpus_ComputeKZGProof() { + blob := GetRandBlob(0) + z := GetRandFieldElement(1) + + dir := "../compute_kzg_proof/corpus" + err := os.MkdirAll(dir, os.ModePerm) + if err != nil { + panic(err) + } + + data := bytes.Join([][]byte{blob[:], z[:]}, []byte{}) + err = os.WriteFile(path.Join(dir, "init"), data, 0644) + if err != nil { + panic(err) + } +} + +func GenerateCorpus_ComputeBlobKZGProof() { + blob := GetRandBlob(0) + commitment := GetRandCommitment(1) + + dir := "../compute_blob_kzg_proof/corpus" + err := os.MkdirAll(dir, os.ModePerm) + if err != nil { + panic(err) + } + + data := bytes.Join([][]byte{blob[:], commitment[:]}, []byte{}) + err = os.WriteFile(path.Join(dir, "init"), data, 0644) + if err != nil { + panic(err) + } +} + +func GenerateCorpus_VerifyKZGProof() { + commitment := GetRandCommitment(0) + z := GetRandFieldElement(1) + y := GetRandFieldElement(2) + proof := GetRandProof(3) + + dir := "../verify_kzg_proof/corpus" + err := os.MkdirAll(dir, os.ModePerm) + if err != nil { + panic(err) + } + + data := bytes.Join([][]byte{commitment[:], z[:], y[:], proof[:]}, []byte{}) + err = os.WriteFile(path.Join(dir, "init"), data, 0644) + if err != nil { + panic(err) + } +} + +func GenerateCorpus_VerifyBlobKZGProof() { + blob := GetRandBlob(0) + commitment := GetRandCommitment(1) + proof := GetRandProof(2) + + dir := "../verify_blob_kzg_proof/corpus" + err := os.MkdirAll(dir, os.ModePerm) + if err != nil { + panic(err) + } + + data := bytes.Join([][]byte{blob[:], commitment[:], proof[:]}, []byte{}) + err = os.WriteFile(path.Join(dir, "init"), data, 0644) + if err != nil { + panic(err) + } +} + +func GenerateCorpus_VerifyBlobKZGProofBatch() { + const n = 3 + var blobs [n][]byte + var commitments [n][]byte + var proofs [n][]byte + + for i := range blobs { + blob := GetRandBlob(int64(i) + 0) + commitment := GetRandCommitment(int64(i) + 1) + proof := GetRandProof(int64(i) + 2) + + blobs[i] = blob[:] + commitments[i] = commitment[:] + proofs[i] = proof[:] + } + + dir := "../verify_blob_kzg_proof_batch/corpus" + err := os.MkdirAll(dir, os.ModePerm) + if err != nil { + panic(err) + } + + blobsBytes := bytes.Join(blobs[:], []byte{}) + commitmentsBytes := bytes.Join(commitments[:], []byte{}) + proofsBytes := bytes.Join(proofs[:], []byte{}) + data := bytes.Join([][]byte{blobsBytes, commitmentsBytes, proofsBytes}, []byte{}) + err = os.WriteFile(path.Join(dir, "init"), data, 0644) + if err != nil { + panic(err) + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Entry point +/////////////////////////////////////////////////////////////////////////////// + +func main() { + ret := ckzg.LoadTrustedSetupFile("../../src/trusted_setup.txt") + if ret != ckzg.C_KZG_OK { + panic("failed to load trusted setup") + } + defer ckzg.FreeTrustedSetup() + + GenerateCorpus_BlobToKZGCommitment() + GenerateCorpus_ComputeKZGProof() + GenerateCorpus_ComputeBlobKZGProof() + GenerateCorpus_VerifyKZGProof() + GenerateCorpus_VerifyBlobKZGProof() + GenerateCorpus_VerifyBlobKZGProofBatch() +} diff --git a/fuzz/verify_blob_kzg_proof/fuzz.c b/fuzz/verify_blob_kzg_proof/fuzz.c new file mode 100644 index 0000000..2588492 --- /dev/null +++ b/fuzz/verify_blob_kzg_proof/fuzz.c @@ -0,0 +1,21 @@ +#include "../base_fuzz.h" + +static const size_t BLOB_OFFSET = 0; +static const size_t COMMITMENT_OFFSET = BLOB_OFFSET + BYTES_PER_BLOB; +static const size_t PROOF_OFFSET = COMMITMENT_OFFSET + BYTES_PER_COMMITMENT; +static const size_t INPUT_SIZE = PROOF_OFFSET + BYTES_PER_PROOF; + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + initialize(); + if (size == INPUT_SIZE) { + bool ok; + verify_blob_kzg_proof( + &ok, + (const Blob *)(data + BLOB_OFFSET), + (const Bytes48 *)(data + COMMITMENT_OFFSET), + (const Bytes48 *)(data + PROOF_OFFSET), + &s + ); + } + return 0; +} diff --git a/fuzz/verify_blob_kzg_proof_batch/fuzz.c b/fuzz/verify_blob_kzg_proof_batch/fuzz.c new file mode 100644 index 0000000..f37937b --- /dev/null +++ b/fuzz/verify_blob_kzg_proof_batch/fuzz.c @@ -0,0 +1,21 @@ +#include "../base_fuzz.h" + +static const size_t BLOBS_OFFSET = 0; +static const size_t COMMITMENTS_OFFSET = BLOBS_OFFSET + BYTES_PER_BLOB; +static const size_t PROOFS_OFFSET = COMMITMENTS_OFFSET + BYTES_PER_COMMITMENT; +static const size_t INPUT_SIZE = PROOFS_OFFSET + BYTES_PER_PROOF; + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + initialize(); + size_t count = size / INPUT_SIZE; + bool ok; + verify_blob_kzg_proof_batch( + &ok, + (const Blob *)(data + BLOBS_OFFSET * count), + (const Bytes48 *)(data + COMMITMENTS_OFFSET * count), + (const Bytes48 *)(data + PROOFS_OFFSET * count), + count, + &s + ); + return 0; +} diff --git a/fuzz/verify_kzg_proof/fuzz.c b/fuzz/verify_kzg_proof/fuzz.c new file mode 100644 index 0000000..f8b185f --- /dev/null +++ b/fuzz/verify_kzg_proof/fuzz.c @@ -0,0 +1,23 @@ +#include "../base_fuzz.h" + +static const size_t COMMITMENT_OFFSET = 0; +static const size_t Z_OFFSET = COMMITMENT_OFFSET + BYTES_PER_COMMITMENT; +static const size_t Y_OFFSET = Z_OFFSET + BYTES_PER_FIELD_ELEMENT; +static const size_t PROOF_OFFSET = Y_OFFSET + BYTES_PER_FIELD_ELEMENT; +static const size_t INPUT_SIZE = PROOF_OFFSET + BYTES_PER_PROOF; + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + initialize(); + if (size == INPUT_SIZE) { + bool ok; + verify_kzg_proof( + &ok, + (const Bytes48 *)(data + COMMITMENT_OFFSET), + (const Bytes32 *)(data + Z_OFFSET), + (const Bytes32 *)(data + Y_OFFSET), + (const Bytes48 *)(data + PROOF_OFFSET), + &s + ); + } + return 0; +}