Vendor import of libfido2 1.8.0

This commit is contained in:
Ed Maste 2021-10-01 19:52:55 -04:00
commit a58dee945a
198 changed files with 43610 additions and 0 deletions

418
CMakeLists.txt Normal file
View File

@ -0,0 +1,418 @@
# 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.
# detect AppleClang; needs to come before project()
cmake_policy(SET CMP0025 NEW)
project(libfido2 C)
cmake_minimum_required(VERSION 3.0)
# Set PIE flags for POSITION_INDEPENDENT_CODE targets, added in CMake 3.14.
if(POLICY CMP0083)
cmake_policy(SET CMP0083 NEW)
endif()
include(CheckCCompilerFlag)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckSymbolExists)
include(CheckIncludeFiles)
include(CheckTypeSize)
include(GNUInstallDirs)
include(CheckPIESupported OPTIONAL RESULT_VARIABLE CHECK_PIE_SUPPORTED)
if(CHECK_PIE_SUPPORTED)
check_pie_supported(LANGUAGES C)
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_COLOR_MAKEFILE OFF)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(FIDO_MAJOR "1")
set(FIDO_MINOR "8")
set(FIDO_PATCH "0")
set(FIDO_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}.${FIDO_PATCH})
option(BUILD_EXAMPLES "Build example programs" ON)
option(BUILD_MANPAGES "Build man pages" ON)
option(BUILD_SHARED_LIBS "Build the shared library" ON)
option(BUILD_STATIC_LIBS "Build the static library" ON)
option(BUILD_TOOLS "Build tool programs" ON)
option(FUZZ "Enable fuzzing instrumentation" OFF)
option(LIBFUZZER "Build libfuzzer harnesses" OFF)
option(USE_HIDAPI "Use hidapi as the HID backend" OFF)
option(USE_WINHELLO "Abstract Windows Hello as a FIDO device" OFF)
option(NFC_LINUX "Experimental NFC support on Linux" OFF)
add_definitions(-D_FIDO_MAJOR=${FIDO_MAJOR})
add_definitions(-D_FIDO_MINOR=${FIDO_MINOR})
add_definitions(-D_FIDO_PATCH=${FIDO_PATCH})
if(CYGWIN OR MSYS)
set(WIN32 1)
add_definitions(-DWINVER=0x0a00)
endif()
if(WIN32)
add_definitions(-DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600)
endif()
if(APPLE)
set(CMAKE_INSTALL_NAME_DIR
"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
endif()
if(NOT MSVC)
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_POSIX_C_SOURCE=200809L")
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_BSD_SOURCE")
if(APPLE)
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_DARWIN_C_SOURCE")
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D__STDC_WANT_LIB_EXT1__=1")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(NFC_LINUX OFF)
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_GNU_SOURCE")
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_DEFAULT_SOURCE")
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D__BSD_VISIBLE=1")
endif()
set(FIDO_CFLAGS "${FIDO_CFLAGS} -std=c99")
set(CMAKE_C_FLAGS "${FIDO_CFLAGS} ${CMAKE_C_FLAGS}")
endif()
check_c_compiler_flag("-Wshorten-64-to-32" HAVE_SHORTEN_64_TO_32)
check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL)
check_include_files(cbor.h HAVE_CBOR_H)
check_include_files(endian.h HAVE_ENDIAN_H)
check_include_files(err.h HAVE_ERR_H)
check_include_files(openssl/opensslv.h HAVE_OPENSSLV_H)
check_include_files(signal.h HAVE_SIGNAL_H)
check_include_files(sys/random.h HAVE_SYS_RANDOM_H)
check_include_files(unistd.h HAVE_UNISTD_H)
check_include_files("windows.h;webauthn.h" HAVE_WEBAUTHN_H)
check_symbol_exists(arc4random_buf stdlib.h HAVE_ARC4RANDOM_BUF)
check_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME)
check_symbol_exists(explicit_bzero string.h HAVE_EXPLICIT_BZERO)
check_symbol_exists(freezero stdlib.h HAVE_FREEZERO)
check_symbol_exists(getline stdio.h HAVE_GETLINE)
check_symbol_exists(getopt unistd.h HAVE_GETOPT)
check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE)
check_symbol_exists(getrandom sys/random.h HAVE_GETRANDOM)
check_symbol_exists(memset_s string.h HAVE_MEMSET_S)
check_symbol_exists(readpassphrase readpassphrase.h HAVE_READPASSPHRASE)
check_symbol_exists(recallocarray stdlib.h HAVE_RECALLOCARRAY)
check_symbol_exists(sigaction signal.h HAVE_SIGACTION)
check_symbol_exists(strlcat string.h HAVE_STRLCAT)
check_symbol_exists(strlcpy string.h HAVE_STRLCPY)
check_symbol_exists(sysconf unistd.h HAVE_SYSCONF)
check_symbol_exists(timespecsub sys/time.h HAVE_TIMESPECSUB)
check_symbol_exists(timingsafe_bcmp string.h HAVE_TIMINGSAFE_BCMP)
set(CMAKE_EXTRA_INCLUDE_FILES signal.h)
check_type_size("sig_atomic_t" HAVE_SIG_ATOMIC_T)
set(CMAKE_EXTRA_INCLUDE_FILES)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
try_compile(HAVE_POSIX_IOCTL
"${CMAKE_CURRENT_BINARY_DIR}/posix_ioctl_check.o"
"${CMAKE_CURRENT_SOURCE_DIR}/openbsd-compat/posix_ioctl_check.c"
COMPILE_DEFINITIONS "-Werror -Woverflow -Wsign-conversion")
list(APPEND CHECK_VARIABLES
HAVE_ARC4RANDOM_BUF
HAVE_CBOR_H
HAVE_CLOCK_GETTIME
HAVE_ENDIAN_H
HAVE_ERR_H
HAVE_FREEZERO
HAVE_GETLINE
HAVE_GETOPT
HAVE_GETPAGESIZE
HAVE_GETRANDOM
HAVE_MEMSET_S
HAVE_OPENSSLV_H
HAVE_POSIX_IOCTL
HAVE_READPASSPHRASE
HAVE_RECALLOCARRAY
HAVE_SIGACTION
HAVE_SIGNAL_H
HAVE_STRLCAT
HAVE_STRLCPY
HAVE_SYSCONF
HAVE_SYS_RANDOM_H
HAVE_TIMESPECSUB
HAVE_TIMINGSAFE_BCMP
HAVE_UNISTD_H
HAVE_WEBAUTHN_H
)
foreach(v ${CHECK_VARIABLES})
if (${v})
add_definitions(-D${v})
endif()
endforeach()
if(HAVE_EXPLICIT_BZERO AND NOT LIBFUZZER)
add_definitions(-DHAVE_EXPLICIT_BZERO)
endif()
if(HAVE_SIGACTION AND (NOT HAVE_SIG_ATOMIC_T STREQUAL ""))
add_definitions(-DSIGNAL_EXAMPLE)
endif()
if(UNIX)
add_definitions(-DHAVE_DEV_URANDOM)
endif()
if(MSVC)
if((NOT CBOR_INCLUDE_DIRS) OR (NOT CBOR_LIBRARY_DIRS) OR
(NOT CRYPTO_INCLUDE_DIRS) OR (NOT CRYPTO_LIBRARY_DIRS) OR
(NOT ZLIB_INCLUDE_DIRS) OR (NOT ZLIB_LIBRARY_DIRS))
message(FATAL_ERROR "please provide definitions for "
"{CBOR,CRYPTO,ZLIB}_{INCLUDE,LIBRARY}_DIRS when building "
"under msvc")
endif()
set(CBOR_LIBRARIES cbor)
set(ZLIB_LIBRARIES zlib)
set(CRYPTO_LIBRARIES crypto-46)
set(MSVC_DISABLED_WARNINGS_LIST
"C4200" # nonstandard extension used: zero-sized array in
# struct/union;
"C4204" # nonstandard extension used: non-constant aggregate
# initializer;
"C4706" # assignment within conditional expression;
"C4996" # The POSIX name for this item is deprecated. Instead,
# use the ISO C and C++ conformant name;
"C6287" # redundant code: the left and right subexpressions are identical
)
# The construction in the following 3 lines was taken from LibreSSL's
# CMakeLists.txt.
string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR
${MSVC_DISABLED_WARNINGS_LIST})
string(REGEX REPLACE "[/-]W[1234][ ]?" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP -W4 -WX ${MSVC_DISABLED_WARNINGS_STR}")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7 /guard:cf /sdl /RTCcsu")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi /guard:cf /sdl")
if (HAVE_WEBAUTHN_H)
add_definitions(-DUSE_WINHELLO)
set(USE_WINHELLO ON)
endif()
else()
include(FindPkgConfig)
pkg_search_module(CBOR libcbor)
pkg_search_module(CRYPTO libcrypto)
pkg_search_module(ZLIB zlib)
if(NOT CBOR_FOUND AND NOT HAVE_CBOR_H)
message(FATAL_ERROR "could not find libcbor")
endif()
if(NOT CRYPTO_FOUND AND NOT HAVE_OPENSSLV_H)
message(FATAL_ERROR "could not find libcrypto")
endif()
if(NOT ZLIB_FOUND)
message(FATAL_ERROR "could not find zlib")
endif()
set(CBOR_LIBRARIES "cbor")
set(CRYPTO_LIBRARIES "crypto")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
pkg_search_module(UDEV libudev REQUIRED)
set(UDEV_NAME "udev")
# If using hidapi, use hidapi-hidraw.
set(HIDAPI_SUFFIX -hidraw)
if(NOT HAVE_CLOCK_GETTIME)
# Look for clock_gettime in librt.
check_library_exists(rt clock_gettime "time.h"
HAVE_CLOCK_GETTIME)
if (HAVE_CLOCK_GETTIME)
add_definitions(-DHAVE_CLOCK_GETTIME)
set(BASE_LIBRARIES ${BASE_LIBRARIES} rt)
endif()
endif()
endif()
if(MINGW)
# MinGW is stuck with a flavour of C89.
add_definitions(-DFIDO_NO_DIAGNOSTIC)
add_definitions(-DWC_ERR_INVALID_CHARS=0x80)
add_compile_options(-Wno-unused-parameter)
endif()
if(USE_HIDAPI)
add_definitions(-DUSE_HIDAPI)
pkg_search_module(HIDAPI hidapi${HIDAPI_SUFFIX} REQUIRED)
set(HIDAPI_LIBRARIES hidapi${HIDAPI_SUFFIX})
endif()
if(FUZZ)
set(NFC_LINUX ON)
endif()
if(NFC_LINUX)
add_definitions(-DNFC_LINUX)
endif()
add_compile_options(-Wall)
add_compile_options(-Wextra)
add_compile_options(-Werror)
add_compile_options(-Wshadow)
add_compile_options(-Wcast-qual)
add_compile_options(-Wwrite-strings)
add_compile_options(-Wmissing-prototypes)
add_compile_options(-Wbad-function-cast)
add_compile_options(-pedantic)
add_compile_options(-pedantic-errors)
if(HAVE_SHORTEN_64_TO_32)
add_compile_options(-Wshorten-64-to-32)
endif()
if(HAVE_STACK_PROTECTOR_ALL)
add_compile_options(-fstack-protector-all)
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g2")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2")
if(FUZZ)
add_definitions(-DFIDO_FUZZ)
endif()
if(LIBFUZZER)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link")
endif()
endif()
# Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425
if(CMAKE_COMPILER_IS_GNUCC)
add_compile_options(-Wno-unused-result)
endif()
# Decide which keyword to use for thread-local storage.
if(CMAKE_COMPILER_IS_GNUCC OR
CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
set(TLS "__thread")
elseif(WIN32)
set(TLS "__declspec(thread)")
endif()
add_definitions(-DTLS=${TLS})
# export list
if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
CMAKE_C_COMPILER_ID STREQUAL "AppleClang"))
# clang + lld
string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
" -exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/src/export.llvm")
elseif(NOT MSVC)
# clang/gcc + gnu ld
if(FUZZ)
string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
" -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/fuzz/export.gnu")
else()
string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
" -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/export.gnu")
endif()
if(NOT WIN32)
string(CONCAT CMAKE_SHARED_LINKER_FLAGS
${CMAKE_SHARED_LINKER_FLAGS}
" -Wl,-z,noexecstack -Wl,-z,relro,-z,now")
string(CONCAT CMAKE_EXE_LINKER_FLAGS
${CMAKE_EXE_LINKER_FLAGS}
" -Wl,-z,noexecstack -Wl,-z,relro,-z,now")
if(FUZZ)
file(STRINGS fuzz/wrapped.sym WRAPPED_SYMBOLS)
foreach(s ${WRAPPED_SYMBOLS})
string(CONCAT CMAKE_SHARED_LINKER_FLAGS
${CMAKE_SHARED_LINKER_FLAGS}
" -Wl,--wrap=${s}")
endforeach()
endif()
endif()
else()
string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
" /def:\"${CMAKE_CURRENT_SOURCE_DIR}/src/export.msvc\"")
endif()
include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${CBOR_INCLUDE_DIRS})
include_directories(${CRYPTO_INCLUDE_DIRS})
include_directories(${HIDAPI_INCLUDE_DIRS})
include_directories(${UDEV_INCLUDE_DIRS})
include_directories(${ZLIB_INCLUDE_DIRS})
link_directories(${CBOR_LIBRARY_DIRS})
link_directories(${CRYPTO_LIBRARY_DIRS})
link_directories(${HIDAPI_LIBRARY_DIRS})
link_directories(${UDEV_LIBRARY_DIRS})
link_directories(${ZLIB_LIBRARY_DIRS})
message(STATUS "BASE_LIBRARIES: ${BASE_LIBRARIES}")
message(STATUS "BUILD_EXAMPLES: ${BUILD_EXAMPLES}")
message(STATUS "BUILD_MANPAGES: ${BUILD_MANPAGES}")
message(STATUS "BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}")
message(STATUS "BUILD_STATIC_LIBS: ${BUILD_STATIC_LIBS}")
message(STATUS "BUILD_TOOLS: ${BUILD_TOOLS}")
message(STATUS "CBOR_INCLUDE_DIRS: ${CBOR_INCLUDE_DIRS}")
message(STATUS "CBOR_LIBRARIES: ${CBOR_LIBRARIES}")
message(STATUS "CBOR_LIBRARY_DIRS: ${CBOR_LIBRARY_DIRS}")
message(STATUS "CBOR_VERSION: ${CBOR_VERSION}")
message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}")
message(STATUS "CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}")
message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}")
message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
message(STATUS "CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}")
message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}")
message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}")
message(STATUS "CRYPTO_LIBRARY_DIRS: ${CRYPTO_LIBRARY_DIRS}")
message(STATUS "CRYPTO_VERSION: ${CRYPTO_VERSION}")
message(STATUS "FIDO_VERSION: ${FIDO_VERSION}")
message(STATUS "FUZZ: ${FUZZ}")
message(STATUS "ZLIB_INCLUDE_DIRS: ${ZLIB_INCLUDE_DIRS}")
message(STATUS "ZLIB_LIBRARIES: ${ZLIB_LIBRARIES}")
message(STATUS "ZLIB_LIBRARY_DIRS: ${ZLIB_LIBRARY_DIRS}")
message(STATUS "ZLIB_VERSION: ${ZLIB_VERSION}")
if(USE_HIDAPI)
message(STATUS "HIDAPI_INCLUDE_DIRS: ${HIDAPI_INCLUDE_DIRS}")
message(STATUS "HIDAPI_LIBRARIES: ${HIDAPI_LIBRARIES}")
message(STATUS "HIDAPI_LIBRARY_DIRS: ${HIDAPI_LIBRARY_DIRS}")
message(STATUS "HIDAPI_VERSION: ${HIDAPI_VERSION}")
endif()
message(STATUS "LIBFUZZER: ${LIBFUZZER}")
message(STATUS "TLS: ${TLS}")
message(STATUS "UDEV_INCLUDE_DIRS: ${UDEV_INCLUDE_DIRS}")
message(STATUS "UDEV_LIBRARIES: ${UDEV_LIBRARIES}")
message(STATUS "UDEV_LIBRARY_DIRS: ${UDEV_LIBRARY_DIRS}")
message(STATUS "UDEV_RULES_DIR: ${UDEV_RULES_DIR}")
message(STATUS "UDEV_VERSION: ${UDEV_VERSION}")
message(STATUS "USE_HIDAPI: ${USE_HIDAPI}")
message(STATUS "USE_WINHELLO: ${USE_WINHELLO}")
message(STATUS "NFC_LINUX: ${NFC_LINUX}")
subdirs(src)
if(BUILD_EXAMPLES)
subdirs(examples)
endif()
if(BUILD_TOOLS)
subdirs(tools)
endif()
if(BUILD_MANPAGES)
subdirs(man)
endif()
if(NOT WIN32)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
if(NOT LIBFUZZER AND NOT FUZZ)
subdirs(regress)
endif()
endif()
if(FUZZ)
subdirs(fuzz)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
subdirs(udev)
endif()
endif()

24
LICENSE Normal file
View File

@ -0,0 +1,24 @@
Copyright (c) 2018-2021 Yubico AB. 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.
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
HOLDER 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.

179
NEWS Normal file
View File

@ -0,0 +1,179 @@
* Version 1.8.0 (2021-07-22)
** Dropped 'Requires.private' entry from pkg-config file.
** Better support for FIDO 2.1 authenticators.
** Support for Windows's native webauthn API.
** Support for attestation format 'none'.
** New API calls:
- fido_assert_set_clientdata;
- fido_cbor_info_algorithm_cose;
- fido_cbor_info_algorithm_count;
- fido_cbor_info_algorithm_type;
- fido_cbor_info_transports_len;
- fido_cbor_info_transports_ptr;
- fido_cred_set_clientdata;
- fido_cred_set_id;
- fido_credman_set_dev_rk;
- fido_dev_is_winhello.
** fido2-token: new -Sc option to update a resident credential.
** Documentation and reliability fixes.
** HID access serialisation on Linux.
* Version 1.7.0 (2021-03-29)
** New dependency on zlib.
** Fixed musl build; gh#259.
** hid_win: detect devices with vendor or product IDs > 0x7fff; gh#264.
** Support for FIDO 2.1 authenticator configuration.
** Support for FIDO 2.1 UV token permissions.
** Support for FIDO 2.1 "credBlobs" and "largeBlobs" extensions.
** New API calls:
- fido_assert_blob_len;
- fido_assert_blob_ptr;
- fido_assert_largeblob_key_len;
- fido_assert_largeblob_key_ptr;
- fido_assert_set_hmac_secret;
- fido_cbor_info_maxcredbloblen;
- fido_cred_largeblob_key_len;
- fido_cred_largeblob_key_ptr;
- fido_cred_set_blob;
- fido_dev_enable_entattest;
- fido_dev_force_pin_change;
- fido_dev_has_uv;
- fido_dev_largeblob_get;
- fido_dev_largeblob_get_array;
- fido_dev_largeblob_remove;
- fido_dev_largeblob_set;
- fido_dev_largeblob_set_array;
- fido_dev_set_pin_minlen;
- fido_dev_set_sigmask;
- fido_dev_supports_credman;
- fido_dev_supports_permissions;
- fido_dev_supports_uv;
- fido_dev_toggle_always_uv.
** New fido_init flag to disable fido_dev_open's U2F fallback; gh#282.
** Experimental NFC support on Linux; enable with -DNFC_LINUX.
* Version 1.6.0 (2020-12-22)
** Fix OpenSSL 1.0 and Cygwin builds.
** hid_linux: fix build on 32-bit systems.
** hid_osx: allow reads from spawned threads.
** Documentation and reliability fixes.
** New API calls:
- fido_cred_authdata_raw_len;
- fido_cred_authdata_raw_ptr;
- fido_cred_sigcount;
- fido_dev_get_uv_retry_count;
- fido_dev_supports_credman.
** Hardened Windows build.
** Native FreeBSD and NetBSD support.
** Use CTAP2 canonical CBOR when combining hmac-secret and credProtect.
* Version 1.5.0 (2020-09-01)
** hid_linux: return FIDO_OK if no devices are found.
** hid_osx:
- repair communication with U2F tokens, gh#166;
- reliability fixes.
** fido2-{assert,cred}: new options to explicitly toggle UP, UV.
** Support for configurable report lengths.
** New API calls:
- fido_cbor_info_maxcredcntlst;
- fido_cbor_info_maxcredidlen;
- fido_cred_aaguid_len;
- fido_cred_aaguid_ptr;
- fido_dev_get_touch_begin;
- fido_dev_get_touch_status.
** Use COSE_ECDH_ES256 with CTAP_CBOR_CLIENT_PIN; gh#154.
** Allow CTAP messages up to 2048 bytes; gh#171.
** Ensure we only list USB devices by default.
* Version 1.4.0 (2020-04-15)
** hid_hidapi: hidapi backend; enable with -DUSE_HIDAPI=1.
** Fall back to U2F if the key claims to, but does not support FIDO2.
** FIDO2 credential protection (credprot) support.
** New API calls:
- fido_cbor_info_fwversion;
- fido_cred_prot;
- fido_cred_set_prot;
- fido_dev_set_transport_functions;
- fido_set_log_handler.
** Support for FreeBSD.
** Support for C++.
** Support for MSYS.
** Fixed EdDSA and RSA self-attestation.
* Version 1.3.1 (2020-02-19)
** fix zero-ing of le1 and le2 when talking to a U2F device.
** dropping sk-libfido2 middleware, please find it in the openssh tree.
* Version 1.3.0 (2019-11-28)
** assert/hmac: encode public key as per spec, gh#60.
** fido2-cred: fix creation of resident keys.
** fido2-{assert,cred}: support for hmac-secret extension.
** hid_osx: detect device removal, gh#56.
** hid_osx: fix device detection in MacOS Catalina.
** New API calls:
- fido_assert_set_authdata_raw;
- fido_assert_sigcount;
- fido_cred_set_authdata_raw;
- fido_dev_cancel.
** Middleware library for use by OpenSSH.
** Support for biometric enrollment.
** Support for OpenBSD.
** Support for self-attestation.
* Version 1.2.0 (released 2019-07-26)
** Credential management support.
** New API reflecting FIDO's 3-state booleans (true, false, absent):
- fido_assert_set_up;
- fido_assert_set_uv;
- fido_cred_set_rk;
- fido_cred_set_uv.
** Command-line tools for Windows.
** Documentation and reliability fixes.
** fido_{assert,cred}_set_options() are now marked as deprecated.
* Version 1.1.0 (released 2019-05-08)
** MacOS: fix IOKit crash on HID read.
** Windows: fix contents of release file.
** EdDSA (Ed25519) support.
** fido_dev_make_cred: fix order of CBOR map keys.
** fido_dev_get_assert: plug memory leak when operating on U2F devices.
* Version 1.0.0 (released 2019-03-21)
** Native HID support on Linux, MacOS, and Windows.
** fido2-{assert,cred}: new -u option to force U2F on dual authenticators.
** fido2-assert: support for multiple resident keys with the same RP.
** Strict checks for CTAP2 compliance on received CBOR payloads.
** Better fuzzing harnesses.
** Documentation and reliability fixes.
* Version 0.4.0 (released 2019-01-07)
** fido2-assert: print the user id for resident credentials.
** Fix encoding of COSE algorithms when making a credential.
** Rework purpose of fido_cred_set_type; no ABI change.
** Minor documentation and code fixes.
* Version 0.3.0 (released 2018-09-11)
** Various reliability fixes.
** Merged fuzzing instrumentation.
** Added regress tests.
** Added support for FIDO 2's hmac-secret extension.
** New API calls:
- fido_assert_hmac_secret_len;
- fido_assert_hmac_secret_ptr;
- fido_assert_set_extensions;
- fido_assert_set_hmac_salt;
- fido_cred_set_extensions;
- fido_dev_force_fido2.
** Support for native builds with Microsoft Visual Studio 17.
* Version 0.2.0 (released 2018-06-20)
** Added command-line tools.
** Added a couple of missing get functions.
* Version 0.1.1 (released 2018-06-05)
** Added documentation.
** Added OpenSSL 1.0 support.
** Minor fixes.
* Version 0.1.0 (released 2018-05-18)
** First beta release.

93
README.adoc Normal file
View File

@ -0,0 +1,93 @@
== libfido2
image:https://github.com/yubico/libfido2/workflows/linux/badge.svg["Linux Build Status (github actions)", link="https://github.com/Yubico/libfido2/actions"]
image:https://github.com/yubico/libfido2/workflows/macos/badge.svg["macOS Build Status (github actions)", link="https://github.com/Yubico/libfido2/actions"]
image:https://github.com/yubico/libfido2/workflows/windows/badge.svg["Windows Build Status (github actions)", link="https://github.com/Yubico/libfido2/actions"]
image:https://github.com/yubico/libfido2/workflows/fuzzer/badge.svg["Fuzz Status (github actions)", link="https://github.com/Yubico/libfido2/actions"]
image:https://oss-fuzz-build-logs.storage.googleapis.com/badges/libfido2.svg["Fuzz Status (oss-fuzz)", link="https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:libfido2"]
*libfido2* provides library functionality and command-line tools to
communicate with a FIDO device over USB, and to verify attestation and
assertion signatures.
*libfido2* supports the FIDO U2F (CTAP 1) and FIDO 2.0 (CTAP 2) protocols.
For usage, see the `examples/` directory.
=== License
*libfido2* is licensed under the BSD 2-clause license. See the LICENSE
file for the full license text.
=== Supported Platforms
*libfido2* is known to work on Linux, macOS, Windows, OpenBSD, and FreeBSD.
=== Documentation
Documentation is available in troff and HTML formats. An
https://developers.yubico.com/libfido2/Manuals/[online mirror of *libfido2*'s documentation]
is also available.
=== Bindings
* .NET: https://github.com/borrrden/Fido2Net[Fido2Net]
* Go: https://github.com/keys-pub/go-libfido2[go-libfido2]
* Perl: https://github.com/jacquesg/p5-FIDO-Raw[p5-FIDO-Raw]
* Rust: https://github.com/PvdBerg1998/libfido2[libfido2]
=== Installation
==== Releases
The current release of *libfido2* is 1.8.0. Please consult Yubico's
https://developers.yubico.com/libfido2/Releases[release page] for source
and binary releases.
==== Ubuntu 20.04 (Focal)
$ sudo apt install libfido2-1
$ sudo apt install libfido2-dev
$ sudo apt install libfido2-doc
Alternatively, newer versions of *libfido2* are available in Yubico's PPA.
Follow the instructions for Ubuntu 18.04 (Bionic) below.
==== Ubuntu 18.04 (Bionic)
$ sudo apt install software-properties-common
$ sudo apt-add-repository ppa:yubico/stable
$ sudo apt update
$ sudo apt install libfido2-dev
==== macOS
$ brew install libfido2
Or from source, on UNIX-like systems:
$ (rm -rf build && mkdir build && cd build && cmake ..)
$ make -C build
$ sudo make -C build install
Depending on the platform,
https://www.freedesktop.org/wiki/Software/pkg-config/[pkg-config] may need to
be installed, or the PKG_CONFIG_PATH environment variable set.
*libfido2* depends on https://github.com/pjk/libcbor[libcbor],
https://www.openssl.org[OpenSSL], and https://zlib.net[zlib]. On Linux, libudev
(part of https://www.freedesktop.org/wiki/Software/systemd[systemd]) is also
required.
For complete, OS-specific installation instructions, please refer to the
`.actions/` (Linux, macOS) and `windows/` directories.
On Linux, you will need to add a udev rule to be able to access the FIDO
device, or run as root. For example, the udev rule may contain the following:
----
#udev rule for allowing HID access to Yubico devices for FIDO support.
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", \
MODE="0664", GROUP="plugdev", ATTRS{idVendor}=="1050"
----

69
examples/CMakeLists.txt Normal file
View File

@ -0,0 +1,69 @@
# 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.
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()
# set the library to link against
if(BUILD_STATIC_LIBS)
# drop -rdynamic
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set(_FIDO2_LIBRARY fido2)
elseif(BUILD_SHARED_LIBS)
set(_FIDO2_LIBRARY fido2_shared)
else()
set(_FIDO2_LIBRARY ${CRYPTO_LIBRARIES} fido2)
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()

98
examples/README.adoc Normal file
View File

@ -0,0 +1,98 @@
= 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 NIST P-256 public key in
PEM format.
- <blobkey>
A credential's associated FIDO 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 ecdsa|rsa|eddsa] [-k pubkey] [-ei cred_id] [-P pin] [-T seconds]
[-b blobkey] [-hruv] <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>.
- assert [-t ecdsa|rsa|eddsa] [-a cred_id] [-h hmac_secret] [-s hmac_salt]
[-P pin] [-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. User verification may be requested through the -v
option. 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.

342
examples/assert.c Normal file
View File

@ -0,0 +1,342 @@
/*
* 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.
*/
#include <fido.h>
#include <fido/es256.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 cdh[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 ecdsa|rsa|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;
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_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_hash(assert, cdh, sizeof(cdh));
if (r != FIDO_OK)
errx(1, "fido_assert_set_clientdata_hash: %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);
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 seconds = 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':
#ifndef SIGNAL_EXAMPLE
(void)seconds;
errx(1, "-T not supported");
#else
if (base10(optarg, &seconds) < 0)
errx(1, "base10: %s", optarg);
if (seconds <= 0 || seconds > 30)
errx(1, "-T: %s must be in (0,30]", optarg);
break;
#endif
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, "ecdsa") == 0)
type = COSE_ES256;
else if (strcmp(optarg, "rsa") == 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_hash(assert, cdh, sizeof(cdh));
if (r != FIDO_OK)
errx(1, "fido_assert_set_clientdata_hash: %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);
#ifdef SIGNAL_EXAMPLE
prepare_signal_handler(SIGINT);
if (seconds) {
prepare_signal_handler(SIGALRM);
alarm((unsigned)seconds);
}
#endif
r = fido_dev_get_assert(dev, assert, pin);
if (r != FIDO_OK) {
#ifdef SIGNAL_EXAMPLE
if (got_signal)
fido_dev_cancel(dev);
#endif
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);
}

346
examples/cred.c Normal file
View File

@ -0,0 +1,346 @@
/*
* 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.
*/
#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 cdh[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 ecdsa|rsa|eddsa] [-k pubkey] "
"[-ei cred_id] [-P pin] [-T seconds] [-b blobkey] [-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 *x509_ptr, size_t x509_len,
const unsigned char *sig_ptr, size_t sig_len, bool rk, bool uv, int ext,
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 hash */
r = fido_cred_set_clientdata_hash(cred, cdh, sizeof(cdh));
if (r != FIDO_OK)
errx(1, "fido_cred_set_clientdata_hash: %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);
/* 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;
}
/* x509 */
r = fido_cred_set_x509(cred, x509_ptr, x509_len);
if (r != FIDO_OK)
errx(1, "fido_cred_set_x509: %s (0x%x)", fido_strerr(r), r);
/* sig */
r = fido_cred_set_sig(cred, sig_ptr, sig_len);
if (r != FIDO_OK)
errx(1, "fido_cred_set_sig: %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_ec_pubkey(key_out, fido_cred_pubkey_ptr(cred),
fido_cred_pubkey_len(cred)) < 0)
errx(1, "write_ec_pubkey");
} else if (type == COSE_RS256) {
if (write_rsa_pubkey(key_out, fido_cred_pubkey_ptr(cred),
fido_cred_pubkey_len(cred)) < 0)
errx(1, "write_rsa_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);
}
static fido_dev_t *
open_from_manifest(const fido_dev_info_t *dev_infos, size_t len,
const char *path)
{
size_t i;
fido_dev_t *dev;
for (i = 0; i < len; i++) {
const fido_dev_info_t *curr = fido_dev_info_ptr(dev_infos, i);
if (path == NULL ||
strcmp(path, fido_dev_info_path(curr)) == 0) {
dev = fido_dev_new_with_info(curr);
if (fido_dev_open_with_info(dev) == FIDO_OK)
return (dev);
fido_dev_free(&dev);
}
}
return (NULL);
}
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;
const char *path = NULL;
unsigned char *body = NULL;
long long seconds = 0;
size_t len;
int type = COSE_ES256;
int ext = 0;
int ch;
int r;
fido_dev_info_t *dev_infos = NULL;
size_t dev_infos_len = 0;
if ((cred = fido_cred_new()) == NULL)
errx(1, "fido_cred_new");
while ((ch = getopt(argc, argv, "P:T:b:e:hi:k:rt:uv")) != -1) {
switch (ch) {
case 'P':
pin = optarg;
break;
case 'T':
#ifndef SIGNAL_EXAMPLE
(void)seconds;
errx(1, "-T not supported");
#else
if (base10(optarg, &seconds) < 0)
errx(1, "base10: %s", optarg);
if (seconds <= 0 || seconds > 30)
errx(1, "-T: %s must be in (0,30]", optarg);
break;
#endif
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 'i':
id_out = optarg;
break;
case 'k':
key_out = optarg;
break;
case 'r':
rk = true;
break;
case 't':
if (strcmp(optarg, "ecdsa") == 0)
type = COSE_ES256;
else if (strcmp(optarg, "rsa") == 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();
}
}
fido_init(0);
argc -= optind;
argv += optind;
if (argc > 1)
usage();
dev_infos = fido_dev_info_new(16);
fido_dev_info_manifest(dev_infos, 16, &dev_infos_len);
if (argc == 1)
path = argv[0];
if ((dev = open_from_manifest(dev_infos, dev_infos_len, path)) == NULL)
errx(1, "open_from_manifest");
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 hash */
r = fido_cred_set_clientdata_hash(cred, cdh, sizeof(cdh));
if (r != FIDO_OK)
errx(1, "fido_cred_set_clientdata_hash: %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);
#ifdef SIGNAL_EXAMPLE
prepare_signal_handler(SIGINT);
if (seconds) {
prepare_signal_handler(SIGALRM);
alarm((unsigned)seconds);
}
#endif
r = fido_dev_make_cred(dev, cred, pin);
if (r != FIDO_OK) {
#ifdef SIGNAL_EXAMPLE
if (got_signal)
fido_dev_cancel(dev);
#endif
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_x5c_ptr(cred),
fido_cred_x5c_len(cred), fido_cred_sig_ptr(cred),
fido_cred_sig_len(cred), rk, uv, ext, 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);
}

33
examples/extern.h Normal file
View File

@ -0,0 +1,33 @@
/*
* 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.
*/
#ifndef _EXTERN_H_
#define _EXTERN_H_
#include <openssl/ec.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
/* 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_ec_pubkey(const char *, const void *, size_t);
int write_rsa_pubkey(const char *, const void *, size_t);
int write_eddsa_pubkey(const char *, const void *, size_t);
#ifdef SIGNAL_EXAMPLE
void prepare_signal_handler(int);
extern volatile sig_atomic_t got_signal;
#endif
#endif /* _EXTERN_H_ */

293
examples/info.c Normal file
View File

@ -0,0 +1,293 @@
/*
* 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.
*/
#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 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_EDDSA:
cose = "eddsa";
break;
case COSE_ES256:
cose = "es256";
break;
case COSE_RS256:
cose = "rs256";
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 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 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 firmware version */
print_fwversion(fido_cbor_info_fwversion(ci));
/* print supported pin protocols */
print_byte_array("pin protocols", fido_cbor_info_protocols_ptr(ci),
fido_cbor_info_protocols_len(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);
}

41
examples/manifest.c Normal file
View File

@ -0,0 +1,41 @@
/*
* 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.
*/
#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);
}

55
examples/reset.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.
*/
/*
* 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);
#ifdef SIGNAL_EXAMPLE
prepare_signal_handler(SIGINT);
#endif
if ((r = fido_dev_reset(dev)) != FIDO_OK) {
#ifdef SIGNAL_EXAMPLE
if (got_signal)
fido_dev_cancel(dev);
#endif
errx(1, "fido_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);
}

48
examples/retries.c Normal file
View File

@ -0,0 +1,48 @@
/*
* 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.
*/
/*
* 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_get_retries: %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);
}

214
examples/select.c Normal file
View File

@ -0,0 +1,214 @@
/*
* 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.
*/
#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(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);
}

54
examples/setpin.c Normal file
View File

@ -0,0 +1,54 @@
/*
* 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.
*/
/*
* 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_setpin: %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);
}

413
examples/util.c Normal file
View File

@ -0,0 +1,413 @@
/*
* 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.
*/
#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/rs256.h>
#include <fido/eddsa.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#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"
#ifdef SIGNAL_EXAMPLE
volatile sig_atomic_t got_signal = 0;
static void
signal_handler(int signo)
{
(void)signo;
got_signal = 1;
}
void
prepare_signal_handler(int signo)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = signal_handler;
if (sigaction(signo, &sa, NULL) < 0)
err(1, "sigaction");
}
#endif
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_ec_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);
}
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_rsa_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);
}

