Add files via upload

This commit is contained in:
Token2
2024-05-24 11:47:45 +02:00
committed by GitHub
parent 04bcffc0d2
commit 2b182947ce
46 changed files with 10879 additions and 0 deletions

59
examples/CMakeLists.txt Normal file
View File

@@ -0,0 +1,59 @@
# Copyright (c) 2018 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/clock_gettime.c
../openbsd-compat/getopt_long.c
../openbsd-compat/strlcat.c
../openbsd-compat/strlcpy.c
)
if(WIN32 AND BUILD_SHARED_LIBS AND NOT CYGWIN AND NOT MSYS)
list(APPEND COMPAT_SOURCES ../openbsd-compat/posix_win.c)
endif()
# enable -Wconversion -Wsign-conversion
if(NOT MSVC)
set_source_files_properties(assert.c cred.c info.c manifest.c reset.c
retries.c setpin.c util.c PROPERTIES COMPILE_FLAGS
"-Wconversion -Wsign-conversion")
endif()
# manifest
add_executable(manifest manifest.c ${COMPAT_SOURCES})
target_link_libraries(manifest ${_FIDO2_LIBRARY})
# info
add_executable(info info.c ${COMPAT_SOURCES})
target_link_libraries(info ${_FIDO2_LIBRARY})
# reset
add_executable(reset reset.c util.c ${COMPAT_SOURCES})
target_link_libraries(reset ${_FIDO2_LIBRARY})
# cred
add_executable(cred cred.c util.c ${COMPAT_SOURCES})
target_link_libraries(cred ${_FIDO2_LIBRARY})
# assert
add_executable(assert assert.c util.c ${COMPAT_SOURCES})
target_link_libraries(assert ${_FIDO2_LIBRARY})
# setpin
add_executable(setpin setpin.c ${COMPAT_SOURCES})
target_link_libraries(setpin ${_FIDO2_LIBRARY})
# retries
add_executable(retries retries.c ${COMPAT_SOURCES})
target_link_libraries(retries ${_FIDO2_LIBRARY})
# select
add_executable(select select.c ${COMPAT_SOURCES})
target_link_libraries(select ${_FIDO2_LIBRARY})
if(MINGW)
# needed for nanosleep() in mingw
target_link_libraries(select winpthread)
endif()

100
examples/README.adoc Normal file
View File

@@ -0,0 +1,100 @@
= Examples
=== Definitions
The following definitions are used in the description below:
- <device>
The file system path or subsystem-specific identification string of a
FIDO device.
- <pin>, [oldpin]
Strings passed directly in the executed command's argument vector.
- <cred_id>
The file system path of a file containing a FIDO credential ID in
binary representation.
- <pubkey>
The file system path of a file containing a public key in PEM format.
- <blobkey>
A credential's associated CTAP 2.1 "largeBlob" symmetric key.
=== Description
The following examples are provided:
- manifest
Prints a list of configured FIDO devices.
- info <device>
Prints information about <device>.
- reset <device>
Performs a factory reset on <device>.
- setpin <pin> [oldpin] <device>
Configures <pin> as the new PIN of <device>. If [oldpin] is provided,
the device's PIN is changed from [oldpin] to <pin>.
- cred [-t es256|es384|rs256|eddsa] [-k pubkey] [-ei cred_id] [-P pin]
[-T seconds] [-b blobkey] [-hruv] [-c cred_protect] <device>
Creates a new credential on <device> and verify that the credential
was signed by the authenticator. The device's attestation certificate
is not verified. If option -k is specified, the credential's public
key is stored in <pubkey>. If option -i is specified, the credential
ID is stored in <cred_id>. The -e option may be used to add <cred_id>
to the list of excluded credentials. If option -h is specified,
the hmac-secret FIDO2 extension is enabled on the generated
credential. If option -r is specified, the generated credential
will involve a resident key. User verification may be requested
through the -v option. If option -u is specified, the credential
is generated using U2F (CTAP1) instead of FIDO2 (CTAP2) commands.
The -T option may be used to enforce a timeout of <seconds>. If the
option -b is specified, the credential's "largeBlob" key is stored in
<blobkey>. If the option -c is specified the the generated credential
will be bound by the specified protection policy.
- assert [-t es256|es384|rs256|eddsa] [-a cred_id] [-h hmac_secret] [-P pin]
[-s hmac_salt] [-T seconds] [-b blobkey] [-puv] <pubkey> <device>
Asks <device> for a FIDO2 assertion corresponding to [cred_id],
which may be omitted for resident keys. The obtained assertion
is verified using <pubkey>. The -p option requests that the user
be present and checks whether the user presence bit was signed by the
authenticator. The -v option requests user verification and checks
whether the user verification bit was signed by the authenticator.
If option -u is specified, the assertion is generated using
U2F (CTAP1) instead of FIDO2 (CTAP2) commands. If option -s is
specified, a FIDO2 hmac-secret is requested from the authenticator,
and the contents of <hmac_salt> are used as the salt. If option -h
is specified, the resulting hmac-secret is stored in <hmac_secret>.
The -T option may be used to enforce a timeout of <seconds>. If the
option -b specified, the credential's "largeBlob" key is stored in
<blobkey>.
- retries <device>
Get the number of PIN attempts left on <device> before lockout.
- select
Enumerates available FIDO devices and, if more than one is present,
simultaneously requests touch on all of them, printing information
about the device touched.
Debugging is possible through the use of the FIDO_DEBUG environment variable.
If set, libfido2 will produce a log of its transactions with the authenticator.
Additionally, an example of a WebAuthn client using libfido2 is available at
https://github.com/martelletto/fido2-webauthn-client.

349
examples/assert.c Normal file
View File

