summaryrefslogtreecommitdiffstats
path: root/fuzz
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 20:45:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 20:45:25 +0000
commit814d128d1c52fe82be73ecff5b7472378041313f (patch)
tree581db0c07936d6d608e8c2e72d4903df306dd589 /fuzz
parentInitial commit. (diff)
downloadlibfido2-814d128d1c52fe82be73ecff5b7472378041313f.tar.xz
libfido2-814d128d1c52fe82be73ecff5b7472378041313f.zip
Adding upstream version 1.14.0.upstream/1.14.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fuzz')
-rw-r--r--fuzz/CMakeLists.txt82
-rw-r--r--fuzz/Dockerfile16
-rw-r--r--fuzz/Makefile90
-rw-r--r--fuzz/README43
-rwxr-xr-xfuzz/build-coverage34
-rw-r--r--fuzz/clock.c80
-rw-r--r--fuzz/dummy.h182
-rw-r--r--fuzz/export.gnu285
-rw-r--r--fuzz/functions.txt954
-rw-r--r--fuzz/fuzz_assert.c534
-rw-r--r--fuzz/fuzz_bio.c442
-rw-r--r--fuzz/fuzz_cred.c482
-rw-r--r--fuzz/fuzz_credman.c407
-rw-r--r--fuzz/fuzz_hid.c239
-rw-r--r--fuzz/fuzz_largeblob.c272
-rw-r--r--fuzz/fuzz_mgmt.c528
-rw-r--r--fuzz/fuzz_netlink.c164
-rw-r--r--fuzz/fuzz_pcsc.c269
-rw-r--r--fuzz/libfuzzer.c230
-rw-r--r--fuzz/mutator_aux.c332
-rw-r--r--fuzz/mutator_aux.h111
-rw-r--r--fuzz/pcsc.c153
-rw-r--r--fuzz/preload-fuzz.c105
-rw-r--r--fuzz/preload-snoop.c218
-rw-r--r--fuzz/prng.c113
-rw-r--r--fuzz/report.tgzbin0 -> 361946 bytes
-rw-r--r--fuzz/summary.txt64
-rw-r--r--fuzz/udev.c270
-rw-r--r--fuzz/uniform_random.c57
-rw-r--r--fuzz/wiredata_fido2.h708
-rw-r--r--fuzz/wiredata_u2f.h153
-rw-r--r--fuzz/wrap.c700
-rw-r--r--fuzz/wrapped.sym102
33 files changed, 8419 insertions, 0 deletions
diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt
new file mode 100644
index 0000000..cc30baa
--- /dev/null
+++ b/fuzz/CMakeLists.txt
@@ -0,0 +1,82 @@
+# Copyright (c) 2019-2023 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
+
+list(APPEND COMPAT_SOURCES
+ ../openbsd-compat/strlcpy.c
+ ../openbsd-compat/strlcat.c
+)
+
+list(APPEND COMMON_SOURCES
+ libfuzzer.c
+ mutator_aux.c
+)
+
+# XXX: OSS-Fuzz require linking using CXX
+set(FUZZ_LINKER_LANGUAGE "C" CACHE STRING "Linker language for fuzz harnesses")
+mark_as_advanced(FUZZ_LINKER_LANGUAGE)
+enable_language(${FUZZ_LINKER_LANGUAGE})
+
+# fuzz_cred
+add_executable(fuzz_cred fuzz_cred.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
+set_target_properties(fuzz_cred PROPERTIES
+ LINK_FLAGS ${FUZZ_LDFLAGS}
+ LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
+target_link_libraries(fuzz_cred fido2_shared)
+
+# fuzz_assert
+add_executable(fuzz_assert fuzz_assert.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
+set_target_properties(fuzz_assert PROPERTIES
+ LINK_FLAGS ${FUZZ_LDFLAGS}
+ LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
+target_link_libraries(fuzz_assert fido2_shared)
+
+# fuzz_mgmt
+add_executable(fuzz_mgmt fuzz_mgmt.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
+set_target_properties(fuzz_mgmt PROPERTIES
+ LINK_FLAGS ${FUZZ_LDFLAGS}
+ LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
+target_link_libraries(fuzz_mgmt fido2_shared)
+
+# fuzz_credman
+add_executable(fuzz_credman fuzz_credman.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
+set_target_properties(fuzz_credman PROPERTIES
+ LINK_FLAGS ${FUZZ_LDFLAGS}
+ LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
+target_link_libraries(fuzz_credman fido2_shared)
+
+# fuzz_bio
+add_executable(fuzz_bio fuzz_bio.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
+set_target_properties(fuzz_bio PROPERTIES
+ LINK_FLAGS ${FUZZ_LDFLAGS}
+ LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
+target_link_libraries(fuzz_bio fido2_shared)
+
+# fuzz_hid
+add_executable(fuzz_hid fuzz_hid.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
+set_target_properties(fuzz_hid PROPERTIES
+ LINK_FLAGS ${FUZZ_LDFLAGS}
+ LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
+target_link_libraries(fuzz_hid fido2_shared)
+
+# fuzz_netlink
+add_executable(fuzz_netlink fuzz_netlink.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
+set_target_properties(fuzz_netlink PROPERTIES
+ LINK_FLAGS ${FUZZ_LDFLAGS}
+ LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
+target_link_libraries(fuzz_netlink fido2_shared)
+
+# fuzz_largeblob
+add_executable(fuzz_largeblob fuzz_largeblob.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
+set_target_properties(fuzz_largeblob PROPERTIES
+ LINK_FLAGS ${FUZZ_LDFLAGS}
+ LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
+target_link_libraries(fuzz_largeblob fido2_shared)
+
+# fuzz_pcsc
+add_executable(fuzz_pcsc fuzz_pcsc.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
+set_target_properties(fuzz_pcsc PROPERTIES
+ LINK_FLAGS ${FUZZ_LDFLAGS}
+ LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
+target_link_libraries(fuzz_pcsc fido2_shared)
diff --git a/fuzz/Dockerfile b/fuzz/Dockerfile
new file mode 100644
index 0000000..7b26e6e
--- /dev/null
+++ b/fuzz/Dockerfile
@@ -0,0 +1,16 @@
+# Copyright (c) 2019-2023 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
+
+FROM alpine:latest
+ENV CC=clang
+ENV CXX=clang++
+RUN apk -q update
+RUN apk add build-base clang clang-analyzer cmake compiler-rt coreutils
+RUN apk add eudev-dev git linux-headers llvm openssl-dev pcsc-lite-dev
+RUN apk add sudo tar zlib-dev
+RUN git clone --branch v0.10.2 --depth=1 https://github.com/PJK/libcbor
+RUN git clone --depth=1 https://github.com/yubico/libfido2
+WORKDIR /libfido2
+RUN ./fuzz/build-coverage /libcbor /libfido2
diff --git a/fuzz/Makefile b/fuzz/Makefile
new file mode 100644
index 0000000..55a506b
--- /dev/null
+++ b/fuzz/Makefile
@@ -0,0 +1,90 @@
+# Copyright (c) 2019-2023 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
+
+IMAGE := libfido2-coverage:1.14.0
+RUNNER := libfido2-runner
+PROFDATA := llvm-profdata
+COV := llvm-cov
+TARGETS := fuzz_assert fuzz_bio fuzz_cred fuzz_credman fuzz_hid \
+ fuzz_largeblob fuzz_netlink fuzz_mgmt fuzz_pcsc
+CORPORA := $(foreach f,${TARGETS},${f}/corpus)
+MINIFY := $(foreach f,${TARGETS},/minify/${f}/corpus)
+REMOTE := gs://libfido2-corpus.clusterfuzz-external.appspot.com
+.DEFAULT_GOAL := all
+
+all: ${TARGETS}
+
+build:
+ docker build -t ${IMAGE} - < Dockerfile
+
+run: build
+ -docker run -it -d --name ${RUNNER} ${IMAGE}
+ docker start ${RUNNER}
+
+sync: run
+ tar Ccf .. - src fuzz | docker exec -i ${RUNNER} tar Cxf /libfido2 -
+ docker exec ${RUNNER} make -C /libfido2/build
+
+corpus: sync
+ docker exec ${RUNNER} /bin/sh -c 'cd /libfido2/fuzz && rm -rf ${TARGETS}'
+ docker exec ${RUNNER} tar Czxf /libfido2/fuzz /libfido2/fuzz/corpus.tgz
+
+${TARGETS}: corpus sync
+ docker exec -e LLVM_PROFILE_FILE=/profraw/$@ ${RUNNER} \
+ /bin/sh -c 'rm -f /profraw/$@ && /libfido2/build/fuzz/$@ \
+ -runs=1 /libfido2/fuzz/$@'
+
+${MINIFY}: /minify/%/corpus: %
+ docker exec ${RUNNER} /bin/sh -c 'rm -rf $@ && mkdir -p $@ && \
+ /libfido2/build/fuzz/$< -use_value_profile=1 -merge=1 $@ \
+ /libfido2/fuzz/$</corpus'
+
+corpus.tgz-: ${MINIFY}
+ docker exec -i ${RUNNER} tar Czcf /minify - ${TARGETS} > $@
+
+profdata: run
+ docker exec ${RUNNER} /bin/sh -c 'rm -f /$@ && ${PROFDATA} \
+ merge -sparse /profraw/* -o /$@'
+
+report.tgz: profdata
+ docker exec ${RUNNER} /bin/sh -c 'rm -rf /report && mkdir /report && \
+ ${COV} show -format=html -tab-size=8 -instr-profile=/$< \
+ -ignore-filename-regex=pcsclite.h --show-branch-summary=false \
+ -output-dir=/report /libfido2/build/src/libfido2.so'
+ docker exec -i ${RUNNER} tar Czcf / - report > $@
+
+summary.txt: profdata
+ docker exec ${RUNNER} ${COV} report -use-color=false \
+ -ignore-filename-regex=pcsclite.h --show-branch-summary=false \
+ /libfido2/build/src/libfido2.so -instr-profile=/$< > $@
+
+functions.txt: profdata
+ docker exec ${RUNNER} /bin/sh -c '${COV} report -use-color=false \
+ -ignore-filename-regex=pcsclite.h -show-functions \
+ --show-branch-summary=false -instr-profile=/$< \
+ /libfido2/build/src/libfido2.so /libfido2/src/*.[ch]' > $@
+
+clean: run
+ docker exec ${RUNNER} /bin/sh -c 'rm -rf /profraw /profdata && \
+ make -C /libfido2/build clean'
+ -docker stop ${RUNNER}
+ rm -rf ${TARGETS}
+
+${CORPORA}:
+ -mkdir -p $@
+ gsutil -q -m rsync -d -r ${REMOTE}/libFuzzer/libfido2_$(@:/corpus=) $@
+
+fetch-oss-fuzz: ${CORPORA}
+ find ${TARGETS} -type f -size +8192c -print0 | xargs -0 rm
+
+fetch-franz:
+ ssh franz tar -C corpus -cf- . | tar -xf-
+
+corpus.tgz:
+ tar zcf $@ ${TARGETS}
+
+.PHONY: build run sync corpus ${TARGETS} ${CORPORA}
+.PHONY: report.tgz summary.txt functions.txt
+.PHONY: fetch-oss-fuzz fetch-franz corpus.tgz
diff --git a/fuzz/README b/fuzz/README
new file mode 100644
index 0000000..427625c
--- /dev/null
+++ b/fuzz/README
@@ -0,0 +1,43 @@
+libfido2 can be fuzzed using AFL or libFuzzer, with or without
+ASAN/MSAN/UBSAN.
+
+AFL is more convenient when fuzzing the path from the authenticator to
+libfido2 in an existing application. To do so, use preload-snoop.c with a real
+authenticator to obtain an initial corpus, rebuild libfido2 with -DFUZZ=ON, and
+use preload-fuzz.c to read device data from stdin.
+
+libFuzzer is better suited for bespoke fuzzers; see fuzz_cred.c, fuzz_credman.c,
+fuzz_assert.c, fuzz_hid.c, and fuzz_mgmt.c for examples. To build these
+harnesses, use -DCMAKE_C_FLAGS=-fsanitize=fuzzer-no-link
+-DFUZZ_LDFLAGS=-fsanitize=fuzzer -DFUZZ=ON.
+
+If -DFUZZ=ON is enabled, symbols listed in wrapped.sym are wrapped in the
+resulting shared object. The wrapper functions simulate failure according to a
+deterministic RNG and probabilities defined in wrap.c. Harnesses wishing to
+use this functionality should call prng_init() with a seed obtained from the
+corpus. To mutate only the seed part of a libFuzzer harness's corpora,
+use '-reduce_inputs=0 --fido-mutate=seed'.
+
+To run under ASAN/MSAN/UBSAN, libfido2 needs to be linked against flavours of
+libcbor and OpenSSL built with the respective sanitiser. In order to keep
+memory utilisation at a manageable level, you can either enforce limits at
+the OS level (e.g. cgroups on Linux), or patch libcbor with the diff below.
+N.B., the patch below is relative to libcbor 0.10.1.
+
+diff --git src/cbor/internal/memory_utils.c src/cbor/internal/memory_utils.c
+index bbea63c..3f7c9af 100644
+--- src/cbor/internal/memory_utils.c
++++ src/cbor/internal/memory_utils.c
+@@ -41,7 +41,11 @@ size_t _cbor_safe_signaling_add(size_t a, size_t b) {
+
+ void* _cbor_alloc_multiple(size_t item_size, size_t item_count) {
+ if (_cbor_safe_to_multiply(item_size, item_count)) {
+- return _cbor_malloc(item_size * item_count);
++ if (item_count > 1000) {
++ return NULL;
++ } else {
++ return _cbor_malloc(item_size * item_count);
++ }
+ } else {
+ return NULL;
+ }
diff --git a/fuzz/build-coverage b/fuzz/build-coverage
new file mode 100755
index 0000000..6cc5041
--- /dev/null
+++ b/fuzz/build-coverage
@@ -0,0 +1,34 @@
+#!/bin/sh -eux
+
+# Copyright (c) 2019 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
+
+LIBCBOR="$1"
+LIBFIDO2="$2"
+
+CC="${CC:-clang}"
+CXX="${CXX:-clang++}"
+PKG_CONFIG_PATH="${PKG_CONFIG_PATH:-${LIBCBOR}/install/lib/pkgconfig}"
+export CC PKG_CONFIG_PATH
+
+# Clean up.
+rm -rf "${LIBCBOR}/build" "${LIBCBOR}/install" "${LIBFIDO2}/build"
+
+# Patch, build, and install libcbor.
+(cd "${LIBCBOR}" && patch -N -l -s -p0 < "${LIBFIDO2}/fuzz/README") || true
+mkdir "${LIBCBOR}/build" "${LIBCBOR}/install"
+(cd "${LIBCBOR}/build" && cmake -DBUILD_SHARED_LIBS=ON \
+ -DCMAKE_INSTALL_PREFIX="${LIBCBOR}/install" ..)
+make -C "${LIBCBOR}/build" VERBOSE=1 all install
+
+# Build libfido2.
+mkdir -p "${LIBFIDO2}/build"
+export CFLAGS="-fprofile-instr-generate -fcoverage-mapping"
+export CFLAGS="${CFLAGS} -fsanitize=fuzzer-no-link"
+export LDFLAGS="${CFLAGS}"
+export FUZZ_LDFLAGS="${LDFLAGS} -fsanitize=fuzzer"
+(cd "${LIBFIDO2}/build" && cmake -DFUZZ=ON -DFUZZ_LDFLAGS="${FUZZ_LDFLAGS}" \
+ -DCMAKE_BUILD_TYPE=Debug ..)
+make -C "${LIBFIDO2}/build"
diff --git a/fuzz/clock.c b/fuzz/clock.c
new file mode 100644
index 0000000..bd758ea
--- /dev/null
+++ b/fuzz/clock.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2021 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 <stdint.h>
+#include <time.h>
+
+#include "mutator_aux.h"
+
+/*
+ * A pseudo-random monotonic clock with a probabilistic discontinuity to
+ * the end of time (as measured by struct timespec).
+ */
+
+extern int prng_up;
+extern int __wrap_clock_gettime(clockid_t, struct timespec *);
+extern int __real_clock_gettime(clockid_t, struct timespec *);
+extern int __wrap_usleep(unsigned int);
+static TLS struct timespec fuzz_clock;
+
+static void
+tick(unsigned int usec)
+{
+ long long drift;
+
+ /*
+ * Simulate a jump to the end of time with 0.125% probability.
+ * This condition should be gracefully handled by callers of
+ * clock_gettime().
+ */
+ if (uniform_random(800) < 1) {
+ fuzz_clock.tv_sec = LLONG_MAX;
+ fuzz_clock.tv_nsec = LONG_MAX;
+ return;
+ }
+
+ drift = usec * 1000LL + (long long)uniform_random(10000000); /* 10ms */
+ if (LLONG_MAX - drift < (long long)fuzz_clock.tv_nsec) {
+ fuzz_clock_reset(); /* Not much we can do here. */
+ } else if (drift + (long long)fuzz_clock.tv_nsec < 1000000000) {
+ fuzz_clock.tv_nsec += (long)(drift);
+ } else {
+ fuzz_clock.tv_sec += (long)(drift / 1000000000);
+ fuzz_clock.tv_nsec += (long)(drift % 1000000000);
+ }
+}
+
+int
+__wrap_clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+ if (!prng_up || clk_id != CLOCK_MONOTONIC)
+ return __real_clock_gettime(clk_id, tp);
+ if (uniform_random(400) < 1)
+ return -1;
+
+ tick(0);
+ *tp = fuzz_clock;
+
+ return 0;
+}
+
+int
+__wrap_usleep(unsigned int usec)
+{
+ if (uniform_random(400) < 1)
+ return -1;
+
+ tick(usec);
+
+ return 0;
+}
+
+void
+fuzz_clock_reset(void)
+{
+ memset(&fuzz_clock, 0, sizeof(fuzz_clock));
+}
diff --git a/fuzz/dummy.h b/fuzz/dummy.h
new file mode 100644
index 0000000..fc4bfc5
--- /dev/null
+++ b/fuzz/dummy.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2020-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
+ */
+
+#ifndef _DUMMY_H
+#define _DUMMY_H
+
+#include <stdint.h>
+
+const char dummy_name[] = "finger1";
+const char dummy_pin1[] = "skepp cg0u3;Y..";
+const char dummy_pin2[] = "bastilha 6rJrfQZI.";
+const char dummy_pin[] = "9}4gT:8d=A37Dh}U";
+const char dummy_rp_id[] = "localhost";
+const char dummy_rp_name[] = "sweet home localhost";
+const char dummy_user_icon[] = "an icon";
+const char dummy_user_name[] = "john smith";
+const char dummy_user_nick[] = "jsmith";
+const char dummy_pcsc_list[] = "reader1\0reader2\0reader3\0\0";
+const char dummy_pcsc_path[] = "pcsc://slot7";
+const uint8_t dummy_id[] = { 0x5e, 0xd2 };
+
+const uint8_t dummy_user_id[] = {
+ 0x78, 0x1c, 0x78, 0x60, 0xad, 0x88, 0xd2, 0x63,
+ 0x32, 0x62, 0x2a, 0xf1, 0x74, 0x5d, 0xed, 0xb2,
+ 0xe7, 0xa4, 0x2b, 0x44, 0x89, 0x29, 0x39, 0xc5,
+ 0x56, 0x64, 0x01, 0x27, 0x0d, 0xbb, 0xc4, 0x49,
+};
+
+const uint8_t dummy_cred_id[] = {
+ 0x4f, 0x72, 0x98, 0x42, 0x4a, 0xe1, 0x17, 0xa5,
+ 0x85, 0xa0, 0xef, 0x3b, 0x11, 0x24, 0x4a, 0x3d,
+};
+
+const uint8_t dummy_cdh[] = {
+ 0xec, 0x8d, 0x8f, 0x78, 0x42, 0x4a, 0x2b, 0xb7,
+ 0x82, 0x34, 0xaa, 0xca, 0x07, 0xa1, 0xf6, 0x56,
+ 0x42, 0x1c, 0xb6, 0xf6, 0xb3, 0x00, 0x86, 0x52,
+ 0x35, 0x2d, 0xa2, 0x62, 0x4a, 0xbe, 0x89, 0x76,
+};
+
+const uint8_t dummy_es256[] = {
+ 0xcc, 0x1b, 0x50, 0xac, 0xc4, 0x19, 0xf8, 0x3a,
+ 0xee, 0x0a, 0x77, 0xd6, 0xf3, 0x53, 0xdb, 0xef,
+ 0xf2, 0xb9, 0x5c, 0x2d, 0x8b, 0x1e, 0x52, 0x58,
+ 0x88, 0xf4, 0x0b, 0x85, 0x1f, 0x40, 0x6d, 0x18,
+ 0x15, 0xb3, 0xcc, 0x25, 0x7c, 0x38, 0x3d, 0xec,
+ 0xdf, 0xad, 0xbd, 0x46, 0x91, 0xc3, 0xac, 0x30,
+ 0x94, 0x2a, 0xf7, 0x78, 0x35, 0x70, 0x59, 0x6f,
+ 0x28, 0xcb, 0x8e, 0x07, 0x85, 0xb5, 0x91, 0x96,
+};
+
+const uint8_t dummy_rs256[] = {
+ 0xd2, 0xa8, 0xc0, 0x11, 0x82, 0x9e, 0x57, 0x2e,
+ 0x60, 0xae, 0x8c, 0xb0, 0x09, 0xe1, 0x58, 0x2b,
+ 0x99, 0xec, 0xc3, 0x11, 0x1b, 0xef, 0x81, 0x49,
+ 0x34, 0x53, 0x6a, 0x01, 0x65, 0x2c, 0x24, 0x09,
+ 0x30, 0x87, 0x98, 0x51, 0x6e, 0x30, 0x4f, 0x60,
+ 0xbd, 0x54, 0xd2, 0x54, 0xbd, 0x94, 0x42, 0xdd,
+ 0x63, 0xe5, 0x2c, 0xc6, 0x04, 0x32, 0xc0, 0x8f,
+ 0x72, 0xd5, 0xb4, 0xf0, 0x4f, 0x42, 0xe5, 0xb0,
+ 0xa2, 0x95, 0x11, 0xfe, 0xd8, 0xb0, 0x65, 0x34,
+ 0xff, 0xfb, 0x44, 0x97, 0x52, 0xfc, 0x67, 0x23,
+ 0x0b, 0xad, 0xf3, 0x3a, 0x82, 0xd4, 0x96, 0x10,
+ 0x87, 0x6b, 0xfa, 0xd6, 0x51, 0x60, 0x3e, 0x1c,
+ 0xae, 0x19, 0xb8, 0xce, 0x08, 0xae, 0x9a, 0xee,
+ 0x78, 0x16, 0x22, 0xcc, 0x92, 0xcb, 0xa8, 0x95,
+ 0x34, 0xe5, 0xb9, 0x42, 0x6a, 0xf0, 0x2e, 0x82,
+ 0x1f, 0x4c, 0x7d, 0x84, 0x94, 0x68, 0x7b, 0x97,
+ 0x2b, 0xf7, 0x7d, 0x67, 0x83, 0xbb, 0xc7, 0x8a,
+ 0x31, 0x5a, 0xf3, 0x2a, 0x95, 0xdf, 0x63, 0xe7,
+ 0x4e, 0xee, 0x26, 0xda, 0x87, 0x00, 0xe2, 0x23,
+ 0x4a, 0x33, 0x9a, 0xa0, 0x1b, 0xce, 0x60, 0x1f,
+ 0x98, 0xa1, 0xb0, 0xdb, 0xbf, 0x20, 0x59, 0x27,
+ 0xf2, 0x06, 0xd9, 0xbe, 0x37, 0xa4, 0x03, 0x6b,
+ 0x6a, 0x4e, 0xaf, 0x22, 0x68, 0xf3, 0xff, 0x28,
+ 0x59, 0x05, 0xc9, 0xf1, 0x28, 0xf4, 0xbb, 0x35,
+ 0xe0, 0xc2, 0x68, 0xc2, 0xaa, 0x54, 0xac, 0x8c,
+ 0xc1, 0x69, 0x9e, 0x4b, 0x32, 0xfc, 0x53, 0x58,
+ 0x85, 0x7d, 0x3f, 0x51, 0xd1, 0xc9, 0x03, 0x02,
+ 0x13, 0x61, 0x62, 0xda, 0xf8, 0xfe, 0x3e, 0xc8,
+ 0x95, 0x12, 0xfb, 0x0c, 0xdf, 0x06, 0x65, 0x6f,
+ 0x23, 0xc7, 0x83, 0x7c, 0x50, 0x2d, 0x27, 0x25,
+ 0x4d, 0xbf, 0x94, 0xf0, 0x89, 0x04, 0xb9, 0x2d,
+ 0xc4, 0xa5, 0x32, 0xa9, 0x25, 0x0a, 0x99, 0x59,
+ 0x01, 0x00, 0x01,
+};
+
+const uint8_t dummy_eddsa[] = {
+ 0xfe, 0x8b, 0x61, 0x50, 0x31, 0x7a, 0xe6, 0xdf,
+ 0xb1, 0x04, 0x9d, 0x4d, 0xb5, 0x7a, 0x5e, 0x96,
+ 0x4c, 0xb2, 0xf9, 0x5f, 0x72, 0x47, 0xb5, 0x18,
+ 0xe2, 0x39, 0xdf, 0x2f, 0x87, 0x19, 0xb3, 0x02,
+};
+
+const uint8_t dummy_netlink_wiredata[] = {
+ 0xd8, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9d, 0x2e, 0x00, 0x00,
+ 0x01, 0x02, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x6e, 0x66, 0x63, 0x00, 0x06, 0x00, 0x01, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00,
+ 0x1f, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x00,
+ 0x14, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x06, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x09, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0c, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x15, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0e, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x1a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x10, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x11, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00,
+ 0x08, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x13, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x0a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x07, 0x00,
+ 0x18, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x9d, 0x2e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x1e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x9d, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x09, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x1e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x9d, 0x2e, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00,
+ 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x06, 0x00, 0x05, 0x00, 0x44, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x06, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00,
+ 0x93, 0xb9, 0x25, 0x00
+};
+
+#endif /* !_DUMMY_H */
diff --git a/fuzz/export.gnu b/fuzz/export.gnu
new file mode 100644
index 0000000..bc25dd6
--- /dev/null
+++ b/fuzz/export.gnu
@@ -0,0 +1,285 @@
+{
+ global:
+ eddsa_pk_free;
+ eddsa_pk_from_EVP_PKEY;
+ eddsa_pk_from_ptr;
+ eddsa_pk_new;
+ eddsa_pk_to_EVP_PKEY;
+ es256_pk_free;
+ es256_pk_from_EC_KEY;
+ es256_pk_from_EVP_PKEY;
+ es256_pk_from_ptr;
+ es256_pk_new;
+ es256_pk_to_EVP_PKEY;
+ es384_pk_free;
+ es384_pk_from_EC_KEY;
+ es384_pk_from_EVP_PKEY;
+ es384_pk_from_ptr;
+ es384_pk_new;
+ es384_pk_to_EVP_PKEY;
+ fido_assert_allow_cred;
+ fido_assert_authdata_len;
+ fido_assert_authdata_ptr;
+ fido_assert_authdata_raw_len;
+ fido_assert_authdata_raw_ptr;
+ fido_assert_blob_len;
+ fido_assert_blob_ptr;
+ fido_assert_clientdata_hash_len;
+ fido_assert_clientdata_hash_ptr;
+ fido_assert_count;
+ fido_assert_flags;
+ fido_assert_free;
+ fido_assert_hmac_secret_len;
+ fido_assert_hmac_secret_ptr;
+ fido_assert_id_len;
+ fido_assert_id_ptr;
+ fido_assert_largeblob_key_len;
+ fido_assert_largeblob_key_ptr;
+ fido_assert_new;
+ fido_assert_rp_id;
+ fido_assert_set_authdata;
+ fido_assert_set_authdata_raw;
+ fido_assert_set_clientdata;
+ fido_assert_set_clientdata_hash;
+ fido_assert_set_count;
+ fido_assert_set_extensions;
+ fido_assert_set_hmac_salt;
+ fido_assert_set_hmac_secret;
+ fido_assert_set_options;
+ fido_assert_set_rp;
+ fido_assert_set_sig;
+ fido_assert_set_up;
+ fido_assert_set_uv;
+ fido_assert_sigcount;
+ fido_assert_sig_len;
+ fido_assert_sig_ptr;
+ fido_assert_user_display_name;
+ fido_assert_user_icon;
+ fido_assert_user_id_len;
+ fido_assert_user_id_ptr;
+ fido_assert_user_name;
+ fido_assert_verify;
+ fido_bio_dev_enroll_begin;
+ fido_bio_dev_enroll_cancel;
+ fido_bio_dev_enroll_continue;
+ fido_bio_dev_enroll_remove;
+ fido_bio_dev_get_info;
+ fido_bio_dev_get_template_array;
+ fido_bio_dev_set_template_name;
+ fido_bio_enroll_free;
+ fido_bio_enroll_last_status;
+ fido_bio_enroll_new;
+ fido_bio_enroll_remaining_samples;
+ fido_bio_info_free;
+ fido_bio_info_max_samples;
+ fido_bio_info_new;
+ fido_bio_info_type;
+ fido_bio_template;
+ fido_bio_template_array_count;
+ fido_bio_template_array_free;
+ fido_bio_template_array_new;
+ fido_bio_template_free;
+ fido_bio_template_id_len;
+ fido_bio_template_id_ptr;
+ fido_bio_template_name;
+ fido_bio_template_new;
+ fido_bio_template_set_id;
+ fido_bio_template_set_name;
+ fido_cbor_info_aaguid_len;
+ fido_cbor_info_aaguid_ptr;
+ fido_cbor_info_algorithm_cose;
+ fido_cbor_info_algorithm_count;
+ fido_cbor_info_algorithm_type;
+ fido_cbor_info_certs_len;
+ fido_cbor_info_certs_name_ptr;
+ fido_cbor_info_certs_value_ptr;
+ fido_cbor_info_extensions_len;
+ fido_cbor_info_extensions_ptr;
+ fido_cbor_info_free;
+ fido_cbor_info_fwversion;
+ fido_cbor_info_maxcredbloblen;
+ fido_cbor_info_maxcredcntlst;
+ fido_cbor_info_maxcredidlen;
+ fido_cbor_info_maxlargeblob;
+ fido_cbor_info_maxmsgsiz;
+ fido_cbor_info_maxrpid_minpinlen;
+ fido_cbor_info_minpinlen;
+ fido_cbor_info_new;
+ fido_cbor_info_new_pin_required;
+ fido_cbor_info_options_len;
+ fido_cbor_info_options_name_ptr;
+ fido_cbor_info_options_value_ptr;
+ fido_cbor_info_protocols_len;
+ fido_cbor_info_protocols_ptr;
+ fido_cbor_info_rk_remaining;
+ fido_cbor_info_transports_len;
+ fido_cbor_info_transports_ptr;
+ fido_cbor_info_uv_attempts;
+ fido_cbor_info_uv_modality;
+ fido_cbor_info_versions_len;
+ fido_cbor_info_versions_ptr;
+ fido_cred_attstmt_len;
+ fido_cred_attstmt_ptr;
+ fido_cred_authdata_len;
+ fido_cred_authdata_ptr;
+ fido_cred_authdata_raw_len;
+ fido_cred_authdata_raw_ptr;
+ fido_cred_clientdata_hash_len;
+ fido_cred_clientdata_hash_ptr;
+ fido_cred_display_name;
+ fido_cred_exclude;
+ fido_cred_flags;
+ fido_cred_largeblob_key_len;
+ fido_cred_largeblob_key_ptr;
+ fido_cred_sigcount;
+ fido_cred_fmt;
+ fido_cred_free;
+ fido_cred_id_len;
+ fido_cred_id_ptr;
+ fido_cred_aaguid_len;
+ fido_cred_aaguid_ptr;
+ fido_credman_del_dev_rk;
+ fido_credman_get_dev_metadata;
+ fido_credman_get_dev_rk;
+ fido_credman_get_dev_rp;
+ fido_credman_metadata_free;
+ fido_credman_metadata_new;
+ fido_credman_rk;
+ fido_credman_rk_count;
+ fido_credman_rk_existing;
+ fido_credman_rk_free;
+ fido_credman_rk_new;
+ fido_credman_rk_remaining;
+ fido_credman_rp_count;
+ fido_credman_rp_free;
+ fido_credman_rp_id;
+ fido_credman_rp_id_hash_len;
+ fido_credman_rp_id_hash_ptr;
+ fido_credman_rp_name;
+ fido_credman_rp_new;
+ fido_credman_set_dev_rk;
+ fido_cred_new;
+ fido_cred_pin_minlen;
+ fido_cred_prot;
+ fido_cred_pubkey_len;
+ fido_cred_pubkey_ptr;
+ fido_cred_rp_id;
+ fido_cred_rp_name;
+ fido_cred_set_attstmt;
+ fido_cred_set_authdata;
+ fido_cred_set_authdata_raw;
+ fido_cred_set_blob;
+ fido_cred_set_clientdata;
+ fido_cred_set_clientdata_hash;
+ fido_cred_set_extensions;
+ fido_cred_set_fmt;
+ fido_cred_set_id;
+ fido_cred_set_options;
+ fido_cred_set_pin_minlen;
+ fido_cred_set_prot;
+ fido_cred_set_rk;
+ fido_cred_set_rp;
+ fido_cred_set_sig;
+ fido_cred_set_type;
+ fido_cred_set_user;
+ fido_cred_set_uv;
+ fido_cred_set_x509;
+ fido_cred_sig_len;
+ fido_cred_sig_ptr;
+ fido_cred_type;
+ fido_cred_user_id_len;
+ fido_cred_user_id_ptr;
+ fido_cred_user_name;
+ fido_cred_verify;
+ fido_cred_verify_self;
+ fido_cred_x5c_len;
+ fido_cred_x5c_ptr;
+ fido_dev_build;
+ fido_dev_cancel;
+ fido_dev_close;
+ fido_dev_enable_entattest;
+ fido_dev_flags;
+ fido_dev_force_fido2;
+ fido_dev_force_pin_change;
+ fido_dev_force_u2f;
+ fido_dev_free;
+ fido_dev_get_assert;
+ fido_dev_get_cbor_info;
+ fido_dev_get_retry_count;
+ fido_dev_get_uv_retry_count;
+ fido_dev_get_touch_begin;
+ fido_dev_get_touch_status;
+ fido_dev_has_pin;
+ fido_dev_has_uv;
+ fido_dev_info_free;
+ fido_dev_info_manifest;
+ fido_dev_info_manufacturer_string;
+ fido_dev_info_new;
+ fido_dev_info_path;
+ fido_dev_info_product;
+ fido_dev_info_product_string;
+ fido_dev_info_ptr;
+ fido_dev_info_set;
+ fido_dev_info_vendor;
+ fido_dev_is_fido2;
+ fido_dev_major;
+ fido_dev_make_cred;
+ fido_dev_minor;
+ fido_dev_new;
+ fido_dev_open;
+ fido_dev_protocol;
+ fido_dev_reset;
+ fido_dev_set_io_functions;
+ fido_dev_set_pcsc;
+ fido_dev_set_pin;
+ fido_dev_set_pin_minlen;
+ fido_dev_set_pin_minlen_rpid;
+ fido_dev_set_timeout;
+ fido_dev_set_transport_functions;
+ fido_dev_supports_cred_prot;
+ fido_dev_supports_credman;
+ fido_dev_supports_permissions;
+ fido_dev_supports_pin;
+ fido_dev_supports_uv;
+ fido_dev_toggle_always_uv;
+ fido_dev_largeblob_get;
+ fido_dev_largeblob_get_array;
+ fido_dev_largeblob_remove;
+ fido_dev_largeblob_set;
+ fido_dev_largeblob_set_array;
+ fido_hid_get_report_len;
+ fido_hid_get_usage;
+ fido_init;
+ fido_nfc_rx;
+ fido_nfc_tx;
+ fido_nl_free;
+ fido_nl_get_nfc_target;
+ fido_nl_new;
+ fido_nl_power_nfc;
+ fido_pcsc_close;
+ fido_pcsc_manifest;
+ fido_pcsc_open;
+ fido_pcsc_read;
+ fido_pcsc_rx;
+ fido_pcsc_tx;
+ fido_pcsc_write;
+ fido_set_log_handler;
+ fido_strerr;
+ rs256_pk_free;
+ rs256_pk_from_ptr;
+ rs256_pk_from_EVP_PKEY;
+ rs256_pk_from_RSA;
+ rs256_pk_new;
+ rs256_pk_to_EVP_PKEY;
+ prng_init;
+ prng_up;
+ fuzz_clock_reset;
+ fuzz_save_corpus;
+ set_netlink_io_functions;
+ set_pcsc_parameters;
+ set_pcsc_io_functions;
+ set_udev_parameters;
+ uniform_random;
+ local:
+ *;
+};
diff --git a/fuzz/functions.txt b/fuzz/functions.txt
new file mode 100644
index 0000000..4ad5a0c
--- /dev/null
+++ b/fuzz/functions.txt
@@ -0,0 +1,954 @@
+File '/libfido2/src/aes256.c':
+Name Regions Miss Cover Lines Miss Cover
+--------------------------------------------------------------------------------------------------------
+aes256_cbc_enc 4 0 100.00% 4 0 100.00%
+aes256_cbc_dec 4 0 100.00% 4 0 100.00%
+aes256_gcm_enc 1 0 100.00% 3 0 100.00%
+aes256_gcm_dec 1 0 100.00% 3 0 100.00%
+aes256.c:aes256_cbc_fips 26 1 96.15% 42 4 90.48%
+aes256.c:aes256_cbc 29 1 96.55% 36 3 91.67%
+aes256.c:aes256_cbc_proto1 1 0 100.00% 5 0 100.00%
+aes256.c:aes256_gcm 52 1 98.08% 60 4 93.33%
+--------------------------------------------------------------------------------------------------------
+TOTAL 118 3 97.46% 157 11 92.99%
+
+File '/libfido2/src/assert.c':
+Name Regions Miss Cover Lines Miss Cover
+-----------------------------------------------------------------------------------------------------------------
+fido_dev_get_assert 40 0 100.00% 35 0 100.00%
+fido_check_flags 13 0 100.00% 15 0 100.00%
+fido_get_signed_hash 20 1 95.00% 34 3 91.18%
+fido_assert_verify 50 4 92.00% 70 7 90.00%
+fido_assert_set_clientdata 12 12 0.00% 11 11 0.00%
+fido_assert_set_clientdata_hash 8 0 100.00% 6 0 100.00%
+fido_assert_set_hmac_salt 10 0 100.00% 6 0 100.00%
+fido_assert_set_hmac_secret 12 12 0.00% 7 7 0.00%
+fido_assert_set_rp 12 0 100.00% 11 0 100.00%
+fido_assert_set_winhello_appid 2 2 0.00% 5 5 0.00%
+fido_assert_allow_cred 13 2 84.62% 22 3 86.36%
+fido_assert_empty_allow_list 2 0 100.00% 5 0 100.00%
+fido_assert_set_extensions 14 0 100.00% 10 0 100.00%
+fido_assert_set_options 8 8 0.00% 5 5 0.00%
+fido_assert_set_up 2 0 100.00% 4 0 100.00%
+fido_assert_set_uv 2 0 100.00% 4 0 100.00%
+fido_assert_clientdata_hash_ptr 1 0 100.00% 3 0 100.00%
+fido_assert_clientdata_hash_len 1 0 100.00% 3 0 100.00%
+fido_assert_new 1 0 100.00% 3 0 100.00%
+fido_assert_reset_tx 1 0 100.00% 13 0 100.00%
+fido_assert_reset_rx 4 0 100.00% 20 0 100.00%
+fido_assert_free 6 0 100.00% 9 0 100.00%
+fido_assert_count 1 0 100.00% 3 0 100.00%
+fido_assert_rp_id 1 0 100.00% 3 0 100.00%
+fido_assert_flags 4 0 100.00% 5 0 100.00%
+fido_assert_sigcount 4 0 100.00% 5 0 100.00%
+fido_assert_authdata_ptr 4 0 100.00% 5 0 100.00%
+fido_assert_authdata_len 4 0 100.00% 5 0 100.00%
+fido_assert_authdata_raw_ptr 4 0 100.00% 5 0 100.00%
+fido_assert_authdata_raw_len 4 0 100.00% 5 0 100.00%
+fido_assert_sig_ptr 4 0 100.00% 5 0 100.00%
+fido_assert_sig_len 4 0 100.00% 5 0 100.00%
+fido_assert_id_ptr 4 0 100.00% 5 0 100.00%
+fido_assert_id_len 4 0 100.00% 5 0 100.00%
+fido_assert_user_id_ptr 4 0 100.00% 5 0 100.00%
+fido_assert_user_id_len 4 0 100.00% 5 0 100.00%
+fido_assert_user_icon 4 0 100.00% 5 0 100.00%
+fido_assert_user_name 4 0 100.00% 5 0 100.00%
+fido_assert_user_display_name 4 0 100.00% 5 0 100.00%
+fido_assert_hmac_secret_ptr 4 0 100.00% 5 0 100.00%
+fido_assert_hmac_secret_len 4 0 100.00% 5 0 100.00%
+fido_assert_largeblob_key_ptr 4 0 100.00% 5 0 100.00%
+fido_assert_largeblob_key_len 4 0 100.00% 5 0 100.00%
+fido_assert_blob_ptr 4 0 100.00% 5 0 100.00%
+fido_assert_blob_len 4 0 100.00% 5 0 100.00%
+fido_assert_set_authdata 28 0 100.00% 33 0 100.00%
+fido_assert_set_authdata_raw 28 0 100.00% 32 0 100.00%
+fido_assert_set_sig 14 0 100.00% 7 0 100.00%
+fido_assert_set_count 10 0 100.00% 17 0 100.00%
+assert.c:fido_dev_get_assert_wait 21 0 100.00% 14 0 100.00%
+assert.c:fido_dev_get_assert_tx 56 2 96.43% 62 5 91.94%
+assert.c:fido_dev_get_assert_rx 27 0 100.00% 36 0 100.00%
+assert.c:adjust_assert_count 24 0 100.00% 26 0 100.00%
+assert.c:parse_assert_reply 15 0 100.00% 28 0 100.00%
+assert.c:fido_get_next_assert_tx 8 0 100.00% 8 0 100.00%
+assert.c:fido_get_next_assert_rx 23 2 91.30% 29 5 82.76%
+assert.c:decrypt_hmac_secrets 9 0 100.00% 15 0 100.00%
+assert.c:get_es256_hash 16 0 100.00% 17 0 100.00%
+assert.c:get_es384_hash 16 0 100.00% 17 0 100.00%
+assert.c:get_eddsa_hash 6 0 100.00% 9 0 100.00%
+assert.c:check_extensions 5 0 100.00% 9 0 100.00%
+assert.c:fido_assert_reset_extattr 1 0 100.00% 5 0 100.00%
+assert.c:fido_assert_clean_authdata 1 0 100.00% 6 0 100.00%
+-----------------------------------------------------------------------------------------------------------------
+TOTAL 628 45 92.83% 782 51 93.48%
+
+File '/libfido2/src/authkey.c':
+Name Regions Miss Cover Lines Miss Cover
+-----------------------------------------------------------------------------------------------------------------
+fido_dev_authkey 1 0 100.00% 3 0 100.00%
+authkey.c:fido_dev_authkey_wait 10 0 100.00% 7 0 100.00%
+authkey.c:fido_dev_authkey_tx 19 0 100.00% 25 0 100.00%
+authkey.c:fido_dev_authkey_rx 14 0 100.00% 21 0 100.00%
+authkey.c:parse_authkey 8 0 100.00% 10 0 100.00%
+-----------------------------------------------------------------------------------------------------------------
+TOTAL 52 0 100.00% 66 0 100.00%
+
+File '/libfido2/src/bio.c':
+Name Regions Miss Cover Lines Miss Cover
+-----------------------------------------------------------------------------------------------------------------
+fido_bio_dev_get_template_array 5 2 60.00% 6 1 83.33%
+fido_bio_dev_set_template_name 7 0 100.00% 6 0 100.00%
+fido_bio_dev_enroll_begin 25 2 92.00% 31 1 96.77%
+fido_bio_dev_enroll_continue 5 2 60.00% 6 1 83.33%
+fido_bio_dev_enroll_cancel 1 1 0.00% 4 4 0.00%
+fido_bio_dev_enroll_remove 1 0 100.00% 4 0 100.00%
+fido_bio_dev_get_info 1 0 100.00% 4 0 100.00%
+fido_bio_template_name 1 0 100.00% 3 0 100.00%
+fido_bio_template_id_ptr 1 0 100.00% 3 0 100.00%
+fido_bio_template_id_len 1 0 100.00% 3 0 100.00%
+fido_bio_template_array_count 1 0 100.00% 3 0 100.00%
+fido_bio_template_array_new 1 0 100.00% 3 0 100.00%
+fido_bio_template_new 1 0 100.00% 3 0 100.00%
+fido_bio_template_array_free 6 0 100.00% 8 0 100.00%
+fido_bio_template_free 6 0 100.00% 8 0 100.00%
+fido_bio_template_set_name 8 0 100.00% 7 0 100.00%
+fido_bio_template_set_id 8 0 100.00% 6 0 100.00%
+fido_bio_template 4 0 100.00% 5 0 100.00%
+fido_bio_enroll_new 1 0 100.00% 3 0 100.00%
+fido_bio_info_new 1 0 100.00% 3 0 100.00%
+fido_bio_info_type 1 0 100.00% 3 0 100.00%
+fido_bio_info_max_samples 1 0 100.00% 3 0 100.00%
+fido_bio_enroll_free 6 0 100.00% 8 0 100.00%
+fido_bio_info_free 6 0 100.00% 7 0 100.00%
+fido_bio_enroll_remaining_samples 1 0 100.00% 3 0 100.00%
+fido_bio_enroll_last_status 1 0 100.00% 3 0 100.00%
+bio.c:bio_get_template_array_wait 11 0 100.00% 7 0 100.00%
+bio.c:bio_tx 43 0 100.00% 55 0 100.00%
+bio.c:bio_prepare_hmac 18 0 100.00% 29 0 100.00%
+bio.c:bio_rx_template_array 19 0 100.00% 24 0 100.00%
+bio.c:bio_parse_template_array 26 1 96.15% 27 4 85.19%
+bio.c:decode_template_array 12 1 91.67% 18 3 83.33%
+bio.c:decode_template 9 0 100.00% 15 0 100.00%
+bio.c:bio_set_template_name_wait 19 0 100.00% 20 0 100.00%
+bio.c:bio_enroll_begin_wait 17 0 100.00% 19 0 100.00%
+bio.c:bio_rx_enroll_begin 23 0 100.00% 31 0 100.00%
+bio.c:bio_parse_enroll_status 20 0 100.00% 28 0 100.00%
+bio.c:bio_parse_template_id 8 0 100.00% 10 0 100.00%
+bio.c:bio_enroll_continue_wait 19 0 100.00% 20 0 100.00%
+bio.c:bio_rx_enroll_continue 19 0 100.00% 25 0 100.00%
+bio.c:bio_enroll_cancel_wait 11 11 0.00% 10 10 0.00%
+bio.c:bio_enroll_remove_wait 17 0 100.00% 19 0 100.00%
+bio.c:bio_get_info_wait 11 0 100.00% 10 0 100.00%
+bio.c:bio_rx_info 19 0 100.00% 24 0 100.00%
+bio.c:bio_reset_info 1 0 100.00% 4 0 100.00%
+bio.c:bio_parse_info 20 0 100.00% 28 0 100.00%
+bio.c:bio_reset_template_array 4 0 100.00% 7 0 100.00%
+bio.c:bio_reset_template 1 0 100.00% 5 0 100.00%
+bio.c:bio_reset_enroll 3 0 100.00% 6 0 100.00%
+-----------------------------------------------------------------------------------------------------------------
+TOTAL 451 20 95.57% 587 24 95.91%
+
+File '/libfido2/src/blob.c':
+Name Regions Miss Cover Lines Miss Cover
+-----------------------------------------------------------------------------------------------------------------
+fido_blob_new 1 0 100.00% 3 0 100.00%
+fido_blob_reset 1 0 100.00% 4 0 100.00%
+fido_blob_set 9 0 100.00% 15 0 100.00%
+fido_blob_append 12 1 91.67% 20 3 85.00%
+fido_blob_free 6 0 100.00% 8 0 100.00%
+fido_free_blob_array 7 0 100.00% 12 0 100.00%
+fido_blob_encode 6 0 100.00% 5 0 100.00%
+fido_blob_decode 1 0 100.00% 3 0 100.00%
+fido_blob_is_empty 3 0 100.00% 3 0 100.00%
+fido_blob_serialise 7 1 85.71% 10 1 90.00%
+-----------------------------------------------------------------------------------------------------------------
+TOTAL 53 2 96.23% 83 4 95.18%
+
+File '/libfido2/src/buf.c':
+Name Regions Miss Cover Lines Miss Cover
+-----------------------------------------------------------------------------------------------------------------
+fido_buf_read 4 0 100.00% 8 0 100.00%
+fido_buf_write 4 1 75.00% 8 1 87.50%
+-----------------------------------------------------------------------------------------------------------------
+TOTAL 8 1 87.50% 16 1 93.75%
+
+File '/libfido2/src/cbor.c':
+Name Regions Miss Cover Lines Miss Cover
+------------------------------------------------------------------------------------------------------------------
+cbor_map_iter 20 1 95.00% 26 4 84.62%
+cbor_array_iter 12 0 100.00% 16 0 100.00%
+cbor_parse_reply 27 0 100.00% 36 0 100.00%
+cbor_vector_free 6 0 100.00% 5 0 100.00%
+cbor_bytestring_copy 14 0 100.00% 18 0 100.00%
+cbor_string_copy 14 0 100.00% 18 0 100.00%
+cbor_add_bytestring 14 0 100.00% 21 0 100.00%
+cbor_add_string 14 0 100.00% 21 0 100.00%
+cbor_add_bool 14 0 100.00% 21 0 100.00%
+cbor_flatten_vector 14 1 92.86% 16 1 93.75%
+cbor_build_frame 15 0 100.00% 25 0 100.00%
+cbor_encode_rp_entity 13 0 100.00% 11 0 100.00%
+cbor_encode_user_entity 21 0 100.00% 15 0 100.00%
+cbor_encode_pubkey_param 36 0 100.00% 39 0 100.00%
+cbor_encode_pubkey 10 0 100.00% 11 0 100.00%
+cbor_encode_pubkey_list 18 0 100.00% 19 0 100.00%
+cbor_encode_str_array 18 0 100.00% 19 0 100.00%
+cbor_encode_cred_ext 55 0 100.00% 50 0 100.00%
+cbor_encode_cred_opt 13 0 100.00% 11 0 100.00%
+cbor_encode_assert_opt 13 0 100.00% 11 0 100.00%
+cbor_encode_pin_auth 21 1 95.24% 22 3 86.36%
+cbor_encode_pin_opt 4 0 100.00% 8 0 100.00%
+cbor_encode_change_pin_auth 32 1 96.88% 36 3 91.67%
+cbor_encode_assert_ext 33 0 100.00% 32 0 100.00%
+cbor_decode_fmt 13 0 100.00% 15 0 100.00%
+cbor_decode_pubkey 26 1 96.15% 36 2 94.44%
+cbor_decode_cred_authdata 31 1 96.77% 35 3 91.43%
+cbor_decode_assert_authdata 21 1 95.24% 32 3 90.62%
+cbor_decode_attstmt 13 0 100.00% 16 0 100.00%
+cbor_decode_uint64 4 0 100.00% 8 0 100.00%
+cbor_decode_cred_id 8 0 100.00% 9 0 100.00%
+cbor_decode_user 8 0 100.00% 9 0 100.00%
+cbor_decode_rp_entity 8 0 100.00% 9 0 100.00%
+cbor_decode_bool 10 0 100.00% 11 0 100.00%
+cbor_build_uint 10 1 90.00% 9 1 88.89%
+cbor_array_append 17 0 100.00% 21 0 100.00%
+cbor_array_drop 18 0 100.00% 17 0 100.00%
+cbor.c:ctap_check_cbor 28 0 100.00% 26 0 100.00%
+cbor.c:check_key_type 8 0 100.00% 7 0 100.00%
+cbor.c:cbor_add_arg 13 0 100.00% 21 0 100.00%
+cbor.c:cbor_add_uint8 14 0 100.00% 21 0 100.00%
+cbor.c:cbor_encode_largeblob_key_ext 6 0 100.00% 6 0 100.00%
+cbor.c:cbor_encode_hmac_secret_param 59 4 93.22% 66 8 87.88%
+cbor.c:get_cose_alg 46 0 100.00% 45 0 100.00%
+cbor.c:find_cose_alg 35 0 100.00% 33 0 100.00%
+cbor.c:decode_attcred 25 0 100.00% 44 0 100.00%
+cbor.c:decode_cred_extensions 14 0 100.00% 24 0 100.00%
+cbor.c:decode_cred_extension 41 0 100.00% 45 0 100.00%
+cbor.c:decode_assert_extensions 14 0 100.00% 23 0 100.00%
+cbor.c:decode_assert_extension 19 0 100.00% 27 0 100.00%
+cbor.c:decode_attstmt_entry 56 0 100.00% 51 0 100.00%
+cbor.c:decode_x5c 4 0 100.00% 6 0 100.00%
+cbor.c:decode_cred_id_entry 10 0 100.00% 19 0 100.00%
+cbor.c:decode_user_entry 25 0 100.00% 35 0 100.00%
+cbor.c:decode_rp_entity_entry 15 0 100.00% 25 0 100.00%
+------------------------------------------------------------------------------------------------------------------
+TOTAL 1070 12 98.88% 1258 28 97.77%
+
+File '/libfido2/src/compress.c':
+Name Regions Miss Cover Lines Miss Cover
+------------------------------------------------------------------------------------------------------------------
+fido_compress 1 0 100.00% 3 0 100.00%
+fido_uncompress 6 0 100.00% 5 0 100.00%
+compress.c:rfc1951_deflate 33 4 87.88% 47 6 87.23%
+compress.c:rfc1950_inflate 27 2 92.59% 22 4 81.82%
+compress.c:rfc1951_inflate 38 8 78.95% 45 14 68.89%
+------------------------------------------------------------------------------------------------------------------
+TOTAL 105 14 86.67% 122 24 80.33%
+
+File '/libfido2/src/config.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_dev_enable_entattest 1 0 100.00% 4 0 100.00%
+fido_dev_toggle_always_uv 1 0 100.00% 4 0 100.00%
+fido_dev_set_pin_minlen 1 0 100.00% 4 0 100.00%
+fido_dev_force_pin_change 1 0 100.00% 4 0 100.00%
+fido_dev_set_pin_minlen_rpid 6 0 100.00% 15 0 100.00%
+config.c:config_enable_entattest_wait 6 0 100.00% 7 0 100.00%
+config.c:config_tx 39 0 100.00% 49 0 100.00%
+config.c:config_prepare_hmac 10 0 100.00% 21 0 100.00%
+config.c:config_toggle_always_uv_wait 6 0 100.00% 7 0 100.00%
+config.c:config_pin_minlen 5 0 100.00% 7 0 100.00%
+config.c:config_pin_minlen_tx 36 0 100.00% 32 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 112 0 100.00% 154 0 100.00%
+
+File '/libfido2/src/cred.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_dev_make_cred 12 0 100.00% 10 0 100.00%
+fido_check_rp_id 4 0 100.00% 11 0 100.00%
+fido_cred_verify 59 2 96.61% 75 4 94.67%
+fido_cred_verify_self 60 4 93.33% 87 7 91.95%
+fido_cred_new 1 0 100.00% 3 0 100.00%
+fido_cred_reset_tx 1 0 100.00% 18 0 100.00%
+fido_cred_reset_rx 1 0 100.00% 7 0 100.00%
+fido_cred_free 6 0 100.00% 9 0 100.00%
+fido_cred_set_authdata 23 0 100.00% 28 0 100.00%
+fido_cred_set_authdata_raw 25 0 100.00% 29 0 100.00%
+fido_cred_set_id 6 0 100.00% 5 0 100.00%
+fido_cred_set_x509 6 0 100.00% 5 0 100.00%
+fido_cred_set_sig 6 0 100.00% 5 0 100.00%
+fido_cred_set_attstmt 20 0 100.00% 23 0 100.00%
+fido_cred_exclude 14 2 85.71% 19 3 84.21%
+fido_cred_empty_exclude_list 2 0 100.00% 5 0 100.00%
+fido_cred_set_clientdata 12 12 0.00% 11 11 0.00%
+fido_cred_set_clientdata_hash 8 0 100.00% 6 0 100.00%
+fido_cred_set_rp 18 0 100.00% 22 0 100.00%
+fido_cred_set_user 32 0 100.00% 41 0 100.00%
+fido_cred_set_extensions 16 0 100.00% 10 0 100.00%
+fido_cred_set_options 8 8 0.00% 5 5 0.00%
+fido_cred_set_rk 2 0 100.00% 4 0 100.00%
+fido_cred_set_uv 2 0 100.00% 4 0 100.00%
+fido_cred_set_prot 21 0 100.00% 14 0 100.00%
+fido_cred_set_pin_minlen 7 0 100.00% 8 0 100.00%
+fido_cred_set_blob 13 0 100.00% 8 0 100.00%
+fido_cred_set_fmt 20 4 80.00% 12 2 83.33%
+fido_cred_set_type 23 2 91.30% 9 1 88.89%
+fido_cred_type 1 0 100.00% 3 0 100.00%
+fido_cred_flags 1 0 100.00% 3 0 100.00%
+fido_cred_sigcount 1 0 100.00% 3 0 100.00%
+fido_cred_clientdata_hash_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_clientdata_hash_len 1 0 100.00% 3 0 100.00%
+fido_cred_x5c_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_x5c_len 1 0 100.00% 3 0 100.00%
+fido_cred_sig_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_sig_len 1 0 100.00% 3 0 100.00%
+fido_cred_authdata_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_authdata_len 1 0 100.00% 3 0 100.00%
+fido_cred_authdata_raw_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_authdata_raw_len 1 0 100.00% 3 0 100.00%
+fido_cred_attstmt_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_attstmt_len 1 0 100.00% 3 0 100.00%
+fido_cred_pubkey_ptr 11 0 100.00% 21 0 100.00%
+fido_cred_pubkey_len 11 0 100.00% 21 0 100.00%
+fido_cred_id_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_id_len 1 0 100.00% 3 0 100.00%
+fido_cred_aaguid_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_aaguid_len 1 0 100.00% 3 0 100.00%
+fido_cred_prot 1 0 100.00% 3 0 100.00%
+fido_cred_pin_minlen 1 0 100.00% 3 0 100.00%
+fido_cred_fmt 1 0 100.00% 3 0 100.00%
+fido_cred_rp_id 1 0 100.00% 3 0 100.00%
+fido_cred_rp_name 1 0 100.00% 3 0 100.00%
+fido_cred_user_name 1 0 100.00% 3 0 100.00%
+fido_cred_display_name 1 0 100.00% 3 0 100.00%
+fido_cred_user_id_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_user_id_len 1 0 100.00% 3 0 100.00%
+fido_cred_largeblob_key_ptr 1 0 100.00% 3 0 100.00%
+fido_cred_largeblob_key_len 1 0 100.00% 3 0 100.00%
+cred.c:fido_dev_make_cred_wait 10 0 100.00% 7 0 100.00%
+cred.c:fido_dev_make_cred_tx 64 0 100.00% 70 0 100.00%
+cred.c:fido_dev_make_cred_rx 29 0 100.00% 32 0 100.00%
+cred.c:parse_makecred_reply 14 0 100.00% 27 0 100.00%
+cred.c:check_extensions 2 0 100.00% 6 0 100.00%
+cred.c:get_signed_hash_u2f 27 0 100.00% 27 0 100.00%
+cred.c:verify_attstmt 25 2 92.00% 43 6 86.05%
+cred.c:fido_cred_clean_authdata 1 0 100.00% 8 0 100.00%
+cred.c:fido_cred_clean_attstmt 1 0 100.00% 8 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 653 36 94.49% 853 39 95.43%
+
+File '/libfido2/src/credman.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_credman_get_dev_metadata 1 0 100.00% 4 0 100.00%
+fido_credman_get_dev_rk 1 0 100.00% 4 0 100.00%
+fido_credman_del_dev_rk 1 0 100.00% 4 0 100.00%
+fido_credman_get_dev_rp 1 0 100.00% 4 0 100.00%
+fido_credman_set_dev_rk 1 0 100.00% 4 0 100.00%
+fido_credman_rk_new 1 0 100.00% 3 0 100.00%
+fido_credman_rk_free 6 1 83.33% 8 1 87.50%
+fido_credman_rk_count 1 0 100.00% 3 0 100.00%
+fido_credman_rk 4 0 100.00% 5 0 100.00%
+fido_credman_metadata_new 1 0 100.00% 3 0 100.00%
+fido_credman_metadata_free 6 1 83.33% 7 1 85.71%
+fido_credman_rk_existing 1 0 100.00% 3 0 100.00%
+fido_credman_rk_remaining 1 0 100.00% 3 0 100.00%
+fido_credman_rp_new 1 0 100.00% 3 0 100.00%
+fido_credman_rp_free 6 1 83.33% 8 1 87.50%
+fido_credman_rp_count 1 0 100.00% 3 0 100.00%
+fido_credman_rp_id 4 0 100.00% 5 0 100.00%
+fido_credman_rp_name 4 0 100.00% 5 0 100.00%
+fido_credman_rp_id_hash_len 4 0 100.00% 5 0 100.00%
+fido_credman_rp_id_hash_ptr 4 0 100.00% 5 0 100.00%
+credman.c:credman_get_metadata_wait 11 0 100.00% 8 0 100.00%
+credman.c:credman_tx 36 0 100.00% 50 0 100.00%
+credman.c:credman_prepare_hmac 31 1 96.77% 50 2 96.00%
+credman.c:credman_rx_metadata 19 0 100.00% 24 0 100.00%
+credman.c:credman_parse_metadata 9 0 100.00% 17 0 100.00%
+credman.c:credman_get_rk_wait 27 0 100.00% 23 0 100.00%
+credman.c:credman_rx_rk 27 0 100.00% 35 0 100.00%
+credman.c:credman_parse_rk_count 16 0 100.00% 20 0 100.00%
+credman.c:credman_grow_array 17 2 88.24% 21 5 76.19%
+credman.c:credman_parse_rk 23 0 100.00% 31 0 100.00%
+credman.c:credman_rx_next_rk 23 2 91.30% 29 5 82.76%
+credman.c:credman_del_rk_wait 16 0 100.00% 15 0 100.00%
+credman.c:credman_get_rp_wait 23 0 100.00% 15 0 100.00%
+credman.c:credman_rx_rp 27 0 100.00% 35 0 100.00%
+credman.c:credman_parse_rp_count 16 0 100.00% 20 0 100.00%
+credman.c:credman_parse_rp 9 0 100.00% 17 0 100.00%
+credman.c:credman_rx_next_rp 23 2 91.30% 29 5 82.76%
+credman.c:credman_set_dev_rk_wait 11 0 100.00% 8 0 100.00%
+credman.c:credman_reset_rk 4 0 100.00% 9 0 100.00%
+credman.c:credman_reset_rp 4 0 100.00% 12 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 422 10 97.63% 557 20 96.41%
+
+File '/libfido2/src/dev.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_dev_info_manifest 2 0 100.00% 11 0 100.00%
+fido_dev_open_with_info 5 5 0.00% 6 6 0.00%
+fido_dev_open 13 4 69.23% 16 6 62.50%
+fido_dev_close 9 2 77.78% 8 1 87.50%
+fido_dev_set_sigmask 18 18 0.00% 11 11 0.00%
+fido_dev_cancel 11 0 100.00% 8 0 100.00%
+fido_dev_set_io_functions 18 4 77.78% 14 6 57.14%
+fido_dev_set_transport_functions 6 2 66.67% 9 3 66.67%
+fido_dev_io_handle 1 1 0.00% 3 3 0.00%
+fido_init 8 1 87.50% 5 0 100.00%
+fido_dev_new 5 0 100.00% 14 0 100.00%
+fido_dev_new_with_info 10 10 0.00% 16 16 0.00%
+fido_dev_free 6 0 100.00% 8 0 100.00%
+fido_dev_protocol 1 0 100.00% 3 0 100.00%
+fido_dev_major 1 0 100.00% 3 0 100.00%
+fido_dev_minor 1 0 100.00% 3 0 100.00%
+fido_dev_build 1 0 100.00% 3 0 100.00%
+fido_dev_flags 1 0 100.00% 3 0 100.00%
+fido_dev_is_fido2 2 0 100.00% 3 0 100.00%
+fido_dev_is_winhello 2 2 0.00% 3 3 0.00%
+fido_dev_supports_pin 3 0 100.00% 3 0 100.00%
+fido_dev_has_pin 2 0 100.00% 3 0 100.00%
+fido_dev_supports_cred_prot 2 0 100.00% 3 0 100.00%
+fido_dev_supports_credman 2 0 100.00% 3 0 100.00%
+fido_dev_supports_uv 3 0 100.00% 3 0 100.00%
+fido_dev_has_uv 2 0 100.00% 3 0 100.00%
+fido_dev_supports_permissions 2 0 100.00% 3 0 100.00%
+fido_dev_force_u2f 2 0 100.00% 4 0 100.00%
+fido_dev_force_fido2 2 2 0.00% 3 3 0.00%
+fido_dev_get_pin_protocol 11 0 100.00% 7 0 100.00%
+fido_dev_maxmsgsize 1 0 100.00% 3 0 100.00%
+fido_dev_set_timeout 6 2 66.67% 6 1 83.33%
+dev.c:run_manifest 10 0 100.00% 13 0 100.00%
+dev.c:fido_dev_open_wait 10 0 100.00% 7 0 100.00%
+dev.c:fido_dev_open_tx 56 11 80.36% 56 20 64.29%
+dev.c:set_random_report_len 11 0 100.00% 6 0 100.00%
+dev.c:fido_dev_open_rx 36 1 97.22% 53 1 98.11%
+dev.c:fido_dev_set_flags 1 0 100.00% 5 0 100.00%
+dev.c:fido_dev_set_extension_flags 7 0 100.00% 7 0 100.00%
+dev.c:fido_dev_set_option_flags 31 0 100.00% 20 0 100.00%
+dev.c:fido_dev_set_protocol_flags 11 0 100.00% 17 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 332 65 80.42% 378 80 78.84%
+
+File '/libfido2/src/ecdh.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_do_ecdh 29 0 100.00% 36 0 100.00%
+ecdh.c:do_ecdh 37 0 100.00% 44 0 100.00%
+ecdh.c:kdf 19 1 94.74% 28 2 92.86%
+ecdh.c:hkdf_sha256 32 1 96.88% 38 3 92.11%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 117 2 98.29% 146 5 96.58%
+
+File '/libfido2/src/eddsa.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+eddsa_pk_decode 8 0 100.00% 9 0 100.00%
+eddsa_pk_new 1 0 100.00% 3 0 100.00%
+eddsa_pk_free 6 0 100.00% 7 0 100.00%
+eddsa_pk_from_ptr 10 0 100.00% 12 0 100.00%
+eddsa_pk_to_EVP_PKEY 3 0 100.00% 7 0 100.00%
+eddsa_pk_from_EVP_PKEY 18 2 88.89% 12 1 91.67%
+eddsa_verify_sig 19 2 89.47% 30 6 80.00%
+eddsa_pk_verify_sig 7 1 85.71% 13 2 84.62%
+eddsa.c:decode_pubkey_point 8 0 100.00% 11 0 100.00%
+eddsa.c:decode_coord 8 0 100.00% 10 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 88 5 94.32% 114 9 92.11%
+
+File '/libfido2/src/err.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_strerr 122 10 91.80% 126 10 92.06%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 122 10 91.80% 126 10 92.06%
+
+File '/libfido2/src/es256.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+es256_pk_decode 8 0 100.00% 9 0 100.00%
+es256_pk_encode 56 0 100.00% 48 0 100.00%
+es256_sk_new 1 0 100.00% 3 0 100.00%
+es256_sk_free 6 0 100.00% 7 0 100.00%
+es256_pk_new 1 0 100.00% 3 0 100.00%
+es256_pk_free 6 0 100.00% 7 0 100.00%
+es256_pk_from_ptr 15 0 100.00% 17 0 100.00%
+es256_pk_set_x 1 0 100.00% 4 0 100.00%
+es256_pk_set_y 1 0 100.00% 4 0 100.00%
+es256_sk_create 39 0 100.00% 40 0 100.00%
+es256_pk_to_EVP_PKEY 42 0 100.00% 53 0 100.00%
+es256_pk_from_EC_KEY 42 2 95.24% 47 4 91.49%
+es256_pk_from_EVP_PKEY 8 0 100.00% 7 0 100.00%
+es256_sk_to_EVP_PKEY 28 0 100.00% 39 0 100.00%
+es256_derive_pk 25 0 100.00% 29 0 100.00%
+es256_verify_sig 12 2 83.33% 19 5 73.68%
+es256_pk_verify_sig 7 1 85.71% 13 2 84.62%
+es256.c:decode_pubkey_point 9 0 100.00% 13 0 100.00%
+es256.c:decode_coord 8 0 100.00% 10 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 315 5 98.41% 372 11 97.04%
+
+File '/libfido2/src/es384.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+es384_pk_decode 8 0 100.00% 9 0 100.00%
+es384_pk_new 1 0 100.00% 3 0 100.00%
+es384_pk_free 6 0 100.00% 7 0 100.00%
+es384_pk_from_ptr 15 0 100.00% 17 0 100.00%
+es384_pk_to_EVP_PKEY 42 0 100.00% 53 0 100.00%
+es384_pk_from_EC_KEY 42 2 95.24% 47 4 91.49%
+es384_pk_from_EVP_PKEY 8 0 100.00% 7 0 100.00%
+es384_verify_sig 12 2 83.33% 19 5 73.68%
+es384_pk_verify_sig 7 1 85.71% 13 2 84.62%
+es384.c:decode_pubkey_point 9 0 100.00% 13 0 100.00%
+es384.c:decode_coord 8 0 100.00% 10 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 158 5 96.84% 198 11 94.44%
+
+File '/libfido2/src/extern.h':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+
+File '/libfido2/src/fallthrough.h':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+
+File '/libfido2/src/fido.h':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+
+File '/libfido2/src/hid.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_hid_get_usage 13 0 100.00% 22 0 100.00%
+fido_hid_get_report_len 19 0 100.00% 27 0 100.00%
+fido_dev_info_new 1 0 100.00% 3 0 100.00%
+fido_dev_info_free 9 0 100.00% 9 0 100.00%
+fido_dev_info_ptr 1 0 100.00% 3 0 100.00%
+fido_dev_info_set 26 2 92.31% 30 3 90.00%
+fido_dev_info_path 1 0 100.00% 3 0 100.00%
+fido_dev_info_vendor 1 0 100.00% 3 0 100.00%
+fido_dev_info_product 1 0 100.00% 3 0 100.00%
+fido_dev_info_manufacturer_string 1 0 100.00% 3 0 100.00%
+fido_dev_info_product_string 1 0 100.00% 3 0 100.00%
+hid.c:get_key_len 6 0 100.00% 12 0 100.00%
+hid.c:get_key_val 6 0 100.00% 18 0 100.00%
+hid.c:fido_dev_info_reset 1 0 100.00% 6 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 87 2 97.70% 145 3 97.93%
+
+File '/libfido2/src/hid_linux.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_hid_manifest 35 4 88.57% 41 2 95.12%
+fido_hid_open 33 33 0.00% 51 51 0.00%
+fido_hid_close 3 3 0.00% 6 6 0.00%
+fido_hid_set_sigmask 2 2 0.00% 6 6 0.00%
+fido_hid_read 15 15 0.00% 21 21 0.00%
+fido_hid_write 12 12 0.00% 17 17 0.00%
+fido_hid_report_in_len 1 1 0.00% 4 4 0.00%
+fido_hid_report_out_len 1 1 0.00% 4 4 0.00%
+hid_linux.c:copy_info 34 0 100.00% 44 0 100.00%
+hid_linux.c:is_fido 15 1 93.33% 16 1 93.75%
+hid_linux.c:get_parent_attr 6 0 100.00% 9 0 100.00%
+hid_linux.c:parse_uevent 12 0 100.00% 24 0 100.00%
+hid_linux.c:get_usb_attr 1 0 100.00% 3 0 100.00%
+hid_linux.c:get_report_descriptor 14 1 92.86% 17 3 82.35%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 184 73 60.33% 263 115 56.27%
+
+File '/libfido2/src/hid_unix.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_hid_unix_open 18 11 38.89% 22 14 36.36%
+fido_hid_unix_wait 11 10 9.09% 21 12 42.86%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 29 21 27.59% 43 26 39.53%
+
+File '/libfido2/src/info.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_dev_get_cbor_info_wait 10 0 100.00% 7 0 100.00%
+fido_dev_get_cbor_info 1 0 100.00% 4 0 100.00%
+fido_cbor_info_new 4 0 100.00% 7 0 100.00%
+fido_cbor_info_reset 1 0 100.00% 10 0 100.00%
+fido_cbor_info_free 6 0 100.00% 8 0 100.00%
+fido_cbor_info_versions_ptr 1 0 100.00% 3 0 100.00%
+fido_cbor_info_versions_len 1 0 100.00% 3 0 100.00%
+fido_cbor_info_extensions_ptr 1 0 100.00% 3 0 100.00%
+fido_cbor_info_extensions_len 1 0 100.00% 3 0 100.00%
+fido_cbor_info_transports_ptr 1 0 100.00% 3 0 100.00%
+fido_cbor_info_transports_len 1 0 100.00% 3 0 100.00%
+fido_cbor_info_aaguid_ptr 1 0 100.00% 3 0 100.00%
+fido_cbor_info_aaguid_len 1 0 100.00% 3 0 100.00%
+fido_cbor_info_options_name_ptr 1 0 100.00% 3 0 100.00%
+fido_cbor_info_options_value_ptr 1 0 100.00% 3 0 100.00%
+fido_cbor_info_options_len 1 0 100.00% 3 0 100.00%
+fido_cbor_info_maxcredbloblen 1 0 100.00% 3 0 100.00%
+fido_cbor_info_maxmsgsiz 1 0 100.00% 3 0 100.00%
+fido_cbor_info_maxcredcntlst 1 0 100.00% 3 0 100.00%
+fido_cbor_info_maxcredidlen 1 0 100.00% 3 0 100.00%
+fido_cbor_info_maxlargeblob 1 0 100.00% 3 0 100.00%
+fido_cbor_info_fwversion 1 0 100.00% 3 0 100.00%
+fido_cbor_info_minpinlen 1 0 100.00% 3 0 100.00%
+fido_cbor_info_maxrpid_minpinlen 1 0 100.00% 3 0 100.00%
+fido_cbor_info_uv_attempts 1 0 100.00% 3 0 100.00%
+fido_cbor_info_uv_modality 1 0 100.00% 3 0 100.00%
+fido_cbor_info_rk_remaining 1 0 100.00% 3 0 100.00%
+fido_cbor_info_protocols_ptr 1 0 100.00% 3 0 100.00%
+fido_cbor_info_protocols_len 1 0 100.00% 3 0 100.00%
+fido_cbor_info_algorithm_count 1 0 100.00% 3 0 100.00%
+fido_cbor_info_algorithm_type 4 0 100.00% 5 0 100.00%
+fido_cbor_info_algorithm_cose 4 0 100.00% 5 0 100.00%
+fido_cbor_info_new_pin_required 1 0 100.00% 3 0 100.00%
+fido_cbor_info_certs_name_ptr 1 0 100.00% 3 0 100.00%
+fido_cbor_info_certs_value_ptr 1 0 100.00% 3 0 100.00%
+fido_cbor_info_certs_len 1 0 100.00% 3 0 100.00%
+info.c:fido_dev_get_cbor_info_tx 8 0 100.00% 9 0 100.00%
+info.c:fido_dev_get_cbor_info_rx 14 0 100.00% 21 0 100.00%
+info.c:parse_reply_element 32 0 100.00% 59 0 100.00%
+info.c:decode_string_array 12 0 100.00% 17 0 100.00%
+info.c:decode_string 4 0 100.00% 10 0 100.00%
+info.c:decode_aaguid 8 0 100.00% 10 0 100.00%
+info.c:decode_options 11 0 100.00% 15 0 100.00%
+info.c:decode_option 7 0 100.00% 15 0 100.00%
+info.c:decode_protocols 12 0 100.00% 17 0 100.00%
+info.c:decode_protocol 6 0 100.00% 12 0 100.00%
+info.c:decode_algorithms 12 0 100.00% 17 0 100.00%
+info.c:decode_algorithm 9 0 100.00% 17 0 100.00%
+info.c:decode_algorithm_entry 20 0 100.00% 27 0 100.00%
+info.c:decode_certs 11 0 100.00% 15 0 100.00%
+info.c:decode_cert 7 0 100.00% 15 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 232 0 100.00% 409 0 100.00%
+
+File '/libfido2/src/io.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_tx 14 0 100.00% 11 0 100.00%
+fido_rx 13 1 92.31% 14 3 78.57%
+fido_rx_cbor_status 16 0 100.00% 19 0 100.00%
+io.c:transport_tx 7 0 100.00% 10 0 100.00%
+io.c:tx_empty 9 0 100.00% 14 0 100.00%
+io.c:tx_pkt 7 0 100.00% 10 0 100.00%
+io.c:tx 13 0 100.00% 19 0 100.00%
+io.c:tx_preamble 17 1 94.12% 20 1 95.00%
+io.c:tx_frame 16 1 93.75% 18 1 94.44%
+io.c:transport_rx 7 0 100.00% 10 0 100.00%
+io.c:rx 40 2 95.00% 52 2 96.15%
+io.c:rx_preamble 23 2 91.30% 22 5 77.27%
+io.c:rx_frame 11 0 100.00% 11 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 193 7 96.37% 230 12 94.78%
+
+File '/libfido2/src/iso7816.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+iso7816_new 4 0 100.00% 16 0 100.00%
+iso7816_free 6 0 100.00% 7 0 100.00%
+iso7816_add 6 1 83.33% 8 1 87.50%
+iso7816_ptr 1 0 100.00% 3 0 100.00%
+iso7816_len 1 0 100.00% 4 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 18 1 94.44% 38 1 97.37%
+
+File '/libfido2/src/largeblob.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_dev_largeblob_get 26 2 92.31% 38 4 89.47%
+fido_dev_largeblob_set 27 0 100.00% 36 0 100.00%
+fido_dev_largeblob_remove 12 0 100.00% 18 0 100.00%
+fido_dev_largeblob_get_array 15 2 86.67% 27 4 85.19%
+fido_dev_largeblob_set_array 14 0 100.00% 19 0 100.00%
+largeblob.c:largeblob_get_array 32 0 100.00% 36 0 100.00%
+largeblob.c:get_chunklen 10 1 90.00% 9 1 88.89%
+largeblob.c:largeblob_get_tx 19 0 100.00% 24 0 100.00%
+largeblob.c:largeblob_get_rx 26 0 100.00% 30 0 100.00%
+largeblob.c:parse_largeblob_reply 8 0 100.00% 9 0 100.00%
+largeblob.c:largeblob_array_check 7 0 100.00% 16 0 100.00%
+largeblob.c:largeblob_array_digest 10 0 100.00% 9 0 100.00%
+largeblob.c:largeblob_array_load 14 2 85.71% 19 7 63.16%
+largeblob.c:largeblob_array_lookup 25 0 100.00% 33 0 100.00%
+largeblob.c:largeblob_decode 16 2 87.50% 16 6 62.50%
+largeblob.c:largeblob_do_decode 27 3 88.89% 30 7 76.67%
+largeblob.c:largeblob_decrypt 15 0 100.00% 24 0 100.00%
+largeblob.c:largeblob_aad 1 0 100.00% 10 0 100.00%
+largeblob.c:largeblob_reset 1 0 100.00% 5 0 100.00%
+largeblob.c:largeblob_encode 16 0 100.00% 21 0 100.00%
+largeblob.c:largeblob_new 1 0 100.00% 3 0 100.00%
+largeblob.c:largeblob_seal 20 0 100.00% 32 0 100.00%
+largeblob.c:largeblob_get_nonce 8 0 100.00% 16 0 100.00%
+largeblob.c:largeblob_free 6 0 100.00% 8 0 100.00%
+largeblob.c:largeblob_add 27 2 92.59% 35 3 91.43%
+largeblob.c:largeblob_drop 21 0 100.00% 27 0 100.00%
+largeblob.c:largeblob_set_array 54 2 96.30% 61 4 93.44%
+largeblob.c:largeblob_get_uv_token 19 0 100.00% 23 0 100.00%
+largeblob.c:largeblob_set_tx 35 0 100.00% 36 0 100.00%
+largeblob.c:prepare_hmac 13 2 84.62% 23 7 69.57%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 525 18 96.57% 693 43 93.80%
+
+File '/libfido2/src/log.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_log_init 1 0 100.00% 4 0 100.00%
+fido_log_debug 6 1 83.33% 8 1 87.50%
+fido_log_xxd 16 1 93.75% 24 1 95.83%
+fido_log_error 8 2 75.00% 11 2 81.82%
+fido_set_log_handler 3 0 100.00% 4 0 100.00%
+log.c:log_on_stderr 1 1 0.00% 3 3 0.00%
+log.c:do_log 4 0 100.00% 9 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 39 5 87.18% 63 7 88.89%
+
+File '/libfido2/src/netlink.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_nl_power_nfc 18 0 100.00% 24 0 100.00%
+fido_nl_get_nfc_target 17 0 100.00% 31 0 100.00%
+fido_nl_free 10 2 80.00% 9 2 77.78%
+fido_nl_new 16 1 93.75% 26 3 88.46%
+set_netlink_io_functions 1 0 100.00% 4 0 100.00%
+netlink.c:nlmsg_new 8 0 100.00% 15 0 100.00%
+netlink.c:nlmsg_set_genl 1 0 100.00% 7 0 100.00%
+netlink.c:nlmsg_write 6 1 83.33% 7 1 85.71%
+netlink.c:nlmsg_set_u32 1 0 100.00% 3 0 100.00%
+netlink.c:nlmsg_setattr 15 1 93.33% 17 0 100.00%
+netlink.c:nlmsg_tx 10 1 90.00% 13 3 76.92%
+netlink.c:nlmsg_ptr 1 0 100.00% 3 0 100.00%
+netlink.c:nlmsg_len 1 0 100.00% 3 0 100.00%
+netlink.c:nlmsg_rx 11 2 81.82% 17 6 64.71%
+netlink.c:nl_parse_reply 20 0 100.00% 28 0 100.00%
+netlink.c:nlmsg_from_buf 15 0 100.00% 17 0 100.00%
+netlink.c:nlmsg_type 1 0 100.00% 3 0 100.00%
+netlink.c:nlmsg_get_status 8 0 100.00% 8 0 100.00%
+netlink.c:nlmsg_read 6 0 100.00% 7 0 100.00%
+netlink.c:nlmsg_get_genl 6 0 100.00% 7 0 100.00%
+netlink.c:nlmsg_iter 6 0 100.00% 13 0 100.00%
+netlink.c:nlmsg_getattr 1 0 100.00% 3 0 100.00%
+netlink.c:nla_from_buf 17 0 100.00% 21 0 100.00%
+netlink.c:nl_nfc_poll 18 0 100.00% 25 0 100.00%
+netlink.c:parse_nfc_event 10 0 100.00% 17 0 100.00%
+netlink.c:nla_type 1 0 100.00% 3 0 100.00%
+netlink.c:nla_get_u32 1 0 100.00% 3 0 100.00%
+netlink.c:nla_read 6 0 100.00% 7 0 100.00%
+netlink.c:nl_dump_nfc_target 19 0 100.00% 31 0 100.00%
+netlink.c:parse_target 9 0 100.00% 13 0 100.00%
+netlink.c:nl_get_nfc_family 23 0 100.00% 33 0 100.00%
+netlink.c:nlmsg_set_u16 1 0 100.00% 3 0 100.00%
+netlink.c:nlmsg_set_str 1 0 100.00% 3 0 100.00%
+netlink.c:parse_family 10 0 100.00% 17 0 100.00%
+netlink.c:nla_get_u16 1 0 100.00% 3 0 100.00%
+netlink.c:nla_iter 6 0 100.00% 13 0 100.00%
+netlink.c:nla_getattr 1 0 100.00% 3 0 100.00%
+netlink.c:parse_mcastgrps 1 0 100.00% 3 0 100.00%
+netlink.c:parse_mcastgrp 15 0 100.00% 24 0 100.00%
+netlink.c:nla_get_str 10 0 100.00% 11 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 329 8 97.57% 498 15 96.99%
+
+File '/libfido2/src/nfc.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_nfc_tx 28 0 100.00% 43 0 100.00%
+fido_nfc_rx 8 0 100.00% 13 0 100.00%
+nfc_is_fido 13 1 92.31% 21 3 85.71%
+fido_is_nfc 3 0 100.00% 3 0 100.00%
+fido_dev_set_nfc 4 1 75.00% 18 3 83.33%
+nfc.c:nfc_do_tx 20 0 100.00% 25 0 100.00%
+nfc.c:tx_short_apdu 14 0 100.00% 32 0 100.00%
+nfc.c:rx_init 25 0 100.00% 27 0 100.00%
+nfc.c:rx_cbor 4 0 100.00% 6 0 100.00%
+nfc.c:rx_msg 18 2 88.89% 23 6 73.91%
+nfc.c:rx_apdu 14 1 92.86% 22 3 86.36%
+nfc.c:tx_get_response 4 0 100.00% 11 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 155 5 96.77% 244 15 93.85%
+
+File '/libfido2/src/nfc_linux.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_nfc_manifest 35 7 80.00% 45 15 66.67%
+fido_nfc_open 20 3 85.00% 23 4 82.61%
+fido_nfc_close 1 1 0.00% 4 4 0.00%
+fido_nfc_set_sigmask 2 2 0.00% 6 6 0.00%
+fido_nfc_read 14 14 0.00% 30 30 0.00%
+fido_nfc_write 12 12 0.00% 18 18 0.00%
+nfc_linux.c:copy_info 39 22 43.59% 44 16 63.64%
+nfc_linux.c:get_usb_attr 1 1 0.00% 3 3 0.00%
+nfc_linux.c:get_parent_attr 6 6 0.00% 9 9 0.00%
+nfc_linux.c:sysnum_from_syspath 15 0 100.00% 17 0 100.00%
+nfc_linux.c:nfc_new 6 0 100.00% 11 0 100.00%
+nfc_linux.c:nfc_target_connect 9 9 0.00% 21 21 0.00%
+nfc_linux.c:nfc_free 12 0 100.00% 11 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 172 77 55.23% 242 126 47.93%
+
+File '/libfido2/src/pcsc.c':
+Name Regions Miss Cover Lines Miss Cover
+-------------------------------------------------------------------------------------------------------------------
+fido_pcsc_manifest 51 0 100.00% 55 0 100.00%
+fido_pcsc_open 32 0 100.00% 43 0 100.00%
+fido_pcsc_close 6 0 100.00% 9 0 100.00%
+fido_pcsc_read 8 0 100.00% 16 0 100.00%
+fido_pcsc_write 8 0 100.00% 22 0 100.00%
+fido_pcsc_tx 1 0 100.00% 3 0 100.00%
+fido_pcsc_rx 1 0 100.00% 3 0 100.00%
+fido_is_pcsc 3 0 100.00% 3 0 100.00%
+fido_dev_set_pcsc 4 1 75.00% 18 3 83.33%
+pcsc.c:list_readers 24 0 100.00% 24 0 100.00%
+pcsc.c:copy_info 30 0 100.00% 41 0 100.00%
+pcsc.c:get_reader 25 0 100.00% 28 0 100.00%
+pcsc.c:prepare_io_request 11 0 100.00% 17 0 100.00%
+-------------------------------------------------------------------------------------------------------------------
+TOTAL 204 1 99.51% 282 3 98.94%
+
+File '/libfido2/src/pin.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+fido_sha256 7 0 100.00% 10 0 100.00%
+fido_dev_get_uv_token 1 0 100.00% 3 0 100.00%
+fido_dev_set_pin 1 0 100.00% 4 0 100.00%
+fido_dev_get_retry_count 1 0 100.00% 4 0 100.00%
+fido_dev_get_uv_retry_count 1 0 100.00% 4 0 100.00%
+cbor_add_uv_params 17 0 100.00% 23 0 100.00%
+pin.c:uv_token_wait 14 2 85.71% 12 1 91.67%
+pin.c:ctap21_uv_token_tx 49 0 100.00% 53 0 100.00%
+pin.c:pin_sha256_enc 19 0 100.00% 24 0 100.00%
+pin.c:encode_uv_permission 20 1 95.00% 19 3 84.21%
+pin.c:ctap20_uv_token_tx 37 0 100.00% 45 0 100.00%
+pin.c:uv_token_rx 27 0 100.00% 34 0 100.00%
+pin.c:parse_uv_token 8 0 100.00% 10 0 100.00%
+pin.c:fido_dev_set_pin_wait 21 0 100.00% 24 0 100.00%
+pin.c:fido_dev_change_pin_tx 45 0 100.00% 56 0 100.00%
+pin.c:pin_pad64_enc 15 0 100.00% 21 0 100.00%
+pin.c:pad64 18 0 100.00% 20 0 100.00%
+pin.c:fido_dev_set_pin_tx 33 0 100.00% 41 0 100.00%
+pin.c:fido_dev_get_pin_retry_count_wait 10 0 100.00% 7 0 100.00%
+pin.c:fido_dev_get_retry_count_tx 19 0 100.00% 23 0 100.00%
+pin.c:fido_dev_get_pin_retry_count_rx 19 0 100.00% 24 0 100.00%
+pin.c:parse_pin_retry_count 1 0 100.00% 3 0 100.00%
+pin.c:parse_retry_count 13 0 100.00% 16 0 100.00%
+pin.c:fido_dev_get_uv_retry_count_wait 10 0 100.00% 7 0 100.00%
+pin.c:fido_dev_get_uv_retry_count_rx 19 0 100.00% 24 0 100.00%
+pin.c:parse_uv_retry_count 1 0 100.00% 3 0 100.00%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 426 3 99.30% 514 4 99.22%
+
+File '/libfido2/src/random.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+fido_get_random 6 0 100.00% 6 0 100.00%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 6 0 100.00% 6 0 100.00%
+
+File '/libfido2/src/reset.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+fido_dev_reset 1 0 100.00% 4 0 100.00%
+reset.c:fido_dev_reset_wait 15 0 100.00% 11 0 100.00%
+reset.c:fido_dev_reset_tx 8 0 100.00% 8 0 100.00%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 24 0 100.00% 23 0 100.00%
+
+File '/libfido2/src/rs1.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+rs1_verify_sig 20 2 90.00% 30 6 80.00%
+rs1.c:rs1_get_EVP_MD 1 0 100.00% 3 0 100.00%
+rs1.c:rs1_free_EVP_MD 1 0 100.00% 3 0 100.00%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 22 2 90.91% 36 6 83.33%
+
+File '/libfido2/src/rs256.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+rs256_pk_decode 8 0 100.00% 9 0 100.00%
+rs256_pk_new 1 0 100.00% 3 0 100.00%
+rs256_pk_free 6 0 100.00% 7 0 100.00%
+rs256_pk_from_ptr 10 0 100.00% 12 0 100.00%
+rs256_pk_to_EVP_PKEY 35 0 100.00% 43 0 100.00%
+rs256_pk_from_RSA 32 6 81.25% 26 9 65.38%
+rs256_pk_from_EVP_PKEY 8 0 100.00% 7 0 100.00%
+rs256_verify_sig 20 2 90.00% 30 5 83.33%
+rs256_pk_verify_sig 7 1 85.71% 13 2 84.62%
+rs256.c:decode_rsa_pubkey 9 0 100.00% 13 0 100.00%
+rs256.c:decode_bignum 8 0 100.00% 10 0 100.00%
+rs256.c:rs256_get_EVP_MD 1 0 100.00% 3 0 100.00%
+rs256.c:rs256_free_EVP_MD 1 0 100.00% 3 0 100.00%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 146 9 93.84% 179 16 91.06%
+
+File '/libfido2/src/time.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+fido_time_now 4 0 100.00% 7 0 100.00%
+fido_time_delta 23 1 95.65% 23 0 100.00%
+time.c:timespec_to_ms 16 2 87.50% 13 2 84.62%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 43 3 93.02% 43 2 95.35%
+
+File '/libfido2/src/touch.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+fido_dev_get_touch_begin 50 0 100.00% 59 0 100.00%
+fido_dev_get_touch_status 17 0 100.00% 20 0 100.00%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 67 0 100.00% 79 0 100.00%
+
+File '/libfido2/src/tpm.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+fido_get_signed_hash_tpm 25 0 100.00% 39 0 100.00%
+tpm.c:check_es256_pubarea 19 0 100.00% 30 0 100.00%
+tpm.c:bswap_es256_pubarea 1 0 100.00% 12 0 100.00%
+tpm.c:check_rs256_pubarea 17 0 100.00% 28 0 100.00%
+tpm.c:bswap_rs256_pubarea 1 0 100.00% 10 0 100.00%
+tpm.c:check_sha1_certinfo 15 0 100.00% 38 0 100.00%
+tpm.c:get_signed_sha1 17 0 100.00% 19 0 100.00%
+tpm.c:get_signed_name 7 0 100.00% 10 0 100.00%
+tpm.c:bswap_sha1_certinfo 1 0 100.00% 8 0 100.00%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 103 0 100.00% 194 0 100.00%
+
+File '/libfido2/src/types.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+fido_str_array_free 4 0 100.00% 7 0 100.00%
+fido_opt_array_free 4 0 100.00% 9 0 100.00%
+fido_byte_array_free 1 0 100.00% 5 0 100.00%
+fido_algo_free 1 0 100.00% 5 0 100.00%
+fido_algo_array_free 4 0 100.00% 7 0 100.00%
+fido_cert_array_free 4 0 100.00% 9 0 100.00%
+fido_str_array_pack 11 0 100.00% 14 0 100.00%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 29 0 100.00% 56 0 100.00%
+
+File '/libfido2/src/u2f.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+u2f_register 76 0 100.00% 81 0 100.00%
+u2f_authenticate 33 0 100.00% 37 0 100.00%
+u2f_get_touch_begin 37 0 100.00% 45 0 100.00%
+u2f_get_touch_status 26 0 100.00% 36 0 100.00%
+u2f.c:key_lookup 51 0 100.00% 65 0 100.00%
+u2f.c:send_dummy_register 37 0 100.00% 45 0 100.00%
+u2f.c:delay_ms 13 1 92.31% 15 3 80.00%
+u2f.c:parse_register_reply 49 0 100.00% 62 0 100.00%
+u2f.c:x5c_get 21 1 95.24% 26 3 88.46%
+u2f.c:sig_get 6 0 100.00% 10 0 100.00%
+u2f.c:encode_cred_attstmt 45 0 100.00% 52 0 100.00%
+u2f.c:encode_cred_authdata 33 2 93.94% 61 6 90.16%
+u2f.c:cbor_blob_from_ec_point 22 0 100.00% 31 0 100.00%
+u2f.c:u2f_authenticate_single 32 0 100.00% 43 0 100.00%
+u2f.c:do_auth 56 0 100.00% 67 0 100.00%
+u2f.c:parse_auth_reply 23 0 100.00% 23 0 100.00%
+u2f.c:authdata_fake 12 0 100.00% 27 0 100.00%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 572 4 99.30% 726 12 98.35%
+
+File '/libfido2/src/util.c':
+Name Regions Miss Cover Lines Miss Cover
+---------------------------------------------------------------------------------------------------------------------
+fido_to_uint64 14 1 92.86% 14 1 92.86%
+---------------------------------------------------------------------------------------------------------------------
+TOTAL 14 1 92.86% 14 1 92.86%
diff --git a/fuzz/fuzz_assert.c b/fuzz/fuzz_assert.c
new file mode 100644
index 0000000..03cb51c
--- /dev/null
+++ b/fuzz/fuzz_assert.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2019-2023 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 <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mutator_aux.h"
+#include "wiredata_fido2.h"
+#include "wiredata_u2f.h"
+#include "dummy.h"
+
+#include "../openbsd-compat/openbsd-compat.h"
+
+/* Parameter set defining a FIDO2 get assertion operation. */
+struct param {
+ char pin[MAXSTR];
+ char rp_id[MAXSTR];
+ int ext;
+ int seed;
+ struct blob cdh;
+ struct blob cred;
+ struct blob es256;
+ struct blob rs256;
+ struct blob eddsa;
+ struct blob wire_data;
+ uint8_t cred_count;
+ uint8_t type;
+ uint8_t opt;
+ uint8_t up;
+ uint8_t uv;
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * get assertion using the example parameters above.
+ */
+static const uint8_t dummy_wire_data_fido[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_ASSERT,
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a U2F
+ * authentication using the example parameters above.
+ */
+static const uint8_t dummy_wire_data_u2f[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_U2F_6985,
+ WIREDATA_CTAP_U2F_6985,
+ WIREDATA_CTAP_U2F_6985,
+ WIREDATA_CTAP_U2F_6985,
+ WIREDATA_CTAP_U2F_AUTH,
+};
+
+struct param *
+unpack(const uint8_t *ptr, size_t len)
+{
+ cbor_item_t *item = NULL, **v;
+ struct cbor_load_result cbor;
+ struct param *p;
+ int ok = -1;
+
+ if ((p = calloc(1, sizeof(*p))) == NULL ||
+ (item = cbor_load(ptr, len, &cbor)) == NULL ||
+ cbor.read != len ||
+ cbor_isa_array(item) == false ||
+ cbor_array_is_definite(item) == false ||
+ cbor_array_size(item) != 15 ||
+ (v = cbor_array_handle(item)) == NULL)
+ goto fail;
+
+ if (unpack_byte(v[0], &p->uv) < 0 ||
+ unpack_byte(v[1], &p->up) < 0 ||
+ unpack_byte(v[2], &p->opt) < 0 ||
+ unpack_byte(v[3], &p->type) < 0 ||
+ unpack_byte(v[4], &p->cred_count) < 0 ||
+ unpack_int(v[5], &p->ext) < 0 ||
+ unpack_int(v[6], &p->seed) < 0 ||
+ unpack_string(v[7], p->rp_id) < 0 ||
+ unpack_string(v[8], p->pin) < 0 ||
+ unpack_blob(v[9], &p->wire_data) < 0 ||
+ unpack_blob(v[10], &p->rs256) < 0 ||
+ unpack_blob(v[11], &p->es256) < 0 ||
+ unpack_blob(v[12], &p->eddsa) < 0 ||
+ unpack_blob(v[13], &p->cred) < 0 ||
+ unpack_blob(v[14], &p->cdh) < 0)
+ goto fail;
+
+ ok = 0;
+fail:
+ if (ok < 0) {
+ free(p);
+ p = NULL;
+ }
+
+ if (item)
+ cbor_decref(&item);
+
+ return p;
+}
+
+size_t
+pack(uint8_t *ptr, size_t len, const struct param *p)
+{
+ cbor_item_t *argv[15], *array = NULL;
+ size_t cbor_alloc_len, cbor_len = 0;
+ unsigned char *cbor = NULL;
+
+ memset(argv, 0, sizeof(argv));
+
+ if ((array = cbor_new_definite_array(15)) == NULL ||
+ (argv[0] = pack_byte(p->uv)) == NULL ||
+ (argv[1] = pack_byte(p->up)) == NULL ||
+ (argv[2] = pack_byte(p->opt)) == NULL ||
+ (argv[3] = pack_byte(p->type)) == NULL ||
+ (argv[4] = pack_byte(p->cred_count)) == NULL ||
+ (argv[5] = pack_int(p->ext)) == NULL ||
+ (argv[6] = pack_int(p->seed)) == NULL ||
+ (argv[7] = pack_string(p->rp_id)) == NULL ||
+ (argv[8] = pack_string(p->pin)) == NULL ||
+ (argv[9] = pack_blob(&p->wire_data)) == NULL ||
+ (argv[10] = pack_blob(&p->rs256)) == NULL ||
+ (argv[11] = pack_blob(&p->es256)) == NULL ||
+ (argv[12] = pack_blob(&p->eddsa)) == NULL ||
+ (argv[13] = pack_blob(&p->cred)) == NULL ||
+ (argv[14] = pack_blob(&p->cdh)) == NULL)
+ goto fail;
+
+ for (size_t i = 0; i < 15; i++)
+ if (cbor_array_push(array, argv[i]) == false)
+ goto fail;
+
+ if ((cbor_len = cbor_serialize_alloc(array, &cbor,
+ &cbor_alloc_len)) == 0 || cbor_len > len) {
+ cbor_len = 0;
+ goto fail;
+ }
+
+ memcpy(ptr, cbor, cbor_len);
+fail:
+ for (size_t i = 0; i < 15; i++)
+ if (argv[i])
+ cbor_decref(&argv[i]);
+
+ if (array)
+ cbor_decref(&array);
+
+ free(cbor);
+
+ return cbor_len;
+}
+
+size_t
+pack_dummy(uint8_t *ptr, size_t len)
+{
+ struct param dummy;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&dummy, 0, sizeof(dummy));
+
+ dummy.type = 1; /* rsa */
+ dummy.ext = FIDO_EXT_HMAC_SECRET;
+
+ strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
+ strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
+
+ dummy.cred.len = sizeof(dummy_cdh); /* XXX */
+ dummy.cdh.len = sizeof(dummy_cdh);
+ dummy.es256.len = sizeof(dummy_es256);
+ dummy.rs256.len = sizeof(dummy_rs256);
+ dummy.eddsa.len = sizeof(dummy_eddsa);
+ dummy.wire_data.len = sizeof(dummy_wire_data_fido);
+
+ memcpy(&dummy.cred.body, &dummy_cdh, dummy.cred.len); /* XXX */
+ memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len);
+ memcpy(&dummy.wire_data.body, &dummy_wire_data_fido,
+ dummy.wire_data.len);
+ memcpy(&dummy.es256.body, &dummy_es256, dummy.es256.len);
+ memcpy(&dummy.rs256.body, &dummy_rs256, dummy.rs256.len);
+ memcpy(&dummy.eddsa.body, &dummy_eddsa, dummy.eddsa.len);
+
+ assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
+
+ if (blob_len > len) {
+ memcpy(ptr, blob, len);
+ return len;
+ }
+
+ memcpy(ptr, blob, blob_len);
+
+ return blob_len;
+}
+
+static void
+get_assert(fido_assert_t *assert, uint8_t opt, const struct blob *cdh,
+ const char *rp_id, int ext, uint8_t up, uint8_t uv, const char *pin,
+ uint8_t cred_count, const struct blob *cred)
+{
+ fido_dev_t *dev;
+
+ if ((dev = open_dev(opt & 2)) == NULL)
+ return;
+ if (opt & 1)
+ fido_dev_force_u2f(dev);
+ if (ext & FIDO_EXT_HMAC_SECRET)
+ fido_assert_set_extensions(assert, FIDO_EXT_HMAC_SECRET);
+ if (ext & FIDO_EXT_CRED_BLOB)
+ fido_assert_set_extensions(assert, FIDO_EXT_CRED_BLOB);
+ if (ext & FIDO_EXT_LARGEBLOB_KEY)
+ fido_assert_set_extensions(assert, FIDO_EXT_LARGEBLOB_KEY);
+ if (up & 1)
+ fido_assert_set_up(assert, FIDO_OPT_TRUE);
+ else if (opt & 1)
+ fido_assert_set_up(assert, FIDO_OPT_FALSE);
+ if (uv & 1)
+ fido_assert_set_uv(assert, FIDO_OPT_TRUE);
+
+ for (uint8_t i = 0; i < cred_count; i++)
+ fido_assert_allow_cred(assert, cred->body, cred->len);
+
+ fido_assert_set_clientdata_hash(assert, cdh->body, cdh->len);
+ fido_assert_set_rp(assert, rp_id);
+ /* XXX reuse cred as hmac salt */
+ fido_assert_set_hmac_salt(assert, cred->body, cred->len);
+
+ /* repeat memory operations to trigger reallocation paths */
+ fido_assert_set_clientdata_hash(assert, cdh->body, cdh->len);
+ fido_assert_set_rp(assert, rp_id);
+ fido_assert_set_hmac_salt(assert, cred->body, cred->len);
+
+ if (strlen(pin) == 0)
+ pin = NULL;
+
+ fido_dev_get_assert(dev, assert, (opt & 1) ? NULL : pin);
+
+ fido_dev_cancel(dev);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+verify_assert(int type, const unsigned char *cdh_ptr, size_t cdh_len,
+ const char *rp_id, const unsigned char *authdata_ptr, size_t authdata_len,
+ const unsigned char *sig_ptr, size_t sig_len, uint8_t up, uint8_t uv,
+ int ext, void *pk)
+{
+ fido_assert_t *assert = NULL;
+ int r;
+
+ if ((assert = fido_assert_new()) == NULL)
+ return;
+
+ fido_assert_set_clientdata_hash(assert, cdh_ptr, cdh_len);
+ fido_assert_set_rp(assert, rp_id);
+ fido_assert_set_count(assert, 1);
+
+ if (fido_assert_set_authdata(assert, 0, authdata_ptr,
+ authdata_len) != FIDO_OK) {
+ fido_assert_set_authdata_raw(assert, 0, authdata_ptr,
+ authdata_len);
+ }
+
+ if (up & 1)
+ fido_assert_set_up(assert, FIDO_OPT_TRUE);
+ if (uv & 1)
+ fido_assert_set_uv(assert, FIDO_OPT_TRUE);
+
+ fido_assert_set_extensions(assert, ext);
+ fido_assert_set_sig(assert, 0, sig_ptr, sig_len);
+
+ /* repeat memory operations to trigger reallocation paths */
+ if (fido_assert_set_authdata(assert, 0, authdata_ptr,
+ authdata_len) != FIDO_OK) {
+ fido_assert_set_authdata_raw(assert, 0, authdata_ptr,
+ authdata_len);
+ }
+ fido_assert_set_sig(assert, 0, sig_ptr, sig_len);
+
+ r = fido_assert_verify(assert, 0, type, pk);
+ consume(&r, sizeof(r));
+
+ fido_assert_free(&assert);
+}
+
+/*
+ * Do a dummy conversion to exercise es256_pk_from_EVP_PKEY().
+ */
+static void
+es256_convert(const es256_pk_t *k)
+{
+ EVP_PKEY *pkey = NULL;
+ es256_pk_t *pk = NULL;
+ int r;
+
+ if ((pkey = es256_pk_to_EVP_PKEY(k)) == NULL ||
+ (pk = es256_pk_new()) == NULL)
+ goto out;
+
+ r = es256_pk_from_EVP_PKEY(pk, pkey);
+ consume(&r, sizeof(r));
+out:
+ es256_pk_free(&pk);
+ EVP_PKEY_free(pkey);
+}
+
+/*
+ * Do a dummy conversion to exercise es384_pk_from_EVP_PKEY().
+ */
+static void
+es384_convert(const es384_pk_t *k)
+{
+ EVP_PKEY *pkey = NULL;
+ es384_pk_t *pk = NULL;
+ int r;
+
+ if ((pkey = es384_pk_to_EVP_PKEY(k)) == NULL ||
+ (pk = es384_pk_new()) == NULL)
+ goto out;
+
+ r = es384_pk_from_EVP_PKEY(pk, pkey);
+ consume(&r, sizeof(r));
+out:
+ es384_pk_free(&pk);
+ EVP_PKEY_free(pkey);
+}
+
+/*
+ * Do a dummy conversion to exercise rs256_pk_from_EVP_PKEY().
+ */
+static void
+rs256_convert(const rs256_pk_t *k)
+{
+ EVP_PKEY *pkey = NULL;
+ rs256_pk_t *pk = NULL;
+ int r;
+
+ if ((pkey = rs256_pk_to_EVP_PKEY(k)) == NULL ||
+ (pk = rs256_pk_new()) == NULL)
+ goto out;
+
+ r = rs256_pk_from_EVP_PKEY(pk, pkey);
+ consume(&r, sizeof(r));
+out:
+ rs256_pk_free(&pk);
+ EVP_PKEY_free(pkey);
+}
+
+/*
+ * Do a dummy conversion to exercise eddsa_pk_from_EVP_PKEY().
+ */
+static void
+eddsa_convert(const eddsa_pk_t *k)
+{
+ EVP_PKEY *pkey = NULL;
+ eddsa_pk_t *pk = NULL;
+ int r;
+
+ if ((pkey = eddsa_pk_to_EVP_PKEY(k)) == NULL ||
+ (pk = eddsa_pk_new()) == NULL)
+ goto out;
+
+ r = eddsa_pk_from_EVP_PKEY(pk, pkey);
+ consume(&r, sizeof(r));
+out:
+ if (pk)
+ eddsa_pk_free(&pk);
+ if (pkey)
+ EVP_PKEY_free(pkey);
+}
+
+void
+test(const struct param *p)
+{
+ fido_assert_t *assert = NULL;
+ es256_pk_t *es256_pk = NULL;
+ es384_pk_t *es384_pk = NULL;
+ rs256_pk_t *rs256_pk = NULL;
+ eddsa_pk_t *eddsa_pk = NULL;
+ uint8_t flags;
+ uint32_t sigcount;
+ int cose_alg = 0;
+ void *pk;
+
+ prng_init((unsigned int)p->seed);
+ fuzz_clock_reset();
+ fido_init(FIDO_DEBUG);
+ fido_set_log_handler(consume_str);
+
+ switch (p->type & 3) {
+ case 0:
+ cose_alg = COSE_ES256;
+
+ if ((es256_pk = es256_pk_new()) == NULL)
+ return;
+
+ es256_pk_from_ptr(es256_pk, p->es256.body, p->es256.len);
+ pk = es256_pk;
+
+ es256_convert(pk);
+
+ break;
+ case 1:
+ cose_alg = COSE_RS256;
+
+ if ((rs256_pk = rs256_pk_new()) == NULL)
+ return;
+
+ rs256_pk_from_ptr(rs256_pk, p->rs256.body, p->rs256.len);
+ pk = rs256_pk;
+
+ rs256_convert(pk);
+
+ break;
+ case 2:
+ cose_alg = COSE_ES384;
+
+ if ((es384_pk = es384_pk_new()) == NULL)
+ return;
+
+ /* XXX reuse p->es256 as es384 */
+ es384_pk_from_ptr(es384_pk, p->es256.body, p->es256.len);
+ pk = es384_pk;
+
+ es384_convert(pk);
+
+ break;
+ default:
+ cose_alg = COSE_EDDSA;
+
+ if ((eddsa_pk = eddsa_pk_new()) == NULL)
+ return;
+
+ eddsa_pk_from_ptr(eddsa_pk, p->eddsa.body, p->eddsa.len);
+ pk = eddsa_pk;
+
+ eddsa_convert(pk);
+
+ break;
+ }
+
+ if ((assert = fido_assert_new()) == NULL)
+ goto out;
+
+ set_wire_data(p->wire_data.body, p->wire_data.len);
+
+ get_assert(assert, p->opt, &p->cdh, p->rp_id, p->ext, p->up, p->uv,
+ p->pin, p->cred_count, &p->cred);
+
+ /* XXX +1 on purpose */
+ for (size_t i = 0; i <= fido_assert_count(assert); i++) {
+ verify_assert(cose_alg,
+ fido_assert_clientdata_hash_ptr(assert),
+ fido_assert_clientdata_hash_len(assert),
+ fido_assert_rp_id(assert),
+ fido_assert_authdata_ptr(assert, i),
+ fido_assert_authdata_len(assert, i),
+ fido_assert_sig_ptr(assert, i),
+ fido_assert_sig_len(assert, i), p->up, p->uv, p->ext, pk);
+ consume(fido_assert_authdata_raw_ptr(assert, i),
+ fido_assert_authdata_raw_len(assert, i));
+ consume(fido_assert_id_ptr(assert, i),
+ fido_assert_id_len(assert, i));
+ consume(fido_assert_user_id_ptr(assert, i),
+ fido_assert_user_id_len(assert, i));
+ consume(fido_assert_hmac_secret_ptr(assert, i),
+ fido_assert_hmac_secret_len(assert, i));
+ consume_str(fido_assert_user_icon(assert, i));
+ consume_str(fido_assert_user_name(assert, i));
+ consume_str(fido_assert_user_display_name(assert, i));
+ consume(fido_assert_blob_ptr(assert, i),
+ fido_assert_blob_len(assert, i));
+ consume(fido_assert_largeblob_key_ptr(assert, i),
+ fido_assert_largeblob_key_len(assert, i));
+ flags = fido_assert_flags(assert, i);
+ consume(&flags, sizeof(flags));
+ sigcount = fido_assert_sigcount(assert, i);
+ consume(&sigcount, sizeof(sigcount));
+ }
+
+out:
+ es256_pk_free(&es256_pk);
+ es384_pk_free(&es384_pk);
+ rs256_pk_free(&rs256_pk);
+ eddsa_pk_free(&eddsa_pk);
+
+ fido_assert_free(&assert);
+}
+
+void
+mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
+{
+ if (flags & MUTATE_SEED)
+ p->seed = (int)seed;
+
+ if (flags & MUTATE_PARAM) {
+ mutate_byte(&p->uv);
+ mutate_byte(&p->up);
+ mutate_byte(&p->opt);
+ mutate_byte(&p->type);
+ mutate_byte(&p->cred_count);
+ mutate_int(&p->ext);
+ mutate_blob(&p->rs256);
+ mutate_blob(&p->es256);
+ mutate_blob(&p->eddsa);
+ mutate_blob(&p->cred);
+ mutate_blob(&p->cdh);
+ mutate_string(p->rp_id);
+ mutate_string(p->pin);
+ }
+
+ if (flags & MUTATE_WIREDATA) {
+ if (p->opt & 1) {
+ p->wire_data.len = sizeof(dummy_wire_data_u2f);
+ memcpy(&p->wire_data.body, &dummy_wire_data_u2f,
+ p->wire_data.len);
+ } else {
+ p->wire_data.len = sizeof(dummy_wire_data_fido);
+ memcpy(&p->wire_data.body, &dummy_wire_data_fido,
+ p->wire_data.len);
+ }
+ mutate_blob(&p->wire_data);
+ }
+}
diff --git a/fuzz/fuzz_bio.c b/fuzz/fuzz_bio.c
new file mode 100644
index 0000000..0c6b12c
--- /dev/null
+++ b/fuzz/fuzz_bio.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 2019 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 <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mutator_aux.h"
+#include "wiredata_fido2.h"
+#include "dummy.h"
+
+#include "../openbsd-compat/openbsd-compat.h"
+
+/* Parameter set defining a FIDO2 credential management operation. */
+struct param {
+ char pin[MAXSTR];
+ char name[MAXSTR];
+ int seed;
+ struct blob id;
+ struct blob info_wire_data;
+ struct blob enroll_wire_data;
+ struct blob list_wire_data;
+ struct blob set_name_wire_data;
+ struct blob remove_wire_data;
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'getFingerprintSensorInfo' bio enrollment command.
+ */
+static const uint8_t dummy_info_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_BIO_INFO,
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with FIDO2
+ * 'enrollBegin' + 'enrollCaptureNextSample' bio enrollment commands.
+ */
+static const uint8_t dummy_enroll_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_BIO_ENROLL,
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'enumerateEnrollments' bio enrollment command.
+ */
+static const uint8_t dummy_list_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_BIO_ENUM,
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'setFriendlyName' bio enrollment command.
+ */
+static const uint8_t dummy_set_name_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_STATUS,
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'removeEnrollment' bio enrollment command.
+ */
+static const uint8_t dummy_remove_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_STATUS,
+};
+
+struct param *
+unpack(const uint8_t *ptr, size_t len)
+{
+ cbor_item_t *item = NULL, **v;
+ struct cbor_load_result cbor;
+ struct param *p;
+ int ok = -1;
+
+ if ((p = calloc(1, sizeof(*p))) == NULL ||
+ (item = cbor_load(ptr, len, &cbor)) == NULL ||
+ cbor.read != len ||
+ cbor_isa_array(item) == false ||
+ cbor_array_is_definite(item) == false ||
+ cbor_array_size(item) != 9 ||
+ (v = cbor_array_handle(item)) == NULL)
+ goto fail;
+
+ if (unpack_int(v[0], &p->seed) < 0 ||
+ unpack_string(v[1], p->pin) < 0 ||
+ unpack_string(v[2], p->name) < 0 ||
+ unpack_blob(v[3], &p->id) < 0 ||
+ unpack_blob(v[4], &p->info_wire_data) < 0 ||
+ unpack_blob(v[5], &p->enroll_wire_data) < 0 ||
+ unpack_blob(v[6], &p->list_wire_data) < 0 ||
+ unpack_blob(v[7], &p->set_name_wire_data) < 0 ||
+ unpack_blob(v[8], &p->remove_wire_data) < 0)
+ goto fail;
+
+ ok = 0;
+fail:
+ if (ok < 0) {
+ free(p);
+ p = NULL;
+ }
+
+ if (item)
+ cbor_decref(&item);
+
+ return p;
+}
+
+size_t
+pack(uint8_t *ptr, size_t len, const struct param *p)
+{
+ cbor_item_t *argv[9], *array = NULL;
+ size_t cbor_alloc_len, cbor_len = 0;
+ unsigned char *cbor = NULL;
+
+ memset(argv, 0, sizeof(argv));
+
+ if ((array = cbor_new_definite_array(9)) == NULL ||
+ (argv[0] = pack_int(p->seed)) == NULL ||
+ (argv[1] = pack_string(p->pin)) == NULL ||
+ (argv[2] = pack_string(p->name)) == NULL ||
+ (argv[3] = pack_blob(&p->id)) == NULL ||
+ (argv[4] = pack_blob(&p->info_wire_data)) == NULL ||
+ (argv[5] = pack_blob(&p->enroll_wire_data)) == NULL ||
+ (argv[6] = pack_blob(&p->list_wire_data)) == NULL ||
+ (argv[7] = pack_blob(&p->set_name_wire_data)) == NULL ||
+ (argv[8] = pack_blob(&p->remove_wire_data)) == NULL)
+ goto fail;
+
+ for (size_t i = 0; i < 9; i++)
+ if (cbor_array_push(array, argv[i]) == false)
+ goto fail;
+
+ if ((cbor_len = cbor_serialize_alloc(array, &cbor,
+ &cbor_alloc_len)) == 0 || cbor_len > len) {
+ cbor_len = 0;
+ goto fail;
+ }
+
+ memcpy(ptr, cbor, cbor_len);
+fail:
+ for (size_t i = 0; i < 9; i++)
+ if (argv[i])
+ cbor_decref(&argv[i]);
+
+ if (array)
+ cbor_decref(&array);
+
+ free(cbor);
+
+ return cbor_len;
+}
+
+size_t
+pack_dummy(uint8_t *ptr, size_t len)
+{
+ struct param dummy;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&dummy, 0, sizeof(dummy));
+
+ strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
+ strlcpy(dummy.name, dummy_name, sizeof(dummy.name));
+
+ dummy.info_wire_data.len = sizeof(dummy_info_wire_data);
+ dummy.enroll_wire_data.len = sizeof(dummy_enroll_wire_data);
+ dummy.list_wire_data.len = sizeof(dummy_list_wire_data);
+ dummy.set_name_wire_data.len = sizeof(dummy_set_name_wire_data);
+ dummy.remove_wire_data.len = sizeof(dummy_remove_wire_data);
+ dummy.id.len = sizeof(dummy_id);
+
+ memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data,
+ dummy.info_wire_data.len);
+ memcpy(&dummy.enroll_wire_data.body, &dummy_enroll_wire_data,
+ dummy.enroll_wire_data.len);
+ memcpy(&dummy.list_wire_data.body, &dummy_list_wire_data,
+ dummy.list_wire_data.len);
+ memcpy(&dummy.set_name_wire_data.body, &dummy_set_name_wire_data,
+ dummy.set_name_wire_data.len);
+ memcpy(&dummy.remove_wire_data.body, &dummy_remove_wire_data,
+ dummy.remove_wire_data.len);
+ memcpy(&dummy.id.body, &dummy_id, dummy.id.len);
+
+ assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
+
+ if (blob_len > len) {
+ memcpy(ptr, blob, len);
+ return len;
+ }
+
+ memcpy(ptr, blob, blob_len);
+
+ return blob_len;
+}
+
+static fido_dev_t *
+prepare_dev(void)
+{
+ fido_dev_t *dev;
+ bool x;
+
+ if ((dev = open_dev(0)) == NULL)
+ return NULL;
+
+ x = fido_dev_is_fido2(dev);
+ consume(&x, sizeof(x));
+ x = fido_dev_supports_pin(dev);
+ consume(&x, sizeof(x));
+ x = fido_dev_has_pin(dev);
+ consume(&x, sizeof(x));
+ x = fido_dev_supports_uv(dev);
+ consume(&x, sizeof(x));
+ x = fido_dev_has_uv(dev);
+ consume(&x, sizeof(x));
+
+ return dev;
+}
+
+static void
+get_info(const struct param *p)
+{
+ fido_dev_t *dev = NULL;
+ fido_bio_info_t *i = NULL;
+ uint8_t type;
+ uint8_t max_samples;
+ int r;
+
+ set_wire_data(p->info_wire_data.body, p->info_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL || (i = fido_bio_info_new()) == NULL)
+ goto done;
+
+ r = fido_bio_dev_get_info(dev, i);
+ consume_str(fido_strerr(r));
+
+ type = fido_bio_info_type(i);
+ max_samples = fido_bio_info_max_samples(i);
+ consume(&type, sizeof(type));
+ consume(&max_samples, sizeof(max_samples));
+
+done:
+ if (dev)
+ fido_dev_close(dev);
+
+ fido_dev_free(&dev);
+ fido_bio_info_free(&i);
+}
+
+static void
+consume_template(const fido_bio_template_t *t)
+{
+ consume_str(fido_bio_template_name(t));
+ consume(fido_bio_template_id_ptr(t), fido_bio_template_id_len(t));
+}
+
+static void
+consume_enroll(fido_bio_enroll_t *e)
+{
+ uint8_t last_status;
+ uint8_t remaining_samples;
+
+ last_status = fido_bio_enroll_last_status(e);
+ remaining_samples = fido_bio_enroll_remaining_samples(e);
+ consume(&last_status, sizeof(last_status));
+ consume(&remaining_samples, sizeof(remaining_samples));
+}
+
+static void
+enroll(const struct param *p)
+{
+ fido_dev_t *dev = NULL;
+ fido_bio_template_t *t = NULL;
+ fido_bio_enroll_t *e = NULL;
+ size_t cnt = 0;
+
+ set_wire_data(p->enroll_wire_data.body, p->enroll_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL ||
+ (t = fido_bio_template_new()) == NULL ||
+ (e = fido_bio_enroll_new()) == NULL)
+ goto done;
+
+ fido_bio_dev_enroll_begin(dev, t, e, (uint32_t)p->seed, p->pin);
+
+ consume_template(t);
+ consume_enroll(e);
+
+ while (fido_bio_enroll_remaining_samples(e) > 0 && cnt++ < 5) {
+ fido_bio_dev_enroll_continue(dev, t, e, p->seed);
+ consume_template(t);
+ consume_enroll(e);
+ }
+
+done:
+ if (dev)
+ fido_dev_close(dev);
+
+ fido_dev_free(&dev);
+ fido_bio_template_free(&t);
+ fido_bio_enroll_free(&e);
+}
+
+static void
+list(const struct param *p)
+{
+ fido_dev_t *dev = NULL;
+ fido_bio_template_array_t *ta = NULL;
+ const fido_bio_template_t *t = NULL;
+
+ set_wire_data(p->list_wire_data.body, p->list_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL ||
+ (ta = fido_bio_template_array_new()) == NULL)
+ goto done;
+
+ fido_bio_dev_get_template_array(dev, ta, p->pin);
+
+ /* +1 on purpose */
+ for (size_t i = 0; i < fido_bio_template_array_count(ta) + 1; i++)
+ if ((t = fido_bio_template(ta, i)) != NULL)
+ consume_template(t);
+
+done:
+ if (dev)
+ fido_dev_close(dev);
+
+ fido_dev_free(&dev);
+ fido_bio_template_array_free(&ta);
+}
+
+static void
+set_name(const struct param *p)
+{
+ fido_dev_t *dev = NULL;
+ fido_bio_template_t *t = NULL;
+
+ set_wire_data(p->set_name_wire_data.body, p->set_name_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL ||
+ (t = fido_bio_template_new()) == NULL)
+ goto done;
+
+ fido_bio_template_set_name(t, p->name);
+ fido_bio_template_set_id(t, p->id.body, p->id.len);
+ consume_template(t);
+
+ fido_bio_dev_set_template_name(dev, t, p->pin);
+
+done:
+ if (dev)
+ fido_dev_close(dev);
+
+ fido_dev_free(&dev);
+ fido_bio_template_free(&t);
+}
+
+static void
+del(const struct param *p)
+{
+ fido_dev_t *dev = NULL;
+ fido_bio_template_t *t = NULL;
+ int r;
+
+ set_wire_data(p->remove_wire_data.body, p->remove_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL ||
+ (t = fido_bio_template_new()) == NULL)
+ goto done;
+
+ r = fido_bio_template_set_id(t, p->id.body, p->id.len);
+ consume_template(t);
+ consume_str(fido_strerr(r));
+
+ fido_bio_dev_enroll_remove(dev, t, p->pin);
+
+done:
+ if (dev)
+ fido_dev_close(dev);
+
+ fido_dev_free(&dev);
+ fido_bio_template_free(&t);
+}
+
+void
+test(const struct param *p)
+{
+ prng_init((unsigned int)p->seed);
+ fuzz_clock_reset();
+ fido_init(FIDO_DEBUG);
+ fido_set_log_handler(consume_str);
+
+ get_info(p);
+ enroll(p);
+ list(p);
+ set_name(p);
+ del(p);
+}
+
+void
+mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
+{
+ if (flags & MUTATE_SEED)
+ p->seed = (int)seed;
+
+ if (flags & MUTATE_PARAM) {
+ mutate_blob(&p->id);
+ mutate_string(p->pin);
+ mutate_string(p->name);
+ }
+
+ if (flags & MUTATE_WIREDATA) {
+ mutate_blob(&p->info_wire_data);
+ mutate_blob(&p->enroll_wire_data);
+ mutate_blob(&p->list_wire_data);
+ mutate_blob(&p->set_name_wire_data);
+ mutate_blob(&p->remove_wire_data);
+ }
+}
diff --git a/fuzz/fuzz_cred.c b/fuzz/fuzz_cred.c
new file mode 100644
index 0000000..497298f
--- /dev/null
+++ b/fuzz/fuzz_cred.c
@@ -0,0 +1,482 @@
+/*
+ * 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 <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mutator_aux.h"
+#include "wiredata_fido2.h"
+#include "wiredata_u2f.h"
+#include "dummy.h"
+
+#include "../openbsd-compat/openbsd-compat.h"
+
+/* Parameter set defining a FIDO2 make credential operation. */
+struct param {
+ char pin[MAXSTR];
+ char rp_id[MAXSTR];
+ char rp_name[MAXSTR];
+ char user_icon[MAXSTR];
+ char user_name[MAXSTR];
+ char user_nick[MAXSTR];
+ int ext;
+ int seed;
+ struct blob cdh;
+ struct blob excl_cred;
+ struct blob user_id;
+ struct blob wire_data;
+ uint8_t excl_count;
+ uint8_t rk;
+ uint8_t type;
+ uint8_t opt;
+ uint8_t uv;
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * make credential using the example parameters above.
+ */
+static const uint8_t dummy_wire_data_fido[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_KEEPALIVE,
+ WIREDATA_CTAP_KEEPALIVE,
+ WIREDATA_CTAP_KEEPALIVE,
+ WIREDATA_CTAP_CBOR_CRED,
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a U2F
+ * registration using the example parameters above.
+ */
+static const uint8_t dummy_wire_data_u2f[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_U2F_6985,
+ WIREDATA_CTAP_U2F_6985,
+ WIREDATA_CTAP_U2F_6985,
+ WIREDATA_CTAP_U2F_6985,
+ WIREDATA_CTAP_U2F_6985,
+ WIREDATA_CTAP_U2F_REGISTER,
+};
+
+struct param *
+unpack(const uint8_t *ptr, size_t len)
+{
+ cbor_item_t *item = NULL, **v;
+ struct cbor_load_result cbor;
+ struct param *p;
+ int ok = -1;
+
+ if ((p = calloc(1, sizeof(*p))) == NULL ||
+ (item = cbor_load(ptr, len, &cbor)) == NULL ||
+ cbor.read != len ||
+ cbor_isa_array(item) == false ||
+ cbor_array_is_definite(item) == false ||
+ cbor_array_size(item) != 17 ||
+ (v = cbor_array_handle(item)) == NULL)
+ goto fail;
+
+ if (unpack_byte(v[0], &p->rk) < 0 ||
+ unpack_byte(v[1], &p->type) < 0 ||
+ unpack_byte(v[2], &p->opt) < 0 ||
+ unpack_byte(v[3], &p->uv) < 0 ||
+ unpack_byte(v[4], &p->excl_count) < 0 ||
+ unpack_int(v[5], &p->ext) < 0 ||
+ unpack_int(v[6], &p->seed) < 0 ||
+ unpack_string(v[7], p->pin) < 0 ||
+ unpack_string(v[8], p->rp_id) < 0 ||
+ unpack_string(v[9], p->rp_name) < 0 ||
+ unpack_string(v[10], p->user_icon) < 0 ||
+ unpack_string(v[11], p->user_name) < 0 ||
+ unpack_string(v[12], p->user_nick) < 0 ||
+ unpack_blob(v[13], &p->cdh) < 0 ||
+ unpack_blob(v[14], &p->user_id) < 0 ||
+ unpack_blob(v[15], &p->wire_data) < 0 ||
+ unpack_blob(v[16], &p->excl_cred) < 0)
+ goto fail;
+
+ ok = 0;
+fail:
+ if (ok < 0) {
+ free(p);
+ p = NULL;
+ }
+
+ if (item)
+ cbor_decref(&item);
+
+ return p;
+}
+
+size_t
+pack(uint8_t *ptr, size_t len, const struct param *p)
+{
+ cbor_item_t *argv[17], *array = NULL;
+ size_t cbor_alloc_len, cbor_len = 0;
+ unsigned char *cbor = NULL;
+
+ memset(argv, 0, sizeof(argv));
+
+ if ((array = cbor_new_definite_array(17)) == NULL ||
+ (argv[0] = pack_byte(p->rk)) == NULL ||
+ (argv[1] = pack_byte(p->type)) == NULL ||
+ (argv[2] = pack_byte(p->opt)) == NULL ||
+ (argv[3] = pack_byte(p->uv)) == NULL ||
+ (argv[4] = pack_byte(p->excl_count)) == NULL ||
+ (argv[5] = pack_int(p->ext)) == NULL ||
+ (argv[6] = pack_int(p->seed)) == NULL ||
+ (argv[7] = pack_string(p->pin)) == NULL ||
+ (argv[8] = pack_string(p->rp_id)) == NULL ||
+ (argv[9] = pack_string(p->rp_name)) == NULL ||
+ (argv[10] = pack_string(p->user_icon)) == NULL ||
+ (argv[11] = pack_string(p->user_name)) == NULL ||
+ (argv[12] = pack_string(p->user_nick)) == NULL ||
+ (argv[13] = pack_blob(&p->cdh)) == NULL ||
+ (argv[14] = pack_blob(&p->user_id)) == NULL ||
+ (argv[15] = pack_blob(&p->wire_data)) == NULL ||
+ (argv[16] = pack_blob(&p->excl_cred)) == NULL)
+ goto fail;
+
+ for (size_t i = 0; i < 17; i++)
+ if (cbor_array_push(array, argv[i]) == false)
+ goto fail;
+
+ if ((cbor_len = cbor_serialize_alloc(array, &cbor,
+ &cbor_alloc_len)) == 0 || cbor_len > len) {
+ cbor_len = 0;
+ goto fail;
+ }
+
+ memcpy(ptr, cbor, cbor_len);
+fail:
+ for (size_t i = 0; i < 17; i++)
+ if (argv[i])
+ cbor_decref(&argv[i]);
+
+ if (array)
+ cbor_decref(&array);
+
+ free(cbor);
+
+ return cbor_len;
+}
+
+size_t
+pack_dummy(uint8_t *ptr, size_t len)
+{
+ struct param dummy;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&dummy, 0, sizeof(dummy));
+
+ dummy.type = 1;
+ dummy.ext = FIDO_EXT_HMAC_SECRET;
+
+ strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
+ strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
+ strlcpy(dummy.rp_name, dummy_rp_name, sizeof(dummy.rp_name));
+ strlcpy(dummy.user_icon, dummy_user_icon, sizeof(dummy.user_icon));
+ strlcpy(dummy.user_name, dummy_user_name, sizeof(dummy.user_name));
+ strlcpy(dummy.user_nick, dummy_user_nick, sizeof(dummy.user_nick));
+
+ dummy.cdh.len = sizeof(dummy_cdh);
+ dummy.user_id.len = sizeof(dummy_user_id);
+ dummy.wire_data.len = sizeof(dummy_wire_data_fido);
+
+ memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len);
+ memcpy(&dummy.user_id.body, &dummy_user_id, dummy.user_id.len);
+ memcpy(&dummy.wire_data.body, &dummy_wire_data_fido,
+ dummy.wire_data.len);
+
+ assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
+
+ if (blob_len > len) {
+ memcpy(ptr, blob, len);
+ return len;
+ }
+
+ memcpy(ptr, blob, blob_len);
+
+ return blob_len;
+}
+
+static void
+make_cred(fido_cred_t *cred, uint8_t opt, int type, const struct blob *cdh,
+ const char *rp_id, const char *rp_name, const struct blob *user_id,
+ const char *user_name, const char *user_nick, const char *user_icon,
+ int ext, uint8_t rk, uint8_t uv, const char *pin, uint8_t excl_count,
+ const struct blob *excl_cred)
+{
+ fido_dev_t *dev;
+
+ if ((dev = open_dev(opt & 2)) == NULL)
+ return;
+ if (opt & 1)
+ fido_dev_force_u2f(dev);
+
+ for (uint8_t i = 0; i < excl_count; i++)
+ fido_cred_exclude(cred, excl_cred->body, excl_cred->len);
+
+ fido_cred_set_type(cred, type);
+ fido_cred_set_clientdata_hash(cred, cdh->body, cdh->len);
+ fido_cred_set_rp(cred, rp_id, rp_name);
+ fido_cred_set_user(cred, user_id->body, user_id->len, user_name,
+ user_nick, user_icon);
+
+ if (ext & FIDO_EXT_HMAC_SECRET)
+ fido_cred_set_extensions(cred, FIDO_EXT_HMAC_SECRET);
+ if (ext & FIDO_EXT_CRED_BLOB)
+ fido_cred_set_blob(cred, user_id->body, user_id->len);
+ if (ext & FIDO_EXT_LARGEBLOB_KEY)
+ fido_cred_set_extensions(cred, FIDO_EXT_LARGEBLOB_KEY);
+ if (ext & FIDO_EXT_MINPINLEN)
+ fido_cred_set_pin_minlen(cred, strlen(pin));
+
+ if (rk & 1)
+ fido_cred_set_rk(cred, FIDO_OPT_TRUE);
+ if (uv & 1)
+ fido_cred_set_uv(cred, FIDO_OPT_TRUE);
+ if (user_id->len)
+ fido_cred_set_prot(cred, user_id->body[0] & 0x03);
+
+ /* repeat memory operations to trigger reallocation paths */
+ fido_cred_set_type(cred, type);
+ fido_cred_set_clientdata_hash(cred, cdh->body, cdh->len);
+ fido_cred_set_rp(cred, rp_id, rp_name);
+ fido_cred_set_user(cred, user_id->body, user_id->len, user_name,
+ user_nick, user_icon);
+
+ if (strlen(pin) == 0)
+ pin = NULL;
+
+ fido_dev_make_cred(dev, cred, (opt & 1) ? NULL : pin);
+
+ fido_dev_cancel(dev);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
+ const char *rp_id, const char *rp_name, const unsigned char *authdata_ptr,
+ size_t authdata_len, const unsigned char *authdata_raw_ptr,
+ size_t authdata_raw_len, int ext, uint8_t rk, uint8_t uv,
+ const unsigned char *x5c_ptr, size_t x5c_len, const unsigned char *sig_ptr,
+ size_t sig_len, const unsigned char *attstmt_ptr, size_t attstmt_len,
+ const char *fmt, int prot, size_t minpinlen)
+{
+ fido_cred_t *cred;
+ uint8_t flags;
+ uint32_t sigcount;
+ int r;
+
+ if ((cred = fido_cred_new()) == NULL)
+ return;
+
+ fido_cred_set_type(cred, type);
+ fido_cred_set_clientdata_hash(cred, cdh_ptr, cdh_len);
+ fido_cred_set_rp(cred, rp_id, rp_name);
+ consume(authdata_ptr, authdata_len);
+ consume(authdata_raw_ptr, authdata_raw_len);
+ consume(x5c_ptr, x5c_len);
+ consume(sig_ptr, sig_len);
+ consume(attstmt_ptr, attstmt_len);
+ if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK)
+ fido_cred_set_authdata_raw(cred, authdata_raw_ptr,
+ authdata_raw_len);
+ fido_cred_set_extensions(cred, ext);
+ if (fido_cred_set_attstmt(cred, attstmt_ptr, attstmt_len) != FIDO_OK) {
+ fido_cred_set_x509(cred, x5c_ptr, x5c_len);
+ fido_cred_set_sig(cred, sig_ptr, sig_len);
+ }
+ fido_cred_set_prot(cred, prot);
+ fido_cred_set_pin_minlen(cred, minpinlen);
+
+ if (rk & 1)
+ fido_cred_set_rk(cred, FIDO_OPT_TRUE);
+ if (uv & 1)
+ fido_cred_set_uv(cred, FIDO_OPT_TRUE);
+ if (fmt)
+ fido_cred_set_fmt(cred, fmt);
+
+ /* repeat memory operations to trigger reallocation paths */
+ if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK)
+ fido_cred_set_authdata_raw(cred, authdata_raw_ptr,
+ authdata_raw_len);
+ if (fido_cred_set_attstmt(cred, attstmt_ptr, attstmt_len) != FIDO_OK) {
+ fido_cred_set_x509(cred, x5c_ptr, x5c_len);
+ fido_cred_set_sig(cred, sig_ptr, sig_len);
+ }
+ fido_cred_set_x509(cred, x5c_ptr, x5c_len);
+ fido_cred_set_sig(cred, sig_ptr, sig_len);
+
+ r = fido_cred_verify(cred);
+ consume(&r, sizeof(r));
+ r = fido_cred_verify_self(cred);
+ consume(&r, sizeof(r));
+
+ consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred));
+ consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred));
+ consume(fido_cred_aaguid_ptr(cred), fido_cred_aaguid_len(cred));
+ consume(fido_cred_user_id_ptr(cred), fido_cred_user_id_len(cred));
+ consume_str(fido_cred_user_name(cred));
+ consume_str(fido_cred_display_name(cred));
+ consume(fido_cred_largeblob_key_ptr(cred),
+ fido_cred_largeblob_key_len(cred));
+
+ flags = fido_cred_flags(cred);
+ consume(&flags, sizeof(flags));
+ sigcount = fido_cred_sigcount(cred);
+ consume(&sigcount, sizeof(sigcount));
+ type = fido_cred_type(cred);
+ consume(&type, sizeof(type));
+ minpinlen = fido_cred_pin_minlen(cred);
+ consume(&minpinlen, sizeof(minpinlen));
+
+ fido_cred_free(&cred);
+}
+
+static void
+test_cred(const struct param *p)
+{
+ fido_cred_t *cred = NULL;
+ int cose_alg = 0;
+
+ if ((cred = fido_cred_new()) == NULL)
+ return;
+
+ switch (p->type & 3) {
+ case 0:
+ cose_alg = COSE_ES256;
+ break;
+ case 1:
+ cose_alg = COSE_RS256;
+ break;
+ case 2:
+ cose_alg = COSE_ES384;
+ break;
+ default:
+ cose_alg = COSE_EDDSA;
+ break;
+ }
+
+ set_wire_data(p->wire_data.body, p->wire_data.len);
+
+ make_cred(cred, p->opt, cose_alg, &p->cdh, p->rp_id, p->rp_name,
+ &p->user_id, p->user_name, p->user_nick, p->user_icon, p->ext,
+ p->rk, p->uv, p->pin, p->excl_count, &p->excl_cred);
+
+ verify_cred(cose_alg,
+ fido_cred_clientdata_hash_ptr(cred),
+ fido_cred_clientdata_hash_len(cred), fido_cred_rp_id(cred),
+ fido_cred_rp_name(cred), fido_cred_authdata_ptr(cred),
+ fido_cred_authdata_len(cred), fido_cred_authdata_raw_ptr(cred),
+ fido_cred_authdata_raw_len(cred), p->ext, p->rk, p->uv,
+ fido_cred_x5c_ptr(cred), fido_cred_x5c_len(cred),
+ fido_cred_sig_ptr(cred), fido_cred_sig_len(cred),
+ fido_cred_attstmt_ptr(cred), fido_cred_attstmt_len(cred),
+ fido_cred_fmt(cred), fido_cred_prot(cred),
+ fido_cred_pin_minlen(cred));
+
+ fido_cred_free(&cred);
+}
+
+static void
+test_touch(const struct param *p)
+{
+ fido_dev_t *dev;
+ int r;
+ int touched;
+
+ set_wire_data(p->wire_data.body, p->wire_data.len);
+
+ if ((dev = open_dev(p->opt & 2)) == NULL)
+ return;
+ if (p->opt & 1)
+ fido_dev_force_u2f(dev);
+
+ r = fido_dev_get_touch_begin(dev);
+ consume_str(fido_strerr(r));
+ r = fido_dev_get_touch_status(dev, &touched, -1);
+ consume_str(fido_strerr(r));
+ consume(&touched, sizeof(touched));
+
+ fido_dev_cancel(dev);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+test_misc(const struct param *p)
+{
+ fido_cred_t *cred = NULL;
+
+ if ((cred = fido_cred_new()) == NULL)
+ return;
+
+ /* reuse user id as credential id */
+ fido_cred_set_id(cred, p->user_id.body, p->user_id.len);
+ consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred));
+ fido_cred_free(&cred);
+}
+
+void
+test(const struct param *p)
+{
+ prng_init((unsigned int)p->seed);
+ fuzz_clock_reset();
+ fido_init(FIDO_DEBUG);
+ fido_set_log_handler(consume_str);
+
+ test_cred(p);
+ test_touch(p);
+ test_misc(p);
+}
+
+void
+mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
+{
+ if (flags & MUTATE_SEED)
+ p->seed = (int)seed;
+
+ if (flags & MUTATE_PARAM) {
+ mutate_byte(&p->rk);
+ mutate_byte(&p->type);
+ mutate_byte(&p->opt);
+ mutate_byte(&p->uv);
+ mutate_byte(&p->excl_count);
+ mutate_int(&p->ext);
+ mutate_blob(&p->cdh);
+ mutate_blob(&p->user_id);
+ mutate_blob(&p->excl_cred);
+ mutate_string(p->pin);
+ mutate_string(p->user_icon);
+ mutate_string(p->user_name);
+ mutate_string(p->user_nick);
+ mutate_string(p->rp_id);
+ mutate_string(p->rp_name);
+ }
+
+ if (flags & MUTATE_WIREDATA) {
+ if (p->opt & 1) {
+ p->wire_data.len = sizeof(dummy_wire_data_u2f);
+ memcpy(&p->wire_data.body, &dummy_wire_data_u2f,
+ p->wire_data.len);
+ } else {
+ p->wire_data.len = sizeof(dummy_wire_data_fido);
+ memcpy(&p->wire_data.body, &dummy_wire_data_fido,
+ p->wire_data.len);
+ }
+ mutate_blob(&p->wire_data);
+ }
+}
diff --git a/fuzz/fuzz_credman.c b/fuzz/fuzz_credman.c
new file mode 100644
index 0000000..ef21475
--- /dev/null
+++ b/fuzz/fuzz_credman.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2019-2021 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 <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mutator_aux.h"
+#include "wiredata_fido2.h"
+#include "dummy.h"
+
+#include "../openbsd-compat/openbsd-compat.h"
+
+/* Parameter set defining a FIDO2 credential management operation. */
+struct param {
+ char pin[MAXSTR];
+ char rp_id[MAXSTR];
+ int seed;
+ struct blob cred_id;
+ struct blob del_wire_data;
+ struct blob meta_wire_data;
+ struct blob rk_wire_data;
+ struct blob rp_wire_data;
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'getCredsMetadata' credential management command.
+ */
+static const uint8_t dummy_meta_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_CREDMAN_META,
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'enumerateRPsBegin' credential management command.
+ */
+static const uint8_t dummy_rp_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_CREDMAN_RPLIST,
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'enumerateCredentialsBegin' credential management command.
+ */
+static const uint8_t dummy_rk_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_CREDMAN_RKLIST,
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'deleteCredential' credential management command.
+ */
+static const uint8_t dummy_del_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_STATUS,
+};
+
+struct param *
+unpack(const uint8_t *ptr, size_t len)
+{
+ cbor_item_t *item = NULL, **v;
+ struct cbor_load_result cbor;
+ struct param *p;
+ int ok = -1;
+
+ if ((p = calloc(1, sizeof(*p))) == NULL ||
+ (item = cbor_load(ptr, len, &cbor)) == NULL ||
+ cbor.read != len ||
+ cbor_isa_array(item) == false ||
+ cbor_array_is_definite(item) == false ||
+ cbor_array_size(item) != 8 ||
+ (v = cbor_array_handle(item)) == NULL)
+ goto fail;
+
+ if (unpack_int(v[0], &p->seed) < 0 ||
+ unpack_string(v[1], p->pin) < 0 ||
+ unpack_string(v[2], p->rp_id) < 0 ||
+ unpack_blob(v[3], &p->cred_id) < 0 ||
+ unpack_blob(v[4], &p->meta_wire_data) < 0 ||
+ unpack_blob(v[5], &p->rp_wire_data) < 0 ||
+ unpack_blob(v[6], &p->rk_wire_data) < 0 ||
+ unpack_blob(v[7], &p->del_wire_data) < 0)
+ goto fail;
+
+ ok = 0;
+fail:
+ if (ok < 0) {
+ free(p);
+ p = NULL;
+ }
+
+ if (item)
+ cbor_decref(&item);
+
+ return p;
+}
+
+size_t
+pack(uint8_t *ptr, size_t len, const struct param *p)
+{
+ cbor_item_t *argv[8], *array = NULL;
+ size_t cbor_alloc_len, cbor_len = 0;
+ unsigned char *cbor = NULL;
+
+ memset(argv, 0, sizeof(argv));
+
+ if ((array = cbor_new_definite_array(8)) == NULL ||
+ (argv[0] = pack_int(p->seed)) == NULL ||
+ (argv[1] = pack_string(p->pin)) == NULL ||
+ (argv[2] = pack_string(p->rp_id)) == NULL ||
+ (argv[3] = pack_blob(&p->cred_id)) == NULL ||
+ (argv[4] = pack_blob(&p->meta_wire_data)) == NULL ||
+ (argv[5] = pack_blob(&p->rp_wire_data)) == NULL ||
+ (argv[6] = pack_blob(&p->rk_wire_data)) == NULL ||
+ (argv[7] = pack_blob(&p->del_wire_data)) == NULL)
+ goto fail;
+
+ for (size_t i = 0; i < 8; i++)
+ if (cbor_array_push(array, argv[i]) == false)
+ goto fail;
+
+ if ((cbor_len = cbor_serialize_alloc(array, &cbor,
+ &cbor_alloc_len)) == 0 || cbor_len > len) {
+ cbor_len = 0;
+ goto fail;
+ }
+
+ memcpy(ptr, cbor, cbor_len);
+fail:
+ for (size_t i = 0; i < 8; i++)
+ if (argv[i])
+ cbor_decref(&argv[i]);
+
+ if (array)
+ cbor_decref(&array);
+
+ free(cbor);
+
+ return cbor_len;
+}
+
+size_t
+pack_dummy(uint8_t *ptr, size_t len)
+{
+ struct param dummy;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&dummy, 0, sizeof(dummy));
+
+ strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
+ strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
+
+ dummy.meta_wire_data.len = sizeof(dummy_meta_wire_data);
+ dummy.rp_wire_data.len = sizeof(dummy_rp_wire_data);
+ dummy.rk_wire_data.len = sizeof(dummy_rk_wire_data);
+ dummy.del_wire_data.len = sizeof(dummy_del_wire_data);
+ dummy.cred_id.len = sizeof(dummy_cred_id);
+
+ memcpy(&dummy.meta_wire_data.body, &dummy_meta_wire_data,
+ dummy.meta_wire_data.len);
+ memcpy(&dummy.rp_wire_data.body, &dummy_rp_wire_data,
+ dummy.rp_wire_data.len);
+ memcpy(&dummy.rk_wire_data.body, &dummy_rk_wire_data,
+ dummy.rk_wire_data.len);
+ memcpy(&dummy.del_wire_data.body, &dummy_del_wire_data,
+ dummy.del_wire_data.len);
+ memcpy(&dummy.cred_id.body, &dummy_cred_id, dummy.cred_id.len);
+
+ assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
+
+ if (blob_len > len) {
+ memcpy(ptr, blob, len);
+ return len;
+ }
+
+ memcpy(ptr, blob, blob_len);
+
+ return blob_len;
+}
+
+static fido_dev_t *
+prepare_dev(void)
+{
+ fido_dev_t *dev;
+ bool x;
+
+ if ((dev = open_dev(0)) == NULL)
+ return NULL;
+
+ x = fido_dev_is_fido2(dev);
+ consume(&x, sizeof(x));
+ x = fido_dev_supports_cred_prot(dev);
+ consume(&x, sizeof(x));
+ x = fido_dev_supports_credman(dev);
+ consume(&x, sizeof(x));
+
+ return dev;
+}
+
+static void
+get_metadata(const struct param *p)
+{
+ fido_dev_t *dev;
+ fido_credman_metadata_t *metadata;
+ uint64_t existing;
+ uint64_t remaining;
+
+ set_wire_data(p->meta_wire_data.body, p->meta_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL)
+ return;
+
+ if ((metadata = fido_credman_metadata_new()) == NULL) {
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+ return;
+ }
+
+ fido_credman_get_dev_metadata(dev, metadata, p->pin);
+
+ existing = fido_credman_rk_existing(metadata);
+ remaining = fido_credman_rk_remaining(metadata);
+ consume(&existing, sizeof(existing));
+ consume(&remaining, sizeof(remaining));
+
+ fido_credman_metadata_free(&metadata);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+get_rp_list(const struct param *p)
+{
+ fido_dev_t *dev;
+ fido_credman_rp_t *rp;
+
+ set_wire_data(p->rp_wire_data.body, p->rp_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL)
+ return;
+
+ if ((rp = fido_credman_rp_new()) == NULL) {
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+ return;
+ }
+
+ fido_credman_get_dev_rp(dev, rp, p->pin);
+
+ /* +1 on purpose */
+ for (size_t i = 0; i < fido_credman_rp_count(rp) + 1; i++) {
+ consume(fido_credman_rp_id_hash_ptr(rp, i),
+ fido_credman_rp_id_hash_len(rp, i));
+ consume_str(fido_credman_rp_id(rp, i));
+ consume_str(fido_credman_rp_name(rp, i));
+ }
+
+ fido_credman_rp_free(&rp);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+get_rk_list(const struct param *p)
+{
+ fido_dev_t *dev;
+ fido_credman_rk_t *rk;
+ const fido_cred_t *cred;
+ int val;
+
+ set_wire_data(p->rk_wire_data.body, p->rk_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL)
+ return;
+
+ if ((rk = fido_credman_rk_new()) == NULL) {
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+ return;
+ }
+
+ fido_credman_get_dev_rk(dev, p->rp_id, rk, p->pin);
+
+ /* +1 on purpose */
+ for (size_t i = 0; i < fido_credman_rk_count(rk) + 1; i++) {
+ if ((cred = fido_credman_rk(rk, i)) == NULL) {
+ assert(i >= fido_credman_rk_count(rk));
+ continue;
+ }
+ val = fido_cred_type(cred);
+ consume(&val, sizeof(val));
+ consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred));
+ consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred));
+ consume(fido_cred_user_id_ptr(cred),
+ fido_cred_user_id_len(cred));
+ consume_str(fido_cred_user_name(cred));
+ consume_str(fido_cred_display_name(cred));
+ val = fido_cred_prot(cred);
+ consume(&val, sizeof(val));
+ }
+
+ fido_credman_rk_free(&rk);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+del_rk(const struct param *p)
+{
+ fido_dev_t *dev;
+
+ set_wire_data(p->del_wire_data.body, p->del_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL)
+ return;
+
+ fido_credman_del_dev_rk(dev, p->cred_id.body, p->cred_id.len, p->pin);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+set_rk(const struct param *p)
+{
+ fido_dev_t *dev = NULL;
+ fido_cred_t *cred = NULL;
+ const char *pin = p->pin;
+ int r0, r1, r2;
+
+ set_wire_data(p->del_wire_data.body, p->del_wire_data.len);
+
+ if ((dev = prepare_dev()) == NULL)
+ return;
+ if ((cred = fido_cred_new()) == NULL)
+ goto out;
+ r0 = fido_cred_set_id(cred, p->cred_id.body, p->cred_id.len);
+ r1 = fido_cred_set_user(cred, p->cred_id.body, p->cred_id.len, p->rp_id,
+ NULL, NULL);
+ if (strlen(pin) == 0)
+ pin = NULL;
+ r2 = fido_credman_set_dev_rk(dev, cred, pin);
+ consume(&r0, sizeof(r0));
+ consume(&r1, sizeof(r1));
+ consume(&r2, sizeof(r2));
+out:
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+ fido_cred_free(&cred);
+}
+
+void
+test(const struct param *p)
+{
+ prng_init((unsigned int)p->seed);
+ fuzz_clock_reset();
+ fido_init(FIDO_DEBUG);
+ fido_set_log_handler(consume_str);
+
+ get_metadata(p);
+ get_rp_list(p);
+ get_rk_list(p);
+ del_rk(p);
+ set_rk(p);
+}
+
+void
+mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
+{
+ if (flags & MUTATE_SEED)
+ p->seed = (int)seed;
+
+ if (flags & MUTATE_PARAM) {
+ mutate_blob(&p->cred_id);
+ mutate_string(p->pin);
+ mutate_string(p->rp_id);
+ }
+
+ if (flags & MUTATE_WIREDATA) {
+ mutate_blob(&p->meta_wire_data);
+ mutate_blob(&p->rp_wire_data);
+ mutate_blob(&p->rk_wire_data);
+ mutate_blob(&p->del_wire_data);
+ }
+}
diff --git a/fuzz/fuzz_hid.c b/fuzz/fuzz_hid.c
new file mode 100644
index 0000000..daaadad
--- /dev/null
+++ b/fuzz/fuzz_hid.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2020-2021 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 <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../openbsd-compat/openbsd-compat.h"
+#include "mutator_aux.h"
+#include "dummy.h"
+
+extern int fido_hid_get_usage(const uint8_t *, size_t, uint32_t *);
+extern int fido_hid_get_report_len(const uint8_t *, size_t, size_t *, size_t *);
+extern void set_udev_parameters(const char *, const struct blob *);
+
+struct param {
+ int seed;
+ char uevent[MAXSTR];
+ struct blob report_descriptor;
+ struct blob netlink_wiredata;
+};
+
+/*
+ * Sample HID report descriptor from the FIDO HID interface of a YubiKey 5.
+ */
+static const uint8_t dummy_report_descriptor[] = {
+ 0x06, 0xd0, 0xf1, 0x09, 0x01, 0xa1, 0x01, 0x09,
+ 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08,
+ 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00,
+ 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, 0x40, 0x91,
+ 0x02, 0xc0
+};
+
+/*
+ * Sample uevent file from a Yubico Security Key.
+ */
+static const char dummy_uevent[] =
+ "DRIVER=hid-generic\n"
+ "HID_ID=0003:00001050:00000120\n"
+ "HID_NAME=Yubico Security Key by Yubico\n"
+ "HID_PHYS=usb-0000:00:14.0-3/input0\n"
+ "HID_UNIQ=\n"
+ "MODALIAS=hid:b0003g0001v00001050p00000120\n";
+
+struct param *
+unpack(const uint8_t *ptr, size_t len)
+{
+ cbor_item_t *item = NULL, **v;
+ struct cbor_load_result cbor;
+ struct param *p;
+ int ok = -1;
+
+ if ((p = calloc(1, sizeof(*p))) == NULL ||
+ (item = cbor_load(ptr, len, &cbor)) == NULL ||
+ cbor.read != len ||
+ cbor_isa_array(item) == false ||
+ cbor_array_is_definite(item) == false ||
+ cbor_array_size(item) != 4 ||
+ (v = cbor_array_handle(item)) == NULL)
+ goto fail;
+
+ if (unpack_int(v[0], &p->seed) < 0 ||
+ unpack_string(v[1], p->uevent) < 0 ||
+ unpack_blob(v[2], &p->report_descriptor) < 0 ||
+ unpack_blob(v[3], &p->netlink_wiredata) < 0)
+ goto fail;
+
+ ok = 0;
+fail:
+ if (ok < 0) {
+ free(p);
+ p = NULL;
+ }
+
+ if (item)
+ cbor_decref(&item);
+
+ return p;
+}
+
+size_t
+pack(uint8_t *ptr, size_t len, const struct param *p)
+{
+ cbor_item_t *argv[4], *array = NULL;
+ size_t cbor_alloc_len, cbor_len = 0;
+ unsigned char *cbor = NULL;
+
+ memset(argv, 0, sizeof(argv));
+
+ if ((array = cbor_new_definite_array(4)) == NULL ||
+ (argv[0] = pack_int(p->seed)) == NULL ||
+ (argv[1] = pack_string(p->uevent)) == NULL ||
+ (argv[2] = pack_blob(&p->report_descriptor)) == NULL ||
+ (argv[3] = pack_blob(&p->netlink_wiredata)) == NULL)
+ goto fail;
+
+ for (size_t i = 0; i < 4; i++)
+ if (cbor_array_push(array, argv[i]) == false)
+ goto fail;
+
+ if ((cbor_len = cbor_serialize_alloc(array, &cbor,
+ &cbor_alloc_len)) == 0 || cbor_len > len) {
+ cbor_len = 0;
+ goto fail;
+ }
+
+ memcpy(ptr, cbor, cbor_len);
+fail:
+ for (size_t i = 0; i < 4; i++)
+ if (argv[i])
+ cbor_decref(&argv[i]);
+
+ if (array)
+ cbor_decref(&array);
+
+ free(cbor);
+
+ return cbor_len;
+}
+
+size_t
+pack_dummy(uint8_t *ptr, size_t len)
+{
+ struct param dummy;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&dummy, 0, sizeof(dummy));
+
+ dummy.report_descriptor.len = sizeof(dummy_report_descriptor);
+ strlcpy(dummy.uevent, dummy_uevent, sizeof(dummy.uevent));
+ memcpy(&dummy.report_descriptor.body, &dummy_report_descriptor,
+ dummy.report_descriptor.len);
+ dummy.netlink_wiredata.len = sizeof(dummy_netlink_wiredata);
+ memcpy(&dummy.netlink_wiredata.body, &dummy_netlink_wiredata,
+ dummy.netlink_wiredata.len);
+
+ assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
+ if (blob_len > len)
+ blob_len = len;
+
+ memcpy(ptr, blob, blob_len);
+
+ return blob_len;
+}
+
+static void
+get_usage(const struct param *p)
+{
+ uint32_t usage_page = 0;
+
+ fido_hid_get_usage(p->report_descriptor.body, p->report_descriptor.len,
+ &usage_page);
+ consume(&usage_page, sizeof(usage_page));
+}
+
+static void
+get_report_len(const struct param *p)
+{
+ size_t report_in_len = 0;
+ size_t report_out_len = 0;
+
+ fido_hid_get_report_len(p->report_descriptor.body,
+ p->report_descriptor.len, &report_in_len, &report_out_len);
+ consume(&report_in_len, sizeof(report_in_len));
+ consume(&report_out_len, sizeof(report_out_len));
+}
+
+static void
+manifest(const struct param *p)
+{
+ size_t ndevs, nfound;
+ fido_dev_info_t *devlist = NULL, *devlist_set = NULL;
+ int16_t vendor_id, product_id;
+ fido_dev_io_t io;
+ fido_dev_transport_t t;
+
+ memset(&io, 0, sizeof(io));
+ memset(&t, 0, sizeof(t));
+ set_netlink_io_functions(fd_read, fd_write);
+ set_wire_data(p->netlink_wiredata.body, p->netlink_wiredata.len);
+ set_udev_parameters(p->uevent, &p->report_descriptor);
+
+ ndevs = uniform_random(64);
+ if ((devlist = fido_dev_info_new(ndevs)) == NULL ||
+ (devlist_set = fido_dev_info_new(1)) == NULL ||
+ fido_dev_info_manifest(devlist, ndevs, &nfound) != FIDO_OK)
+ goto out;
+ for (size_t i = 0; i < nfound; i++) {
+ const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
+ consume_str(fido_dev_info_path(di));
+ consume_str(fido_dev_info_manufacturer_string(di));
+ consume_str(fido_dev_info_product_string(di));
+ vendor_id = fido_dev_info_vendor(di);
+ product_id = fido_dev_info_product(di);
+ consume(&vendor_id, sizeof(vendor_id));
+ consume(&product_id, sizeof(product_id));
+ fido_dev_info_set(devlist_set, 0, fido_dev_info_path(di),
+ fido_dev_info_manufacturer_string(di),
+ fido_dev_info_product_string(di), &io, &t);
+ }
+out:
+ fido_dev_info_free(&devlist, ndevs);
+ fido_dev_info_free(&devlist_set, 1);
+}
+
+void
+test(const struct param *p)
+{
+ prng_init((unsigned int)p->seed);
+ fuzz_clock_reset();
+ fido_init(FIDO_DEBUG);
+ fido_set_log_handler(consume_str);
+
+ get_usage(p);
+ get_report_len(p);
+ manifest(p);
+}
+
+void
+mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
+{
+ if (flags & MUTATE_SEED)
+ p->seed = (int)seed;
+
+ if (flags & MUTATE_PARAM) {
+ mutate_blob(&p->report_descriptor);
+ mutate_string(p->uevent);
+ }
+
+ if (flags & MUTATE_WIREDATA)
+ mutate_blob(&p->netlink_wiredata);
+}
diff --git a/fuzz/fuzz_largeblob.c b/fuzz/fuzz_largeblob.c
new file mode 100644
index 0000000..6cdc0c0
--- /dev/null
+++ b/fuzz/fuzz_largeblob.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2020 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 <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mutator_aux.h"
+#include "wiredata_fido2.h"
+#include "dummy.h"
+
+#include "../openbsd-compat/openbsd-compat.h"
+
+/* Parameter set defining a FIDO2 "large blob" operation. */
+struct param {
+ char pin[MAXSTR];
+ int seed;
+ struct blob key;
+ struct blob get_wiredata;
+ struct blob set_wiredata;
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'authenticatorLargeBlobs' 'get' command.
+ */
+static const uint8_t dummy_get_wiredata[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY
+};
+
+/*
+ * Collection of HID reports from an authenticator issued with a FIDO2
+ * 'authenticatorLargeBlobs' 'set' command.
+ */
+static const uint8_t dummy_set_wiredata[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_PINTOKEN,
+ WIREDATA_CTAP_CBOR_STATUS
+};
+
+/*
+ * XXX this needs to match the encrypted blob embedded in
+ * WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY.
+ */
+static const uint8_t dummy_key[] = {
+ 0xa9, 0x1b, 0xc4, 0xdd, 0xfc, 0x9a, 0x93, 0x79,
+ 0x75, 0xba, 0xf7, 0x7f, 0x4d, 0x57, 0xfc, 0xa6,
+ 0xe1, 0xf8, 0x06, 0x43, 0x23, 0x99, 0x51, 0x32,
+ 0xce, 0x6e, 0x19, 0x84, 0x50, 0x13, 0x2d, 0x7b
+};
+
+struct param *
+unpack(const uint8_t *ptr, size_t len)
+{
+ cbor_item_t *item = NULL, **v;
+ struct cbor_load_result cbor;
+ struct param *p;
+ int ok = -1;
+
+ if ((p = calloc(1, sizeof(*p))) == NULL ||
+ (item = cbor_load(ptr, len, &cbor)) == NULL ||
+ cbor.read != len ||
+ cbor_isa_array(item) == false ||
+ cbor_array_is_definite(item) == false ||
+ cbor_array_size(item) != 5 ||
+ (v = cbor_array_handle(item)) == NULL)
+ goto fail;
+
+ if (unpack_int(v[0], &p->seed) < 0 ||
+ unpack_string(v[1], p->pin) < 0 ||
+ unpack_blob(v[2], &p->key) < 0 ||
+ unpack_blob(v[3], &p->get_wiredata) < 0 ||
+ unpack_blob(v[4], &p->set_wiredata) < 0)
+ goto fail;
+
+ ok = 0;
+fail:
+ if (ok < 0) {
+ free(p);
+ p = NULL;
+ }
+
+ if (item)
+ cbor_decref(&item);
+
+ return p;
+}
+
+size_t
+pack(uint8_t *ptr, size_t len, const struct param *p)
+{
+ cbor_item_t *argv[5], *array = NULL;
+ size_t cbor_alloc_len, cbor_len = 0;
+ unsigned char *cbor = NULL;
+
+ memset(argv, 0, sizeof(argv));
+
+ if ((array = cbor_new_definite_array(5)) == NULL ||
+ (argv[0] = pack_int(p->seed)) == NULL ||
+ (argv[1] = pack_string(p->pin)) == NULL ||
+ (argv[2] = pack_blob(&p->key)) == NULL ||
+ (argv[3] = pack_blob(&p->get_wiredata)) == NULL ||
+ (argv[4] = pack_blob(&p->set_wiredata)) == NULL)
+ goto fail;
+
+ for (size_t i = 0; i < 5; i++)
+ if (cbor_array_push(array, argv[i]) == false)
+ goto fail;
+
+ if ((cbor_len = cbor_serialize_alloc(array, &cbor,
+ &cbor_alloc_len)) == 0 || cbor_len > len) {
+ cbor_len = 0;
+ goto fail;
+ }
+
+ memcpy(ptr, cbor, cbor_len);
+fail:
+ for (size_t i = 0; i < 5; i++)
+ if (argv[i])
+ cbor_decref(&argv[i]);
+
+ if (array)
+ cbor_decref(&array);
+
+ free(cbor);
+
+ return cbor_len;
+}
+
+size_t
+pack_dummy(uint8_t *ptr, size_t len)
+{
+ struct param dummy;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&dummy, 0, sizeof(dummy));
+
+ strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin));
+
+ dummy.get_wiredata.len = sizeof(dummy_get_wiredata);
+ dummy.set_wiredata.len = sizeof(dummy_set_wiredata);
+ dummy.key.len = sizeof(dummy_key);
+
+ memcpy(&dummy.get_wiredata.body, &dummy_get_wiredata,
+ dummy.get_wiredata.len);
+ memcpy(&dummy.set_wiredata.body, &dummy_set_wiredata,
+ dummy.set_wiredata.len);
+ memcpy(&dummy.key.body, &dummy_key, dummy.key.len);
+
+ assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
+
+ if (blob_len > len) {
+ memcpy(ptr, blob, len);
+ return len;
+ }
+
+ memcpy(ptr, blob, blob_len);
+
+ return blob_len;
+}
+
+static fido_dev_t *
+prepare_dev(void)
+{
+ fido_dev_t *dev;
+
+ if ((dev = open_dev(0)) == NULL)
+ return NULL;
+
+ return dev;
+}
+
+static void
+get_blob(const struct param *p, int array)
+{
+ fido_dev_t *dev;
+ u_char *ptr = NULL;
+ size_t len = 0;
+
+ set_wire_data(p->get_wiredata.body, p->get_wiredata.len);
+
+ if ((dev = prepare_dev()) == NULL)
+ return;
+
+ if (array)
+ fido_dev_largeblob_get_array(dev, &ptr, &len);
+ else
+ fido_dev_largeblob_get(dev, p->key.body, p->key.len, &ptr, &len);
+ consume(ptr, len);
+ free(ptr);
+
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+
+static void
+set_blob(const struct param *p, int op)
+{
+ fido_dev_t *dev;
+ const char *pin;
+
+ set_wire_data(p->set_wiredata.body, p->set_wiredata.len);
+
+ if ((dev = prepare_dev()) == NULL)
+ return;
+ pin = p->pin;
+ if (strlen(pin) == 0)
+ pin = NULL;
+
+ switch (op) {
+ case 0:
+ fido_dev_largeblob_remove(dev, p->key.body, p->key.len, pin);
+ break;
+ case 1:
+ /* XXX reuse p->get_wiredata as the blob to be set */
+ fido_dev_largeblob_set(dev, p->key.body, p->key.len,
+ p->get_wiredata.body, p->get_wiredata.len, pin);
+ break;
+ case 2:
+ /* XXX reuse p->get_wiredata as the body of the cbor array */
+ fido_dev_largeblob_set_array(dev, p->get_wiredata.body,
+ p->get_wiredata.len, pin);
+ }
+
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+void
+test(const struct param *p)
+{
+ prng_init((unsigned int)p->seed);
+ fuzz_clock_reset();
+ fido_init(FIDO_DEBUG);
+ fido_set_log_handler(consume_str);
+
+ get_blob(p, 0);
+ get_blob(p, 1);
+ set_blob(p, 0);
+ set_blob(p, 1);
+ set_blob(p, 2);
+}
+
+void
+mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
+{
+ if (flags & MUTATE_SEED)
+ p->seed = (int)seed;
+
+ if (flags & MUTATE_PARAM) {
+ mutate_blob(&p->key);
+ mutate_string(p->pin);
+ }
+
+ if (flags & MUTATE_WIREDATA) {
+ mutate_blob(&p->get_wiredata);
+ mutate_blob(&p->set_wiredata);
+ }
+}
diff --git a/fuzz/fuzz_mgmt.c b/fuzz/fuzz_mgmt.c
new file mode 100644
index 0000000..cbc313d
--- /dev/null
+++ b/fuzz/fuzz_mgmt.c
@@ -0,0 +1,528 @@
+/*
+ * 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 <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mutator_aux.h"
+#include "wiredata_fido2.h"
+#include "dummy.h"
+
+#include "../openbsd-compat/openbsd-compat.h"
+
+#define MAXRPID 64
+
+struct param {
+ char pin1[MAXSTR];
+ char pin2[MAXSTR];
+ struct blob reset_wire_data;
+ struct blob info_wire_data;
+ struct blob set_pin_wire_data;
+ struct blob change_pin_wire_data;
+ struct blob retry_wire_data;
+ struct blob config_wire_data;
+ int seed;
+};
+
+static const uint8_t dummy_reset_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_KEEPALIVE,
+ WIREDATA_CTAP_KEEPALIVE,
+ WIREDATA_CTAP_KEEPALIVE,
+ WIREDATA_CTAP_CBOR_STATUS,
+};
+
+static const uint8_t dummy_info_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_INFO,
+};
+
+static const uint8_t dummy_set_pin_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_STATUS,
+};
+
+static const uint8_t dummy_change_pin_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_AUTHKEY,
+ WIREDATA_CTAP_CBOR_STATUS,
+};
+
+static const uint8_t dummy_retry_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_RETRIES,
+};
+
+static const uint8_t dummy_config_wire_data[] = {
+ WIREDATA_CTAP_INIT,
+ WIREDATA_CTAP_CBOR_INFO,
+ WIREDATA_CTAP_CBOR_STATUS,
+};
+
+struct param *
+unpack(const uint8_t *ptr, size_t len)
+{
+ cbor_item_t *item = NULL, **v;
+ struct cbor_load_result cbor;
+ struct param *p;
+ int ok = -1;
+
+ if ((p = calloc(1, sizeof(*p))) == NULL ||
+ (item = cbor_load(ptr, len, &cbor)) == NULL ||
+ cbor.read != len ||
+ cbor_isa_array(item) == false ||
+ cbor_array_is_definite(item) == false ||
+ cbor_array_size(item) != 9 ||
+ (v = cbor_array_handle(item)) == NULL)
+ goto fail;
+
+ if (unpack_int(v[0], &p->seed) < 0 ||
+ unpack_string(v[1], p->pin1) < 0 ||
+ unpack_string(v[2], p->pin2) < 0 ||
+ unpack_blob(v[3], &p->reset_wire_data) < 0 ||
+ unpack_blob(v[4], &p->info_wire_data) < 0 ||
+ unpack_blob(v[5], &p->set_pin_wire_data) < 0 ||
+ unpack_blob(v[6], &p->change_pin_wire_data) < 0 ||
+ unpack_blob(v[7], &p->retry_wire_data) < 0 ||
+ unpack_blob(v[8], &p->config_wire_data) < 0)
+ goto fail;
+
+ ok = 0;
+fail:
+ if (ok < 0) {
+ free(p);
+ p = NULL;
+ }
+
+ if (item)
+ cbor_decref(&item);
+
+ return p;
+}
+
+size_t
+pack(uint8_t *ptr, size_t len, const struct param *p)
+{
+ cbor_item_t *argv[9], *array = NULL;
+ size_t cbor_alloc_len, cbor_len = 0;
+ unsigned char *cbor = NULL;
+
+ memset(argv, 0, sizeof(argv));
+
+ if ((array = cbor_new_definite_array(9)) == NULL ||
+ (argv[0] = pack_int(p->seed)) == NULL ||
+ (argv[1] = pack_string(p->pin1)) == NULL ||
+ (argv[2] = pack_string(p->pin2)) == NULL ||
+ (argv[3] = pack_blob(&p->reset_wire_data)) == NULL ||
+ (argv[4] = pack_blob(&p->info_wire_data)) == NULL ||
+ (argv[5] = pack_blob(&p->set_pin_wire_data)) == NULL ||
+ (argv[6] = pack_blob(&p->change_pin_wire_data)) == NULL ||
+ (argv[7] = pack_blob(&p->retry_wire_data)) == NULL ||
+ (argv[8] = pack_blob(&p->config_wire_data)) == NULL)
+ goto fail;
+
+ for (size_t i = 0; i < 9; i++)
+ if (cbor_array_push(array, argv[i]) == false)
+ goto fail;
+
+ if ((cbor_len = cbor_serialize_alloc(array, &cbor,
+ &cbor_alloc_len)) == 0 || cbor_len > len) {
+ cbor_len = 0;
+ goto fail;
+ }
+
+ memcpy(ptr, cbor, cbor_len);
+fail:
+ for (size_t i = 0; i < 9; i++)
+ if (argv[i])
+ cbor_decref(&argv[i]);
+
+ if (array)
+ cbor_decref(&array);
+
+ free(cbor);
+
+ return cbor_len;
+}
+
+size_t
+pack_dummy(uint8_t *ptr, size_t len)
+{
+ struct param dummy;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&dummy, 0, sizeof(dummy));
+
+ strlcpy(dummy.pin1, dummy_pin1, sizeof(dummy.pin1));
+ strlcpy(dummy.pin2, dummy_pin2, sizeof(dummy.pin2));
+
+ dummy.reset_wire_data.len = sizeof(dummy_reset_wire_data);
+ dummy.info_wire_data.len = sizeof(dummy_info_wire_data);
+ dummy.set_pin_wire_data.len = sizeof(dummy_set_pin_wire_data);
+ dummy.change_pin_wire_data.len = sizeof(dummy_change_pin_wire_data);
+ dummy.retry_wire_data.len = sizeof(dummy_retry_wire_data);
+ dummy.config_wire_data.len = sizeof(dummy_config_wire_data);
+
+ memcpy(&dummy.reset_wire_data.body, &dummy_reset_wire_data,
+ dummy.reset_wire_data.len);
+ memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data,
+ dummy.info_wire_data.len);
+ memcpy(&dummy.set_pin_wire_data.body, &dummy_set_pin_wire_data,
+ dummy.set_pin_wire_data.len);
+ memcpy(&dummy.change_pin_wire_data.body, &dummy_change_pin_wire_data,
+ dummy.change_pin_wire_data.len);
+ memcpy(&dummy.retry_wire_data.body, &dummy_retry_wire_data,
+ dummy.retry_wire_data.len);
+ memcpy(&dummy.config_wire_data.body, &dummy_config_wire_data,
+ dummy.config_wire_data.len);
+
+ assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
+
+ if (blob_len > len) {
+ memcpy(ptr, blob, len);
+ return len;
+ }
+
+ memcpy(ptr, blob, blob_len);
+
+ return blob_len;
+}
+
+static void
+dev_reset(const struct param *p)
+{
+ fido_dev_t *dev;
+
+ set_wire_data(p->reset_wire_data.body, p->reset_wire_data.len);
+
+ if ((dev = open_dev(0)) == NULL)
+ return;
+
+ fido_dev_reset(dev);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+dev_get_cbor_info(const struct param *p)
+{
+ fido_dev_t *dev;
+ fido_cbor_info_t *ci;
+ uint64_t n;
+ uint8_t proto, major, minor, build, flags;
+ bool v;
+
+ set_wire_data(p->info_wire_data.body, p->info_wire_data.len);
+
+ if ((dev = open_dev(0)) == NULL)
+ return;
+
+ proto = fido_dev_protocol(dev);
+ major = fido_dev_major(dev);
+ minor = fido_dev_minor(dev);
+ build = fido_dev_build(dev);
+ flags = fido_dev_flags(dev);
+
+ consume(&proto, sizeof(proto));
+ consume(&major, sizeof(major));
+ consume(&minor, sizeof(minor));
+ consume(&build, sizeof(build));
+ consume(&flags, sizeof(flags));
+
+ if ((ci = fido_cbor_info_new()) == NULL)
+ goto out;
+
+ fido_dev_get_cbor_info(dev, ci);
+
+ for (size_t i = 0; i < fido_cbor_info_versions_len(ci); i++) {
+ char * const *sa = fido_cbor_info_versions_ptr(ci);
+ consume(sa[i], strlen(sa[i]));
+ }
+
+ for (size_t i = 0; i < fido_cbor_info_extensions_len(ci); i++) {
+ char * const *sa = fido_cbor_info_extensions_ptr(ci);
+ consume(sa[i], strlen(sa[i]));
+ }
+
+ for (size_t i = 0; i < fido_cbor_info_transports_len(ci); i++) {
+ char * const *sa = fido_cbor_info_transports_ptr(ci);
+ consume(sa[i], strlen(sa[i]));
+ }
+
+ for (size_t i = 0; i < fido_cbor_info_options_len(ci); i++) {
+ char * const *sa = fido_cbor_info_options_name_ptr(ci);
+ const bool *va = fido_cbor_info_options_value_ptr(ci);
+ consume(sa[i], strlen(sa[i]));
+ consume(&va[i], sizeof(va[i]));
+ }
+
+ /* +1 on purpose */
+ for (size_t i = 0; i <= fido_cbor_info_algorithm_count(ci); i++) {
+ const char *type = fido_cbor_info_algorithm_type(ci, i);
+ int cose = fido_cbor_info_algorithm_cose(ci, i);
+ consume_str(type);
+ consume(&cose, sizeof(cose));
+ }
+
+ for (size_t i = 0; i < fido_cbor_info_certs_len(ci); i++) {
+ char * const *na = fido_cbor_info_certs_name_ptr(ci);
+ const uint64_t *va = fido_cbor_info_certs_value_ptr(ci);
+ consume(na[i], strlen(na[i]));
+ consume(&va[i], sizeof(va[i]));
+ }
+
+ n = fido_cbor_info_maxmsgsiz(ci);
+ consume(&n, sizeof(n));
+ n = fido_cbor_info_maxcredbloblen(ci);
+ consume(&n, sizeof(n));
+ n = fido_cbor_info_maxcredcntlst(ci);
+ consume(&n, sizeof(n));
+ n = fido_cbor_info_maxcredidlen(ci);
+ consume(&n, sizeof(n));
+ n = fido_cbor_info_maxlargeblob(ci);
+ consume(&n, sizeof(n));
+ n = fido_cbor_info_fwversion(ci);
+ consume(&n, sizeof(n));
+ n = fido_cbor_info_minpinlen(ci);
+ consume(&n, sizeof(n));
+ n = fido_cbor_info_maxrpid_minpinlen(ci);
+ consume(&n, sizeof(n));
+ n = fido_cbor_info_uv_attempts(ci);
+ consume(&n, sizeof(n));
+ n = fido_cbor_info_uv_modality(ci);
+ consume(&n, sizeof(n));
+ n = (uint64_t)fido_cbor_info_rk_remaining(ci);
+ consume(&n, sizeof(n));
+
+ consume(fido_cbor_info_aaguid_ptr(ci), fido_cbor_info_aaguid_len(ci));
+ consume(fido_cbor_info_protocols_ptr(ci),
+ fido_cbor_info_protocols_len(ci));
+
+ v = fido_cbor_info_new_pin_required(ci);
+ consume(&v, sizeof(v));
+
+out:
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+
+ fido_cbor_info_free(&ci);
+}
+
+static void
+dev_set_pin(const struct param *p)
+{
+ fido_dev_t *dev;
+
+ set_wire_data(p->set_pin_wire_data.body, p->set_pin_wire_data.len);
+
+ if ((dev = open_dev(0)) == NULL)
+ return;
+
+ fido_dev_set_pin(dev, p->pin1, NULL);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+dev_change_pin(const struct param *p)
+{
+ fido_dev_t *dev;
+
+ set_wire_data(p->change_pin_wire_data.body, p->change_pin_wire_data.len);
+
+ if ((dev = open_dev(0)) == NULL)
+ return;
+
+ fido_dev_set_pin(dev, p->pin2, p->pin1);
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+dev_get_retry_count(const struct param *p)
+{
+ fido_dev_t *dev;
+ int n = 0;
+
+ set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len);
+
+ if ((dev = open_dev(0)) == NULL)
+ return;
+
+ fido_dev_get_retry_count(dev, &n);
+ consume(&n, sizeof(n));
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+dev_get_uv_retry_count(const struct param *p)
+{
+ fido_dev_t *dev;
+ int n = 0;
+
+ set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len);
+
+ if ((dev = open_dev(0)) == NULL)
+ return;
+
+ fido_dev_get_uv_retry_count(dev, &n);
+ consume(&n, sizeof(n));
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+dev_enable_entattest(const struct param *p)
+{
+ fido_dev_t *dev;
+ const char *pin;
+ int r;
+
+ set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
+ if ((dev = open_dev(0)) == NULL)
+ return;
+ pin = p->pin1;
+ if (strlen(pin) == 0)
+ pin = NULL;
+ r = fido_dev_enable_entattest(dev, pin);
+ consume_str(fido_strerr(r));
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+dev_toggle_always_uv(const struct param *p)
+{
+ fido_dev_t *dev;
+ const char *pin;
+ int r;
+
+ set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
+ if ((dev = open_dev(0)) == NULL)
+ return;
+ pin = p->pin1;
+ if (strlen(pin) == 0)
+ pin = NULL;
+ r = fido_dev_toggle_always_uv(dev, pin);
+ consume_str(fido_strerr(r));
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+dev_force_pin_change(const struct param *p)
+{
+ fido_dev_t *dev;
+ const char *pin;
+ int r;
+
+ set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
+ if ((dev = open_dev(0)) == NULL)
+ return;
+ pin = p->pin1;
+ if (strlen(pin) == 0)
+ pin = NULL;
+ r = fido_dev_force_pin_change(dev, pin);
+ consume_str(fido_strerr(r));
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+dev_set_pin_minlen(const struct param *p)
+{
+ fido_dev_t *dev;
+ const char *pin;
+ int r;
+
+ set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
+ if ((dev = open_dev(0)) == NULL)
+ return;
+ pin = p->pin1;
+ if (strlen(pin) == 0)
+ pin = NULL;
+ r = fido_dev_set_pin_minlen(dev, strlen(p->pin2), pin);
+ consume_str(fido_strerr(r));
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+static void
+dev_set_pin_minlen_rpid(const struct param *p)
+{
+ fido_dev_t *dev;
+ const char *rpid[MAXRPID];
+ const char *pin;
+ size_t n;
+ int r;
+
+ set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
+ if ((dev = open_dev(0)) == NULL)
+ return;
+ n = uniform_random(MAXRPID);
+ for (size_t i = 0; i < n; i++)
+ rpid[i] = dummy_rp_id;
+ pin = p->pin1;
+ if (strlen(pin) == 0)
+ pin = NULL;
+ r = fido_dev_set_pin_minlen_rpid(dev, rpid, n, pin);
+ consume_str(fido_strerr(r));
+ fido_dev_close(dev);
+ fido_dev_free(&dev);
+}
+
+void
+test(const struct param *p)
+{
+ prng_init((unsigned int)p->seed);
+ fuzz_clock_reset();
+ fido_init(FIDO_DEBUG);
+ fido_set_log_handler(consume_str);
+
+ dev_reset(p);
+ dev_get_cbor_info(p);
+ dev_set_pin(p);
+ dev_change_pin(p);
+ dev_get_retry_count(p);
+ dev_get_uv_retry_count(p);
+ dev_enable_entattest(p);
+ dev_toggle_always_uv(p);
+ dev_force_pin_change(p);
+ dev_set_pin_minlen(p);
+ dev_set_pin_minlen_rpid(p);
+}
+
+void
+mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
+{
+ if (flags & MUTATE_SEED)
+ p->seed = (int)seed;
+
+ if (flags & MUTATE_PARAM) {
+ mutate_string(p->pin1);
+ mutate_string(p->pin2);
+ }
+
+ if (flags & MUTATE_WIREDATA) {
+ mutate_blob(&p->reset_wire_data);
+ mutate_blob(&p->info_wire_data);
+ mutate_blob(&p->set_pin_wire_data);
+ mutate_blob(&p->change_pin_wire_data);
+ mutate_blob(&p->retry_wire_data);
+ }
+}
diff --git a/fuzz/fuzz_netlink.c b/fuzz/fuzz_netlink.c
new file mode 100644
index 0000000..4d28129
--- /dev/null
+++ b/fuzz/fuzz_netlink.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2020 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 <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../openbsd-compat/openbsd-compat.h"
+#include "mutator_aux.h"
+#include "dummy.h"
+
+struct param {
+ int seed;
+ int dev;
+ struct blob wiredata;
+};
+
+struct param *
+unpack(const uint8_t *ptr, size_t len)
+{
+ cbor_item_t *item = NULL, **v;
+ struct cbor_load_result cbor;
+ struct param *p;
+ int ok = -1;
+
+ if ((p = calloc(1, sizeof(*p))) == NULL ||
+ (item = cbor_load(ptr, len, &cbor)) == NULL ||
+ cbor.read != len ||
+ cbor_isa_array(item) == false ||
+ cbor_array_is_definite(item) == false ||
+ cbor_array_size(item) != 3 ||
+ (v = cbor_array_handle(item)) == NULL)
+ goto fail;
+
+ if (unpack_int(v[0], &p->seed) < 0 ||
+ unpack_int(v[1], &p->dev) < 0 ||
+ unpack_blob(v[2], &p->wiredata) < 0)
+ goto fail;
+
+ ok = 0;
+fail:
+ if (ok < 0) {
+ free(p);
+ p = NULL;
+ }
+
+ if (item)
+ cbor_decref(&item);
+
+ return p;
+}
+
+size_t
+pack(uint8_t *ptr, size_t len, const struct param *p)
+{
+ cbor_item_t *argv[3], *array = NULL;
+ size_t cbor_alloc_len, cbor_len = 0;
+ unsigned char *cbor = NULL;
+
+ memset(argv, 0, sizeof(argv));
+
+ if ((array = cbor_new_definite_array(3)) == NULL ||
+ (argv[0] = pack_int(p->seed)) == NULL ||
+ (argv[1] = pack_int(p->dev)) == NULL ||
+ (argv[2] = pack_blob(&p->wiredata)) == NULL)
+ goto fail;
+
+ for (size_t i = 0; i < 3; i++)
+ if (cbor_array_push(array, argv[i]) == false)
+ goto fail;
+
+ if ((cbor_len = cbor_serialize_alloc(array, &cbor,
+ &cbor_alloc_len)) == 0 || cbor_len > len) {
+ cbor_len = 0;
+ goto fail;
+ }
+
+ memcpy(ptr, cbor, cbor_len);
+fail:
+ for (size_t i = 0; i < 3; i++)
+ if (argv[i])
+ cbor_decref(&argv[i]);
+
+ if (array)
+ cbor_decref(&array);
+
+ free(cbor);
+
+ return cbor_len;
+}
+
+size_t
+pack_dummy(uint8_t *ptr, size_t len)
+{
+ struct param dummy;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&dummy, 0, sizeof(dummy));
+
+ dummy.wiredata.len = sizeof(dummy_netlink_wiredata);
+ memcpy(&dummy.wiredata.body, &dummy_netlink_wiredata,
+ dummy.wiredata.len);
+
+ assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
+
+ if (blob_len > len) {
+ memcpy(ptr, blob, len);
+ return len;
+ }
+
+ memcpy(ptr, blob, blob_len);
+
+ return blob_len;
+}
+
+void
+test(const struct param *p)
+{
+ fido_nl_t *nl;
+ uint32_t target;
+
+ prng_init((unsigned int)p->seed);
+ fuzz_clock_reset();
+ fido_init(FIDO_DEBUG);
+ fido_set_log_handler(consume_str);
+
+ set_netlink_io_functions(fd_read, fd_write);
+ set_wire_data(p->wiredata.body, p->wiredata.len);
+
+ if ((nl = fido_nl_new()) == NULL)
+ return;
+
+ consume(&nl->fd, sizeof(nl->fd));
+ consume(&nl->nfc_type, sizeof(nl->nfc_type));
+ consume(&nl->nfc_mcastgrp, sizeof(nl->nfc_mcastgrp));
+ consume(&nl->saddr, sizeof(nl->saddr));
+
+ fido_nl_power_nfc(nl, (uint32_t)p->dev);
+
+ if (fido_nl_get_nfc_target(nl, (uint32_t)p->dev, &target) == 0)
+ consume(&target, sizeof(target));
+
+ fido_nl_free(&nl);
+}
+
+void
+mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
+{
+ if (flags & MUTATE_SEED)
+ p->seed = (int)seed;
+
+ if (flags & MUTATE_PARAM)
+ mutate_int(&p->dev);
+
+ if (flags & MUTATE_WIREDATA)
+ mutate_blob(&p->wiredata);
+}
diff --git a/fuzz/fuzz_pcsc.c b/fuzz/fuzz_pcsc.c
new file mode 100644
index 0000000..cf6210b
--- /dev/null
+++ b/fuzz/fuzz_pcsc.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 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
+ */
+
+#define _FIDO_INTERNAL
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <winscard.h>
+
+#include "mutator_aux.h"
+#include "wiredata_fido2.h"
+#include "dummy.h"
+
+#include "../src/extern.h"
+
+struct param {
+ int seed;
+ char path[MAXSTR];
+ struct blob pcsc_list;
+ struct blob tx_apdu;
+ struct blob wiredata_init;
+ struct blob wiredata_msg;
+};
+
+static const uint8_t dummy_tx_apdu[] = { WIREDATA_CTAP_EXTENDED_APDU };
+static const uint8_t dummy_wiredata_init[] = { WIREDATA_CTAP_NFC_INIT };
+static const uint8_t dummy_wiredata_msg[] = { WIREDATA_CTAP_NFC_MSG };
+
+struct param *
+unpack(const uint8_t *ptr, size_t len)
+{
+ cbor_item_t *item = NULL, **v;
+ struct cbor_load_result cbor;
+ struct param *p;
+ int ok = -1;
+
+ if ((p = calloc(1, sizeof(*p))) == NULL ||
+ (item = cbor_load(ptr, len, &cbor)) == NULL ||
+ cbor.read != len ||
+ cbor_isa_array(item) == false ||
+ cbor_array_is_definite(item) == false ||
+ cbor_array_size(item) != 6 ||
+ (v = cbor_array_handle(item)) == NULL)
+ goto fail;
+
+ if (unpack_int(v[0], &p->seed) < 0 ||
+ unpack_string(v[1], p->path) < 0 ||
+ unpack_blob(v[2], &p->pcsc_list) < 0 ||
+ unpack_blob(v[3], &p->tx_apdu) < 0 ||
+ unpack_blob(v[4], &p->wiredata_init) < 0 ||
+ unpack_blob(v[5], &p->wiredata_msg) < 0)
+ goto fail;
+
+ ok = 0;
+fail:
+ if (ok < 0) {
+ free(p);
+ p = NULL;
+ }
+
+ if (item)
+ cbor_decref(&item);
+
+ return p;
+}
+
+size_t
+pack(uint8_t *ptr, size_t len, const struct param *p)
+{
+ cbor_item_t *argv[6], *array = NULL;
+ size_t cbor_alloc_len, cbor_len = 0;
+ unsigned char *cbor = NULL;
+
+ memset(argv, 0, sizeof(argv));
+
+ if ((array = cbor_new_definite_array(6)) == NULL ||
+ (argv[0] = pack_int(p->seed)) == NULL ||
+ (argv[1] = pack_string(p->path)) == NULL ||
+ (argv[2] = pack_blob(&p->pcsc_list)) == NULL ||
+ (argv[3] = pack_blob(&p->tx_apdu)) == NULL ||
+ (argv[4] = pack_blob(&p->wiredata_init)) == NULL ||
+ (argv[5] = pack_blob(&p->wiredata_msg)) == NULL)
+ goto fail;
+
+ for (size_t i = 0; i < 6; i++)
+ if (cbor_array_push(array, argv[i]) == false)
+ goto fail;
+
+ if ((cbor_len = cbor_serialize_alloc(array, &cbor,
+ &cbor_alloc_len)) == 0 || cbor_len > len) {
+ cbor_len = 0;
+ goto fail;
+ }
+
+ memcpy(ptr, cbor, cbor_len);
+fail:
+ for (size_t i = 0; i < 6; i++)
+ if (argv[i])
+ cbor_decref(&argv[i]);
+
+ if (array)
+ cbor_decref(&array);
+
+ free(cbor);
+
+ return cbor_len;
+}
+
+size_t
+pack_dummy(uint8_t *ptr, size_t len)
+{
+ struct param dummy;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&dummy, 0, sizeof(dummy));
+
+ strlcpy(dummy.path, dummy_pcsc_path, sizeof(dummy.path));
+
+ dummy.pcsc_list.len = sizeof(dummy_pcsc_list);
+ memcpy(&dummy.pcsc_list.body, &dummy_pcsc_list, dummy.pcsc_list.len);
+
+ dummy.tx_apdu.len = sizeof(dummy_tx_apdu);
+ memcpy(&dummy.tx_apdu.body, &dummy_tx_apdu, dummy.tx_apdu.len);
+
+ dummy.wiredata_init.len = sizeof(dummy_wiredata_init);
+ memcpy(&dummy.wiredata_init.body, &dummy_wiredata_init,
+ dummy.wiredata_init.len);
+
+ dummy.wiredata_msg.len = sizeof(dummy_wiredata_msg);
+ memcpy(&dummy.wiredata_msg.body, &dummy_wiredata_msg,
+ dummy.wiredata_msg.len);
+
+ assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
+
+ if (blob_len > len) {
+ memcpy(ptr, blob, len);
+ return len;
+ }
+
+ memcpy(ptr, blob, blob_len);
+
+ return blob_len;
+}
+
+static void
+test_manifest(void)
+{
+ size_t ndevs, nfound;
+ fido_dev_info_t *devlist = NULL;
+ int16_t vendor_id, product_id;
+ int r;
+
+ r = fido_pcsc_manifest(NULL, 0, &nfound);
+ assert(r == FIDO_OK && nfound == 0);
+ r = fido_pcsc_manifest(NULL, 1, &nfound);
+ assert(r == FIDO_ERR_INVALID_ARGUMENT);
+
+ ndevs = uniform_random(64);
+ if ((devlist = fido_dev_info_new(ndevs)) == NULL ||
+ fido_pcsc_manifest(devlist, ndevs, &nfound) != FIDO_OK)
+ goto out;
+
+ for (size_t i = 0; i < nfound; i++) {
+ const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
+ consume_str(fido_dev_info_path(di));
+ consume_str(fido_dev_info_manufacturer_string(di));
+ consume_str(fido_dev_info_product_string(di));
+ vendor_id = fido_dev_info_vendor(di);
+ product_id = fido_dev_info_product(di);
+ consume(&vendor_id, sizeof(vendor_id));
+ consume(&product_id, sizeof(product_id));
+ }
+
+out:
+ fido_dev_info_free(&devlist, ndevs);
+}
+
+static void
+test_tx(const char *path, const struct blob *apdu, uint8_t cmd, u_char *rx_buf,
+ size_t rx_len)
+{
+ fido_dev_t dev;
+ const u_char *tx_ptr = NULL;
+ size_t tx_len = 0;
+ int n;
+
+ memset(&dev, 0, sizeof(dev));
+
+ if (fido_dev_set_pcsc(&dev) < 0)
+ return;
+ if ((dev.io_handle = fido_pcsc_open(path)) == NULL)
+ return;
+
+ if (apdu) {
+ tx_ptr = apdu->body;
+ tx_len = apdu->len;
+ }
+
+ fido_pcsc_tx(&dev, cmd, tx_ptr, tx_len);
+
+ if ((n = fido_pcsc_rx(&dev, cmd, rx_buf, rx_len, -1)) >= 0)
+ consume(rx_buf, n);
+
+ fido_pcsc_close(dev.io_handle);
+}
+
+static void
+test_misc(void)
+{
+ assert(fido_pcsc_open(NULL) == NULL);
+ assert(fido_pcsc_write(NULL, NULL, INT_MAX + 1LL) == -1);
+}
+
+void
+test(const struct param *p)
+{
+ u_char buf[512];
+
+ prng_init((unsigned int)p->seed);
+ fuzz_clock_reset();
+ fido_init(FIDO_DEBUG);
+ fido_set_log_handler(consume_str);
+
+ set_pcsc_parameters(&p->pcsc_list);
+ set_pcsc_io_functions(nfc_read, nfc_write, consume);
+
+ set_wire_data(p->wiredata_init.body, p->wiredata_init.len);
+ test_manifest();
+
+ test_misc();
+
+ set_wire_data(p->wiredata_init.body, p->wiredata_init.len);
+ test_tx(p->path, NULL, CTAP_CMD_INIT, buf, uniform_random(20));
+
+ set_wire_data(p->wiredata_msg.body, p->wiredata_msg.len);
+ test_tx(p->path, &p->tx_apdu, CTAP_CMD_MSG, buf, sizeof(buf));
+
+ set_wire_data(p->wiredata_msg.body, p->wiredata_msg.len);
+ test_tx(p->path, &p->tx_apdu, CTAP_CMD_CBOR, buf, sizeof(buf));
+
+ set_wire_data(p->wiredata_msg.body, p->wiredata_msg.len);
+ test_tx(p->path, &p->tx_apdu, CTAP_CMD_LOCK, buf, sizeof(buf));
+}
+
+void
+mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
+{
+ if (flags & MUTATE_SEED)
+ p->seed = (int)seed;
+
+ if (flags & MUTATE_PARAM) {
+ mutate_string(p->path);
+ mutate_blob(&p->pcsc_list);
+ mutate_blob(&p->tx_apdu);
+ }
+
+ if (flags & MUTATE_WIREDATA) {
+ mutate_blob(&p->wiredata_init);
+ mutate_blob(&p->wiredata_msg);
+ }
+}
diff --git a/fuzz/libfuzzer.c b/fuzz/libfuzzer.c
new file mode 100644
index 0000000..073ebe6
--- /dev/null
+++ b/fuzz/libfuzzer.c
@@ -0,0 +1,230 @@
+/*
+ * 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>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mutator_aux.h"
+
+extern int fuzz_save_corpus;
+
+static bool debug;
+static unsigned int flags = MUTATE_ALL;
+static unsigned long long test_fail;
+static unsigned long long test_total;
+static unsigned long long mutate_fail;
+static unsigned long long mutate_total;
+
+int LLVMFuzzerInitialize(int *, char ***);
+int LLVMFuzzerTestOneInput(const uint8_t *, size_t);
+size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int);
+
+static int
+save_seed(const char *opt)
+{
+ const char *path;
+ int fd = -1, status = 1;
+ void *buf = NULL;
+ const size_t buflen = MAXCORPUS;
+ size_t n;
+ struct param *p = NULL;
+
+ if ((path = strchr(opt, '=')) == NULL || strlen(++path) == 0) {
+ warnx("usage: --fido-save-seed=<path>");
+ goto fail;
+ }
+
+ if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, 0644)) == -1) {
+ warn("open %s", path);
+ goto fail;
+ }
+
+ if ((buf = malloc(buflen)) == NULL) {
+ warn("malloc");
+ goto fail;
+ }
+
+ n = pack_dummy(buf, buflen);
+
+ if ((p = unpack(buf, n)) == NULL) {
+ warnx("unpack");
+ goto fail;
+ }
+
+ if (write(fd, buf, n) != (ssize_t)n) {
+ warn("write %s", path);
+ goto fail;
+ }
+
+ status = 0;
+fail:
+ if (fd != -1)
+ close(fd);
+ free(buf);
+ free(p);
+
+ 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)
+{
+ const char *f;
+
+ if ((f = strchr(opt, '=')) == NULL || strlen(++f) == 0)
+ errx(1, "usage: --fido-mutate=<flag>");
+
+ if (strcmp(f, "seed") == 0)
+ *mutate_flags |= MUTATE_SEED;
+ else if (strcmp(f, "param") == 0)
+ *mutate_flags |= MUTATE_PARAM;
+ else if (strcmp(f, "wiredata") == 0)
+ *mutate_flags |= MUTATE_WIREDATA;
+ else
+ errx(1, "--fido-mutate: unknown flag '%s'", f);
+}
+
+int
+LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ unsigned int mutate_flags = 0;
+
+ for (int i = 0; i < *argc; i++)
+ if (strcmp((*argv)[i], "--fido-debug") == 0) {
+ debug = 1;
+ } else if (strncmp((*argv)[i], "--fido-save-seed=", 17) == 0) {
+ exit(save_seed((*argv)[i]));
+ } else if (strncmp((*argv)[i], "--fido-mutate=", 14) == 0) {
+ parse_mutate_flags((*argv)[i], &mutate_flags);
+ }
+
+ if (mutate_flags)
+ flags = mutate_flags;
+
+ return 0;
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ struct param *p;
+
+ if (size > MAXCORPUS)
+ return 0;
+
+ if (++test_total % 100000 == 0 && debug) {
+ double r = (double)test_fail/(double)test_total * 100.0;
+ fprintf(stderr, "%s: %llu/%llu (%.2f%%)\n", __func__,
+ test_fail, test_total, r);
+ }
+
+ 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);
+ }
+
+ return 0;
+}
+
+size_t
+LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize,
+ unsigned int seed) NO_MSAN
+{
+ struct param *p;
+ uint8_t blob[MAXCORPUS];
+ size_t blob_len;
+
+ memset(&p, 0, sizeof(p));
+
+#ifdef WITH_MSAN
+ __msan_unpoison(data, maxsize);
+#endif
+
+ if (++mutate_total % 100000 == 0 && debug) {
+ double r = (double)mutate_fail/(double)mutate_total * 100.0;
+ fprintf(stderr, "%s: %llu/%llu (%.2f%%)\n", __func__,
+ mutate_fail, mutate_total, r);
+ }
+
+ if ((p = unpack(data, size)) == NULL) {
+ mutate_fail++;
+ return pack_dummy(data, maxsize);
+ }
+
+ mutate(p, seed, flags);
+
+ if ((blob_len = pack(blob, sizeof(blob), p)) == 0 ||
+ blob_len > sizeof(blob) || blob_len > maxsize) {
+ mutate_fail++;
+ free(p);
+ return 0;
+ }
+
+ free(p);
+
+ memcpy(data, blob, blob_len);
+
+ return blob_len;
+}
diff --git a/fuzz/mutator_aux.c b/fuzz/mutator_aux.c
new file mode 100644
index 0000000..64c633f
--- /dev/null
+++ b/fuzz/mutator_aux.c
@@ -0,0 +1,332 @@
+/*
+ * 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 <assert.h>
+#include <cbor.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mutator_aux.h"
+
+int fido_nfc_rx(fido_dev_t *, uint8_t, unsigned char *, size_t, int);
+int fido_nfc_tx(fido_dev_t *, uint8_t, const unsigned char *, size_t);
+size_t LLVMFuzzerMutate(uint8_t *, size_t, size_t);
+
+extern int prng_up;
+static const uint8_t *wire_data_ptr = NULL;
+static size_t wire_data_len = 0;
+
+void
+consume(const void *body, size_t len)
+{
+ const volatile uint8_t *ptr = body;
+ volatile uint8_t x = 0;
+
+#ifdef WITH_MSAN
+ __msan_check_mem_is_initialized(body, len);
+#endif
+
+ while (len--)
+ x ^= *ptr++;
+
+ (void)x;
+}
+
+void
+consume_str(const char *str)
+{
+ if (str != NULL)
+ consume(str, strlen(str) + 1);
+}
+
+int
+unpack_int(cbor_item_t *item, int *v)
+{
+ if (cbor_is_int(item) == false ||
+ cbor_int_get_width(item) != CBOR_INT_64)
+ return -1;
+
+ if (cbor_isa_uint(item))
+ *v = (int)cbor_get_uint64(item);
+ else
+ *v = (int)(-cbor_get_uint64(item) - 1);
+
+ return 0;
+}
+
+int
+unpack_string(cbor_item_t *item, char *v)
+{
+ size_t len;
+
+ if (cbor_isa_bytestring(item) == false ||
+ (len = cbor_bytestring_length(item)) >= MAXSTR)
+ return -1;
+
+ memcpy(v, cbor_bytestring_handle(item), len);
+ v[len] = '\0';
+
+ return 0;
+}
+
+int
+unpack_byte(cbor_item_t *item, uint8_t *v)
+{
+ if (cbor_isa_uint(item) == false ||
+ cbor_int_get_width(item) != CBOR_INT_8)
+ return -1;
+
+ *v = cbor_get_uint8(item);
+
+ return 0;
+}
+
+int
+unpack_blob(cbor_item_t *item, struct blob *v)
+{
+ if (cbor_isa_bytestring(item) == false ||
+ (v->len = cbor_bytestring_length(item)) > sizeof(v->body))
+ return -1;
+
+ memcpy(v->body, cbor_bytestring_handle(item), v->len);
+
+ return 0;
+}
+
+cbor_item_t *
+pack_int(int v) NO_MSAN
+{
+ if (v < 0)
+ return cbor_build_negint64((uint64_t)(-(int64_t)v - 1));
+ else
+ return cbor_build_uint64((uint64_t)v);
+}
+
+cbor_item_t *
+pack_string(const char *v) NO_MSAN
+{
+ if (strlen(v) >= MAXSTR)
+ return NULL;
+
+ return cbor_build_bytestring((const unsigned char *)v, strlen(v));
+}
+
+cbor_item_t *
+pack_byte(uint8_t v) NO_MSAN
+{
+ return cbor_build_uint8(v);
+}
+
+cbor_item_t *
+pack_blob(const struct blob *v) NO_MSAN
+{
+ return cbor_build_bytestring(v->body, v->len);
+}
+
+void
+mutate_byte(uint8_t *b)
+{
+ LLVMFuzzerMutate(b, sizeof(*b), sizeof(*b));
+}
+
+void
+mutate_int(int *i)
+{
+ LLVMFuzzerMutate((uint8_t *)i, sizeof(*i), sizeof(*i));
+}
+
+void
+mutate_blob(struct blob *blob)
+{
+ blob->len = LLVMFuzzerMutate((uint8_t *)blob->body, blob->len,
+ sizeof(blob->body));
+}
+
+void
+mutate_string(char *s)
+{
+ size_t n;
+
+ n = LLVMFuzzerMutate((uint8_t *)s, strlen(s), MAXSTR - 1);
+ s[n] = '\0';
+}
+
+static int
+buf_read(unsigned char *ptr, size_t len, int ms)
+{
+ size_t n;
+
+ (void)ms;
+
+ if (prng_up && uniform_random(400) < 1) {
+ errno = EIO;
+ return -1;
+ }
+
+ if (wire_data_len < len)
+ n = wire_data_len;
+ else
+ n = len;
+
+ memcpy(ptr, wire_data_ptr, n);
+
+ wire_data_ptr += n;
+ wire_data_len -= n;
+
+ return (int)n;
+}
+
+static int
+buf_write(const unsigned char *ptr, size_t len)
+{
+ consume(ptr, len);
+
+ if (prng_up && uniform_random(400) < 1) {
+ errno = EIO;
+ return -1;
+ }
+
+ return (int)len;
+}
+
+static void *
+hid_open(const char *path)
+{
+ (void)path;
+
+ return (void *)HID_DEV_HANDLE;
+}
+
+static void
+hid_close(void *handle)
+{
+ assert(handle == (void *)HID_DEV_HANDLE);
+}
+
+static int
+hid_read(void *handle, unsigned char *ptr, size_t len, int ms)
+{
+ assert(handle == (void *)HID_DEV_HANDLE);
+ assert(len >= CTAP_MIN_REPORT_LEN && len <= CTAP_MAX_REPORT_LEN);
+
+ return buf_read(ptr, len, ms);
+}
+
+static int
+hid_write(void *handle, const unsigned char *ptr, size_t len)
+{
+ assert(handle == (void *)HID_DEV_HANDLE);
+ assert(len >= CTAP_MIN_REPORT_LEN + 1 &&
+ len <= CTAP_MAX_REPORT_LEN + 1);
+
+ return buf_write(ptr, len);
+}
+
+static void *
+nfc_open(const char *path)
+{
+ (void)path;
+
+ return (void *)NFC_DEV_HANDLE;
+}
+
+static void
+nfc_close(void *handle)
+{
+ assert(handle == (void *)NFC_DEV_HANDLE);
+}
+
+int
+nfc_read(void *handle, unsigned char *ptr, size_t len, int ms)
+{
+ assert(handle == (void *)NFC_DEV_HANDLE);
+ assert(len > 0 && len <= 264);
+
+ return buf_read(ptr, len, ms);
+}
+
+int
+nfc_write(void *handle, const unsigned char *ptr, size_t len)
+{
+ assert(handle == (void *)NFC_DEV_HANDLE);
+ assert(len > 0 && len <= 256 + 2);
+
+ return buf_write(ptr, len);
+}
+
+ssize_t
+fd_read(int fd, void *ptr, size_t len)
+{
+ assert(fd != -1);
+
+ return buf_read(ptr, len, -1);
+}
+
+ssize_t
+fd_write(int fd, const void *ptr, size_t len)
+{
+ assert(fd != -1);
+
+ return buf_write(ptr, len);
+}
+
+fido_dev_t *
+open_dev(int nfc)
+{
+ fido_dev_t *dev;
+ fido_dev_io_t io;
+ fido_dev_transport_t t;
+
+ memset(&io, 0, sizeof(io));
+ memset(&t, 0, sizeof(t));
+
+ if ((dev = fido_dev_new()) == NULL)
+ return NULL;
+
+ if (nfc) {
+ io.open = nfc_open;
+ io.close = nfc_close;
+ io.read = nfc_read;
+ io.write = nfc_write;
+ } else {
+ io.open = hid_open;
+ io.close = hid_close;
+ io.read = hid_read;
+ io.write = hid_write;
+ }
+
+ if (fido_dev_set_io_functions(dev, &io) != FIDO_OK)
+ goto fail;
+
+ if (nfc) {
+ t.rx = fido_nfc_rx;
+ t.tx = fido_nfc_tx;
+ if (fido_dev_set_transport_functions(dev, &t) != FIDO_OK)
+ goto fail;
+ }
+
+ if (fido_dev_set_timeout(dev, 300) != FIDO_OK ||
+ fido_dev_open(dev, "nodev") != FIDO_OK)
+ goto fail;
+
+ return dev;
+fail:
+ fido_dev_free(&dev);
+
+ return NULL;
+}
+
+void
+set_wire_data(const uint8_t *ptr, size_t len)
+{
+ wire_data_ptr = ptr;
+ wire_data_len = len;
+}
diff --git a/fuzz/mutator_aux.h b/fuzz/mutator_aux.h
new file mode 100644
index 0000000..5ad5661
--- /dev/null
+++ b/fuzz/mutator_aux.h
@@ -0,0 +1,111 @@
+/*
+ * 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
+ */
+
+#ifndef _MUTATOR_AUX_H
+#define _MUTATOR_AUX_H
+
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdint.h>
+#include <cbor.h>
+
+#include "../src/fido.h"
+#include "../src/fido/bio.h"
+#include "../src/fido/config.h"
+#include "../src/fido/credman.h"
+#include "../src/fido/eddsa.h"
+#include "../src/fido/es256.h"
+#include "../src/fido/es384.h"
+#include "../src/fido/rs256.h"
+#include "../src/netlink.h"
+
+/*
+ * As of LLVM 10.0.0, MSAN support in libFuzzer was still experimental.
+ * We therefore have to be careful when using our custom mutator, or
+ * MSAN will flag uninitialised reads on memory populated by libFuzzer.
+ * Since there is no way to suppress MSAN without regenerating object
+ * code (in which case you might as well rebuild libFuzzer with MSAN),
+ * we adjust our mutator to make it less accurate while allowing
+ * fuzzing to proceed.
+ */
+
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+# include <sanitizer/msan_interface.h>
+# define NO_MSAN __attribute__((no_sanitize("memory")))
+# define WITH_MSAN 1
+# endif
+#endif
+
+#if !defined(WITH_MSAN)
+# define NO_MSAN
+#endif
+
+#define MUTATE_SEED 0x01
+#define MUTATE_PARAM 0x02
+#define MUTATE_WIREDATA 0x04
+#define MUTATE_ALL (MUTATE_SEED | MUTATE_PARAM | MUTATE_WIREDATA)
+
+#define MAXSTR 1024
+#define MAXBLOB 3600
+#define MAXCORPUS 8192
+
+#define HID_DEV_HANDLE 0x68696421
+#define NFC_DEV_HANDLE 0x6e666321
+
+struct blob {
+ uint8_t body[MAXBLOB];
+ size_t len;
+};
+
+struct param;
+
+struct param *unpack(const uint8_t *, size_t);
+size_t pack(uint8_t *, size_t, const struct param *);
+size_t pack_dummy(uint8_t *, size_t);
+void mutate(struct param *, unsigned int, unsigned int);
+void test(const struct param *);
+
+void consume(const void *, size_t);
+void consume_str(const char *);
+
+int unpack_blob(cbor_item_t *, struct blob *);
+int unpack_byte(cbor_item_t *, uint8_t *);
+int unpack_int(cbor_item_t *, int *);
+int unpack_string(cbor_item_t *, char *);
+
+cbor_item_t *pack_blob(const struct blob *);
+cbor_item_t *pack_byte(uint8_t);
+cbor_item_t *pack_int(int);
+cbor_item_t *pack_string(const char *);
+
+void mutate_byte(uint8_t *);
+void mutate_int(int *);
+void mutate_blob(struct blob *);
+void mutate_string(char *);
+
+ssize_t fd_read(int, void *, size_t);
+ssize_t fd_write(int, const void *, size_t);
+
+int nfc_read(void *, unsigned char *, size_t, int);
+int nfc_write(void *, const unsigned char *, size_t);
+
+fido_dev_t *open_dev(int);
+void set_wire_data(const uint8_t *, size_t);
+
+void fuzz_clock_reset(void);
+void prng_init(unsigned long);
+unsigned long prng_uint32(void);
+
+uint32_t uniform_random(uint32_t);
+
+void set_pcsc_parameters(const struct blob *);
+void set_pcsc_io_functions(int (*)(void *, u_char *, size_t, int),
+ int (*)(void *, const u_char *, size_t), void (*)(const void *, size_t));
+
+#endif /* !_MUTATOR_AUX_H */
diff --git a/fuzz/pcsc.c b/fuzz/pcsc.c
new file mode 100644
index 0000000..f6a3e9b
--- /dev/null
+++ b/fuzz/pcsc.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 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 <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <winscard.h>
+
+#include "mutator_aux.h"
+
+static const struct blob *reader_list;
+static int (*xread)(void *, u_char *, size_t, int);
+static int (*xwrite)(void *, const u_char *, size_t);
+static void (*xconsume)(const void *, size_t);
+
+LONG __wrap_SCardEstablishContext(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
+LONG __wrap_SCardListReaders(SCARDCONTEXT, LPCSTR, LPSTR, LPDWORD);
+LONG __wrap_SCardReleaseContext(SCARDCONTEXT);
+LONG __wrap_SCardConnect(SCARDCONTEXT, LPCSTR, DWORD, DWORD, LPSCARDHANDLE,
+ LPDWORD);
+LONG __wrap_SCardDisconnect(SCARDHANDLE, DWORD);
+LONG __wrap_SCardTransmit(SCARDHANDLE, const SCARD_IO_REQUEST *, LPCBYTE,
+ DWORD, SCARD_IO_REQUEST *, LPBYTE, LPDWORD);
+
+LONG
+__wrap_SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
+ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
+{
+ assert(dwScope == SCARD_SCOPE_SYSTEM);
+ assert(pvReserved1 == NULL);
+ assert(pvReserved2 == NULL);
+
+ *phContext = 1;
+
+ if (uniform_random(400) < 1)
+ return SCARD_E_NO_SERVICE;
+ if (uniform_random(400) < 1)
+ return SCARD_E_NO_SMARTCARD;
+ if (uniform_random(400) < 1)
+ return SCARD_E_NO_MEMORY;
+ if (uniform_random(400) < 1)
+ *phContext = 0;
+
+ return SCARD_S_SUCCESS;
+}
+
+LONG
+__wrap_SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
+ LPSTR mszReaders, LPDWORD pcchReaders)
+{
+ assert(hContext == 1);
+ assert(mszGroups == NULL);
+ assert(mszReaders != NULL);
+ assert(pcchReaders != 0);
+
+ if (reader_list == NULL || uniform_random(400) < 1)
+ return SCARD_E_NO_READERS_AVAILABLE;
+ if (uniform_random(400) < 1)
+ return SCARD_E_NO_MEMORY;
+
+ memcpy(mszReaders, reader_list->body, reader_list->len > *pcchReaders ?
+ *pcchReaders : reader_list->len);
+ *pcchReaders = (DWORD)reader_list->len; /* on purpose */
+
+ return SCARD_S_SUCCESS;
+}
+
+LONG
+__wrap_SCardReleaseContext(SCARDCONTEXT hContext)
+{
+ assert(hContext == 1);
+
+ return SCARD_S_SUCCESS;
+}
+
+LONG
+__wrap_SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
+ DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
+{
+ uint32_t r;
+
+ assert(hContext == 1);
+ xconsume(szReader, strlen(szReader) + 1);
+ assert(dwShareMode == SCARD_SHARE_SHARED);
+ assert(dwPreferredProtocols == SCARD_PROTOCOL_ANY);
+ assert(phCard != NULL);
+ assert(pdwActiveProtocol != NULL);
+
+ if ((r = uniform_random(400)) < 1)
+ return SCARD_E_UNEXPECTED;
+
+ *phCard = 1;
+ *pdwActiveProtocol = (r & 1) ? SCARD_PROTOCOL_T0 : SCARD_PROTOCOL_T1;
+
+ if (uniform_random(400) < 1)
+ *pdwActiveProtocol = SCARD_PROTOCOL_RAW;
+
+ return SCARD_S_SUCCESS;
+}
+
+LONG
+__wrap_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
+{
+ assert(hCard == 1);
+ assert(dwDisposition == SCARD_LEAVE_CARD);
+
+ return SCARD_S_SUCCESS;
+}
+
+extern void consume(const void *body, size_t len);
+
+LONG
+__wrap_SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
+ LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci,
+ LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
+{
+ void *ioh = (void *)NFC_DEV_HANDLE;
+ int n;
+
+ assert(hCard == 1);
+ xconsume(pioSendPci, sizeof(*pioSendPci));
+ xwrite(ioh, pbSendBuffer, cbSendLength);
+ assert(pioRecvPci == NULL);
+
+ if (uniform_random(400) < 1 ||
+ (n = xread(ioh, pbRecvBuffer, *pcbRecvLength, -1)) == -1)
+ return SCARD_E_UNEXPECTED;
+ *pcbRecvLength = (DWORD)n;
+
+ return SCARD_S_SUCCESS;
+}
+
+void
+set_pcsc_parameters(const struct blob *reader_list_ptr)
+{
+ reader_list = reader_list_ptr;
+}
+
+void
+set_pcsc_io_functions(int (*read_f)(void *, u_char *, size_t, int),
+ int (*write_f)(void *, const u_char *, size_t),
+ void (*consume_f)(const void *, size_t))
+{
+ xread = read_f;
+ xwrite = write_f;
+ xconsume = consume_f;
+}
diff --git a/fuzz/preload-fuzz.c b/fuzz/preload-fuzz.c
new file mode 100644
index 0000000..f18848d
--- /dev/null
+++ b/fuzz/preload-fuzz.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2019 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
+ */
+
+/*
+ * cc -fPIC -D_GNU_SOURCE -shared -o preload-fuzz.so preload-fuzz.c
+ * LD_PRELOAD=$(realpath preload-fuzz.so)
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define FUZZ_DEV_PREFIX "nodev"
+
+static int fd_fuzz = -1;
+static int (*open_f)(const char *, int, mode_t);
+static int (*close_f)(int);
+static ssize_t (*write_f)(int, const void *, size_t);
+
+int
+open(const char *path, int flags, ...)
+{
+ va_list ap;
+ mode_t mode;
+
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ va_end(ap);
+
+ if (open_f == NULL) {
+ open_f = dlsym(RTLD_NEXT, "open");
+ if (open_f == NULL) {
+ warnx("%s: dlsym", __func__);
+ errno = EACCES;
+ return (-1);
+ }
+ }
+
+ if (strncmp(path, FUZZ_DEV_PREFIX, strlen(FUZZ_DEV_PREFIX)) != 0)
+ return (open_f(path, flags, mode));
+
+ if (fd_fuzz != -1) {
+ warnx("%s: fd_fuzz != -1", __func__);
+ errno = EACCES;
+ return (-1);
+ }
+
+ if ((fd_fuzz = dup(STDIN_FILENO)) < 0) {
+ warn("%s: dup", __func__);
+ errno = EACCES;
+ return (-1);
+ }
+
+ return (fd_fuzz);
+}
+
+int
+close(int fd)
+{
+ if (close_f == NULL) {
+ close_f = dlsym(RTLD_NEXT, "close");
+ if (close_f == NULL) {
+ warnx("%s: dlsym", __func__);
+ errno = EACCES;
+ return (-1);
+ }
+ }
+
+ if (fd == fd_fuzz)
+ fd_fuzz = -1;
+
+ return (close_f(fd));
+}
+
+ssize_t
+write(int fd, const void *buf, size_t nbytes)
+{
+ if (write_f == NULL) {
+ write_f = dlsym(RTLD_NEXT, "write");
+ if (write_f == NULL) {
+ warnx("%s: dlsym", __func__);
+ errno = EBADF;
+ return (-1);
+ }
+ }
+
+ if (fd != fd_fuzz)
+ return (write_f(fd, buf, nbytes));
+
+ return (nbytes);
+}
diff --git a/fuzz/preload-snoop.c b/fuzz/preload-snoop.c
new file mode 100644
index 0000000..34d57ad
--- /dev/null
+++ b/fuzz/preload-snoop.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2019 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
+ */
+
+/*
+ * cc -fPIC -D_GNU_SOURCE -shared -o preload-snoop.so preload-snoop.c
+ * LD_PRELOAD=$(realpath preload-snoop.so)
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define SNOOP_DEV_PREFIX "/dev/hidraw"
+
+struct fd_tuple {
+ int snoop_in;
+ int snoop_out;
+ int real_dev;
+};
+
+static struct fd_tuple *fd_tuple;
+static int (*open_f)(const char *, int, mode_t);
+static int (*close_f)(int);
+static ssize_t (*read_f)(int, void *, size_t);
+static ssize_t (*write_f)(int, const void *, size_t);
+
+static int
+get_fd(const char *hid_path, const char *suffix)
+{
+ char *s = NULL;
+ char path[PATH_MAX];
+ int fd;
+ int r;
+
+ if ((s = strdup(hid_path)) == NULL) {
+ warnx("%s: strdup", __func__);
+ return (-1);
+ }
+
+ for (size_t i = 0; i < strlen(s); i++)
+ if (s[i] == '/')
+ s[i] = '_';
+
+ if ((r = snprintf(path, sizeof(path), "%s-%s", s, suffix)) < 0 ||
+ (size_t)r >= sizeof(path)) {
+ warnx("%s: snprintf", __func__);
+ free(s);
+ return (-1);
+ }
+
+ free(s);
+ s = NULL;
+
+ if ((fd = open_f(path, O_CREAT | O_WRONLY, 0644)) < 0) {
+ warn("%s: open", __func__);
+ return (-1);
+ }
+
+ return (fd);
+}
+
+int
+open(const char *path, int flags, ...)
+{
+ va_list ap;
+ mode_t mode;
+
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ va_end(ap);
+
+ if (open_f == NULL) {
+ open_f = dlsym(RTLD_NEXT, "open");
+ if (open_f == NULL) {
+ warnx("%s: dlsym", __func__);
+ errno = EACCES;
+ return (-1);
+ }
+ }
+
+ if (strncmp(path, SNOOP_DEV_PREFIX, strlen(SNOOP_DEV_PREFIX)) != 0)
+ return (open_f(path, flags, mode));
+
+ if (fd_tuple != NULL) {
+ warnx("%s: fd_tuple != NULL", __func__);
+ errno = EACCES;
+ return (-1);
+ }
+
+ if ((fd_tuple = calloc(1, sizeof(*fd_tuple))) == NULL) {
+ warn("%s: calloc", __func__);
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ fd_tuple->snoop_in = -1;
+ fd_tuple->snoop_out = -1;
+ fd_tuple->real_dev = -1;
+
+ if ((fd_tuple->snoop_in = get_fd(path, "in")) < 0 ||
+ (fd_tuple->snoop_out = get_fd(path, "out")) < 0 ||
+ (fd_tuple->real_dev = open_f(path, flags, mode)) < 0) {
+ warn("%s: get_fd/open", __func__);
+ goto fail;
+ }
+
+ return (fd_tuple->real_dev);
+fail:
+ if (fd_tuple->snoop_in != -1)
+ close(fd_tuple->snoop_in);
+ if (fd_tuple->snoop_out != -1)
+ close(fd_tuple->snoop_out);
+ if (fd_tuple->real_dev != -1)
+ close(fd_tuple->real_dev);
+
+ free(fd_tuple);
+ fd_tuple = NULL;
+
+ errno = EACCES;
+
+ return (-1);
+}
+
+int
+close(int fd)
+{
+ if (close_f == NULL) {
+ close_f = dlsym(RTLD_NEXT, "close");
+ if (close_f == NULL) {
+ warnx("%s: dlsym", __func__);
+ errno = EBADF;
+ return (-1);
+ }
+ }
+
+ if (fd_tuple == NULL || fd_tuple->real_dev != fd)
+ return (close_f(fd));
+
+ close_f(fd_tuple->snoop_in);
+ close_f(fd_tuple->snoop_out);
+ close_f(fd_tuple->real_dev);
+
+ free(fd_tuple);
+ fd_tuple = NULL;
+
+ return (0);
+}
+
+ssize_t
+read(int fd, void *buf, size_t nbytes)
+{
+ ssize_t n;
+
+ if (read_f == NULL) {
+ read_f = dlsym(RTLD_NEXT, "read");
+ if (read_f == NULL) {
+ warnx("%s: dlsym", __func__);
+ errno = EBADF;
+ return (-1);
+ }
+ }
+
+ if (write_f == NULL) {
+ write_f = dlsym(RTLD_NEXT, "write");
+ if (write_f == NULL) {
+ warnx("%s: dlsym", __func__);
+ errno = EBADF;
+ return (-1);
+ }
+ }
+
+ if (fd_tuple == NULL || fd_tuple->real_dev != fd)
+ return (read_f(fd, buf, nbytes));
+
+ if ((n = read_f(fd, buf, nbytes)) < 0 ||
+ write_f(fd_tuple->snoop_in, buf, n) != n)
+ return (-1);
+
+ return (n);
+}
+
+ssize_t
+write(int fd, const void *buf, size_t nbytes)
+{
+ ssize_t n;
+
+ if (write_f == NULL) {
+ write_f = dlsym(RTLD_NEXT, "write");
+ if (write_f == NULL) {
+ warnx("%s: dlsym", __func__);
+ errno = EBADF;
+ return (-1);
+ }
+ }
+
+ if (fd_tuple == NULL || fd_tuple->real_dev != fd)
+ return (write_f(fd, buf, nbytes));
+
+ if ((n = write_f(fd, buf, nbytes)) < 0 ||
+ write_f(fd_tuple->snoop_out, buf, n) != n)
+ return (-1);
+
+ return (n);
+}
diff --git a/fuzz/prng.c b/fuzz/prng.c
new file mode 100644
index 0000000..61114ac
--- /dev/null
+++ b/fuzz/prng.c
@@ -0,0 +1,113 @@
+/*
+ A C-program for MT19937, with initialization improved 2002/1/26.
+ Coded by Takuji Nishimura and Makoto Matsumoto.
+
+ Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+ Any feedback is very welcome.
+ http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mutator_aux.h"
+
+#define init_genrand prng_init
+#define genrand_int32 prng_uint32
+
+/* Period parameters */
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0dfUL /* constant vector a */
+#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
+
+int prng_up = 0;
+static unsigned long mt[N]; /* the array for the state vector */
+static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
+
+/* initializes mt[N] with a seed */
+void init_genrand(unsigned long s)
+{
+ mt[0]= s & 0xffffffffUL;
+ for (mti=1; mti<N; mti++) {
+ mt[mti] =
+ (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) +
+ (unsigned long)mti);
+ /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+ /* In the previous versions, MSBs of the seed affect */
+ /* only MSBs of the array mt[]. */
+ /* 2002/01/09 modified by Makoto Matsumoto */
+ mt[mti] &= 0xffffffffUL;
+ /* for >32 bit machines */
+ }
+ prng_up = 1;
+}
+
+/* generates a random number on [0,0xffffffff]-interval */
+unsigned long genrand_int32(void)
+{
+ unsigned long y;
+ static unsigned long mag01[2]={0x0UL, MATRIX_A};
+ /* mag01[x] = x * MATRIX_A for x=0,1 */
+
+ if (mti >= N) { /* generate N words at one time */
+ int kk;
+
+ assert(mti != N+1);
+
+ for (kk=0;kk<N-M;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ for (;kk<N-1;kk++) {
+ y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+ mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+ }
+ y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+ mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+
+ mti = 0;
+ }
+
+ y = mt[mti++];
+
+ /* Tempering */
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9d2c5680UL;
+ y ^= (y << 15) & 0xefc60000UL;
+ y ^= (y >> 18);
+
+ return y;
+}
diff --git a/fuzz/report.tgz b/fuzz/report.tgz
new file mode 100644
index 0000000..9c01263
--- /dev/null
+++ b/fuzz/report.tgz
Binary files differ
diff --git a/fuzz/summary.txt b/fuzz/summary.txt
new file mode 100644
index 0000000..adda3ac
--- /dev/null
+++ b/fuzz/summary.txt
@@ -0,0 +1,64 @@
+Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+fuzz/clock.c 24 1 95.83% 4 0 100.00% 35 1 97.14%
+fuzz/pcsc.c 59 0 100.00% 8 0 100.00% 75 12 84.00%
+fuzz/prng.c 31 0 100.00% 2 0 100.00% 35 1 97.14%
+fuzz/udev.c 110 2 98.18% 17 0 100.00% 126 12 90.48%
+fuzz/uniform_random.c 7 1 85.71% 1 0 100.00% 12 1 91.67%
+fuzz/wrap.c 23 0 100.00% 3 0 100.00% 29 0 100.00%
+openbsd-compat/explicit_bzero.c 4 0 100.00% 1 0 100.00% 7 0 100.00%
+openbsd-compat/freezero.c 4 0 100.00% 1 0 100.00% 6 0 100.00%
+openbsd-compat/recallocarray.c 41 7 82.93% 1 0 100.00% 36 7 80.56%
+openbsd-compat/timingsafe_bcmp.c 4 0 100.00% 1 0 100.00% 7 0 100.00%
+src/aes256.c 118 3 97.46% 8 0 100.00% 157 11 92.99%
+src/assert.c 628 45 92.83% 63 4 93.65% 782 51 93.48%
+src/authkey.c 52 0 100.00% 5 0 100.00% 66 0 100.00%
+src/bio.c 451 20 95.57% 49 2 95.92% 587 24 95.91%
+src/blob.c 53 2 96.23% 10 0 100.00% 83 4 95.18%
+src/buf.c 8 1 87.50% 2 0 100.00% 16 1 93.75%
+src/cbor.c 1070 12 98.88% 55 0 100.00% 1258 28 97.77%
+src/compress.c 105 14 86.67% 5 0 100.00% 122 24 80.33%
+src/config.c 112 0 100.00% 11 0 100.00% 154 0 100.00%
+src/cred.c 653 36 94.49% 70 2 97.14% 853 39 95.43%
+src/credman.c 422 10 97.63% 40 0 100.00% 557 20 96.41%
+src/dev.c 332 65 80.42% 41 6 85.37% 378 80 78.84%
+src/ecdh.c 117 2 98.29% 4 0 100.00% 146 5 96.58%
+src/eddsa.c 88 5 94.32% 10 0 100.00% 114 9 92.11%
+src/err.c 122 10 91.80% 1 0 100.00% 126 10 92.06%
+src/es256.c 315 5 98.41% 19 0 100.00% 372 11 97.04%
+src/es384.c 158 5 96.84% 11 0 100.00% 198 11 94.44%
+src/hid.c 87 2 97.70% 14 0 100.00% 145 3 97.93%
+src/hid_linux.c 184 73 60.33% 14 7 50.00% 263 115 56.27%
+src/hid_unix.c 29 21 27.59% 2 0 100.00% 43 26 39.53%
+src/info.c 232 0 100.00% 51 0 100.00% 409 0 100.00%
+src/io.c 193 7 96.37% 13 0 100.00% 230 12 94.78%
+src/iso7816.c 18 1 94.44% 5 0 100.00% 38 1 97.37%
+src/largeblob.c 525 18 96.57% 30 0 100.00% 693 43 93.80%
+src/log.c 39 5 87.18% 7 1 85.71% 63 7 88.89%
+src/netlink.c 329 8 97.57% 40 0 100.00% 498 15 96.99%
+src/nfc.c 155 5 96.77% 12 0 100.00% 244 15 93.85%
+src/nfc_linux.c 172 77 55.23% 13 7 46.15% 242 126 47.93%
+src/pcsc.c 204 1 99.51% 13 0 100.00% 282 3 98.94%
+src/pin.c 426 3 99.30% 26 0 100.00% 514 4 99.22%
+src/random.c 6 0 100.00% 1 0 100.00% 6 0 100.00%
+src/reset.c 24 0 100.00% 3 0 100.00% 23 0 100.00%
+src/rs1.c 22 2 90.91% 3 0 100.00% 36 6 83.33%
+src/rs256.c 146 9 93.84% 13 0 100.00% 179 16 91.06%
+src/time.c 43 3 93.02% 3 0 100.00% 43 2 95.35%
+src/touch.c 67 0 100.00% 2 0 100.00% 79 0 100.00%
+src/tpm.c 103 0 100.00% 9 0 100.00% 194 0 100.00%
+src/types.c 29 0 100.00% 7 0 100.00% 56 0 100.00%
+src/u2f.c 572 4 99.30% 17 0 100.00% 726 12 98.35%
+src/util.c 14 1 92.86% 1 0 100.00% 14 1 92.86%
+
+Files which contain no functions:
+fuzz/mutator_aux.h 0 0 - 0 0 - 0 0 -
+openbsd-compat/openbsd-compat.h 0 0 - 0 0 - 0 0 -
+openbsd-compat/time.h 0 0 - 0 0 - 0 0 -
+src/extern.h 0 0 - 0 0 - 0 0 -
+src/fallthrough.h 0 0 - 0 0 - 0 0 -
+src/fido.h 0 0 - 0 0 - 0 0 -
+src/fido/err.h 0 0 - 0 0 - 0 0 -
+src/fido/param.h 0 0 - 0 0 - 0 0 -
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+TOTAL 8730 486 94.43% 742 29 96.09% 11357 769 93.23%
diff --git a/fuzz/udev.c b/fuzz/udev.c
new file mode 100644
index 0000000..3194012
--- /dev/null
+++ b/fuzz/udev.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2021 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 <sys/types.h>
+
+#include <linux/hidraw.h>
+#include <linux/input.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <libudev.h>
+#include <stdlib.h>
+
+#include "mutator_aux.h"
+
+struct udev {
+ int magic;
+};
+
+struct udev_enumerate {
+ int magic;
+ struct udev_list_entry *list_entry;
+};
+
+struct udev_list_entry {
+ int magic;
+};
+
+struct udev_device {
+ int magic;
+ struct udev_device *parent;
+};
+
+#define UDEV_MAGIC 0x584492cc
+#define UDEV_DEVICE_MAGIC 0x569180dd
+#define UDEV_LIST_ENTRY_MAGIC 0x497422ee
+#define UDEV_ENUM_MAGIC 0x583570ff
+
+#define ASSERT_TYPE(x, m) assert((x) != NULL && (x)->magic == (m))
+#define ASSERT_UDEV(x) ASSERT_TYPE((x), UDEV_MAGIC)
+#define ASSERT_UDEV_ENUM(x) ASSERT_TYPE((x), UDEV_ENUM_MAGIC)
+#define ASSERT_UDEV_LIST_ENTRY(x) ASSERT_TYPE((x), UDEV_LIST_ENTRY_MAGIC)
+#define ASSERT_UDEV_DEVICE(x) ASSERT_TYPE((x), UDEV_DEVICE_MAGIC)
+
+static const char *uevent;
+static const struct blob *report_descriptor;
+
+struct udev *__wrap_udev_new(void);
+struct udev_device *__wrap_udev_device_get_parent_with_subsystem_devtype(
+ struct udev_device *, const char *, const char *);
+struct udev_device *__wrap_udev_device_new_from_syspath(struct udev *,
+ const char *);
+struct udev_enumerate *__wrap_udev_enumerate_new(struct udev *);
+struct udev_list_entry *__wrap_udev_enumerate_get_list_entry(
+ struct udev_enumerate *);
+struct udev_list_entry *__wrap_udev_list_entry_get_next(
+ struct udev_list_entry *);
+const char *__wrap_udev_device_get_sysattr_value(struct udev_device *,
+ const char *);
+const char *__wrap_udev_list_entry_get_name(struct udev_list_entry *);
+const char *__wrap_udev_device_get_devnode(struct udev_device *);
+const char *__wrap_udev_device_get_sysnum(struct udev_device *);
+int __wrap_udev_enumerate_add_match_subsystem(struct udev_enumerate *,
+ const char *);
+int __wrap_udev_enumerate_scan_devices(struct udev_enumerate *);
+int __wrap_ioctl(int, unsigned long , ...);
+void __wrap_udev_device_unref(struct udev_device *);
+void __wrap_udev_enumerate_unref(struct udev_enumerate *);
+void __wrap_udev_unref(struct udev *);
+void set_udev_parameters(const char *, const struct blob *);
+
+struct udev_device *
+__wrap_udev_device_get_parent_with_subsystem_devtype(struct udev_device *child,
+ const char *subsystem, const char *devtype)
+{
+ ASSERT_UDEV_DEVICE(child);
+ fido_log_debug("%s", subsystem); /* XXX consume */
+ fido_log_debug("%s", devtype); /* XXX consume */
+ if (child->parent != NULL)
+ return child->parent;
+ if ((child->parent = calloc(1, sizeof(*child->parent))) == NULL)
+ return NULL;
+ child->parent->magic = UDEV_DEVICE_MAGIC;
+
+ return child->parent;
+}
+
+const char *
+__wrap_udev_device_get_sysattr_value(struct udev_device *udev_device,
+ const char *sysattr)
+{
+ ASSERT_UDEV_DEVICE(udev_device);
+ if (uniform_random(400) < 1)
+ return NULL;
+ if (!strcmp(sysattr, "manufacturer") || !strcmp(sysattr, "product"))
+ return "product info"; /* XXX randomise? */
+ else if (!strcmp(sysattr, "uevent"))
+ return uevent;
+
+ return NULL;
+}
+
+const char *
+__wrap_udev_list_entry_get_name(struct udev_list_entry *entry)
+{
+ ASSERT_UDEV_LIST_ENTRY(entry);
+ return uniform_random(400) < 1 ? NULL : "name"; /* XXX randomise? */
+}
+
+struct udev_device *
+__wrap_udev_device_new_from_syspath(struct udev *udev, const char *syspath)
+{
+ struct udev_device *udev_device;
+
+ ASSERT_UDEV(udev);
+ fido_log_debug("%s", syspath);
+ if ((udev_device = calloc(1, sizeof(*udev_device))) == NULL)
+ return NULL;
+ udev_device->magic = UDEV_DEVICE_MAGIC;
+
+ return udev_device;
+}
+
+const char *
+__wrap_udev_device_get_devnode(struct udev_device *udev_device)
+{
+ ASSERT_UDEV_DEVICE(udev_device);
+ return uniform_random(400) < 1 ? NULL : "/dev/zero";
+}
+
+const char *
+__wrap_udev_device_get_sysnum(struct udev_device *udev_device)
+{
+ ASSERT_UDEV_DEVICE(udev_device);
+ return uniform_random(400) < 1 ? NULL : "101010"; /* XXX randomise? */
+}
+
+void
+__wrap_udev_device_unref(struct udev_device *udev_device)
+{
+ ASSERT_UDEV_DEVICE(udev_device);
+ if (udev_device->parent) {
+ ASSERT_UDEV_DEVICE(udev_device->parent);
+ free(udev_device->parent);
+ }
+ free(udev_device);
+}
+
+struct udev *
+__wrap_udev_new(void)
+{
+ struct udev *udev;
+
+ if ((udev = calloc(1, sizeof(*udev))) == NULL)
+ return NULL;
+ udev->magic = UDEV_MAGIC;
+
+ return udev;
+}
+
+struct udev_enumerate *
+__wrap_udev_enumerate_new(struct udev *udev)
+{
+ struct udev_enumerate *udev_enum;
+
+ ASSERT_UDEV(udev);
+ if ((udev_enum = calloc(1, sizeof(*udev_enum))) == NULL)
+ return NULL;
+ udev_enum->magic = UDEV_ENUM_MAGIC;
+
+ return udev_enum;
+}
+
+int
+__wrap_udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enum,
+ const char *subsystem)
+{
+ ASSERT_UDEV_ENUM(udev_enum);
+ fido_log_debug("%s:", subsystem);
+ return uniform_random(400) < 1 ? -EINVAL : 0;
+}
+
+int
+__wrap_udev_enumerate_scan_devices(struct udev_enumerate *udev_enum)
+{
+ ASSERT_UDEV_ENUM(udev_enum);
+ return uniform_random(400) < 1 ? -EINVAL : 0;
+}
+
+struct udev_list_entry *
+__wrap_udev_enumerate_get_list_entry(struct udev_enumerate *udev_enum)
+{
+ ASSERT_UDEV_ENUM(udev_enum);
+ if ((udev_enum->list_entry = calloc(1,
+ sizeof(*udev_enum->list_entry))) == NULL)
+ return NULL;
+ udev_enum->list_entry->magic = UDEV_LIST_ENTRY_MAGIC;
+
+ return udev_enum->list_entry;
+}
+
+struct udev_list_entry *
+__wrap_udev_list_entry_get_next(struct udev_list_entry *udev_list_entry)
+{
+ ASSERT_UDEV_LIST_ENTRY(udev_list_entry);
+ return uniform_random(400) < 1 ? NULL : udev_list_entry;
+}
+
+void
+__wrap_udev_enumerate_unref(struct udev_enumerate *udev_enum)
+{
+ ASSERT_UDEV_ENUM(udev_enum);
+ if (udev_enum->list_entry)
+ ASSERT_UDEV_LIST_ENTRY(udev_enum->list_entry);
+ free(udev_enum->list_entry);
+ free(udev_enum);
+}
+
+void
+__wrap_udev_unref(struct udev *udev)
+{
+ ASSERT_UDEV(udev);
+ free(udev);
+}
+
+int
+__wrap_ioctl(int fd, unsigned long request, ...)
+{
+ va_list ap;
+ struct hidraw_report_descriptor *hrd;
+
+ (void)fd;
+
+ if (uniform_random(400) < 1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ va_start(ap, request);
+
+ switch (IOCTL_REQ(request)) {
+ case IOCTL_REQ(HIDIOCGRDESCSIZE):
+ *va_arg(ap, int *) = (int)report_descriptor->len;
+ break;
+ case IOCTL_REQ(HIDIOCGRDESC):
+ hrd = va_arg(ap, struct hidraw_report_descriptor *);
+ assert(hrd->size == report_descriptor->len);
+ memcpy(hrd->value, report_descriptor->body, hrd->size);
+ break;
+ default:
+ warnx("%s: unknown request 0x%lx", __func__, request);
+ abort();
+ }
+
+ va_end(ap);
+
+ return 0;
+}
+
+void
+set_udev_parameters(const char *uevent_ptr,
+ const struct blob *report_descriptor_ptr)
+{
+ uevent = uevent_ptr;
+ report_descriptor = report_descriptor_ptr;
+}
diff --git a/fuzz/uniform_random.c b/fuzz/uniform_random.c
new file mode 100644
index 0000000..357091c
--- /dev/null
+++ b/fuzz/uniform_random.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+uint32_t uniform_random(uint32_t);
+unsigned long prng_uint32(void);
+
+/*
+ * Calculate a uniformly distributed random number less than upper_bound
+ * avoiding "modulo bias".
+ *
+ * Uniformity is achieved by generating new random numbers until the one
+ * returned is outside the range [0, 2**32 % upper_bound). This
+ * guarantees the selected random number will be inside
+ * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
+ * after reduction modulo upper_bound.
+ */
+uint32_t
+uniform_random(uint32_t upper_bound)
+{
+ uint32_t r, min;
+
+ if (upper_bound < 2)
+ return 0;
+
+ /* 2**32 % x == (2**32 - x) % x */
+ min = -upper_bound % upper_bound;
+
+ /*
+ * This could theoretically loop forever but each retry has
+ * p > 0.5 (worst case, usually far better) of selecting a
+ * number inside the range we need, so it should rarely need
+ * to re-roll.
+ */
+ for (;;) {
+ r = (uint32_t)prng_uint32();
+ if (r >= min)
+ break;
+ }
+
+ return r % upper_bound;
+}
diff --git a/fuzz/wiredata_fido2.h b/fuzz/wiredata_fido2.h
new file mode 100644
index 0000000..6c66c54
--- /dev/null
+++ b/fuzz/wiredata_fido2.h
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2020-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
+ */
+
+#ifndef _WIREDATA_FIDO2_H
+#define _WIREDATA_FIDO2_H
+
+#define WIREDATA_CTAP_INIT \
+ 0xff, 0xff, 0xff, 0xff, 0x86, 0x00, 0x11, 0x80, \
+ 0x43, 0x56, 0x40, 0xb1, 0x4e, 0xd9, 0x2d, 0x00, \
+ 0x22, 0x00, 0x02, 0x02, 0x05, 0x02, 0x01, 0x05, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_KEEPALIVE \
+ 0x00, 0x22, 0x00, 0x02, 0xbb, 0x00, 0x01, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_INFO \
+ 0x00, 0x22, 0x00, 0x02, 0x90, 0x00, 0xb9, 0x00, \
+ 0xa9, 0x01, 0x83, 0x66, 0x55, 0x32, 0x46, 0x5f, \
+ 0x56, 0x32, 0x68, 0x46, 0x49, 0x44, 0x4f, 0x5f, \
+ 0x32, 0x5f, 0x30, 0x6c, 0x46, 0x49, 0x44, 0x4f, \
+ 0x5f, 0x32, 0x5f, 0x31, 0x5f, 0x50, 0x52, 0x45, \
+ 0x02, 0x82, 0x6b, 0x63, 0x72, 0x65, 0x64, 0x50, \
+ 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x6b, 0x68, \
+ 0x6d, 0x61, 0x63, 0x2d, 0x73, 0x65, 0x63, 0x72, \
+ 0x00, 0x22, 0x00, 0x02, 0x00, 0x65, 0x74, 0x03, \
+ 0x50, 0x19, 0x56, 0xe5, 0xbd, 0xa3, 0x74, 0x45, \
+ 0xf1, 0xa8, 0x14, 0x35, 0x64, 0x03, 0xfd, 0xbc, \
+ 0x18, 0x04, 0xa5, 0x62, 0x72, 0x6b, 0xf5, 0x62, \
+ 0x75, 0x70, 0xf5, 0x64, 0x70, 0x6c, 0x61, 0x74, \
+ 0xf4, 0x69, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, \
+ 0x50, 0x69, 0x6e, 0xf4, 0x75, 0x63, 0x72, 0x65, \
+ 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x4d, \
+ 0x00, 0x22, 0x00, 0x02, 0x01, 0x67, 0x6d, 0x74, \
+ 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0xf5, \
+ 0x05, 0x19, 0x04, 0xb0, 0x06, 0x81, 0x01, 0x07, \
+ 0x08, 0x08, 0x18, 0x80, 0x0a, 0x82, 0xa2, 0x63, \
+ 0x61, 0x6c, 0x67, 0x26, 0x64, 0x74, 0x79, 0x70, \
+ 0x65, 0x6a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, \
+ 0x2d, 0x6b, 0x65, 0x79, 0xa2, 0x63, 0x61, 0x6c, \
+ 0x67, 0x27, 0x64, 0x74, 0x79, 0x70, 0x65, 0x6a, \
+ 0x00, 0x22, 0x00, 0x02, 0x02, 0x70, 0x75, 0x62, \
+ 0x6c, 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_AUTHKEY \
+ 0x00, 0x22, 0x00, 0x02, 0x90, 0x00, 0x51, 0x00, \
+ 0xa1, 0x01, 0xa5, 0x01, 0x02, 0x03, 0x38, 0x18, \
+ 0x20, 0x01, 0x21, 0x58, 0x20, 0x2a, 0xb8, 0x2d, \
+ 0x36, 0x69, 0xab, 0x30, 0x9d, 0xe3, 0x5e, 0x9b, \
+ 0xfb, 0x94, 0xfc, 0x1d, 0x92, 0x95, 0xaf, 0x01, \
+ 0x47, 0xfe, 0x4b, 0x87, 0xe5, 0xcf, 0x3f, 0x05, \
+ 0x0b, 0x39, 0xda, 0x17, 0x49, 0x22, 0x58, 0x20, \
+ 0x15, 0x1b, 0xbe, 0x08, 0x78, 0x60, 0x4d, 0x3c, \
+ 0x00, 0x22, 0x00, 0x02, 0x00, 0x3f, 0xf1, 0x60, \
+ 0xa6, 0xd8, 0xf8, 0xed, 0xce, 0x4a, 0x30, 0x5d, \
+ 0x1a, 0xaf, 0x80, 0xc4, 0x0a, 0xd2, 0x6f, 0x77, \
+ 0x38, 0x12, 0x97, 0xaa, 0xbd, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_PINTOKEN \
+ 0x00, 0x22, 0x00, 0x02, 0x90, 0x00, 0x14, 0x00, \
+ 0xa1, 0x02, 0x50, 0xee, 0x40, 0x4c, 0x85, 0xd7, \
+ 0xa1, 0x2f, 0x56, 0xc4, 0x4e, 0xc5, 0x93, 0x41, \
+ 0xd0, 0x3b, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_STATUS \
+ 0x00, 0x22, 0x00, 0x02, 0x90, 0x00, 0x01, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_RETRIES \
+ 0x00, 0x22, 0x00, 0x02, 0x90, 0x00, 0x04, 0x00, \
+ 0xa1, 0x03, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_ASSERT \
+ 0x00, 0x22, 0x00, 0x02, 0x90, 0x00, 0xcb, 0x00, \
+ 0xa3, 0x01, 0xa2, 0x62, 0x69, 0x64, 0x58, 0x40, \
+ 0x4a, 0x4c, 0x9e, 0xcc, 0x81, 0x7d, 0x42, 0x03, \
+ 0x2b, 0x41, 0xd1, 0x38, 0xd3, 0x49, 0xb4, 0xfc, \
+ 0xfb, 0xe4, 0x4e, 0xe4, 0xff, 0x76, 0x34, 0x16, \
+ 0x68, 0x06, 0x9d, 0xa6, 0x01, 0x32, 0xb9, 0xff, \
+ 0xc2, 0x35, 0x0d, 0x89, 0x43, 0x66, 0x12, 0xf8, \
+ 0x8e, 0x5b, 0xde, 0xf4, 0xcc, 0xec, 0x9d, 0x03, \
+ 0x00, 0x92, 0x00, 0x0e, 0x00, 0x85, 0xc2, 0xf5, \
+ 0xe6, 0x8e, 0xeb, 0x3f, 0x3a, 0xec, 0xc3, 0x1d, \
+ 0x04, 0x6e, 0xf3, 0x5b, 0x88, 0x64, 0x74, 0x79, \
+ 0x70, 0x65, 0x6a, 0x70, 0x75, 0x62, 0x6c, 0x69, \
+ 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x02, 0x58, 0x25, \
+ 0x49, 0x96, 0x0d, 0xe5, 0x88, 0x0e, 0x8c, 0x68, \
+ 0x74, 0x34, 0x17, 0x0f, 0x64, 0x76, 0x60, 0x5b, \
+ 0x8f, 0xe4, 0xae, 0xb9, 0xa2, 0x86, 0x32, 0xc7, \
+ 0x00, 0x92, 0x00, 0x0e, 0x01, 0x99, 0x5c, 0xf3, \
+ 0xba, 0x83, 0x1d, 0x97, 0x63, 0x04, 0x00, 0x00, \
+ 0x00, 0x09, 0x03, 0x58, 0x47, 0x30, 0x45, 0x02, \
+ 0x21, 0x00, 0xcf, 0x3f, 0x36, 0x0e, 0x1f, 0x6f, \
+ 0xd6, 0xa0, 0x9d, 0x13, 0xcf, 0x55, 0xf7, 0x49, \
+ 0x8f, 0xc8, 0xc9, 0x03, 0x12, 0x76, 0x41, 0x75, \
+ 0x7b, 0xb5, 0x0a, 0x90, 0xa5, 0x82, 0x26, 0xf1, \
+ 0x6b, 0x80, 0x02, 0x20, 0x34, 0x9b, 0x7a, 0x82, \
+ 0x00, 0x92, 0x00, 0x0e, 0x02, 0xd3, 0xe1, 0x79, \
+ 0x49, 0x55, 0x41, 0x9f, 0xa4, 0x06, 0x06, 0xbd, \
+ 0xc8, 0xb9, 0x2b, 0x5f, 0xe1, 0xa7, 0x99, 0x1c, \
+ 0xa1, 0xfc, 0x7e, 0x3e, 0xd5, 0x85, 0x2e, 0x11, \
+ 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_CRED \
+ 0x00, 0x91, 0x00, 0x03, 0x90, 0x03, 0xe1, 0x00, \
+ 0xa3, 0x01, 0x66, 0x70, 0x61, 0x63, 0x6b, 0x65, \
+ 0x64, 0x02, 0x58, 0xc4, 0x49, 0x96, 0x0d, 0xe5, \
+ 0x88, 0x0e, 0x8c, 0x68, 0x74, 0x34, 0x17, 0x0f, \
+ 0x64, 0x76, 0x60, 0x5b, 0x8f, 0xe4, 0xae, 0xb9, \
+ 0xa2, 0x86, 0x32, 0xc7, 0x99, 0x5c, 0xf3, 0xba, \
+ 0x83, 0x1d, 0x97, 0x63, 0x45, 0x00, 0x00, 0x00, \
+ 0x00, 0xf8, 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, \
+ 0x00, 0x91, 0x00, 0x03, 0x00, 0x15, 0x80, 0x06, \
+ 0x17, 0x11, 0x1f, 0x9e, 0xdc, 0x7d, 0x00, 0x40, \
+ 0xed, 0x88, 0x48, 0xa1, 0xdb, 0x56, 0x4d, 0x0f, \
+ 0x0d, 0xc8, 0x8f, 0x0f, 0xe9, 0x16, 0xb1, 0x78, \
+ 0xa9, 0x40, 0x98, 0x71, 0xa0, 0xb3, 0xf2, 0xcf, \
+ 0x05, 0x73, 0x6c, 0x12, 0xbf, 0x00, 0x96, 0xf3, \
+ 0x7b, 0x93, 0xba, 0x49, 0xee, 0x23, 0xb4, 0x78, \
+ 0x2e, 0xfb, 0xce, 0x27, 0xa8, 0xc2, 0x26, 0x78, \
+ 0x00, 0x91, 0x00, 0x03, 0x01, 0xcc, 0x95, 0x2d, \
+ 0x40, 0xdb, 0xd1, 0x40, 0x3d, 0x2b, 0xa3, 0x31, \
+ 0xa0, 0x75, 0x82, 0x63, 0xf0, 0xa5, 0x01, 0x02, \
+ 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x9d, \
+ 0x95, 0xa1, 0xb5, 0xd6, 0x11, 0xbf, 0xe2, 0x28, \
+ 0xa0, 0x7f, 0xca, 0x1e, 0xd9, 0x09, 0x0f, 0x0d, \
+ 0xe7, 0x8e, 0x29, 0xe8, 0x2e, 0x11, 0xdb, 0x55, \
+ 0x62, 0x13, 0xd7, 0x26, 0xc2, 0x7e, 0x2b, 0x22, \
+ 0x00, 0x91, 0x00, 0x03, 0x02, 0x58, 0x20, 0xbe, \
+ 0x74, 0x2a, 0xac, 0xde, 0x11, 0x40, 0x76, 0x31, \
+ 0x0b, 0xed, 0x55, 0xde, 0xf3, 0x03, 0xe4, 0x1c, \
+ 0xac, 0x42, 0x63, 0x8f, 0xe8, 0x30, 0x63, 0xb7, \
+ 0x07, 0x4e, 0x5d, 0xfb, 0x17, 0x5e, 0x9b, 0x03, \
+ 0xa3, 0x63, 0x61, 0x6c, 0x67, 0x26, 0x63, 0x73, \
+ 0x69, 0x67, 0x58, 0x48, 0x30, 0x46, 0x02, 0x21, \
+ 0x00, 0xfb, 0xd1, 0x26, 0x76, 0x34, 0x74, 0xac, \
+ 0x00, 0x91, 0x00, 0x03, 0x03, 0xf6, 0xd8, 0x5c, \
+ 0x5d, 0xbc, 0xda, 0xe0, 0x43, 0xe0, 0xa5, 0x42, \
+ 0x9f, 0xc7, 0xe2, 0x18, 0x3e, 0xe2, 0x2c, 0x94, \
+ 0x78, 0xbf, 0x9c, 0xeb, 0x3e, 0x9d, 0x02, 0x21, \
+ 0x00, 0xab, 0x21, 0x1b, 0xc4, 0x30, 0x69, 0xee, \
+ 0x7f, 0x09, 0xe6, 0x6b, 0x99, 0x98, 0x34, 0x07, \
+ 0x7b, 0x9a, 0x58, 0xb2, 0xe8, 0x77, 0xe0, 0xba, \
+ 0x7d, 0xab, 0x65, 0xf8, 0xba, 0x2a, 0xcb, 0x9a, \
+ 0x00, 0x91, 0x00, 0x03, 0x04, 0x41, 0x63, 0x78, \
+ 0x35, 0x63, 0x81, 0x59, 0x02, 0xb3, 0x30, 0x82, \
+ 0x02, 0xaf, 0x30, 0x82, 0x01, 0x97, 0xa0, 0x03, \
+ 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x5b, 0x3d, \
+ 0xb6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, \
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, \
+ 0x30, 0x21, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, \
+ 0x55, 0x04, 0x03, 0x0c, 0x16, 0x59, 0x75, 0x62, \
+ 0x00, 0x91, 0x00, 0x03, 0x05, 0x69, 0x63, 0x6f, \
+ 0x20, 0x46, 0x49, 0x44, 0x4f, 0x20, 0x50, 0x72, \
+ 0x65, 0x76, 0x69, 0x65, 0x77, 0x20, 0x43, 0x41, \
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x34, \
+ 0x31, 0x32, 0x31, 0x30, 0x35, 0x37, 0x31, 0x30, \
+ 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x31, 0x32, 0x33, \
+ 0x31, 0x31, 0x30, 0x35, 0x37, 0x31, 0x30, 0x5a, \
+ 0x30, 0x6f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
+ 0x00, 0x91, 0x00, 0x03, 0x06, 0x55, 0x04, 0x06, \
+ 0x13, 0x02, 0x53, 0x45, 0x31, 0x12, 0x30, 0x10, \
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x59, \
+ 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x41, 0x42, \
+ 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, \
+ 0x0b, 0x0c, 0x19, 0x41, 0x75, 0x74, 0x68, 0x65, \
+ 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x6f, 0x72, \
+ 0x20, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, \
+ 0x00, 0x91, 0x00, 0x03, 0x07, 0x74, 0x69, 0x6f, \
+ 0x6e, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, \
+ 0x04, 0x03, 0x0c, 0x1f, 0x59, 0x75, 0x62, 0x69, \
+ 0x63, 0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, 0x45, \
+ 0x45, 0x20, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, \
+ 0x20, 0x31, 0x32, 0x31, 0x33, 0x39, 0x33, 0x39, \
+ 0x31, 0x32, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, \
+ 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, \
+ 0x00, 0x91, 0x00, 0x03, 0x08, 0x06, 0x08, 0x2a, \
+ 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, \
+ 0x42, 0x00, 0x04, 0xfb, 0x2c, 0xdd, 0x30, 0x43, \
+ 0x28, 0xc5, 0x72, 0x4a, 0x50, 0xcc, 0xe6, 0xf6, \
+ 0x0b, 0xad, 0x7d, 0x27, 0xa9, 0x1b, 0x59, 0xe1, \
+ 0xe6, 0x6f, 0x29, 0x7b, 0x89, 0xc9, 0xd4, 0x3d, \
+ 0xc2, 0xb2, 0xc7, 0x78, 0x89, 0xb4, 0xf0, 0xff, \
+ 0x9d, 0x02, 0x28, 0xcb, 0x94, 0x6d, 0xfc, 0xe0, \
+ 0x00, 0x91, 0x00, 0x03, 0x09, 0x1b, 0x19, 0x58, \
+ 0x9b, 0x67, 0x80, 0x4a, 0xac, 0x97, 0x7f, 0x28, \
+ 0x18, 0x9c, 0xcd, 0xb3, 0x25, 0x74, 0xca, 0x28, \
+ 0xa3, 0x6c, 0x30, 0x6a, 0x30, 0x22, 0x06, 0x09, \
+ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xc4, 0x0a, \
+ 0x02, 0x04, 0x15, 0x31, 0x2e, 0x33, 0x2e, 0x36, \
+ 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, \
+ 0x31, 0x34, 0x38, 0x32, 0x2e, 0x31, 0x2e, 0x36, \
+ 0x00, 0x91, 0x00, 0x03, 0x0a, 0x30, 0x13, 0x06, \
+ 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xe5, \
+ 0x1c, 0x02, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, \
+ 0x04, 0x30, 0x30, 0x21, 0x06, 0x0b, 0x2b, 0x06, \
+ 0x01, 0x04, 0x01, 0x82, 0xe5, 0x1c, 0x01, 0x01, \
+ 0x04, 0x04, 0x12, 0x04, 0x10, 0xf8, 0xa0, 0x11, \
+ 0xf3, 0x8c, 0x0a, 0x4d, 0x15, 0x80, 0x06, 0x17, \
+ 0x11, 0x1f, 0x9e, 0xdc, 0x7d, 0x30, 0x0c, 0x06, \
+ 0x00, 0x91, 0x00, 0x03, 0x0b, 0x03, 0x55, 0x1d, \
+ 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, \
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
+ 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, \
+ 0x82, 0x01, 0x01, 0x00, 0x32, 0xf3, 0xe4, 0xbd, \
+ 0x58, 0xd7, 0x42, 0x2b, 0xaf, 0x49, 0x99, 0x86, \
+ 0x08, 0x1f, 0x0d, 0xa9, 0x3b, 0xc6, 0xaa, 0x1c, \
+ 0x72, 0x11, 0xf9, 0x28, 0x53, 0xeb, 0xf3, 0xeb, \
+ 0x00, 0x91, 0x00, 0x03, 0x0c, 0x73, 0xda, 0x69, \
+ 0x3b, 0x06, 0xde, 0x31, 0x33, 0x8e, 0x5d, 0x02, \
+ 0xec, 0xf6, 0x76, 0xe9, 0x5c, 0x42, 0xbe, 0xa5, \
+ 0x8f, 0x25, 0xd3, 0x37, 0x3f, 0x77, 0xbb, 0x2a, \
+ 0x9d, 0x7c, 0xb2, 0x3e, 0x11, 0x8c, 0x41, 0xd4, \
+ 0x9a, 0x4c, 0x9a, 0xd8, 0xf3, 0xe2, 0xa4, 0xec, \
+ 0x01, 0x77, 0x7a, 0x74, 0xa8, 0xc4, 0x12, 0x43, \
+ 0xc3, 0x1e, 0xce, 0x20, 0x8f, 0x2d, 0x0f, 0x6e, \
+ 0x00, 0x91, 0x00, 0x03, 0x0d, 0xbc, 0x61, 0x9b, \
+ 0xe1, 0x84, 0xa1, 0x72, 0xf6, 0xa9, 0xac, 0xcb, \
+ 0xf8, 0x73, 0x6d, 0x5b, 0xe2, 0x98, 0xb3, 0x6b, \
+ 0xec, 0xe7, 0x1e, 0x77, 0x8d, 0x0a, 0x69, 0xaa, \
+ 0xf9, 0x94, 0xb8, 0x63, 0x6d, 0xe8, 0xfa, 0xf6, \
+ 0x2f, 0xd3, 0xce, 0x7f, 0x04, 0x4c, 0x32, 0x2c, \
+ 0xf7, 0x26, 0x3e, 0x34, 0x99, 0xe6, 0xa5, 0xb2, \
+ 0xb0, 0x2a, 0xbb, 0xad, 0x5b, 0xd9, 0xec, 0xe5, \
+ 0x00, 0x91, 0x00, 0x03, 0x0e, 0xb0, 0x71, 0x4d, \
+ 0x73, 0xbb, 0x94, 0x61, 0x49, 0x9c, 0x94, 0x2a, \
+ 0x5f, 0x1d, 0xcc, 0xaf, 0x65, 0x03, 0x3b, 0x39, \
+ 0x39, 0xd4, 0x47, 0xd9, 0xfc, 0xc4, 0x7b, 0x0b, \
+ 0x16, 0xd8, 0xe9, 0x01, 0xfc, 0xec, 0x3f, 0x8c, \
+ 0x1b, 0xc0, 0xc6, 0xac, 0x0b, 0x5d, 0x74, 0xc7, \
+ 0xbb, 0x03, 0x05, 0x69, 0x17, 0xe9, 0x98, 0x1a, \
+ 0x19, 0xb9, 0x09, 0x5c, 0xa1, 0xf4, 0xab, 0x9f, \
+ 0x00, 0x91, 0x00, 0x03, 0x0f, 0x02, 0x7c, 0x28, \
+ 0x0f, 0x8a, 0xf9, 0xed, 0x1d, 0x29, 0x3c, 0xf6, \
+ 0xcc, 0x2f, 0x04, 0x6d, 0x9a, 0xd6, 0x62, 0xb4, \
+ 0xa9, 0x6e, 0xb1, 0xca, 0xca, 0xac, 0x5e, 0x05, \
+ 0x3e, 0x83, 0x91, 0x47, 0x7c, 0x1f, 0x8b, 0x60, \
+ 0x01, 0xde, 0x65, 0x3a, 0xbf, 0xf2, 0xaa, 0xbb, \
+ 0x55, 0x98, 0x86, 0x91, 0x7e, 0xad, 0x3b, 0x36, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_CREDMAN_META \
+ 0x00, 0x12, 0x00, 0x04, 0x90, 0x00, 0x07, 0x00, \
+ 0xa2, 0x01, 0x00, 0x02, 0x18, 0x19, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_CREDMAN_RPLIST \
+ 0x00, 0x15, 0x00, 0x02, 0x90, 0x00, 0x37, 0x00, \
+ 0xa3, 0x03, 0xa1, 0x62, 0x69, 0x64, 0x6a, 0x79, \
+ 0x75, 0x62, 0x69, 0x63, 0x6f, 0x2e, 0x63, 0x6f, \
+ 0x6d, 0x04, 0x58, 0x20, 0x37, 0x82, 0x09, 0xb7, \
+ 0x2d, 0xef, 0xcb, 0xa9, 0x1d, 0xcb, 0xf8, 0x54, \
+ 0xed, 0xb4, 0xda, 0xa6, 0x48, 0x82, 0x8a, 0x2c, \
+ 0xbd, 0x18, 0x0a, 0xfc, 0x77, 0xa7, 0x44, 0x34, \
+ 0x65, 0x5a, 0x1c, 0x7d, 0x05, 0x03, 0x00, 0x00, \
+ 0x00, 0x15, 0x00, 0x02, 0x90, 0x00, 0x36, 0x00, \
+ 0xa2, 0x03, 0xa1, 0x62, 0x69, 0x64, 0x6b, 0x79, \
+ 0x75, 0x62, 0x69, 0x6b, 0x65, 0x79, 0x2e, 0x6f, \
+ 0x72, 0x67, 0x04, 0x58, 0x20, 0x12, 0x6b, 0xba, \
+ 0x6a, 0x2d, 0x7a, 0x81, 0x84, 0x25, 0x7b, 0x74, \
+ 0xdd, 0x1d, 0xdd, 0x46, 0xb6, 0x2a, 0x8c, 0xa2, \
+ 0xa7, 0x83, 0xfe, 0xdb, 0x5b, 0x19, 0x48, 0x73, \
+ 0x55, 0xb7, 0xe3, 0x46, 0x09, 0x00, 0x00, 0x00, \
+ 0x00, 0x15, 0x00, 0x02, 0x90, 0x00, 0x37, 0x00, \
+ 0xa2, 0x03, 0xa1, 0x62, 0x69, 0x64, 0x6c, 0x77, \
+ 0x65, 0x62, 0x61, 0x75, 0x74, 0x68, 0x6e, 0x2e, \
+ 0x64, 0x65, 0x76, 0x04, 0x58, 0x20, 0xd6, 0x32, \
+ 0x7d, 0x8c, 0x6a, 0x5d, 0xe6, 0xae, 0x0e, 0x33, \
+ 0xd0, 0xa3, 0x31, 0xfb, 0x67, 0x77, 0xb9, 0x4e, \
+ 0xf4, 0x73, 0x19, 0xfe, 0x7e, 0xfd, 0xfa, 0x82, \
+ 0x70, 0x8e, 0x1f, 0xbb, 0xa2, 0x55, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_CREDMAN_RKLIST \
+ 0x00, 0x15, 0x00, 0x04, 0x90, 0x00, 0xc5, 0x00, \
+ 0xa5, 0x06, 0xa3, 0x62, 0x69, 0x64, 0x58, 0x20, \
+ 0xe4, 0xe1, 0x06, 0x31, 0xde, 0x00, 0x0f, 0x4f, \
+ 0x12, 0x6e, 0xc9, 0x68, 0x2d, 0x43, 0x3f, 0xf1, \
+ 0x02, 0x2c, 0x6e, 0xe6, 0x96, 0x10, 0xbf, 0x73, \
+ 0x35, 0xc9, 0x20, 0x27, 0x06, 0xba, 0x39, 0x09, \
+ 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x6a, 0x62, 0x6f, \
+ 0x62, 0x20, 0x62, 0x61, 0x6e, 0x61, 0x6e, 0x61, \
+ 0x00, 0x15, 0x00, 0x04, 0x00, 0x6b, 0x64, 0x69, \
+ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, \
+ 0x65, 0x67, 0x62, 0x62, 0x61, 0x6e, 0x61, 0x6e, \
+ 0x61, 0x07, 0xa2, 0x62, 0x69, 0x64, 0x50, 0x19, \
+ 0xf7, 0x78, 0x0c, 0xa0, 0xbc, 0xb9, 0xa6, 0xd5, \
+ 0x1e, 0xd7, 0x87, 0xfb, 0x6c, 0x80, 0x03, 0x64, \
+ 0x74, 0x79, 0x70, 0x65, 0x6a, 0x70, 0x75, 0x62, \
+ 0x6c, 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x08, \
+ 0x00, 0x15, 0x00, 0x04, 0x01, 0xa5, 0x01, 0x02, \
+ 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x81, \
+ 0x6c, 0xdd, 0x8c, 0x8f, 0x8c, 0xc8, 0x43, 0xa7, \
+ 0xbb, 0x79, 0x51, 0x09, 0xb1, 0xdf, 0xbe, 0xc4, \
+ 0xa5, 0x54, 0x16, 0x9e, 0x58, 0x56, 0xb3, 0x0b, \
+ 0x34, 0x4f, 0xa5, 0x6c, 0x05, 0xa2, 0x21, 0x22, \
+ 0x58, 0x20, 0xcd, 0xc2, 0x0c, 0x99, 0x83, 0x5a, \
+ 0x61, 0x73, 0xd8, 0xe0, 0x74, 0x23, 0x46, 0x64, \
+ 0x00, 0x15, 0x00, 0x04, 0x02, 0x39, 0x4c, 0xb0, \
+ 0xf4, 0x6c, 0x0a, 0x37, 0x72, 0xaa, 0xa8, 0xea, \
+ 0x58, 0xd3, 0xd4, 0xe0, 0x51, 0xb2, 0x28, 0x09, \
+ 0x05, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x15, 0x00, 0x04, 0x90, 0x00, 0xa0, 0x00, \
+ 0xa4, 0x06, 0xa3, 0x62, 0x69, 0x64, 0x58, 0x20, \
+ 0x56, 0xa1, 0x3c, 0x06, 0x2b, 0xad, 0xa2, 0x21, \
+ 0x7d, 0xcd, 0x91, 0x08, 0x47, 0xa8, 0x8a, 0x06, \
+ 0x06, 0xf6, 0x66, 0x91, 0xf6, 0xeb, 0x89, 0xe4, \
+ 0xdf, 0x26, 0xbc, 0x46, 0x59, 0xc3, 0x7d, 0xc0, \
+ 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x6a, 0x62, 0x6f, \
+ 0x62, 0x20, 0x62, 0x61, 0x6e, 0x61, 0x6e, 0x61, \
+ 0x00, 0x15, 0x00, 0x04, 0x00, 0x6b, 0x64, 0x69, \
+ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, \
+ 0x65, 0x67, 0x62, 0x62, 0x61, 0x6e, 0x61, 0x6e, \
+ 0x61, 0x07, 0xa2, 0x62, 0x69, 0x64, 0x50, 0xd8, \
+ 0x27, 0x4b, 0x25, 0xed, 0x19, 0xef, 0x11, 0xaf, \
+ 0xa6, 0x89, 0x7b, 0x84, 0x50, 0xe7, 0x62, 0x64, \
+ 0x74, 0x79, 0x70, 0x65, 0x6a, 0x70, 0x75, 0x62, \
+ 0x6c, 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x08, \
+ 0x00, 0x15, 0x00, 0x04, 0x01, 0xa4, 0x01, 0x01, \
+ 0x03, 0x27, 0x20, 0x06, 0x21, 0x58, 0x20, 0x8d, \
+ 0xfe, 0x45, 0xd5, 0x7d, 0xb6, 0x17, 0xab, 0x86, \
+ 0x2d, 0x32, 0xf6, 0x85, 0xf0, 0x92, 0x76, 0xb7, \
+ 0xce, 0x73, 0xca, 0x4e, 0x0e, 0xfd, 0xd5, 0xdb, \
+ 0x2a, 0x1d, 0x55, 0x90, 0x96, 0x52, 0xc2, 0x0a, \
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x15, 0x00, 0x04, 0x90, 0x00, 0xa0, 0x00, \
+ 0xa4, 0x06, 0xa3, 0x62, 0x69, 0x64, 0x58, 0x20, \
+ 0x04, 0x0e, 0x0f, 0xa0, 0xcd, 0x60, 0x35, 0x9a, \
+ 0xba, 0x47, 0x0c, 0x10, 0xb6, 0x82, 0x6e, 0x2f, \
+ 0x66, 0xb9, 0xa7, 0xcf, 0xd8, 0x47, 0xb4, 0x3d, \
+ 0xfd, 0x77, 0x1a, 0x38, 0x22, 0xa1, 0xda, 0xa5, \
+ 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x6a, 0x62, 0x6f, \
+ 0x62, 0x20, 0x62, 0x61, 0x6e, 0x61, 0x6e, 0x61, \
+ 0x00, 0x15, 0x00, 0x04, 0x00, 0x6b, 0x64, 0x69, \
+ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, \
+ 0x65, 0x67, 0x62, 0x62, 0x61, 0x6e, 0x61, 0x6e, \
+ 0x61, 0x07, 0xa2, 0x62, 0x69, 0x64, 0x50, 0x00, \
+ 0x5d, 0xdf, 0xef, 0xe2, 0xf3, 0x06, 0xb2, 0xa5, \
+ 0x46, 0x4d, 0x98, 0xbc, 0x14, 0x65, 0xc1, 0x64, \
+ 0x74, 0x79, 0x70, 0x65, 0x6a, 0x70, 0x75, 0x62, \
+ 0x6c, 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x08, \
+ 0x00, 0x15, 0x00, 0x04, 0x01, 0xa4, 0x01, 0x01, \
+ 0x03, 0x27, 0x20, 0x06, 0x21, 0x58, 0x20, 0x72, \
+ 0x79, 0x14, 0x69, 0xdf, 0xcb, 0x64, 0x75, 0xee, \
+ 0xd4, 0x45, 0x94, 0xbc, 0x48, 0x4d, 0x2a, 0x9f, \
+ 0xc9, 0xf4, 0xb5, 0x1b, 0x05, 0xa6, 0x5b, 0x54, \
+ 0x9a, 0xac, 0x6c, 0x2e, 0xc6, 0x90, 0x62, 0x0a, \
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x15, 0x00, 0x04, 0x90, 0x00, 0xc3, 0x00, \
+ 0xa4, 0x06, 0xa3, 0x62, 0x69, 0x64, 0x58, 0x20, \
+ 0xce, 0x32, 0xd8, 0x79, 0xdd, 0x86, 0xa2, 0x42, \
+ 0x7c, 0xc3, 0xe1, 0x95, 0x12, 0x93, 0x1a, 0x03, \
+ 0xe6, 0x70, 0xb8, 0xff, 0xcd, 0xa5, 0xdf, 0x15, \
+ 0xfc, 0x88, 0x2a, 0xf5, 0x44, 0xf1, 0x33, 0x9c, \
+ 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x6a, 0x62, 0x6f, \
+ 0x62, 0x20, 0x62, 0x61, 0x6e, 0x61, 0x6e, 0x61, \
+ 0x00, 0x15, 0x00, 0x04, 0x00, 0x6b, 0x64, 0x69, \
+ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, \
+ 0x65, 0x67, 0x62, 0x62, 0x61, 0x6e, 0x61, 0x6e, \
+ 0x61, 0x07, 0xa2, 0x62, 0x69, 0x64, 0x50, 0x0a, \
+ 0x26, 0x5b, 0x7e, 0x1a, 0x2a, 0xba, 0x70, 0x5f, \
+ 0x18, 0x26, 0x14, 0xb2, 0x71, 0xca, 0x98, 0x64, \
+ 0x74, 0x79, 0x70, 0x65, 0x6a, 0x70, 0x75, 0x62, \
+ 0x6c, 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x08, \
+ 0x00, 0x15, 0x00, 0x04, 0x01, 0xa5, 0x01, 0x02, \
+ 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0x8b, \
+ 0x48, 0xf0, 0x69, 0xfb, 0x22, 0xfb, 0xf3, 0x86, \
+ 0x57, 0x7c, 0xdd, 0x82, 0x2c, 0x1c, 0x0c, 0xdc, \
+ 0x27, 0xe2, 0x6a, 0x4c, 0x1a, 0x10, 0x04, 0x27, \
+ 0x51, 0x3e, 0x2a, 0x9d, 0x3a, 0xb6, 0xb5, 0x22, \
+ 0x58, 0x20, 0x70, 0xfe, 0x91, 0x67, 0x64, 0x53, \
+ 0x63, 0x83, 0x72, 0x31, 0xe9, 0xe5, 0x20, 0xb7, \
+ 0x00, 0x15, 0x00, 0x04, 0x02, 0xee, 0xc9, 0xfb, \
+ 0x63, 0xd7, 0xe4, 0x76, 0x39, 0x80, 0x82, 0x74, \
+ 0xb8, 0xfa, 0x67, 0xf5, 0x1b, 0x8f, 0xe0, 0x0a, \
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x15, 0x00, 0x04, 0x90, 0x00, 0xc3, 0x00, \
+ 0xa4, 0x06, 0xa3, 0x62, 0x69, 0x64, 0x58, 0x20, \
+ 0xf9, 0xa3, 0x67, 0xbf, 0x5e, 0x80, 0x95, 0xdb, \
+ 0x4c, 0xc5, 0x8f, 0x65, 0x36, 0xc5, 0xaf, 0xdd, \
+ 0x90, 0x2e, 0x62, 0x68, 0x67, 0x9c, 0xa2, 0x26, \
+ 0x2f, 0x2a, 0xf9, 0x3a, 0xda, 0x15, 0xf2, 0x27, \
+ 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x6a, 0x62, 0x6f, \
+ 0x62, 0x20, 0x62, 0x61, 0x6e, 0x61, 0x6e, 0x61, \
+ 0x00, 0x15, 0x00, 0x04, 0x00, 0x6b, 0x64, 0x69, \
+ 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, \
+ 0x65, 0x67, 0x62, 0x62, 0x61, 0x6e, 0x61, 0x6e, \
+ 0x61, 0x07, 0xa2, 0x62, 0x69, 0x64, 0x50, 0xfb, \
+ 0xa6, 0xbe, 0xc1, 0x01, 0xf6, 0x7a, 0x81, 0xf9, \
+ 0xcd, 0x6d, 0x20, 0x41, 0x7a, 0x1c, 0x40, 0x64, \
+ 0x74, 0x79, 0x70, 0x65, 0x6a, 0x70, 0x75, 0x62, \
+ 0x6c, 0x69, 0x63, 0x2d, 0x6b, 0x65, 0x79, 0x08, \
+ 0x00, 0x15, 0x00, 0x04, 0x01, 0xa5, 0x01, 0x02, \
+ 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20, 0xda, \
+ 0x2b, 0x53, 0xc3, 0xbe, 0x48, 0xf8, 0xab, 0xbd, \
+ 0x06, 0x28, 0x46, 0xfa, 0x35, 0xab, 0xf9, 0xc5, \
+ 0x2e, 0xfd, 0x3c, 0x38, 0x88, 0xb3, 0xe1, 0xa7, \
+ 0xc5, 0xc6, 0xed, 0x72, 0x54, 0x37, 0x93, 0x22, \
+ 0x58, 0x20, 0x12, 0x82, 0x32, 0x2d, 0xab, 0xbc, \
+ 0x64, 0xb3, 0xed, 0xcc, 0xd5, 0x22, 0xec, 0x79, \
+ 0x00, 0x15, 0x00, 0x04, 0x02, 0x4b, 0xe2, 0x4d, \
+ 0x0c, 0x4b, 0x8d, 0x31, 0x4c, 0xb4, 0x0f, 0xd4, \
+ 0xa9, 0xbe, 0x0c, 0xab, 0x9e, 0x0a, 0xc9, 0x0a, \
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_BIO_INFO \
+ 0x00, 0x10, 0x00, 0x04, 0x90, 0x00, 0x06, 0x00, \
+ 0xa2, 0x02, 0x01, 0x03, 0x04, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_BIO_ENROLL \
+ 0x00, 0x0a, 0x00, 0x05, 0xbb, 0x00, 0x01, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x0a, 0x00, 0x05, 0xbb, 0x00, 0x01, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x0a, 0x00, 0x05, 0xbb, 0x00, 0x01, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x0a, 0x00, 0x05, 0x90, 0x00, 0x0a, 0x00, \
+ 0xa3, 0x04, 0x42, 0x68, 0x96, 0x05, 0x00, 0x06, \
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x0a, 0x00, 0x05, 0xbb, 0x00, 0x01, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x0a, 0x00, 0x05, 0xbb, 0x00, 0x01, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x0a, 0x00, 0x05, 0x90, 0x00, 0x06, 0x00, \
+ 0xa2, 0x05, 0x00, 0x06, 0x01, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x0a, 0x00, 0x05, 0xbb, 0x00, 0x01, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x0a, 0x00, 0x05, 0x90, 0x00, 0x06, 0x00, \
+ 0xa2, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_BIO_ENUM \
+ 0x00, 0x10, 0x00, 0x0f, 0x90, 0x00, 0x2e, 0x00, \
+ 0xa1, 0x07, 0x83, 0xa2, 0x01, 0x42, 0xce, 0xa3, \
+ 0x02, 0x67, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, \
+ 0x31, 0xa2, 0x01, 0x42, 0xbf, 0x5e, 0x02, 0x67, \
+ 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x32, 0xa2, \
+ 0x01, 0x42, 0x5e, 0xd2, 0x02, 0x67, 0x66, 0x69, \
+ 0x6e, 0x67, 0x65, 0x72, 0x33, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_CBOR_LARGEBLOB_GET_ARRAY \
+ 0x89, 0xc9, 0x8d, 0x28, 0x90, 0x01, 0xe6, 0x00, \
+ 0xa1, 0x01, 0x59, 0x01, 0xe0, 0x81, 0xa3, 0x01, \
+ 0x59, 0x01, 0xb8, 0xb3, 0x26, 0x24, 0x99, 0xde, \
+ 0x06, 0x3f, 0xca, 0xde, 0x98, 0x8d, 0x9d, 0xc5, \
+ 0x3f, 0x26, 0x6c, 0xc7, 0x40, 0x93, 0xc4, 0x88, \
+ 0x06, 0x51, 0x4f, 0xb9, 0x61, 0xf2, 0xc9, 0x8d, \
+ 0xbc, 0xce, 0x79, 0x08, 0xec, 0x90, 0xc5, 0x5b, \
+ 0xe5, 0x0a, 0x72, 0x08, 0x7b, 0xe1, 0xf9, 0x16, \
+ 0x89, 0xc9, 0x8d, 0x28, 0x00, 0x06, 0x8b, 0x76, \
+ 0x32, 0xa0, 0xae, 0x55, 0xb2, 0x39, 0x71, 0xce, \
+ 0x34, 0x4b, 0x6e, 0x6b, 0x89, 0xa6, 0x5e, 0x69, \
+ 0x07, 0xac, 0xf6, 0x01, 0x3c, 0xba, 0x45, 0x7a, \
+ 0x75, 0x25, 0x3a, 0xbd, 0x95, 0x22, 0x9d, 0xc3, \
+ 0xe4, 0x42, 0x31, 0x5c, 0xb5, 0xf4, 0x64, 0x6a, \
+ 0x56, 0x1d, 0xab, 0xc7, 0x6e, 0x96, 0x75, 0xe7, \
+ 0xb3, 0x22, 0x0b, 0x82, 0xac, 0x57, 0x78, 0xdf, \
+ 0x89, 0xc9, 0x8d, 0x28, 0x01, 0x57, 0x06, 0xc5, \
+ 0x4b, 0x61, 0x0b, 0x4d, 0xa1, 0x66, 0xa0, 0x89, \
+ 0xad, 0x19, 0x8f, 0xd8, 0x96, 0x55, 0x22, 0x5f, \
+ 0xca, 0x2e, 0xc1, 0xd7, 0xbd, 0xa1, 0x83, 0x66, \
+ 0x4d, 0x85, 0xcb, 0x01, 0x60, 0x3f, 0xf7, 0xf7, \
+ 0xa3, 0x7a, 0xfa, 0x99, 0xa0, 0x1e, 0x25, 0x90, \
+ 0xd0, 0xd0, 0x3b, 0x54, 0x90, 0x77, 0x94, 0xa6, \
+ 0x88, 0xea, 0xc3, 0x6b, 0xa0, 0x59, 0x5e, 0x69, \
+ 0x89, 0xc9, 0x8d, 0x28, 0x02, 0x78, 0x0b, 0x2b, \
+ 0xab, 0x5b, 0x04, 0x2f, 0x78, 0x15, 0x86, 0x2b, \
+ 0x0f, 0x63, 0xb2, 0xd7, 0xc9, 0xe9, 0xac, 0x0e, \
+ 0xbc, 0x17, 0xe4, 0x19, 0x88, 0xe0, 0xe6, 0x13, \
+ 0xf8, 0x15, 0x08, 0xa7, 0xe1, 0x6e, 0x71, 0x5c, \
+ 0xef, 0x3e, 0xc1, 0x0f, 0x74, 0xdb, 0xdc, 0x52, \
+ 0x9c, 0xfc, 0xe9, 0xa9, 0xf3, 0x0d, 0x52, 0xbc, \
+ 0x0c, 0xe8, 0xba, 0xd1, 0x76, 0x46, 0x87, 0xb5, \
+ 0x89, 0xc9, 0x8d, 0x28, 0x03, 0x30, 0xe6, 0x9d, \
+ 0xa1, 0x2b, 0xa5, 0x9e, 0x3b, 0x86, 0xb3, 0x5f, \
+ 0xe3, 0x81, 0xa6, 0x76, 0x32, 0x9d, 0xf9, 0xc5, \
+ 0x07, 0x93, 0xb3, 0xdf, 0x64, 0xe2, 0x78, 0x9c, \
+ 0x00, 0xc7, 0x86, 0x79, 0xd6, 0x67, 0xa2, 0xfb, \
+ 0xf2, 0x8d, 0xea, 0xe9, 0xc8, 0xfc, 0x43, 0xd2, \
+ 0x0f, 0x2f, 0x7d, 0x9d, 0xd3, 0x8f, 0x9c, 0xdd, \
+ 0xa2, 0x9f, 0x42, 0x76, 0x40, 0xcc, 0x4a, 0xd0, \
+ 0x89, 0xc9, 0x8d, 0x28, 0x04, 0xb4, 0x87, 0x18, \
+ 0x06, 0xc3, 0xc7, 0x89, 0x98, 0x72, 0xcc, 0x1a, \
+ 0xd1, 0xd8, 0x78, 0xb9, 0x75, 0x0b, 0x92, 0xe3, \
+ 0xcc, 0xed, 0x38, 0x39, 0x4b, 0xa9, 0xcf, 0x30, \
+ 0xd6, 0xb5, 0xa1, 0x3f, 0xfa, 0x4f, 0x29, 0x99, \
+ 0xa9, 0x03, 0x77, 0xf6, 0x53, 0xfa, 0xd8, 0x32, \
+ 0xce, 0xf4, 0xf6, 0x0a, 0x3c, 0xe8, 0x9c, 0x3d, \
+ 0xaa, 0xe0, 0x7b, 0x2c, 0xa5, 0x28, 0xe1, 0xdd, \
+ 0x89, 0xc9, 0x8d, 0x28, 0x05, 0x51, 0xbf, 0xe1, \
+ 0xd4, 0xf5, 0x5e, 0x38, 0x2c, 0xec, 0xab, 0xdd, \
+ 0xb8, 0x5c, 0x13, 0x43, 0x62, 0xc2, 0xb6, 0x02, \
+ 0x18, 0xce, 0x9a, 0x62, 0x67, 0x6a, 0xeb, 0x99, \
+ 0xf6, 0x2f, 0xf1, 0xf1, 0xec, 0x3e, 0x74, 0xfa, \
+ 0xf8, 0x16, 0x43, 0xea, 0x1e, 0xef, 0x5d, 0x37, \
+ 0x6c, 0x13, 0xf9, 0x7f, 0x65, 0x09, 0xab, 0x60, \
+ 0x38, 0xda, 0x0f, 0xe7, 0xfa, 0x9e, 0x17, 0x10, \
+ 0x89, 0xc9, 0x8d, 0x28, 0x06, 0xdc, 0x4c, 0x4d, \
+ 0xae, 0x5c, 0xb4, 0x0d, 0x6b, 0x05, 0x6d, 0x25, \
+ 0x3f, 0x78, 0x5d, 0xf3, 0x34, 0x33, 0xa4, 0x89, \
+ 0x34, 0x0e, 0x88, 0x66, 0x40, 0x57, 0x6b, 0x34, \
+ 0x83, 0xfd, 0x39, 0xe7, 0xfb, 0x84, 0x09, 0xb3, \
+ 0x16, 0x8f, 0x80, 0xdf, 0x1b, 0xe0, 0x02, 0x4c, \
+ 0xde, 0x31, 0x2a, 0x32, 0x58, 0x5b, 0xa3, 0x23, \
+ 0x8e, 0x2a, 0xa6, 0xaf, 0x03, 0x19, 0x02, 0x7a, \
+ 0x89, 0xc9, 0x8d, 0x28, 0x07, 0xf8, 0xbf, 0xa6, \
+ 0xad, 0xf9, 0xd1, 0xdc, 0xbd, 0x6e, 0xb3, 0xc1, \
+ 0xfb, 0x65, 0xd8, 0x5f, 0x2e, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_NFC_INIT \
+ 0x55, 0x32, 0x46, 0x5f, 0x56, 0x32, 0x90, 0x00
+
+#define WIREDATA_CTAP_NFC_MSG \
+ 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00
+
+#define WIREDATA_CTAP_EXTENDED_APDU \
+ 0x00, 0xa4, 0x04, 0x00, 0x00, 0x02, 0x00, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, \
+ 0x00
+
+#endif /* _WIREDATA_FIDO2_H */
diff --git a/fuzz/wiredata_u2f.h b/fuzz/wiredata_u2f.h
new file mode 100644
index 0000000..3be22d3
--- /dev/null
+++ b/fuzz/wiredata_u2f.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2020 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
+ */
+
+#ifndef _WIREDATA_U2F_H
+#define _WIREDATA_U2F_H
+
+#define WIREDATA_CTAP_U2F_6985 \
+ 0x00, 0x00, 0x99, 0x01, 0x83, 0x00, 0x02, 0x69, \
+ 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_U2F_AUTH \
+ 0x00, 0x00, 0x99, 0x01, 0x83, 0x00, 0x4e, 0x01, \
+ 0x00, 0x00, 0x00, 0x2c, 0x30, 0x45, 0x02, 0x20, \
+ 0x1c, 0xf5, 0x7c, 0xf6, 0xde, 0xbe, 0xe9, 0x86, \
+ 0xee, 0x97, 0xb7, 0x64, 0xa3, 0x4e, 0x7a, 0x70, \
+ 0x85, 0xd0, 0x66, 0xf9, 0xf0, 0xcd, 0x04, 0x5d, \
+ 0x97, 0xf2, 0x3c, 0x22, 0xe3, 0x0e, 0x61, 0xc8, \
+ 0x02, 0x21, 0x00, 0x97, 0xef, 0xae, 0x36, 0xe6, \
+ 0x17, 0x9f, 0x5e, 0x2d, 0xd7, 0x8c, 0x34, 0xa7, \
+ 0x00, 0x00, 0x99, 0x01, 0x00, 0xa1, 0xe9, 0xfb, \
+ 0x8f, 0x86, 0x8c, 0xe3, 0x1e, 0xde, 0x3f, 0x4e, \
+ 0x1b, 0xe1, 0x2f, 0x8f, 0x2f, 0xca, 0x42, 0x26, \
+ 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#define WIREDATA_CTAP_U2F_REGISTER \
+ 0x00, 0x00, 0x99, 0x01, 0x83, 0x03, 0x1e, 0x05, \
+ 0x04, 0x9f, 0xa0, 0xf9, 0x0d, 0x4c, 0xf4, 0xae, \
+ 0x96, 0x3c, 0xb7, 0x46, 0xb7, 0x5c, 0x9d, 0x8b, \
+ 0x48, 0x19, 0xdf, 0xc4, 0xad, 0xea, 0xb2, 0x70, \
+ 0x58, 0x72, 0xd9, 0xce, 0x75, 0xf5, 0xe6, 0x8e, \
+ 0x0f, 0x9c, 0x0e, 0x2e, 0x62, 0x3e, 0x91, 0xd3, \
+ 0x7b, 0x97, 0x46, 0x60, 0xb9, 0x57, 0x13, 0x97, \
+ 0x26, 0xae, 0x0f, 0xb3, 0x8f, 0x2e, 0x9b, 0x3f, \
+ 0x00, 0x00, 0x99, 0x01, 0x00, 0xa5, 0x55, 0xec, \
+ 0x8c, 0x25, 0x7c, 0x65, 0xb7, 0x09, 0x40, 0x48, \
+ 0xae, 0xa8, 0xcb, 0xa1, 0x91, 0xac, 0x40, 0x24, \
+ 0xf2, 0x34, 0x6e, 0x3a, 0x8f, 0xa5, 0xb7, 0x48, \
+ 0x54, 0x6e, 0xfb, 0xf4, 0x37, 0x88, 0x69, 0x79, \
+ 0x6f, 0x12, 0xc1, 0x32, 0xdf, 0x15, 0x5d, 0x6e, \
+ 0x82, 0x54, 0xc0, 0x6e, 0x56, 0x4f, 0x3a, 0x9c, \
+ 0xc3, 0x96, 0x7a, 0xde, 0xa5, 0xfe, 0xec, 0xd1, \
+ 0x00, 0x00, 0x99, 0x01, 0x01, 0x5a, 0x21, 0x85, \
+ 0x0e, 0x25, 0x7b, 0x8d, 0x6e, 0x1d, 0x32, 0x29, \
+ 0xdb, 0x21, 0xb0, 0xa3, 0x30, 0x82, 0x02, 0x4f, \
+ 0x30, 0x82, 0x01, 0x37, 0xa0, 0x03, 0x02, 0x01, \
+ 0x02, 0x02, 0x04, 0x2a, 0xd9, 0x6a, 0xf3, 0x30, \
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, \
+ 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x2e, \
+ 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, \
+ 0x00, 0x00, 0x99, 0x01, 0x02, 0x03, 0x13, 0x23, \
+ 0x59, 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x55, \
+ 0x32, 0x46, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, \
+ 0x43, 0x41, 0x20, 0x53, 0x65, 0x72, 0x69, 0x61, \
+ 0x6c, 0x20, 0x34, 0x35, 0x37, 0x32, 0x30, 0x30, \
+ 0x36, 0x33, 0x31, 0x30, 0x20, 0x17, 0x0d, 0x31, \
+ 0x34, 0x30, 0x38, 0x30, 0x31, 0x30, 0x30, 0x30, \
+ 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, \
+ 0x00, 0x00, 0x99, 0x01, 0x03, 0x35, 0x30, 0x30, \
+ 0x39, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, \
+ 0x30, 0x5a, 0x30, 0x31, 0x31, 0x2f, 0x30, 0x2d, \
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x26, 0x59, \
+ 0x75, 0x62, 0x69, 0x63, 0x6f, 0x20, 0x55, 0x32, \
+ 0x46, 0x20, 0x45, 0x45, 0x20, 0x53, 0x65, 0x72, \
+ 0x69, 0x61, 0x6c, 0x20, 0x32, 0x33, 0x39, 0x32, \
+ 0x35, 0x37, 0x33, 0x34, 0x35, 0x31, 0x36, 0x35, \
+ 0x00, 0x00, 0x99, 0x01, 0x04, 0x35, 0x30, 0x33, \
+ 0x38, 0x37, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, \
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, \
+ 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, \
+ 0x07, 0x03, 0x42, 0x00, 0x04, 0x2f, 0xe1, 0xa2, \
+ 0x3e, 0xbf, 0xa5, 0x5b, 0x3e, 0x46, 0x1d, 0x59, \
+ 0xa4, 0x35, 0x22, 0xd7, 0x97, 0x48, 0x98, 0x1c, \
+ 0xba, 0x6d, 0x28, 0x9a, 0x98, 0xf1, 0xbd, 0x7d, \
+ 0x00, 0x00, 0x99, 0x01, 0x05, 0xff, 0x65, 0x66, \
+ 0x80, 0xdb, 0xbb, 0xed, 0xbc, 0x2b, 0xae, 0x60, \
+ 0x7e, 0x6e, 0xf7, 0x72, 0xf5, 0x76, 0xb0, 0x4d, \
+ 0x54, 0xc4, 0xe5, 0xf3, 0x2f, 0x59, 0x6f, 0x26, \
+ 0xe6, 0x11, 0x15, 0xc7, 0x27, 0x2c, 0xf6, 0xca, \
+ 0x75, 0x94, 0xa3, 0x3b, 0x30, 0x39, 0x30, 0x22, \
+ 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, \
+ 0xc4, 0x0a, 0x02, 0x04, 0x15, 0x31, 0x2e, 0x33, \
+ 0x00, 0x00, 0x99, 0x01, 0x06, 0x2e, 0x36, 0x2e, \
+ 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x31, \
+ 0x34, 0x38, 0x32, 0x2e, 0x31, 0x2e, 0x32, 0x30, \
+ 0x13, 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01, \
+ 0x82, 0xe5, 0x1c, 0x02, 0x01, 0x01, 0x04, 0x04, \
+ 0x03, 0x02, 0x04, 0x30, 0x30, 0x0d, 0x06, 0x09, \
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, \
+ 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, \
+ 0x00, 0x00, 0x99, 0x01, 0x07, 0x85, 0x6a, 0xfa, \
+ 0x8b, 0xcf, 0x4f, 0x3f, 0x62, 0x5f, 0x29, 0x1b, \
+ 0xc1, 0x15, 0x8e, 0x3c, 0x7e, 0xbd, 0x25, 0x52, \
+ 0xbc, 0xf7, 0x57, 0x07, 0x53, 0xf5, 0x12, 0x1d, \
+ 0xa6, 0xa5, 0x4d, 0x24, 0xcc, 0xcf, 0xae, 0x27, \
+ 0xce, 0xd6, 0xab, 0x31, 0x12, 0x8c, 0x29, 0x7e, \
+ 0x5b, 0x5b, 0x89, 0x05, 0xdd, 0xa0, 0x20, 0x17, \
+ 0x93, 0x1f, 0x1f, 0x5f, 0x59, 0x25, 0x93, 0x59, \
+ 0x00, 0x00, 0x99, 0x01, 0x08, 0x51, 0xfc, 0x00, \
+ 0x4b, 0xcb, 0xe2, 0x0a, 0xdd, 0x7d, 0x8d, 0x05, \
+ 0x2f, 0x95, 0x43, 0xb3, 0x49, 0x6c, 0x15, 0xb8, \
+ 0x31, 0x0e, 0x10, 0xcb, 0xd9, 0xbb, 0x05, 0x38, \
+ 0x27, 0x4f, 0x58, 0x3e, 0xad, 0x1f, 0x45, 0x12, \
+ 0x88, 0xc3, 0xea, 0x76, 0xd0, 0x70, 0xad, 0x44, \
+ 0xe5, 0x3a, 0xfe, 0xa8, 0xf2, 0x2d, 0x1f, 0x73, \
+ 0x62, 0x5f, 0xf2, 0xd5, 0x89, 0xfe, 0x30, 0xdf, \
+ 0x00, 0x00, 0x99, 0x01, 0x09, 0x26, 0x62, 0xcb, \
+ 0x7c, 0xbb, 0x7c, 0x99, 0x61, 0x80, 0xad, 0xcf, \
+ 0xa9, 0x8a, 0x4d, 0x01, 0x2c, 0xf3, 0x13, 0x46, \
+ 0xcd, 0x11, 0x74, 0x6a, 0x58, 0x48, 0xe8, 0xbe, \
+ 0xed, 0xf3, 0xe3, 0x0c, 0xcb, 0xd9, 0xc1, 0xdd, \
+ 0x22, 0x16, 0x71, 0xb2, 0x83, 0x88, 0x61, 0xf6, \
+ 0x5a, 0x45, 0x36, 0x23, 0xb5, 0x18, 0xd5, 0x56, \
+ 0x7f, 0xa8, 0xf0, 0xa3, 0xce, 0x10, 0x5d, 0xf4, \
+ 0x00, 0x00, 0x99, 0x01, 0x0a, 0xf1, 0x39, 0x53, \
+ 0xe1, 0x14, 0xea, 0x59, 0xe0, 0xa7, 0xf2, 0xfe, \
+ 0x66, 0x88, 0x67, 0x43, 0x2e, 0x52, 0xfd, 0x6a, \
+ 0x2f, 0x64, 0xf7, 0x3c, 0x48, 0xcd, 0x9b, 0x38, \
+ 0xf2, 0xdf, 0xba, 0x2c, 0x7a, 0x4b, 0x3b, 0x11, \
+ 0x28, 0xdf, 0x26, 0xd6, 0x6a, 0x24, 0xf8, 0x95, \
+ 0xdd, 0xa0, 0xb6, 0x11, 0x80, 0xf4, 0x14, 0x4f, \
+ 0x6b, 0x70, 0x75, 0xc3, 0x18, 0xa4, 0x9a, 0xe0, \
+ 0x00, 0x00, 0x99, 0x01, 0x0b, 0x8b, 0x58, 0xd3, \
+ 0x6a, 0xdb, 0x1e, 0x30, 0x53, 0x67, 0x2b, 0x17, \
+ 0xc5, 0xa1, 0x9f, 0x7f, 0x0a, 0x22, 0xf1, 0x0e, \
+ 0x94, 0x30, 0x44, 0x02, 0x20, 0x07, 0x5c, 0x4f, \
+ 0xd2, 0x83, 0xb6, 0x9f, 0x0a, 0x4a, 0x4d, 0x4b, \
+ 0x08, 0x35, 0xeb, 0xc0, 0x7e, 0x4a, 0x14, 0x2e, \
+ 0xc7, 0x8c, 0xd6, 0x64, 0x2f, 0xd3, 0x1e, 0xcc, \
+ 0xb5, 0xe8, 0x42, 0xea, 0xf6, 0x02, 0x20, 0x6b, \
+ 0x00, 0x00, 0x99, 0x01, 0x0c, 0x5a, 0xba, 0x4a, \
+ 0xc8, 0xd7, 0x89, 0xcc, 0x77, 0xe6, 0xb9, 0xa3, \
+ 0x34, 0xea, 0x06, 0x85, 0x72, 0xc6, 0x28, 0xa8, \
+ 0x7a, 0xaa, 0x19, 0x88, 0x34, 0xbb, 0xdc, 0x64, \
+ 0x90, 0x0a, 0xdb, 0x39, 0x90, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+#endif /* !_WIREDATA_U2F_H */
diff --git a/fuzz/wrap.c b/fuzz/wrap.c
new file mode 100644
index 0000000..6f40ea1
--- /dev/null
+++ b/fuzz/wrap.c
@@ -0,0 +1,700 @@
+/*
+ * 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 <sys/types.h>
+#include <sys/random.h>
+#include <sys/socket.h>
+
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+#include <cbor.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <zlib.h>
+
+#include "mutator_aux.h"
+
+extern int prng_up;
+
+int fuzz_save_corpus;
+
+/*
+ * Build wrappers around functions of interest, and have them fail
+ * in a pseudo-random manner. A uniform probability of 0.25% (1/400)
+ * allows for a depth of log(0.5)/log(399/400) > 276 operations
+ * before simulated errors become statistically more likely.
+ */
+
+#define WRAP(type, name, args, retval, param, prob) \
+extern type __wrap_##name args; \
+extern type __real_##name args; \
+type __wrap_##name args { \
+ if (prng_up && uniform_random(400) < (prob)) { \
+ return (retval); \
+ } \
+ \
+ return (__real_##name param); \
+}
+
+WRAP(void *,
+ malloc,
+ (size_t size),
+ NULL,
+ (size),
+ 1
+)
+
+WRAP(void *,
+ calloc,
+ (size_t nmemb, size_t size),
+ NULL,
+ (nmemb, size),
+ 1
+)
+
+WRAP(void *,
+ realloc,
+ (void *ptr, size_t size),
+ NULL,
+ (ptr, size),
+ 1
+)
+
+WRAP(char *,
+ strdup,
+ (const char *s),
+ NULL,
+ (s),
+ 1
+)
+
+WRAP(ssize_t,
+ getrandom,
+ (void *buf, size_t buflen, unsigned int flags),
+ -1,
+ (buf, buflen, flags),
+ 1
+)
+
+WRAP(int,
+ EVP_Cipher,
+ (EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
+ unsigned int inl),
+ -1,
+ (ctx, out, in, inl),
+ 1
+)
+
+WRAP(int,
+ EVP_CIPHER_CTX_ctrl,
+ (EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr),
+ 0,
+ (ctx, type, arg, ptr),
+ 1
+)
+
+WRAP(EVP_CIPHER_CTX *,
+ EVP_CIPHER_CTX_new,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(int,
+ EVP_CipherInit,
+ (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+ const unsigned char *key, const unsigned char *iv, int enc),
+ 0,
+ (ctx, cipher, key, iv, enc),
+ 1
+)
+
+WRAP(RSA *,
+ EVP_PKEY_get0_RSA,
+ (EVP_PKEY *pkey),
+ NULL,
+ (pkey),
+ 1
+)
+
+WRAP(EC_KEY *,
+ EVP_PKEY_get0_EC_KEY,
+ (EVP_PKEY *pkey),
+ NULL,
+ (pkey),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_get_raw_public_key,
+ (const EVP_PKEY *pkey, unsigned char *pub, size_t *len),
+ 0,
+ (pkey, pub, len),
+ 1
+)
+
+WRAP(EVP_MD_CTX *,
+ EVP_MD_CTX_new,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(int,
+ EVP_DigestVerifyInit,
+ (EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e,
+ EVP_PKEY *pkey),
+ 0,
+ (ctx, pctx, type, e, pkey),
+ 1
+)
+
+WRAP(int,
+ EVP_DigestInit_ex,
+ (EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl),
+ 0,
+ (ctx, type, impl),
+ 1
+)
+
+WRAP(int,
+ EVP_DigestUpdate,
+ (EVP_MD_CTX *ctx, const void *data, size_t count),
+ 0,
+ (ctx, data, count),
+ 1
+)
+
+WRAP(int,
+ EVP_DigestFinal_ex,
+ (EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize),
+ 0,
+ (ctx, md, isize),
+ 1
+)
+
+WRAP(BIGNUM *,
+ BN_bin2bn,
+ (const unsigned char *s, int len, BIGNUM *ret),
+ NULL,
+ (s, len, ret),
+ 1
+)
+
+WRAP(int,
+ BN_bn2bin,
+ (const BIGNUM *a, unsigned char *to),
+ -1,
+ (a, to),
+ 1
+)
+
+WRAP(BIGNUM *,
+ BN_CTX_get,
+ (BN_CTX *ctx),
+ NULL,
+ (ctx),
+ 1
+)
+
+WRAP(BN_CTX *,
+ BN_CTX_new,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(BIGNUM *,
+ BN_new,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(RSA *,
+ RSA_new,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(int,
+ RSA_set0_key,
+ (RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d),
+ 0,
+ (r, n, e, d),
+ 1
+)
+
+WRAP(int,
+ RSA_pkey_ctx_ctrl,
+ (EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2),
+ -1,
+ (ctx, optype, cmd, p1, p2),
+ 1
+)
+
+WRAP(EC_KEY *,
+ EC_KEY_new_by_curve_name,
+ (int nid),
+ NULL,
+ (nid),
+ 1
+)
+
+WRAP(const EC_GROUP *,
+ EC_KEY_get0_group,
+ (const EC_KEY *key),
+ NULL,
+ (key),
+ 1
+)
+
+WRAP(const BIGNUM *,
+ EC_KEY_get0_private_key,
+ (const EC_KEY *key),
+ NULL,
+ (key),
+ 1
+)
+
+WRAP(EC_POINT *,
+ EC_POINT_new,
+ (const EC_GROUP *group),
+ NULL,
+ (group),
+ 1
+)
+
+WRAP(int,
+ EC_POINT_get_affine_coordinates_GFp,
+ (const EC_GROUP *group, const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx),
+ 0,
+ (group, p, x, y, ctx),
+ 1
+)
+
+WRAP(EVP_PKEY *,
+ EVP_PKEY_new,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_assign,
+ (EVP_PKEY *pkey, int type, void *key),
+ 0,
+ (pkey, type, key),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_keygen_init,
+ (EVP_PKEY_CTX *ctx),
+ 0,
+ (ctx),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_keygen,
+ (EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey),
+ 0,
+ (ctx, ppkey),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_paramgen_init,
+ (EVP_PKEY_CTX *ctx),
+ 0,
+ (ctx),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_paramgen,
+ (EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey),
+ 0,
+ (ctx, ppkey),
+ 1
+)
+
+WRAP(EVP_PKEY *,
+ EVP_PKEY_new_raw_public_key,
+ (int type, ENGINE *e, const unsigned char *key, size_t keylen),
+ NULL,
+ (type, e, key, keylen),
+ 1
+)
+
+WRAP(EVP_PKEY_CTX *,
+ EVP_PKEY_CTX_new,
+ (EVP_PKEY *pkey, ENGINE *e),
+ NULL,
+ (pkey, e),
+ 1
+)
+
+WRAP(EVP_PKEY_CTX *,
+ EVP_PKEY_CTX_new_id,
+ (int id, ENGINE *e),
+ NULL,
+ (id, e),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_derive,
+ (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen),
+ 0,
+ (ctx, key, pkeylen),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_derive_init,
+ (EVP_PKEY_CTX *ctx),
+ 0,
+ (ctx),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_derive_set_peer,
+ (EVP_PKEY_CTX *ctx, EVP_PKEY *peer),
+ 0,
+ (ctx, peer),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_verify_init,
+ (EVP_PKEY_CTX *ctx),
+ 0,
+ (ctx),
+ 1
+)
+
+WRAP(int,
+ EVP_PKEY_CTX_ctrl,
+ (EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2),
+ -1,
+ (ctx, keytype, optype, cmd, p1, p2),
+ 1
+)
+
+WRAP(const EVP_MD *,
+ EVP_sha1,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(const EVP_MD *,
+ EVP_sha256,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(const EVP_CIPHER *,
+ EVP_aes_256_cbc,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(const EVP_CIPHER *,
+ EVP_aes_256_gcm,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(unsigned char *,
+ HMAC,
+ (const EVP_MD *evp_md, const void *key, int key_len,
+ const unsigned char *d, int n, unsigned char *md,
+ unsigned int *md_len),
+ NULL,
+ (evp_md, key, key_len, d, n, md, md_len),
+ 1
+)
+
+WRAP(HMAC_CTX *,
+ HMAC_CTX_new,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(int,
+ HMAC_Init_ex,
+ (HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md,
+ ENGINE *impl),
+ 0,
+ (ctx, key, key_len, md, impl),
+ 1
+)
+
+WRAP(int,
+ HMAC_Update,
+ (HMAC_CTX *ctx, const unsigned char *data, int len),
+ 0,
+ (ctx, data, len),
+ 1
+)
+
+WRAP(int,
+ HMAC_Final,
+ (HMAC_CTX *ctx, unsigned char *md, unsigned int *len),
+ 0,
+ (ctx, md, len),
+ 1
+)
+
+WRAP(unsigned char *,
+ SHA1,
+ (const unsigned char *d, size_t n, unsigned char *md),
+ NULL,
+ (d, n, md),
+ 1
+)
+
+WRAP(unsigned char *,
+ SHA256,
+ (const unsigned char *d, size_t n, unsigned char *md),
+ NULL,
+ (d, n, md),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_build_string,
+ (const char *val),
+ NULL,
+ (val),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_build_bytestring,
+ (cbor_data handle, size_t length),
+ NULL,
+ (handle, length),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_build_bool,
+ (bool value),
+ NULL,
+ (value),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_build_negint8,
+ (uint8_t value),
+ NULL,
+ (value),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_build_negint16,
+ (uint16_t value),
+ NULL,
+ (value),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_load,
+ (cbor_data source, size_t source_size, struct cbor_load_result *result),
+ NULL,
+ (source, source_size, result),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_build_uint8,
+ (uint8_t value),
+ NULL,
+ (value),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_build_uint16,
+ (uint16_t value),
+ NULL,
+ (value),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_build_uint32,
+ (uint32_t value),
+ NULL,
+ (value),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_build_uint64,
+ (uint64_t value),
+ NULL,
+ (value),
+ 1
+)
+
+WRAP(struct cbor_pair *,
+ cbor_map_handle,
+ (const cbor_item_t *item),
+ NULL,
+ (item),
+ 1
+)
+
+WRAP(cbor_item_t **,
+ cbor_array_handle,
+ (const cbor_item_t *item),
+ NULL,
+ (item),
+ 1
+)
+
+WRAP(bool,
+ cbor_array_push,
+ (cbor_item_t *array, cbor_item_t *pushee),
+ false,
+ (array, pushee),
+ 1
+)
+
+WRAP(bool,
+ cbor_map_add,
+ (cbor_item_t *item, struct cbor_pair pair),
+ false,
+ (item, pair),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_new_definite_map,
+ (size_t size),
+ NULL,
+ (size),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_new_definite_array,
+ (size_t size),
+ NULL,
+ (size),
+ 1
+)
+
+WRAP(cbor_item_t *,
+ cbor_new_definite_bytestring,
+ (void),
+ NULL,
+ (),
+ 1
+)
+
+WRAP(size_t,
+ cbor_serialize_alloc,
+ (const cbor_item_t *item, cbor_mutable_data *buffer,
+ size_t *buffer_size),
+ 0,
+ (item, buffer, buffer_size),
+ 1
+)
+
+WRAP(int,
+ fido_tx,
+ (fido_dev_t *d, uint8_t cmd, const void *buf, size_t count, int *ms),
+ -1,
+ (d, cmd, buf, count, ms),
+ 1
+)
+
+WRAP(int,
+ bind,
+ (int sockfd, const struct sockaddr *addr, socklen_t addrlen),
+ -1,
+ (sockfd, addr, addrlen),
+ 1
+)
+
+WRAP(int,
+ deflateInit2_,
+ (z_streamp strm, int level, int method, int windowBits, int memLevel,
+ int strategy, const char *version, int stream_size),
+ Z_STREAM_ERROR,
+ (strm, level, method, windowBits, memLevel, strategy, version,
+ stream_size),
+ 1
+)
+
+int __wrap_deflate(z_streamp, int);
+int __real_deflate(z_streamp, int);
+
+int
+__wrap_deflate(z_streamp strm, int flush)
+{
+ if (prng_up && uniform_random(400) < 1) {
+ return Z_BUF_ERROR;
+ }
+ /* should never happen, but we check for it */
+ if (prng_up && uniform_random(400) < 1) {
+ strm->avail_out = UINT_MAX;
+ return Z_STREAM_END;
+ }
+
+ return __real_deflate(strm, flush);
+}
+
+int __wrap_asprintf(char **, const char *, ...);
+
+int
+__wrap_asprintf(char **strp, const char *fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ if (prng_up && uniform_random(400) < 1) {
+ *strp = (void *)0xdeadbeef;
+ return -1;
+ }
+
+ va_start(ap, fmt);
+ r = vasprintf(strp, fmt, ap);
+ va_end(ap);
+
+ return r;
+}
diff --git a/fuzz/wrapped.sym b/fuzz/wrapped.sym
new file mode 100644
index 0000000..219a0d8
--- /dev/null
+++ b/fuzz/wrapped.sym
@@ -0,0 +1,102 @@
+asprintf
+bind
+BN_bin2bn
+BN_bn2bin
+BN_CTX_get
+BN_CTX_new
+BN_new
+calloc
+cbor_array_handle
+cbor_array_push
+cbor_build_bool
+cbor_build_bytestring
+cbor_build_negint16
+cbor_build_negint8
+cbor_build_string
+cbor_build_uint16
+cbor_build_uint32
+cbor_build_uint64
+cbor_build_uint8
+cbor_load
+cbor_map_add
+cbor_map_handle
+cbor_new_definite_array
+cbor_new_definite_bytestring
+cbor_new_definite_map
+cbor_serialize_alloc
+clock_gettime
+deflate
+deflateInit2_
+EC_KEY_get0_group
+EC_KEY_get0_private_key
+EC_KEY_new_by_curve_name
+EC_POINT_get_affine_coordinates_GFp
+EC_POINT_new
+EVP_aes_256_cbc
+EVP_aes_256_gcm
+EVP_Cipher
+EVP_CIPHER_CTX_ctrl
+EVP_CIPHER_CTX_new
+EVP_CipherInit
+EVP_DigestFinal_ex
+EVP_DigestInit_ex
+EVP_DigestUpdate
+EVP_DigestVerifyInit
+EVP_MD_CTX_new
+EVP_PKEY_assign
+EVP_PKEY_CTX_ctrl
+EVP_PKEY_CTX_new
+EVP_PKEY_CTX_new_id
+EVP_PKEY_derive
+EVP_PKEY_derive_init
+EVP_PKEY_derive_set_peer
+EVP_PKEY_get0_EC_KEY
+EVP_PKEY_get0_RSA
+EVP_PKEY_get_raw_public_key
+EVP_PKEY_keygen
+EVP_PKEY_keygen_init
+EVP_PKEY_new
+EVP_PKEY_new_raw_public_key
+EVP_PKEY_paramgen
+EVP_PKEY_paramgen_init
+EVP_PKEY_verify_init
+EVP_sha1
+EVP_sha256
+fido_tx
+getrandom
+HMAC
+HMAC_CTX_new
+HMAC_Final
+HMAC_Init_ex
+HMAC_Update
+ioctl
+malloc
+realloc
+RSA_new
+RSA_pkey_ctx_ctrl
+RSA_set0_key
+SCardConnect
+SCardDisconnect
+SCardEstablishContext
+SCardListReaders
+SCardReleaseContext
+SCardTransmit
+SHA1
+SHA256
+strdup
+udev_device_get_devnode
+udev_device_get_parent_with_subsystem_devtype
+udev_device_get_sysattr_value
+udev_device_get_sysnum
+udev_device_new_from_syspath
+udev_device_unref
+udev_enumerate_add_match_subsystem
+udev_enumerate_get_list_entry
+udev_enumerate_new
+udev_enumerate_scan_devices
+udev_enumerate_unref
+udev_list_entry_get_name
+udev_list_entry_get_next
+udev_new
+udev_unref
+usleep