63
fuzz/CMakeLists.txt Normal file
View File

@ -0,0 +1,63 @@
# 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.
list(APPEND COMPAT_SOURCES
../openbsd-compat/strlcpy.c
../openbsd-compat/strlcat.c
)
list(APPEND COMMON_SOURCES
libfuzzer.c
mutator_aux.c
)
set(FUZZ_LDFLAGS "-fsanitize=fuzzer")
# fuzz_cred
add_executable(fuzz_cred fuzz_cred.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
target_compile_options(fuzz_cred PRIVATE ${FUZZ_LDFLAGS})
set_target_properties(fuzz_cred PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})
target_link_libraries(fuzz_cred fido2_shared)
# fuzz_assert
add_executable(fuzz_assert fuzz_assert.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
target_compile_options(fuzz_assert PRIVATE ${FUZZ_LDFLAGS})
set_target_properties(fuzz_assert PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})
target_link_libraries(fuzz_assert fido2_shared)
# fuzz_mgmt
add_executable(fuzz_mgmt fuzz_mgmt.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
target_compile_options(fuzz_mgmt PRIVATE ${FUZZ_LDFLAGS})
set_target_properties(fuzz_mgmt PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})
target_link_libraries(fuzz_mgmt fido2_shared)
# fuzz_credman
add_executable(fuzz_credman fuzz_credman.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
target_compile_options(fuzz_credman PRIVATE ${FUZZ_LDFLAGS})
set_target_properties(fuzz_credman PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})
target_link_libraries(fuzz_credman fido2_shared)
# fuzz_bio
add_executable(fuzz_bio fuzz_bio.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
target_compile_options(fuzz_bio PRIVATE ${FUZZ_LDFLAGS})
set_target_properties(fuzz_bio PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})
target_link_libraries(fuzz_bio fido2_shared)
# fuzz_hid
add_executable(fuzz_hid fuzz_hid.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
target_compile_options(fuzz_hid PRIVATE ${FUZZ_LDFLAGS})
set_target_properties(fuzz_hid PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})
target_link_libraries(fuzz_hid fido2_shared)
# fuzz_netlink
add_executable(fuzz_netlink fuzz_netlink.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
target_compile_options(fuzz_netlink PRIVATE ${FUZZ_LDFLAGS})
set_target_properties(fuzz_netlink PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})
target_link_libraries(fuzz_netlink fido2_shared)
# fuzz_largeblob
add_executable(fuzz_largeblob fuzz_largeblob.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
target_compile_options(fuzz_largeblob PRIVATE ${FUZZ_LDFLAGS})
set_target_properties(fuzz_largeblob PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})
target_link_libraries(fuzz_largeblob fido2_shared)

12
fuzz/Dockerfile Normal file
View File

@ -0,0 +1,12 @@
# 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.
FROM ubuntu:focal
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install -y clang-11 cmake git libssl-dev libudev-dev make pkg-config
RUN apt-get install -y zlib1g-dev
RUN git clone --branch v0.8.0 https://github.com/PJK/libcbor
RUN git clone https://github.com/yubico/libfido2
RUN CC=clang-11 CXX=clang++-11 /libfido2/fuzz/build-coverage /libcbor /libfido2

79
fuzz/Makefile Normal file
View File

@ -0,0 +1,79 @@
# 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.
IMAGE := libfido2-coverage:1.8.0
RUNNER := libfido2-runner
PROFDATA := llvm-profdata-11
COV := llvm-cov-11
TARGETS := fuzz_assert fuzz_bio fuzz_cred fuzz_credman fuzz_hid \
fuzz_largeblob fuzz_netlink fuzz_mgmt
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=/$< \
-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 \
/libfido2/build/src/libfido2.so -instr-profile=/$< > $@
functions.txt: profdata
docker exec ${RUNNER} /bin/sh -c '${COV} report -use-color=false \
-show-functions -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=) $@
corpus.tgz: ${CORPORA}
tar zcf $@ ${TARGETS}
.PHONY: build run sync corpus ${TARGETS} ${CORPORA}
.PHONY: report.tgz summary.txt functions.txt

33
fuzz/README Normal file
View File

@ -0,0 +1,33 @@
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 -DFUZZ=ON -DLIBFUZZER=ON.
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.
diff --git src/cbor/internal/memory_utils.c src/cbor/internal/memory_utils.c
index aa049a2..e294b38 100644
--- src/cbor/internal/memory_utils.c
+++ src/cbor/internal/memory_utils.c
@@ -28,7 +28,10 @@ bool _cbor_safe_to_multiply(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;
}

31
fuzz/build-coverage Executable file
View File

@ -0,0 +1,31 @@
#!/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.
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 LDFLAGS="${CFLAGS}"
(cd "${LIBFIDO2}/build" && cmake -DFUZZ=ON -DLIBFUZZER=ON \
-DCMAKE_BUILD_TYPE=Debug ..)
make -C "${LIBFIDO2}/build"

96
fuzz/dummy.h Normal file
View File

@ -0,0 +1,96 @@
/*
* 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.
*/
#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 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,
};
#endif /* !_DUMMY_H */

242
fuzz/export.gnu Normal file
View File

@ -0,0 +1,242 @@
{
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_ptr;
es256_pk_new;
es256_pk_to_EVP_PKEY;
fido_assert_allow_cred;
fido_assert_authdata_len;
fido_assert_authdata_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_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_extensions_len;
fido_cbor_info_extensions_ptr;
fido_cbor_info_free;
fido_cbor_info_maxmsgsiz;
fido_cbor_info_maxcredbloblen;
fido_cbor_info_maxcredcntlst;
fido_cbor_info_maxcredidlen;
fido_cbor_info_fwversion;
fido_cbor_info_new;
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_transports_len;
fido_cbor_info_transports_ptr;
fido_cbor_info_versions_len;
fido_cbor_info_versions_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_prot;
fido_cred_pubkey_len;
fido_cred_pubkey_ptr;
fido_cred_rp_id;
fido_cred_rp_name;
fido_cred_set_authdata;
fido_cred_set_authdata_raw;
fido_cred_set_blob;
fido_cred_set_clientdata_hash;
fido_cred_set_extensions;
fido_cred_set_fmt;
fido_cred_set_id;
fido_cred_set_options;
fido_cred_set_prot;
fido_cred_set_rk;
fido_cred_set_rp;
fido_cred_set_sig;
fido_cred_set_type;
fido_cred_set_user;
fido_cred_set_uv;
fido_cred_set_x509;
fido_cred_sig_len;
fido_cred_sig_ptr;
fido_cred_type;
fido_cred_user_id_len;
fido_cred_user_id_ptr;
fido_cred_user_name;
fido_cred_verify;
fido_cred_verify_self;
fido_cred_x5c_len;
fido_cred_x5c_ptr;
fido_dev_build;
fido_dev_cancel;
fido_dev_close;
fido_dev_enable_entattest;
fido_dev_flags;
fido_dev_force_fido2;
fido_dev_force_pin_change;
fido_dev_force_u2f;
fido_dev_free;
fido_dev_get_assert;
fido_dev_get_cbor_info;
fido_dev_get_retry_count;
fido_dev_get_uv_retry_count;
fido_dev_get_touch_begin;
fido_dev_get_touch_status;
fido_dev_has_pin;
fido_dev_has_uv;
fido_dev_info_free;
fido_dev_info_manifest;
fido_dev_info_manufacturer_string;
fido_dev_info_new;
fido_dev_info_path;
fido_dev_info_product;
fido_dev_info_product_string;
fido_dev_info_ptr;
fido_dev_info_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_pin;
fido_dev_set_pin_minlen;
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_set_log_handler;
fido_strerr;
rs256_pk_free;
rs256_pk_from_ptr;
rs256_pk_from_RSA;
rs256_pk_new;
rs256_pk_to_EVP_PKEY;
prng_init;
set_netlink_io_functions;
set_udev_parameters;
uniform_random;
local:
*;
};

807
fuzz/functions.txt Normal file
View File

@ -0,0 +1,807 @@
File '/libfido2/src/aes256.c':
Name Regions Miss Cover Lines Miss Cover
------------------------------------------------------------------------------
aes256_cbc_enc 3 0 100.00% 4 0 100.00%
aes256_cbc_dec 3 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 2 92.31% 45 7 84.44%
aes256.c:aes256_cbc 29 1 96.55% 40 3 92.50%
aes256.c:aes256_cbc_proto1 1 0 100.00% 7 0 100.00%
aes256.c:aes256_gcm 51 1 98.04% 69 4 94.20%
------------------------------------------------------------------------------
TOTAL 115 4 96.52% 175 14 92.00%
File '/libfido2/src/assert.c':
Name Regions Miss Cover Lines Miss Cover
---------------------------------------------------------------------------------------
fido_dev_get_assert 40 0 100.00% 41 0 100.00%
fido_check_flags 13 0 100.00% 18 0 100.00%
fido_get_signed_hash 32 0 100.00% 46 0 100.00%
fido_verify_sig_es256 17 2 88.24% 31 7 77.42%
fido_verify_sig_rs256 17 2 88.24% 31 7 77.42%
fido_verify_sig_eddsa 23 2 91.30% 43 7 83.72%
fido_assert_verify 48 4 91.67% 79 5 93.67%
fido_assert_set_clientdata 12 12 0.00% 12 12 0.00%
fido_assert_set_clientdata_hash 8 0 100.00% 7 0 100.00%
fido_assert_set_hmac_salt 10 0 100.00% 7 0 100.00%
fido_assert_set_hmac_secret 12 12 0.00% 8 8 0.00%
fido_assert_set_rp 12 0 100.00% 14 0 100.00%
fido_assert_allow_cred 13 2 84.62% 29 3 89.66%
fido_assert_set_extensions 14 0 100.00% 11 0 100.00%
fido_assert_set_options 6 6 0.00% 6 6 0.00%
fido_assert_set_up 2 0 100.00% 5 0 100.00%
fido_assert_set_uv 2 0 100.00% 5 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% 12 0 100.00%
fido_assert_reset_rx 4 0 100.00% 19 0 100.00%
fido_assert_free 6 0 100.00% 10 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% 6 0 100.00%
fido_assert_sigcount 4 0 100.00% 6 0 100.00%
fido_assert_authdata_ptr 4 0 100.00% 6 0 100.00%
fido_assert_authdata_len 4 0 100.00% 6 0 100.00%
fido_assert_sig_ptr 4 0 100.00% 6 0 100.00%
fido_assert_sig_len 4 0 100.00% 6 0 100.00%
fido_assert_id_ptr 4 0 100.00% 6 0 100.00%
fido_assert_id_len 4 0 100.00% 6 0 100.00%
fido_assert_user_id_ptr 4 0 100.00% 6 0 100.00%
fido_assert_user_id_len 4 0 100.00% 6 0 100.00%
fido_assert_user_icon 4 0 100.00% 6 0 100.00%
fido_assert_user_name 4 0 100.00% 6 0 100.00%
fido_assert_user_display_name 4 0 100.00% 6 0 100.00%
fido_assert_hmac_secret_ptr 4 0 100.00% 6 0 100.00%
fido_assert_hmac_secret_len 4 0 100.00% 6 0 100.00%
fido_assert_largeblob_key_ptr 4 0 100.00% 6 0 100.00%
fido_assert_largeblob_key_len 4 0 100.00% 6 0 100.00%
fido_assert_blob_ptr 4 0 100.00% 6 0 100.00%
fido_assert_blob_len 4 0 100.00% 6 0 100.00%
fido_assert_set_authdata 24 0 100.00% 35 0 100.00%
fido_assert_set_authdata_raw 24 0 100.00% 34 0 100.00%
fido_assert_set_sig 14 0 100.00% 8 0 100.00%
fido_assert_set_count 10 0 100.00% 21 0 100.00%
assert.c:fido_dev_get_assert_wait 21 0 100.00% 16 0 100.00%
assert.c:fido_dev_get_assert_tx 56 2 96.43% 77 5 93.51%
assert.c:fido_dev_get_assert_rx 19 0 100.00% 38 0 100.00%
assert.c:adjust_assert_count 24 0 100.00% 33 0 100.00%
assert.c:parse_assert_reply 12 0 100.00% 26 0 100.00%
assert.c:fido_get_next_assert_tx 8 0 100.00% 10 0 100.00%
assert.c:fido_get_next_assert_rx 15 2 86.67% 26 4 84.62%
assert.c:decrypt_hmac_secrets 9 0 100.00% 16 0 100.00%
assert.c:check_extensions 5 0 100.00% 11 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% 5 0 100.00%
---------------------------------------------------------------------------------------
TOTAL 616 46 92.53% 924 64 93.07%
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% 9 0 100.00%
authkey.c:fido_dev_authkey_tx 19 0 100.00% 33 0 100.00%
authkey.c:fido_dev_authkey_rx 6 0 100.00% 18 0 100.00%
authkey.c:parse_authkey 8 0 100.00% 12 0 100.00%
---------------------------------------------------------------------------------------
TOTAL 44 0 100.00% 75 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 0 100.00%
fido_bio_dev_set_template_name 7 0 100.00% 6 0 100.00%
fido_bio_dev_enroll_begin 25 2 92.00% 37 0 100.00%
fido_bio_dev_enroll_continue 5 2 60.00% 6 0 100.00%
fido_bio_dev_enroll_cancel 1 1 0.00% 3 3 0.00%
fido_bio_dev_enroll_remove 1 0 100.00% 3 0 100.00%
fido_bio_dev_get_info 1 0 100.00% 3 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% 10 0 100.00%
fido_bio_template_free 6 0 100.00% 10 0 100.00%
fido_bio_template_set_name 8 0 100.00% 9 0 100.00%
fido_bio_template_set_id 8 0 100.00% 8 0 100.00%
fido_bio_template 4 0 100.00% 6 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% 11 0 100.00%
fido_bio_info_free 6 0 100.00% 9 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% 9 0 100.00%
bio.c:bio_tx 43 0 100.00% 66 0 100.00%
bio.c:bio_prepare_hmac 18 0 100.00% 36 0 100.00%
bio.c:bio_rx_template_array 11 0 100.00% 21 0 100.00%
bio.c:bio_parse_template_array 26 1 96.15% 34 4 88.24%
bio.c:decode_template_array 12 1 91.67% 23 3 86.96%
bio.c:decode_template 9 0 100.00% 18 0 100.00%
bio.c:bio_set_template_name_wait 19 0 100.00% 24 0 100.00%
bio.c:bio_enroll_begin_wait 17 0 100.00% 24 0 100.00%
bio.c:bio_rx_enroll_begin 15 0 100.00% 29 0 100.00%
bio.c:bio_parse_enroll_status 20 0 100.00% 31 0 100.00%
bio.c:bio_parse_template_id 8 0 100.00% 12 0 100.00%
bio.c:bio_enroll_continue_wait 19 0 100.00% 25 0 100.00%
bio.c:bio_rx_enroll_continue 11 0 100.00% 22 0 100.00%
bio.c:bio_enroll_cancel_wait 11 11 0.00% 12 12 0.00%
bio.c:bio_enroll_remove_wait 17 0 100.00% 24 0 100.00%
bio.c:bio_get_info_wait 11 0 100.00% 11 0 100.00%
bio.c:bio_rx_info 11 0 100.00% 21 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% 31 0 100.00%
bio.c:bio_reset_template_array 4 0 100.00% 8 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% 7 0 100.00%
---------------------------------------------------------------------------------------
TOTAL 419 20 95.23% 660 22 96.67%
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% 19 0 100.00%
fido_blob_append 12 2 83.33% 22 6 72.73%
fido_blob_free 6 0 100.00% 10 0 100.00%
fido_free_blob_array 7 0 100.00% 14 0 100.00%
fido_blob_encode 6 0 100.00% 6 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% 12 1 91.67%
---------------------------------------------------------------------------------------
TOTAL 53 3 94.34% 96 7 92.71%
File '/libfido2/src/buf.c':
Name Regions Miss Cover Lines Miss Cover
---------------------------------------------------------------------------------------
fido_buf_read 4 0 100.00% 10 0 100.00%
fido_buf_write 4 1 75.00% 10 1 90.00%
---------------------------------------------------------------------------------------
TOTAL 8 1 87.50% 20 1 95.00%
File '/libfido2/src/cbor.c':
Name Regions Miss Cover Lines Miss Cover
----------------------------------------------------------------------------------------
cbor_map_iter 20 1 95.00% 30 4 86.67%
cbor_array_iter 12 0 100.00% 20 0 100.00%
cbor_parse_reply 27 0 100.00% 43 0 100.00%
cbor_vector_free 6 0 100.00% 5 0 100.00%
cbor_bytestring_copy 14 0 100.00% 22 0 100.00%
cbor_string_copy 14 0 100.00% 23 0 100.00%
cbor_add_bytestring 14 0 100.00% 26 0 100.00%
cbor_add_string 14 0 100.00% 26 0 100.00%
cbor_add_bool 14 0 100.00% 26 0 100.00%
cbor_flatten_vector 14 1 92.86% 21 1 95.24%
cbor_build_frame 15 0 100.00% 32 0 100.00%
cbor_encode_rp_entity 13 0 100.00% 14 0 100.00%
cbor_encode_user_entity 21 0 100.00% 18 0 100.00%
cbor_encode_pubkey_param 36 0 100.00% 48 0 100.00%
cbor_encode_pubkey 10 0 100.00% 13 0 100.00%
cbor_encode_pubkey_list 18 0 100.00% 23 0 100.00%
cbor_encode_cred_ext 46 0 100.00% 46 0 100.00%
cbor_encode_cred_opt 13 0 100.00% 13 0 100.00%
cbor_encode_assert_opt 13 0 100.00% 13 0 100.00%
cbor_encode_pin_auth 20 1 95.00% 30 3 90.00%
cbor_encode_pin_opt 4 0 100.00% 10 0 100.00%
cbor_encode_change_pin_auth 33 1 96.97% 49 3 93.88%
cbor_encode_assert_ext 33 0 100.00% 35 0 100.00%
cbor_decode_fmt 11 0 100.00% 19 0 100.00%
cbor_decode_pubkey 21 1 95.24% 32 2 93.75%
cbor_decode_cred_authdata 31 1 96.77% 45 3 93.33%
cbor_decode_assert_authdata 21 0 100.00% 42 0 100.00%
cbor_decode_attstmt 8 0 100.00% 10 0 100.00%
cbor_decode_uint64 4 0 100.00% 10 0 100.00%
cbor_decode_cred_id 8 0 100.00% 10 0 100.00%
cbor_decode_user 8 0 100.00% 10 0 100.00%
cbor_decode_rp_entity 8 0 100.00% 10 0 100.00%
cbor_build_uint 10 4 60.00% 10 5 50.00%
cbor_array_append 17 0 100.00% 23 0 100.00%
cbor_array_drop 18 2 88.89% 19 3 84.21%
cbor.c:ctap_check_cbor 28 0 100.00% 32 0 100.00%
cbor.c:check_key_type 8 0 100.00% 9 0 100.00%
cbor.c:cbor_add_arg 13 0 100.00% 28 0 100.00%
cbor.c:cbor_add_uint8 14 0 100.00% 26 0 100.00%
cbor.c:cbor_encode_largeblob_key_ext 6 0 100.00% 7 0 100.00%
cbor.c:cbor_encode_hmac_secret_param 53 2 96.23% 75 4 94.67%
cbor.c:get_cose_alg 36 0 100.00% 48 0 100.00%
cbor.c:find_cose_alg 35 0 100.00% 40 0 100.00%
cbor.c:decode_attcred 25 0 100.00% 56 0 100.00%
cbor.c:decode_cred_extensions 14 0 100.00% 31 0 100.00%
cbor.c:decode_cred_extension 40 3 92.50% 45 9 80.00%
cbor.c:decode_assert_extensions 14 0 100.00% 29 0 100.00%
cbor.c:decode_assert_extension 19 0 100.00% 31 0 100.00%
cbor.c:decode_attstmt_entry 38 0 100.00% 44 0 100.00%
cbor.c:decode_x5c 4 0 100.00% 8 0 100.00%
cbor.c:decode_cred_id_entry 10 0 100.00% 23 0 100.00%
cbor.c:decode_user_entry 25 0 100.00% 39 0 100.00%
cbor.c:decode_rp_entity_entry 15 0 100.00% 29 0 100.00%
----------------------------------------------------------------------------------------
TOTAL 986 17 98.28% 1426 37 97.41%
File '/libfido2/src/compress.c':
Name Regions Miss Cover Lines Miss Cover
----------------------------------------------------------------------------------------
fido_compress 1 0 100.00% 3 0 100.00%
fido_uncompress 1 0 100.00% 3 0 100.00%
compress.c:do_compress 32 4 87.50% 24 3 87.50%
----------------------------------------------------------------------------------------
TOTAL 34 4 88.24% 30 3 90.00%
File '/libfido2/src/config.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_dev_enable_entattest 1 0 100.00% 3 0 100.00%
fido_dev_toggle_always_uv 1 0 100.00% 3 0 100.00%
fido_dev_set_pin_minlen 1 0 100.00% 3 0 100.00%
fido_dev_force_pin_change 1 0 100.00% 3 0 100.00%
config.c:config_enable_entattest_wait 6 0 100.00% 8 0 100.00%
config.c:config_tx 37 0 100.00% 57 0 100.00%
config.c:config_prepare_hmac 8 1 87.50% 22 3 86.36%
config.c:config_toggle_always_uv_wait 6 0 100.00% 8 0 100.00%
config.c:config_pin_minlen 5 0 100.00% 8 0 100.00%
config.c:config_pin_minlen_tx 28 0 100.00% 31 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 94 1 98.94% 146 3 97.95%
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% 14 0 100.00%
fido_cred_verify 50 4 92.00% 75 8 89.33%
fido_cred_verify_self 58 6 89.66% 94 10 89.36%
fido_cred_new 1 0 100.00% 3 0 100.00%
fido_cred_reset_tx 1 0 100.00% 22 0 100.00%
fido_cred_reset_rx 1 0 100.00% 8 0 100.00%
fido_cred_free 6 0 100.00% 10 0 100.00%
fido_cred_set_authdata 23 0 100.00% 37 0 100.00%
fido_cred_set_authdata_raw 25 0 100.00% 38 0 100.00%
fido_cred_set_id 6 0 100.00% 6 0 100.00%
fido_cred_set_x509 6 0 100.00% 6 0 100.00%
fido_cred_set_sig 6 0 100.00% 6 0 100.00%
fido_cred_exclude 14 2 85.71% 25 3 88.00%
fido_cred_set_clientdata 12 12 0.00% 12 12 0.00%
fido_cred_set_clientdata_hash 8 0 100.00% 7 0 100.00%
fido_cred_set_rp 18 0 100.00% 26 0 100.00%
fido_cred_set_user 32 0 100.00% 46 0 100.00%
fido_cred_set_extensions 15 0 100.00% 11 0 100.00%
fido_cred_set_options 6 6 0.00% 6 6 0.00%
fido_cred_set_rk 2 0 100.00% 5 0 100.00%
fido_cred_set_uv 2 0 100.00% 5 0 100.00%
fido_cred_set_prot 21 0 100.00% 16 0 100.00%
fido_cred_set_blob 13 2 84.62% 10 1 90.00%
fido_cred_set_fmt 18 4 77.78% 16 1 93.75%
fido_cred_set_type 17 0 100.00% 9 0 100.00%
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_pubkey_ptr 9 0 100.00% 20 0 100.00%
fido_cred_pubkey_len 9 0 100.00% 20 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_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% 9 0 100.00%
cred.c:fido_dev_make_cred_tx 64 0 100.00% 85 0 100.00%
cred.c:fido_dev_make_cred_rx 19 0 100.00% 27 0 100.00%
cred.c:parse_makecred_reply 14 0 100.00% 29 0 100.00%
cred.c:check_extensions 2 0 100.00% 9 0 100.00%
cred.c:get_signed_hash_u2f 22 0 100.00% 20 0 100.00%
cred.c:verify_sig 27 2 92.59% 40 7 82.50%
cred.c:fido_cred_clean_authdata 1 0 100.00% 9 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 581 38 93.46% 872 48 94.50%
File '/libfido2/src/credman.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_credman_get_dev_metadata 1 0 100.00% 3 0 100.00%
fido_credman_get_dev_rk 1 0 100.00% 3 0 100.00%
fido_credman_del_dev_rk 1 0 100.00% 3 0 100.00%
fido_credman_get_dev_rp 1 0 100.00% 3 0 100.00%
fido_credman_set_dev_rk 1 0 100.00% 3 0 100.00%
fido_credman_rk_new 1 0 100.00% 3 0 100.00%
fido_credman_rk_free 6 1 83.33% 10 0 100.00%
fido_credman_rk_count 1 0 100.00% 3 0 100.00%
fido_credman_rk 4 0 100.00% 6 0 100.00%
fido_credman_metadata_new 1 0 100.00% 3 0 100.00%
fido_credman_metadata_free 6 1 83.33% 9 0 100.00%
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% 10 0 100.00%
fido_credman_rp_count 1 0 100.00% 3 0 100.00%
fido_credman_rp_id 4 0 100.00% 6 0 100.00%
fido_credman_rp_name 4 0 100.00% 6 0 100.00%
fido_credman_rp_id_hash_len 4 0 100.00% 6 0 100.00%
fido_credman_rp_id_hash_ptr 4 0 100.00% 6 0 100.00%
credman.c:credman_get_metadata_wait 11 0 100.00% 10 0 100.00%
credman.c:credman_tx 36 0 100.00% 60 0 100.00%
credman.c:credman_prepare_hmac 31 1 96.77% 56 2 96.43%
credman.c:credman_rx_metadata 11 0 100.00% 21 0 100.00%
credman.c:credman_parse_metadata 9 0 100.00% 19 0 100.00%
credman.c:credman_get_rk_wait 27 0 100.00% 28 0 100.00%
credman.c:credman_rx_rk 19 0 100.00% 36 0 100.00%
credman.c:credman_parse_rk_count 16 0 100.00% 25 0 100.00%
credman.c:credman_grow_array 17 2 88.24% 28 5 82.14%
credman.c:credman_parse_rk 23 0 100.00% 33 0 100.00%
credman.c:credman_rx_next_rk 15 2 86.67% 26 4 84.62%
credman.c:credman_del_rk_wait 16 0 100.00% 20 0 100.00%
credman.c:credman_get_rp_wait 23 0 100.00% 18 0 100.00%
credman.c:credman_rx_rp 19 0 100.00% 36 0 100.00%
credman.c:credman_parse_rp_count 16 0 100.00% 25 0 100.00%
credman.c:credman_parse_rp 9 0 100.00% 19 0 100.00%
credman.c:credman_rx_next_rp 15 2 86.67% 26 4 84.62%
credman.c:credman_set_dev_rk_wait 11 0 100.00% 10 0 100.00%
credman.c:credman_reset_rk 4 0 100.00% 10 0 100.00%
credman.c:credman_reset_rp 4 0 100.00% 13 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 382 10 97.38% 614 15 97.56%
File '/libfido2/src/dev.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_dev_register_manifest_func 10 2 80.00% 18 3 83.33%
fido_dev_unregister_manifest_func 7 7 0.00% 13 13 0.00%
fido_dev_info_manifest 22 4 81.82% 28 0 100.00%
fido_dev_open_with_info 5 5 0.00% 6 6 0.00%
fido_dev_open 11 5 54.55% 26 12 53.85%
fido_dev_close 9 2 77.78% 10 0 100.00%
fido_dev_set_sigmask 12 12 0.00% 10 10 0.00%
fido_dev_cancel 11 0 100.00% 8 0 100.00%
fido_dev_get_touch_begin 50 0 100.00% 68 0 100.00%
fido_dev_get_touch_status 17 0 100.00% 25 0 100.00%
fido_dev_set_io_functions 18 4 77.78% 17 6 64.71%
fido_dev_set_transport_functions 6 2 66.67% 11 3 72.73%
fido_init 8 1 87.50% 6 0 100.00%
fido_dev_new 5 0 100.00% 16 0 100.00%
fido_dev_new_with_info 10 10 0.00% 20 20 0.00%
fido_dev_free 6 0 100.00% 11 0 100.00%
fido_dev_protocol 1 0 100.00% 3 0 100.00%
fido_dev_major 1 0 100.00% 3 0 100.00%
fido_dev_minor 1 0 100.00% 3 0 100.00%
fido_dev_build 1 0 100.00% 3 0 100.00%
fido_dev_flags 1 0 100.00% 3 0 100.00%
fido_dev_is_fido2 2 0 100.00% 3 0 100.00%
fido_dev_is_winhello 2 2 0.00% 3 3 0.00%
fido_dev_supports_pin 3 0 100.00% 3 0 100.00%
fido_dev_has_pin 2 0 100.00% 3 0 100.00%
fido_dev_supports_cred_prot 2 0 100.00% 3 0 100.00%
fido_dev_supports_credman 2 0 100.00% 3 0 100.00%
fido_dev_supports_uv 3 0 100.00% 3 0 100.00%
fido_dev_has_uv 2 0 100.00% 3 0 100.00%
fido_dev_supports_permissions 2 0 100.00% 3 0 100.00%
fido_dev_force_u2f 2 0 100.00% 4 0 100.00%
fido_dev_force_fido2 2 2 0.00% 3 3 0.00%
fido_dev_get_pin_protocol 11 0 100.00% 8 0 100.00%
fido_dev_maxmsgsize 1 0 100.00% 3 0 100.00%
dev.c:find_manifest_func_node 5 0 100.00% 9 0 100.00%
dev.c:fido_dev_open_wait 10 0 100.00% 9 0 100.00%
dev.c:fido_dev_open_tx 56 15 73.21% 67 26 61.19%
dev.c:set_random_report_len 11 0 100.00% 6 0 100.00%
dev.c:fido_dev_open_rx 36 1 97.22% 62 1 98.39%
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% 8 0 100.00%
dev.c:fido_dev_set_option_flags 29 0 100.00% 19 0 100.00%
dev.c:fido_dev_set_protocol_flags 11 0 100.00% 18 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 414 74 82.13% 556 106 80.94%
File '/libfido2/src/ecdh.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_do_ecdh 29 0 100.00% 40 0 100.00%
ecdh.c:do_ecdh 37 0 100.00% 48 0 100.00%
ecdh.c:kdf 19 1 94.74% 32 2 93.75%
ecdh.c:hkdf_sha256 32 1 96.88% 41 3 92.68%
-----------------------------------------------------------------------------------------
TOTAL 117 2 98.29% 161 5 96.89%
File '/libfido2/src/eddsa.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
eddsa_pk_decode 8 0 100.00% 10 0 100.00%
eddsa_pk_new 1 0 100.00% 3 0 100.00%
eddsa_pk_free 6 0 100.00% 9 0 100.00%
eddsa_pk_from_ptr 6 0 100.00% 8 0 100.00%
eddsa_pk_to_EVP_PKEY 3 0 100.00% 9 0 100.00%
eddsa_pk_from_EVP_PKEY 14 0 100.00% 12 0 100.00%
eddsa.c:decode_pubkey_point 8 0 100.00% 14 0 100.00%
eddsa.c:decode_coord 8 0 100.00% 12 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 54 0 100.00% 77 0 100.00%
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% 10 0 100.00%
es256_pk_encode 56 0 100.00% 70 0 100.00%
es256_sk_new 1 0 100.00% 3 0 100.00%
es256_sk_free 6 0 100.00% 9 0 100.00%
es256_pk_new 1 0 100.00% 3 0 100.00%
es256_pk_free 6 0 100.00% 9 0 100.00%
es256_pk_from_ptr 11 0 100.00% 13 0 100.00%
es256_pk_set_x 1 0 100.00% 5 0 100.00%
es256_pk_set_y 1 0 100.00% 5 0 100.00%
es256_sk_create 39 0 100.00% 46 0 100.00%
es256_pk_to_EVP_PKEY 42 0 100.00% 66 0 100.00%
es256_pk_from_EC_KEY 38 0 100.00% 43 0 100.00%
es256_sk_to_EVP_PKEY 28 0 100.00% 50 0 100.00%
es256_derive_pk 25 0 100.00% 34 0 100.00%
es256.c:decode_pubkey_point 9 0 100.00% 16 0 100.00%
es256.c:decode_coord 8 0 100.00% 12 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 280 0 100.00% 394 0 100.00%
File '/libfido2/src/extern.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% 28 0 100.00%
fido_hid_get_report_len 19 0 100.00% 33 0 100.00%
fido_dev_info_new 1 0 100.00% 3 0 100.00%
fido_dev_info_free 9 0 100.00% 18 0 100.00%
fido_dev_info_ptr 1 0 100.00% 3 0 100.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% 14 0 100.00%
hid.c:get_key_val 6 0 100.00% 20 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 60 0 100.00% 134 0 100.00%
File '/libfido2/src/hid_linux.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_hid_manifest 35 4 88.57% 50 1 98.00%
fido_hid_open 27 27 0.00% 44 44 0.00%
fido_hid_close 3 3 0.00% 8 8 0.00%
fido_hid_set_sigmask 2 2 0.00% 8 8 0.00%
fido_hid_read 15 15 0.00% 26 26 0.00%
fido_hid_write 12 12 0.00% 21 21 0.00%
fido_hid_report_in_len 1 1 0.00% 5 5 0.00%
fido_hid_report_out_len 1 1 0.00% 5 5 0.00%
hid_linux.c:copy_info 34 0 100.00% 53 0 100.00%
hid_linux.c:is_fido 10 2 80.00% 19 2 89.47%
hid_linux.c:get_parent_attr 6 0 100.00% 11 0 100.00%
hid_linux.c:parse_uevent 12 0 100.00% 28 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% 22 3 86.36%
-----------------------------------------------------------------------------------------
TOTAL 173 68 60.69% 303 123 59.41%
File '/libfido2/src/hid_unix.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_hid_unix_open 18 11 38.89% 26 14 46.15%
fido_hid_unix_wait 12 9 25.00% 26 14 46.15%
-----------------------------------------------------------------------------------------
TOTAL 30 20 33.33% 52 28 46.15%
File '/libfido2/src/info.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_dev_get_cbor_info_wait 10 0 100.00% 9 0 100.00%
fido_dev_get_cbor_info 1 0 100.00% 3 0 100.00%
fido_cbor_info_new 1 0 100.00% 3 0 100.00%
fido_cbor_info_reset 1 0 100.00% 8 0 100.00%
fido_cbor_info_free 6 0 100.00% 9 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_fwversion 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% 6 0 100.00%
fido_cbor_info_algorithm_cose 4 0 100.00% 6 0 100.00%
info.c:fido_dev_get_cbor_info_tx 8 0 100.00% 12 0 100.00%
info.c:fido_dev_get_cbor_info_rx 6 0 100.00% 18 0 100.00%
info.c:parse_reply_element 19 0 100.00% 39 0 100.00%
info.c:decode_string_array 12 0 100.00% 21 0 100.00%
info.c:decode_string 4 0 100.00% 14 0 100.00%
info.c:decode_aaguid 8 0 100.00% 12 0 100.00%
info.c:decode_options 11 0 100.00% 18 0 100.00%
info.c:decode_option 11 0 100.00% 22 0 100.00%
info.c:decode_protocols 12 0 100.00% 21 0 100.00%
info.c:decode_protocol 6 0 100.00% 16 0 100.00%
info.c:decode_algorithms 12 0 100.00% 21 0 100.00%
info.c:decode_algorithm 9 0 100.00% 23 0 100.00%
info.c:decode_algorithm_entry 20 0 100.00% 31 0 100.00%
info.c:free_algo 1 0 100.00% 5 0 100.00%
info.c:free_str_array 4 0 100.00% 8 0 100.00%
info.c:free_opt_array 4 0 100.00% 9 0 100.00%
info.c:free_byte_array 1 0 100.00% 6 0 100.00%
info.c:free_algo_array 4 0 100.00% 8 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 198 0 100.00% 405 0 100.00%
File '/libfido2/src/io.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_tx 13 0 100.00% 13 0 100.00%
fido_rx 13 1 92.31% 17 3 82.35%
fido_rx_cbor_status 8 0 100.00% 12 0 100.00%
io.c:tx_empty 9 0 100.00% 17 0 100.00%
io.c:tx 13 0 100.00% 21 0 100.00%
io.c:tx_preamble 16 1 93.75% 24 1 95.83%
io.c:tx_frame 15 1 93.33% 22 1 95.45%
io.c:rx 40 2 95.00% 65 1 98.46%
io.c:rx_preamble 23 2 91.30% 26 5 80.77%
io.c:rx_frame 8 0 100.00% 11 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 158 7 95.57% 228 11 95.18%
File '/libfido2/src/iso7816.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
iso7816_new 4 0 100.00% 18 0 100.00%
iso7816_free 6 0 100.00% 8 0 100.00%
iso7816_add 6 1 83.33% 9 0 100.00%
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% 42 0 100.00%
File '/libfido2/src/largeblob.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_dev_largeblob_get 26 2 92.31% 41 4 90.24%
fido_dev_largeblob_set 27 0 100.00% 39 0 100.00%
fido_dev_largeblob_remove 12 0 100.00% 21 0 100.00%
fido_dev_largeblob_get_array 15 2 86.67% 30 4 86.67%
fido_dev_largeblob_set_array 14 0 100.00% 21 0 100.00%
largeblob.c:largeblob_get_array 32 0 100.00% 39 0 100.00%
largeblob.c:get_chunklen 9 1 88.89% 11 0 100.00%
largeblob.c:largeblob_get_tx 19 0 100.00% 28 0 100.00%
largeblob.c:largeblob_get_rx 15 0 100.00% 23 0 100.00%
largeblob.c:parse_largeblob_reply 8 0 100.00% 10 0 100.00%
largeblob.c:largeblob_array_check 7 0 100.00% 18 0 100.00%
largeblob.c:largeblob_array_digest 10 0 100.00% 11 0 100.00%
largeblob.c:largeblob_array_load 14 2 85.71% 21 7 66.67%
largeblob.c:largeblob_array_lookup 25 0 100.00% 36 0 100.00%
largeblob.c:largeblob_decode 16 2 87.50% 17 6 64.71%
largeblob.c:largeblob_do_decode 27 3 88.89% 32 5 84.38%
largeblob.c:largeblob_decrypt 15 0 100.00% 28 0 100.00%
largeblob.c:largeblob_aad 1 0 100.00% 12 0 100.00%
largeblob.c:largeblob_reset 1 0 100.00% 5 0 100.00%
largeblob.c:largeblob_encode 16 0 100.00% 23 0 100.00%
largeblob.c:largeblob_new 1 0 100.00% 3 0 100.00%
largeblob.c:largeblob_seal 20 0 100.00% 35 0 100.00%
largeblob.c:largeblob_get_nonce 8 1 87.50% 19 3 84.21%
largeblob.c:largeblob_free 6 0 100.00% 9 0 100.00%
largeblob.c:largeblob_add 27 2 92.59% 40 3 92.50%
largeblob.c:largeblob_drop 21 0 100.00% 30 0 100.00%
largeblob.c:largeblob_set_array 54 2 96.30% 64 4 93.75%
largeblob.c:largeblob_get_uv_token 19 0 100.00% 27 0 100.00%
largeblob.c:largeblob_set_tx 35 0 100.00% 40 0 100.00%
largeblob.c:prepare_hmac 13 2 84.62% 26 7 73.08%
-----------------------------------------------------------------------------------------
TOTAL 513 19 96.30% 759 43 94.33%
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% 10 0 100.00%
fido_log_xxd 16 1 93.75% 27 0 100.00%
fido_log_error 8 2 75.00% 13 1 92.31%
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% 12 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 39 5 87.18% 73 4 94.52%
File '/libfido2/src/netlink.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_nl_power_nfc 18 1 94.44% 26 3 88.46%
fido_nl_get_nfc_target 16 1 93.75% 33 3 90.91%
fido_nl_free 10 2 80.00% 11 1 90.91%
fido_nl_new 16 2 87.50% 29 6 79.31%
set_netlink_io_functions 1 0 100.00% 4 0 100.00%
netlink.c:nlmsg_new 8 0 100.00% 18 0 100.00%
netlink.c:nlmsg_set_genl 1 0 100.00% 9 0 100.00%
netlink.c:nlmsg_write 6 1 83.33% 9 1 88.89%
netlink.c:nlmsg_set_u32 1 0 100.00% 3 0 100.00%
netlink.c:nlmsg_setattr 14 1 92.86% 21 0 100.00%
netlink.c:nlmsg_tx 10 1 90.00% 15 3 80.00%
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 3 72.73% 19 9 52.63%
netlink.c:nl_parse_reply 20 0 100.00% 30 0 100.00%
netlink.c:nlmsg_from_buf 15 0 100.00% 22 0 100.00%
netlink.c:nlmsg_type 1 0 100.00% 3 0 100.00%
netlink.c:nlmsg_get_status 8 0 100.00% 10 0 100.00%
netlink.c:nlmsg_read 6 0 100.00% 9 0 100.00%
netlink.c:nlmsg_get_genl 6 0 100.00% 10 0 100.00%
netlink.c:nlmsg_iter 6 0 100.00% 15 0 100.00%
netlink.c:nlmsg_getattr 1 0 100.00% 3 0 100.00%
netlink.c:nla_from_buf 17 0 100.00% 26 0 100.00%
netlink.c:nl_nfc_poll 18 1 94.44% 27 3 88.89%
netlink.c:parse_nfc_event 10 0 100.00% 19 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% 9 0 100.00%
netlink.c:nl_dump_nfc_target 19 1 94.74% 33 3 90.91%
netlink.c:parse_target 9 0 100.00% 15 0 100.00%
netlink.c:nl_get_nfc_family 23 1 95.65% 35 3 91.43%
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% 20 0 100.00%
netlink.c:nla_get_u16 1 0 100.00% 3 0 100.00%
netlink.c:nla_iter 6 0 100.00% 15 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% 27 0 100.00%
netlink.c:nla_get_str 10 0 100.00% 13 0 100.00%
-----------------------------------------------------------------------------------------
TOTAL 327 15 95.41% 565 35 93.81%
File '/libfido2/src/nfc_linux.c':
Name Regions Miss Cover Lines Miss Cover
-----------------------------------------------------------------------------------------
fido_nfc_tx 28 0 100.00% 48 0 100.00%
fido_nfc_rx 8 1 87.50% 13 3 76.92%
fido_nfc_manifest 35 2 94.29% 54 0 100.00%
fido_nfc_open 14 14 0.00% 21 21 0.00%
fido_nfc_close 1 1 0.00% 5 5 0.00%
fido_nfc_set_sigmask 2 2 0.00% 8 8 0.00%
fido_nfc_read 14 14 0.00% 34 34 0.00%
fido_nfc_write 12 12 0.00% 21 21 0.00%
nfc_linux.c:nfc_do_tx 20 2 90.00% 30 6 80.00%
nfc_linux.c:tx_short_apdu 14 0 100.00% 37 0 100.00%
nfc_linux.c:rx_init 25 6 76.00% 34 5 85.29%
nfc_linux.c:rx_cbor 4 0 100.00% 8 0 100.00%
nfc_linux.c:rx_msg 18 2 88.89% 28 6 78.57%
nfc_linux.c:rx_apdu 8 1 87.50% 22 3 86.36%
nfc_linux.c:tx_get_response 4 0 100.00% 14 0 100.00%
nfc_linux.c:copy_info 30 6 80.00% 42 0 100.00%
nfc_linux.c:get_usb_attr 1 0 100.00% 3 0 100.00%
nfc_linux.c:get_parent_attr 6 0 100.00% 11 0 100.00%
nfc_linux.c:to_int 21 21 0.00% 16 16 0.00%
nfc_linux.c:sysnum_from_syspath 12 12 0.00% 20 20 0.00%
nfc_linux.c:nfc_new 6 6 0.00% 14 14 0.00%
nfc_linux.c:nfc_target_connect 9 9 0.00% 24 24 0.00%
nfc_linux.c:nfc_free 12 12 0.00% 13 13 0.00%
-----------------------------------------------------------------------------------------
TOTAL 304 123 59.54% 520 199 61.73%
File '/libfido2/src/pin.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------
fido_sha256 7 0 100.00% 13 0 100.00%
fido_dev_get_uv_token 1 0 100.00% 3 0 100.00%
fido_dev_set_pin 1 0 100.00% 3 0 100.00%
fido_dev_get_retry_count 1 0 100.00% 3 0 100.00%
fido_dev_get_uv_retry_count 1 0 100.00% 3 0 100.00%
cbor_add_uv_params 17 0 100.00% 28 0 100.00%
pin.c:uv_token_wait 14 2 85.71% 14 0 100.00%
pin.c:ctap21_uv_token_tx 49 0 100.00% 59 0 100.00%
pin.c:pin_sha256_enc 19 0 100.00% 30 0 100.00%
pin.c:encode_uv_permission 20 1 95.00% 19 3 84.21%
pin.c:ctap20_uv_token_tx 37 0 100.00% 53 0 100.00%
pin.c:uv_token_rx 20 0 100.00% 36 0 100.00%
pin.c:parse_uv_token 8 0 100.00% 12 0 100.00%
pin.c:fido_dev_set_pin_wait 21 0 100.00% 27 0 100.00%
pin.c:fido_dev_change_pin_tx 45 0 100.00% 68 0 100.00%
pin.c:pin_pad64_enc 15 0 100.00% 26 0 100.00%
pin.c:pad64 18 0 100.00% 24 0 100.00%
pin.c:fido_dev_set_pin_tx 33 0 100.00% 48 0 100.00%
pin.c:fido_dev_get_pin_retry_count_wait 10 0 100.00% 9 0 100.00%
pin.c:fido_dev_get_retry_count_tx 19 0 100.00% 28 0 100.00%
pin.c:fido_dev_get_pin_retry_count_rx 11 0 100.00% 21 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% 20 0 100.00%
pin.c:fido_dev_get_uv_retry_count_wait 10 0 100.00% 9 0 100.00%
pin.c:fido_dev_get_uv_retry_count_rx 11 0 100.00% 21 0 100.00%
pin.c:parse_uv_retry_count 1 0 100.00% 3 0 100.00%
-------------------------------------------------------------------------------------------
TOTAL 403 3 99.26% 583 3 99.49%
File '/libfido2/src/random.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------
fido_get_random 6 1 83.33% 8 1 87.50%
-------------------------------------------------------------------------------------------
TOTAL 6 1 83.33% 8 1 87.50%
File '/libfido2/src/reset.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------
fido_dev_reset 1 0 100.00% 3 0 100.00%
reset.c:fido_dev_reset_wait 15 0 100.00% 14 0 100.00%
reset.c:fido_dev_reset_tx 8 0 100.00% 10 0 100.00%
-------------------------------------------------------------------------------------------
TOTAL 24 0 100.00% 27 0 100.00%
File '/libfido2/src/rs256.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------
rs256_pk_decode 8 0 100.00% 10 0 100.00%
rs256_pk_new 1 0 100.00% 3 0 100.00%
rs256_pk_free 6 0 100.00% 9 0 100.00%
rs256_pk_from_ptr 6 0 100.00% 8 0 100.00%
rs256_pk_to_EVP_PKEY 32 0 100.00% 48 0 100.00%
rs256_pk_from_RSA 32 4 87.50% 32 6 81.25%
rs256.c:decode_rsa_pubkey 9 0 100.00% 16 0 100.00%
rs256.c:decode_bignum 8 0 100.00% 12 0 100.00%
-------------------------------------------------------------------------------------------
TOTAL 102 4 96.08% 138 6 95.65%
File '/libfido2/src/u2f.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------
u2f_register 70 1 98.57% 88 0 100.00%
u2f_authenticate 32 0 100.00% 44 0 100.00%
u2f_get_touch_begin 30 0 100.00% 46 0 100.00%
u2f_get_touch_status 18 0 100.00% 29 0 100.00%
u2f.c:key_lookup 44 0 100.00% 69 0 100.00%
u2f.c:send_dummy_register 31 1 96.77% 49 0 100.00%
u2f.c:parse_register_reply 49 0 100.00% 71 0 100.00%
u2f.c:x5c_get 21 1 95.24% 34 3 91.18%
u2f.c:sig_get 6 0 100.00% 11 0 100.00%
u2f.c:encode_cred_authdata 33 2 93.94% 76 6 92.11%
u2f.c:cbor_blob_from_ec_point 22 0 100.00% 39 0 100.00%
u2f.c:u2f_authenticate_single 32 0 100.00% 52 0 100.00%
u2f.c:do_auth 50 1 98.00% 71 0 100.00%
u2f.c:parse_auth_reply 23 0 100.00% 29 0 100.00%
u2f.c:authdata_fake 12 0 100.00% 34 0 100.00%
-------------------------------------------------------------------------------------------
TOTAL 473 6 98.73% 742 9 98.79%