@@ -0,0 +1,349 @@
/*
* Copyright (c) 2018-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 <fido.h>
#include <fido/es256.h>
#include <fido/es384.h>
#include <fido/rs256.h>
#include <fido/eddsa.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "../openbsd-compat/openbsd-compat.h"
#include "extern.h"
static const unsigned char cd[32] = {
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,
};
static void
usage(void)
{
fprintf(stderr, "usage: assert [-t es256|es384|rs256|eddsa] "
"[-a cred_id] [-h hmac_secret] [-s hmac_salt] [-P pin] "
"[-T seconds] [-b blobkey] [-puv] <pubkey> <device>\n");
exit(EXIT_FAILURE);
}
static void
verify_assert(int type, const unsigned char *authdata_ptr, size_t authdata_len,
const unsigned char *sig_ptr, size_t sig_len, bool up, bool uv, int ext,
const char *key)
{
fido_assert_t *assert = NULL;
EC_KEY *ec = NULL;
RSA *rsa = NULL;
EVP_PKEY *eddsa = 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;
void *pk;
int r;
/* credential pubkey */
switch (type) {
case COSE_ES256:
if ((ec = read_ec_pubkey(key)) == NULL)
errx(1, "read_ec_pubkey");
if ((es256_pk = es256_pk_new()) == NULL)
errx(1, "es256_pk_new");
if (es256_pk_from_EC_KEY(es256_pk, ec) != FIDO_OK)
errx(1, "es256_pk_from_EC_KEY");
pk = es256_pk;
EC_KEY_free(ec);
ec = NULL;
break;
case COSE_ES384:
if ((ec = read_ec_pubkey(key)) == NULL)
errx(1, "read_ec_pubkey");
if ((es384_pk = es384_pk_new()) == NULL)
errx(1, "es384_pk_new");
if (es384_pk_from_EC_KEY(es384_pk, ec) != FIDO_OK)
errx(1, "es384_pk_from_EC_KEY");
pk = es384_pk;
EC_KEY_free(ec);
ec = NULL;
break;
case COSE_RS256:
if ((rsa = read_rsa_pubkey(key)) == NULL)
errx(1, "read_rsa_pubkey");
if ((rs256_pk = rs256_pk_new()) == NULL)
errx(1, "rs256_pk_new");
if (rs256_pk_from_RSA(rs256_pk, rsa) != FIDO_OK)
errx(1, "rs256_pk_from_RSA");
pk = rs256_pk;
RSA_free(rsa);
rsa = NULL;
break;
case COSE_EDDSA:
if ((eddsa = read_eddsa_pubkey(key)) == NULL)
errx(1, "read_eddsa_pubkey");
if ((eddsa_pk = eddsa_pk_new()) == NULL)
errx(1, "eddsa_pk_new");
if (eddsa_pk_from_EVP_PKEY(eddsa_pk, eddsa) != FIDO_OK)
errx(1, "eddsa_pk_from_EVP_PKEY");
pk = eddsa_pk;
EVP_PKEY_free(eddsa);
eddsa = NULL;
break;
default:
errx(1, "unknown credential type %d", type);
}
if ((assert = fido_assert_new()) == NULL)
errx(1, "fido_assert_new");
/* client data hash */
r = fido_assert_set_clientdata(assert, cd, sizeof(cd));
if (r != FIDO_OK)
errx(1, "fido_assert_set_clientdata: %s (0x%x)", fido_strerr(r), r);
/* relying party */
r = fido_assert_set_rp(assert, "localhost");
if (r != FIDO_OK)
errx(1, "fido_assert_set_rp: %s (0x%x)", fido_strerr(r), r);
/* authdata */
r = fido_assert_set_count(assert, 1);
if (r != FIDO_OK)
errx(1, "fido_assert_set_count: %s (0x%x)", fido_strerr(r), r);
r = fido_assert_set_authdata(assert, 0, authdata_ptr, authdata_len);
if (r != FIDO_OK)
errx(1, "fido_assert_set_authdata: %s (0x%x)", fido_strerr(r), r);
/* extension */
r = fido_assert_set_extensions(assert, ext);
if (r != FIDO_OK)
errx(1, "fido_assert_set_extensions: %s (0x%x)", fido_strerr(r),
r);
/* user presence */
if (up && (r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK)
errx(1, "fido_assert_set_up: %s (0x%x)", fido_strerr(r), r);
/* user verification */
if (uv && (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK)
errx(1, "fido_assert_set_uv: %s (0x%x)", fido_strerr(r), r);
/* sig */
r = fido_assert_set_sig(assert, 0, sig_ptr, sig_len);
if (r != FIDO_OK)
errx(1, "fido_assert_set_sig: %s (0x%x)", fido_strerr(r), r);
r = fido_assert_verify(assert, 0, type, pk);
if (r != FIDO_OK)
errx(1, "fido_assert_verify: %s (0x%x)", fido_strerr(r), r);
es256_pk_free(&es256_pk);
es384_pk_free(&es384_pk);
rs256_pk_free(&rs256_pk);
eddsa_pk_free(&eddsa_pk);
fido_assert_free(&assert);
}
int
main(int argc, char **argv)
{
bool up = false;
bool uv = false;
bool u2f = false;
fido_dev_t *dev = NULL;
fido_assert_t *assert = NULL;
const char *pin = NULL;
const char *blobkey_out = NULL;
const char *hmac_out = NULL;
unsigned char *body = NULL;
long long ms = 0;
size_t len;
int type = COSE_ES256;
int ext = 0;
int ch;
int r;
if ((assert = fido_assert_new()) == NULL)
errx(1, "fido_assert_new");
while ((ch = getopt(argc, argv, "P:T:a:b:h:ps:t:uv")) != -1) {
switch (ch) {
case 'P':
pin = optarg;
break;
case 'T':
if (base10(optarg, &ms) < 0)
errx(1, "base10: %s", optarg);
if (ms <= 0 || ms > 30)
errx(1, "-T: %s must be in (0,30]", optarg);
ms *= 1000; /* seconds to milliseconds */
break;
case 'a':
if (read_blob(optarg, &body, &len) < 0)
errx(1, "read_blob: %s", optarg);
if ((r = fido_assert_allow_cred(assert, body,
len)) != FIDO_OK)
errx(1, "fido_assert_allow_cred: %s (0x%x)",
fido_strerr(r), r);
free(body);
body = NULL;
break;
case 'b':
ext |= FIDO_EXT_LARGEBLOB_KEY;
blobkey_out = optarg;
break;
case 'h':
hmac_out = optarg;
break;
case 'p':
up = true;
break;
case 's':
ext |= FIDO_EXT_HMAC_SECRET;
if (read_blob(optarg, &body, &len) < 0)
errx(1, "read_blob: %s", optarg);
if ((r = fido_assert_set_hmac_salt(assert, body,
len)) != FIDO_OK)
errx(1, "fido_assert_set_hmac_salt: %s (0x%x)",
fido_strerr(r), r);
free(body);
body = NULL;
break;
case 't':
if (strcmp(optarg, "es256") == 0)
type = COSE_ES256;
else if (strcmp(optarg, "es384") == 0)
type = COSE_ES384;
else if (strcmp(optarg, "rs256") == 0)
type = COSE_RS256;
else if (strcmp(optarg, "eddsa") == 0)
type = COSE_EDDSA;
else
errx(1, "unknown type %s", optarg);
break;
case 'u':
u2f = true;
break;
case 'v':
uv = true;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 2)
usage();
fido_init(0);
if ((dev = fido_dev_new()) == NULL)
errx(1, "fido_dev_new");
r = fido_dev_open(dev, argv[1]);
if (r != FIDO_OK)
errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
if (u2f)
fido_dev_force_u2f(dev);
/* client data hash */
r = fido_assert_set_clientdata(assert, cd, sizeof(cd));
if (r != FIDO_OK)
errx(1, "fido_assert_set_clientdata: %s (0x%x)", fido_strerr(r), r);
/* relying party */
r = fido_assert_set_rp(assert, "localhost");
if (r != FIDO_OK)
errx(1, "fido_assert_set_rp: %s (0x%x)", fido_strerr(r), r);
/* extensions */
r = fido_assert_set_extensions(assert, ext);
if (r != FIDO_OK)
errx(1, "fido_assert_set_extensions: %s (0x%x)", fido_strerr(r),
r);
/* user presence */
if (up && (r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK)
errx(1, "fido_assert_set_up: %s (0x%x)", fido_strerr(r), r);
/* user verification */
if (uv && (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK)
errx(1, "fido_assert_set_uv: %s (0x%x)", fido_strerr(r), r);
/* timeout */
if (ms != 0 && (r = fido_dev_set_timeout(dev, (int)ms)) != FIDO_OK)
errx(1, "fido_dev_set_timeout: %s (0x%x)", fido_strerr(r), r);
if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) {
fido_dev_cancel(dev);
errx(1, "fido_dev_get_assert: %s (0x%x)", fido_strerr(r), r);
}
r = fido_dev_close(dev);
if (r != FIDO_OK)
errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
fido_dev_free(&dev);
if (fido_assert_count(assert) != 1)
errx(1, "fido_assert_count: %d signatures returned",
(int)fido_assert_count(assert));
/* when verifying, pin implies uv */
if (pin)
uv = true;
verify_assert(type, fido_assert_authdata_ptr(assert, 0),
fido_assert_authdata_len(assert, 0), fido_assert_sig_ptr(assert, 0),
fido_assert_sig_len(assert, 0), up, uv, ext, argv[0]);
if (hmac_out != NULL) {
/* extract the hmac secret */
if (write_blob(hmac_out, fido_assert_hmac_secret_ptr(assert, 0),
fido_assert_hmac_secret_len(assert, 0)) < 0)
errx(1, "write_blob");
}
if (blobkey_out != NULL) {
/* extract the hmac secret */
if (write_blob(blobkey_out,
fido_assert_largeblob_key_ptr(assert, 0),
fido_assert_largeblob_key_len(assert, 0)) < 0)
errx(1, "write_blob");
}
fido_assert_free(&assert);
exit(0);
}

331
examples/cred.c Normal file
View File

@@ -0,0 +1,331 @@
/*
* Copyright (c) 2018-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 <errno.h>
#include <fido.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "../openbsd-compat/openbsd-compat.h"
#include "extern.h"
static const unsigned char cd[32] = {
0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb,
0xdd, 0xd7, 0xfb, 0x06, 0x37, 0x62, 0xea, 0x26,
0x20, 0x44, 0x8e, 0x69, 0x7c, 0x03, 0xf2, 0x31,
0x2f, 0x99, 0xdc, 0xaf, 0x3e, 0x8a, 0x91, 0x6b,
};
static const unsigned char user_id[32] = {
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,
};
static void
usage(void)
{
fprintf(stderr, "usage: cred [-t es256|es384|rs256|eddsa] [-k pubkey] "
"[-ei cred_id] [-P pin] [-T seconds] [-b blobkey] [-c cred_protect] [-hruv] "
"<device>\n");
exit(EXIT_FAILURE);
}
static void
verify_cred(int type, const char *fmt, const unsigned char *authdata_ptr,
size_t authdata_len, const unsigned char *attstmt_ptr, size_t attstmt_len,
bool rk, bool uv, int ext, int cred_protect, const char *key_out,
const char *id_out)
{
fido_cred_t *cred;
int r;
if ((cred = fido_cred_new()) == NULL)
errx(1, "fido_cred_new");
/* type */
r = fido_cred_set_type(cred, type);
if (r != FIDO_OK)
errx(1, "fido_cred_set_type: %s (0x%x)", fido_strerr(r), r);
/* client data */
r = fido_cred_set_clientdata(cred, cd, sizeof(cd));
if (r != FIDO_OK)
errx(1, "fido_cred_set_clientdata: %s (0x%x)", fido_strerr(r), r);
/* relying party */
r = fido_cred_set_rp(cred, "localhost", "sweet home localhost");
if (r != FIDO_OK)
errx(1, "fido_cred_set_rp: %s (0x%x)", fido_strerr(r), r);
/* authdata */
r = fido_cred_set_authdata(cred, authdata_ptr, authdata_len);
if (r != FIDO_OK)
errx(1, "fido_cred_set_authdata: %s (0x%x)", fido_strerr(r), r);
/* extensions */
r = fido_cred_set_extensions(cred, ext);
if (r != FIDO_OK)
errx(1, "fido_cred_set_extensions: %s (0x%x)", fido_strerr(r), r);
/* resident key */
if (rk && (r = fido_cred_set_rk(cred, FIDO_OPT_TRUE)) != FIDO_OK)
errx(1, "fido_cred_set_rk: %s (0x%x)", fido_strerr(r), r);
/* user verification */
if (uv && (r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
errx(1, "fido_cred_set_uv: %s (0x%x)", fido_strerr(r), r);
/* credProt */
if (cred_protect != 0 && (r = fido_cred_set_prot(cred,
cred_protect)) != FIDO_OK)
errx(1, "fido_cred_set_prot: %s (0x%x)", fido_strerr(r), r);
/* fmt */
r = fido_cred_set_fmt(cred, fmt);
if (r != FIDO_OK)
errx(1, "fido_cred_set_fmt: %s (0x%x)", fido_strerr(r), r);
if (!strcmp(fido_cred_fmt(cred), "none")) {
warnx("no attestation data, skipping credential verification");
goto out;
}
/* attestation statement */
r = fido_cred_set_attstmt(cred, attstmt_ptr, attstmt_len);
if (r != FIDO_OK)
errx(1, "fido_cred_set_attstmt: %s (0x%x)", fido_strerr(r), r);
r = fido_cred_verify(cred);
if (r != FIDO_OK)
errx(1, "fido_cred_verify: %s (0x%x)", fido_strerr(r), r);
out:
if (key_out != NULL) {
/* extract the credential pubkey */
if (type == COSE_ES256) {
if (write_es256_pubkey(key_out,
fido_cred_pubkey_ptr(cred),
fido_cred_pubkey_len(cred)) < 0)
errx(1, "write_es256_pubkey");
} else if (type == COSE_ES384) {
if (write_es384_pubkey(key_out,
fido_cred_pubkey_ptr(cred),
fido_cred_pubkey_len(cred)) < 0)
errx(1, "write_es384_pubkey");
} else if (type == COSE_RS256) {
if (write_rs256_pubkey(key_out,
fido_cred_pubkey_ptr(cred),
fido_cred_pubkey_len(cred)) < 0)
errx(1, "write_rs256_pubkey");
} else if (type == COSE_EDDSA) {
if (write_eddsa_pubkey(key_out,
fido_cred_pubkey_ptr(cred),
fido_cred_pubkey_len(cred)) < 0)
errx(1, "write_eddsa_pubkey");
}
}
if (id_out != NULL) {
/* extract the credential id */
if (write_blob(id_out, fido_cred_id_ptr(cred),
fido_cred_id_len(cred)) < 0)
errx(1, "write_blob");
}
fido_cred_free(&cred);
}
int
main(int argc, char **argv)
{
bool rk = false;
bool uv = false;
bool u2f = false;
fido_dev_t *dev;
fido_cred_t *cred = NULL;
const char *pin = NULL;
const char *blobkey_out = NULL;
const char *key_out = NULL;
const char *id_out = NULL;
unsigned char *body = NULL;
long long ms = 0;
size_t len;
int type = COSE_ES256;
int ext = 0;
int ch;
int r;
long long cred_protect = 0;
if ((cred = fido_cred_new()) == NULL)
errx(1, "fido_cred_new");
while ((ch = getopt(argc, argv, "P:T:b:e:hi:k:rt:uvc:")) != -1) {
switch (ch) {
case 'P':
pin = optarg;
break;
case 'T':
if (base10(optarg, &ms) < 0)
errx(1, "base10: %s", optarg);
if (ms <= 0 || ms > 30)
errx(1, "-T: %s must be in (0,30]", optarg);
ms *= 1000; /* seconds to milliseconds */
break;
case 'b':
ext |= FIDO_EXT_LARGEBLOB_KEY;
blobkey_out = optarg;
break;
case 'e':
if (read_blob(optarg, &body, &len) < 0)
errx(1, "read_blob: %s", optarg);
r = fido_cred_exclude(cred, body, len);
if (r != FIDO_OK)
errx(1, "fido_cred_exclude: %s (0x%x)",
fido_strerr(r), r);
free(body);
body = NULL;
break;
case 'h':
ext |= FIDO_EXT_HMAC_SECRET;
break;
case 'c':
if (base10(optarg, &cred_protect) < 0)
errx(1, "base10: %s", optarg);
if (cred_protect <= 0 || cred_protect > 3)
errx(1, "-c: %s must be in (1,3)", optarg);
ext |= FIDO_EXT_CRED_PROTECT;
break;
case 'i':
id_out = optarg;
break;
case 'k':
key_out = optarg;
break;
case 'r':
rk = true;
break;
case 't':
if (strcmp(optarg, "es256") == 0)
type = COSE_ES256;
else if (strcmp(optarg, "es384") == 0)
type = COSE_ES384;
else if (strcmp(optarg, "rs256") == 0)
type = COSE_RS256;
else if (strcmp(optarg, "eddsa") == 0)
type = COSE_EDDSA;
else
errx(1, "unknown type %s", optarg);
break;
case 'u':
u2f = true;
break;
case 'v':
uv = true;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
fido_init(0);
if ((dev = fido_dev_new()) == NULL)
errx(1, "fido_dev_new");
r = fido_dev_open(dev, argv[0]);
if (r != FIDO_OK)
errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
if (u2f)
fido_dev_force_u2f(dev);
/* type */
r = fido_cred_set_type(cred, type);
if (r != FIDO_OK)
errx(1, "fido_cred_set_type: %s (0x%x)", fido_strerr(r), r);
/* client data */
r = fido_cred_set_clientdata(cred, cd, sizeof(cd));
if (r != FIDO_OK)
errx(1, "fido_cred_set_clientdata: %s (0x%x)", fido_strerr(r), r);
/* relying party */
r = fido_cred_set_rp(cred, "localhost", "sweet home localhost");
if (r != FIDO_OK)
errx(1, "fido_cred_set_rp: %s (0x%x)", fido_strerr(r), r);
/* user */
r = fido_cred_set_user(cred, user_id, sizeof(user_id), "john smith",
"jsmith", NULL);
if (r != FIDO_OK)
errx(1, "fido_cred_set_user: %s (0x%x)", fido_strerr(r), r);
/* extensions */
r = fido_cred_set_extensions(cred, ext);
if (r != FIDO_OK)
errx(1, "fido_cred_set_extensions: %s (0x%x)", fido_strerr(r), r);
/* resident key */
if (rk && (r = fido_cred_set_rk(cred, FIDO_OPT_TRUE)) != FIDO_OK)
errx(1, "fido_cred_set_rk: %s (0x%x)", fido_strerr(r), r);
/* user verification */
if (uv && (r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
errx(1, "fido_cred_set_uv: %s (0x%x)", fido_strerr(r), r);
/* credProt */
if (cred_protect != 0 && (r = fido_cred_set_prot(cred,
(int)cred_protect)) != FIDO_OK)
errx(1, "fido_cred_set_prot: %s (0x%x)", fido_strerr(r), r);
/* timeout */
if (ms != 0 && (r = fido_dev_set_timeout(dev, (int)ms)) != FIDO_OK)
errx(1, "fido_dev_set_timeout: %s (0x%x)", fido_strerr(r), r);
if ((r = fido_dev_make_cred(dev, cred, pin)) != FIDO_OK) {
fido_dev_cancel(dev);
errx(1, "fido_makecred: %s (0x%x)", fido_strerr(r), r);
}
r = fido_dev_close(dev);
if (r != FIDO_OK)
errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
fido_dev_free(&dev);
/* when verifying, pin implies uv */
if (pin)
uv = true;
verify_cred(type, fido_cred_fmt(cred), fido_cred_authdata_ptr(cred),
fido_cred_authdata_len(cred), fido_cred_attstmt_ptr(cred),
fido_cred_attstmt_len(cred), rk, uv, ext, fido_cred_prot(cred),
key_out, id_out);
if (blobkey_out != NULL) {
/* extract the "largeBlob" key */
if (write_blob(blobkey_out, fido_cred_largeblob_key_ptr(cred),
fido_cred_largeblob_key_len(cred)) < 0)
errx(1, "write_blob");
}
fido_cred_free(&cred);
exit(0);
}

27
examples/extern.h Normal file
View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2018-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 _EXTERN_H_
#define _EXTERN_H_
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
/* util.c */
EC_KEY *read_ec_pubkey(const char *);
RSA *read_rsa_pubkey(const char *);
EVP_PKEY *read_eddsa_pubkey(const char *);
int base10(const char *, long long *);
int read_blob(const char *, unsigned char **, size_t *);
int write_blob(const char *, const unsigned char *, size_t);
int write_es256_pubkey(const char *, const void *, size_t);
int write_es384_pubkey(const char *, const void *, size_t);
int write_rs256_pubkey(const char *, const void *, size_t);
int write_eddsa_pubkey(const char *, const void *, size_t);
#endif /* _EXTERN_H_ */

382
examples/info.c Normal file
View File

@@ -0,0 +1,382 @@
/*
* Copyright (c) 2018-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 <fido.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../openbsd-compat/openbsd-compat.h"
/*
* Pretty-print a device's capabilities flags and return the result.
*/
static void
format_flags(char *ret, size_t retlen, uint8_t flags)
{
memset(ret, 0, retlen);
if (flags & FIDO_CAP_WINK) {
if (strlcat(ret, "wink,", retlen) >= retlen)
goto toolong;
} else {
if (strlcat(ret, "nowink,", retlen) >= retlen)
goto toolong;
}
if (flags & FIDO_CAP_CBOR) {
if (strlcat(ret, " cbor,", retlen) >= retlen)
goto toolong;
} else {
if (strlcat(ret, " nocbor,", retlen) >= retlen)
goto toolong;
}
if (flags & FIDO_CAP_NMSG) {
if (strlcat(ret, " nomsg", retlen) >= retlen)
goto toolong;
} else {
if (strlcat(ret, " msg", retlen) >= retlen)
goto toolong;
}
return;
toolong:
strlcpy(ret, "toolong", retlen);
}
/*
* Print a FIDO device's attributes on stdout.
*/
static void
print_attr(const fido_dev_t *dev)
{
char flags_txt[128];
printf("proto: 0x%02x\n", fido_dev_protocol(dev));
printf("major: 0x%02x\n", fido_dev_major(dev));
printf("minor: 0x%02x\n", fido_dev_minor(dev));
printf("build: 0x%02x\n", fido_dev_build(dev));
format_flags(flags_txt, sizeof(flags_txt), fido_dev_flags(dev));
printf("caps: 0x%02x (%s)\n", fido_dev_flags(dev), flags_txt);
}
/*
* Auxiliary function to print an array of strings on stdout.
*/
static void
print_str_array(const char *label, char * const *sa, size_t len)
{
if (len == 0)
return;
printf("%s strings: ", label);
for (size_t i = 0; i < len; i++)
printf("%s%s", i > 0 ? ", " : "", sa[i]);
printf("\n");
}
/*
* Auxiliary function to print (char *, bool) pairs on stdout.
*/
static void
print_opt_array(const char *label, char * const *name, const bool *value,
size_t len)
{
if (len == 0)
return;
printf("%s: ", label);
for (size_t i = 0; i < len; i++)
printf("%s%s%s", i > 0 ? ", " : "",
value[i] ? "" : "no", name[i]);
printf("\n");
}
/*
* Auxiliary function to print (char *, uint64_t) pairs on stdout.
*/
static void
print_cert_array(const char *label, char * const *name, const uint64_t *value,
size_t len)
{
if (len == 0)
return;
printf("%s: ", label);
for (size_t i = 0; i < len; i++)
printf("%s%s %llu", i > 0 ? ", " : "", name[i],
(unsigned long long)value[i]);
printf("\n");
}
/*
* Auxiliary function to print a list of supported COSE algorithms on stdout.
*/
static void
print_algorithms(const fido_cbor_info_t *ci)
{
const char *cose, *type;
size_t len;
if ((len = fido_cbor_info_algorithm_count(ci)) == 0)
return;
printf("algorithms: ");
for (size_t i = 0; i < len; i++) {
cose = type = "unknown";
switch (fido_cbor_info_algorithm_cose(ci, i)) {
case COSE_ES256:
cose = "es256";
break;
case COSE_ES384:
cose = "es384";
break;
case COSE_RS256:
cose = "rs256";
break;
case COSE_EDDSA:
cose = "eddsa";
break;
}
if (fido_cbor_info_algorithm_type(ci, i) != NULL)
type = fido_cbor_info_algorithm_type(ci, i);
printf("%s%s (%s)", i > 0 ? ", " : "", cose, type);
}
printf("\n");
}
/*
* Auxiliary function to print an authenticator's AAGUID on stdout.
*/
static void
print_aaguid(const unsigned char *buf, size_t buflen)
{
printf("aaguid: ");
while (buflen--)
printf("%02x", *buf++);
printf("\n");
}
/*
* Auxiliary function to print an authenticator's maximum message size on
* stdout.
*/
static void
print_maxmsgsiz(uint64_t maxmsgsiz)
{
printf("maxmsgsiz: %d\n", (int)maxmsgsiz);
}
/*
* Auxiliary function to print an authenticator's maximum number of credentials
* in a credential list on stdout.
*/
static void
print_maxcredcntlst(uint64_t maxcredcntlst)
{
printf("maxcredcntlst: %d\n", (int)maxcredcntlst);
}
/*
* Auxiliary function to print an authenticator's maximum credential ID length
* on stdout.
*/
static void
print_maxcredidlen(uint64_t maxcredidlen)
{
printf("maxcredlen: %d\n", (int)maxcredidlen);
}
/*
* Auxiliary function to print the maximum size of an authenticator's
* serialized largeBlob array.
*/
static void
print_maxlargeblob(uint64_t maxlargeblob)
{
printf("maxlargeblob: %d\n", (int)maxlargeblob);
}
/*
* Auxiliary function to print the authenticator's estimated number of
* remaining resident credentials.
*/
static void
print_rk_remaining(int64_t rk_remaining)
{
printf("remaining rk(s): ");
if (rk_remaining == -1)
printf("undefined\n");
else
printf("%d\n", (int)rk_remaining);
}
/*
* Auxiliary function to print the minimum pin length observed by the
* authenticator.
*/
static void
print_minpinlen(uint64_t minpinlen)
{
printf("minpinlen: %d\n", (int)minpinlen);
}
/*
* Auxiliary function to print the authenticator's preferred (platform)
* UV attempts.
*/
static void
print_uv_attempts(uint64_t uv_attempts)
{
printf("platform uv attempt(s): %d\n", (int)uv_attempts);
}
/*
* Auxiliary function to print an authenticator's firmware version on stdout.
*/
static void
print_fwversion(uint64_t fwversion)
{
printf("fwversion: 0x%x\n", (int)fwversion);
}
/*
* Auxiliary function to print an array of bytes on stdout.
*/
static void
print_byte_array(const char *label, const uint8_t *ba, size_t len)
{
if (len == 0)
return;
printf("%s: ", label);
for (size_t i = 0; i < len; i++)
printf("%s%u", i > 0 ? ", " : "", (unsigned)ba[i]);
printf("\n");
}
static void
getinfo(const char *path)
{
fido_dev_t *dev;
fido_cbor_info_t *ci;
int r;
fido_init(0);
if ((dev = fido_dev_new()) == NULL)
errx(1, "fido_dev_new");
if ((r = fido_dev_open(dev, path)) != FIDO_OK)
errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
print_attr(dev);
if (fido_dev_is_fido2(dev) == false)
goto end;
if ((ci = fido_cbor_info_new()) == NULL)
errx(1, "fido_cbor_info_new");
if ((r = fido_dev_get_cbor_info(dev, ci)) != FIDO_OK)
errx(1, "fido_dev_get_cbor_info: %s (0x%x)", fido_strerr(r), r);
/* print supported protocol versions */
print_str_array("version", fido_cbor_info_versions_ptr(ci),
fido_cbor_info_versions_len(ci));
/* print supported extensions */
print_str_array("extension", fido_cbor_info_extensions_ptr(ci),
fido_cbor_info_extensions_len(ci));
/* print supported transports */
print_str_array("transport", fido_cbor_info_transports_ptr(ci),
fido_cbor_info_transports_len(ci));
/* print supported algorithms */
print_algorithms(ci);
/* print aaguid */
print_aaguid(fido_cbor_info_aaguid_ptr(ci),
fido_cbor_info_aaguid_len(ci));
/* print supported options */
print_opt_array("options", fido_cbor_info_options_name_ptr(ci),
fido_cbor_info_options_value_ptr(ci),
fido_cbor_info_options_len(ci));
/* print certifications */
print_cert_array("certifications", fido_cbor_info_certs_name_ptr(ci),
fido_cbor_info_certs_value_ptr(ci),
fido_cbor_info_certs_len(ci));
/* print firmware version */
print_fwversion(fido_cbor_info_fwversion(ci));
/* print maximum message size */
print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci));
/* print maximum number of credentials allowed in credential lists */
print_maxcredcntlst(fido_cbor_info_maxcredcntlst(ci));
/* print maximum length of a credential ID */
print_maxcredidlen(fido_cbor_info_maxcredidlen(ci));
/* print maximum length of largeBlob array */
print_maxlargeblob(fido_cbor_info_maxlargeblob(ci));
/* print number of remaining resident credentials */
print_rk_remaining(fido_cbor_info_rk_remaining(ci));
/* print minimum pin length */
print_minpinlen(fido_cbor_info_minpinlen(ci));
/* print supported pin protocols */
print_byte_array("pin protocols", fido_cbor_info_protocols_ptr(ci),
fido_cbor_info_protocols_len(ci));
/* print whether a new pin is required */
printf("pin change required: %s\n",
fido_cbor_info_new_pin_required(ci) ? "true" : "false");
/* print platform uv attempts */
print_uv_attempts(fido_cbor_info_uv_attempts(ci));
fido_cbor_info_free(&ci);
end:
if ((r = fido_dev_close(dev)) != FIDO_OK)
errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
fido_dev_free(&dev);
}
int
main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: info <device>\n");
exit(EXIT_FAILURE);
}
getinfo(argv[1]);
exit(0);
}

42
examples/manifest.c Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2018 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 <fido.h>
#include <stdio.h>
#include <stdlib.h>
#include "../openbsd-compat/openbsd-compat.h"
int
main(void)
{
fido_dev_info_t *devlist;
size_t ndevs;
int r;
fido_init(0);
if ((devlist = fido_dev_info_new(64)) == NULL)
errx(1, "fido_dev_info_new");
if ((r = fido_dev_info_manifest(devlist, 64, &ndevs)) != FIDO_OK)
errx(1, "fido_dev_info_manifest: %s (0x%x)", fido_strerr(r), r);
for (size_t i = 0; i < ndevs; i++) {
const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
printf("%s: vendor=0x%04x, product=0x%04x (%s %s)\n",
fido_dev_info_path(di),
(uint16_t)fido_dev_info_vendor(di),
(uint16_t)fido_dev_info_product(di),
fido_dev_info_manufacturer_string(di),
fido_dev_info_product_string(di));
}
fido_dev_info_free(&devlist, ndevs);
exit(0);
}

49
examples/reset.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2018-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
*/
/*
* Perform a factory reset on a given authenticator.
*/
#include <fido.h>
#include <stdio.h>
#include <stdlib.h>
#include "../openbsd-compat/openbsd-compat.h"
#include "extern.h"
int
main(int argc, char **argv)
{
fido_dev_t *dev;
int r;
if (argc != 2) {
fprintf(stderr, "usage: reset <device>\n");
exit(EXIT_FAILURE);
}
fido_init(0);
if ((dev = fido_dev_new()) == NULL)
errx(1, "fido_dev_new");
if ((r = fido_dev_open(dev, argv[1])) != FIDO_OK)
errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
if ((r = fido_dev_reset(dev)) != FIDO_OK) {
fido_dev_cancel(dev);
errx(1, "fido_dev_reset: %s (0x%x)", fido_strerr(r), r);
}
if ((r = fido_dev_close(dev)) != FIDO_OK)
errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
fido_dev_free(&dev);
exit(0);
}

49
examples/retries.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2018 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
*/
/*
* Get an authenticator's number of PIN attempts left.
*/
#include <fido.h>
#include <stdio.h>
#include <stdlib.h>
#include "../openbsd-compat/openbsd-compat.h"
int
main(int argc, char **argv)
{
fido_dev_t *dev;
int n;
int r;
if (argc != 2) {
fprintf(stderr, "usage: retries <device>\n");
exit(EXIT_FAILURE);
}
fido_init(0);
if ((dev = fido_dev_new()) == NULL)
errx(1, "fido_dev_new");
if ((r = fido_dev_open(dev, argv[1])) != FIDO_OK)
errx(1, "fido_open: %s (0x%x)", fido_strerr(r), r);
if ((r = fido_dev_get_retry_count(dev, &n)) != FIDO_OK)
errx(1, "fido_dev_get_retry_count: %s (0x%x)", fido_strerr(r), r);
if ((r = fido_dev_close(dev)) != FIDO_OK)
errx(1, "fido_close: %s (0x%x)", fido_strerr(r), r);
fido_dev_free(&dev);
printf("%d\n", n);
exit(0);
}

215
examples/select.c Normal file
View File

@@ -0,0 +1,215 @@
/*
* 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
*/
#include <errno.h>
#include <fido.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "../openbsd-compat/openbsd-compat.h"
#define FIDO_POLL_MS 50
#if defined(_MSC_VER)
static int
nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{
if (rmtp != NULL) {
errno = EINVAL;
return (-1);
}
Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000));
return (0);
}
#endif
static fido_dev_t *
open_dev(const fido_dev_info_t *di)
{
fido_dev_t *dev;
int r;
if ((dev = fido_dev_new()) == NULL) {
warnx("%s: fido_dev_new", __func__);
return (NULL);
}
if ((r = fido_dev_open(dev, fido_dev_info_path(di))) != FIDO_OK) {
warnx("%s: fido_dev_open %s: %s", __func__,
fido_dev_info_path(di), fido_strerr(r));
fido_dev_free(&dev);
return (NULL);
}
printf("%s (0x%04x:0x%04x) is %s\n", fido_dev_info_path(di),
fido_dev_info_vendor(di), fido_dev_info_product(di),
fido_dev_is_fido2(dev) ? "fido2" : "u2f");
return (dev);
}
static int
select_dev(const fido_dev_info_t *devlist, size_t ndevs, fido_dev_t **dev,
size_t *idx, int secs)
{
const fido_dev_info_t *di;
fido_dev_t **devtab;
struct timespec ts_start;
struct timespec ts_now;
struct timespec ts_delta;
struct timespec ts_pause;
size_t nopen = 0;
int touched;
int r;
long ms_remain;
*dev = NULL;
*idx = 0;
printf("%u authenticator(s) detected\n", (unsigned)ndevs);
if (ndevs == 0)
return (0); /* nothing to do */
if ((devtab = calloc(ndevs, sizeof(*devtab))) == NULL) {
warn("%s: calloc", __func__);
return (-1);
}
for (size_t i = 0; i < ndevs; i++) {
di = fido_dev_info_ptr(devlist, i);
if ((devtab[i] = open_dev(di)) != NULL) {
*idx = i;
nopen++;
}
}
printf("%u authenticator(s) opened\n", (unsigned)nopen);
if (nopen < 2) {
if (nopen == 1)
*dev = devtab[*idx]; /* single candidate */
r = 0;
goto out;
}
for (size_t i = 0; i < ndevs; i++) {
di = fido_dev_info_ptr(devlist, i);
if (devtab[i] == NULL)
continue; /* failed to open */
if ((r = fido_dev_get_touch_begin(devtab[i])) != FIDO_OK) {
warnx("%s: fido_dev_get_touch_begin %s: %s", __func__,
fido_dev_info_path(di), fido_strerr(r));
r = -1;
goto out;
}
}
if (clock_gettime(CLOCK_MONOTONIC, &ts_start) != 0) {
warn("%s: clock_gettime", __func__);
r = -1;
goto out;
}
ts_pause.tv_sec = 0;
ts_pause.tv_nsec = 200000000; /* 200ms */
do {
nanosleep(&ts_pause, NULL);
for (size_t i = 0; i < ndevs; i++) {
di = fido_dev_info_ptr(devlist, i);
if (devtab[i] == NULL) {
/* failed to open or discarded */
continue;
}
if ((r = fido_dev_get_touch_status(devtab[i], &touched,
FIDO_POLL_MS)) != FIDO_OK) {
warnx("%s: fido_dev_get_touch_status %s: %s",
__func__, fido_dev_info_path(di),
fido_strerr(r));
fido_dev_close(devtab[i]);
fido_dev_free(&devtab[i]);
continue; /* discard */
}
if (touched) {
*dev = devtab[i];
*idx = i;
r = 0;
goto out;
}
}
if (clock_gettime(CLOCK_MONOTONIC, &ts_now) != 0) {
warn("%s: clock_gettime", __func__);
r = -1;
goto out;
}
timespecsub(&ts_now, &ts_start, &ts_delta);
ms_remain = (secs * 1000) - ((long)ts_delta.tv_sec * 1000) +
((long)ts_delta.tv_nsec / 1000000);
} while (ms_remain > FIDO_POLL_MS);
printf("timeout after %d seconds\n", secs);
r = -1;
out:
if (r != 0) {
*dev = NULL;
*idx = 0;
}
for (size_t i = 0; i < ndevs; i++) {
if (devtab[i] && devtab[i] != *dev) {
fido_dev_cancel(devtab[i]);
fido_dev_close(devtab[i]);
fido_dev_free(&devtab[i]);
}
}
free(devtab);
return (r);
}
int
main(void)
{
const fido_dev_info_t *di;
fido_dev_info_t *devlist;
fido_dev_t *dev;
size_t idx;
size_t ndevs;
int r;
fido_init(0);
if ((devlist = fido_dev_info_new(64)) == NULL)
errx(1, "fido_dev_info_new");
if ((r = fido_dev_info_manifest(devlist, 64, &ndevs)) != FIDO_OK)
errx(1, "fido_dev_info_manifest: %s (0x%x)", fido_strerr(r), r);
if (select_dev(devlist, ndevs, &dev, &idx, 15) != 0)
errx(1, "select_dev");
if (dev == NULL)
errx(1, "no authenticator found");
di = fido_dev_info_ptr(devlist, idx);
printf("%s: %s by %s (PIN %sset)\n", fido_dev_info_path(di),
fido_dev_info_product_string(di),
fido_dev_info_manufacturer_string(di),
fido_dev_has_pin(dev) ? "" : "un");
fido_dev_close(dev);
fido_dev_free(&dev);
fido_dev_info_free(&devlist, ndevs);
exit(0);
}

55
examples/setpin.c Normal file
View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2018 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
*/
/*
* Configure a PIN on a given authenticator.
*/
#include <fido.h>
#include <stdio.h>
#include <stdlib.h>
#include "../openbsd-compat/openbsd-compat.h"
static void
setpin(const char *path, const char *pin, const char *oldpin)
{
fido_dev_t *dev;
int r;
fido_init(0);
if ((dev = fido_dev_new()) == NULL)
errx(1, "fido_dev_new");
if ((r = fido_dev_open(dev, path)) != FIDO_OK)
errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
if ((r = fido_dev_set_pin(dev, pin, oldpin)) != FIDO_OK)
errx(1, "fido_dev_set_pin: %s (0x%x)", fido_strerr(r), r);
if ((r = fido_dev_close(dev)) != FIDO_OK)
errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
fido_dev_free(&dev);
}
int
main(int argc, char **argv)
{
if (argc < 3 || argc > 4) {
fprintf(stderr, "usage: setpin <pin> [oldpin] <device>\n");
exit(EXIT_FAILURE);
}
if (argc == 3)
setpin(argv[2], argv[1], NULL);
else
setpin(argv[3], argv[1], argv[2]);
exit(0);
}

444
examples/util.c Normal file
View File

@@ -0,0 +1,444 @@
/*
* Copyright (c) 2018-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/stat.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <fido.h>
#include <fido/es256.h>
#include <fido/es384.h>
#include <fido/rs256.h>
#include <fido/eddsa.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef _MSC_VER
#include "../openbsd-compat/posix_win.h"
#endif
#include "../openbsd-compat/openbsd-compat.h"
#include "extern.h"
int
base10(const char *str, long long *ll)
{
char *ep;
*ll = strtoll(str, &ep, 10);
if (str == ep || *ep != '\0')
return (-1);
else if (*ll == LLONG_MIN && errno == ERANGE)
return (-1);
else if (*ll == LLONG_MAX && errno == ERANGE)
return (-1);
return (0);
}
int
write_blob(const char *path, const unsigned char *ptr, size_t len)
{
int fd, ok = -1;
ssize_t n;
if ((fd = open(path, O_WRONLY | O_CREAT, 0600)) < 0) {
warn("open %s", path);
goto fail;
}
if ((n = write(fd, ptr, len)) < 0) {
warn("write");
goto fail;
}
if ((size_t)n != len) {
warnx("write");
goto fail;
}
ok = 0;
fail:
if (fd != -1) {
close(fd);
}
return (ok);
}
int
read_blob(const char *path, unsigned char **ptr, size_t *len)
{
int fd, ok = -1;
struct stat st;
ssize_t n;
*ptr = NULL;
*len = 0;
if ((fd = open(path, O_RDONLY)) < 0) {
warn("open %s", path);
goto fail;
}
if (fstat(fd, &st) < 0) {
warn("stat %s", path);
goto fail;
}
if (st.st_size < 0) {
warnx("stat %s: invalid size", path);
goto fail;
}
*len = (size_t)st.st_size;
if ((*ptr = malloc(*len)) == NULL) {
warn("malloc");
goto fail;
}
if ((n = read(fd, *ptr, *len)) < 0) {
warn("read");
goto fail;
}
if ((size_t)n != *len) {
warnx("read");
goto fail;
}
ok = 0;
fail:
if (fd != -1) {
close(fd);
}
if (ok < 0) {
free(*ptr);
*ptr = NULL;
*len = 0;
}
return (ok);
}
EC_KEY *
read_ec_pubkey(const char *path)
{
FILE *fp = NULL;
EVP_PKEY *pkey = NULL;
EC_KEY *ec = NULL;
if ((fp = fopen(path, "r")) == NULL) {
warn("fopen");
goto fail;
}
if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
warnx("PEM_read_PUBKEY");
goto fail;
}
if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
warnx("EVP_PKEY_get1_EC_KEY");
goto fail;
}
fail:
if (fp != NULL) {
fclose(fp);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}
return (ec);
}
int
write_es256_pubkey(const char *path, const void *ptr, size_t len)
{
FILE *fp = NULL;
EVP_PKEY *pkey = NULL;
es256_pk_t *pk = NULL;
int fd = -1;
int ok = -1;
if ((pk = es256_pk_new()) == NULL) {
warnx("es256_pk_new");
goto fail;
}
if (es256_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
warnx("es256_pk_from_ptr");
goto fail;
}
if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) {
warn("open %s", path);
goto fail;
}
if ((fp = fdopen(fd, "w")) == NULL) {
warn("fdopen");
goto fail;
}
fd = -1; /* owned by fp now */
if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL) {
warnx("es256_pk_to_EVP_PKEY");
goto fail;
}
if (PEM_write_PUBKEY(fp, pkey) == 0) {
warnx("PEM_write_PUBKEY");
goto fail;
}
ok = 0;
fail:
es256_pk_free(&pk);
if (fp != NULL) {
fclose(fp);
}
if (fd != -1) {
close(fd);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}
return (ok);
}
int
write_es384_pubkey(const char *path, const void *ptr, size_t len)
{
FILE *fp = NULL;
EVP_PKEY *pkey = NULL;
es384_pk_t *pk = NULL;
int fd = -1;
int ok = -1;
if ((pk = es384_pk_new()) == NULL) {
warnx("es384_pk_new");
goto fail;
}
if (es384_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
warnx("es384_pk_from_ptr");
goto fail;
}
if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) {
warn("open %s", path);
goto fail;
}
if ((fp = fdopen(fd, "w")) == NULL) {
warn("fdopen");
goto fail;
}
fd = -1; /* owned by fp now */
if ((pkey = es384_pk_to_EVP_PKEY(pk)) == NULL) {
warnx("es384_pk_to_EVP_PKEY");
goto fail;
}
if (PEM_write_PUBKEY(fp, pkey) == 0) {
warnx("PEM_write_PUBKEY");
goto fail;
}
ok = 0;
fail:
es384_pk_free(&pk);
if (fp != NULL) {
fclose(fp);
}
if (fd != -1) {
close(fd);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}
return (ok);
}
RSA *
read_rsa_pubkey(const char *path)
{
FILE *fp = NULL;
EVP_PKEY *pkey = NULL;
RSA *rsa = NULL;
if ((fp = fopen(path, "r")) == NULL) {
warn("fopen");
goto fail;
}
if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
warnx("PEM_read_PUBKEY");
goto fail;
}
if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) {
warnx("EVP_PKEY_get1_RSA");
goto fail;
}
fail:
if (fp != NULL) {
fclose(fp);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}
return (rsa);
}
int
write_rs256_pubkey(const char *path, const void *ptr, size_t len)
{
FILE *fp = NULL;
EVP_PKEY *pkey = NULL;
rs256_pk_t *pk = NULL;
int fd = -1;
int ok = -1;
if ((pk = rs256_pk_new()) == NULL) {
warnx("rs256_pk_new");
goto fail;
}
if (rs256_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
warnx("rs256_pk_from_ptr");
goto fail;
}
if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) {
warn("open %s", path);
goto fail;
}
if ((fp = fdopen(fd, "w")) == NULL) {
warn("fdopen");
goto fail;
}
fd = -1; /* owned by fp now */
if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) {
warnx("rs256_pk_to_EVP_PKEY");
goto fail;
}
if (PEM_write_PUBKEY(fp, pkey) == 0) {
warnx("PEM_write_PUBKEY");
goto fail;
}
ok = 0;
fail:
rs256_pk_free(&pk);
if (fp != NULL) {
fclose(fp);
}
if (fd != -1) {
close(fd);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}
return (ok);
}
EVP_PKEY *
read_eddsa_pubkey(const char *path)
{
FILE *fp = NULL;
EVP_PKEY *pkey = NULL;
if ((fp = fopen(path, "r")) == NULL) {
warn("fopen");
goto fail;
}
if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
warnx("PEM_read_PUBKEY");
goto fail;
}
fail:
if (fp) {
fclose(fp);
}
return (pkey);
}
int
write_eddsa_pubkey(const char *path, const void *ptr, size_t len)
{
FILE *fp = NULL;
EVP_PKEY *pkey = NULL;
eddsa_pk_t *pk = NULL;
int fd = -1;
int ok = -1;
if ((pk = eddsa_pk_new()) == NULL) {
warnx("eddsa_pk_new");
goto fail;
}
if (eddsa_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
warnx("eddsa_pk_from_ptr");
goto fail;
}
if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) < 0) {
warn("open %s", path);
goto fail;
}
if ((fp = fdopen(fd, "w")) == NULL) {
warn("fdopen");
goto fail;
}
fd = -1; /* owned by fp now */
if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) {
warnx("eddsa_pk_to_EVP_PKEY");
goto fail;
}
if (PEM_write_PUBKEY(fp, pkey) == 0) {
warnx("PEM_write_PUBKEY");
goto fail;
}
ok = 0;
fail:
eddsa_pk_free(&pk);
if (fp != NULL) {
fclose(fp);
}
if (fd != -1) {
close(fd);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}
return (ok);
}

