Skip to content

Commit

Permalink
Merge pull request #554 from djmdjm/fuzz
Browse files Browse the repository at this point in the history
Basic fuzzing for C extraction of ML-KEM768
  • Loading branch information
franziskuskiefer authored Sep 19, 2024
2 parents 6a8770c + 8f23a83 commit 41072c6
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 1 deletion.
2 changes: 1 addition & 1 deletion libcrux-ml-kem/cg/eurydice_glue.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ static inline uint8_t core_num__u8_6__wrapping_sub(uint8_t x, uint8_t y) {

#define Eurydice_range_iter_next(iter_ptr, t, ret_t) \
(((iter_ptr)->start == (iter_ptr)->end) \
? (CLITERAL(ret_t){.tag = None}) \
? (CLITERAL(ret_t){.tag = None, .f0 = 0}) \
: (CLITERAL(ret_t){.tag = Some, .f0 = (iter_ptr)->start++}))

#define core_iter_range___core__iter__traits__iterator__Iterator_for_core__ops__range__Range_A__TraitClause_0___6__next \
Expand Down
5 changes: 5 additions & 0 deletions libcrux-ml-kem/cg/fuzz/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dec_fuzz
enc_fuzz
mkcorpus
valid_fuzz
*.o
35 changes: 35 additions & 0 deletions libcrux-ml-kem/cg/fuzz/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
CC=clang-18
CXX=clang++-18
FUZZ_FLAGS=-fsanitize=address,undefined,fuzzer -fno-omit-frame-pointer
FUZZ_LIBS=-L/usr/lib/llvm-18/lib -lFuzzer

CXXFLAGS=-O2 -g -Wall -Wextra -Wno-unused-parameter -Wno-exceptions -I..
CFLAGS=$(CXXFLAGS)
LDFLAGS=-g
LIBS=
COMMON_DEPS=

TARGETS=enc_fuzz valid_fuzz dec_fuzz mkcorpus

all: $(TARGETS)

.cc.o:
$(CXX) $(CXXFLAGS) $(FUZZ_FLAGS) -c $< -o $@

.c.o:
$(CC) $(CFLAGS) -c $< -o $@

enc_fuzz: enc_fuzz.o $(COMMON_DEPS)
$(CXX) -o $@ enc_fuzz.o $(LDFLAGS) $(LIBS) $(FUZZ_FLAGS) $(FUZZ_LIBS)

dec_fuzz: dec_fuzz.o $(COMMON_DEPS)
$(CXX) -o $@ dec_fuzz.o $(LDFLAGS) $(LIBS) $(FUZZ_FLAGS) $(FUZZ_LIBS)

valid_fuzz: valid_fuzz.o $(COMMON_DEPS)
$(CXX) -o $@ valid_fuzz.o $(LDFLAGS) $(LIBS) $(FUZZ_FLAGS) $(FUZZ_LIBS)

mkcorpus: mkcorpus.o
$(CC) -o $@ mkcorpus.o

clean:
-rm -f *.o $(TARGETS)
52 changes: 52 additions & 0 deletions libcrux-ml-kem/cg/fuzz/dec_fuzz.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Basic fuzz test for depcapsulate operation,

#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "libcrux_mlkem768_portable.h"

extern "C"
{

void privkeys(libcrux_ml_kem_types_MlKemPrivateKey_55 *zero_sk,
libcrux_ml_kem_types_MlKemPrivateKey_55 *rnd_sk)
{
uint8_t rnd[64];
memset(rnd, 0, sizeof(rnd));
auto kp = libcrux_ml_kem_mlkem768_portable_kyber_generate_key_pair(rnd);
*zero_sk = kp.sk;
(void)getentropy(rnd, sizeof(rnd));
kp = libcrux_ml_kem_mlkem768_portable_kyber_generate_key_pair(rnd);
*rnd_sk = kp.sk;
}

int LLVMFuzzerTestOneInput(const uint8_t *input, size_t len)
{
static bool once;
uint8_t ret[32];
libcrux_ml_kem_types_MlKemPrivateKey_55 zero_sk, rnd_sk;
libcrux_ml_kem_mlkem768_MlKem768Ciphertext ct;

if (!once)
{
privkeys(&zero_sk, &rnd_sk);
once = true;
}

memset(&ct, 0, sizeof(ct));
if (len > sizeof(ct.value))
{
len = sizeof(ct.value);
}
memcpy(ct.value, input, len);

libcrux_ml_kem_mlkem768_portable_decapsulate(&zero_sk, &ct, ret);
libcrux_ml_kem_mlkem768_portable_decapsulate(&rnd_sk, &ct, ret);
return 0;
}

} // extern
34 changes: 34 additions & 0 deletions libcrux-ml-kem/cg/fuzz/enc_fuzz.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Basic fuzz test for encapsulate operation.

#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "libcrux_mlkem768_portable.h"

extern "C"
{

int LLVMFuzzerTestOneInput(const uint8_t *input, size_t len)
{
uint8_t rnd[32];
libcrux_ml_kem_mlkem768_MlKem768PublicKey pk;

memset(rnd, 0, sizeof(rnd));
memset(&pk, 0, sizeof(pk));
if (len > sizeof(pk.value))
{
len = sizeof(pk.value);
}
memcpy(pk.value, input, len);

(void)libcrux_ml_kem_mlkem768_portable_encapsulate(&pk, rnd);
(void)getentropy(rnd, sizeof(rnd));
(void)libcrux_ml_kem_mlkem768_portable_encapsulate(&pk, rnd);
return 0;
}

} // extern
65 changes: 65 additions & 0 deletions libcrux-ml-kem/cg/fuzz/mkcorpus.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Makes basic seed corpora for other fuzzers
//
// Will write to ./pubkey_corpus (for valid_fuzz and enc_fuzz) and
// to ./ciphertext_corpus (for dec_fuzz)

#include <err.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#include "libcrux_mlkem768_portable.h"

#define NSEEDS 1000

void write_blob(const char *path, int n, const char *suffix, const void *p,
size_t l) {
char name[256];
FILE *f;

snprintf(name, sizeof(name), "%s/%06d.%s", path, n, suffix);
if ((f = fopen(name, "wb+")) == NULL) {
err(1, "fopen %s", name);
}
if (fwrite(p, l, 1, f) != 1) {
err(1, "write %s", name);
}
fclose(f);
}

int main(void) {
int i;
uint8_t rnd[64];
libcrux_ml_kem_mlkem768_MlKem768KeyPair kp;
tuple_3c enc;

if (mkdir("pubkey_corpus", 0777) != 0 && errno != EEXIST)
err(1, "mkdir pubkey_corpus");
if (mkdir("ciphertext_corpus", 0777) != 0 && errno != EEXIST)
err(1, "mkdir ciphertext_corpus");

for (i = 0; i < NSEEDS; i++) {
if (i == 0) {
memset(rnd, 0, sizeof(rnd));
} else {
(void)getentropy(rnd, sizeof(rnd));
}
kp = libcrux_ml_kem_mlkem768_portable_kyber_generate_key_pair(rnd);
write_blob("pubkey_corpus", i, "pk", kp.pk.value, sizeof(kp.pk.value));

if (i == 0) {
memset(rnd, 0, sizeof(rnd));
} else {
(void)getentropy(rnd, sizeof(rnd));
}
enc = libcrux_ml_kem_mlkem768_portable_encapsulate(&kp.pk, rnd);
write_blob("ciphertext_corpus", i, "ct", enc.fst.value,
sizeof(enc.fst.value));
}
return 0;
}
32 changes: 32 additions & 0 deletions libcrux-ml-kem/cg/fuzz/valid_fuzz.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Basic fuzz test for pubkey validation.

#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "libcrux_mlkem768_portable.h"

extern "C"
{

int LLVMFuzzerTestOneInput(const uint8_t *input, size_t len)
{
uint8_t rnd[32];
libcrux_ml_kem_mlkem768_MlKem768PublicKey pk;

memset(rnd, 0, sizeof(rnd));
memset(&pk, 0, sizeof(pk));
if (len > sizeof(pk.value))
{
len = sizeof(pk.value);
}
memcpy(pk.value, input, len);

(void)libcrux_ml_kem_mlkem768_portable_validate_public_key(&pk);
return 0;
}

} // extern

0 comments on commit 41072c6

Please sign in to comment.