471
fuzz/fuzz_assert.c Normal file
View File

@ -0,0 +1,471 @@
/*
* 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.
*/
#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)) > 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[4096];
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;
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);
assert(fido_assert_verify(assert, 0, type, pk) != FIDO_OK);
fido_assert_free(&assert);
}
/*
* Do a dummy conversion to exercise rs256_pk_from_RSA().
*/
static void
rs256_convert(const rs256_pk_t *k)
{
EVP_PKEY *pkey = NULL;
rs256_pk_t *pk = NULL;
RSA *rsa = NULL;
volatile int r;
if ((pkey = rs256_pk_to_EVP_PKEY(k)) == NULL ||
(pk = rs256_pk_new()) == NULL ||
(rsa = EVP_PKEY_get0_RSA(pkey)) == NULL)
goto out;
r = rs256_pk_from_RSA(pk, rsa);
out:
if (pk)
rs256_pk_free(&pk);
if (pkey)
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;
volatile 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);
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;
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);
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;
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;
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_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);
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);
}
}

440
fuzz/fuzz_bio.c Normal file
View File

@ -0,0 +1,440 @@
/*
* 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.
*/
#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)) > 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[4096];
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);
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);
}
}

455
fuzz/fuzz_cred.c Normal file
View File

@ -0,0 +1,455 @@
/*
* 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.
*/
#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)) > 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[4096];
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 (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 char *fmt, int prot)
{
fido_cred_t *cred;
uint8_t flags;
uint32_t sigcount;
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);
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);
fido_cred_set_x509(cred, x5c_ptr, x5c_len);
fido_cred_set_sig(cred, sig_ptr, sig_len);
fido_cred_set_prot(cred, prot);
if (rk & 1)
fido_cred_set_rk(cred, FIDO_OPT_TRUE);
if (uv & 1)
fido_cred_set_uv(cred, FIDO_OPT_TRUE);
if (fmt)
fido_cred_set_fmt(cred, fmt);
/* repeat memory operations to trigger reallocation paths */
if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK)
fido_cred_set_authdata_raw(cred, authdata_ptr, authdata_len);
fido_cred_set_x509(cred, x5c_ptr, x5c_len);
fido_cred_set_sig(cred, sig_ptr, sig_len);
assert(fido_cred_verify(cred) != FIDO_OK);
assert(fido_cred_verify_self(cred) != FIDO_OK);
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));
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;
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_fmt(cred), fido_cred_prot(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);
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);
}
}

405
fuzz/fuzz_credman.c Normal file
View File

@ -0,0 +1,405 @@
/*
* 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.
*/
#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)) > 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[4096];
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);
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);
}
}

215
fuzz/fuzz_hid.c Normal file
View File

@ -0,0 +1,215 @@
/*
* 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.
*/
#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"
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;
};
/*
* 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) != 3 ||
(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)
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_string(p->uevent)) == NULL ||
(argv[2] = pack_blob(&p->report_descriptor)) == 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)) > 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[4096];
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);
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;
int16_t vendor_id, product_id;
set_udev_parameters(p->uevent, &p->report_descriptor);
ndevs = uniform_random(64);
if ((devlist = fido_dev_info_new(ndevs)) == 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));
}
out:
fido_dev_info_free(&devlist, ndevs);
}
void
test(const struct param *p)
{
prng_init((unsigned int)p->seed);
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);
}
}

270
fuzz/fuzz_largeblob.c Normal file
View File

@ -0,0 +1,270 @@
/*
* 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.
*/
#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)) > 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[4096];
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);
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);
}
}

480
fuzz/fuzz_mgmt.c Normal file
View File

@ -0,0 +1,480 @@
/*
* 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.
*/
#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"
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)) > 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[4096];
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;
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));
}
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_fwversion(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));
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);
}
void
test(const struct param *p)
{
prng_init((unsigned int)p->seed);
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);
}
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);
}
}

249
fuzz/fuzz_netlink.c Normal file
View File

@ -0,0 +1,249 @@
/*
* 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.
*/
#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"
struct param {
int seed;
int dev;
struct blob wiredata;
};
/*
* Sample netlink messages. These are unlikely to get the harness very far in
* terms of coverage, but serve to give libFuzzer a sense of the underlying
* structure.
*/
static const uint8_t sample_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
};
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)) > 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[4096];
size_t blob_len;
memset(&dummy, 0, sizeof(dummy));
dummy.wiredata.len = sizeof(sample_netlink_wiredata);
memcpy(&dummy.wiredata.body, &sample_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);
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);
}

177
fuzz/libfuzzer.c Normal file
View File

@ -0,0 +1,177 @@
/*
* 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.
*/
#include <err.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "mutator_aux.h"
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 = 4096;
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 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 > 4096)
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 {
test(p);
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[4096];
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;
}

326
fuzz/mutator_aux.c Normal file
View File

@ -0,0 +1,326 @@
/*
* 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.
*/
#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"
#define HID_DEV_HANDLE 0x68696421
#define NFC_DEV_HANDLE 0x6e666321
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);
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
consume_str(const char *str)
{
if (str != NULL)
consume(str, strlen(str) + 1);
}
int
unpack_int(cbor_item_t *item, int *v)
{
if (cbor_is_int(item) == false ||
cbor_int_get_width(item) != CBOR_INT_64)
return -1;
if (cbor_isa_uint(item))
*v = (int)cbor_get_uint64(item);
else
*v = (int)(-cbor_get_uint64(item) - 1);
return 0;
}
int
unpack_string(cbor_item_t *item, char *v)
{
size_t len;
if (cbor_isa_bytestring(item) == false ||
(len = cbor_bytestring_length(item)) >= MAXSTR)
return -1;
memcpy(v, cbor_bytestring_handle(item), len);
v[len] = '\0';
return 0;
}
int
unpack_byte(cbor_item_t *item, uint8_t *v)
{
if (cbor_isa_uint(item) == false ||
cbor_int_get_width(item) != CBOR_INT_8)
return -1;
*v = cbor_get_uint8(item);
return 0;
}
int
unpack_blob(cbor_item_t *item, struct blob *v)
{
if (cbor_isa_bytestring(item) == false ||
(v->len = cbor_bytestring_length(item)) > sizeof(v->body))
return -1;
memcpy(v->body, cbor_bytestring_handle(item), v->len);
return 0;
}
cbor_item_t *
pack_int(int v) NO_MSAN
{
if (v < 0)
return cbor_build_negint64((uint64_t)(-(int64_t)v - 1));
else
return cbor_build_uint64((uint64_t)v);
}
cbor_item_t *
pack_string(const char *v) NO_MSAN
{
if (strlen(v) >= MAXSTR)
return NULL;
return cbor_build_bytestring((const unsigned char *)v, strlen(v));
}
cbor_item_t *
pack_byte(uint8_t v) NO_MSAN
{
return cbor_build_uint8(v);
}
cbor_item_t *
pack_blob(const struct blob *v) NO_MSAN
{
return cbor_build_bytestring(v->body, v->len);
}
void
mutate_byte(uint8_t *b)
{
LLVMFuzzerMutate(b, sizeof(*b), sizeof(*b));
}
void
mutate_int(int *i)
{
LLVMFuzzerMutate((uint8_t *)i, sizeof(*i), sizeof(*i));
}
void
mutate_blob(struct blob *blob)
{
blob->len = LLVMFuzzerMutate((uint8_t *)blob->body, blob->len,
sizeof(blob->body));
}
void
mutate_string(char *s)
{
size_t n;
n = LLVMFuzzerMutate((uint8_t *)s, strlen(s), MAXSTR - 1);
s[n] = '\0';
}
/* XXX should fail, but doesn't */
static int
buf_read(unsigned char *ptr, size_t len, int ms)
{
size_t n;
(void)ms;
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 (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);
}
static int
nfc_read(void *handle, unsigned char *ptr, size_t len, int ms)
{
assert(handle == (void *)NFC_DEV_HANDLE);
assert(len > 0 && len <= 256 + 2);
return buf_read(ptr, len, ms);
}
static 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_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;
}

96
fuzz/mutator_aux.h Normal file
View File

@ -0,0 +1,96 @@
/*
* 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.
*/
#ifndef _MUTATOR_AUX_H
#define _MUTATOR_AUX_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/es256.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 3072
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);
fido_dev_t *open_dev(int);
void set_wire_data(const uint8_t *, size_t);
void prng_init(unsigned long);
unsigned long prng_uint32(void);
uint32_t uniform_random(uint32_t);
#endif /* !_MUTATOR_AUX_H */

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

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

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

@ -0,0 +1,217 @@
/*
* 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.
*/
/*
* 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.

51
fuzz/summary.txt Normal file
View File

@ -0,0 +1,51 @@
Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
fuzz/prng.c 31 0 100.00% 2 0 100.00% 49 0 100.00%
fuzz/udev.c 103 5 95.15% 17 1 94.12% 141 7 95.04%
fuzz/uniform_random.c 7 1 85.71% 1 0 100.00% 23 1 95.65%
fuzz/wrap.c 6 0 100.00% 1 0 100.00% 7 0 100.00%
openbsd-compat/explicit_bzero.c 4 0 100.00% 1 0 100.00% 13 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% 49 7 85.71%
openbsd-compat/strlcat.c 12 1 91.67% 1 0 100.00% 25 1 96.00%
openbsd-compat/timingsafe_bcmp.c 4 0 100.00% 1 0 100.00% 8 0 100.00%
src/aes256.c 115 4 96.52% 8 0 100.00% 175 14 92.00%
src/assert.c 616 46 92.53% 59 3 94.92% 924 64 93.07%
src/authkey.c 44 0 100.00% 5 0 100.00% 75 0 100.00%
src/bio.c 419 20 95.23% 49 2 95.92% 660 22 96.67%
src/blob.c 53 3 94.34% 10 0 100.00% 96 7 92.71%
src/buf.c 8 1 87.50% 2 0 100.00% 20 1 95.00%
src/cbor.c 986 17 98.28% 53 0 100.00% 1426 37 97.41%
src/compress.c 34 4 88.24% 3 0 100.00% 30 3 90.00%
src/config.c 94 1 98.94% 10 0 100.00% 146 3 97.95%
src/cred.c 581 38 93.46% 63 2 96.83% 872 48 94.50%
src/credman.c 382 10 97.38% 40 0 100.00% 614 15 97.56%
src/dev.c 414 74 82.13% 43 6 86.05% 556 106 80.94%
src/ecdh.c 117 2 98.29% 4 0 100.00% 161 5 96.89%
src/eddsa.c 54 0 100.00% 8 0 100.00% 77 0 100.00%
src/err.c 122 10 91.80% 1 0 100.00% 126 10 92.06%
src/es256.c 280 0 100.00% 16 0 100.00% 394 0 100.00%
src/hid.c 60 0 100.00% 12 0 100.00% 134 0 100.00%
src/hid_linux.c 173 68 60.69% 14 7 50.00% 303 123 59.41%
src/hid_unix.c 30 20 33.33% 2 0 100.00% 52 28 46.15%
src/info.c 198 0 100.00% 44 0 100.00% 405 0 100.00%
src/io.c 158 7 95.57% 10 0 100.00% 228 11 95.18%
src/iso7816.c 18 1 94.44% 5 0 100.00% 42 0 100.00%
src/largeblob.c 513 19 96.30% 30 0 100.00% 759 43 94.33%
src/log.c 39 5 87.18% 7 1 85.71% 73 4 94.52%
src/netlink.c 327 15 95.41% 40 0 100.00% 565 35 93.81%
src/nfc_linux.c 304 123 59.54% 23 10 56.52% 520 199 61.73%
src/pin.c 403 3 99.26% 26 0 100.00% 583 3 99.49%
src/random.c 6 1 83.33% 1 0 100.00% 8 1 87.50%
src/reset.c 24 0 100.00% 3 0 100.00% 27 0 100.00%
src/rs256.c 102 4 96.08% 8 0 100.00% 138 6 95.65%
src/u2f.c 473 6 98.73% 15 0 100.00% 742 9 98.79%
Files which contain no functions:
openbsd-compat/openbsd-compat.h 0 0 - 0 0 - 0 0 -
src/extern.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 7359 516 92.99% 640 32 95.00% 11252 813 92.77%

269
fuzz/udev.c Normal file
View File

@ -0,0 +1,269 @@
/*
* 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.
*/
#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 (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;
}

633
fuzz/wiredata_fido2.h Normal file
View File

@ -0,0 +1,633 @@
/*
* 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.
*/
#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
#endif /* _WIREDATA_FIDO2_H */

152
fuzz/wiredata_u2f.h Normal file
View File

@ -0,0 +1,152 @@
/*
* 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.
*/
#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 */

582
fuzz/wrap.c Normal file
View File