89
fuzz/CMakeLists.txt Normal file
View File

@@ -0,0 +1,89 @@
# Copyright (c) 2019-2024 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)
# fuzz_attobj
add_executable(fuzz_attobj fuzz_attobj.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
set_target_properties(fuzz_attobj PROPERTIES
LINK_FLAGS ${FUZZ_LDFLAGS}
LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
target_link_libraries(fuzz_attobj fido2_shared)

16
fuzz/Dockerfile Normal file
View File

@@ -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.11.0 --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

90
fuzz/Makefile Normal file
View File

@@ -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.15.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

43
fuzz/README Normal file
View File

@@ -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;
}

34
fuzz/build-coverage Normal file
View File

@@ -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"

80
fuzz/clock.c Normal file
View File

@@ -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));
}

182
fuzz/dummy.h Normal file
View File

@@ -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 */

289
fuzz/export.gnu Normal file
View File

@@ -0,0 +1,289 @@
{
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_attobj;
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_list_count;
fido_cred_x5c_list_len;
fido_cred_x5c_list_ptr;
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:
*;
};

956
fuzz/functions.txt Normal file
View File

@@ -0,0 +1,956 @@
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 42 0 100.00% 55 0 100.00%
bio.c:bio_get_cmd 8 0 100.00% 5 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 458 20 95.63% 592 24 95.95%
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 0 100.00% 8 0 100.00%
-----------------------------------------------------------------------------------------------------------------
TOTAL 8 0 100.00% 16 0 100.00%
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 35 0 100.00% 50 0 100.00%
credman.c:credman_get_cmd 7 0 100.00% 5 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 428 10 97.66% 562 20 96.44%
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 3 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 42 0 100.00% 25 0 100.00%
dev.c:fido_dev_set_protocol_flags 11 0 100.00% 17 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 344 65 81.10% 383 80 79.11%
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 38 0 100.00% 53 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 26 0 100.00% 29 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 202 73 63.86% 277 115 58.48%
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 1 94.44% 23 3 86.96%
nfc.c:rx_apdu 14 0 100.00% 22 0 100.00%
nfc.c:tx_get_response 4 0 100.00% 11 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 155 3 98.06% 244 9 96.31%
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 2 90.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 6 33.33% 21 9 57.14%
nfc_linux.c:nfc_free 12 0 100.00% 11 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 172 73 57.56% 242 114 52.89%
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 24 1 95.83% 21 3 85.71%
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 430 3 99.30% 516 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%

