aboutsummaryrefslogtreecommitdiff
path: root/contrib/libfido2/fuzz/libfuzzer.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libfido2/fuzz/libfuzzer.c')
-rw-r--r--contrib/libfido2/fuzz/libfuzzer.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/contrib/libfido2/fuzz/libfuzzer.c b/contrib/libfido2/fuzz/libfuzzer.c
index 09aec4ea2b68..073ebe655cf2 100644
--- a/contrib/libfido2/fuzz/libfuzzer.c
+++ b/contrib/libfido2/fuzz/libfuzzer.c
@@ -1,9 +1,12 @@
/*
- * Copyright (c) 2019 Yubico AB. All rights reserved.
+ * Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
+#include <openssl/sha.h>
+
#include <err.h>
#include <fcntl.h>
#include <stdbool.h>
@@ -15,6 +18,8 @@
#include "mutator_aux.h"
+extern int fuzz_save_corpus;
+
static bool debug;
static unsigned int flags = MUTATE_ALL;
static unsigned long long test_fail;
@@ -32,7 +37,7 @@ save_seed(const char *opt)
const char *path;
int fd = -1, status = 1;
void *buf = NULL;
- const size_t buflen = 4096;
+ const size_t buflen = MAXCORPUS;
size_t n;
struct param *p = NULL;
@@ -73,6 +78,50 @@ fail:
return status;
}
+static int
+save_corpus(const struct param *p)
+{
+ uint8_t blob[MAXCORPUS], dgst[SHA256_DIGEST_LENGTH];
+ size_t blob_len;
+ char path[PATH_MAX];
+ int r, fd;
+
+ if ((blob_len = pack(blob, sizeof(blob), p)) == 0 ||
+ blob_len > sizeof(blob)) {
+ warnx("pack");
+ return -1;
+ }
+
+ if (SHA256(blob, blob_len, dgst) != dgst) {
+ warnx("sha256");
+ return -1;
+ }
+
+ if ((r = snprintf(path, sizeof(path), "saved_corpus_%02x%02x%02x%02x"
+ "%02x%02x%02x%02x", dgst[0], dgst[1], dgst[2], dgst[3], dgst[4],
+ dgst[5], dgst[6], dgst[7])) < 0 || (size_t)r >= sizeof(path)) {
+ warnx("snprintf");
+ return -1;
+ }
+
+ if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, 0644)) == -1) {
+ warn("open %s", path);
+ return -1;
+ }
+
+ if (write(fd, blob, blob_len) != (ssize_t)blob_len) {
+ warn("write");
+ r = -1;
+ } else {
+ warnx("wrote %s", path);
+ r = 0;
+ }
+
+ close(fd);
+
+ return r;
+}
+
static void
parse_mutate_flags(const char *opt, unsigned int *mutate_flags)
{
@@ -116,7 +165,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
struct param *p;
- if (size > 4096)
+ if (size > MAXCORPUS)
return 0;
if (++test_total % 100000 == 0 && debug) {
@@ -128,7 +177,11 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
if ((p = unpack(data, size)) == NULL)
test_fail++;
else {
+ fuzz_save_corpus = 0;
test(p);
+ if (fuzz_save_corpus && save_corpus(p) < 0)
+ fprintf(stderr, "%s: failed to save corpus\n",
+ __func__);
free(p);
}
@@ -140,7 +193,7 @@ LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize,
unsigned int seed) NO_MSAN
{
struct param *p;
- uint8_t blob[4096];
+ uint8_t blob[MAXCORPUS];
size_t blob_len;
memset(&p, 0, sizeof(p));