@ -0,0 +1,582 @@
/*
* 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.
*/
#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 "mutator_aux.h"
extern int prng_up;
/*
* Build wrappers around functions of interest, and have them fail
* in a pseudo-random manner.
*/
#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(char *,
strdup,
(const char *s),
NULL,
(s),
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_EncryptInit_ex,
(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl,
const unsigned char *key, const unsigned char *iv),
0,
(ctx, type, impl, key, iv),
1
)
WRAP(int,
EVP_CIPHER_CTX_set_padding,
(EVP_CIPHER_CTX *x, int padding),
0,
(x, padding),
1
)
WRAP(int,
EVP_EncryptUpdate,
(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl),
0,
(ctx, out, outl, in, inl),
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(int,
EVP_DecryptInit_ex,
(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl,
const unsigned char *key, const unsigned char *iv),
0,
(ctx, type, impl, key, iv),
1
)
WRAP(int,
EVP_DecryptUpdate,
(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl),
0,
(ctx, out, outl, in, inl),
1
)
WRAP(int,
SHA256_Init,
(SHA256_CTX *c),
0,
(c),
1
)
WRAP(int,
SHA256_Update,
(SHA256_CTX *c, const void *data, size_t len),
0,
(c, data, len),
1
)
WRAP(int,
SHA256_Final,
(unsigned char *md, SHA256_CTX *c),
0,
(md, c),
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(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(int,
RSA_set0_key,
(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d),
0,
(r, n, e, d),
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(const EVP_MD *,
EVP_sha256,
(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 *,
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_uint32,
(uint32_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(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),
-1,
(d, cmd, buf, count),
1
)
WRAP(int,
usleep,
(unsigned int usec),
-1,
(usec),
1
)

83
fuzz/wrapped.sym Normal file
View File

@ -0,0 +1,83 @@
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_uint32
cbor_build_uint8
cbor_load
cbor_map_add
cbor_map_handle
cbor_new_definite_array
cbor_new_definite_map
cbor_serialize_alloc
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_Cipher
EVP_CIPHER_CTX_ctrl
EVP_CIPHER_CTX_new
EVP_CIPHER_CTX_set_padding
EVP_CipherInit
EVP_DecryptInit_ex
EVP_DecryptUpdate
EVP_DigestVerifyInit
EVP_EncryptInit_ex
EVP_EncryptUpdate
EVP_MD_CTX_new
EVP_PKEY_assign
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_sha256
fido_tx
HMAC
HMAC_CTX_new
HMAC_Final
HMAC_Init_ex
HMAC_Update
ioctl
malloc
RSA_set0_key
SHA256
SHA256_Final
SHA256_Init
SHA256_Update
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

371
man/CMakeLists.txt Normal file
View File

@ -0,0 +1,371 @@
# 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.
find_program(MANDOC_PATH mandoc)
find_program(GZIP_PATH gzip)
message(STATUS "MANDOC_PATH: ${MANDOC_PATH}")
message(STATUS "GZIP_PATH: ${GZIP_PATH}")
list(APPEND MAN_SOURCES
eddsa_pk_new.3
es256_pk_new.3
fido2-assert.1
fido2-cred.1
fido2-token.1
fido_init.3
fido_assert_new.3
fido_assert_allow_cred.3
fido_assert_set_authdata.3
fido_assert_verify.3
fido_bio_dev_get_info.3
fido_bio_enroll_new.3
fido_bio_info_new.3
fido_bio_template.3
fido_cbor_info_new.3
fido_cred_new.3
fido_cred_exclude.3
fido_credman_metadata_new.3
fido_cred_set_authdata.3
fido_cred_verify.3
fido_dev_enable_entattest.3
fido_dev_get_assert.3
fido_dev_get_touch_begin.3
fido_dev_info_manifest.3
fido_dev_largeblob_get.3
fido_dev_make_cred.3
fido_dev_open.3
fido_dev_set_io_functions.3
fido_dev_set_pin.3
fido_strerr.3
rs256_pk_new.3
)
list(APPEND MAN_ALIAS
eddsa_pk_new eddsa_pk_free
eddsa_pk_new eddsa_pk_from_ptr
eddsa_pk_new eddsa_pk_to_EVP_PKEY
es256_pk_new es256_pk_free
es256_pk_new es256_pk_from_EC_KEY
es256_pk_new es256_pk_from_ptr
es256_pk_new es256_pk_to_EVP_PKEY
fido_assert_new fido_assert_authdata_len
fido_assert_new fido_assert_authdata_ptr
fido_assert_new fido_assert_blob_len
fido_assert_new fido_assert_blob_ptr
fido_assert_new fido_assert_clientdata_hash_len
fido_assert_new fido_assert_clientdata_hash_ptr
fido_assert_new fido_assert_count
fido_assert_new fido_assert_flags
fido_assert_new fido_assert_free
fido_assert_new fido_assert_hmac_secret_len
fido_assert_new fido_assert_hmac_secret_ptr
fido_assert_new fido_assert_id_len
fido_assert_new fido_assert_id_ptr
fido_assert_new fido_assert_largeblob_key_len
fido_assert_new fido_assert_largeblob_key_ptr
fido_assert_new fido_assert_rp_id
fido_assert_new fido_assert_sigcount
fido_assert_new fido_assert_sig_len
fido_assert_new fido_assert_sig_ptr
fido_assert_new fido_assert_user_display_name
fido_assert_new fido_assert_user_icon
fido_assert_new fido_assert_user_id_len
fido_assert_new fido_assert_user_id_ptr
fido_assert_new fido_assert_user_name
fido_assert_set_authdata fido_assert_set_clientdata
fido_assert_set_authdata fido_assert_set_clientdata_hash
fido_assert_set_authdata fido_assert_set_count
fido_assert_set_authdata fido_assert_set_extensions
fido_assert_set_authdata fido_assert_set_hmac_salt
fido_assert_set_authdata fido_assert_set_hmac_secret
fido_assert_set_authdata fido_assert_set_rp
fido_assert_set_authdata fido_assert_set_sig
fido_assert_set_authdata fido_assert_set_up
fido_assert_set_authdata fido_assert_set_uv
fido_bio_dev_get_info fido_bio_dev_enroll_begin
fido_bio_dev_get_info fido_bio_dev_enroll_cancel
fido_bio_dev_get_info fido_bio_dev_enroll_continue
fido_bio_dev_get_info fido_bio_dev_enroll_remove
fido_bio_dev_get_info fido_bio_dev_get_template_array
fido_bio_dev_get_info fido_bio_dev_set_template_name
fido_bio_enroll_new fido_bio_enroll_free
fido_bio_enroll_new fido_bio_enroll_last_status
fido_bio_enroll_new fido_bio_enroll_remaining_samples
fido_bio_info_new fido_bio_info_free
fido_bio_info_new fido_bio_info_max_samples
fido_bio_info_new fido_bio_info_type
fido_bio_template fido_bio_template_array_count
fido_bio_template fido_bio_template_array_free
fido_bio_template fido_bio_template_array_new
fido_bio_template fido_bio_template_free
fido_bio_template fido_bio_template_id_len
fido_bio_template fido_bio_template_id_ptr
fido_bio_template fido_bio_template_name
fido_bio_template fido_bio_template_new
fido_bio_template fido_bio_template_set_id
fido_bio_template fido_bio_template_set_name
fido_cbor_info_new fido_cbor_info_aaguid_len
fido_cbor_info_new fido_cbor_info_aaguid_ptr
fido_cbor_info_new fido_cbor_info_algorithm_cose
fido_cbor_info_new fido_cbor_info_algorithm_count
fido_cbor_info_new fido_cbor_info_algorithm_type
fido_cbor_info_new fido_cbor_info_extensions_len
fido_cbor_info_new fido_cbor_info_extensions_ptr
fido_cbor_info_new fido_cbor_info_free
fido_cbor_info_new fido_cbor_info_maxmsgsiz
fido_cbor_info_new fido_cbor_info_maxcredbloblen
fido_cbor_info_new fido_cbor_info_maxcredcntlst;
fido_cbor_info_new fido_cbor_info_maxcredidlen;
fido_cbor_info_new fido_cbor_info_fwversion
fido_cbor_info_new fido_cbor_info_options_len
fido_cbor_info_new fido_cbor_info_options_name_ptr
fido_cbor_info_new fido_cbor_info_options_value_ptr
fido_cbor_info_new fido_cbor_info_protocols_len
fido_cbor_info_new fido_cbor_info_protocols_ptr
fido_cbor_info_new fido_cbor_info_transports_len
fido_cbor_info_new fido_cbor_info_transports_ptr
fido_cbor_info_new fido_cbor_info_versions_len
fido_cbor_info_new fido_cbor_info_versions_ptr
fido_cbor_info_new fido_dev_get_cbor_info
fido_cred_new fido_cred_authdata_len
fido_cred_new fido_cred_authdata_ptr
fido_cred_new fido_cred_authdata_raw_len
fido_cred_new fido_cred_authdata_raw_ptr
fido_cred_new fido_cred_clientdata_hash_len
fido_cred_new fido_cred_clientdata_hash_ptr
fido_cred_new fido_cred_display_name
fido_cred_new fido_cred_flags
fido_cred_new fido_cred_sigcount
fido_cred_new fido_cred_fmt
fido_cred_new fido_cred_free
fido_cred_new fido_cred_id_len
fido_cred_new fido_cred_id_ptr
fido_cred_new fido_cred_aaguid_len
fido_cred_new fido_cred_aaguid_ptr
fido_cred_new fido_cred_largeblob_key_len
fido_cred_new fido_cred_largeblob_key_ptr
fido_cred_new fido_cred_prot
fido_cred_new fido_cred_pubkey_len
fido_cred_new fido_cred_pubkey_ptr
fido_cred_new fido_cred_rp_id
fido_cred_new fido_cred_rp_name
fido_cred_new fido_cred_sig_len
fido_cred_new fido_cred_sig_ptr
fido_cred_new fido_cred_type
fido_cred_new fido_cred_user_name
fido_cred_new fido_cred_user_id_len
fido_cred_new fido_cred_user_id_ptr
fido_cred_new fido_cred_x5c_len
fido_cred_new fido_cred_x5c_ptr
fido_credman_metadata_new fido_credman_del_dev_rk
fido_credman_metadata_new fido_credman_get_dev_metadata
fido_credman_metadata_new fido_credman_get_dev_rk
fido_credman_metadata_new fido_credman_get_dev_rp
fido_credman_metadata_new fido_credman_metadata_free
fido_credman_metadata_new fido_credman_rk
fido_credman_metadata_new fido_credman_rk_count
fido_credman_metadata_new fido_credman_rk_existing
fido_credman_metadata_new fido_credman_rk_free
fido_credman_metadata_new fido_credman_rk_new
fido_credman_metadata_new fido_credman_rk_remaining
fido_credman_metadata_new fido_credman_rp_count
fido_credman_metadata_new fido_credman_rp_free
fido_credman_metadata_new fido_credman_rp_id
fido_credman_metadata_new fido_credman_rp_id_hash_len
fido_credman_metadata_new fido_credman_rp_id_hash_ptr
fido_credman_metadata_new fido_credman_rp_name
fido_credman_metadata_new fido_credman_rp_new
fido_credman_metadata_new fido_credman_set_dev_rk
fido_cred_set_authdata fido_cred_set_authdata_raw
fido_cred_set_authdata fido_cred_set_blob
fido_cred_set_authdata fido_cred_set_clientdata
fido_cred_set_authdata fido_cred_set_clientdata_hash
fido_cred_set_authdata fido_cred_set_extensions
fido_cred_set_authdata fido_cred_set_fmt
fido_cred_set_authdata fido_cred_set_id
fido_cred_set_authdata fido_cred_set_prot
fido_cred_set_authdata fido_cred_set_rk
fido_cred_set_authdata fido_cred_set_rp
fido_cred_set_authdata fido_cred_set_sig
fido_cred_set_authdata fido_cred_set_type
fido_cred_set_authdata fido_cred_set_user
fido_cred_set_authdata fido_cred_set_uv
fido_cred_set_authdata fido_cred_set_x509
fido_dev_enable_entattest fido_dev_toggle_always_uv
fido_dev_enable_entattest fido_dev_force_pin_change
fido_dev_enable_entattest fido_dev_set_pin_minlen
fido_dev_get_touch_begin fido_dev_get_touch_status
fido_dev_info_manifest fido_dev_info_free
fido_dev_info_manifest fido_dev_info_manufacturer_string
fido_dev_info_manifest fido_dev_info_new
fido_dev_info_manifest fido_dev_info_path
fido_dev_info_manifest fido_dev_info_product
fido_dev_info_manifest fido_dev_info_product_string
fido_dev_info_manifest fido_dev_info_ptr
fido_dev_info_manifest fido_dev_info_vendor
fido_dev_open fido_dev_build
fido_dev_open fido_dev_cancel
fido_dev_open fido_dev_close
fido_dev_open fido_dev_flags
fido_dev_open fido_dev_force_fido2
fido_dev_open fido_dev_force_u2f
fido_dev_open fido_dev_free
fido_dev_open fido_dev_is_fido2
fido_dev_open fido_dev_is_winhello
fido_dev_open fido_dev_major
fido_dev_open fido_dev_minor
fido_dev_open fido_dev_new
fido_dev_open fido_dev_protocol
fido_dev_open fido_dev_supports_cred_prot
fido_dev_open fido_dev_supports_credman
fido_dev_open fido_dev_supports_pin
fido_dev_open fido_dev_supports_uv
fido_dev_open fido_dev_has_uv
fido_dev_set_pin fido_dev_get_retry_count
fido_dev_set_pin fido_dev_get_uv_retry_count
fido_dev_set_pin fido_dev_reset
fido_dev_set_io_functions fido_dev_set_sigmask
fido_dev_largeblob_get fido_dev_largeblob_set
fido_dev_largeblob_get fido_dev_largeblob_remove
fido_dev_largeblob_get fido_dev_largeblob_get_array
fido_dev_largeblob_get fido_dev_largeblob_set_array
rs256_pk_new rs256_pk_free
rs256_pk_new rs256_pk_from_ptr
rs256_pk_new rs256_pk_from_RSA
rs256_pk_new rs256_pk_to_EVP_PKEY
)
list(LENGTH MAN_ALIAS MAN_ALIAS_LEN)
math(EXPR MAN_ALIAS_MAX "${MAN_ALIAS_LEN} - 2")
# man_copy
foreach(f ${MAN_SOURCES})
add_custom_command(OUTPUT ${f}
COMMAND cp -f ${CMAKE_SOURCE_DIR}/man/${f} .
DEPENDS ${f})
list(APPEND COPY_FILES ${f})
endforeach()
# man_lint
foreach(f ${MAN_SOURCES})
add_custom_command(OUTPUT ${f}.lint
COMMAND mandoc -T lint -W warning ${f} > ${f}.lint
DEPENDS ${f})
list(APPEND LINT_FILES ${f}.lint)
endforeach()
# man_html
foreach(f ${MAN_SOURCES})
string(REGEX REPLACE ".[13]" "" g ${f})
add_custom_command(OUTPUT ${g}.html
COMMAND mandoc -T html -O man="%N.html",style=style.css -I os="Yubico AB" ${f} > ${g}.html
DEPENDS ${f})
list(APPEND HTML_FILES ${g}.html)
endforeach()
# man_html_partial
foreach(f ${MAN_SOURCES})
string(REGEX REPLACE ".[13]" "" g ${f})
add_custom_command(OUTPUT ${g}.partial
COMMAND cat ${CMAKE_SOURCE_DIR}/man/dyc.css > ${g}.partial
COMMAND mandoc -T html -O man="%N.html",fragment ${f} >> ${g}.partial
DEPENDS ${f})
list(APPEND HTML_PARTIAL_FILES ${g}.partial)
endforeach()
# man_gzip
foreach(f ${MAN_SOURCES})
add_custom_command(OUTPUT ${f}.gz
COMMAND gzip -cn ${f} > ${f}.gz
DEPENDS ${f})
list(APPEND GZ_FILES ${f}.gz)
endforeach()
macro(define_symlink_target NAME EXT)
foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2)
math(EXPR j "${i} + 1")
list(GET MAN_ALIAS ${i} SRC)
list(GET MAN_ALIAS ${j} DST)
add_custom_command(OUTPUT ${DST}.${EXT}
COMMAND ln -sf ${SRC}.${EXT} ${DST}.${EXT})
list(APPEND ${NAME}_LINK_FILES ${DST}.${EXT})
endforeach()
add_custom_target(${NAME} DEPENDS ${${NAME}_LINK_FILES})
endmacro()
add_custom_target(man_copy DEPENDS ${COPY_FILES})
add_custom_target(man_lint DEPENDS ${LINT_FILES})
add_custom_target(man_html DEPENDS ${HTML_FILES})
add_custom_target(man_html_partial DEPENDS ${HTML_PARTIAL_FILES})
add_custom_target(man_gzip DEPENDS ${GZ_FILES})
define_symlink_target(man_symlink 3)
define_symlink_target(man_symlink_html html)
define_symlink_target(man_symlink_html_partial partial)
define_symlink_target(man_symlink_gzip 3.gz)
add_dependencies(man_symlink man_copy)
add_dependencies(man_lint man_symlink)
add_dependencies(man_html man_lint)
add_dependencies(man_symlink_html man_html)
add_dependencies(man_html_partial man_lint)
add_dependencies(man_symlink_html_partial man_html_partial)
add_custom_target(man ALL)
if(MANDOC_PATH)
add_dependencies(man man_symlink_html)
add_dependencies(man_gzip man_lint)
install(FILES ${CMAKE_SOURCE_DIR}/man/style.css
DESTINATION "${CMAKE_INSTALL_DOCDIR}/html")
foreach(f ${MAN_SOURCES})
string(REGEX REPLACE ".[13]" "" f ${f})
install(FILES ${CMAKE_BINARY_DIR}/man/${f}.html
DESTINATION "${CMAKE_INSTALL_DOCDIR}/html")
endforeach()
foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2)
math(EXPR j "${i} + 1")
list(GET MAN_ALIAS ${j} DST)
install(FILES ${CMAKE_BINARY_DIR}/man/${DST}.html
DESTINATION "${CMAKE_INSTALL_DOCDIR}/html")
endforeach()
endif()
if(GZIP_PATH)
add_dependencies(man_gzip man_copy)
add_dependencies(man_symlink_gzip man_gzip)
add_dependencies(man man_symlink_gzip)
foreach(f ${MAN_SOURCES})
if (${f} MATCHES ".1$")
install(FILES ${CMAKE_BINARY_DIR}/man/${f}.gz
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
elseif(${f} MATCHES ".3$")
install(FILES ${CMAKE_BINARY_DIR}/man/${f}.gz
DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")
endif()
endforeach()
foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2)
math(EXPR j "${i} + 1")
list(GET MAN_ALIAS ${j} DST)
install(FILES ${CMAKE_BINARY_DIR}/man/${DST}.3.gz
DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")
endforeach()
elseif(NOT MSVC)
add_dependencies(man man_symlink)
foreach(f ${MAN_SOURCES})
if (${f} MATCHES ".1$")
install(FILES ${CMAKE_BINARY_DIR}/man/${f}
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
elseif(${f} MATCHES ".3$")
install(FILES ${CMAKE_BINARY_DIR}/man/${f}
DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")
endif()
endforeach()
foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2)
math(EXPR j "${i} + 1")
list(GET MAN_ALIAS ${j} DST)
install(FILES ${CMAKE_BINARY_DIR}/man/${DST}.3
DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")
endforeach()
endif()

7
man/NOTES Normal file
View File

@ -0,0 +1,7 @@
To generate .partial files for https://developers.yubico.com/:
$ make -C build man_symlink_html_partial
$ (cd build/man && pax -p p -r -w *.partial /tmp/partial)
Use mandoc 1.14.4. Otherwise, adjust dyc.css to mandoc's HTML
output.

14
man/dyc.css Normal file
View File

@ -0,0 +1,14 @@
<style>
table.head, table.foot { width: 100%; }
td.head-rtitle, td.foot-os { text-align: right; }
td.head-vol { text-align: center; }
div.Pp { margin: 1ex 0ex; }
div.Nd, div.Bf, div.Op { display: inline; }
span.Pa, span.Ad { font-style: italic; }
span.Ms { font-weight: bold; }
dl.Bl-diag > dt { font-weight: bold; }
code.Nm, code.Fl, code.Cm, code.Ic, code.In, code.Fd, code.Fn,
code.Cd { font-weight: bold; font-family: monospace; }
var { font-family: monospace; }
.Sh { font-size: 1.5em; padding-top: 1em; padding-bottom: 1em; }
</style>

122
man/eddsa_pk_new.3 Normal file
View File

@ -0,0 +1,122 @@
.\" 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.
.\"
.Dd $Mdocdate: May 15 2019 $
.Dt EDDSA_PK_NEW 3
.Os
.Sh NAME
.Nm eddsa_pk_new ,
.Nm eddsa_pk_free ,
.Nm eddsa_pk_from_EVP_PKEY ,
.Nm eddsa_pk_from_ptr ,
.Nm eddsa_pk_to_EVP_PKEY
.Nd FIDO 2 COSE EDDSA API
.Sh SYNOPSIS
.In openssl/evp.h
.In fido/eddsa.h
.Ft eddsa_pk_t *
.Fn eddsa_pk_new "void"
.Ft void
.Fn eddsa_pk_free "eddsa_pk_t **pkp"
.Ft int
.Fn eddsa_pk_from_EVP_PKEY "eddsa_pk_t *pk" "const EVP_PKEY *pkey"
.Ft int
.Fn eddsa_pk_from_ptr "eddsa_pk_t *pk" "const void *ptr" "size_t len"
.Ft EVP_PKEY *
.Fn eddsa_pk_to_EVP_PKEY "const eddsa_pk_t *pk"
.Sh DESCRIPTION
EDDSA is the name given in the CBOR Object Signing and Encryption
(COSE) RFC to EDDSA over Curve25519 with SHA-512.
The COSE EDDSA API of
.Em libfido2
is an auxiliary API with routines to convert between the different
EDDSA public key types used in
.Em libfido2
and
.Em OpenSSL .
.Pp
In
.Em libfido2 ,
EDDSA public keys are abstracted by the
.Vt eddsa_pk_t
type.
.Pp
The
.Fn eddsa_pk_new
function returns a pointer to a newly allocated, empty
.Vt eddsa_pk_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn eddsa_pk_free
function releases the memory backing
.Fa *pkp ,
where
.Fa *pkp
must have been previously allocated by
.Fn eddsa_pk_new .
On return,
.Fa *pkp
is set to NULL.
Either
.Fa pkp
or
.Fa *pkp
may be NULL, in which case
.Fn eddsa_pk_free
is a NOP.
.Pp
The
.Fn eddsa_pk_from_EVP_PKEY
function fills
.Fa pk
with the contents of
.Fa pkey .
No references to
.Fa pkey
are kept.
.Pp
The
.Fn eddsa_pk_from_ptr
function fills
.Fa pk
with the contents of
.Fa ptr ,
where
.Fa ptr
points to
.Fa len
bytes.
No references to
.Fa ptr
are kept.
.Pp
The
.Fn eddsa_pk_to_EVP_PKEY
function converts
.Fa pk
to a newly allocated
.Fa EVP_PKEY
type with a reference count of 1.
No internal references to the returned pointer are kept.
If an error occurs,
.Fn eddsa_pk_to_EVP_PKEY
returns NULL.
.Sh RETURN VALUES
The
.Fn eddsa_pk_from_EC_KEY
and
.Fn eddsa_pk_from_ptr
functions return
.Dv FIDO_OK
on success.
On error, a different error code defined in
.In fido/err.h
is returned.
.Sh SEE ALSO
.Xr es256_pk_new 3 ,
.Xr fido_assert_verify 3 ,
.Xr fido_cred_pubkey_ptr 3 ,
.Xr rs256_pk_new 3

126
man/es256_pk_new.3 Normal file
View File

@ -0,0 +1,126 @@
.\" 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.
.\"
.Dd $Mdocdate: May 24 2018 $
.Dt ES256_PK_NEW 3
.Os
.Sh NAME
.Nm es256_pk_new ,
.Nm es256_pk_free ,
.Nm es256_pk_from_EC_KEY ,
.Nm es256_pk_from_ptr ,
.Nm es256_pk_to_EVP_PKEY
.Nd FIDO 2 COSE ES256 API
.Sh SYNOPSIS
.In openssl/ec.h
.In fido/es256.h
.Ft es256_pk_t *
.Fn es256_pk_new "void"
.Ft void
.Fn es256_pk_free "es256_pk_t **pkp"
.Ft int
.Fn es256_pk_from_EC_KEY "es256_pk_t *pk" "const EC_KEY *ec"
.Ft int
.Fn es256_pk_from_ptr "es256_pk_t *pk" "const void *ptr" "size_t len"
.Ft EVP_PKEY *
.Fn es256_pk_to_EVP_PKEY "const es256_pk_t *pk"
.Sh DESCRIPTION
ES256 is the name given in the CBOR Object Signing and Encryption
(COSE) RFC to ECDSA over P-256 with SHA-256.
The COSE ES256 API of
.Em libfido2
is an auxiliary API with routines to convert between the different
ECDSA public key types used in
.Em libfido2
and
.Em OpenSSL .
.Pp
In
.Em libfido2 ,
ES256 public keys are abstracted by the
.Vt es256_pk_t
type.
.Pp
The
.Fn es256_pk_new
function returns a pointer to a newly allocated, empty
.Vt es256_pk_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn es256_pk_free
function releases the memory backing
.Fa *pkp ,
where
.Fa *pkp
must have been previously allocated by
.Fn es256_pk_new .
On return,
.Fa *pkp
is set to NULL.
Either
.Fa pkp
or
.Fa *pkp
may be NULL, in which case
.Fn es256_pk_free
is a NOP.
.Pp
The
.Fn es256_pk_from_EC_KEY
function fills
.Fa pk
with the contents of
.Fa ec .
No references to
.Fa ec
are kept.
.Pp
The
.Fn es256_pk_from_ptr
function fills
.Fa pk
with the contents of
.Fa ptr ,
where
.Fa ptr
points to
.Fa len
bytes.
The
.Fa ptr
pointer may point to an uncompressed point, or to the
concatenation of the x and y coordinates.
No references to
.Fa ptr
are kept.
.Pp
The
.Fn es256_pk_to_EVP_PKEY
function converts
.Fa pk
to a newly allocated
.Fa EVP_PKEY
type with a reference count of 1.
No internal references to the returned pointer are kept.
If an error occurs,
.Fn es256_pk_to_EVP_PKEY
returns NULL.
.Sh RETURN VALUES
The
.Fn es256_pk_from_EC_KEY
and
.Fn es256_pk_from_ptr
functions return
.Dv FIDO_OK
on success.
On error, a different error code defined in
.In fido/err.h
is returned.
.Sh SEE ALSO
.Xr eddsa_pk_new 3 ,
.Xr fido_assert_verify 3 ,
.Xr fido_cred_pubkey_ptr 3 ,
.Xr rs256_pk_new 3

256
man/fido2-assert.1 Normal file
View File

@ -0,0 +1,256 @@
.\" 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.
.\"
.Dd $Mdocdate: November 5 2019 $
.Dt FIDO2-ASSERT 1
.Os
.Sh NAME
.Nm fido2-assert
.Nd get/verify a FIDO 2 assertion
.Sh SYNOPSIS
.Nm
.Fl G
.Op Fl bdhpruv
.Op Fl t Ar option
.Op Fl i Ar input_file
.Op Fl o Ar output_file
.Ar device
.Nm
.Fl V
.Op Fl dhpv
.Op Fl i Ar input_file
.Ar key_file
.Op Ar type
.Sh DESCRIPTION
.Nm
gets or verifies a FIDO 2 assertion.
.Pp
The input of
.Nm
is defined by the parameters of the assertion to be obtained/verified.
See the
.Sx INPUT FORMAT
section for details.
.Pp
The output of
.Nm
is defined by the result of the selected operation.
See the
.Sx OUTPUT FORMAT
section for details.
.Pp
If an assertion is successfully obtained or verified,
.Nm
exits 0.
Otherwise,
.Nm
exits 1.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl G
Tells
.Nm
to obtain a new assertion from
.Ar device .
.It Fl V
Tells
.Nm
to verify an assertion using the PEM-encoded public key in
.Ar key_file
of type
.Ar type ,
where
.Ar type
may be
.Em es256
(denoting ECDSA over NIST P-256 with SHA-256),
.Em rs256
(denoting 2048-bit RSA with PKCS#1.5 padding and SHA-256), or
.Em eddsa
(denoting EDDSA over Curve25519 with SHA-512).
If
.Ar type
is not specified,
.Em es256
is assumed.
.It Fl b
Request the credential's
.Dq largeBlobKey ,
a 32-byte symmetric key associated with the asserted credential.
.It Fl h
If obtaining an assertion, enable the FIDO2 hmac-secret
extension.
If verifying an assertion, check whether the extension data bit was
signed by the authenticator.
.It Fl d
Causes
.Nm
to emit debugging output on
.Em stderr .
.It Fl i Ar input_file
Tells
.Nm
to read the parameters of the assertion from
.Ar input_file
instead of
.Em stdin .
.It Fl o Ar output_file
Tells
.Nm
to write output on
.Ar output_file
instead of
.Em stdout .
.It Fl p
If obtaining an assertion, request user presence.
If verifying an assertion, check whether the user presence bit was
signed by the authenticator.
.It Fl r
Obtain an assertion using a resident credential.
If
.Fl r
is specified,
.Nm
will not expect a credential id in its input, and may output
multiple assertions.
Resident credentials are called
.Dq discoverable credentials
in FIDO 2.1.
.It Fl t Ar option
Toggles a key/value
.Ar option ,
where
.Ar option
is a string of the form
.Dq key=value .
The options supported at present are:
.Bl -tag -width Ds
.It Cm up Ns = Ns Ar true|false
Asks the authenticator for user presence to be enabled or disabled.
.It Cm uv Ns = Ns Ar true|false
Asks the authenticator for user verification to be enabled or
disabled.
.It Cm pin Ns = Ns Ar true|false
Tells
.Nm
whether to prompt for a PIN and request user verification.
.El
.Pp
The
.Fl t
option may be specified multiple times.
.It Fl u
Obtain an assertion using U2F.
By default,
.Nm
will use FIDO2 if supported by the authenticator, and fallback to
U2F otherwise.
.It Fl v
If obtaining an assertion, prompt the user for a PIN and request
user verification from the authenticator.
If verifying an assertion, check whether the user verification bit
was signed by the authenticator.
.El
.Pp
If a
.Em tty
is available,
.Nm
will use it to obtain the PIN.
Otherwise,
.Em stdin
is used.
.Sh INPUT FORMAT
The input of
.Nm
consists of base64 blobs and UTF-8 strings separated
by newline characters ('\\n').
.Pp
When obtaining an assertion,
.Nm
expects its input to consist of:
.Pp
.Bl -enum -offset indent -compact
.It
client data hash (base64 blob);
.It
relying party id (UTF-8 string);
.It
credential id, if credential not resident (base64 blob);
.It
hmac salt, if the FIDO2 hmac-secret extension is enabled
(base64 blob);
.El
.Pp
When verifying an assertion,
.Nm
expects its input to consist of:
.Pp
.Bl -enum -offset indent -compact
.It
client data hash (base64 blob);
.It
relying party id (UTF-8 string);
.It
authenticator data (base64 blob);
.It
assertion signature (base64 blob);
.El
.Pp
UTF-8 strings passed to
.Nm
must not contain embedded newline or NUL characters.
.Sh OUTPUT FORMAT
The output of
.Nm
consists of base64 blobs and UTF-8 strings separated
by newline characters ('\\n').
.Pp
For each generated assertion,
.Nm
outputs:
.Pp
.Bl -enum -offset indent -compact
.It
client data hash (base64 blob);
.It
relying party id (UTF-8 string);
.It
authenticator data (base64 blob);
.It
assertion signature (base64 blob);
.It
user id, if credential resident (base64 blob);
.It
hmac secret, if the FIDO2 hmac-secret extension is enabled
(base64 blob);
.It
the credential's associated 32-byte symmetric key
.Pq Dq largeBlobKey ,
if requested (base64 blob).
.El
.Pp
When verifying an assertion,
.Nm
produces no output.
.Sh EXAMPLES
Assuming
.Pa cred
contains a
.Em es256
credential created according to the steps outlined in
.Xr fido2-cred 1 ,
obtain an assertion from an authenticator at
.Pa /dev/hidraw5
and verify it:
.Pp
.Dl $ echo assertion challenge | openssl sha256 -binary | base64 > assert_param
.Dl $ echo relying party >> assert_param
.Dl $ head -1 cred >> assert_param
.Dl $ tail -n +2 cred > pubkey
.Dl $ fido2-assert -G -i assert_param /dev/hidraw5 | fido2-assert -V pubkey es256
.Sh SEE ALSO
.Xr fido2-cred 1 ,
.Xr fido2-token 1

267
man/fido2-cred.1 Normal file
View File

@ -0,0 +1,267 @@
.\" 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.
.\"
.Dd $Mdocdate: November 5 2019 $
.Dt FIDO2-CRED 1
.Os
.Sh NAME
.Nm fido2-cred
.Nd make/verify a FIDO 2 credential
.Sh SYNOPSIS
.Nm
.Fl M
.Op Fl bdhqruv
.Op Fl c Ar cred_protect
.Op Fl i Ar input_file
.Op Fl o Ar output_file
.Ar device
.Op Ar type
.Nm
.Fl V
.Op Fl dhv
.Op Fl c Ar cred_protect
.Op Fl i Ar input_file
.Op Fl o Ar output_file
.Op Ar type
.Sh DESCRIPTION
.Nm
makes or verifies a FIDO 2 credential.
.Pp
A credential
.Ar type
may be
.Em es256
(denoting ECDSA over NIST P-256 with SHA-256),
.Em rs256
(denoting 2048-bit RSA with PKCS#1.5 padding and SHA-256), or
.Em eddsa
(denoting EDDSA over Curve25519 with SHA-512).
If
.Ar type
is not specified,
.Em es256
is assumed.
.Pp
When making a credential, the authenticator may require the user
to authenticate with a PIN.
If the
.Fl q
option is not specified,
.Nm
will prompt the user for the PIN.
If a
.Em tty
is available,
.Nm
will use it to obtain the PIN.
Otherwise,
.Em stdin
is used.
.Pp
The input of
.Nm
is defined by the parameters of the credential to be made/verified.
See the
.Sx INPUT FORMAT
section for details.
.Pp
The output of
.Nm
is defined by the result of the selected operation.
See the
.Sx OUTPUT FORMAT
section for details.
.Pp
If a credential is successfully created or verified,
.Nm
exits 0.
Otherwise,
.Nm
exits 1.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl M
Tells
.Nm
to make a new credential on
.Ar device .
.It Fl V
Tells
.Nm
to verify a credential.
.It Fl b
Request the credential's
.Dq largeBlobKey ,
a 32-byte symmetric key associated with the generated credential.
.It Fl c Ar cred_protect
If making a credential, set the credential's protection level to
.Ar cred_protect ,
where
.Ar cred_protect
is the credential's protection level in decimal notation.
Please refer to
.In fido/param.h
for the set of possible values.
If verifying a credential, check whether the credential's protection
level was signed by the authenticator as
.Ar cred_protect .
.It Fl d
Causes
.Nm
to emit debugging output on
.Em stderr .
.It Fl h
If making a credential, enable the FIDO2 hmac-secret extension.
If verifying a credential, check whether the extension data bit was
signed by the authenticator.
.It Fl i Ar input_file
Tells
.Nm
to read the parameters of the credential from
.Ar input_file
instead of
.Em stdin .
.It Fl o Ar output_file
Tells
.Nm
to write output on
.Ar output_file
instead of
.Em stdout .
.It Fl q
Tells
.Nm
to be quiet.
If a PIN is required and
.Fl q
is specified,
.Nm
will fail.
.It Fl r
Create a resident credential.
Resident credentials are called
.Dq discoverable credentials
in FIDO 2.1.
.It Fl u
Create a U2F credential.
By default,
.Nm
will use FIDO2 if supported by the authenticator, and fallback to
U2F otherwise.
.It Fl v
If making a credential, request user verification.
If verifying a credential, check whether the user verification bit
was signed by the authenticator.
.El
.Sh INPUT FORMAT
The input of
.Nm
consists of base64 blobs and UTF-8 strings separated
by newline characters ('\\n').
.Pp
When making a credential,
.Nm
expects its input to consist of:
.Pp
.Bl -enum -offset indent -compact
.It
client data hash (base64 blob);
.It
relying party id (UTF-8 string);
.It
user name (UTF-8 string);
.It
user id (base64 blob).
.El
.Pp
When verifying a credential,
.Nm
expects its input to consist of:
.Pp
.Bl -enum -offset indent -compact
.It
client data hash (base64 blob);
.It
relying party id (UTF-8 string);
.It
credential format (UTF-8 string);
.It
authenticator data (base64 blob);
.It
credential id (base64 blob);
.It
attestation signature (base64 blob);
.It
attestation certificate (optional, base64 blob).
.El
.Pp
UTF-8 strings passed to
.Nm
must not contain embedded newline or NUL characters.
.Sh OUTPUT FORMAT
The output of
.Nm
consists of base64 blobs, UTF-8 strings, and PEM-encoded public
keys separated by newline characters ('\\n').
.Pp
Upon the successful generation of a credential,
.Nm
outputs:
.Pp
.Bl -enum -offset indent -compact
.It
client data hash (base64 blob);
.It
relying party id (UTF-8 string);
.It
credential format (UTF-8 string);
.It
authenticator data (base64 blob);
.It
credential id (base64 blob);
.It
attestation signature (base64 blob);
.It
attestation certificate, if present (base64 blob).
.It
the credential's associated 32-byte symmetric key
.Pq Dq largeBlobKey ,
if present (base64 blob).
.El
.Pp
Upon the successful verification of a credential,
.Nm
outputs:
.Pp
.Bl -enum -offset indent -compact
.It
credential id (base64 blob);
.It
PEM-encoded credential key.
.El
.Sh EXAMPLES
Create a new
.Em es256
credential on
.Pa /dev/hidraw5 ,
verify it, and save the id and the public key of the credential in
.Em cred :
.Pp
.Dl $ echo credential challenge | openssl sha256 -binary | base64 > cred_param
.Dl $ echo relying party >> cred_param
.Dl $ echo user name >> cred_param
.Dl $ dd if=/dev/urandom bs=1 count=32 | base64 >> cred_param
.Dl $ fido2-cred -M -i cred_param /dev/hidraw5 | fido2-cred -V -o cred
.Sh SEE ALSO
.Xr fido2-assert 1 ,
.Xr fido2-token 1
.Sh CAVEATS
Please note that
.Nm
handles Basic Attestation and Self Attestation transparently.
In the case of Basic Attestation, the validity of the authenticator's
attestation certificate is
.Em not
verified.

388
man/fido2-token.1 Normal file
View File

@ -0,0 +1,388 @@
.\" 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.
.\"
.Dd $Mdocdate: September 13 2019 $
.Dt FIDO2-TOKEN 1
.Os
.Sh NAME
.Nm fido2-token
.Nd find and manage a FIDO 2 authenticator
.Sh SYNOPSIS
.Nm
.Fl C
.Op Fl d
.Ar device
.Nm
.Fl D
.Op Fl d
.Fl i
.Ar cred_id
.Ar device
.Nm
.Fl D
.Fl b
.Op Fl d
.Fl k Ar key_path
.Ar device
.Nm
.Fl D
.Fl b
.Op Fl d
.Fl n Ar rp_id
.Op Fl i Ar cred_id
.Ar device
.Nm
.Fl D
.Fl e
.Op Fl d
.Fl i
.Ar template_id
.Ar device
.Nm
.Fl D
.Fl u
.Op Fl d
.Ar device
.Nm
.Fl G
.Fl b
.Op Fl d
.Fl k Ar key_path
.Ar blob_path
.Ar device
.Nm
.Fl G
.Fl b
.Op Fl d
.Fl n Ar rp_id
.Op Fl i Ar cred_id
.Ar blob_path
.Ar device
.Nm
.Fl I
.Op Fl cd
.Op Fl k Ar rp_id Fl i Ar cred_id
.Ar device
.Nm
.Fl L
.Op Fl bder
.Op Fl k Ar rp_id
.Op device
.Nm
.Fl R
.Op Fl d
.Ar device
.Nm
.Fl S
.Op Fl adefu
.Ar device
.Nm
.Fl S
.Op Fl d
.Fl i Ar template_id
.Fl n Ar template_name
.Nm
.Fl S
.Op Fl d
.Fl l Ar pin_length
.Ar device
.Nm
.Fl S
.Fl b
.Op Fl d
.Fl k Ar key_path
.Ar blob_path
.Ar device
.Nm
.Fl S
.Fl b
.Op Fl d
.Fl n Ar rp_id
.Op Fl i Ar cred_id
.Ar blob_path
.Ar device
.Nm
.Fl S
.Fl c
.Op Fl d
.Fl i Ar cred_id
.Fl k Ar user_id
.Fl n Ar name
.Fl p Ar display_name
.Ar device
.Nm
.Fl V
.Sh DESCRIPTION
.Nm
manages a FIDO 2 authenticator.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl C Ar device
Changes the PIN of
.Ar device .
The user will be prompted for the current and new PINs.
.It Fl D Fl i Ar id Ar device
Deletes the resident credential specified by
.Ar id
from
.Ar device ,
where
.Ar id
is the credential's base64-encoded id.
The user will be prompted for the PIN.
.It Fl D Fl b Fl k Ar key_path Ar device
Deletes a
.Dq largeBlob
encrypted with
.Ar key_path
from
.Ar device ,
where
.Ar key_path
must hold the blob's base64-encoded encryption key.
A PIN or equivalent user-verification gesture is required.
.It Fl D Fl b Fl n Ar rp_id Oo Fl i Ar cred_id Oc Ar device
Deletes a
.Dq largeBlob
corresponding to
.Ar rp_id
from
.Ar device .
If
.Ar rp_id
has multiple credentials enrolled on
.Ar device ,
the credential ID must be specified using
.Fl i Ar cred_id ,
where
.Ar cred_id
is a base64-encoded blob.
A PIN or equivalent user-verification gesture is required.
.It Fl D Fl e Fl i Ar id Ar device
Deletes the biometric enrollment specified by
.Ar id
from
.Ar device ,
where
.Ar id
is the enrollment's template base64-encoded id.
The user will be prompted for the PIN.
.It Fl D Fl u Ar device
Disables the FIDO 2.1
.Dq user verification always
feature on
.Ar device .
.It Fl G Fl b Fl k Ar key_path Ar blob_path Ar device
Gets a FIDO 2.1
.Dq largeBlob
encrypted with
.Ar key_path
from
.Ar device ,
where
.Ar key_path
must hold the blob's base64-encoded encryption key.
The blob is written to
.Ar blob_path .
A PIN or equivalent user-verification gesture is required.
.It Fl G Fl b Fl n Ar rp_id Oo Fl i Ar cred_id Oc Ar blob_path Ar device
Gets a FIDO 2.1
.Dq largeBlob
associated with
.Ar rp_id
from
.Ar device .
If
.Ar rp_id
has multiple credentials enrolled on
.Ar device ,
the credential ID must be specified using
.Fl i Ar cred_id ,
where
.Ar cred_id
is a base64-encoded blob.
The blob is written to
.Ar blob_path .
A PIN or equivalent user-verification gesture is required.
.It Fl I Ar device
Retrieves information on
.Ar device .
.It Fl I Fl c Ar device
Retrieves resident credential metadata from
.Ar device .
The user will be prompted for the PIN.
.It Fl I Fl k Ar rp_id Fl i Ar cred_id Ar device
Prints the credential id (base64-encoded) and public key
(PEM encoded) of the resident credential specified by
.Ar rp_id
and
.Ar cred_id ,
where
.Ar rp_id
is a UTF-8 relying party id, and
.Ar cred_id
is a base64-encoded credential id.
The user will be prompted for the PIN.
.It Fl L
Produces a list of authenticators found by the operating system.
.It Fl L Fl b Ar device
Produces a list of FIDO 2.1
.Dq largeBlobs
on
.Ar device .
A PIN or equivalent user-verification gesture is required.
.It Fl L Fl e Ar device
Produces a list of biometric enrollments on
.Ar device .
The user will be prompted for the PIN.
.It Fl L Fl r Ar device
Produces a list of relying parties with resident credentials on
.Ar device .
The user will be prompted for the PIN.
.It Fl L Fl k Ar rp_id Ar device
Produces a list of resident credentials corresponding to
relying party
.Ar rp_id
on
.Ar device .
The user will be prompted for the PIN.
.It Fl R
Performs a reset on
.Ar device .
.Nm
will NOT prompt for confirmation.
.It Fl S
Sets the PIN of
.Ar device .
The user will be prompted for the PIN.
.It Fl S Fl a Ar device
Enables FIDO 2.1 Enterprise Attestation on
.Ar device .
.It Fl S Fl b Fl k Ar key_path Ar blob_path Ar device
Sets
.Ar blob_path
as a FIDO 2.1
.Dq largeBlob
encrypted with
.Ar key_path
on
.Ar device ,
where
.Ar blob_path
holds the blob's plaintext, and
.Ar key_path
the blob's base64-encoded encryption.
A PIN or equivalent user-verification gesture is required.
.It Fl S Fl b Fl n Ar rp_id Oo Fl i Ar cred_id Oc Ar blob_path Ar device
Sets
.Ar blob_path
as a FIDO 2.1
.Dq largeBlob
associated with
.Ar rp_id
on
.Ar device .
If
.Ar rp_id
has multiple credentials enrolled on
.Ar device ,
the credential ID must be specified using
.Fl i Ar cred_id ,
where
.Ar cred_id
is a base64-encoded blob.
A PIN or equivalent user-verification gesture is required.
.It Fl S Fl c Fl i Ar cred_id Fl k Ar user_id Fl n Ar name Fl p Ar display_name Ar device
Sets the
.Ar name
and
.Ar display_name
attributes of the resident credential identified by
.Ar cred_id
and
.Ar user_id ,
where
.Ar name
and
.Ar display_name
are UTF-8 strings and
.Ar cred_id
and
.Ar user_id
are base64-encoded blobs.
A PIN or equivalent user-verification gesture is required.
.It Fl S Fl e Ar device
Performs a new biometric enrollment on
.Ar device .
The user will be prompted for the PIN.
.It Fl S Fl e Fl i Ar template_id Fl n Ar template_name Ar device
Sets the friendly name of the biometric enrollment specified by
.Ar template_id
to
.Ar template_name
on
.Ar device ,
where
.Ar template_id
is base64-encoded and
.Ar template_name
is a UTF-8 string.
The user will be prompted for the PIN.
.It Fl S Fl f Ar device
Forces a PIN change on
.Ar device .
The user will be prompted for the PIN.
.It Fl S Fl l Ar pin_length Ar device
Sets the minimum PIN length of
.Ar device
to
.Ar pin_length .
The user will be prompted for the PIN.
.It Fl S Fl u Ar device
Enables the FIDO 2.1
.Dq user verification always
feature on
.Ar device .
.It Fl V
Prints version information.
.It Fl d
Causes
.Nm
to emit debugging output on
.Em stderr .
.El
.Pp
If a
.Em tty
is available,
.Nm
will use it to prompt for PINs.
Otherwise,
.Em stdin
is used.
.Pp
.Nm
exits 0 on success and 1 on error.
.Sh SEE ALSO
.Xr fido2-assert 1 ,
.Xr fido2-cred 1
.Sh CAVEATS
The actual user-flow to perform a reset is outside the scope of the
FIDO2 specification, and may therefore vary depending on the
authenticator.
Yubico authenticators do not allow resets after 5 seconds from
power-up, and expect a reset to be confirmed by the user through
touch within 30 seconds.
.Pp
An authenticator's path may contain spaces.
.Pp
Resident credentials are called
.Dq discoverable credentials
in FIDO 2.1.
.Pp
Whether the FIDO 2.1
.Dq user verification always
feature is activated or deactivated after an authenticator reset
is vendor-specific.

View File

@ -0,0 +1,47 @@
.\" 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.
.\"
.Dd $Mdocdate: May 23 2018 $
.Dt FIDO_ASSERT_ALLOW_CRED 3
.Os
.Sh NAME
.Nm fido_assert_allow_cred
.Nd appends a credential ID to the list of credentials allowed in an assertion
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_assert_allow_cred "fido_assert_t *assert" "const unsigned char *ptr" "size_t len"
.Sh DESCRIPTION
The
.Fn fido_assert_allow_cred
function adds
.Fa ptr
to the list of credentials allowed in
.Fa assert ,
where
.Fa ptr
points to a credential ID of
.Fa len
bytes.
A copy of
.Fa ptr
is made, and no references to the passed pointer are kept.
If
.Fn fido_assert_allow_cred
fails, the existing list of allowed credentials is preserved.
.Pp
For the format of a FIDO 2 credential ID, please refer to the
Web Authentication (webauthn) standard.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_assert_allow_cred
are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_assert_new 3 ,
.Xr fido_assert_set_authdata 3 ,
.Xr fido_dev_get_assert 3

243
man/fido_assert_new.3 Normal file
View File

@ -0,0 +1,243 @@
.\" 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.
.\"
.Dd $Mdocdate: October 22 2019 $
.Dt FIDO_ASSERT_NEW 3
.Os
.Sh NAME
.Nm fido_assert_new ,
.Nm fido_assert_free ,
.Nm fido_assert_count ,
.Nm fido_assert_rp_id ,
.Nm fido_assert_user_display_name ,
.Nm fido_assert_user_icon ,
.Nm fido_assert_user_name ,
.Nm fido_assert_authdata_ptr ,
.Nm fido_assert_blob_ptr ,
.Nm fido_assert_clientdata_hash_ptr ,
.Nm fido_assert_hmac_secret_ptr ,
.Nm fido_assert_largeblob_key_ptr ,
.Nm fido_assert_user_id_ptr ,
.Nm fido_assert_sig_ptr ,
.Nm fido_assert_id_ptr ,
.Nm fido_assert_authdata_len ,
.Nm fido_assert_blob_len ,
.Nm fido_assert_clientdata_hash_len ,
.Nm fido_assert_hmac_secret_len ,
.Nm fido_assert_largeblob_key_len ,
.Nm fido_assert_user_id_len ,
.Nm fido_assert_sig_len ,
.Nm fido_assert_id_len ,
.Nm fido_assert_sigcount ,
.Nm fido_assert_flags
.Nd FIDO 2 assertion API
.Sh SYNOPSIS
.In fido.h
.Ft fido_assert_t *
.Fn fido_assert_new "void"
.Ft void
.Fn fido_assert_free "fido_assert_t **assert_p"
.Ft size_t
.Fn fido_assert_count "const fido_assert_t *assert"
.Ft const char *
.Fn fido_assert_rp_id "const fido_assert_t *assert"
.Ft const char *
.Fn fido_assert_user_display_name "const fido_assert_t *assert" "size_t idx"
.Ft const char *
.Fn fido_assert_user_icon "const fido_assert_t *assert" "size_t idx"
.Ft const char *
.Fn fido_assert_user_name "const fido_assert_t *assert" "size_t idx"
.Ft const unsigned char *
.Fn fido_assert_authdata_ptr "const fido_assert_t *assert" "size_t idx"
.Ft const unsigned char *
.Fn fido_assert_clientdata_hash_ptr "const fido_assert_t *assert"
.Ft const unsigned char *
.Fn fido_assert_blob_ptr "const fido_assert_t *assert" "size_t idx"
.Ft const unsigned char *
.Fn fido_assert_hmac_secret_ptr "const fido_assert_t *assert" "size_t idx"
.Ft const unsigned char *
.Fn fido_assert_largeblob_key_ptr "const fido_assert_t *assert" "size_t idx"
.Ft const unsigned char *
.Fn fido_assert_user_id_ptr "const fido_assert_t *assert" "size_t idx"
.Ft const unsigned char *
.Fn fido_assert_sig_ptr "const fido_assert_t *assert" "size_t idx"
.Ft const unsigned char *
.Fn fido_assert_id_ptr "const fido_assert_t *assert" "size_t idx"
.Ft size_t
.Fn fido_assert_authdata_len "const fido_assert_t *assert" "size_t idx"
.Ft size_t
.Fn fido_assert_clientdata_hash_len "const fido_assert_t *assert"
.Ft size_t
.Fn fido_assert_blob_len "const fido_assert_t *assert" "size_t idx"
.Ft size_t
.Fn fido_assert_hmac_secret_len "const fido_assert_t *assert" "size_t idx"
.Ft size_t
.Fn fido_assert_largeblob_key_len "const fido_assert_t *assert" "size_t idx"
.Ft size_t
.Fn fido_assert_user_id_len "const fido_assert_t *assert" "size_t idx"
.Ft size_t
.Fn fido_assert_sig_len "const fido_assert_t *assert" "size_t idx"
.Ft size_t
.Fn fido_assert_id_len "const fido_assert_t *assert" "size_t idx"
.Ft uint32_t
.Fn fido_assert_sigcount "const fido_assert_t *assert" "size_t idx"
.Ft uint8_t
.Fn fido_assert_flags "const fido_assert_t *assert" "size_t idx"
.Sh DESCRIPTION
FIDO 2 assertions are abstracted in
.Em libfido2
by the
.Vt fido_assert_t
type.
The functions described in this page allow a
.Vt fido_assert_t
type to be allocated, deallocated, and inspected.
For other operations on
.Vt fido_assert_t ,
please refer to
.Xr fido_assert_set_authdata 3 ,
.Xr fido_assert_allow_cred 3 ,
.Xr fido_assert_verify 3 ,
and
.Xr fido_dev_get_assert 3 .
.Pp
The
.Fn fido_assert_new
function returns a pointer to a newly allocated, empty
.Vt fido_assert_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_assert_free
function releases the memory backing
.Fa *assert_p ,
where
.Fa *assert_p
must have been previously allocated by
.Fn fido_assert_new .
On return,
.Fa *assert_p
is set to NULL.
Either
.Fa assert_p
or
.Fa *assert_p
may be NULL, in which case
.Fn fido_assert_free
is a NOP.
.Pp
The
.Fn fido_assert_count
function returns the number of statements in
.Fa assert .
.Pp
The
.Fn fido_assert_rp_id
function returns a pointer to a NUL-terminated string holding the
relying party ID of
.Fa assert .
.Pp
The
.Fn fido_assert_user_display_name ,
.Fn fido_assert_user_icon ,
and
.Fn fido_assert_user_name ,
functions return pointers to the user display name, icon, and
name attributes of statement
.Fa idx
in
.Fa assert .
If not NULL, the values returned by these functions point to
NUL-terminated UTF-8 strings.
.Pp
The
.Fn fido_assert_user_id_ptr ,
.Fn fido_assert_authdata_ptr ,
.Fn fido_assert_blob_ptr ,
.Fn fido_assert_hmac_secret_ptr ,
.Fn fido_assert_largeblob_key_ptr ,
.Fn fido_assert_sig_ptr ,
and
.Fn fido_assert_id_ptr
functions return pointers to the user ID, CBOR-encoded
authenticator data, cred blob, hmac-secret,
.Dq largeBlobKey ,
signature, and credential ID attributes of statement
.Fa idx
in
.Fa assert .
.Pp
The
.Fn fido_assert_user_id_len ,
.Fn fido_assert_authdata_len ,
.Fn fido_assert_blob_len ,
.Fn fido_assert_hmac_secret_len ,
.Fn fido_assert_largeblob_key_len ,
.Fn fido_assert_sig_len ,
and
.Fn fido_assert_id_len
functions can be used to retrieve the corresponding length of a
specific attribute.
.Pp
The
.Fn fido_assert_sigcount
function can be used to obtain the signature counter of statement
.Fa idx
in
.Fa assert .
.Pp
The
.Fn fido_assert_flags
function returns the authenticator data flags of statement
.Fa idx
in
.Fa assert .
.Pp
Please note that the first statement in
.Fa assert
has an
.Fa idx
(index) value of 0.
.Pp
The authenticator data and signature parts of an assertion
statement are typically passed to a FIDO 2 server for verification.
.Pp
The
.Fn fido_assert_clientdata_hash_ptr
function returns a pointer to the client data hash of
.Fa assert .
The corresponding length can be obtained by
.Fn fido_assert_clientdata_hash_len .
.Sh RETURN VALUES
The authenticator data returned by
.Fn fido_assert_authdata_ptr
is a CBOR-encoded byte string, as obtained from the authenticator.
.Pp
The
.Fn fido_assert_user_display_name ,
.Fn fido_assert_user_icon ,
.Fn fido_assert_user_name ,
.Fn fido_assert_authdata_ptr ,
.Fn fido_assert_clientdata_hash_ptr ,
.Fn fido_assert_hmac_secret_ptr ,
.Fn fido_assert_largeblob_key_ptr ,
.Fn fido_assert_user_id_ptr ,
and
.Fn fido_assert_sig_ptr
functions return NULL if the respective field in
.Fa assert
is not set.
If not NULL, returned pointers are guaranteed to exist until any API
function that takes
.Fa assert
without the
.Em const
qualifier is invoked.
.Sh SEE ALSO
.Xr fido_assert_allow_cred 3 ,
.Xr fido_assert_set_authdata 3 ,
.Xr fido_assert_verify 3 ,
.Xr fido_dev_get_assert 3 ,
.Xr fido_dev_largeblob_get 3

View File

@ -0,0 +1,221 @@
.\" 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.
.\"
.Dd $Mdocdate: May 23 2018 $
.Dt FIDO_ASSERT_SET_AUTHDATA 3
.Os
.Sh NAME
.Nm fido_assert_set_authdata ,
.Nm fido_assert_set_authdata_raw ,
.Nm fido_assert_set_clientdata ,
.Nm fido_assert_set_clientdata_hash ,
.Nm fido_assert_set_count ,
.Nm fido_assert_set_extensions ,
.Nm fido_assert_set_hmac_salt ,
.Nm fido_assert_set_hmac_secret ,
.Nm fido_assert_set_up ,
.Nm fido_assert_set_uv ,
.Nm fido_assert_set_rp ,
.Nm fido_assert_set_sig
.Nd set parameters of a FIDO 2 assertion
.Sh SYNOPSIS
.In fido.h
.Bd -literal
typedef enum {
FIDO_OPT_OMIT = 0, /* use authenticator's default */
FIDO_OPT_FALSE, /* explicitly set option to false */
FIDO_OPT_TRUE, /* explicitly set option to true */
} fido_opt_t;
.Ed
.Ft int
.Fn fido_assert_set_authdata "fido_assert_t *assert" " size_t idx" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_assert_set_authdata_raw "fido_assert_t *assert" " size_t idx" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_assert_set_clientdata "fido_assert_t *assert" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_assert_set_clientdata_hash "fido_assert_t *assert" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_assert_set_count "fido_assert_t *assert" "size_t n"
.Ft int
.Fn fido_assert_set_extensions "fido_assert_t *assert" "int flags"
.Ft int
.Fn fido_assert_set_hmac_salt "fido_assert_t *assert" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_assert_set_hmac_secret "fido_assert_t *assert" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_assert_set_up "fido_assert_t *assert" "fido_opt_t up"
.Ft int
.Fn fido_assert_set_uv "fido_assert_t *assert" "fido_opt_t uv"
.Ft int
.Fn fido_assert_set_rp "fido_assert_t *assert" "const char *id"
.Ft int
.Fn fido_assert_set_sig "fido_assert_t *assert" "size_t idx" "const unsigned char *ptr" "size_t len"
.Sh DESCRIPTION
The
.Nm
set of functions define the various parameters of a FIDO 2
assertion, allowing a
.Fa fido_assert_t
type to be prepared for a subsequent call to
.Xr fido_dev_get_assert 3
or
.Xr fido_assert_verify 3 .
For the complete specification of a FIDO 2 assertion and the format
of its constituent parts, please refer to the Web Authentication
(webauthn) standard.
.Pp
The
.Fn fido_assert_set_count
function sets the number of assertion statements in
.Fa assert
to
.Fa n .
.Pp
The
.Fn fido_assert_set_authdata
and
.Fn fido_assert_set_sig
functions set the authenticator data and signature parts of the
statement with index
.Fa idx
of
.Fa assert
to
.Fa ptr ,
where
.Fa ptr
points to
.Fa len
bytes.
A copy of
.Fa ptr
is made, and no references to the passed pointer are kept.
Please note that the first assertion statement of
.Fa assert
has an
.Fa idx
of
.Em 0 .
The authenticator data passed to
.Fn fido_assert_set_authdata
must be a CBOR-encoded byte string, as obtained from
.Fn fido_assert_authdata_ptr .
Alternatively, a raw binary blob may be passed to
.Fn fido_assert_set_authdata_raw .
.Pp
The
.Fn fido_assert_set_clientdata_hash ,
.Fn fido_assert_set_hmac_salt ,
and
.Fn fido_assert_set_hmac_secret
functions set the client data hash and hmac-salt parts of
.Fa assert
to
.Fa ptr ,
where
.Fa ptr
points to
.Fa len
bytes.
A copy of
.Fa ptr
is made, and no references to the passed pointer are kept.
.Pp
The
.Fn fido_assert_set_clientdata
function allows an application to set the client data hash of
.Fa assert
by specifying the assertion's unhashed client data.
This is required by Windows Hello, which calculates the client data
hash internally.
For compatibility with Windows Hello, applications should use
.Fn fido_assert_set_clientdata
instead of
.Fn fido_assert_set_clientdata_hash .
.Pp
The
.Fn fido_assert_set_rp
function sets the relying party
.Fa id
of
.Fa assert ,
where
.Fa id
is a NUL-terminated UTF-8 string.
The content of
.Fa id
is copied, and no references to the passed pointer are kept.
.Pp
The
.Fn fido_assert_set_extensions
function sets the extensions of
.Fa assert
to the bitmask
.Fa flags .
At the moment, only the
.Dv FIDO_EXT_CRED_BLOB ,
.Dv FIDO_EXT_HMAC_SECRET ,
and
.Dv FIDO_EXT_LARGEBLOB_KEY
extensions are supported.
If
.Fa flags
is zero, the extensions of
.Fa assert
are cleared.
.Pp
The
.Fn fido_assert_set_up
and
.Fn fido_assert_set_uv
functions set the
.Fa up
(user presence) and
.Fa uv
(user verification)
attributes of
.Fa assert .
Both are
.Dv FIDO_OPT_OMIT
by default, allowing the authenticator to use its default settings.
.Pp
Use of the
.Nm
set of functions may happen in two distinct situations:
when asking a FIDO device to produce a series of assertion
statements, prior to
.Xr fido_dev_get_assert 3
(i.e, in the context of a FIDO client), or when verifying assertion
statements using
.Xr fido_assert_verify 3
(i.e, in the context of a FIDO server).
.Pp
For a complete description of the generation of a FIDO 2 assertion
and its verification, please refer to the FIDO 2 specification.
An example of how to use the
.Nm
set of functions can be found in the
.Pa examples/assert.c
file shipped with
.Em libfido2 .
.Pp
.Fn fido_assert_set_hmac_secret
is not normally useful in a FIDO client or server \(em it is provided
to enable testing other functionality that relies on retrieving the
HMAC secret from an assertion obtained from an authenticator.
.Sh RETURN VALUES
The
.Nm
functions return
.Dv FIDO_OK
on success.
The error codes returned by the
.Nm
set of functions are defined in
.In fido/err.h .
.Sh SEE ALSO
.Xr fido_assert_allow_cred 3 ,
.Xr fido_assert_verify 3 ,
.Xr fido_dev_get_assert 3

79
man/fido_assert_verify.3 Normal file
View File

@ -0,0 +1,79 @@
.\" 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.
.\"
.Dd $Mdocdate: May 24 2018 $
.Dt FIDO_ASSERT_VERIFY 3
.Os
.Sh NAME
.Nm fido_assert_verify
.Nd verifies the signature of a FIDO 2 assertion statement
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_assert_verify "fido_assert_t *assert" "size_t idx" "int cose_alg" "const void *pk"
.Sh DESCRIPTION
The
.Fn fido_assert_verify
function verifies whether the signature contained in statement index
.Fa idx
of
.Fa assert
matches the parameters of the assertion.
Before using
.Fn fido_assert_verify
in a sensitive context, the reader is strongly encouraged to make
herself familiar with the FIDO 2 assertion statement process
as defined in the Web Authentication (webauthn) standard.
.Pp
A brief description follows:
.Pp
The
.Fn fido_assert_verify
function verifies whether the client data hash, relying party ID,
user presence and user verification attributes of
.Fa assert
have been attested by the holder of the private counterpart of
the public key
.Fa pk
of COSE type
.Fa cose_alg ,
where
.Fa cose_alg
is
.Dv COSE_ES256 ,
.Dv COSE_RS256 ,
or
.Dv COSE_EDDSA ,
and
.Fa pk
points to a
.Vt es256_pk_t ,
.Vt rs256_pk_t ,
or
.Vt eddsa_pk_t
type accordingly.
.Pp
Please note that the first statement in
.Fa assert
has an
.Fa idx
of 0.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_assert_verify
are defined in
.In fido/err.h .
If
statement
.Fa idx
of
.Fa assert
passes verification with
.Fa pk ,
then
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_assert_new 3 ,
.Xr fido_assert_set_authdata 3

122
man/fido_bio_dev_get_info.3 Normal file
View File

@ -0,0 +1,122 @@
.\" 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.
.\"
.Dd $Mdocdate: September 13 2019 $
.Dt FIDO_BIO_DEV_GET_INFO 3
.Os
.Sh NAME
.Nm fido_bio_dev_get_info ,
.Nm fido_bio_dev_enroll_begin ,
.Nm fido_bio_dev_enroll_continue ,
.Nm fido_bio_dev_enroll_cancel ,
.Nm fido_bio_dev_enroll_remove ,
.Nm fido_bio_dev_get_template_array ,
.Nm fido_bio_dev_set_template_name
.Nd FIDO 2 biometric authenticator API
.Sh SYNOPSIS
.In fido.h
.In fido/bio.h
.Ft int
.Fn fido_bio_dev_get_info "fido_dev_t *dev" "fido_bio_info_t *info"
.Ft int
.Fn fido_bio_dev_enroll_begin "fido_dev_t *dev" "fido_bio_template_t *template" "fido_bio_enroll_t *enroll" "uint32_t timeout_ms" "const char *pin"
.Ft int
.Fn fido_bio_dev_enroll_continue "fido_dev_t *dev" "const fido_bio_template_t *template" "fido_bio_enroll_t *enroll" "uint32_t timeout_ms"
.Ft int
.Fn fido_bio_dev_enroll_cancel "fido_dev_t *dev"
.Ft int
.Fn fido_bio_dev_enroll_remove "fido_dev_t *dev" "const fido_bio_template_t *template" "const char *pin"
.Ft int
.Fn fido_bio_dev_get_template_array "fido_dev_t *dev" "fido_bio_template_array_t *template_array" "const char *pin"
.Ft int
.Fn fido_bio_dev_set_template_name "fido_dev_t *dev" "const fido_bio_template_t *template" "const char *pin"
.Sh DESCRIPTION
The functions described in this page allow biometric
templates on a FIDO2 authenticator to be listed, created,
removed, and customised.
Please note that not all FIDO2 authenticators support biometric
enrollment.
For a description of the types involved, please refer to
.Xr fido_bio_info_new 3 ,
.Xr fido_bio_enroll_new 3 ,
and
.Xr fido_bio_template 3 .
.Pp
The
.Fn fido_bio_dev_get_info
function populates
.Fa info
with sensor information from
.Fa dev .
.Pp
The
.Fn fido_bio_dev_enroll_begin
function initiates a biometric enrollment on
.Fa dev ,
instructing the authenticator to wait
.Fa timeout_ms
milliseconds.
On success,
.Fa template
and
.Fa enroll
will be populated with the newly created template's
information and enrollment status, respectively.
.Pp
The
.Fn fido_bio_dev_enroll_continue
function continues an ongoing enrollment on
.Fa dev ,
instructing the authenticator to wait
.Fa timeout_ms
milliseconds.
On success,
.Fa enroll
will be updated to reflect the status of the biometric
enrollment.
.Pp
The
.Fn fido_bio_dev_enroll_cancel
function cancels an ongoing enrollment on
.Fa dev .
.Pp
The
.Fn fido_bio_dev_enroll_remove
function removes
.Fa template
from
.Fa dev .
.Pp
The
.Fn fido_bio_dev_get_template_array
function populates
.Fa template_array
with the templates currently enrolled on
.Fa dev .
.Pp
The
.Fn fido_bio_dev_set_template_name
function sets the friendly name of
.Fa template
on
.Fa dev .
.Sh RETURN VALUES
The error codes returned by
.Fn fido_bio_dev_get_info ,
.Fn fido_bio_dev_enroll_begin ,
.Fn fido_bio_dev_enroll_continue ,
.Fn fido_bio_dev_enroll_cancel ,
.Fn fido_bio_dev_enroll_remove ,
.Fn fido_bio_dev_get_template_array ,
and
.Fn fido_bio_dev_set_template_name
are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_bio_enroll_new 3 ,
.Xr fido_bio_info_new 3 ,
.Xr fido_bio_template 3

95
man/fido_bio_enroll_new.3 Normal file
View File

@ -0,0 +1,95 @@
.\" 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.
.\"
.Dd $Mdocdate: September 13 2019 $
.Dt FIDO_BIO_ENROLL_NEW 3
.Os
.Sh NAME
.Nm fido_bio_enroll_new ,
.Nm fido_bio_enroll_free ,
.Nm fido_bio_enroll_last_status ,
.Nm fido_bio_enroll_remaining_samples
.Nd FIDO 2 biometric enrollment API
.Sh SYNOPSIS
.In fido.h
.In fido/bio.h
.Bd -literal
#define FIDO_BIO_ENROLL_FP_GOOD 0x00
#define FIDO_BIO_ENROLL_FP_TOO_HIGH 0x01
#define FIDO_BIO_ENROLL_FP_TOO_LOW 0x02
#define FIDO_BIO_ENROLL_FP_TOO_LEFT 0x03
#define FIDO_BIO_ENROLL_FP_TOO_RIGHT 0x04
#define FIDO_BIO_ENROLL_FP_TOO_FAST 0x05
#define FIDO_BIO_ENROLL_FP_TOO_SLOW 0x06
#define FIDO_BIO_ENROLL_FP_POOR_QUALITY 0x07
#define FIDO_BIO_ENROLL_FP_TOO_SKEWED 0x08
#define FIDO_BIO_ENROLL_FP_TOO_SHORT 0x09
#define FIDO_BIO_ENROLL_FP_MERGE_FAILURE 0x0a
#define FIDO_BIO_ENROLL_FP_EXISTS 0x0b
#define FIDO_BIO_ENROLL_FP_DATABASE_FULL 0x0c
#define FIDO_BIO_ENROLL_NO_USER_ACTIVITY 0x0d
#define FIDO_BIO_ENROLL_NO_USER_PRESENCE_TRANSITION 0x0e
.Ed
.Ft fido_bio_enroll_t *
.Fn fido_bio_enroll_new "void"
.Ft void
.Fn fido_bio_enroll_free "fido_bio_enroll_t **enroll_p"
.Ft uint8_t
.Fn fido_bio_enroll_last_status "const fido_bio_enroll_t *enroll"
.Ft uint8_t
.Fn fido_bio_enroll_remaining_samples "const fido_bio_enroll_t *enroll"
.Sh DESCRIPTION
Ongoing FIDO 2 biometric enrollments are abstracted in
.Em libfido2
by the
.Vt fido_bio_enroll_t
type.
.Pp
The functions described in this page allow a
.Vt fido_bio_enroll_t
type to be allocated, deallocated, and inspected.
For device operations on
.Vt fido_bio_enroll_t ,
please refer to
.Xr fido_bio_dev_get_info 3 .
.Pp
The
.Fn fido_bio_enroll_new
function returns a pointer to a newly allocated, empty
.Vt fido_bio_enroll_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_bio_enroll_free
function releases the memory backing
.Fa *enroll_p ,
where
.Fa *enroll_p
must have been previously allocated by
.Fn fido_bio_enroll_new .
On return,
.Fa *enroll_p
is set to NULL.
Either
.Fa enroll_p
or
.Fa *enroll_p
may be NULL, in which case
.Fn fido_bio_enroll_free
is a NOP.
.Pp
The
.Fn fido_bio_enroll_last_status
function returns the enrollment status of
.Fa enroll .
.Pp
The
.Fn fido_bio_enroll_remaining_samples
function returns the number of samples left for
.Fa enroll
to complete.
.Sh SEE ALSO
.Xr fido_bio_dev_get_info 3 ,
.Xr fido_bio_template 3

81
man/fido_bio_info_new.3 Normal file
View File

@ -0,0 +1,81 @@
.\" 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.
.\"
.Dd $Mdocdate: September 13 2019 $
.Dt FIDO_BIO_INFO_NEW 3
.Os
.Sh NAME
.Nm fido_bio_info_new ,
.Nm fido_bio_info_free ,
.Nm fido_bio_info_type ,
.Nm fido_bio_info_max_samples
.Nd FIDO 2 biometric sensor information API
.Sh SYNOPSIS
.In fido.h
.In fido/bio.h
.Ft fido_bio_info_t *
.Fn fido_bio_info_new "void"
.Ft void
.Fn fido_bio_info_free "fido_bio_info_t **info_p"
.Ft uint8_t
.Fn fido_bio_info_type "const fido_bio_info_t *info"
.Ft uint8_t
.Fn fido_bio_info_max_samples "const fido_bio_info_t *info"
.Sh DESCRIPTION
Biometric sensor metadata is abstracted in
.Em libfido2
by the
.Vt fido_bio_info_t
type.
.Pp
The functions described in this page allow a
.Vt fido_bio_info_t
type to be allocated, deallocated, and inspected.
For device operations on
.Vt fido_bio_info_t ,
please refer to
.Xr fido_bio_dev_get_info 3 .
.Pp
The
.Fn fido_bio_info_new
function returns a pointer to a newly allocated, empty
.Vt fido_bio_info_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_bio_info_free
function releases the memory backing
.Fa *info_p ,
where
.Fa *info_p
must have been previously allocated by
.Fn fido_bio_info_new .
On return,
.Fa *info_p
is set to NULL.
Either
.Fa info_p
or
.Fa *info_p
may be NULL, in which case
.Fn fido_bio_info_free
is a NOP.
.Pp
The
.Fn fido_bio_info_type
function returns the fingerprint sensor type, which is
.Dv 1
for touch sensors, and
.Dv 2
for swipe sensors.
.Pp
The
.Fn fido_bio_info_max_samples
function returns the maximum number of successful samples
required for enrollment.
.Sh SEE ALSO
.Xr fido_bio_dev_get_info 3 ,
.Xr fido_bio_enroll_new 3 ,
.Xr fido_bio_template 3

179
man/fido_bio_template.3 Normal file
View File

@ -0,0 +1,179 @@
.\" 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.
.\"
.Dd $Mdocdate: September 13 2019 $
.Dt FIDO_BIO_TEMPLATE 3
.Os
.Sh NAME
.Nm fido_bio_template ,
.Nm fido_bio_template_array_count ,
.Nm fido_bio_template_array_free ,
.Nm fido_bio_template_array_new ,
.Nm fido_bio_template_free ,
.Nm fido_bio_template_id_len ,
.Nm fido_bio_template_id_ptr ,
.Nm fido_bio_template_name ,
.Nm fido_bio_template_new ,
.Nm fido_bio_template_set_id ,
.Nm fido_bio_template_set_name
.Nd FIDO 2 biometric template API
.Sh SYNOPSIS
.In fido.h
.In fido/bio.h
.Ft fido_bio_template_t *
.Fn fido_bio_template_new "void"
.Ft void
.Fn fido_bio_template_free "fido_bio_template_t **template_p"
.Ft const char *
.Fn fido_bio_template_name "const fido_bio_template_t *template"
.Ft const unsigned char *
.Fn fido_bio_template_id_ptr "const fido_bio_template_t *template"
.Ft size_t
.Fn fido_bio_template_id_len "const fido_bio_template_t *template"
.Ft int
.Fn fido_bio_template_set_id "fido_bio_template_t *template" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_bio_template_set_name "fido_bio_template_t *template" "const char *name"
.Ft fido_bio_template_array_t *
.Fn fido_bio_template_array_new "void"
.Ft void
.Fn fido_bio_template_array_free "fido_bio_template_array_t **array_p"
.Ft size_t
.Fn fido_bio_template_array_count "const fido_bio_template_array_t *array"
.Ft const fido_bio_template_t *
.Fn fido_bio_template "const fido_bio_template_array_t *array" "size_t idx"
.Sh DESCRIPTION
Existing FIDO 2 biometric enrollments are abstracted in
.Em libfido2
by the
.Vt fido_bio_template_t
and
.Vt fido_bio_template_array_t
types.
.Pp
The functions described in this page allow a
.Vt fido_bio_template_t
type to be allocated, deallocated, changed, and inspected,
and a
.Vt fido_bio_template_array_t
type to be allocated, deallocated, and inspected.
For device operations on
.Vt fido_bio_template_t
and
.Vt fido_bio_template_array_t ,
please refer to
.Xr fido_bio_dev_get_info 3 .
.Pp
The
.Fn fido_bio_template_new
function returns a pointer to a newly allocated, empty
.Vt fido_bio_template_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_bio_template_free
function releases the memory backing
.Fa *template_p ,
where
.Fa *template_p
must have been previously allocated by
.Fn fido_bio_template_new .
On return,
.Fa *template_p
is set to NULL.
Either
.Fa template_p
or
.Fa *template_p
may be NULL, in which case
.Fn fido_bio_template_free
is a NOP.
.Pp
The
.Fn fido_bio_template_name
function returns a pointer to a NUL-terminated string containing
the friendly name of
.Fa template ,
or NULL if
.Fa template
does not have a friendly name set.
.Pp
The
.Fn fido_bio_template_id_ptr
function returns a pointer to the template id of
.Fa template ,
or NULL if
.Fa template
does not have an id.
The corresponding length can be obtained by
.Fn fido_bio_template_id_len .
.Pp
The
.Fn fido_bio_template_set_name
function sets the friendly name of
.Fa template
to
.Fa name .
If
.Fa name
is NULL, the friendly name of
.Fa template
is unset.
.Pp
The
.Fn fido_bio_template_array_new
function returns a pointer to a newly allocated, empty
.Vt fido_bio_template_array_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_bio_template_array_free
function releases the memory backing
.Fa *array_p ,
where
.Fa *array_p
must have been previously allocated by
.Fn fido_bio_template_array_new .
On return,
.Fa *array_p
is set to NULL.
Either
.Fa array_p
or
.Fa *array_p
may be NULL, in which case
.Fn fido_bio_template_array_free
is a NOP.
.Pp
The
.Fn fido_bio_template_array_count
function returns the number of templates in
.Fa array .
.Pp
The
.Fn fido_bio_template
function returns a pointer to the template at index
.Fa idx
in
.Fa array .
Please note that the first template in
.Fa array
has an
.Fa idx
(index) value of 0.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_bio_template_set_id
and
.Fn fido_bio_template_set_name
are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_bio_dev_get_info 3 ,
.Xr fido_bio_enroll_new 3

231
man/fido_cbor_info_new.3 Normal file
View File

@ -0,0 +1,231 @@
.\" 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.
.\"
.Dd $Mdocdate: May 24 2018 $
.Dt FIDO_CBOR_INFO_NEW 3
.Os
.Sh NAME
.Nm fido_cbor_info_new ,
.Nm fido_cbor_info_free ,
.Nm fido_dev_get_cbor_info ,
.Nm fido_cbor_info_aaguid_ptr ,
.Nm fido_cbor_info_extensions_ptr ,
.Nm fido_cbor_info_protocols_ptr ,
.Nm fido_cbor_info_transports_ptr ,
.Nm fido_cbor_info_versions_ptr ,
.Nm fido_cbor_info_options_name_ptr ,
.Nm fido_cbor_info_options_value_ptr ,
.Nm fido_cbor_info_algorithm_type ,
.Nm fido_cbor_info_algorithm_cose ,
.Nm fido_cbor_info_algorithm_count ,
.Nm fido_cbor_info_aaguid_len ,
.Nm fido_cbor_info_extensions_len ,
.Nm fido_cbor_info_protocols_len ,
.Nm fido_cbor_info_transports_len ,
.Nm fido_cbor_info_versions_len ,
.Nm fido_cbor_info_options_len ,
.Nm fido_cbor_info_maxmsgsiz ,
.Nm fido_cbor_info_maxcredcntlst ,
.Nm fido_cbor_info_maxcredidlen ,
.Nm fido_cbor_info_fwversion
.Nd FIDO 2 CBOR Info API
.Sh SYNOPSIS
.In fido.h
.Ft fido_cbor_info_t *
.Fn fido_cbor_info_new "void"
.Ft void
.Fn fido_cbor_info_free "fido_cbor_info_t **ci_p"
.Ft int
.Fn fido_dev_get_cbor_info "fido_dev_t *dev" "fido_cbor_info_t *ci"
.Ft const unsigned char *
.Fn fido_cbor_info_aaguid_ptr "const fido_cbor_info_t *ci"
.Ft char **
.Fn fido_cbor_info_extensions_ptr "const fido_cbor_info_t *ci"
.Ft const uint8_t *
.Fn fido_cbor_info_protocols_ptr "const fido_cbor_info_t *ci"
.Ft char **
.Fn fido_cbor_info_transports_ptr "const fido_cbor_info_t *ci"
.Ft char **
.Fn fido_cbor_info_versions_ptr "const fido_cbor_info_t *ci"
.Ft char **
.Fn fido_cbor_info_options_name_ptr "const fido_cbor_info_t *ci"
.Ft const bool *
.Fn fido_cbor_info_options_value_ptr "const fido_cbor_info_t *ci"
.Ft const char *
.Fn fido_cbor_info_algorithm_type "const fido_cbor_info_t *ci" "size_t idx"
.Ft int
.Fn fido_cbor_info_algorithm_cose "const fido_cbor_info_t *ci" "size_t idx"
.Ft size_t
.Fn fido_cbor_info_algorithm_count "const fido_cbor_info_t *ci"
.Ft size_t
.Fn fido_cbor_info_aaguid_len "const fido_cbor_info_t *ci"
.Ft size_t
.Fn fido_cbor_info_extensions_len "const fido_cbor_info_t *ci"
.Ft size_t
.Fn fido_cbor_info_protocols_len "const fido_cbor_info_t *ci"
.Ft size_t
.Fn fido_cbor_info_transports_len "const fido_cbor_info_t *ci"
.Ft size_t
.Fn fido_cbor_info_versions_len "const fido_cbor_info_t *ci"
.Ft size_t
.Fn fido_cbor_info_options_len "const fido_cbor_info_t *ci"
.Ft uint64_t
.Fn fido_cbor_info_maxmsgsiz "const fido_cbor_info_t *ci"
.Ft uint64_t
.Fn fido_cbor_info_maxcredbloblen "const fido_cbor_info_t *ci"
.Ft uint64_t
.Fn fido_cbor_info_maxcredcntlst "const fido_cbor_info_t *ci"
.Ft uint64_t
.Fn fido_cbor_info_maxcredidlen "const fido_cbor_info_t *ci"
.Ft uint64_t
.Fn fido_cbor_info_fwversion "const fido_cbor_info_t *ci"
.Sh DESCRIPTION
The
.Fn fido_cbor_info_new
function returns a pointer to a newly allocated, empty
.Vt fido_cbor_info_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_cbor_info_free
function releases the memory backing
.Fa *ci_p ,
where
.Fa *ci_p
must have been previously allocated by
.Fn fido_cbor_info_new .
On return,
.Fa *ci_p
is set to NULL.
Either
.Fa ci_p
or
.Fa *ci_p
may be NULL, in which case
.Fn fido_cbor_info_free
is a NOP.
.Pp
The
.Fn fido_dev_get_cbor_info
function transmits a
.Dv CTAP_CBOR_GETINFO
command to
.Fa dev
and fills
.Fa ci
with attributes retrieved from the command's response.
The
.Fn fido_dev_get_cbor_info
function may block.
.Pp
The
.Fn fido_cbor_info_aaguid_ptr ,
.Fn fido_cbor_info_extensions_ptr ,
.Fn fido_cbor_info_protocols_ptr ,
.Fn fido_cbor_info_transports_ptr ,
and
.Fn fido_cbor_info_versions_ptr
functions return pointers to the authenticator attestation GUID,
supported extensions, PIN protocol, transports, and CTAP version
strings of
.Fa ci .
The corresponding length of a given attribute can be
obtained by
.Fn fido_cbor_info_aaguid_len ,
.Fn fido_cbor_info_extensions_len ,
.Fn fido_cbor_info_protocols_len ,
.Fn fido_cbor_info_transports_len ,
or
.Fn fido_cbor_info_versions_len .
.Pp
The
.Fn fido_cbor_info_options_name_ptr
and
.Fn fido_cbor_info_options_value_ptr
functions return pointers to the array of option names and their
respective values
in
.Fa ci .
The length of the options array is returned by
.Fn fido_cbor_info_options_len .
.Pp
The
.Fn fido_cbor_info_algorithm_count
function returns the number of supported algorithms in
.Fa ci .
The
.Fn fido_cbor_info_algorithm_cose
function returns the COSE identifier of algorithm
.Fa idx
in
.Fa ci ,
or 0 if the COSE identifier is unknown or unset.
The
.Fn fido_cbor_info_algorithm_type
function returns the type of algorithm
.Fa idx
in
.Fa ci ,
or NULL if the type is unset.
Please note that the first algorithm in
.Fa ci
has an
.Fa idx
(index) value of 0.
.Pp
The
.Fn fido_cbor_info_maxmsgsiz
function returns the maximum message size attribute of
.Fa ci .
.Pp
The
.Fn fido_cbor_info_maxcredbloblen
function returns the maximum
.Dq credBlob
length in bytes supported by the authenticator as reported in
.Fa ci .
.Pp
The
.Fn fido_cbor_info_maxcredcntlst
function returns the maximum supported number of credentials in
a single credential ID list as reported in
.Fa ci .
.Pp
The
.Fn fido_cbor_info_maxcredidlen
function returns the maximum supported length of a credential ID
as reported in
.Fa ci .
.Pp
The
.Fn fido_cbor_info_fwversion
function returns the firmware version attribute of
.Fa ci .
.Pp
A complete example of how to use these functions can be found in the
.Pa example/info.c
file shipped with
.Em libfido2 .
.Sh RETURN VALUES
The
.Fn fido_cbor_info_aaguid_ptr ,
.Fn fido_cbor_info_extensions_ptr ,
.Fn fido_cbor_info_protocols_ptr ,
.Fn fido_cbor_info_transports_ptr ,
.Fn fido_cbor_info_versions_ptr ,
.Fn fido_cbor_info_options_name_ptr ,
and
.Fn fido_cbor_info_options_value_ptr
functions return NULL if the respective field in
.Fa ci
is absent.
If not NULL, returned pointers are guaranteed to exist until any
API function that takes
.Fa ci
without the
.Em const
qualifier is invoked.
.Sh SEE ALSO
.Xr fido_dev_open 3

60
man/fido_cred_exclude.3 Normal file
View File

@ -0,0 +1,60 @@
.\" 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.
.\"
.Dd $Mdocdate: May 23 2018 $
.Dt FIDO_CRED_EXCLUDE 3
.Os
.Sh NAME
.Nm fido_cred_exclude
.Nd appends a credential ID to a credential's list of excluded credentials
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_cred_exclude "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Sh DESCRIPTION
The
.Fn fido_cred_exclude
function adds
.Fa ptr
to the list of credentials excluded by
.Fa cred ,
where
.Fa ptr
points to a credential ID of
.Fa len
bytes.
A copy of
.Fa ptr
is made, and no references to the passed pointer are kept.
If
.Fn fido_cred_exclude
fails, the existing list of excluded credentials is preserved.
.Pp
If
.Nm
returns success and
.Fa cred
is later passed to
.Xr fido_dev_make_cred 3
on a device that contains the credential
denoted by
.Fa ptr ,
then
.Xr fido_dev_make_cred 3
will fail.
.Pp
For the format of a FIDO 2 credential ID, please refer to the
Web Authentication (webauthn) standard.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_cred_exclude
are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_cred_new 3 ,
.Xr fido_cred_set_authdata 3 ,
.Xr fido_dev_make_cred 3

257
man/fido_cred_new.3 Normal file
View File

@ -0,0 +1,257 @@
.\" 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.
.\"
.Dd $Mdocdate: May 23 2018 $
.Dt FIDO_CRED_NEW 3
.Os
.Sh NAME
.Nm fido_cred_new ,
.Nm fido_cred_free ,
.Nm fido_cred_prot ,
.Nm fido_cred_fmt ,
.Nm fido_cred_rp_id ,
.Nm fido_cred_rp_name ,
.Nm fido_cred_user_name ,
.Nm fido_cred_display_name ,
.Nm fido_cred_authdata_ptr ,
.Nm fido_cred_authdata_raw_ptr ,
.Nm fido_cred_clientdata_hash_ptr ,
.Nm fido_cred_id_ptr ,
.Nm fido_cred_aaguid_ptr ,
.Nm fido_cred_largeblob_key_ptr ,
.Nm fido_cred_pubkey_ptr ,
.Nm fido_cred_sig_ptr ,
.Nm fido_cred_user_id_ptr ,
.Nm fido_cred_x5c_ptr ,
.Nm fido_cred_authdata_len ,
.Nm fido_cred_authdata_raw_len ,
.Nm fido_cred_clientdata_hash_len ,
.Nm fido_cred_id_len ,
.Nm fido_cred_aaguid_len ,
.Nm fido_cred_largeblob_key_len ,
.Nm fido_cred_pubkey_len ,
.Nm fido_cred_sig_len ,
.Nm fido_cred_user_id_len ,
.Nm fido_cred_x5c_len ,
.Nm fido_cred_type ,
.Nm fido_cred_flags ,
.Nm fido_cred_sigcount
.Nd FIDO 2 credential API
.Sh SYNOPSIS
.In fido.h
.Ft fido_cred_t *
.Fn fido_cred_new "void"
.Ft void
.Fn fido_cred_free "fido_cred_t **cred_p"
.Ft int
.Fn fido_cred_prot "fido_cred_t *cred"
.Ft const char *
.Fn fido_cred_fmt "const fido_cred_t *cred"
.Ft const char *
.Fn fido_cred_rp_id "const fido_cred_t *cred"
.Ft const char *
.Fn fido_cred_rp_name "const fido_cred_t *cred"
.Ft const char *
.Fn fido_cred_user_name "const fido_cred_t *cred"
.Ft const char *
.Fn fido_cred_display_name "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_authdata_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_authdata_raw_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_clientdata_hash_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_id_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_aaguid_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_largeblob_key_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_pubkey_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_sig_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_user_id_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_x5c_ptr "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_authdata_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_authdata_raw_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_clientdata_hash_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_id_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_aaguid_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_largeblob_key_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_pubkey_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_sig_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_user_id_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_x5c_len "const fido_cred_t *cred"
.Ft int
.Fn fido_cred_type "const fido_cred_t *cred"
.Ft uint8_t
.Fn fido_cred_flags "const fido_cred_t *cred"
.Ft uint32_t
.Fn fido_cred_sigcount "const fido_cred_t *cred"
.Sh DESCRIPTION
FIDO 2 credentials are abstracted in
.Em libfido2
by the
.Vt fido_cred_t
type.
The functions described in this page allow a
.Vt fido_cred_t
type to be allocated, deallocated, and inspected.
For other operations on
.Vt fido_cred_t ,
please refer to
.Xr fido_cred_set_authdata 3 ,
.Xr fido_cred_exclude 3 ,
.Xr fido_cred_verify 3 ,
and
.Xr fido_dev_make_cred 3 .
.Pp
The
.Fn fido_cred_new
function returns a pointer to a newly allocated, empty
.Vt fido_cred_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_cred_free
function releases the memory backing
.Fa *cred_p ,
where
.Fa *cred_p
must have been previously allocated by
.Fn fido_cred_new .
On return,
.Fa *cred_p
is set to NULL.
Either
.Fa cred_p
or
.Fa *cred_p
may be NULL, in which case
.Fn fido_cred_free
is a NOP.
.Pp
The
.Fn fido_cred_prot
function returns the protection of
.Fa cred .
See
.Xr fido_cred_set_prot 3
for the values understood by
.Em libfido2 .
.Pp
The
.Fn fido_cred_fmt
function returns a pointer to a NUL-terminated string containing
the format of
.Fa cred ,
or NULL if
.Fa cred
does not have a format set.
.Pp
The
.Fn fido_cred_rp_id ,
.Fn fido_cred_rp_name ,
.Fn fido_cred_user_name ,
and
.Fn fido_cred_display_name
functions return pointers to NUL-terminated strings holding the
relying party ID, relying party name, user name, and user display
name attributes of
.Fa cred ,
or NULL if the respective entry is not set.
.Pp
The
.Fn fido_cred_authdata_ptr ,
.Fn fido_cred_authdata_raw_ptr ,
.Fn fido_cred_clientdata_hash_ptr ,
.Fn fido_cred_id_ptr ,
.Fn fido_cred_aaguid_ptr ,
.Fn fido_cred_largeblob_key_ptr ,
.Fn fido_cred_pubkey_ptr ,
.Fn fido_cred_sig_ptr ,
.Fn fido_cred_user_id_ptr ,
and
.Fn fido_cred_x5c_ptr
functions return pointers to the CBOR-encoded and raw authenticator
data, client data hash, ID, authenticator attestation GUID,
.Dq largeBlobKey ,
public key, signature, user ID, and x509 certificate parts of
.Fa cred ,
or NULL if the respective entry is not set.
.Pp
The corresponding length can be obtained by
.Fn fido_cred_authdata_len ,
.Fn fido_cred_authdata_raw_len ,
.Fn fido_cred_clientdata_hash_len ,
.Fn fido_cred_id_len ,
.Fn fido_cred_aaguid_len ,
.Fn fido_cred_largeblob_key_len ,
.Fn fido_cred_pubkey_len ,
.Fn fido_cred_sig_len ,
.Fn fido_cred_user_id_len ,
and
.Fn fido_cred_x5c_len .
.Pp
The authenticator data, x509 certificate, and signature parts of a
credential are typically passed to a FIDO 2 server for verification.
.Pp
The
.Fn fido_cred_type
function returns the COSE algorithm of
.Fa cred .
.Pp
The
.Fn fido_cred_flags
function returns the authenticator data flags of
.Fa cred .
.Pp
The
.Fn fido_cred_sigcount
function returns the authenticator data signature counter of
.Fa cred .
.Sh RETURN VALUES
The authenticator data returned by
.Fn fido_cred_authdata_ptr
is a CBOR-encoded byte string, as obtained from the authenticator.
To obtain the decoded byte string, use
.Fn fido_cred_authdata_raw_ptr .
.Pp
If not NULL, pointers returned by
.Fn fido_cred_fmt ,
.Fn fido_cred_authdata_ptr ,
.Fn fido_cred_clientdata_hash_ptr ,
.Fn fido_cred_id_ptr ,
.Fn fido_cred_aaguid_ptr ,
.Fn fido_cred_largeblob_key_ptr ,
.Fn fido_cred_pubkey_ptr ,
.Fn fido_cred_sig_ptr ,
and
.Fn fido_cred_x5c_ptr
are guaranteed to exist until any API function that takes
.Fa cred
without the
.Em const
qualifier is invoked.
.Sh SEE ALSO
.Xr fido_cred_exclude 3 ,
.Xr fido_cred_set_authdata 3 ,
.Xr fido_cred_verify 3 ,
.Xr fido_credman_metadata_new 3 ,
.Xr fido_dev_largeblob_get 3 ,
.Xr fido_dev_make_cred 3

View File

@ -0,0 +1,307 @@
.\" 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.
.\"
.Dd $Mdocdate: May 23 2018 $
.Dt FIDO_CRED_SET_AUTHDATA 3
.Os
.Sh NAME
.Nm fido_cred_set_authdata ,
.Nm fido_cred_set_authdata_raw ,
.Nm fido_cred_set_x509 ,
.Nm fido_cred_set_sig ,
.Nm fido_cred_set_id ,
.Nm fido_cred_set_clientdata ,
.Nm fido_cred_set_clientdata_hash ,
.Nm fido_cred_set_rp ,
.Nm fido_cred_set_user ,
.Nm fido_cred_set_extensions ,
.Nm fido_cred_set_blob ,
.Nm fido_cred_set_prot ,
.Nm fido_cred_set_rk ,
.Nm fido_cred_set_uv ,
.Nm fido_cred_set_fmt ,
.Nm fido_cred_set_type
.Nd set parameters of a FIDO 2 credential
.Sh SYNOPSIS
.In fido.h
.Bd -literal
typedef enum {
FIDO_OPT_OMIT = 0, /* use authenticator's default */
FIDO_OPT_FALSE, /* explicitly set option to false */
FIDO_OPT_TRUE, /* explicitly set option to true */
} fido_opt_t;
.Ed
.Ft int
.Fn fido_cred_set_authdata "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_authdata_raw "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_x509 "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_sig "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_id "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_clientdata "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_clientdata_hash "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_rp "fido_cred_t *cred" "const char *id" "const char *name"
.Ft int
.Fn fido_cred_set_user "fido_cred_t *cred" "const unsigned char *user_id" "size_t user_id_len" "const char *name" "const char *display_name" "const char *icon"
.Ft int
.Fn fido_cred_set_extensions "fido_cred_t *cred" "int flags"
.Ft int
.Fn fido_cred_set_blob "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_prot "fido_cred_t *cred" "int prot"
.Ft int
.Fn fido_cred_set_rk "fido_cred_t *cred" "fido_opt_t rk"
.Ft int
.Fn fido_cred_set_uv "fido_cred_t *cred" "fido_opt_t uv"
.Ft int
.Fn fido_cred_set_fmt "fido_cred_t *cred" "const char *ptr"
.Ft int
.Fn fido_cred_set_type "fido_cred_t *cred" "int cose_alg"
.Sh DESCRIPTION
The
.Nm
set of functions define the various parameters of a FIDO 2
credential, allowing a
.Fa fido_cred_t
type to be prepared for a subsequent call to
.Xr fido_dev_make_cred 3
or
.Xr fido_cred_verify 3 .
For the complete specification of a FIDO 2 credential and the format
of its constituent parts, please refer to the Web Authentication
(webauthn) standard.
.Pp
The
.Fn fido_cred_set_authdata ,
.Fn fido_cred_set_x509 ,
.Fn fido_cred_set_sig ,
.Fn fido_cred_set_id ,
and
.Fn fido_cred_set_clientdata_hash
functions set the authenticator data, attestation certificate,
signature, id, and client data hash parts of
.Fa cred
to
.Fa ptr ,
where
.Fa ptr
points to
.Fa len
bytes.
A copy of
.Fa ptr
is made, and no references to the passed pointer are kept.
The authenticator data passed to
.Fn fido_cred_set_authdata
must be a CBOR-encoded byte string, as obtained from
.Fn fido_cred_authdata_ptr .
Alternatively, a raw binary blob may be passed to
.Fn fido_cred_set_authdata_raw .
.Pp
An application calling
.Fn fido_cred_set_authdata
does not need to call
.Fn fido_cred_set_id .
The latter is meant to be used in contexts where the
credential's authenticator data is not available.
.Pp
The
.Fn fido_cred_set_clientdata
function allows an application to set the client data hash of
.Fa cred
by specifying the credential's unhashed client data.
This is required by Windows Hello, which calculates the client data
hash internally.
For compatibility with Windows Hello, applications should use
.Fn fido_cred_set_clientdata
instead of
.Fn fido_cred_set_clientdata_hash .
.Pp
The
.Fn fido_cred_set_rp
function sets the relying party
.Fa id
and
.Fa name
parameters of
.Fa cred ,
where
.Fa id
and
.Fa name
are NUL-terminated UTF-8 strings.
The contents of
.Fa id
and
.Fa name
are copied, and no references to the passed pointers are kept.
.Pp
The
.Fn fido_cred_set_user
function sets the user attributes of
.Fa cred ,
where
.Fa user_id
points to
.Fa user_id_len
bytes and
.Fa name ,
.Fa display_name ,
and
.Fa icon
are NUL-terminated UTF-8 strings.
The contents of
.Fa user_id ,
.Fa name ,
.Fa display_name ,
and
.Fa icon
are copied, and no references to the passed pointers are kept.
Previously set user attributes are flushed.
The
.Fa user_id ,
.Fa name ,
.Fa display_name ,
and
.Fa icon
parameters may be NULL.
.Pp
The
.Fn fido_cred_set_extensions
function sets the extensions of
.Fa cred
to the bitmask
.Fa flags .
At the moment, only the
.Dv FIDO_EXT_CRED_BLOB ,
.Dv FIDO_EXT_CRED_PROTECT ,
.Dv FIDO_EXT_HMAC_SECRET ,
and
.Dv FIDO_EXT_LARGEBLOB_KEY
extensions are supported.
If
.Fa flags
is zero, the extensions of
.Fa cred
are cleared.
.Pp
The
.Fn fido_cred_set_blob
function sets the
.Dq credBlob
to be stored with
.Fa cred
to the data pointed to by
.Fa ptr ,
which must be
.Fa len
bytes long.
.Pp
The
.Fn fido_cred_set_prot
function sets the protection of
.Fa cred
to the scalar
.Fa prot .
At the moment, only the
.Dv FIDO_CRED_PROT_UV_OPTIONAL ,
.Dv FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID ,
and
.Dv FIDO_CRED_PROT_UV_REQUIRED
protections are supported.
If
.Fa prot
is zero, the protection of
.Fa cred
is cleared.
.Pp
The
.Fn fido_cred_set_rk
and
.Fn fido_cred_set_uv
functions set the
.Em rk
.Pq resident/discoverable key
and
.Em uv
.Pq user verification
attributes of
.Fa cred .
Both are
.Dv FIDO_OPT_OMIT
by default, allowing the authenticator to use its default settings.
.Pp
The
.Fn fido_cred_set_fmt
function sets the attestation format of
.Fa cred
to
.Fa fmt ,
where
.Fa fmt
must be
.Vt "packed"
.Pq the format used in FIDO2 ,
.Vt "fido-u2f"
.Pq the format used by U2F ,
or
.Vt "none" .
A copy of
.Fa fmt
is made, and no references to the passed pointer are kept.
Note that not all authenticators support FIDO2 and therefore may not
be able to generate
.Vt "packed" .
.Pp
The
.Fn fido_cred_set_type
function sets the type of
.Fa cred to
.Fa cose_alg ,
where
.Fa cose_alg
is
.Dv COSE_ES256 ,
.Dv COSE_RS256 ,
or
.Dv COSE_EDDSA .
The type of a credential may only be set once.
Note that not all authenticators support COSE_RS256 or COSE_EDDSA.
.Pp
Use of the
.Nm
set of functions may happen in two distinct situations:
when generating a new credential on a FIDO device, prior to
.Xr fido_dev_make_cred 3
(i.e, in the context of a FIDO client), or when validating
a generated credential using
.Xr fido_cred_verify 3
(i.e, in the context of a FIDO server).
.Pp
For a complete description of the generation of a FIDO 2 credential
and its verification, please refer to the FIDO 2 specification.
A concrete utilisation example of the
.Nm
set of functions can be found in the
.Pa cred.c
example shipped with
.Em libfido2 .
.Sh RETURN VALUES
The error codes returned by the
.Nm
set of functions are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_cred_exclude 3 ,
.Xr fido_cred_verify 3 ,
.Xr fido_dev_make_cred 3

69
man/fido_cred_verify.3 Normal file
View File

@ -0,0 +1,69 @@
.\" 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.
.\"
.Dd $Mdocdate: May 23 2018 $
.Dt FIDO_CRED_VERIFY 3
.Os
.Sh NAME
.Nm fido_cred_verify
.Nd verifies the attestation signature of a FIDO 2 credential
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_cred_verify "const fido_cred_t *cred"
.Sh DESCRIPTION
The
.Fn fido_cred_verify
function verifies whether the attestation signature contained in
.Fa cred
matches the attributes of the credential.
Before using
.Fn fido_cred_verify
in a sensitive context, the reader is strongly encouraged to make
herself familiar with the FIDO 2 credential attestation process
as defined in the Web Authentication (webauthn) standard.
.Pp
A brief description follows:
.Pp
The
.Fn fido_cred_verify
function verifies whether the client data hash, relying party ID,
credential ID, type, and resident/discoverable key and user verification
attributes of
.Fa cred
have been attested by the holder of the private counterpart of
the public key contained in the credential's x509 certificate.
.Pp
Please note that the x509 certificate itself is not verified.
.Pp
The attestation statement formats supported by
.Fn fido_cred_verify
are
.Em packed
and
.Em fido-u2f .
The attestation type implemented by
.Fn fido_cred_verify
is
.Em Basic Attestation .
The attestation key pair is assumed to be of the type ES256.
Other attestation formats and types are not supported.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_cred_verify
are defined in
.In fido/err.h .
If
.Fa cred
does not contain attestation data, then
.Dv FIDO_ERR_INVALID_ARGUMENT
is returned.
If
.Fa cred
passes verification, then
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_cred_new 3 ,
.Xr fido_cred_set_authdata 3

View File

@ -0,0 +1,326 @@
.\" 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.
.\"
.Dd $Mdocdate: June 28 2019 $
.Dt FIDO_CREDMAN_METADATA_NEW 3
.Os
.Sh NAME
.Nm fido_credman_metadata_new ,
.Nm fido_credman_rk_new ,
.Nm fido_credman_rp_new ,
.Nm fido_credman_metadata_free ,
.Nm fido_credman_rk_free ,
.Nm fido_credman_rp_free ,
.Nm fido_credman_rk_existing ,
.Nm fido_credman_rk_remaining ,
.Nm fido_credman_rk ,
.Nm fido_credman_rk_count ,
.Nm fido_credman_rp_id ,
.Nm fido_credman_rp_name ,
.Nm fido_credman_rp_count ,
.Nm fido_credman_rp_id_hash_ptr ,
.Nm fido_credman_rp_id_hash_len ,
.Nm fido_credman_get_dev_metadata ,
.Nm fido_credman_get_dev_rk ,
.Nm fido_credman_set_dev_rk ,
.Nm fido_credman_del_dev_rk ,
.Nm fido_credman_get_dev_rp
.Nd FIDO 2 credential management API
.Sh SYNOPSIS
.In fido.h
.In fido/credman.h
.Ft fido_credman_metadata_t *
.Fn fido_credman_metadata_new "void"
.Ft fido_credman_rk_t *
.Fn fido_credman_rk_new "void"
.Ft fido_credman_rp_t *
.Fn fido_credman_rp_new "void"
.Ft void
.Fn fido_credman_metadata_free "fido_credman_metadata_t **metadata_p"
.Ft void
.Fn fido_credman_rk_free "fido_credman_rk_t **rk_p"
.Ft void
.Fn fido_credman_rp_free "fido_credman_rp_t **rp_p"
.Ft uint64_t
.Fn fido_credman_rk_existing "const fido_credman_metadata_t *metadata"
.Ft uint64_t
.Fn fido_credman_rk_remaining "const fido_credman_metadata_t *metadata"
.Ft const fido_cred_t *
.Fn fido_credman_rk "const fido_credman_rk_t *rk" "size_t idx"
.Ft size_t
.Fn fido_credman_rk_count "const fido_credman_rk_t *rk"
.Ft const char *
.Fn fido_credman_rp_id "const fido_credman_rp_t *rp" "size_t idx"
.Ft const char *
.Fn fido_credman_rp_name "const fido_credman_rp_t *rp" "size_t idx"
.Ft size_t
.Fn fido_credman_rp_count "const fido_credman_rp_t *rp"
.Ft const unsigned char *
.Fn fido_credman_rp_id_hash_ptr "const fido_credman_rp_t *rp" "size_t idx"
.Ft size_t
.Fn fido_credman_rp_id_hash_len "const fido_credman_rp_t *" "size_t idx"
.Ft int
.Fn fido_credman_get_dev_metadata "fido_dev_t *dev" "fido_credman_metadata_t *metadata" "const char *pin"
.Ft int
.Fn fido_credman_get_dev_rk "fido_dev_t *dev" "const char *rp_id" "fido_credman_rk_t *rk" "const char *pin"
.Ft int
.Fn fido_credman_set_dev_rk "fido_dev_t *dev" "fido_cred_t *cred" "const char *pin"
.Ft int
.Fn fido_credman_del_dev_rk "fido_dev_t *dev" "const unsigned char *cred_id" "size_t cred_id_len" "const char *pin"
.Ft int
.Fn fido_credman_get_dev_rp "fido_dev_t *dev" "fido_credman_rp_t *rp" "const char *pin"
.Sh DESCRIPTION
The credential management API of
.Em libfido2
allows resident credentials on a FIDO2 authenticator to be listed,
inspected, modified, and removed.
Please note that not all FIDO2 authenticators support credential
management.
To obtain information on what an authenticator supports, please
refer to
.Xr fido_cbor_info_new 3 .
.Pp
The
.Vt fido_credman_metadata_t
type abstracts credential management metadata.
.Pp
The
.Fn fido_credman_metadata_new
function returns a pointer to a newly allocated, empty
.Vt fido_credman_metadata_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_credman_metadata_free
function releases the memory backing
.Fa *metadata_p ,
where
.Fa *metadata_p
must have been previously allocated by
.Fn fido_credman_metadata_new .
On return,
.Fa *metadata_p
is set to NULL.
Either
.Fa metadata_p
or
.Fa *metadata_p
may be NULL, in which case
.Fn fido_credman_metadata_free
is a NOP.
.Pp
The
.Fn fido_credman_get_dev_metadata
function populates
.Fa metadata
with information retrieved from
.Fa dev .
A valid
.Fa pin
must be provided.
.Pp
The
.Fn fido_credman_rk_existing
function inspects
.Fa metadata
and returns the number of resident credentials on the
authenticator.
The
.Fn fido_credman_rk_remaining
function inspects
.Fa metadata
and returns the estimated number of resident credentials that can
be created on the authenticator.
.Pp
The
.Vt fido_credman_rk_t
type abstracts the set of resident credentials belonging to a
given relying party.
.Pp
The
.Fn fido_credman_rk_new
function returns a pointer to a newly allocated, empty
.Vt fido_credman_rk_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_credman_rk_free
function releases the memory backing
.Fa *rk_p ,
where
.Fa *rk_p
must have been previously allocated by
.Fn fido_credman_rk_new .
On return,
.Fa *rk_p
is set to NULL.
Either
.Fa rk_p
or
.Fa *rk_p
may be NULL, in which case
.Fn fido_credman_rk_free
is a NOP.
.Pp
The
.Fn fido_credman_get_dev_rk
function populates
.Fa rk
with the set of resident credentials belonging to
.Fa rp_id
in
.Fa dev .
A valid
.Fa pin
must be provided.
.Pp
The
.Fn fido_credman_rk_count
function returns the number of resident credentials in
.Fa rk .
The
.Fn fido_credman_rk
function returns a pointer to the credential at index
.Fa idx
in
.Fa rk .
Please note that the first credential in
.Fa rk
has an
.Fa idx
(index) value of 0.
.Pp
The
.Fn fido_credman_set_dev_rk
function updates the credential pointed to by
.Fa cred
in
.Fa dev .
The credential id and user id attributes of
.Fa cred
must be set.
See
.Xr fido_cred_set_id 3
and
.Xr fido_cred_set_user 3
for details.
Only a credential's user attributes (name, display name)
may be updated at this time.
.Pp
The
.Fn fido_credman_del_dev_rk
function deletes the resident credential identified by
.Fa cred_id
from
.Fa dev ,
where
.Fa cred_id
points to
.Fa cred_id_len
bytes.
A valid
.Fa pin
must be provided.
.Pp
The
.Vt fido_credman_rp_t
type abstracts information about a relying party.
.Pp
The
.Fn fido_credman_rp_new
function returns a pointer to a newly allocated, empty
.Vt fido_credman_rp_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_credman_rp_free
function releases the memory backing
.Fa *rp_p ,
where
.Fa *rp_p
must have been previously allocated by
.Fn fido_credman_rp_new .
On return,
.Fa *rp_p
is set to NULL.
Either
.Fa rp_p
or
.Fa *rp_p
may be NULL, in which case
.Fn fido_credman_rp_free
is a NOP.
.Pp
The
.Fn fido_credman_get_dev_rp
function populates
.Fa rp
with information about relying parties with resident credentials
in
.Fa dev .
A valid
.Fa pin
must be provided.
.Pp
The
.Fn fido_credman_rp_count
function returns the number of relying parties in
.Fa rp .
.Pp
The
.Fn fido_credman_rp_id
and
.Fn fido_credman_rp_name
functions return pointers to the id and name of relying party
.Fa idx
in
.Fa rp .
If not NULL, the values returned by these functions point to
NUL-terminated UTF-8 strings.
Please note that the first relying party in
.Fa rp
has an
.Fa idx
(index) value of 0.
.Pp
The
.Fn fido_credman_rp_id_hash_ptr
function returns a pointer to the hashed id of relying party
.Fa idx
in
.Fa rp .
The corresponding length can be obtained by
.Fn fido_credman_rp_id_hash_len .
Please note that the first relying party in
.Fa rp
has an
.Fa idx
(index) value of 0.
.Sh RETURN VALUES
The
.Fn fido_credman_get_dev_metadata ,
.Fn fido_credman_get_dev_rk ,
.Fn fido_credman_set_dev_rk ,
.Fn fido_credman_del_dev_rk ,
and
.Fn fido_credman_get_dev_rp
functions return
.Dv FIDO_OK
on success.
On error, a different error code defined in
.In fido/err.h
is returned.
Functions returning pointers are not guaranteed to succeed, and
should have their return values checked for NULL.
.Sh SEE ALSO
.Xr fido_cbor_info_new 3 ,
.Xr fido_cred_new 3 ,
.Xr fido_dev_supports_credman 3
.Sh CAVEATS
Resident credentials are called
.Dq discoverable credentials
in FIDO 2.1.

View File

@ -0,0 +1,98 @@
.\" 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.
.\"
.Dd $Mdocdate: September 22 2020 $
.Dt FIDO_DEV_ENABLE_ENTATTEST 3
.Os
.Sh NAME
.Nm fido_dev_enable_entattest ,
.Nm fido_dev_toggle_always_uv ,
.Nm fido_dev_force_pin_change ,
.Nm fido_dev_set_pin_minlen
.Nd FIDO 2.1 configuration authenticator API
.Sh SYNOPSIS
.In fido.h
.In fido/config.h
.Ft int
.Fn fido_dev_enable_entattest "fido_dev_t *dev" "const char *pin"
.Ft int
.Fn fido_dev_toggle_always_uv "fido_dev_t *dev" "const char *pin"
.Ft int
.Fn fido_dev_force_pin_change "fido_dev_t *dev" "const char *pin"
.Ft int
.Fn fido_dev_set_pin_minlen "fido_dev_t *dev" "size_t len" "const char *pin"
.Sh DESCRIPTION
The functions described in this page allow configuration of a
FIDO 2.1 authenticator.
.Pp
The
.Fn fido_dev_enable_entattest
function enables the
.Em Enterprise Attestation
feature on
.Fa dev .
.Em Enterprise Attestation
instructs the authenticator to include uniquely identifying
information in subsequent attestation statements.
The
.Fa pin
parameter may be NULL if
.Fa dev
does not have a PIN set.
.Pp
The
.Fn fido_dev_toggle_always_uv
function toggles the
.Dq user verification always
feature on
.Fa dev .
When set, this toggle enforces user verification at the
authenticator level for all known credentials.
If
.Fa dev
supports U2F (CTAP1) and the user verification methods supported by
the authenticator do not allow protection of U2F credentials, the
U2F subsystem will be disabled by the authenticator.
The
.Fa pin
parameter may be NULL if
.Fa dev
does not have a PIN set.
.Pp
The
.Fn fido_dev_force_pin_change
instructs
.Fa dev
to require a PIN change.
Subsequent PIN authentication attempts against
.Fa dev
will fail until its PIN is changed.
.Pp
The
.Fn fido_dev_set_pin_minlen
function sets the minimum PIN length of
.Fa dev
to
.Fa len .
Minimum PIN lengths may only be increased.
.Pp
Configuration settings are reflected in the payload returned by the
authenticator in response to a
.Xr fido_dev_get_cbor_info 3
call.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_dev_enable_entattest ,
.Fn fido_dev_toggle_always_uv ,
.Fn fido_dev_force_pin_change ,
and
.Fn fido_dev_set_pin_minlen
are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_dev_get_cbor_info 3 ,
.Xr fido_dev_reset 3

76
man/fido_dev_get_assert.3 Normal file
View File

@ -0,0 +1,76 @@
.\" 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.
.\"
.Dd $Mdocdate: May 24 2018 $
.Dt FIDO_DEV_GET_ASSERT 3
.Os
.Sh NAME
.Nm fido_dev_get_assert
.Nd obtains an assertion from a FIDO device
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_dev_get_assert "fido_dev_t *dev" " fido_assert_t *assert" "const char *pin"
.Sh DESCRIPTION
The
.Fn fido_dev_get_assert
function asks the FIDO device represented by
.Fa dev
for an assertion according to the following parameters defined in
.Fa assert :
.Pp
.Bl -dash -compact
.It
.Nm relying party ID ;
.It
.Nm client data hash ;
.It
.Nm list of allowed credential IDs ;
.It
.Nm user presence and user verification attributes .
.El
.Pp
See
.Xr fido_assert_set_authdata 3
for information on how these values are set.
.Pp
If a PIN is not needed to authenticate the request against
.Fa dev ,
then
.Fa pin
may be NULL.
Otherwise
.Fa pin
must point to a NUL-terminated UTF-8 string.
.Pp
After a successful call to
.Fn fido_dev_get_assert ,
the
.Xr fido_assert_count 3 ,
.Xr fido_assert_user_display_name 3 ,
.Xr fido_assert_user_icon 3 ,
.Xr fido_assert_user_name 3 ,
.Xr fido_assert_authdata_ptr 3 ,
.Xr fido_assert_user_id_ptr 3 ,
.Xr fido_assert_sig_ptr 3 ,
and
.Xr fido_assert_sigcount 3
functions may be invoked on
.Fa assert
to retrieve the various attributes of the generated assertion.
.Pp
Please note that
.Fn fido_dev_get_assert
is synchronous and will block if necessary.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_dev_get_assert
are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_assert_new 3 ,
.Xr fido_assert_set_authdata 3

View File

@ -0,0 +1,73 @@
.\" 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.
.\"
.Dd $Mdocdate: August 5 2020 $
.Dt FIDO_DEV_GET_TOUCH_BEGIN 3
.Os
.Sh NAME
.Nm fido_dev_get_touch_begin ,
.Nm fido_dev_get_touch_status
.Nd asynchronously wait for touch on a FIDO 2 authenticator
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_dev_get_touch_begin "fido_dev_t *dev"
.Ft int
.Fn fido_dev_get_touch_status "fido_dev_t *dev" "int *touched" "int ms"
.Sh DESCRIPTION
The functions described in this page allow an application to
asynchronously wait for touch on a FIDO authenticator.
This is useful when multiple authenticators are present and
the application needs to know which one to use.
.Pp
The
.Fn fido_dev_get_touch_begin
function initiates a touch request on
.Fa dev .
.Pp
The
.Fn fido_dev_get_touch_status
function continues an ongoing touch request on
.Fa dev ,
blocking up to
.Fa ms
milliseconds.
On success,
.Fa touched
will be updated to reflect the touch request status.
If
.Fa touched
is 1, the device was touched, and the touch request is
terminated.
If
.Fa touched
is 0, the application may call
.Fn fido_dev_get_touch_status
to continue the touch request, or
.Fn fido_dev_cancel
to terminate it.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_dev_get_touch_begin
and
.Fn fido_dev_get_touch_status
are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh EXAMPLES
Please refer to
.Em examples/select.c
in
.Em libfido2's
source tree.
.Sh SEE ALSO
.Xr fido_dev_cancel 3
.Sh CAVEATS
The
.Fn fido_dev_get_touch_status
function will cause a command to be transmitted to U2F
authenticators.
These transmissions should not exceed a frequency of 5Hz.

View File

@ -0,0 +1,143 @@
.\" 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.
.\"
.Dd $Mdocdate: May 25 2018 $
.Dt FIDO_DEV_INFO_MANIFEST 3
.Os
.Sh NAME
.Nm fido_dev_info_manifest ,
.Nm fido_dev_info_new ,
.Nm fido_dev_info_free ,
.Nm fido_dev_info_ptr ,
.Nm fido_dev_info_path ,
.Nm fido_dev_info_product ,
.Nm fido_dev_info_vendor ,
.Nm fido_dev_info_manufacturer_string ,
.Nm fido_dev_info_product_string
.Nd FIDO 2 device discovery functions
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_dev_info_manifest "fido_dev_info_t *devlist" "size_t ilen" "size_t *olen"
.Ft fido_dev_info_t *
.Fn fido_dev_info_new "size_t n"
.Ft void
.Fn fido_dev_info_free "fido_dev_info_t **devlist_p" "size_t n"
.Ft const fido_dev_info_t *
.Fn fido_dev_info_ptr "const fido_dev_info_t *devlist" "size_t i"
.Ft const char *
.Fn fido_dev_info_path "const fido_dev_info_t *di"
.Ft int16_t
.Fn fido_dev_info_product "const fido_dev_info_t *di"
.Ft int16_t
.Fn fido_dev_info_vendor "const fido_dev_info_t *di"
.Ft const char *
.Fn fido_dev_info_manufacturer_string "const fido_dev_info_t *di"
.Ft const char *
.Fn fido_dev_info_product_string "const fido_dev_info_t *di"
.Sh DESCRIPTION
The
.Fn fido_dev_info_manifest
function fills
.Fa devlist
with up to
.Fa ilen
FIDO devices found by the underlying operating system.
Currently only USB HID devices are supported.
The number of discovered devices is returned in
.Fa olen ,
where
.Fa olen
is an addressable pointer.
.Pp
The
.Fn fido_dev_info_new
function returns a pointer to a newly allocated, empty device list
with
.Fa n
available slots.
If memory is not available, NULL is returned.
.Pp
The
.Fn fido_dev_info_free
function releases the memory backing
.Fa *devlist_p ,
where
.Fa *devlist_p
must have been previously allocated by
.Fn fido_dev_info_new .
The number
.Fa n
of allocated slots must also be provided.
On return,
.Fa *devlist_p
is set to NULL.
Either
.Fa devlist_p
or
.Fa *devlist_p
may be NULL, in which case
.Fn fido_dev_info_free
is a NOP.
.Pp
The
.Fn fido_dev_info_ptr
function returns a pointer to slot number
.Fa i
of
.Fa devlist .
It is the caller's responsibility to ensure that
.Fa i
is bounded.
Please note that the first slot has index 0.
.Pp
The
.Fn fido_dev_info_path
returns the filesystem path or subsystem-specific identification
string of
.Fa di .
.Pp
The
.Fn fido_dev_info_product
function returns the product ID of
.Fa di .
.Pp
The
.Fn fido_dev_info_vendor
function returns the vendor ID of
.Fa di .
.Pp
The
.Fn fido_dev_info_manufacturer_string
function returns the manufacturer string of
.Fa di .
.Pp
The
.Fn fido_dev_info_product_string
function returns the product string of
.Fa di .
.Pp
An example of how to use the functions described in this document
can be found in the
.Pa examples/manifest.c
file shipped with
.Em libfido2 .
.Sh RETURN VALUES
The
.Fn fido_dev_info_manifest
function always returns
.Dv FIDO_OK .
If a discovery error occurs, the
.Fa olen
pointer is set to 0.
.Pp
The pointers returned by
.Fn fido_dev_info_ptr ,
.Fn fido_dev_info_path ,
.Fn fido_dev_info_manufacturer_string ,
and
.Fn fido_dev_info_product_string
are guaranteed to exist until
.Fn fido_dev_info_free
is called on the corresponding device list.

View File

@ -0,0 +1,194 @@
.\" 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.
.\"
.Dd $Mdocdate: October 26 2020 $
.Dt FIDO_LARGEBLOB_GET 3
.Os
.Sh NAME
.Nm fido_dev_largeblob_get ,
.Nm fido_dev_largeblob_set ,
.Nm fido_dev_largeblob_remove ,
.Nm fido_dev_largeblob_get_array ,
.Nm fido_dev_largeblob_set_array
.Nd FIDO 2 large blob API
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_dev_largeblob_get "fido_dev_t *dev" "const unsigned char *key_ptr" "size_t key_len" "unsigned char **blob_ptr" "size_t *blob_len"
.Ft int
.Fn fido_dev_largeblob_set "fido_dev_t *dev" "const unsigned char *key_ptr" "size_t key_len" "const unsigned char *blob_ptr" "size_t blob_len" "const char *pin"
.Ft int
.Fn fido_dev_largeblob_remove "fido_dev_t *dev" "const unsigned char *key_ptr" "size_t key_len" "const char *pin"
.Ft int
.Fn fido_dev_largeblob_get_array "fido_dev_t *dev" "unsigned char **cbor_ptr" "size_t *cbor_len"
.Ft int
.Fn fido_dev_largeblob_set_array "fido_dev_t *dev" "const unsigned char *cbor_ptr" "size_t cbor_len" "const char *pin"
.Sh DESCRIPTION
The
.Dq largeBlobs
API of
.Em libfido2
allows binary blobs residing on a FIDO 2.1 authenticator to be
read, written, and inspected.
.Dq largeBlobs
is a FIDO 2.1 extension.
.Pp
.Dq largeBlobs
are stored as elements of a CBOR array.
Confidentiality is ensured by encrypting each element with a
distinct, credential-bound 256-bit AES-GCM key.
The array is otherwise shared between different credentials and
FIDO2 relying parties.
.Pp
Retrieval of a credential's encryption key is possible during
enrollment with
.Xr fido_cred_set_extensions 3
and
.Xr fido_cred_largeblob_key_ptr 3 ,
during assertion with
.Xr fido_assert_set_extensions 3
and
.Xr fido_assert_largeblob_key_ptr 3 ,
or, in the case of a resident credential, via
.Em libfido2's
credential management API.
.Pp
The
.Dq largeBlobs
CBOR array is opaque to the authenticator.
Management of the array is left at the discretion of FIDO2 clients.
For further details on FIDO 2.1's
.Dq largeBlobs
extension, please refer to the FIDO 2.1 spec.
.Pp
The
.Fn fido_dev_largeblob_get
function retrieves the authenticator's
.Dq largeBlobs
CBOR array and, on success, returns the first blob
.Pq iterating from array index zero
that can be
decrypted by
.Fa key_ptr ,
where
.Fa key_ptr
points to
.Fa key_len
bytes.
On success,
.Fn fido_dev_largeblob_get
sets
.Fa blob_ptr
to the body of the decrypted blob, and
.Fa blob_len
to the length of the decrypted blob in bytes.
It is the caller's responsibility to free
.Fa blob_ptr .
.Pp
The
.Fn fido_dev_largeblob_set
function uses
.Fa key_ptr
to encrypt
.Fa blob_ptr
and inserts the result in the authenticator's
.Dq largeBlobs
CBOR array.
Insertion happens at the end of the array if no existing element
can be decrypted by
.Fa key_ptr ,
or at the position of the first element
.Pq iterating from array index zero
that can be decrypted by
.Fa key_ptr .
.Fa key_len
holds the length of
.Fa key_ptr
in bytes, and
.Fa blob_len
the length of
.Fa blob_ptr
in bytes.
A
.Fa pin
or equivalent user-verification gesture is required.
.Pp
The
.Fn fido_dev_largeblob_remove
function retrieves the authenticator's
.Dq largeBlobs
CBOR array and, on success, drops the first blob
.Pq iterating from array index zero
that can be decrypted by
.Fa key_ptr ,
where
.Fa key_ptr
points to
.Fa key_len
bytes.
A
.Fa pin
or equivalent user-verification gesture is required.
.Pp
The
.Fn fido_dev_largeblob_get_array
function retrieves the authenticator's
.Dq largeBlobs
CBOR array and, on success,
sets
.Fa cbor_ptr
to the body of the CBOR array, and
.Fa cbor_len
to its corresponding length in bytes.
It is the caller's responsibility to free
.Fa cbor_ptr .
.Pp
Finally, the
.Fn fido_dev_largeblob_set_array
function sets the authenticator's
.Dq largeBlobs
CBOR array to the data pointed to by
.Fa cbor_ptr ,
where
.Fa cbor_ptr
points to
.Fa cbor_len
bytes.
A
.Fa pin
or equivalent user-verification gesture is required.
.Sh RETURN VALUES
The functions
.Fn fido_dev_largeblob_set ,
.Fn fido_dev_largeblob_get ,
.Fn fido_dev_largeblob_remove ,
.Fn fido_dev_largeblob_get_array ,
and
.Fn fido_dev_largeblob_set_array
return
.Dv FIDO_OK
on success.
On error, an error code defined in
.In fido/err.h
is returned.
.Sh SEE ALSO
.Xr fido_assert_largeblob_key_len 3 ,
.Xr fido_assert_largeblob_key_ptr 3 ,
.Xr fido_assert_set_extensions 3 ,
.Xr fido_cred_largeblob_key_len 3 ,
.Xr fido_cred_largeblob_key_ptr 3 ,
.Xr fido_cred_set_extensions 3 ,
.Xr fido_credman_dev_get_rk 3 ,
.Xr fido_credman_dev_get_rp 3 ,
.Xr fido_dev_get_assert 3 ,
.Xr fido_dev_make_cred 3
.Sh CAVEATS
The
.Dq largeBlobs
extension is not meant to be used to store sensitive data.
When retrieved, a credential's
.Dq largeBlobs
encryption key is transmitted in the clear, and an authenticator's
.Dq largeBlobs
CBOR array can be read without user interaction or verification.

77
man/fido_dev_make_cred.3 Normal file
View File

@ -0,0 +1,77 @@
.\" 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.
.\"
.Dd $Mdocdate: May 23 2018 $
.Dt FIDO_DEV_MAKE_CRED 3
.Os
.Sh NAME
.Nm fido_dev_make_cred
.Nd generates a new credential on a FIDO device
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_dev_make_cred "fido_dev_t *dev" " fido_cred_t *cred" "const char *pin"
.Sh DESCRIPTION
The
.Fn fido_dev_make_cred
function asks the FIDO device represented by
.Fa dev
to generate a new credential according to the following parameters
defined in
.Fa cred :
.Pp
.Bl -dash -compact
.It
.Nm type ;
.It
.Nm client data hash ;
.It
.Nm relying party ;
.It
.Nm user attributes ;
.It
.Nm list of excluded credential IDs ;
.It
.Nm resident/discoverable key and user verification attributes .
.El
.Pp
See
.Xr fido_cred_set_authdata 3
for information on how these values are set.
.Pp
If a PIN is not needed to authenticate the request against
.Fa dev ,
then
.Fa pin
may be NULL.
Otherwise
.Fa pin
must point to a NUL-terminated UTF-8 string.
.Pp
After a successful call to
.Fn fido_dev_make_cred ,
the
.Xr fido_cred_authdata_ptr 3 ,
.Xr fido_cred_pubkey_ptr 3 ,
.Xr fido_cred_x5c_ptr 3 ,
and
.Xr fido_cred_sig_ptr 3
functions may be invoked on
.Fa cred
to retrieve the various parts of the generated credential.
.Pp
Please note that
.Fn fido_dev_make_cred
is synchronous and will block if necessary.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_dev_make_cred
are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh SEE ALSO
.Xr fido_cred_new 3 ,
.Xr fido_cred_set_authdata 3

250
man/fido_dev_open.3 Normal file
View File

@ -0,0 +1,250 @@
.\" 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.
.\"
.Dd $Mdocdate: May 25 2018 $
.Dt FIDO_DEV_OPEN 3
.Os
.Sh NAME
.Nm fido_dev_open ,
.Nm fido_dev_close ,
.Nm fido_dev_cancel ,
.Nm fido_dev_new ,
.Nm fido_dev_free ,
.Nm fido_dev_force_fido2 ,
.Nm fido_dev_force_u2f ,
.Nm fido_dev_is_fido2 ,
.Nm fido_dev_is_winhello ,
.Nm fido_dev_supports_credman ,
.Nm fido_dev_supports_cred_prot ,
.Nm fido_dev_supports_pin ,
.Nm fido_dev_has_pin ,
.Nm fido_dev_supports_uv ,
.Nm fido_dev_has_uv ,
.Nm fido_dev_protocol ,
.Nm fido_dev_build ,
.Nm fido_dev_flags ,
.Nm fido_dev_major ,
.Nm fido_dev_minor
.Nd FIDO 2 device open/close and related functions
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_dev_open "fido_dev_t *dev" "const char *path"
.Ft int
.Fn fido_dev_close "fido_dev_t *dev"
.Ft int
.Fn fido_dev_cancel "fido_dev_t *dev"
.Ft fido_dev_t *
.Fn fido_dev_new "void"
.Ft void
.Fn fido_dev_free "fido_dev_t **dev_p"
.Ft void
.Fn fido_dev_force_fido2 "fido_dev_t *dev"
.Ft void
.Fn fido_dev_force_u2f "fido_dev_t *dev"
.Ft bool
.Fn fido_dev_is_fido2 "const fido_dev_t *dev"
.Ft bool
.Fn fido_dev_is_winhello "const fido_dev_t *dev"
.Ft bool
.Fn fido_dev_supports_credman "const fido_dev_t *dev"
.Ft bool
.Fn fido_dev_supports_cred_prot "const fido_dev_t *dev"
.Ft bool
.Fn fido_dev_supports_pin "const fido_dev_t *dev"
.Ft bool
.Fn fido_dev_has_pin "const fido_dev_t *dev"
.Ft bool
.Fn fido_dev_supports_uv "const fido_dev_t *dev"
.Ft bool
.Fn fido_dev_has_uv "const fido_dev_t *dev"
.Ft uint8_t
.Fn fido_dev_protocol "const fido_dev_t *dev"
.Ft uint8_t
.Fn fido_dev_build "const fido_dev_t *dev"
.Ft uint8_t
.Fn fido_dev_flags "const fido_dev_t *dev"
.Ft uint8_t
.Fn fido_dev_major "const fido_dev_t *dev"
.Ft uint8_t
.Fn fido_dev_minor "const fido_dev_t *dev"
.Sh DESCRIPTION
The
.Fn fido_dev_open
function opens the device pointed to by
.Fa path ,
where
.Fa dev
is a freshly allocated or otherwise closed
.Vt fido_dev_t .
If
.Fa dev
claims to be FIDO2,
.Em libfido2
will attempt to speak FIDO2 to
.Fa dev .
If that fails,
.Em libfido2
will fallback to U2F unless the
.Dv FIDO_DISABLE_U2F_FALLBACK
flag was set in
.Xr fido_init 3 .
.Pp
The
.Fn fido_dev_close
function closes the device represented by
.Fa dev .
If
.Fa dev
is already closed,
.Fn fido_dev_close
is a NOP.
.Pp
The
.Fn fido_dev_cancel
function cancels any pending requests on
.Fa dev .
.Pp
The
.Fn fido_dev_new
function returns a pointer to a newly allocated, empty
.Vt fido_dev_t .
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn fido_dev_free
function releases the memory backing
.Fa *dev_p ,
where
.Fa *dev_p
must have been previously allocated by
.Fn fido_dev_new .
On return,
.Fa *dev_p
is set to NULL.
Either
.Fa dev_p
or
.Fa *dev_p
may be NULL, in which case
.Fn fido_dev_free
is a NOP.
.Pp
The
.Fn fido_dev_force_fido2
function can be used to force CTAP2 communication with
.Fa dev .
.Pp
The
.Fn fido_dev_force_u2f
function can be used to force CTAP1 (U2F) communication with
.Fa dev .
.Pp
The
.Fn fido_dev_is_fido2
function returns
.Dv true
if
.Fa dev
is a FIDO 2 device.
.Pp
The
.Fn fido_dev_is_winhello
function returns
.Dv true
if
.Fa dev
is a Windows Hello device.
.Pp
The
.Fn fido_dev_supports_credman
function returns
.Dv true
if
.Fa dev
supports FIDO 2.1 Credential Management.
.Pp
The
.Fn fido_dev_supports_cred_prot
function returns
.Dv true
if
.Fa dev
supports FIDO 2.1 Credential Protection.
.Pp
The
.Fn fido_dev_supports_pin
function returns
.Dv true
if
.Fa dev
supports FIDO 2.0 Client PINs.
.Pp
The
.Fn fido_dev_has_pin
function returns
.Dv true
if
.Fa dev
has a FIDO 2.0 Client PIN set.
.Pp
The
.Fn fido_dev_supports_uv
function returns
.Dv true
if
.Fa dev
supports a built-in user verification method.
.Pp
The
.Fn fido_dev_has_uv
function returns
.Dv true
if
.Fa dev
supports built-in user verification and its user verification
feature is configured.
.Pp
The
.Fn fido_dev_protocol
function returns the CTAPHID protocol version identifier of
.Fa dev .
.Pp
The
.Fn fido_dev_build
function returns the CTAPHID build version number of
.Fa dev .
.Pp
The
.Fn fido_dev_flags
function returns the CTAPHID capabilities flags of
.Fa dev .
.Pp
The
.Fn fido_dev_major
function returns the CTAPHID major version number of
.Fa dev .
.Pp
The
.Fn fido_dev_minor
function returns the CTAPHID minor version number of
.Fa dev .
.Pp
For the format and meaning of the CTAPHID parameters returned by
functions above, please refer to the FIDO Client to Authenticator
Protocol (CTAP) specification.
.Sh RETURN VALUES
On success,
.Fn fido_dev_open
and
.Fn fido_dev_close
return
.Dv FIDO_OK .
On error, a different error code defined in
.In fido/err.h
is returned.
.Sh SEE ALSO
.Xr fido_dev_info_manifest 3 ,
.Xr fido_dev_set_io_functions 3 ,
.Xr fido_init 3

View File

@ -0,0 +1,134 @@
.\" 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.
.\"
.Dd $Mdocdate: May 25 2018 $
.Dt FIDO_DEV_SET_IO_FUNCTIONS 3
.Os
.Sh NAME
.Nm fido_dev_set_io_functions ,
.Nm fido_dev_set_sigmask
.Nd FIDO 2 device I/O interface
.Sh SYNOPSIS
.In fido.h
.Bd -literal
typedef void *fido_dev_io_open_t(const char *);
typedef void fido_dev_io_close_t(void *);
typedef int fido_dev_io_read_t(void *, unsigned char *, size_t, int);
typedef int fido_dev_io_write_t(void *, const unsigned char *, size_t);
typedef struct fido_dev_io {
fido_dev_io_open_t *open;
fido_dev_io_close_t *close;
fido_dev_io_read_t *read;
fido_dev_io_write_t *write;
} fido_dev_io_t;
#ifdef _WIN32
typedef int fido_sigset_t;
#else
typedef sigset_t fido_sigset_t;
#endif
.Ed
.Ft int
.Fn fido_dev_set_io_functions "fido_dev_t *dev" "const fido_dev_io_t *io"
.Ft int
.Fn fido_dev_set_sigmask "fido_dev_t *dev" "const fido_sigset_t *sigmask"
.Sh DESCRIPTION
The
.Fn fido_dev_set_io_functions
function sets the I/O handlers used by
.Em libfido2
to talk to
.Fa dev .
By default, these handlers are set to the operating system's native HID or NFC
interfaces.
They are defined as follows:
.Bl -tag -width Ds
.It Vt fido_dev_open_t
Receives a
.Vt const char *
holding a path and opens the corresponding device, returning a
non-NULL opaque pointer on success and NULL on error.
.It Vt fido_dev_close_t
Receives the opaque pointer returned by
.Vt fido_dev_open_t
and closes the device.
.It Vt fido_dev_read_t
Reads a single transmission unit (HID report, APDU) from a device.
The first parameter is the opaque pointer returned by
.Vt fido_dev_open_t .
The second parameter is the read buffer, and the third parameter
is the read buffer size.
The fourth parameter is the number of milliseconds the caller is
willing to sleep, should the call need to block.
If this value holds -1,
.Vt fido_dev_read_t
may block indefinitely.
On success, the number of bytes read is returned.
On error, -1 is returned.
.It Vt fido_dev_write_t
Writes a single transmission unit (HID report, APDU) to
.Fa dev .
The first parameter is the opaque pointer returned by
.Vt fido_dev_open_t .
The second parameter is the write buffer, and the third parameter
is the number of bytes to be written.
A
.Vt fido_dev_write_t
may block.
On success, the number of bytes written is returned.
On error, -1 is returned.
.El
.Pp
When calling
.Fn fido_dev_set_io_functions ,
the
.Fa open ,
.Fa close ,
.Fa read ,
and
.Fa write
fields of
.Fa io
may not be NULL.
.Pp
No references to
.Fa io
are held by
.Fn fido_dev_set_io_functions .
.Pp
The
.Fn fido_dev_set_sigmask
function may be used to specify a non-NULL signal mask
.Fa sigmask
to be used while
.Em libfido2's
default I/O handlers wait on
.Fa dev .
On UNIX-like operating systems,
.Vt fido_sigset_t
is defined as
.Vt sigset_t .
On Windows,
.Vt fido_sigset_t
is defined as
.Vt int
and
.Fn fido_dev_set_sigmask
is a no-op.
.Pp
No references to
.Fa sigmask
are held by
.Fn fido_dev_set_sigmask .
.Sh RETURN VALUES
On success,
.Fn fido_dev_set_io_functions
and
.Fn fido_dev_set_sigmask
return
.Dv FIDO_OK .
On error, a different error code defined in
.In fido/err.h
is returned.

103
man/fido_dev_set_pin.3 Normal file
View File

@ -0,0 +1,103 @@
.\" 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.
.\"
.Dd $Mdocdate: May 25 2018 $
.Dt FIDO_DEV_SET_PIN 3
.Os
.Sh NAME
.Nm fido_dev_set_pin ,
.Nm fido_dev_get_retry_count ,
.Nm fido_dev_get_uv_retry_count ,
.Nm fido_dev_reset
.Nd FIDO 2 device management functions
.Sh SYNOPSIS
.In fido.h
.Ft int
.Fn fido_dev_set_pin "fido_dev_t *dev" "const char *pin" "const char *oldpin"
.Ft int
.Fn fido_dev_get_retry_count "fido_dev_t *dev" "int *retries"
.Ft int
.Fn fido_dev_get_uv_retry_count "fido_dev_t *dev" "int *retries"
.Ft int
.Fn fido_dev_reset "fido_dev_t *dev"
.Sh DESCRIPTION
The
.Fn fido_dev_set_pin
function sets the PIN of device
.Fa dev
to
.Fa pin ,
where
.Fa pin
is a NUL-terminated UTF-8 string.
If
.Fa oldpin
is not NULL, the device's PIN is changed from
.Fa oldpin
to
.Fa pin ,
where
.Fa pin
and
.Fa oldpin
are NUL-terminated UTF-8 strings.
.Pp
The
.Fn fido_dev_get_retry_count
function fills
.Fa retries
with the number of PIN retries left in
.Fa dev
before lock-out, where
.Fa retries
is an addressable pointer.
.Pp
The
.Fn fido_dev_get_uv_retry_count
function fills
.Fa retries
with the number of built-in UV retries left in
.Fa dev
before built-in UV is disabled, where
.Fa retries
is an addressable pointer.
.Pp
The
.Fn fido_dev_reset
function performs a reset on
.Fa dev ,
resetting the device's PIN and erasing credentials stored on the
device.
.Pp
Please note that
.Fn fido_dev_set_pin ,
.Fn fido_dev_get_retry_count ,
.Fn fido_dev_get_uv_retry_count ,
and
.Fn fido_dev_reset
are synchronous and will block if necessary.
.Sh RETURN VALUES
The error codes returned by
.Fn fido_dev_set_pin ,
.Fn fido_dev_get_retry_count ,
.Fn fido_dev_get_uv_retry_count ,
and
.Fn fido_dev_reset
are defined in
.In fido/err.h .
On success,
.Dv FIDO_OK
is returned.
.Sh CAVEATS
Regarding
.Fn fido_dev_reset ,
the actual user-flow to perform a reset is outside the scope of the
FIDO2 specification, and may therefore vary depending on the
authenticator.
Yubico authenticators will return
.Dv FIDO_ERR_NOT_ALLOWED
if a reset is issued later than 5 seconds after power-up, and
.Dv FIDO_ERR_ACTION_TIMEOUT
if the user fails to confirm the reset by touching the key
within 30 seconds.

52
man/fido_init.3 Normal file
View File

@ -0,0 +1,52 @@
.\" 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.
.\"
.Dd $Mdocdate: May 25 2018 $
.Dt FIDO_INIT 3
.Os
.Sh NAME
.Nm fido_init
.Nd initialise the FIDO 2 library
.Sh SYNOPSIS
.In fido.h
.Ft void
.Fn fido_init "int flags"
.Sh DESCRIPTION
The
.Fn fido_init
function initialises the
.Em libfido2
library.
Its invocation must precede that of any other
.Em libfido2
function in the context of the executing thread.
.Pp
If
.Dv FIDO_DEBUG
is set in
.Fa flags ,
then
debug output will be emitted by
.Em libfido2
on
.Em stderr .
Alternatively, the
.Ev FIDO_DEBUG
environment variable may be set.
.Pp
If
.Dv FIDO_DISABLE_U2F_FALLBACK
is set in
.Fa flags ,
then
.Em libfido2
will not fallback to U2F in
.Xr fido_dev_open 3
if a device claims to be FIDO2 but fails to respond to a
FIDO2 command.
.Sh SEE ALSO
.Xr fido_assert_new 3 ,
.Xr fido_cred_new 3 ,
.Xr fido_dev_info_manifest 3 ,
.Xr fido_dev_open 3

27
man/fido_strerr.3 Normal file
View File

@ -0,0 +1,27 @@
.\" 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.
.\"
.Dd $Mdocdate: May 25 2018 $
.Dt FIDO_STRERR 3
.Os
.Sh NAME
.Nm fido_strerr
.Nd FIDO 2 error codes
.Sh SYNOPSIS
.In fido.h
.Ft const char *
.Fn fido_strerr "int n"
.Sh DESCRIPTION
The
.Fn fido_strerr
function translates the error code
.Fa n
into a readable string,
where
.Fa n
is an error code defined in
.In fido/err.h .
.Fn fido_strerr
never returns NULL.
Returned pointers point to static strings.

122
man/rs256_pk_new.3 Normal file
View File

@ -0,0 +1,122 @@
.\" 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.
.\"
.Dd $Mdocdate: May 24 2018 $
.Dt RS256_PK_NEW 3
.Os
.Sh NAME
.Nm rs256_pk_new ,
.Nm rs256_pk_free ,
.Nm rs256_pk_from_RSA ,
.Nm rs256_pk_from_ptr ,
.Nm rs256_pk_to_EVP_PKEY
.Nd FIDO 2 COSE RS256 API
.Sh SYNOPSIS
.In openssl/rsa.h
.In fido/rs256.h
.Ft rs256_pk_t *
.Fn rs256_pk_new "void"
.Ft void
.Fn rs256_pk_free "rs256_pk_t **pkp"
.Ft int
.Fn rs256_pk_from_RSA "rs256_pk_t *pk" "const RSA *rsa"
.Ft int
.Fn rs256_pk_from_ptr "rs256_pk_t *pk" "const void *ptr" "size_t len"
.Ft EVP_PKEY *
.Fn rs256_pk_to_EVP_PKEY "const rs256_pk_t *pk"
.Sh DESCRIPTION
RS256 is the name given in the CBOR Object Signing and Encryption
(COSE) RFC to PKCS#1.5 2048-bit RSA with SHA-256.
The COSE RS256 API of
.Em libfido2
is an auxiliary API with routines to convert between the different
RSA public key types used in
.Em libfido2
and
.Em OpenSSL .
.Pp
In
.Em libfido2 ,
RS256 public keys are abstracted by the
.Vt rs256_pk_t
type.
.Pp
The
.Fn rs256_pk_new
function returns a pointer to a newly allocated, empty
.Vt rs256_pk_t
type.
If memory cannot be allocated, NULL is returned.
.Pp
The
.Fn rs256_pk_free
function releases the memory backing
.Fa *pkp ,
where
.Fa *pkp
must have been previously allocated by
.Fn rs256_pk_new .
On return,
.Fa *pkp
is set to NULL.
Either
.Fa pkp
or
.Fa *pkp
may be NULL, in which case
.Fn rs256_pk_free
is a NOP.
.Pp
The
.Fn rs256_pk_from_RSA
function fills
.Fa pk
with the contents of
.Fa rsa .
No references to
.Fa rsa
are kept.
.Pp
The
.Fn rs256_pk_from_ptr
function fills
.Fa pk
with the contents of
.Fa ptr ,
where
.Fa ptr
points to
.Fa len
bytes.
No references to
.Fa ptr
are kept.
.Pp
The
.Fn rs256_pk_to_EVP_PKEY
function converts
.Fa pk
to a newly allocated
.Fa EVP_PKEY
type with a reference count of 1.
No internal references to the returned pointer are kept.
If an error occurs,
.Fn rs256_pk_to_EVP_PKEY
returns NULL.
.Sh RETURN VALUES
The
.Fn rs256_pk_from_RSA
and
.Fn rs256_pk_from_ptr
functions return
.Dv FIDO_OK
on success.
On error, a different error code defined in
.In fido/err.h
is returned.
.Sh SEE ALSO
.Xr eddsa_pk_new 3 ,
.Xr es256_pk_new 3 ,
.Xr fido_assert_verify 3 ,
.Xr fido_cred_pubkey_ptr 3

24
man/style.css Normal file
View File

@ -0,0 +1,24 @@
* { margin: 0; padding: 0; }
body {
font-family: monospace;
font-size: 1em;
margin: 2% auto;
max-width: 54em;
}
ul { margin-left: 1em; }
a { color: #009900; }
.Sh { font-size: 1em; padding-top: 1em; padding-bottom: 1em; }
.foot { padding-top: 1em; }
table.head, table.foot { width: 100%; }
td.head-rtitle, td.foot-os { text-align: right; }
td.head-vol { text-align: center; }
div.Pp { margin: 1ex 0ex; }
div.Nd, div.Bf, div.Op { display: inline; }
span.Pa, span.Ad { font-style: italic; }
span.Ms { font-weight: bold; }
dl.Bl-diag > dt { font-weight: bold; }
code.Nm, code.Fl, code.Cm, code.Ic, code.In, code.Fd, code.Fn,
code.Cd { font-weight: bold; font-family: inherit; }

View File

@ -0,0 +1,115 @@
/* $NetBSD: getline.c,v 1.1.1.6 2015/01/02 20:34:27 christos Exp $ */
/* NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/* NETBSD ORIGINAL: external/bsd/file/dist/src/getline.c */
#include "openbsd-compat.h"
#if 0
#include "file.h"
#endif
#if !HAVE_GETLINE
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include <string.h>
static ssize_t
getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
{
char *ptr, *eptr;
if (*buf == NULL || *bufsiz == 0) {
if ((*buf = malloc(BUFSIZ)) == NULL)
return -1;
*bufsiz = BUFSIZ;
}
for (ptr = *buf, eptr = *buf + *bufsiz;;) {
int c = fgetc(fp);
if (c == -1) {
if (feof(fp)) {
ssize_t diff = (ssize_t)(ptr - *buf);
if (diff != 0) {
*ptr = '\0';
return diff;
}
}
return -1;
}
*ptr++ = (char)c;
if (c == delimiter) {
*ptr = '\0';
return ptr - *buf;
}
if (ptr + 2 >= eptr) {
char *nbuf;
size_t nbufsiz = *bufsiz * 2;
ssize_t d = ptr - *buf;
if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
return -1;
*buf = nbuf;
*bufsiz = nbufsiz;
eptr = nbuf + nbufsiz;
ptr = nbuf + d;
}
}
}
ssize_t
getline(char **buf, size_t *bufsiz, FILE *fp)
{
return getdelim(buf, bufsiz, '\n', fp);
}
#endif
#ifdef TEST
int
main(int argc, char *argv[])
{
char *p = NULL;
ssize_t len;
size_t n = 0;
while ((len = getline(&p, &n, stdin)) != -1)
(void)printf("%" SIZE_T_FORMAT "d %s", len, p);
free(p);
return 0;
}
#endif

View File

@ -0,0 +1,27 @@
/* Placed in the public domain */
#include "openbsd-compat.h"
#if !defined(HAVE_GETPAGESIZE)
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <limits.h>
int
getpagesize(void)
{
#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
long r = sysconf(_SC_PAGESIZE);
if (r > 0 && r < INT_MAX)
return (int)r;
#endif
/*
* This is at the lower end of common values and appropriate for
* our current use of getpagesize() in recallocarray().
*/
return 4096;
}
#endif /* !defined(HAVE_GETPAGESIZE) */

View File

@ -0,0 +1,32 @@
/*
* 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.
*/
#include "openbsd-compat.h"
#if !defined(HAVE_CLOCK_GETTIME)
#if _WIN32
int
clock_gettime(clockid_t clock_id, struct timespec *tp)
{
ULONGLONG ms;
if (clock_id != CLOCK_MONOTONIC) {
errno = EINVAL;
return (-1);
}
ms = GetTickCount64();
tp->tv_sec = ms / 1000L;
tp->tv_nsec = (ms % 1000L) * 1000000L;
return (0);
}
#else
#error "please provide an implementation of clock_gettime() for your platform"
#endif /* _WIN32 */
#endif /* !defined(HAVE_CLOCK_GETTIME) */

View File

@ -0,0 +1,51 @@
/*
* 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.
*/
#include "openbsd-compat.h"
#if defined(_WIN32) && !defined(HAVE_ENDIAN_H)
/*
* Hopefully, if the endianness differs from the end result, the compiler
* optimizes these functions with some type of bswap instruction. Or,
* otherwise, to just return the input value unmodified. GCC and clang
* both does these optimization at least. This should be preferred over
* relying on some BYTE_ORDER macro, which may or may not be defined.
*/
uint32_t
htole32(uint32_t in)
{
uint32_t out = 0;
uint8_t *b = (uint8_t *)&out;
b[0] = (uint8_t)((in >> 0) & 0xff);
b[1] = (uint8_t)((in >> 8) & 0xff);
b[2] = (uint8_t)((in >> 16) & 0xff);
b[3] = (uint8_t)((in >> 24) & 0xff);
return (out);
}
uint64_t
htole64(uint64_t in)
{
uint64_t out = 0;
uint8_t *b = (uint8_t *)&out;
b[0] = (uint8_t)((in >> 0) & 0xff);
b[1] = (uint8_t)((in >> 8) & 0xff);
b[2] = (uint8_t)((in >> 16) & 0xff);
b[3] = (uint8_t)((in >> 24) & 0xff);
b[4] = (uint8_t)((in >> 32) & 0xff);
b[5] = (uint8_t)((in >> 40) & 0xff);
b[6] = (uint8_t)((in >> 48) & 0xff);
b[7] = (uint8_t)((in >> 56) & 0xff);
return (out);
}
#endif /* WIN32 && !HAVE_ENDIAN_H */

85
openbsd-compat/err.h Normal file
View File

@ -0,0 +1,85 @@
/*
* Public domain
* err.h compatibility shim
*/
#ifndef _COMPAT_ERR_H
#define _COMPAT_ERR_H
#if !defined(HAVE_ERR_H)
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if defined(_MSC_VER)
__declspec(noreturn)
#else
__attribute__((noreturn))
#endif
static inline void
err(int eval, const char *fmt, ...)
{
int sverrno = errno;
va_list ap;
va_start(ap, fmt);
if (fmt != NULL) {
vfprintf(stderr, fmt, ap);
fprintf(stderr, ": ");
}
va_end(ap);
fprintf(stderr, "%s\n", strerror(sverrno));
exit(eval);
}
#if defined(_MSC_VER)
__declspec(noreturn)
#else
__attribute__((noreturn))
#endif
static inline void
errx(int eval, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (fmt != NULL)
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
exit(eval);
}
static inline void
warn(const char *fmt, ...)
{
int sverrno = errno;
va_list ap;
va_start(ap, fmt);
if (fmt != NULL) {
vfprintf(stderr, fmt, ap);
fprintf(stderr, ": ");
}
va_end(ap);
fprintf(stderr, "%s\n", strerror(sverrno));
}
static inline void
warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (fmt != NULL)
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
}
#endif /* !defined(HAVE_ERR_H) */
#endif /* _COMPAT_ERR_H */

View File

@ -0,0 +1,57 @@
/* OPENBSD ORIGINAL: lib/libc/string/explicit_bzero.c */
/* $OpenBSD: explicit_bzero.c,v 1.1 2014/01/22 21:06:45 tedu Exp $ */
/*
* Public domain.
* Written by Ted Unangst
*/
#include "openbsd-compat.h"
#if !defined(HAVE_EXPLICIT_BZERO) && !defined(_WIN32)
#include <string.h>
/*
* explicit_bzero - don't let the compiler optimize away bzero
*/
#ifdef HAVE_MEMSET_S
void
explicit_bzero(void *p, size_t n)
{
if (n == 0)
return;
(void)memset_s(p, n, 0, n);
}
#else /* HAVE_MEMSET_S */
/*
* Indirect bzero through a volatile pointer to hopefully avoid
* dead-store optimisation eliminating the call.
*/
static void (* volatile ssh_bzero)(void *, size_t) = bzero;
void
explicit_bzero(void *p, size_t n)
{
if (n == 0)
return;
/*
* clang -fsanitize=memory needs to intercept memset-like functions
* to correctly detect memory initialisation. Make sure one is called
* directly since our indirection trick above successfully confuses it.
*/
#if defined(__has_feature)
# if __has_feature(memory_sanitizer)
memset(p, 0, n);
# endif
#endif
ssh_bzero(p, n);
}
#endif /* HAVE_MEMSET_S */
#endif /* !defined(HAVE_EXPLICIT_BZERO) && !defined(_WIN32) */

View File

@ -0,0 +1,19 @@
/*
* Public domain.
* Win32 explicit_bzero compatibility shim.
*/
#include "openbsd-compat.h"
#if !defined(HAVE_EXPLICIT_BZERO) && defined(_WIN32)
#include <windows.h>
#include <string.h>
void
explicit_bzero(void *buf, size_t len)
{
SecureZeroMemory(buf, len);
}
#endif /* !defined(HAVE_EXPLICIT_BZERO) && defined(_WIN32) */

30
openbsd-compat/freezero.c Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
*
* 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 "openbsd-compat.h"
#ifndef HAVE_FREEZERO
void
freezero(void *ptr, size_t sz)
{
if (ptr == NULL)
return;
explicit_bzero(ptr, sz);
free(ptr);
}
#endif /* HAVE_FREEZERO */

74
openbsd-compat/getopt.h Normal file
View File

@ -0,0 +1,74 @@
/* $OpenBSD: getopt.h,v 1.2 2008/06/26 05:42:04 ray Exp $ */
/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#ifndef _GETOPT_H_
#define _GETOPT_H_
/*
* GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions
*/
#define no_argument 0
#define required_argument 1
#define optional_argument 2
struct option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};
int getopt_long(int, char * const *, const char *,
const struct option *, int *);
int getopt_long_only(int, char * const *, const char *,
const struct option *, int *);
#ifndef _GETOPT_DEFINED_
#define _GETOPT_DEFINED_
int getopt(int, char * const *, const char *);
int getsubopt(char **, char * const *, char **);
extern char *optarg; /* getopt(3) external variables */
extern int opterr;
extern int optind;
extern int optopt;
extern int optreset;
extern char *suboptarg; /* getsubopt(3) external variable */
#endif
#endif /* !_GETOPT_H_ */

View File

@ -0,0 +1,523 @@
/* $OpenBSD: getopt_long.c,v 1.25 2011/03/05 22:10:11 guenther Exp $ */
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* 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.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/* OPENBSD ORIGINAL: lib/libc/stdlib/getopt_long.c */
#include "openbsd-compat.h"
#if !defined(HAVE_GETOPT)
#if 0
#include <err.h>
#include <getopt.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define PRINT_ERROR ((opterr) && (*options != ':'))
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
/* return values */
#define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#define EMSG ""
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
static char *place = EMSG; /* option letter processing */
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c";
static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s";
static const char noarg[] = "option doesn't take an argument -- %.*s";
static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(int a, int b)
{
int c;
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return (b);
}
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(int panonopt_start, int panonopt_end, int opt_end,
char * const *nargv)
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
/* LINTED const cast */
((char **) nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap;
}
}
}
/*
* parse_long_options --
* Parse long options in argc/argv argument vector.
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too)
{
char *current_argv, *has_equal;
size_t current_argv_len;
int i, match;
current_argv = place;
match = -1;
optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
break;
}
/*
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1)
continue;
if (match == -1) /* partial match */
match = i;
else {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return (BADCH);
}
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
warnx(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return (BADARG);
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR)
warnx(recargstring,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return (BADARG);
}
} else { /* unknown option */
if (short_too) {
--optind;
return (-1);
}
if (PRINT_ERROR)
warnx(illoptstring, current_argv);
optopt = 0;
return (BADCH);
}
if (idx)
*idx = match;
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
return (0);
} else
return (long_options[match].val);
}
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
*/
static int
getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
{
char *oli; /* option letter list index */
int optchar, short_too;
static int posixly_correct = -1;
if (options == NULL)
return (-1);
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
optind = optreset = 1;
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*/
if (posixly_correct == -1 || optreset)
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
if (*options == '-')
flags |= FLAG_ALLARGS;
else if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
if (*options == '+' || *options == '-')
options++;
optarg = NULL;
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
if (*(place = nargv[optind]) != '-' ||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return (INORDER);
}
if (!(flags & FLAG_PERMUTE)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1);
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++;
place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
}
/*
* Check long options if:
* 1) we were passed some
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
if (*place == '-')
place++; /* --foo long option */
else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
idx, short_too);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
if ((optchar = (int)*place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') ||
(oli = strchr(options, optchar)) == NULL) {
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0')
return (-1);
if (!*place)
++optind;
if (PRINT_ERROR)
warnx(illoptchar, optchar);
optopt = optchar;
return (BADCH);
}
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */
if (*place) /* no space */
/* NOTHING */;
else if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else /* white space */
place = nargv[optind];
optchar = parse_long_options(nargv, options, long_options,
idx, 0);
place = EMSG;
return (optchar);
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = place;
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return (optchar);
}
/*
* getopt --
* Parse argc/argv argument vector.
*
* [eventually this will replace the BSD getopt]
*/
int
getopt(int nargc, char * const *nargv, const char *options)
{
/*
* We don't pass FLAG_PERMUTE to getopt_internal() since
* the BSD getopt(3) (unlike GNU) has never done this.
*
* Furthermore, since many privileged programs call getopt()
* before dropping privileges it makes sense to keep things
* as simple (and bug-free) as possible.
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
}
#if 0
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE));
}
/*
* getopt_long_only --
* Parse argc/argv argument vector.
*/
int
getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE|FLAG_LONGONLY));
}
#endif
#endif /* !defined(HAVE_GETOPT) */

124
openbsd-compat/hkdf.c Normal file
View File

@ -0,0 +1,124 @@
/* $OpenBSD: hkdf.c,v 1.4 2019/11/21 20:02:20 tim Exp $ */
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or 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 "openbsd-compat.h"
#include "fido.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include <assert.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/hmac.h>
#define CRYPTOerror(r) CRYPTOerr(ERR_LIB_CRYPTO, (r))
/* https://tools.ietf.org/html/rfc5869#section-2 */
int
HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest,
const uint8_t *secret, size_t secret_len, const uint8_t *salt,
size_t salt_len, const uint8_t *info, size_t info_len)
{
uint8_t prk[EVP_MAX_MD_SIZE];
size_t prk_len;
if (!HKDF_extract(prk, &prk_len, digest, secret, secret_len, salt,
salt_len))
return 0;
if (!HKDF_expand(out_key, out_len, digest, prk, prk_len, info,
info_len))
return 0;
return 1;
}
/* https://tools.ietf.org/html/rfc5869#section-2.2 */
int
HKDF_extract(uint8_t *out_key, size_t *out_len,
const EVP_MD *digest, const uint8_t *secret, size_t secret_len,
const uint8_t *salt, size_t salt_len)
{
unsigned int len;
/*
* If salt is not given, HashLength zeros are used. However, HMAC does
* that internally already so we can ignore it.
*/
if (salt_len > INT_MAX || HMAC(digest, salt, (int)salt_len, secret,
secret_len, out_key, &len) == NULL) {
CRYPTOerror(ERR_R_CRYPTO_LIB);
return 0;
}
*out_len = len;
return 1;
}
/* https://tools.ietf.org/html/rfc5869#section-2.3 */
int
HKDF_expand(uint8_t *out_key, size_t out_len,
const EVP_MD *digest, const uint8_t *prk, size_t prk_len,
const uint8_t *info, size_t info_len)
{
const size_t digest_len = EVP_MD_size(digest);
uint8_t previous[EVP_MAX_MD_SIZE];
size_t n, done = 0;
unsigned int i;
int ret = 0;
HMAC_CTX hmac;
/* Expand key material to desired length. */
n = (out_len + digest_len - 1) / digest_len;
if (out_len + digest_len < out_len || n > 255 || prk_len > INT_MAX) {
CRYPTOerror(EVP_R_TOO_LARGE);
return 0;
}
HMAC_CTX_init(&hmac);
if (!HMAC_Init_ex(&hmac, prk, (int)prk_len, digest, NULL))
goto out;
for (i = 0; i < n; i++) {
uint8_t ctr = i + 1;
size_t todo;
if (i != 0 && (!HMAC_Init_ex(&hmac, NULL, 0, NULL, NULL) ||
!HMAC_Update(&hmac, previous, digest_len)))
goto out;
if (!HMAC_Update(&hmac, info, info_len) ||
!HMAC_Update(&hmac, &ctr, 1) ||
!HMAC_Final(&hmac, previous, NULL))
goto out;
todo = digest_len;
if (done + todo > out_len)
todo = out_len - done;
memcpy(out_key + done, previous, todo);
done += todo;
}
ret = 1;
out:
HMAC_CTX_cleanup(&hmac);
explicit_bzero(previous, sizeof(previous));
if (ret != 1)
CRYPTOerror(ERR_R_CRYPTO_LIB);
return ret;
}
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */

65
openbsd-compat/hkdf.h Normal file
View File

@ -0,0 +1,65 @@
/* $OpenBSD: hkdf.h,v 1.2 2018/04/03 13:33:53 tb Exp $ */
/* Copyright (c) 2014, Google Inc.
*
* Permission to use, copy, modify, and/or 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. */
#ifndef OPENSSL_HEADER_HKDF_H
#define OPENSSL_HEADER_HKDF_H
#include <openssl/evp.h>
#if defined(__cplusplus)
extern "C" {
#endif
/*
* HKDF computes HKDF (as specified by RFC 5869) of initial keying
* material |secret| with |salt| and |info| using |digest|, and
* outputs |out_len| bytes to |out_key|. It returns one on success and
* zero on error.
*
* HKDF is an Extract-and-Expand algorithm. It does not do any key
* stretching, and as such, is not suited to be used alone to generate
* a key from a password.
*/
int HKDF(uint8_t *out_key, size_t out_len, const struct env_md_st *digest,
const uint8_t *secret, size_t secret_len, const uint8_t *salt,
size_t salt_len, const uint8_t *info, size_t info_len);
/*
* HKDF_extract computes a HKDF PRK (as specified by RFC 5869) from
* initial keying material |secret| and salt |salt| using |digest|,
* and outputs |out_len| bytes to |out_key|. The maximum output size
* is |EVP_MAX_MD_SIZE|. It returns one on success and zero on error.
*/
int HKDF_extract(uint8_t *out_key, size_t *out_len,
const struct env_md_st *digest, const uint8_t *secret,
size_t secret_len, const uint8_t *salt, size_t salt_len);
/*
* HKDF_expand computes a HKDF OKM (as specified by RFC 5869) of
* length |out_len| from the PRK |prk| and info |info| using |digest|,
* and outputs the result to |out_key|. It returns one on success and
* zero on error.
*/
int HKDF_expand(uint8_t *out_key, size_t out_len,
const EVP_MD *digest, const uint8_t *prk, size_t prk_len,
const uint8_t *info, size_t info_len);
#if defined(__cplusplus)
} /* extern C */
#endif
#endif /* OPENSSL_HEADER_HKDF_H */

View File

@ -0,0 +1,119 @@
/*
* 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.
*/
#ifndef _OPENBSD_COMPAT_H
#define _OPENBSD_COMPAT_H
#if defined(_MSC_VER)
#include "types.h"
#endif
#if defined(HAVE_ENDIAN_H)
#include <endian.h>
#endif
#if defined(__APPLE__) && !defined(HAVE_ENDIAN_H)
#include <libkern/OSByteOrder.h>
#define be16toh(x) OSSwapBigToHostInt16((x))
#define htobe16(x) OSSwapHostToBigInt16((x))
#define be32toh(x) OSSwapBigToHostInt32((x))
#define htole32(x) OSSwapHostToLittleInt32((x))
#define htole64(x) OSSwapHostToLittleInt64((x))
#endif /* __APPLE__ && !HAVE_ENDIAN_H */
#if defined(_WIN32) && !defined(HAVE_ENDIAN_H)
#include <stdint.h>
#include <winsock2.h>
#if !defined(_MSC_VER)
#include <sys/param.h>
#endif
#define be16toh(x) ntohs((x))
#define htobe16(x) htons((x))
#define be32toh(x) ntohl((x))
uint32_t htole32(uint32_t);
uint64_t htole64(uint64_t);
#endif /* _WIN32 && !HAVE_ENDIAN_H */
#if defined(__FreeBSD__) && !defined(HAVE_ENDIAN_H)
#include <sys/endian.h>
#endif
#include <stdlib.h>
#include <string.h>
#if !defined(HAVE_STRLCAT)
size_t strlcat(char *, const char *, size_t);
#endif
#if !defined(HAVE_STRLCPY)
size_t strlcpy(char *, const char *, size_t);
#endif
#if !defined(HAVE_RECALLOCARRAY)
void *recallocarray(void *, size_t, size_t, size_t);
#endif
#if !defined(HAVE_EXPLICIT_BZERO)
void explicit_bzero(void *, size_t);
#endif
#if !defined(HAVE_FREEZERO)
void freezero(void *, size_t);
#endif
#if !defined(HAVE_GETPAGESIZE)
int getpagesize(void);
#endif
#if !defined(HAVE_TIMINGSAFE_BCMP)
int timingsafe_bcmp(const void *, const void *, size_t);
#endif
#if !defined(HAVE_READPASSPHRASE)
#include "readpassphrase.h"
#else
#include <readpassphrase.h>
#endif
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include <stdint.h>
#include "hkdf.h"
#define EVP_PKEY_get0_EC_KEY(x) ((x)->pkey.ec)
#define EVP_PKEY_get0_RSA(x) ((x)->pkey.rsa)
#endif
#if !defined(HAVE_ERR_H)
#include "err.h"
#else
#include <err.h>
#endif
#if !defined(HAVE_GETOPT)
#include "getopt.h"
#else
#include <unistd.h>
#endif
#if !defined(HAVE_GETLINE)
#include <stdio.h>
ssize_t getline(char **, size_t *, FILE *);
#endif
#if defined(_MSC_VER)
#define strerror_r(e, b, l) strerror_s((b), (l), (e))
#endif
#include "time.h"
#if !defined(HAVE_POSIX_IOCTL)
#define IOCTL_REQ(x) (x)
#else
#define IOCTL_REQ(x) ((int)(x))
#endif
#endif /* !_OPENBSD_COMPAT_H */

View File

@ -0,0 +1,7 @@
#include <sys/ioctl.h>
int
posix_ioctl_check(int fd)
{
return ioctl(fd, -1, 0);
}

View File

@ -0,0 +1,61 @@
/*
* Public domain
*
* File IO compatibility shims
* Brent Cook <bcook@openbsd.org>
*/
#define NO_REDEF_POSIX_FUNCTIONS
#include <windows.h>
#include <errno.h>
#include <io.h>
#include "posix_win.h"
int
posix_open(const char *path, ...)
{
va_list ap;
int mode = 0;
int flags;
va_start(ap, path);
flags = va_arg(ap, int);
if (flags & O_CREAT)
mode = va_arg(ap, int);
va_end(ap);
flags |= O_BINARY | O_NOINHERIT;
return (open(path, flags, mode));
}
int
posix_close(int fd)
{
return (close(fd));
}
ssize_t
posix_read(int fd, void *buf, size_t count)
{
if (count > INT_MAX) {
errno = EINVAL;
return (-1);
}
return (read(fd, buf, (unsigned int)count));
}
ssize_t
posix_write(int fd, const void *buf, size_t count)
{
if (count > INT_MAX) {
errno = EINVAL;
return (-1);
}
return (write(fd, buf, (unsigned int)count));
}

View File

@ -0,0 +1,47 @@
/*
* Public domain
*
* BSD socket emulation code for Winsock2
* Brent Cook <bcook@openbsd.org>
*/
#ifndef _COMPAT_POSIX_WIN_H
#define _COMPAT_POSIX_WIN_H
#ifdef _WIN32
#include <windows.h>
#include <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if _MSC_VER >= 1900
#include <../ucrt/fcntl.h>
#else
#include <../include/fcntl.h>
#endif
#include "types.h"
int posix_open(const char *path, ...);
int posix_close(int fd);
ssize_t posix_read(int fd, void *buf, size_t count);
ssize_t posix_write(int fd, const void *buf, size_t count);
#ifndef NO_REDEF_POSIX_FUNCTIONS
#define open(path, ...) posix_open(path, __VA_ARGS__)
#define close(fd) posix_close(fd)
#define read(fd, buf, count) posix_read(fd, buf, count)
#define write(fd, buf, count) posix_write(fd, buf, count)
#endif
#endif /* _WIN32 */
#endif /* !_COMPAT_POSIX_WIN_H */

View File

@ -0,0 +1,214 @@
/* $OpenBSD: readpassphrase.c,v 1.26 2016/10/18 12:47:18 millert Exp $ */
/*
* Copyright (c) 2000-2002, 2007, 2010
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* 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.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */
#include "openbsd-compat.h"
#ifndef HAVE_READPASSPHRASE
#include <termios.h>
#include <signal.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <paths.h>
#ifndef _PATH_TTY
# define _PATH_TTY "/dev/tty"
#endif
#ifndef TCSASOFT
/* If we don't have TCSASOFT define it so that ORing it it below is a no-op. */
# define TCSASOFT 0
#endif
/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
#if !defined(_POSIX_VDISABLE) && defined(VDISABLE)
# define _POSIX_VDISABLE VDISABLE
#endif
static volatile sig_atomic_t signo[NSIG];
static void handler(int);
char *
readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
{
ssize_t nr;
int input, output, save_errno, i, need_restart;
char ch, *p, *end;
struct termios term, oterm;
struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
struct sigaction savetstp, savettin, savettou, savepipe;
/* I suppose we could alloc on demand in this case (XXX). */
if (bufsiz == 0) {
errno = EINVAL;
return(NULL);
}
restart:
for (i = 0; i < NSIG; i++)
signo[i] = 0;
need_restart = 0;
/*
* Read and write to /dev/tty if available. If not, read from
* stdin and write to stderr unless a tty is required.
*/
if ((flags & RPP_STDIN) ||
(input = output = open(_PATH_TTY, O_RDWR)) == -1) {
if (flags & RPP_REQUIRE_TTY) {
errno = ENOTTY;
return(NULL);
}
input = STDIN_FILENO;
output = STDERR_FILENO;
}
/*
* Turn off echo if possible.
* If we are using a tty but are not the foreground pgrp this will
* generate SIGTTOU, so do it *before* installing the signal handlers.
*/
if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
memcpy(&term, &oterm, sizeof(term));
if (!(flags & RPP_ECHO_ON))
term.c_lflag &= ~(ECHO | ECHONL);
#ifdef VSTATUS
if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
term.c_cc[VSTATUS] = _POSIX_VDISABLE;
#endif
(void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
} else {
memset(&term, 0, sizeof(term));
term.c_lflag |= ECHO;
memset(&oterm, 0, sizeof(oterm));
oterm.c_lflag |= ECHO;
}
/*
* Catch signals that would otherwise cause the user to end
* up with echo turned off in the shell. Don't worry about
* things like SIGXCPU and SIGVTALRM for now.
*/
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0; /* don't restart system calls */
sa.sa_handler = handler;
(void)sigaction(SIGALRM, &sa, &savealrm);
(void)sigaction(SIGHUP, &sa, &savehup);
(void)sigaction(SIGINT, &sa, &saveint);
(void)sigaction(SIGPIPE, &sa, &savepipe);
(void)sigaction(SIGQUIT, &sa, &savequit);
(void)sigaction(SIGTERM, &sa, &saveterm);
(void)sigaction(SIGTSTP, &sa, &savetstp);
(void)sigaction(SIGTTIN, &sa, &savettin);
(void)sigaction(SIGTTOU, &sa, &savettou);
if (!(flags & RPP_STDIN))
(void)write(output, prompt, strlen(prompt));
end = buf + bufsiz - 1;
p = buf;
while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
if (p < end) {
if ((flags & RPP_SEVENBIT))
ch &= 0x7f;
if (isalpha((unsigned char)ch)) {
if ((flags & RPP_FORCELOWER))
ch = (char)tolower((unsigned char)ch);
if ((flags & RPP_FORCEUPPER))
ch = (char)toupper((unsigned char)ch);
}
*p++ = ch;
}
}
*p = '\0';
save_errno = errno;
if (!(term.c_lflag & ECHO))
(void)write(output, "\n", 1);
/* Restore old terminal settings and signals. */
if (memcmp(&term, &oterm, sizeof(term)) != 0) {
const int sigttou = signo[SIGTTOU];
/* Ignore SIGTTOU generated when we are not the fg pgrp. */
while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&
errno == EINTR && !signo[SIGTTOU])
continue;
signo[SIGTTOU] = sigttou;
}
(void)sigaction(SIGALRM, &savealrm, NULL);
(void)sigaction(SIGHUP, &savehup, NULL);
(void)sigaction(SIGINT, &saveint, NULL);
(void)sigaction(SIGQUIT, &savequit, NULL);
(void)sigaction(SIGPIPE, &savepipe, NULL);
(void)sigaction(SIGTERM, &saveterm, NULL);
(void)sigaction(SIGTSTP, &savetstp, NULL);
(void)sigaction(SIGTTIN, &savettin, NULL);
(void)sigaction(SIGTTOU, &savettou, NULL);
if (input != STDIN_FILENO)
(void)close(input);
/*
* If we were interrupted by a signal, resend it to ourselves
* now that we have restored the signal handlers.
*/
for (i = 0; i < NSIG; i++) {
if (signo[i]) {
kill(getpid(), i);
switch (i) {
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
need_restart = 1;
}
}
}
if (need_restart)
goto restart;
if (save_errno)
errno = save_errno;
return(nr == -1 ? NULL : buf);
}
#if 0
char *
getpass(const char *prompt)
{
static char buf[_PASSWORD_LEN + 1];
return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
}
#endif
static void handler(int s)
{
signo[s] = 1;
}
#endif /* HAVE_READPASSPHRASE */