534
fuzz/fuzz_assert.c Normal file
View File

@@ -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);
}
}

333
fuzz/fuzz_attobj.c Normal file
View File

@@ -0,0 +1,333 @@
/*
* Copyright (c) 2024 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"
struct param {
int seed;
char rp_id[MAXSTR];
struct blob cdh;
struct blob attobj;
uint8_t type;
};
static const uint8_t dummy_attestation_object[] = {
0xa3, 0x63, 0x66, 0x6d, 0x74, 0x66, 0x70, 0x61,
0x63, 0x6b, 0x65, 0x64, 0x67, 0x61, 0x74, 0x74,
0x53, 0x74, 0x6d, 0x74, 0xa3, 0x63, 0x61, 0x6c,
0x67, 0x26, 0x63, 0x73, 0x69, 0x67, 0x58, 0x46,
0x30, 0x44, 0x02, 0x20, 0x54, 0x92, 0x28, 0x3b,
0x83, 0x33, 0x47, 0x56, 0x68, 0x79, 0xb2, 0x0c,
0x84, 0x80, 0xcc, 0x67, 0x27, 0x8b, 0xfa, 0x48,
0x43, 0x0d, 0x3c, 0xb4, 0x02, 0x36, 0x87, 0x97,
0x3e, 0xdf, 0x2f, 0x65, 0x02, 0x20, 0x1b, 0x56,
0x17, 0x06, 0xe2, 0x26, 0x0f, 0x6a, 0xe9, 0xa9,
0x70, 0x99, 0x62, 0xeb, 0x3a, 0x04, 0x1a, 0xc4,
0xa7, 0x03, 0x28, 0x56, 0x7c, 0xed, 0x47, 0x08,
0x68, 0x73, 0x6a, 0xb6, 0x89, 0x0d, 0x63, 0x78,
0x35, 0x63, 0x81, 0x59, 0x02, 0xe6, 0x30, 0x82,
0x02, 0xe2, 0x30, 0x81, 0xcb, 0x02, 0x01, 0x01,
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30,
0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x12, 0x59, 0x75, 0x62, 0x69,
0x63, 0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, 0x54,
0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e,
0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x31, 0x35,
0x31, 0x32, 0x35, 0x38, 0x35, 0x34, 0x5a, 0x17,
0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x34, 0x31,
0x32, 0x35, 0x38, 0x35, 0x34, 0x5a, 0x30, 0x1d,
0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x12, 0x59, 0x75, 0x62, 0x69, 0x63,
0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, 0x54, 0x65,
0x73, 0x74, 0x20, 0x45, 0x45, 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,
0xdb, 0x0a, 0xdb, 0xf5, 0x21, 0xc7, 0x5c, 0xce,
0x63, 0xdc, 0xa6, 0xe1, 0xe8, 0x25, 0x06, 0x0d,
0x94, 0xe6, 0x27, 0x54, 0x19, 0x4f, 0x9d, 0x24,
0xaf, 0x26, 0x1a, 0xbe, 0xad, 0x99, 0x44, 0x1f,
0x95, 0xa3, 0x71, 0x91, 0x0a, 0x3a, 0x20, 0xe7,
0x3e, 0x91, 0x5e, 0x13, 0xe8, 0xbe, 0x38, 0x05,
0x7a, 0xd5, 0x7a, 0xa3, 0x7e, 0x76, 0x90, 0x8f,
0xaf, 0xe2, 0x8a, 0x94, 0xb6, 0x30, 0xeb, 0x9d,
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03,
0x82, 0x02, 0x01, 0x00, 0x95, 0x40, 0x6b, 0x50,
0x61, 0x7d, 0xad, 0x84, 0xa3, 0xb4, 0xeb, 0x88,
0x0f, 0xe3, 0x30, 0x0f, 0x2d, 0xa2, 0x0a, 0x00,
0xd9, 0x25, 0x04, 0xee, 0x72, 0xfa, 0x67, 0xdf,
0x58, 0x51, 0x0f, 0x0b, 0x47, 0x02, 0x9c, 0x3e,
0x41, 0x29, 0x4a, 0x93, 0xac, 0x29, 0x85, 0x89,
0x2d, 0xa4, 0x7a, 0x81, 0x32, 0x28, 0x57, 0x71,
0x01, 0xef, 0xa8, 0x42, 0x88, 0x16, 0x96, 0x37,
0x91, 0xd5, 0xdf, 0xe0, 0x8f, 0xc9, 0x3c, 0x8d,
0xb0, 0xcd, 0x89, 0x70, 0x82, 0xec, 0x79, 0xd3,
0xc6, 0x78, 0x73, 0x29, 0x32, 0xe5, 0xab, 0x6c,
0xbd, 0x56, 0x9f, 0xd5, 0x45, 0x91, 0xce, 0xc1,
0xdd, 0x8d, 0x64, 0xdc, 0xe9, 0x9c, 0x1f, 0x5e,
0x3c, 0xd2, 0xaf, 0x51, 0xa5, 0x82, 0x18, 0xaf,
0xe0, 0x37, 0xe7, 0x32, 0x9e, 0x76, 0x05, 0x77,
0x02, 0x7b, 0xe6, 0x24, 0xa0, 0x31, 0x56, 0x1b,
0xfd, 0x19, 0xc5, 0x71, 0xd3, 0xf0, 0x9e, 0xc0,
0x73, 0x05, 0x4e, 0xbc, 0x85, 0xb8, 0x53, 0x9e,
0xef, 0xc5, 0xbc, 0x9c, 0x56, 0xa3, 0xba, 0xd9,
0x27, 0x6a, 0xbb, 0xa9, 0x7a, 0x40, 0xd7, 0x47,
0x8b, 0x55, 0x72, 0x6b, 0xe3, 0xfe, 0x28, 0x49,
0x71, 0x24, 0xf4, 0x8f, 0xf4, 0x20, 0x81, 0xea,
0x38, 0xff, 0x7c, 0x0a, 0x4f, 0xdf, 0x02, 0x82,
0x39, 0x81, 0x82, 0x3b, 0xca, 0x09, 0xdd, 0xca,
0xaa, 0x0f, 0x27, 0xf5, 0xa4, 0x83, 0x55, 0x6c,
0x9a, 0x39, 0x9b, 0x15, 0x3a, 0x16, 0x63, 0xdc,
0x5b, 0xf9, 0xac, 0x5b, 0xbc, 0xf7, 0x9f, 0xbe,
0x0f, 0x8a, 0xa2, 0x3c, 0x31, 0x13, 0xa3, 0x32,
0x48, 0xca, 0x58, 0x87, 0xf8, 0x7b, 0xa0, 0xa1,
0x0a, 0x6a, 0x60, 0x96, 0x93, 0x5f, 0x5d, 0x26,
0x9e, 0x63, 0x1d, 0x09, 0xae, 0x9a, 0x41, 0xe5,
0xbd, 0x08, 0x47, 0xfe, 0xe5, 0x09, 0x9b, 0x20,
0xfd, 0x12, 0xe2, 0xe6, 0x40, 0x7f, 0xba, 0x4a,
0x61, 0x33, 0x66, 0x0d, 0x0e, 0x73, 0xdb, 0xb0,
0xd5, 0xa2, 0x9a, 0x9a, 0x17, 0x0d, 0x34, 0x30,
0x85, 0x6a, 0x42, 0x46, 0x9e, 0xff, 0x34, 0x8f,
0x5f, 0x87, 0x6c, 0x35, 0xe7, 0xa8, 0x4d, 0x35,
0xeb, 0xc1, 0x41, 0xaa, 0x8a, 0xd2, 0xda, 0x19,
0xaa, 0x79, 0xa2, 0x5f, 0x35, 0x2c, 0xa0, 0xfd,
0x25, 0xd3, 0xf7, 0x9d, 0x25, 0x18, 0x2d, 0xfa,
0xb4, 0xbc, 0xbb, 0x07, 0x34, 0x3c, 0x8d, 0x81,
0xbd, 0xf4, 0xe9, 0x37, 0xdb, 0x39, 0xe9, 0xd1,
0x45, 0x5b, 0x20, 0x41, 0x2f, 0x2d, 0x27, 0x22,
0xdc, 0x92, 0x74, 0x8a, 0x92, 0xd5, 0x83, 0xfd,
0x09, 0xfb, 0x13, 0x9b, 0xe3, 0x39, 0x7a, 0x6b,
0x5c, 0xfa, 0xe6, 0x76, 0x9e, 0xe0, 0xe4, 0xe3,
0xef, 0xad, 0xbc, 0xfd, 0x42, 0x45, 0x9a, 0xd4,
0x94, 0xd1, 0x7e, 0x8d, 0xa7, 0xd8, 0x05, 0xd5,
0xd3, 0x62, 0xcf, 0x15, 0xcf, 0x94, 0x7d, 0x1f,
0x5b, 0x58, 0x20, 0x44, 0x20, 0x90, 0x71, 0xbe,
0x66, 0xe9, 0x9a, 0xab, 0x74, 0x32, 0x70, 0x53,
0x1d, 0x69, 0xed, 0x87, 0x66, 0xf4, 0x09, 0x4f,
0xca, 0x25, 0x30, 0xc2, 0x63, 0x79, 0x00, 0x3c,
0xb1, 0x9b, 0x39, 0x3f, 0x00, 0xe0, 0xa8, 0x88,
0xef, 0x7a, 0x51, 0x5b, 0xe7, 0xbd, 0x49, 0x64,
0xda, 0x41, 0x7b, 0x24, 0xc3, 0x71, 0x22, 0xfd,
0xd1, 0xd1, 0x20, 0xb3, 0x3f, 0x97, 0xd3, 0x97,
0xb2, 0xaa, 0x18, 0x1c, 0x9e, 0x03, 0x77, 0x7b,
0x5b, 0x7e, 0xf9, 0xa3, 0xa0, 0xd6, 0x20, 0x81,
0x2c, 0x38, 0x8f, 0x9d, 0x25, 0xde, 0xe9, 0xc8,
0xf5, 0xdd, 0x6a, 0x47, 0x9c, 0x65, 0x04, 0x5a,
0x56, 0xe6, 0xc2, 0xeb, 0xf2, 0x02, 0x97, 0xe1,
0xb9, 0xd8, 0xe1, 0x24, 0x76, 0x9f, 0x23, 0x62,
0x39, 0x03, 0x4b, 0xc8, 0xf7, 0x34, 0x07, 0x49,
0xd6, 0xe7, 0x4d, 0x9a, 0x68, 0x61, 0x75, 0x74,
0x68, 0x44, 0x61, 0x74, 0x61, 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, 0x41,
0x00, 0x00, 0x00, 0x00, 0xf8, 0xa0, 0x11, 0xf3,
0x8c, 0x0a, 0x4d, 0x15, 0x80, 0x06, 0x17, 0x11,
0x1f, 0x9e, 0xdc, 0x7d, 0x00, 0x40, 0x53, 0xfb,
0xdf, 0xaa, 0xce, 0x63, 0xde, 0xc5, 0xfe, 0x47,
0xe6, 0x52, 0xeb, 0xf3, 0x5d, 0x53, 0xa8, 0xbf,
0x9d, 0xd6, 0x09, 0x6b, 0x5e, 0x7f, 0xe0, 0x0d,
0x51, 0x30, 0x85, 0x6a, 0xda, 0x68, 0x70, 0x85,
0xb0, 0xdb, 0x08, 0x0b, 0x83, 0x2c, 0xef, 0x44,
0xe2, 0x36, 0x88, 0xee, 0x76, 0x90, 0x6e, 0x7b,
0x50, 0x3e, 0x9a, 0xa0, 0xd6, 0x3c, 0x34, 0xe3,
0x83, 0xe7, 0xd1, 0xbd, 0x9f, 0x25, 0xa5, 0x01,
0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20,
0x17, 0x5b, 0x27, 0xa6, 0x56, 0xb2, 0x26, 0x0c,
0x26, 0x0c, 0x55, 0x42, 0x78, 0x17, 0x5d, 0x4c,
0xf8, 0xa2, 0xfd, 0x1b, 0xb9, 0x54, 0xdf, 0xd5,
0xeb, 0xbf, 0x22, 0x64, 0xf5, 0x21, 0x9a, 0xc6,
0x22, 0x58, 0x20, 0x87, 0x5f, 0x90, 0xe6, 0xfd,
0x71, 0x27, 0x9f, 0xeb, 0xe3, 0x03, 0x44, 0xbc,
0x8d, 0x49, 0xc6, 0x1c, 0x31, 0x3b, 0x72, 0xae,
0xd4, 0x53, 0xb1, 0xfe, 0x5d, 0xe1, 0x30, 0xfc,
0x2b, 0x1e, 0xd2
};
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->rp_id) < 0 ||
unpack_blob(v[2], &p->cdh) < 0 ||
unpack_blob(v[3], &p->attobj) < 0 ||
unpack_byte(v[4], &p->type) < 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(17)) == NULL ||
(argv[0] = pack_int(p->seed)) == NULL ||
(argv[1] = pack_string(p->rp_id)) == NULL ||
(argv[2] = pack_blob(&p->cdh)) == NULL ||
(argv[3] = pack_blob(&p->attobj)) == NULL ||
(argv[4] = pack_byte(p->type)) == 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));
dummy.type = 1;
strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
dummy.cdh.len = sizeof(dummy_cdh);
dummy.attobj.len = sizeof(dummy_attestation_object);
memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len);
memcpy(&dummy.attobj.body, dummy_attestation_object, dummy.attobj.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
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->type);
p->attobj.len = sizeof(dummy_attestation_object);
memcpy(&p->attobj.body, &dummy_attestation_object,
p->attobj.len);
mutate_blob(&p->attobj);
}
}
void
test(const struct param *p)
{
fido_cred_t *cred = NULL;
int r, cose_alg;
prng_init((unsigned int)p->seed);
fuzz_clock_reset();
fido_init(FIDO_DEBUG);
fido_set_log_handler(consume_str);
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;
}
r = fido_cred_set_type(cred, cose_alg);
consume(&r, sizeof(r));
r = fido_cred_set_rp(cred, p->rp_id, NULL);
consume(&r, sizeof(r));
r = fido_cred_set_clientdata_hash(cred, p->cdh.body, p->cdh.len);
consume(&r, sizeof(r));
r = fido_cred_set_attobj(cred, p->attobj.body, p->attobj.len);
consume(&r, sizeof(r));
consume_str(fido_cred_fmt(cred));
consume(fido_cred_attstmt_ptr(cred), fido_cred_attstmt_len(cred));
consume(fido_cred_authdata_ptr(cred), fido_cred_authdata_len(cred));
r = fido_cred_verify(cred);
consume(&r, sizeof(r));
fido_cred_free(&cred);
}

442
fuzz/fuzz_bio.c Normal file
View File

@@ -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);
}
}

487
fuzz/fuzz_cred.c Normal file
View File

@@ -0,0 +1,487 @@
/*
* 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);
/* XXX +1 on purpose */
for (size_t i = 0; i < fido_cred_x5c_list_count(cred) + 1; i++)
consume(fido_cred_x5c_list_ptr(cred, i),
fido_cred_x5c_list_len(cred, i));
/* 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);
}
}

407
fuzz/fuzz_credman.c Normal file
View File

@@ -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);
}
}

239
fuzz/fuzz_hid.c Normal file
View File

@@ -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);
}

272
fuzz/fuzz_largeblob.c Normal file
View File

@@ -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);
}
}

528
fuzz/fuzz_mgmt.c Normal file
View File

@@ -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);
}
}

164
fuzz/fuzz_netlink.c Normal file
View File

@@ -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);
}

269
fuzz/fuzz_pcsc.c Normal file
View File

@@ -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);
}
}

231
fuzz/libfuzzer.c Normal file
View File

@@ -0,0 +1,231 @@
/*
* 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 <limits.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;
}

338
fuzz/mutator_aux.c Normal file
View File

@@ -0,0 +1,338 @@
/*
* 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));
#ifdef WITH_MSAN
__msan_unpoison(b, sizeof(*b));
#endif
}
void
mutate_int(int *i)
{
LLVMFuzzerMutate((uint8_t *)i, sizeof(*i), sizeof(*i));
#ifdef WITH_MSAN
__msan_unpoison(i, sizeof(*i));
#endif
}
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;
}

111
fuzz/mutator_aux.h Normal file
View File

@@ -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 */