View File

@ -0,0 +1,44 @@
/* $OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $ */
/*
* Copyright (c) 2000, 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* 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.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/* OPENBSD ORIGINAL: include/readpassphrase.h */
#ifndef _READPASSPHRASE_H_
#define _READPASSPHRASE_H_
#ifndef HAVE_READPASSPHRASE
#include <stdlib.h>
#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */
#define RPP_ECHO_ON 0x01 /* Leave echo on. */
#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */
#define RPP_FORCELOWER 0x04 /* Force input to lower case. */
#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */
#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */
#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */
char * readpassphrase(const char *, char *, size_t, int);
#endif /* HAVE_READPASSPHRASE */
#endif /* !_READPASSPHRASE_H_ */

View File

@ -0,0 +1,131 @@
/*
* Author: Manoj Ampalam <manoj.ampalam@microsoft.com>
*
* Author: Bryan Berns <berns@uwalumni.com>
* Modified group detection use s4u token information
*
* Copyright(c) 2016 Microsoft Corp.
* All rights reserved
*
* Misc Unix POSIX routine implementations for Windows
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
#define UMDF_USING_NTSTATUS
#define SECURITY_WIN32
#include <windows.h>
#include <stdio.h>
#include <time.h>
#include <shlwapi.h>
#include <conio.h>
#include <lm.h>
#include <sddl.h>
#include <aclapi.h>
#include <ntsecapi.h>
#include <security.h>
#include <ntstatus.h>
#include <wchar.h>
#include "openbsd-compat.h"
#ifndef HAVE_READPASSPHRASE
/*on error returns NULL and sets errno*/
static wchar_t *
utf8_to_utf16(const char *utf8)
{
int needed = 0;
wchar_t* utf16 = NULL;
if ((needed = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0)) == 0 ||
(utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, needed) == 0) {
/* debug3("failed to convert utf8 payload:%s error:%d", utf8, GetLastError()); */
errno = ENOMEM;
return NULL;
}
return utf16;
}
char *
readpassphrase(const char *prompt, char *outBuf, size_t outBufLen, int flags)
{
size_t current_index = 0;
char ch;
wchar_t* wtmp = NULL;
if (outBufLen == 0) {
errno = EINVAL;
return NULL;
}
while (_kbhit()) (void)_getch();
wtmp = utf8_to_utf16(prompt);
if (wtmp == NULL)
errx(1, "unable to alloc memory");
_cputws(wtmp);
free(wtmp);
while (current_index < outBufLen - 1) {
ch = (char)_getch();
if (ch == '\r') {
if (_kbhit()) (void)_getch(); /* read linefeed if its there */
break;
} else if (ch == '\n') {
break;
} else if (ch == '\b') { /* backspace */
if (current_index > 0) {
if (flags & RPP_ECHO_ON)
printf_s("%c \b", ch);
current_index--; /* overwrite last character */
}
} else if (ch == '\003') { /* exit on Ctrl+C */
errx(1, "");
} else {
if (flags & RPP_SEVENBIT)
ch &= 0x7f;
if (isalpha((unsigned char)ch)) {
if(flags & RPP_FORCELOWER)
ch = (char)tolower((unsigned char)ch);
if(flags & RPP_FORCEUPPER)
ch = (char)toupper((unsigned char)ch);
}
outBuf[current_index++] = ch;
if(flags & RPP_ECHO_ON)
printf_s("%c", ch);
}
}
outBuf[current_index] = '\0';
_cputs("\n");
return outBuf;
}
#endif /* HAVE_READPASSPHRASE */

Some files were not shown because too many files have changed in this diff Show More