153
fuzz/pcsc.c Normal file
View File

@@ -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;
}

105
fuzz/preload-fuzz.c Normal file
View File

@@ -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);
}

218
fuzz/preload-snoop.c Normal file
View File

@@ -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);
}

113
fuzz/prng.c Normal file
View File

@@ -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;
}

BIN
fuzz/report.tgz Normal file

Binary file not shown.

64
fuzz/summary.txt Normal file
View File

@@ -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 458 20 95.63% 50 2 96.00% 592 24 95.95%
src/blob.c 53 2 96.23% 10 0 100.00% 83 4 95.18%
src/buf.c 8 0 100.00% 2 0 100.00% 16 0 100.00%
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 428 10 97.66% 41 0 100.00% 562 20 96.44%
src/dev.c 344 65 81.10% 41 6 85.37% 383 80 79.11%
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 202 73 63.86% 14 7 50.00% 277 115 58.48%
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 3 98.06% 12 0 100.00% 244 9 96.31%
src/nfc_linux.c 172 73 57.56% 13 6 53.85% 242 114 52.89%
src/pcsc.c 204 1 99.51% 13 0 100.00% 282 3 98.94%
src/pin.c 430 3 99.30% 26 0 100.00% 516 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 8777 479 94.54% 744 28 96.24% 11388 750 93.41%

270
fuzz/udev.c Normal file
View File

@@ -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;
}

57
fuzz/uniform_random.c Normal file
View File

@@ -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;
}

708
fuzz/wiredata_fido2.h Normal file
View File

@@ -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 */

153
fuzz/wiredata_u2f.h Normal file
View File

@@ -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 */

700
fuzz/wrap.c Normal file
View File

@@ -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;
}

102
fuzz/wrapped.sym Normal file
View File

@@ -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