Vendor import of libfido2 1.11.0

This commit is contained in:
Ed Maste 2023-04-26 12:39:46 -04:00
parent 3a9b77fea2
commit cd0b1b947d
72 changed files with 3466 additions and 990 deletions

View file

@ -1,4 +1,4 @@
# Copyright (c) 2018-2021 Yubico AB. All rights reserved.
# Copyright (c) 2018-2022 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
@ -28,18 +28,19 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_COLOR_MAKEFILE OFF)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(FIDO_MAJOR "1")
set(FIDO_MINOR "10")
set(FIDO_MINOR "11")
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_SHARED_LIBS "Build a shared library" ON)
option(BUILD_STATIC_LIBS "Build a 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_PCSC "Enable experimental PCSC support" OFF)
option(USE_WINHELLO "Abstract Windows Hello as a FIDO device" ON)
option(NFC_LINUX "Enable NFC support on Linux" ON)
@ -91,6 +92,7 @@ check_include_files(sys/random.h HAVE_SYS_RANDOM_H)
check_include_files(unistd.h HAVE_UNISTD_H)
check_symbol_exists(arc4random_buf stdlib.h HAVE_ARC4RANDOM_BUF)
check_symbol_exists(asprintf stdio.h HAVE_ASPRINTF)
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)
@ -116,6 +118,7 @@ try_compile(HAVE_POSIX_IOCTL
list(APPEND CHECK_VARIABLES
HAVE_ARC4RANDOM_BUF
HAVE_ASPRINTF
HAVE_CBOR_H
HAVE_CLOCK_GETTIME
HAVE_ENDIAN_H
@ -166,8 +169,8 @@ if(MSVC)
"building under msvc")
endif()
set(CBOR_LIBRARIES cbor)
set(ZLIB_LIBRARIES zlib)
set(CRYPTO_LIBRARIES crypto-47)
set(ZLIB_LIBRARIES zlib1)
set(CRYPTO_LIBRARIES crypto-49)
set(MSVC_DISABLED_WARNINGS_LIST
"C4152" # nonstandard extension used: function/data pointer
# conversion in expression;
@ -237,6 +240,17 @@ else()
add_compile_options(-Wno-unused-parameter)
endif()
if(FUZZ)
set(USE_PCSC ON)
add_definitions(-DFIDO_FUZZ)
endif()
# If building with PCSC, look for pcsc-lite.
if(USE_PCSC AND NOT (APPLE OR CYGWIN OR MSYS OR MINGW))
pkg_search_module(PCSC libpcsclite REQUIRED)
set(PCSC_LIBRARIES pcsclite)
endif()
if(USE_HIDAPI)
add_definitions(-DUSE_HIDAPI)
pkg_search_module(HIDAPI hidapi${HIDAPI_SUFFIX} REQUIRED)
@ -244,7 +258,7 @@ else()
endif()
if(NFC_LINUX)
add_definitions(-DNFC_LINUX)
add_definitions(-DUSE_NFC)
endif()
if(WIN32)
@ -285,10 +299,6 @@ else()
add_definitions(-DOPENSSL_API_COMPAT=0x10100000L)
endif()
if(FUZZ)
add_definitions(-DFIDO_FUZZ)
endif()
if(LIBFUZZER)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link")
endif()
@ -309,6 +319,10 @@ elseif(WIN32)
endif()
add_definitions(-DTLS=${TLS})
if(USE_PCSC)
add_definitions(-DUSE_PCSC)
endif()
# export list
if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
CMAKE_C_COMPILER_ID STREQUAL "AppleClang"))
@ -345,16 +359,18 @@ else()
" /def:\"${CMAKE_CURRENT_SOURCE_DIR}/src/export.msvc\"")
endif()
include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${PROJECT_SOURCE_DIR}/src)
include_directories(${CBOR_INCLUDE_DIRS})
include_directories(${CRYPTO_INCLUDE_DIRS})
include_directories(${HIDAPI_INCLUDE_DIRS})
include_directories(${PCSC_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(${PCSC_LIBRARY_DIRS})
link_directories(${UDEV_LIBRARY_DIRS})
link_directories(${ZLIB_LIBRARY_DIRS})
@ -372,9 +388,14 @@ 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_CROSSCOMPILING: ${CMAKE_CROSSCOMPILING}")
message(STATUS "CMAKE_GENERATOR_PLATFORM: ${CMAKE_GENERATOR_PLATFORM}")
message(STATUS "CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}")
message(STATUS "CMAKE_HOST_SYSTEM_PROCESSOR: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
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_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
message(STATUS "CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}")
message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}")
message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}")
@ -392,6 +413,10 @@ if(USE_HIDAPI)
message(STATUS "HIDAPI_LIBRARY_DIRS: ${HIDAPI_LIBRARY_DIRS}")
message(STATUS "HIDAPI_VERSION: ${HIDAPI_VERSION}")
endif()
message(STATUS "PCSC_INCLUDE_DIRS: ${PCSC_INCLUDE_DIRS}")
message(STATUS "PCSC_LIBRARIES: ${PCSC_LIBRARIES}")
message(STATUS "PCSC_LIBRARY_DIRS: ${PCSC_LIBRARY_DIRS}")
message(STATUS "PCSC_VERSION: ${PCSC_VERSION}")
message(STATUS "LIBFUZZER: ${LIBFUZZER}")
message(STATUS "TLS: ${TLS}")
message(STATUS "UDEV_INCLUDE_DIRS: ${UDEV_INCLUDE_DIRS}")
@ -400,10 +425,22 @@ 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_PCSC: ${USE_PCSC}")
message(STATUS "USE_WINHELLO: ${USE_WINHELLO}")
message(STATUS "NFC_LINUX: ${NFC_LINUX}")
if(BUILD_SHARED_LIBS)
set(_FIDO2_LIBRARY fido2_shared)
elseif(BUILD_STATIC_LIBS)
set(_FIDO2_LIBRARY fido2)
else()
message(FATAL_ERROR "Nothing to build (BUILD_*_LIBS=OFF)")
endif()
enable_testing()
subdirs(src)
subdirs(regress)
if(BUILD_EXAMPLES)
subdirs(examples)
endif()
@ -415,10 +452,6 @@ if(BUILD_MANPAGES)
endif()
if(NOT WIN32)
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT FUZZ)
enable_testing()
subdirs(regress)
endif()
if(FUZZ)
subdirs(fuzz)
endif()

11
NEWS
View file

@ -1,3 +1,14 @@
* Version 1.11.0 (2022-05-03)
** Experimental PCSC support; enable with -DUSE_PCSC.
** Improved OpenSSL 3.0 compatibility.
** Use RFC1951 raw deflate to compress CTAP 2.1 largeBlobs.
** winhello: advertise "uv" instead of "clientPin".
** winhello: support hmac-secret in fido_dev_get_assert().
** New API calls:
- fido_cbor_info_maxlargeblob.
** Documentation and reliability fixes.
** Separate build and regress targets.
* Version 1.10.0 (2022-01-17)
** hid_osx: handle devices with paths > 511 bytes; gh#462.
** bio: fix CTAP2 canonical CBOR encoding in fido_bio_dev_enroll_*(); gh#480.

View file

@ -7,7 +7,7 @@ image:https://github.com/yubico/libfido2/workflows/fuzzer/badge.svg["Fuzz Status
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
communicate with a FIDO device over USB or NFC, and to verify attestation and
assertion signatures.
*libfido2* supports the FIDO U2F (CTAP 1) and FIDO2 (CTAP 2) protocols.
@ -23,8 +23,6 @@ file for the full license text.
*libfido2* is known to work on Linux, macOS, Windows, OpenBSD, and FreeBSD.
NFC support is available on Linux and Windows.
=== Documentation
Documentation is available in troff and HTML formats. An
@ -38,19 +36,29 @@ is also available.
* Perl: https://github.com/jacquesg/p5-FIDO-Raw[p5-FIDO-Raw]
* Rust: https://github.com/PvdBerg1998/libfido2[libfido2]
=== Releases
The current release of *libfido2* is 1.11.0. Signed release tarballs are
available at Yubico's
https://developers.yubico.com/libfido2/Releases[release page].
=== Dependencies
*libfido2* depends on https://github.com/pjk/libcbor[libcbor],
https://www.openssl.org[OpenSSL] 1.1 or newer, and https://zlib.net[zlib].
On Linux, libudev
(part of https://www.freedesktop.org/wiki/Software/systemd[systemd]) is also
required.
=== Installation
==== Releases
==== Fedora 35 and 34
The current release of *libfido2* is 1.10.0. Please consult Yubico's
https://developers.yubico.com/libfido2/Releases[release page] for source
and binary releases.
$ sudo dnf install libfido2 libfido2-devel fido2-tools
==== Ubuntu 20.04 (Focal)
==== Ubuntu 22.04 (Jammy) and 20.04 (Focal)
$ sudo apt install libfido2-1
$ sudo apt install libfido2-dev
$ sudo apt install libfido2-doc
$ sudo apt install libfido2-1 libfido2-dev libfido2-doc fido2-tools
Alternatively, newer versions of *libfido2* are available in Yubico's PPA.
Follow the instructions for Ubuntu 18.04 (Bionic) below.
@ -60,33 +68,10 @@ Follow the instructions for Ubuntu 18.04 (Bionic) below.
$ sudo apt install software-properties-common
$ sudo apt-add-repository ppa:yubico/stable
$ sudo apt update
$ sudo apt install libfido2-dev
$ sudo apt install libfido2-1 libfido2-dev libfido2-doc fido2-tools
==== macOS
$ brew install libfido2
Or from source, on UNIX-like systems:
$ cmake -B build
$ 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] 1.1 or newer, 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:
On Linux, you may need to add a udev rule to be able to access the FIDO
device. For example, the udev rule may contain the following:
----
#udev rule for allowing HID access to Yubico devices for FIDO support.
@ -94,3 +79,67 @@ device, or run as root. For example, the udev rule may contain the following:
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", \
MODE="0664", GROUP="plugdev", ATTRS{idVendor}=="1050"
----
==== macOS
$ brew install libfido2
==== Windows
Please consult Yubico's
https://developers.yubico.com/libfido2/Releases[release page] for ARM, ARM64,
Win32, and Win64 artefacts.
=== Building from source
On UNIX-like systems:
$ cmake -B build
$ 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. For complete,
OS-specific build instructions, please refer to the `.actions/`
(Linux, macOS, BSD) and `windows/` directories.
=== Build-time Customisation
*libfido2* supports a number of CMake options. Some of the options require
additional dependencies. Options that are disabled by default are not
officially supported.
[%autowidth.stretch]
|===
|*Option* |*Description* |*Default*
| BUILD_EXAMPLES | Build example programs | ON
| BUILD_MANPAGES | Build man pages | ON
| BUILD_SHARED_LIBS | Build a shared library | ON
| BUILD_STATIC_LIBS | Build a static library | ON
| BUILD_TOOLS | Build auxiliary tools | ON
| FUZZ | Enable fuzzing instrumentation | OFF
| LIBFUZZER | Build libfuzzer harnesses | OFF
| NFC_LINUX | Enable netlink NFC support on Linux | ON
| USE_HIDAPI | Use hidapi as the HID backend | OFF
| USE_PCSC | Enable experimental PCSC support | OFF
| USE_WINHELLO | Abstract Windows Hello as a FIDO device | ON
|===
The USE_HIDAPI option requires https://github.com/libusb/hidapi[hidapi]. The
USE_PCSC option requires https://github.com/LudovicRousseau/PCSC[pcsc-lite] on
Linux.
=== Development
Please use https://github.com/Yubico/libfido2/discussions[GitHub Discussions]
to ask questions and suggest features, and
https://github.com/Yubico/libfido2/pulls[GitHub pull-requests] for code
contributions.
=== Reporting bugs
Please use https://github.com/Yubico/libfido2/issues[GitHub Issues] to report
bugs. To report security issues, please contact security@yubico.com. A PGP
public key can be found at
https://www.yubico.com/support/security-advisories/issue-rating-system/.

View file

@ -13,17 +13,6 @@ 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

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Yubico AB. All rights reserved.
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -182,6 +182,16 @@ print_maxcredidlen(uint64_t maxcredidlen)
printf("maxcredlen: %d\n", (int)maxcredidlen);
}
/*
* Auxiliary function to print the maximum size of an authenticator's
* serialized largeBlob array.
*/
static void
print_maxlargeblob(uint64_t maxlargeblob)
{
printf("maxlargeblob: %d\n", (int)maxlargeblob);
}
/*
* Auxiliary function to print an authenticator's firmware version on stdout.
*/
@ -264,6 +274,9 @@ getinfo(const char *path)
/* print maximum length of a credential ID */
print_maxcredidlen(fido_cbor_info_maxcredidlen(ci));
/* print maximum length of largeBlob array */
print_maxlargeblob(fido_cbor_info_maxlargeblob(ci));
/* print firmware version */
print_fwversion(fido_cbor_info_fwversion(ci));

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Yubico AB. All rights reserved.
* Copyright (c) 2020-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -23,7 +23,7 @@ nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
return (-1);
}
Sleep(rqtp->tv_nsec / 1000000);
Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000));
return (0);
}

View file

@ -29,7 +29,7 @@ setpin(const char *path, const char *pin, const char *oldpin)
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);
errx(1, "fido_dev_set_pin: %s (0x%x)", fido_strerr(r), r);
if ((r = fido_dev_close(dev)) != FIDO_OK)
errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);

View file

@ -61,3 +61,9 @@ add_executable(fuzz_largeblob fuzz_largeblob.c ${COMMON_SOURCES} ${COMPAT_SOURCE
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)
# fuzz_pcsc
add_executable(fuzz_pcsc fuzz_pcsc.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
target_compile_options(fuzz_pcsc PRIVATE ${FUZZ_LDFLAGS})
set_target_properties(fuzz_pcsc PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})
target_link_libraries(fuzz_pcsc fido2_shared)

View file

@ -1,12 +1,16 @@
# Copyright (c) 2019-2021 Yubico AB. All rights reserved.
# Copyright (c) 2019-2022 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
FROM ubuntu:focal
ENV DEBIAN_FRONTEND=noninteractive
ENV CC=clang-14
ENV CXX=clang++-14
RUN apt-get update
RUN apt-get install -y clang-12 cmake git libssl-dev libudev-dev make pkg-config
RUN apt-get install -y zlib1g-dev
RUN git clone --branch v0.9.0 https://github.com/PJK/libcbor
RUN git clone https://github.com/yubico/libfido2
RUN CC=clang-12 CXX=clang++-12 /libfido2/fuzz/build-coverage /libcbor /libfido2
RUN apt-get install -y cmake git libssl-dev libudev-dev make pkg-config
RUN apt-get install -y libpcsclite-dev zlib1g-dev software-properties-common
RUN git clone --branch v0.9.0 --depth=1 https://github.com/PJK/libcbor
RUN git clone --depth=1 https://github.com/yubico/libfido2
WORKDIR /libfido2
RUN ./.actions/setup_clang "${CC}"
RUN ./fuzz/build-coverage /libcbor /libfido2

View file

@ -1,13 +1,13 @@
# Copyright (c) 2019-2021 Yubico AB. All rights reserved.
# Copyright (c) 2019-2022 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
IMAGE := libfido2-coverage:1.10.0
IMAGE := libfido2-coverage:1.11.2
RUNNER := libfido2-runner
PROFDATA := llvm-profdata-12
COV := llvm-cov-12
PROFDATA := llvm-profdata-14
COV := llvm-cov-14
TARGETS := fuzz_assert fuzz_bio fuzz_cred fuzz_credman fuzz_hid \
fuzz_largeblob fuzz_netlink fuzz_mgmt
fuzz_largeblob fuzz_netlink fuzz_mgmt fuzz_pcsc
CORPORA := $(foreach f,${TARGETS},${f}/corpus)
MINIFY := $(foreach f,${TARGETS},/minify/${f}/corpus)
REMOTE := gs://libfido2-corpus.clusterfuzz-external.appspot.com
@ -24,7 +24,7 @@ run: build
sync: run
tar Ccf .. - src fuzz | docker exec -i ${RUNNER} tar Cxf /libfido2 -
docker exec ${RUNNER} make -C libfido2/build
docker exec ${RUNNER} make -C /libfido2/build
corpus: sync
docker exec ${RUNNER} /bin/sh -c 'cd /libfido2/fuzz && rm -rf ${TARGETS}'
@ -45,23 +45,24 @@ corpus.tgz-: ${MINIFY}
profdata: run
docker exec ${RUNNER} /bin/sh -c 'rm -f /$@ && ${PROFDATA} \
merge -sparse profraw/* -o $@'
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=/$< \
--show-branch-summary=false -output-dir=/report \
/libfido2/build/src/libfido2.so'
-ignore-filename-regex=pcsclite.h --show-branch-summary=false \
-output-dir=/report /libfido2/build/src/libfido2.so'
docker exec -i ${RUNNER} tar Czcf / - report > $@
summary.txt: profdata
docker exec ${RUNNER} ${COV} report -use-color=false \
--show-branch-summary=false /libfido2/build/src/libfido2.so \
-instr-profile=/$< > $@
-ignore-filename-regex=pcsclite.h --show-branch-summary=false \
/libfido2/build/src/libfido2.so -instr-profile=/$< > $@
functions.txt: profdata
docker exec ${RUNNER} /bin/sh -c '${COV} report -use-color=false \
-show-functions --show-branch-summary=false -instr-profile=/$< \
-ignore-filename-regex=pcsclite.h -show-functions \
--show-branch-summary=false -instr-profile=/$< \
/libfido2/build/src/libfido2.so /libfido2/src/*.[ch]' > $@
clean: run

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Yubico AB. All rights reserved.
* Copyright (c) 2020-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -18,6 +18,8 @@ const char dummy_rp_name[] = "sweet home localhost";
const char dummy_user_icon[] = "an icon";
const char dummy_user_name[] = "john smith";
const char dummy_user_nick[] = "jsmith";
const char dummy_pcsc_list[] = "reader1\0reader2\0reader3\0\0";
const char dummy_pcsc_path[] = "pcsc://slot7";
const uint8_t dummy_id[] = { 0x5e, 0xd2 };
const uint8_t dummy_user_id[] = {

View file

@ -85,10 +85,11 @@
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_maxlargeblob;
fido_cbor_info_maxmsgsiz;
fido_cbor_info_fwversion;
fido_cbor_info_new;
fido_cbor_info_options_len;
@ -212,6 +213,7 @@
fido_dev_protocol;
fido_dev_reset;
fido_dev_set_io_functions;
fido_dev_set_pcsc;
fido_dev_set_pin;
fido_dev_set_pin_minlen;
fido_dev_set_pin_minlen_rpid;
@ -237,6 +239,13 @@
fido_nl_get_nfc_target;
fido_nl_new;
fido_nl_power_nfc;
fido_pcsc_close;
fido_pcsc_manifest;
fido_pcsc_open;
fido_pcsc_read;
fido_pcsc_rx;
fido_pcsc_tx;
fido_pcsc_write;
fido_set_log_handler;
fido_strerr;
rs256_pk_free;
@ -246,8 +255,11 @@
rs256_pk_new;
rs256_pk_to_EVP_PKEY;
prng_init;
prng_up;
fuzz_clock_reset;
set_netlink_io_functions;
set_pcsc_parameters;
set_pcsc_io_functions;
set_udev_parameters;
uniform_random;
local:

View file

@ -1,16 +1,16 @@
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_cbc_enc 4 0 100.00% 4 0 100.00%
aes256_cbc_dec 4 0 100.00% 4 0 100.00%
aes256_gcm_enc 1 0 100.00% 3 0 100.00%
aes256_gcm_dec 1 0 100.00% 3 0 100.00%
aes256.c:aes256_cbc_fips 26 2 92.31% 42 7 83.33%
aes256.c:aes256_cbc 29 1 96.55% 36 3 91.67%
aes256.c:aes256_cbc_proto1 1 0 100.00% 5 0 100.00%
aes256.c:aes256_gcm 51 1 98.04% 60 4 93.33%
aes256.c:aes256_gcm 52 1 98.08% 60 4 93.33%
--------------------------------------------------------------------------------------------------------
TOTAL 115 4 96.52% 157 14 91.08%
TOTAL 118 4 96.61% 157 14 91.08%
File '/libfido2/src/assert.c':
Name Regions Miss Cover Lines Miss Cover
@ -18,7 +18,7 @@ Name Regions Miss Cover Lines Miss
fido_dev_get_assert 40 0 100.00% 35 0 100.00%
fido_check_flags 13 0 100.00% 15 0 100.00%
fido_get_signed_hash 36 0 100.00% 46 0 100.00%
fido_assert_verify 48 4 91.67% 67 5 92.54%
fido_assert_verify 48 4 91.67% 67 7 89.55%
fido_assert_set_clientdata 12 12 0.00% 11 11 0.00%
fido_assert_set_clientdata_hash 8 0 100.00% 6 0 100.00%
fido_assert_set_hmac_salt 10 0 100.00% 6 0 100.00%
@ -26,7 +26,7 @@ fido_assert_set_hmac_secret 12 12 0.00% 7 7
fido_assert_set_rp 12 0 100.00% 11 0 100.00%
fido_assert_allow_cred 13 2 84.62% 22 3 86.36%
fido_assert_set_extensions 14 0 100.00% 10 0 100.00%
fido_assert_set_options 6 6 0.00% 5 5 0.00%
fido_assert_set_options 8 8 0.00% 5 5 0.00%
fido_assert_set_up 2 0 100.00% 4 0 100.00%
fido_assert_set_uv 2 0 100.00% 4 0 100.00%
fido_assert_clientdata_hash_ptr 1 0 100.00% 3 0 100.00%
@ -72,7 +72,7 @@ assert.c:check_extensions 5 0 100.00% 9 0
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 563 40 92.90% 694 40 94.24%
TOTAL 565 42 92.57% 694 42 93.95%
File '/libfido2/src/authkey.c':
Name Regions Miss Cover Lines Miss Cover
@ -88,10 +88,10 @@ TOTAL 44 0 100.00% 59 0
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_get_template_array 5 2 60.00% 6 1 83.33%
fido_bio_dev_set_template_name 7 0 100.00% 6 0 100.00%
fido_bio_dev_enroll_begin 25 2 92.00% 31 0 100.00%
fido_bio_dev_enroll_continue 5 2 60.00% 6 0 100.00%
fido_bio_dev_enroll_begin 25 2 92.00% 31 1 96.77%
fido_bio_dev_enroll_continue 5 2 60.00% 6 1 83.33%
fido_bio_dev_enroll_cancel 1 1 0.00% 4 4 0.00%
fido_bio_dev_enroll_remove 1 0 100.00% 4 0 100.00%
fido_bio_dev_get_info 1 0 100.00% 4 0 100.00%
@ -138,7 +138,7 @@ bio.c:bio_reset_template_array 4 0 100.00% 7 0
bio.c:bio_reset_template 1 0 100.00% 5 0 100.00%
bio.c:bio_reset_enroll 3 0 100.00% 6 0 100.00%
-----------------------------------------------------------------------------------------------------------------
TOTAL 419 20 95.23% 559 21 96.24%
TOTAL 419 20 95.23% 559 24 95.71%
File '/libfido2/src/blob.c':
Name Regions Miss Cover Lines Miss Cover
@ -187,9 +187,9 @@ cbor_encode_str_array 18 0 100.00% 19 0
cbor_encode_cred_ext 55 0 100.00% 50 0 100.00%
cbor_encode_cred_opt 13 0 100.00% 11 0 100.00%
cbor_encode_assert_opt 13 0 100.00% 11 0 100.00%
cbor_encode_pin_auth 20 1 95.00% 22 3 86.36%
cbor_encode_pin_auth 21 1 95.24% 22 3 86.36%
cbor_encode_pin_opt 4 0 100.00% 8 0 100.00%
cbor_encode_change_pin_auth 31 1 96.77% 36 3 91.67%
cbor_encode_change_pin_auth 32 1 96.88% 36 3 91.67%
cbor_encode_assert_ext 33 0 100.00% 32 0 100.00%
cbor_decode_fmt 13 0 100.00% 15 0 100.00%
cbor_decode_pubkey 21 1 95.24% 30 2 93.33%
@ -200,7 +200,7 @@ cbor_decode_uint64 4 0 100.00% 8 0
cbor_decode_cred_id 8 0 100.00% 9 0 100.00%
cbor_decode_user 8 0 100.00% 9 0 100.00%
cbor_decode_rp_entity 8 0 100.00% 9 0 100.00%
cbor_build_uint 10 1 90.00% 9 2 77.78%
cbor_build_uint 10 1 90.00% 9 1 88.89%
cbor_array_append 17 0 100.00% 21 0 100.00%
cbor_array_drop 18 2 88.89% 17 3 82.35%
cbor.c:ctap_check_cbor 28 0 100.00% 26 0 100.00%
@ -222,16 +222,18 @@ cbor.c:decode_cred_id_entry 10 0 100.00% 19 0
cbor.c:decode_user_entry 25 0 100.00% 35 0 100.00%
cbor.c:decode_rp_entity_entry 15 0 100.00% 25 0 100.00%
------------------------------------------------------------------------------------------------------------------
TOTAL 1047 23 97.80% 1237 46 96.28%
TOTAL 1049 23 97.81% 1237 45 96.36%
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% 22 3 86.36%
fido_uncompress 6 0 100.00% 5 0 100.00%
compress.c:rfc1951_deflate 33 2 93.94% 47 3 93.62%
compress.c:rfc1950_inflate 27 2 92.59% 22 4 81.82%
compress.c:rfc1951_inflate 38 10 73.68% 45 17 62.22%
------------------------------------------------------------------------------------------------------------------
TOTAL 34 4 88.24% 28 3 89.29%
TOTAL 105 14 86.67% 122 24 80.33%
File '/libfido2/src/config.c':
Name Regions Miss Cover Lines Miss Cover
@ -255,8 +257,8 @@ Name Regions Miss Cover Lines Mis
-------------------------------------------------------------------------------------------------------------------
fido_dev_make_cred 12 0 100.00% 10 0 100.00%
fido_check_rp_id 4 0 100.00% 11 0 100.00%
fido_cred_verify 56 2 96.43% 72 5 93.06%
fido_cred_verify_self 58 4 93.10% 83 5 93.98%
fido_cred_verify 56 2 96.43% 72 4 94.44%
fido_cred_verify_self 58 4 93.10% 83 7 91.57%
fido_cred_new 1 0 100.00% 3 0 100.00%
fido_cred_reset_tx 1 0 100.00% 19 0 100.00%
fido_cred_reset_rx 1 0 100.00% 7 0 100.00%
@ -273,13 +275,13 @@ fido_cred_set_clientdata_hash 8 0 100.00% 6
fido_cred_set_rp 18 0 100.00% 22 0 100.00%
fido_cred_set_user 32 0 100.00% 41 0 100.00%
fido_cred_set_extensions 16 0 100.00% 10 0 100.00%
fido_cred_set_options 6 6 0.00% 5 5 0.00%
fido_cred_set_options 8 8 0.00% 5 5 0.00%
fido_cred_set_rk 2 0 100.00% 4 0 100.00%
fido_cred_set_uv 2 0 100.00% 4 0 100.00%
fido_cred_set_prot 21 0 100.00% 14 0 100.00%
fido_cred_set_pin_minlen 7 0 100.00% 8 0 100.00%
fido_cred_set_blob 13 2 84.62% 8 1 87.50%
fido_cred_set_fmt 20 4 80.00% 12 1 91.67%
fido_cred_set_fmt 20 4 80.00% 12 2 83.33%
fido_cred_set_type 17 0 100.00% 7 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%
@ -319,11 +321,11 @@ cred.c:fido_dev_make_cred_rx 29 0 100.00% 32
cred.c:parse_makecred_reply 14 0 100.00% 27 0 100.00%
cred.c:check_extensions 2 0 100.00% 6 0 100.00%
cred.c:get_signed_hash_u2f 27 0 100.00% 26 0 100.00%
cred.c:verify_attstmt 23 2 91.30% 40 5 87.50%
cred.c:verify_attstmt 23 2 91.30% 40 6 85.00%
cred.c:fido_cred_clean_authdata 1 0 100.00% 8 0 100.00%
cred.c:fido_cred_clean_attstmt 1 0 100.00% 8 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 632 34 94.62% 830 36 95.66%
TOTAL 634 36 94.32% 830 39 95.30%
File '/libfido2/src/credman.c':
Name Regions Miss Cover Lines Miss Cover
@ -334,15 +336,15 @@ fido_credman_del_dev_rk 1 0 100.00% 4
fido_credman_get_dev_rp 1 0 100.00% 4 0 100.00%
fido_credman_set_dev_rk 1 0 100.00% 4 0 100.00%
fido_credman_rk_new 1 0 100.00% 3 0 100.00%
fido_credman_rk_free 6 1 83.33% 8 0 100.00%
fido_credman_rk_free 6 1 83.33% 8 1 87.50%
fido_credman_rk_count 1 0 100.00% 3 0 100.00%
fido_credman_rk 4 0 100.00% 5 0 100.00%
fido_credman_metadata_new 1 0 100.00% 3 0 100.00%
fido_credman_metadata_free 6 1 83.33% 7 0 100.00%
fido_credman_metadata_free 6 1 83.33% 7 1 85.71%
fido_credman_rk_existing 1 0 100.00% 3 0 100.00%
fido_credman_rk_remaining 1 0 100.00% 3 0 100.00%
fido_credman_rp_new 1 0 100.00% 3 0 100.00%
fido_credman_rp_free 6 1 83.33% 8 0 100.00%
fido_credman_rp_free 6 1 83.33% 8 1 87.50%
fido_credman_rp_count 1 0 100.00% 3 0 100.00%
fido_credman_rp_id 4 0 100.00% 5 0 100.00%
fido_credman_rp_name 4 0 100.00% 5 0 100.00%
@ -369,21 +371,17 @@ credman.c:credman_set_dev_rk_wait 11 0 100.00% 8
credman.c:credman_reset_rk 4 0 100.00% 9 0 100.00%
credman.c:credman_reset_rp 4 0 100.00% 12 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 382 10 97.38% 518 15 97.10%
TOTAL 382 10 97.38% 518 18 96.53%
File '/libfido2/src/dev.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
fido_dev_register_manifest_func 10 2 80.00% 14 3 78.57%
fido_dev_unregister_manifest_func 7 7 0.00% 11 11 0.00%
fido_dev_info_manifest 22 4 81.82% 24 0 100.00%
fido_dev_info_manifest 2 0 100.00% 11 0 100.00%
fido_dev_open_with_info 5 5 0.00% 6 6 0.00%
fido_dev_open 5 1 80.00% 19 12 36.84%
fido_dev_close 9 2 77.78% 8 0 100.00%
fido_dev_open 13 6 53.85% 16 6 62.50%
fido_dev_close 9 2 77.78% 8 1 87.50%
fido_dev_set_sigmask 18 18 0.00% 11 11 0.00%
fido_dev_cancel 11 0 100.00% 8 0 100.00%
fido_dev_get_touch_begin 50 0 100.00% 59 0 100.00%
fido_dev_get_touch_status 17 0 100.00% 20 0 100.00%
fido_dev_set_io_functions 18 4 77.78% 14 6 57.14%
fido_dev_set_transport_functions 6 2 66.67% 9 3 66.67%
fido_dev_io_handle 1 1 0.00% 3 3 0.00%
@ -410,17 +408,17 @@ fido_dev_force_fido2 2 2 0.00% 3
fido_dev_get_pin_protocol 11 0 100.00% 7 0 100.00%
fido_dev_maxmsgsize 1 0 100.00% 3 0 100.00%
fido_dev_set_timeout 6 2 66.67% 6 1 83.33%
dev.c:find_manifest_func_node 5 0 100.00% 8 0 100.00%
dev.c:run_manifest 10 0 100.00% 13 0 100.00%
dev.c:fido_dev_open_wait 10 0 100.00% 7 0 100.00%
dev.c:fido_dev_open_tx 56 15 73.21% 56 26 53.57%
dev.c:set_random_report_len 11 0 100.00% 6 0 100.00%
dev.c:fido_dev_open_rx 36 1 97.22% 53 1 98.11%
dev.c:fido_dev_set_flags 1 0 100.00% 5 0 100.00%
dev.c:fido_dev_set_extension_flags 7 0 100.00% 7 0 100.00%
dev.c:fido_dev_set_option_flags 29 0 100.00% 18 0 100.00%
dev.c:fido_dev_set_option_flags 31 0 100.00% 20 0 100.00%
dev.c:fido_dev_set_protocol_flags 11 0 100.00% 17 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 421 79 81.24% 491 105 78.62%
TOTAL 332 71 78.61% 378 86 77.25%
File '/libfido2/src/ecdh.c':
Name Regions Miss Cover Lines Miss Cover
@ -438,15 +436,15 @@ Name Regions Miss Cover Lines Mis
eddsa_pk_decode 8 0 100.00% 9 0 100.00%
eddsa_pk_new 1 0 100.00% 3 0 100.00%
eddsa_pk_free 6 0 100.00% 7 0 100.00%
eddsa_pk_from_ptr 6 0 100.00% 6 0 100.00%
eddsa_pk_from_ptr 10 0 100.00% 12 0 100.00%
eddsa_pk_to_EVP_PKEY 3 0 100.00% 7 0 100.00%
eddsa_pk_from_EVP_PKEY 14 0 100.00% 10 0 100.00%
eddsa_pk_from_EVP_PKEY 18 2 88.89% 12 1 91.67%
eddsa_verify_sig 19 2 89.47% 30 6 80.00%
eddsa_pk_verify_sig 7 1 85.71% 13 2 84.62%
eddsa.c:decode_pubkey_point 8 0 100.00% 11 0 100.00%
eddsa.c:decode_coord 8 0 100.00% 10 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 80 3 96.25% 106 8 92.45%
TOTAL 88 5 94.32% 114 9 92.11%
File '/libfido2/src/err.c':
Name Regions Miss Cover Lines Miss Cover
@ -464,21 +462,21 @@ es256_sk_new 1 0 100.00% 3
es256_sk_free 6 0 100.00% 7 0 100.00%
es256_pk_new 1 0 100.00% 3 0 100.00%
es256_pk_free 6 0 100.00% 7 0 100.00%
es256_pk_from_ptr 11 0 100.00% 10 0 100.00%
es256_pk_from_ptr 15 0 100.00% 17 0 100.00%
es256_pk_set_x 1 0 100.00% 4 0 100.00%
es256_pk_set_y 1 0 100.00% 4 0 100.00%
es256_sk_create 39 0 100.00% 41 0 100.00%
es256_pk_to_EVP_PKEY 42 0 100.00% 54 0 100.00%
es256_pk_from_EC_KEY 38 0 100.00% 36 0 100.00%
es256_pk_from_EVP_PKEY 7 2 71.43% 7 0 100.00%
es256_sk_to_EVP_PKEY 28 0 100.00% 40 0 100.00%
es256_derive_pk 25 0 100.00% 30 0 100.00%
es256_sk_create 39 0 100.00% 40 0 100.00%
es256_pk_to_EVP_PKEY 42 0 100.00% 53 0 100.00%
es256_pk_from_EC_KEY 42 2 95.24% 47 4 91.49%
es256_pk_from_EVP_PKEY 8 2 75.00% 7 1 85.71%
es256_sk_to_EVP_PKEY 28 0 100.00% 39 0 100.00%
es256_derive_pk 25 0 100.00% 29 0 100.00%
es256_verify_sig 12 2 83.33% 19 5 73.68%
es256_pk_verify_sig 7 1 85.71% 13 2 84.62%
es256.c:decode_pubkey_point 9 0 100.00% 13 0 100.00%
es256.c:decode_coord 8 0 100.00% 10 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 306 5 98.37% 358 7 98.04%
TOTAL 315 7 97.78% 372 12 96.77%
File '/libfido2/src/extern.h':
Name Regions Miss Cover Lines Miss Cover
@ -511,7 +509,7 @@ TOTAL 87 2 97.70% 145
File '/libfido2/src/hid_linux.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
fido_hid_manifest 35 4 88.57% 41 1 97.56%
fido_hid_manifest 35 4 88.57% 41 2 95.12%
fido_hid_open 27 27 0.00% 40 40 0.00%
fido_hid_close 3 3 0.00% 6 6 0.00%
fido_hid_set_sigmask 2 2 0.00% 6 6 0.00%
@ -526,15 +524,15 @@ hid_linux.c:parse_uevent 12 0 100.00% 24
hid_linux.c:get_usb_attr 1 0 100.00% 3 0 100.00%
hid_linux.c:get_report_descriptor 14 1 92.86% 17 3 82.35%
-------------------------------------------------------------------------------------------------------------------
TOTAL 173 68 60.69% 250 104 58.40%
TOTAL 173 68 60.69% 250 105 58.00%
File '/libfido2/src/hid_unix.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
fido_hid_unix_open 18 11 38.89% 22 14 36.36%
fido_hid_unix_wait 10 9 10.00% 21 10 52.38%
fido_hid_unix_wait 11 10 9.09% 21 12 42.86%
-------------------------------------------------------------------------------------------------------------------
TOTAL 28 20 28.57% 43 24 44.19%
TOTAL 29 21 27.59% 43 26 39.53%
File '/libfido2/src/info.c':
Name Regions Miss Cover Lines Miss Cover
@ -559,6 +557,7 @@ fido_cbor_info_maxcredbloblen 1 0 100.00% 3
fido_cbor_info_maxmsgsiz 1 0 100.00% 3 0 100.00%
fido_cbor_info_maxcredcntlst 1 0 100.00% 3 0 100.00%
fido_cbor_info_maxcredidlen 1 0 100.00% 3 0 100.00%
fido_cbor_info_maxlargeblob 1 0 100.00% 3 0 100.00%
fido_cbor_info_fwversion 1 0 100.00% 3 0 100.00%
fido_cbor_info_protocols_ptr 1 0 100.00% 3 0 100.00%
fido_cbor_info_protocols_len 1 0 100.00% 3 0 100.00%
@ -567,7 +566,7 @@ fido_cbor_info_algorithm_type 4 0 100.00% 5
fido_cbor_info_algorithm_cose 4 0 100.00% 5 0 100.00%
info.c:fido_dev_get_cbor_info_tx 8 0 100.00% 9 0 100.00%
info.c:fido_dev_get_cbor_info_rx 6 0 100.00% 14 0 100.00%
info.c:parse_reply_element 19 0 100.00% 37 0 100.00%
info.c:parse_reply_element 20 0 100.00% 39 0 100.00%
info.c:decode_string_array 12 0 100.00% 17 0 100.00%
info.c:decode_string 4 0 100.00% 10 0 100.00%
info.c:decode_aaguid 8 0 100.00% 10 0 100.00%
@ -579,37 +578,37 @@ info.c:decode_algorithms 12 0 100.00% 17
info.c:decode_algorithm 9 0 100.00% 17 0 100.00%
info.c:decode_algorithm_entry 20 0 100.00% 27 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 184 0 100.00% 316 0 100.00%
TOTAL 186 0 100.00% 321 0 100.00%
File '/libfido2/src/io.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
fido_tx 13 0 100.00% 11 0 100.00%
fido_tx 14 0 100.00% 11 0 100.00%
fido_rx 13 1 92.31% 14 3 78.57%
fido_rx_cbor_status 8 0 100.00% 10 0 100.00%
io.c:transport_tx 7 0 100.00% 10 0 100.00%
io.c:tx_empty 9 0 100.00% 14 0 100.00%
io.c:tx_pkt 7 0 100.00% 10 0 100.00%
io.c:tx 13 0 100.00% 19 0 100.00%
io.c:tx_preamble 16 1 93.75% 20 1 95.00%
io.c:tx_frame 15 1 93.33% 18 1 94.44%
io.c:tx_preamble 17 1 94.12% 20 1 95.00%
io.c:tx_frame 16 1 93.75% 18 1 94.44%
io.c:transport_rx 7 0 100.00% 10 0 100.00%
io.c:rx 40 2 95.00% 52 1 98.08%
io.c:rx 40 2 95.00% 52 2 96.15%
io.c:rx_preamble 23 2 91.30% 22 5 77.27%
io.c:rx_frame 11 0 100.00% 11 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 182 7 96.15% 221 11 95.02%
TOTAL 185 7 96.22% 221 12 94.57%
File '/libfido2/src/iso7816.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
iso7816_new 4 0 100.00% 16 0 100.00%
iso7816_free 6 0 100.00% 7 0 100.00%
iso7816_add 6 1 83.33% 8 0 100.00%
iso7816_add 6 1 83.33% 8 1 87.50%
iso7816_ptr 1 0 100.00% 3 0 100.00%
iso7816_len 1 0 100.00% 4 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 18 1 94.44% 38 0 100.00%
TOTAL 18 1 94.44% 38 1 97.37%
File '/libfido2/src/largeblob.c':
Name Regions Miss Cover Lines Miss Cover
@ -620,7 +619,7 @@ fido_dev_largeblob_remove 12 0 100.00% 18
fido_dev_largeblob_get_array 15 2 86.67% 27 4 85.19%
fido_dev_largeblob_set_array 14 0 100.00% 19 0 100.00%
largeblob.c:largeblob_get_array 32 0 100.00% 36 0 100.00%
largeblob.c:get_chunklen 9 1 88.89% 9 0 100.00%
largeblob.c:get_chunklen 10 1 90.00% 9 1 88.89%
largeblob.c:largeblob_get_tx 19 0 100.00% 24 0 100.00%
largeblob.c:largeblob_get_rx 15 0 100.00% 21 0 100.00%
largeblob.c:parse_largeblob_reply 8 0 100.00% 9 0 100.00%
@ -629,7 +628,7 @@ largeblob.c:largeblob_array_digest 10 0 100.00% 9
largeblob.c:largeblob_array_load 14 2 85.71% 19 7 63.16%
largeblob.c:largeblob_array_lookup 25 0 100.00% 33 0 100.00%
largeblob.c:largeblob_decode 16 2 87.50% 16 6 62.50%
largeblob.c:largeblob_do_decode 27 3 88.89% 30 5 83.33%
largeblob.c:largeblob_do_decode 27 3 88.89% 30 7 76.67%
largeblob.c:largeblob_decrypt 15 0 100.00% 24 0 100.00%
largeblob.c:largeblob_aad 1 0 100.00% 10 0 100.00%
largeblob.c:largeblob_reset 1 0 100.00% 5 0 100.00%
@ -645,34 +644,34 @@ largeblob.c:largeblob_get_uv_token 19 0 100.00% 23
largeblob.c:largeblob_set_tx 35 0 100.00% 36 0 100.00%
largeblob.c:prepare_hmac 13 2 84.62% 23 7 69.57%
-------------------------------------------------------------------------------------------------------------------
TOTAL 513 19 96.30% 684 43 93.71%
TOTAL 514 19 96.30% 684 46 93.27%
File '/libfido2/src/log.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
fido_log_init 1 0 100.00% 4 0 100.00%
fido_log_debug 6 1 83.33% 8 0 100.00%
fido_log_xxd 16 1 93.75% 24 0 100.00%
fido_log_error 8 2 75.00% 11 1 90.91%
fido_log_debug 6 1 83.33% 8 1 87.50%
fido_log_xxd 16 1 93.75% 24 1 95.83%
fido_log_error 8 2 75.00% 11 2 81.82%
fido_set_log_handler 3 0 100.00% 4 0 100.00%
log.c:log_on_stderr 1 1 0.00% 3 3 0.00%
log.c:do_log 4 0 100.00% 9 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 39 5 87.18% 63 4 93.65%
TOTAL 39 5 87.18% 63 7 88.89%
File '/libfido2/src/netlink.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
fido_nl_power_nfc 18 1 94.44% 24 3 87.50%
fido_nl_get_nfc_target 17 1 94.12% 31 3 90.32%
fido_nl_free 10 2 80.00% 9 1 88.89%
fido_nl_free 10 2 80.00% 9 2 77.78%
fido_nl_new 16 1 93.75% 26 3 88.46%
set_netlink_io_functions 1 0 100.00% 4 0 100.00%
netlink.c:nlmsg_new 8 0 100.00% 15 0 100.00%
netlink.c:nlmsg_set_genl 1 0 100.00% 7 0 100.00%
netlink.c:nlmsg_write 6 1 83.33% 7 1 85.71%
netlink.c:nlmsg_set_u32 1 0 100.00% 3 0 100.00%
netlink.c:nlmsg_setattr 14 1 92.86% 17 0 100.00%
netlink.c:nlmsg_setattr 15 1 93.33% 17 0 100.00%
netlink.c:nlmsg_tx 10 1 90.00% 13 3 76.92%
netlink.c:nlmsg_ptr 1 0 100.00% 3 0 100.00%
netlink.c:nlmsg_len 1 0 100.00% 3 0 100.00%
@ -704,36 +703,62 @@ netlink.c:parse_mcastgrps 1 0 100.00% 3
netlink.c:parse_mcastgrp 15 0 100.00% 24 0 100.00%
netlink.c:nla_get_str 10 0 100.00% 11 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 328 14 95.73% 498 32 93.57%
TOTAL 329 14 95.74% 498 33 93.37%
File '/libfido2/src/nfc.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
fido_nfc_tx 28 0 100.00% 43 0 100.00%
fido_nfc_rx 8 0 100.00% 13 0 100.00%
fido_is_nfc 3 0 100.00% 3 0 100.00%
fido_dev_set_nfc 4 4 0.00% 18 18 0.00%
nfc.c:nfc_do_tx 20 0 100.00% 25 0 100.00%
nfc.c:tx_short_apdu 14 0 100.00% 32 0 100.00%
nfc.c:rx_init 25 0 100.00% 27 0 100.00%
nfc.c:rx_cbor 4 0 100.00% 6 0 100.00%
nfc.c:rx_msg 18 2 88.89% 23 6 73.91%
nfc.c:rx_apdu 14 1 92.86% 22 3 86.36%
nfc.c:tx_get_response 4 0 100.00% 11 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 142 7 95.07% 223 27 87.89%
File '/libfido2/src/nfc_linux.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
fido_nfc_tx 28 0 100.00% 43 0 100.00%
fido_nfc_rx 8 1 87.50% 13 3 76.92%
fido_nfc_manifest 35 5 85.71% 45 13 71.11%
fido_nfc_open 20 3 85.00% 23 5 78.26%
fido_nfc_manifest 35 7 80.00% 45 15 66.67%
fido_nfc_open 20 3 85.00% 23 4 82.61%
fido_nfc_close 1 1 0.00% 4 4 0.00%
fido_nfc_set_sigmask 2 2 0.00% 6 6 0.00%
fido_nfc_read 14 14 0.00% 30 30 0.00%
fido_nfc_write 12 12 0.00% 18 18 0.00%
nfc_linux.c:nfc_do_tx 20 2 90.00% 25 6 76.00%
nfc_linux.c:tx_short_apdu 14 0 100.00% 32 0 100.00%
nfc_linux.c:rx_init 25 6 76.00% 27 5 81.48%
nfc_linux.c:rx_cbor 4 0 100.00% 6 0 100.00%
nfc_linux.c:rx_msg 18 2 88.89% 23 6 73.91%
nfc_linux.c:rx_apdu 14 1 92.86% 22 3 86.36%
nfc_linux.c:tx_get_response 4 0 100.00% 11 0 100.00%
nfc_linux.c:copy_info 41 9 78.05% 44 3 93.18%
nfc_linux.c:copy_info 41 8 80.49% 47 5 89.36%
nfc_linux.c:get_usb_attr 1 0 100.00% 3 0 100.00%
nfc_linux.c:get_parent_attr 6 0 100.00% 9 0 100.00%
nfc_linux.c:to_int 21 6 71.43% 14 1 92.86%
nfc_linux.c:sysnum_from_syspath 12 0 100.00% 17 0 100.00%
nfc_linux.c:sysnum_from_syspath 15 0 100.00% 17 0 100.00%
nfc_linux.c:nfc_new 6 0 100.00% 11 0 100.00%
nfc_linux.c:nfc_target_connect 9 9 0.00% 21 21 0.00%
nfc_linux.c:nfc_free 12 0 100.00% 11 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 327 73 77.68% 458 124 72.93%
TOTAL 174 56 67.82% 245 103 57.96%
File '/libfido2/src/pcsc.c':
Name Regions Miss Cover Lines Miss Cover
-------------------------------------------------------------------------------------------------------------------
fido_pcsc_manifest 51 0 100.00% 55 0 100.00%
fido_pcsc_open 32 0 100.00% 43 0 100.00%
fido_pcsc_close 6 0 100.00% 9 0 100.00%
fido_pcsc_read 8 0 100.00% 16 0 100.00%
fido_pcsc_write 8 0 100.00% 22 0 100.00%
fido_pcsc_tx 1 0 100.00% 3 0 100.00%
fido_pcsc_rx 1 0 100.00% 3 0 100.00%
fido_is_pcsc 3 0 100.00% 3 0 100.00%
fido_dev_set_pcsc 4 1 75.00% 18 3 83.33%
pcsc.c:list_readers 24 0 100.00% 24 0 100.00%
pcsc.c:copy_info 27 0 100.00% 37 0 100.00%
pcsc.c:get_reader 25 0 100.00% 28 0 100.00%
pcsc.c:prepare_io_request 11 0 100.00% 17 0 100.00%
-------------------------------------------------------------------------------------------------------------------
TOTAL 201 1 99.50% 278 3 98.92%
File '/libfido2/src/pin.c':
Name Regions Miss Cover Lines Miss Cover
@ -744,7 +769,7 @@ fido_dev_set_pin 1 0 100.00% 4
fido_dev_get_retry_count 1 0 100.00% 4 0 100.00%
fido_dev_get_uv_retry_count 1 0 100.00% 4 0 100.00%
cbor_add_uv_params 17 0 100.00% 23 0 100.00%
pin.c:uv_token_wait 14 2 85.71% 12 0 100.00%
pin.c:uv_token_wait 14 2 85.71% 12 1 91.67%
pin.c:ctap21_uv_token_tx 49 0 100.00% 53 0 100.00%
pin.c:pin_sha256_enc 19 0 100.00% 24 0 100.00%
pin.c:encode_uv_permission 20 1 95.00% 19 3 84.21%
@ -765,7 +790,7 @@ pin.c:fido_dev_get_uv_retry_count_wait 10 0 100.00% 7
pin.c:fido_dev_get_uv_retry_count_rx 11 0 100.00% 17 0 100.00%
pin.c:parse_uv_retry_count 1 0 100.00% 3 0 100.00%
---------------------------------------------------------------------------------------------------------------------
TOTAL 403 3 99.26% 495 3 99.39%
TOTAL 403 3 99.26% 495 4 99.19%
File '/libfido2/src/random.c':
Name Regions Miss Cover Lines Miss Cover
@ -786,11 +811,11 @@ TOTAL 24 0 100.00% 23
File '/libfido2/src/rs1.c':
Name Regions Miss Cover Lines Miss Cover
---------------------------------------------------------------------------------------------------------------------
rs1_verify_sig 20 0 100.00% 30 0 100.00%
rs1.c:rs1_get_EVP_MD 4 0 100.00% 6 0 100.00%
rs1_verify_sig 20 1 95.00% 30 3 90.00%
rs1.c:rs1_get_EVP_MD 4 1 75.00% 6 1 83.33%
rs1.c:rs1_free_EVP_MD 1 0 100.00% 3 0 100.00%
---------------------------------------------------------------------------------------------------------------------
TOTAL 25 0 100.00% 39 0 100.00%
TOTAL 25 2 92.00% 39 4 89.74%
File '/libfido2/src/rs256.c':
Name Regions Miss Cover Lines Miss Cover
@ -801,7 +826,7 @@ rs256_pk_free 6 0 100.00% 7
rs256_pk_from_ptr 6 0 100.00% 6 0 100.00%
rs256_pk_to_EVP_PKEY 32 0 100.00% 39 0 100.00%
rs256_pk_from_RSA 32 4 87.50% 26 6 76.92%
rs256_pk_from_EVP_PKEY 7 2 71.43% 7 0 100.00%
rs256_pk_from_EVP_PKEY 7 2 71.43% 7 1 85.71%
rs256_verify_sig 20 1 95.00% 30 2 93.33%
rs256_pk_verify_sig 7 1 85.71% 13 2 84.62%
rs256.c:decode_rsa_pubkey 9 0 100.00% 13 0 100.00%
@ -809,31 +834,39 @@ rs256.c:decode_bignum 8 0 100.00% 10
rs256.c:rs256_get_EVP_MD 4 0 100.00% 6 0 100.00%
rs256.c:rs256_free_EVP_MD 1 0 100.00% 3 0 100.00%
---------------------------------------------------------------------------------------------------------------------
TOTAL 141 8 94.33% 172 10 94.19%
TOTAL 141 8 94.33% 172 11 93.60%
File '/libfido2/src/time.c':
Name Regions Miss Cover Lines Miss Cover
---------------------------------------------------------------------------------------------------------------------
fido_time_now 4 0 100.00% 7 0 100.00%
fido_time_delta 23 1 95.65% 23 0 100.00%
time.c:timespec_to_ms 16 2 87.50% 13 1 92.31%
time.c:timespec_to_ms 16 2 87.50% 13 2 84.62%
---------------------------------------------------------------------------------------------------------------------
TOTAL 43 3 93.02% 43 1 97.67%
TOTAL 43 3 93.02% 43 2 95.35%
File '/libfido2/src/touch.c':
Name Regions Miss Cover Lines Miss Cover
---------------------------------------------------------------------------------------------------------------------
fido_dev_get_touch_begin 50 0 100.00% 59 0 100.00%
fido_dev_get_touch_status 17 0 100.00% 20 0 100.00%
---------------------------------------------------------------------------------------------------------------------
TOTAL 67 0 100.00% 79 0 100.00%
File '/libfido2/src/tpm.c':
Name Regions Miss Cover Lines Miss Cover
---------------------------------------------------------------------------------------------------------------------
fido_get_signed_hash_tpm 25 0 100.00% 39 0 100.00%
tpm.c:check_es256_pubarea 18 0 100.00% 30 0 100.00%
fido_get_signed_hash_tpm 25 1 96.00% 39 3 92.31%
tpm.c:check_es256_pubarea 19 1 94.74% 30 3 90.00%
tpm.c:bswap_es256_pubarea 1 0 100.00% 12 0 100.00%
tpm.c:check_rs256_pubarea 16 0 100.00% 28 0 100.00%
tpm.c:check_rs256_pubarea 17 1 94.12% 28 3 89.29%
tpm.c:bswap_rs256_pubarea 1 0 100.00% 10 0 100.00%
tpm.c:check_sha1_certinfo 14 0 100.00% 38 0 100.00%
tpm.c:check_sha1_certinfo 15 0 100.00% 38 0 100.00%
tpm.c:get_signed_sha1 17 0 100.00% 19 0 100.00%
tpm.c:get_signed_name 7 0 100.00% 10 0 100.00%
tpm.c:bswap_sha1_certinfo 1 0 100.00% 8 0 100.00%
---------------------------------------------------------------------------------------------------------------------
TOTAL 100 0 100.00% 194 0 100.00%
TOTAL 103 3 97.09% 194 9 95.36%
File '/libfido2/src/types.c':
Name Regions Miss Cover Lines Miss Cover
@ -869,3 +902,10 @@ u2f.c:parse_auth_reply 23 0 100.00% 23
u2f.c:authdata_fake 12 0 100.00% 27 0 100.00%
---------------------------------------------------------------------------------------------------------------------
TOTAL 528 4 99.24% 685 12 98.25%
File '/libfido2/src/util.c':
Name Regions Miss Cover Lines Miss Cover
---------------------------------------------------------------------------------------------------------------------
fido_to_uint64 14 1 92.86% 14 1 92.86%
---------------------------------------------------------------------------------------------------------------------
TOTAL 14 1 92.86% 14 1 92.86%

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 Yubico AB. All rights reserved.
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -288,6 +288,9 @@ dev_get_cbor_info(const struct param *p)
n = fido_cbor_info_maxcredidlen(ci);
consume(&n, sizeof(n));
n = fido_cbor_info_maxlargeblob(ci);
consume(&n, sizeof(n));
n = fido_cbor_info_fwversion(ci);
consume(&n, sizeof(n));

266
fuzz/fuzz_pcsc.c Normal file
View file

@ -0,0 +1,266 @@
/*
* Copyright (c) 2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#define _FIDO_INTERNAL
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <winscard.h>
#include "mutator_aux.h"
#include "wiredata_fido2.h"
#include "dummy.h"
#include "../src/extern.h"
struct param {
int seed;
char path[MAXSTR];
struct blob pcsc_list;
struct blob tx_apdu;
struct blob wiredata_init;
struct blob wiredata_msg;
};
static const uint8_t dummy_tx_apdu[] = { WIREDATA_CTAP_EXTENDED_APDU };
static const uint8_t dummy_wiredata_init[] = { WIREDATA_CTAP_NFC_INIT };
static const uint8_t dummy_wiredata_msg[] = { WIREDATA_CTAP_NFC_MSG };
struct param *
unpack(const uint8_t *ptr, size_t len)
{
cbor_item_t *item = NULL, **v;
struct cbor_load_result cbor;
struct param *p;
int ok = -1;
if ((p = calloc(1, sizeof(*p))) == NULL ||
(item = cbor_load(ptr, len, &cbor)) == NULL ||
cbor.read != len ||
cbor_isa_array(item) == false ||
cbor_array_is_definite(item) == false ||
cbor_array_size(item) != 6 ||
(v = cbor_array_handle(item)) == NULL)
goto fail;
if (unpack_int(v[0], &p->seed) < 0 ||
unpack_string(v[1], p->path) < 0 ||
unpack_blob(v[2], &p->pcsc_list) < 0 ||
unpack_blob(v[3], &p->tx_apdu) < 0 ||
unpack_blob(v[4], &p->wiredata_init) < 0 ||
unpack_blob(v[5], &p->wiredata_msg) < 0)
goto fail;
ok = 0;
fail:
if (ok < 0) {
free(p);
p = NULL;
}
if (item)
cbor_decref(&item);
return p;
}
size_t
pack(uint8_t *ptr, size_t len, const struct param *p)
{
cbor_item_t *argv[6], *array = NULL;
size_t cbor_alloc_len, cbor_len = 0;
unsigned char *cbor = NULL;
memset(argv, 0, sizeof(argv));
if ((array = cbor_new_definite_array(6)) == NULL ||
(argv[0] = pack_int(p->seed)) == NULL ||
(argv[1] = pack_string(p->path)) == NULL ||
(argv[2] = pack_blob(&p->pcsc_list)) == NULL ||
(argv[3] = pack_blob(&p->tx_apdu)) == NULL ||
(argv[4] = pack_blob(&p->wiredata_init)) == NULL ||
(argv[5] = pack_blob(&p->wiredata_msg)) == NULL)
goto fail;
for (size_t i = 0; i < 6; i++)
if (cbor_array_push(array, argv[i]) == false)
goto fail;
if ((cbor_len = cbor_serialize_alloc(array, &cbor,
&cbor_alloc_len)) > len) {
cbor_len = 0;
goto fail;
}
memcpy(ptr, cbor, cbor_len);
fail:
for (size_t i = 0; i < 6; i++)
if (argv[i])
cbor_decref(&argv[i]);
if (array)
cbor_decref(&array);
free(cbor);
return cbor_len;
}
size_t
pack_dummy(uint8_t *ptr, size_t len)
{
struct param dummy;
uint8_t blob[4096];
size_t blob_len;
memset(&dummy, 0, sizeof(dummy));
strlcpy(dummy.path, dummy_pcsc_path, sizeof(dummy.path));
dummy.pcsc_list.len = sizeof(dummy_pcsc_list);
memcpy(&dummy.pcsc_list.body, &dummy_pcsc_list, dummy.pcsc_list.len);
dummy.tx_apdu.len = sizeof(dummy_tx_apdu);
memcpy(&dummy.tx_apdu.body, &dummy_tx_apdu, dummy.tx_apdu.len);
dummy.wiredata_init.len = sizeof(dummy_wiredata_init);
memcpy(&dummy.wiredata_init.body, &dummy_wiredata_init,
dummy.wiredata_init.len);
dummy.wiredata_msg.len = sizeof(dummy_wiredata_msg);
memcpy(&dummy.wiredata_msg.body, &dummy_wiredata_msg,
dummy.wiredata_msg.len);
assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
if (blob_len > len) {
memcpy(ptr, blob, len);
return len;
}
memcpy(ptr, blob, blob_len);
return blob_len;
}
static void
test_manifest(void)
{
size_t ndevs, nfound;
fido_dev_info_t *devlist = NULL;
int16_t vendor_id, product_id;
int r;
r = fido_pcsc_manifest(NULL, 0, &nfound);
assert(r == FIDO_OK && nfound == 0);
r = fido_pcsc_manifest(NULL, 1, &nfound);
assert(r == FIDO_ERR_INVALID_ARGUMENT);
ndevs = uniform_random(64);
if ((devlist = fido_dev_info_new(ndevs)) == NULL ||
fido_pcsc_manifest(devlist, ndevs, &nfound) != FIDO_OK)
goto out;
for (size_t i = 0; i < nfound; i++) {
const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
consume_str(fido_dev_info_path(di));
consume_str(fido_dev_info_manufacturer_string(di));
consume_str(fido_dev_info_product_string(di));
vendor_id = fido_dev_info_vendor(di);
product_id = fido_dev_info_product(di);
consume(&vendor_id, sizeof(vendor_id));
consume(&product_id, sizeof(product_id));
}
out:
fido_dev_info_free(&devlist, ndevs);
}
static void
test_tx(const char *path, const struct blob *apdu, uint8_t cmd, u_char *rx_buf,
size_t rx_len)
{
fido_dev_t dev;
const u_char *tx_ptr = NULL;
size_t tx_len = 0;
int n;
memset(&dev, 0, sizeof(dev));
if (fido_dev_set_pcsc(&dev) < 0)
return;
if ((dev.io_handle = fido_pcsc_open(path)) == NULL)
return;
if (apdu) {
tx_ptr = apdu->body;
tx_len = apdu->len;
}
fido_pcsc_tx(&dev, cmd, tx_ptr, tx_len);
if ((n = fido_pcsc_rx(&dev, cmd, rx_buf, rx_len, -1)) >= 0)
consume(rx_buf, n);
fido_pcsc_close(dev.io_handle);
}
static void
test_misc(void)
{
assert(fido_pcsc_open(NULL) == NULL);
assert(fido_pcsc_write(NULL, NULL, INT_MAX + 1LL) == -1);
}
void
test(const struct param *p)
{
u_char buf[512];
prng_init((unsigned int)p->seed);
fuzz_clock_reset();
fido_init(FIDO_DEBUG);
fido_set_log_handler(consume_str);
set_pcsc_parameters(&p->pcsc_list);
set_pcsc_io_functions(nfc_read, nfc_write, consume);
test_manifest();
test_misc();
set_wire_data(p->wiredata_init.body, p->wiredata_init.len);
test_tx(p->path, NULL, CTAP_CMD_INIT, buf, uniform_random(20));
set_wire_data(p->wiredata_msg.body, p->wiredata_msg.len);
test_tx(p->path, &p->tx_apdu, CTAP_CMD_MSG, buf, sizeof(buf));
set_wire_data(p->wiredata_msg.body, p->wiredata_msg.len);
test_tx(p->path, &p->tx_apdu, CTAP_CMD_CBOR, buf, sizeof(buf));
set_wire_data(p->wiredata_msg.body, p->wiredata_msg.len);
test_tx(p->path, &p->tx_apdu, CTAP_CMD_LOCK, buf, sizeof(buf));
}
void
mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
{
if (flags & MUTATE_SEED)
p->seed = (int)seed;
if (flags & MUTATE_PARAM) {
mutate_string(p->path);
mutate_blob(&p->pcsc_list);
mutate_blob(&p->tx_apdu);
}
if (flags & MUTATE_WIREDATA) {
mutate_blob(&p->wiredata_init);
mutate_blob(&p->wiredata_msg);
}
}

View file

@ -15,9 +15,6 @@
#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);
@ -241,16 +238,16 @@ nfc_close(void *handle)
assert(handle == (void *)NFC_DEV_HANDLE);
}
static int
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);
assert(len > 0 && len <= 264);
return buf_read(ptr, len, ms);
}
static int
int
nfc_write(void *handle, const unsigned char *ptr, size_t len)
{
assert(handle == (void *)NFC_DEV_HANDLE);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 Yubico AB. All rights reserved.
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -51,6 +51,9 @@
#define MAXSTR 1024
#define MAXBLOB 3600
#define HID_DEV_HANDLE 0x68696421
#define NFC_DEV_HANDLE 0x6e666321
struct blob {
uint8_t body[MAXBLOB];
size_t len;
@ -85,6 +88,9 @@ void mutate_string(char *);
ssize_t fd_read(int, void *, size_t);
ssize_t fd_write(int, const void *, size_t);
int nfc_read(void *, unsigned char *, size_t, int);
int nfc_write(void *, const unsigned char *, size_t);
fido_dev_t *open_dev(int);
void set_wire_data(const uint8_t *, size_t);
@ -94,4 +100,8 @@ unsigned long prng_uint32(void);
uint32_t uniform_random(uint32_t);
void set_pcsc_parameters(const struct blob *);
void set_pcsc_io_functions(int (*)(void *, u_char *, size_t, int),
int (*)(void *, const u_char *, size_t), void (*)(const void *, size_t));
#endif /* !_MUTATOR_AUX_H */

152
fuzz/pcsc.c Normal file
View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <winscard.h>
#include "mutator_aux.h"
static const struct blob *reader_list;
static int (*xread)(void *, u_char *, size_t, int);
static int (*xwrite)(void *, const u_char *, size_t);
static void (*xconsume)(const void *, size_t);
LONG __wrap_SCardEstablishContext(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT);
LONG __wrap_SCardListReaders(SCARDCONTEXT, LPCSTR, LPSTR, LPDWORD);
LONG __wrap_SCardReleaseContext(SCARDCONTEXT);
LONG __wrap_SCardConnect(SCARDCONTEXT, LPCSTR, DWORD, DWORD, LPSCARDHANDLE,
LPDWORD);
LONG __wrap_SCardDisconnect(SCARDHANDLE, DWORD);
LONG __wrap_SCardTransmit(SCARDHANDLE, const SCARD_IO_REQUEST *, LPCBYTE,
DWORD, SCARD_IO_REQUEST *, LPBYTE, LPDWORD);
LONG
__wrap_SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
{
assert(dwScope == SCARD_SCOPE_SYSTEM);
assert(pvReserved1 == NULL);
assert(pvReserved2 == NULL);
*phContext = 1;
if (uniform_random(400) < 1)
return SCARD_E_NO_SERVICE;
if (uniform_random(400) < 1)
return SCARD_E_NO_SMARTCARD;
if (uniform_random(400) < 1)
return SCARD_E_NO_MEMORY;
if (uniform_random(400) < 1)
*phContext = 0;
return SCARD_S_SUCCESS;
}
LONG
__wrap_SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups,
LPSTR mszReaders, LPDWORD pcchReaders)
{
assert(hContext == 1);
assert(mszGroups == NULL);
assert(mszReaders != NULL);
assert(pcchReaders != 0);
if (reader_list == NULL || uniform_random(400) < 1)
return SCARD_E_NO_READERS_AVAILABLE;
if (uniform_random(400) < 1)
return SCARD_E_NO_MEMORY;
memcpy(mszReaders, reader_list->body, reader_list->len > *pcchReaders ?
*pcchReaders : reader_list->len);
*pcchReaders = (DWORD)reader_list->len; /* on purpose */
return SCARD_S_SUCCESS;
}
LONG
__wrap_SCardReleaseContext(SCARDCONTEXT hContext)
{
assert(hContext == 1);
return SCARD_S_SUCCESS;
}
LONG
__wrap_SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
{
uint32_t r;
assert(hContext == 1);
xconsume(szReader, strlen(szReader) + 1);
assert(dwShareMode == SCARD_SHARE_SHARED);
assert(dwPreferredProtocols == SCARD_PROTOCOL_ANY);
assert(phCard != NULL);
assert(pdwActiveProtocol != NULL);
if ((r = uniform_random(400)) < 1)
return SCARD_E_UNEXPECTED;
*phCard = 1;
*pdwActiveProtocol = (r & 1) ? SCARD_PROTOCOL_T0 : SCARD_PROTOCOL_T1;
if (uniform_random(400) < 1)
*pdwActiveProtocol = SCARD_PROTOCOL_RAW;
return SCARD_S_SUCCESS;
}
LONG
__wrap_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
{
assert(hCard == 1);
assert(dwDisposition == SCARD_LEAVE_CARD);
return SCARD_S_SUCCESS;
}
extern void consume(const void *body, size_t len);
LONG
__wrap_SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci,
LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
{
void *ioh = (void *)NFC_DEV_HANDLE;
int n;
assert(hCard == 1);
xconsume(pioSendPci, sizeof(*pioSendPci));
xwrite(ioh, pbSendBuffer, cbSendLength);
assert(pioRecvPci == NULL);
if (uniform_random(400) < 1 ||
(n = xread(ioh, pbRecvBuffer, *pcbRecvLength, -1)) == -1)
return SCARD_E_UNEXPECTED;
*pcbRecvLength = (DWORD)n;
return SCARD_S_SUCCESS;
}
void
set_pcsc_parameters(const struct blob *reader_list_ptr)
{
reader_list = reader_list_ptr;
}
void
set_pcsc_io_functions(int (*read_f)(void *, u_char *, size_t, int),
int (*write_f)(void *, const u_char *, size_t),
void (*consume_f)(const void *, size_t))
{
xread = read_f;
xwrite = write_f;
xconsume = consume_f;
}

Binary file not shown.

View file

@ -1,52 +1,58 @@
Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
fuzz/clock.c 24 1 95.83% 4 0 100.00% 35 0 100.00%
fuzz/prng.c 31 0 100.00% 2 0 100.00% 35 0 100.00%
fuzz/udev.c 103 1 99.03% 17 0 100.00% 126 3 97.62%
fuzz/clock.c 24 1 95.83% 4 0 100.00% 35 1 97.14%
fuzz/pcsc.c 59 0 100.00% 8 0 100.00% 75 12 84.00%
fuzz/prng.c 31 0 100.00% 2 0 100.00% 35 1 97.14%
fuzz/udev.c 109 1 99.08% 17 0 100.00% 126 11 91.27%
fuzz/uniform_random.c 7 1 85.71% 1 0 100.00% 12 1 91.67%
fuzz/wrap.c 6 0 100.00% 1 0 100.00% 7 0 100.00%
fuzz/wrap.c 17 0 100.00% 3 0 100.00% 29 0 100.00%
openbsd-compat/explicit_bzero.c 4 0 100.00% 1 0 100.00% 7 0 100.00%
openbsd-compat/freezero.c 4 0 100.00% 1 0 100.00% 6 0 100.00%
openbsd-compat/recallocarray.c 41 7 82.93% 1 0 100.00% 36 7 80.56%
openbsd-compat/strlcat.c 12 1 91.67% 1 0 100.00% 21 1 95.24%
openbsd-compat/timingsafe_bcmp.c 4 0 100.00% 1 0 100.00% 7 0 100.00%
src/aes256.c 115 4 96.52% 8 0 100.00% 157 14 91.08%
src/assert.c 563 40 92.90% 56 3 94.64% 694 40 94.24%
src/aes256.c 118 4 96.61% 8 0 100.00% 157 14 91.08%
src/assert.c 565 42 92.57% 56 3 94.64% 694 42 93.95%
src/authkey.c 44 0 100.00% 5 0 100.00% 59 0 100.00%
src/bio.c 419 20 95.23% 49 2 95.92% 559 21 96.24%
src/bio.c 419 20 95.23% 49 2 95.92% 559 24 95.71%
src/blob.c 53 2 96.23% 10 0 100.00% 83 4 95.18%
src/buf.c 8 1 87.50% 2 0 100.00% 16 1 93.75%
src/cbor.c 1047 23 97.80% 54 0 100.00% 1237 46 96.28%
src/compress.c 34 4 88.24% 3 0 100.00% 28 3 89.29%
src/cbor.c 1049 23 97.81% 54 0 100.00% 1237 45 96.36%
src/compress.c 105 14 86.67% 5 0 100.00% 122 24 80.33%
src/config.c 108 0 100.00% 11 0 100.00% 151 0 100.00%
src/cred.c 632 34 94.62% 69 2 97.10% 830 36 95.66%
src/credman.c 382 10 97.38% 40 0 100.00% 518 15 97.10%
src/dev.c 421 79 81.24% 45 7 84.44% 491 105 78.62%
src/cred.c 634 36 94.32% 69 2 97.10% 830 39 95.30%
src/credman.c 382 10 97.38% 40 0 100.00% 518 18 96.53%
src/dev.c 332 71 78.61% 41 6 85.37% 378 86 77.25%
src/ecdh.c 117 2 98.29% 4 0 100.00% 146 5 96.58%
src/eddsa.c 80 3 96.25% 10 0 100.00% 106 8 92.45%
src/eddsa.c 88 5 94.32% 10 0 100.00% 114 9 92.11%
src/err.c 122 10 91.80% 1 0 100.00% 126 10 92.06%
src/es256.c 306 5 98.37% 19 0 100.00% 358 7 98.04%
src/es256.c 315 7 97.78% 19 0 100.00% 372 12 96.77%
src/hid.c 87 2 97.70% 14 0 100.00% 145 3 97.93%
src/hid_linux.c 173 68 60.69% 14 7 50.00% 250 104 58.40%
src/hid_unix.c 28 20 28.57% 2 0 100.00% 43 24 44.19%
src/info.c 184 0 100.00% 39 0 100.00% 316 0 100.00%
src/io.c 182 7 96.15% 13 0 100.00% 221 11 95.02%
src/iso7816.c 18 1 94.44% 5 0 100.00% 38 0 100.00%
src/largeblob.c 513 19 96.30% 30 0 100.00% 684 43 93.71%
src/log.c 39 5 87.18% 7 1 85.71% 63 4 93.65%
src/netlink.c 328 14 95.73% 40 0 100.00% 498 32 93.57%
src/nfc_linux.c 327 73 77.68% 23 5 78.26% 458 124 72.93%
src/pin.c 403 3 99.26% 26 0 100.00% 495 3 99.39%
src/hid_linux.c 173 68 60.69% 14 7 50.00% 250 105 58.00%
src/hid_unix.c 29 21 27.59% 2 0 100.00% 43 26 39.53%
src/info.c 186 0 100.00% 40 0 100.00% 321 0 100.00%
src/io.c 185 7 96.22% 13 0 100.00% 221 12 94.57%
src/iso7816.c 18 1 94.44% 5 0 100.00% 38 1 97.37%
src/largeblob.c 514 19 96.30% 30 0 100.00% 684 46 93.27%
src/log.c 39 5 87.18% 7 1 85.71% 63 7 88.89%
src/netlink.c 329 14 95.74% 40 0 100.00% 498 33 93.37%
src/nfc.c 142 7 95.07% 11 1 90.91% 223 27 87.89%
src/nfc_linux.c 174 56 67.82% 13 5 61.54% 245 103 57.96%
src/pcsc.c 201 1 99.50% 13 0 100.00% 278 3 98.92%
src/pin.c 403 3 99.26% 26 0 100.00% 495 4 99.19%
src/random.c 6 1 83.33% 1 0 100.00% 6 1 83.33%
src/reset.c 24 0 100.00% 3 0 100.00% 23 0 100.00%
src/rs1.c 25 0 100.00% 3 0 100.00% 39 0 100.00%
src/rs256.c 141 8 94.33% 13 0 100.00% 172 10 94.19%
src/time.c 43 3 93.02% 3 0 100.00% 43 1 97.67%
src/tpm.c 100 0 100.00% 9 0 100.00% 194 0 100.00%
src/rs1.c 25 2 92.00% 3 0 100.00% 39 4 89.74%
src/rs256.c 141 8 94.33% 13 0 100.00% 172 11 93.60%
src/time.c 43 3 93.02% 3 0 100.00% 43 2 95.35%
src/touch.c 67 0 100.00% 2 0 100.00% 79 0 100.00%
src/tpm.c 103 3 97.09% 9 0 100.00% 194 9 95.36%
src/types.c 25 0 100.00% 6 0 100.00% 46 0 100.00%
src/u2f.c 528 4 99.24% 17 0 100.00% 685 12 98.25%
src/util.c 14 1 92.86% 1 0 100.00% 14 1 92.86%
Files which contain no functions:
fuzz/mutator_aux.h 0 0 - 0 0 - 0 0 -
openbsd-compat/openbsd-compat.h 0 0 - 0 0 - 0 0 -
openbsd-compat/time.h 0 0 - 0 0 - 0 0 -
src/extern.h 0 0 - 0 0 - 0 0 -
@ -54,4 +60,4 @@ src/fido.h 0 0 -
src/fido/err.h 0 0 - 0 0 - 0 0 -
src/fido/param.h 0 0 - 0 0 - 0 0 -
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL 7861 476 93.94% 684 27 96.05% 10270 699 93.19%
TOTAL 8227 484 94.12% 710 27 96.20% 10756 777 92.78%

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Yubico AB. All rights reserved.
* Copyright (c) 2020-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -630,4 +630,78 @@
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
#define WIREDATA_CTAP_NFC_INIT \
0x55, 0x32, 0x46, 0x5f, 0x56, 0x32, 0x90, 0x00
#define WIREDATA_CTAP_NFC_MSG \
0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00
#define WIREDATA_CTAP_EXTENDED_APDU \
0x00, 0xa4, 0x04, 0x00, 0x00, 0x02, 0x00, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, \
0x00
#endif /* _WIREDATA_FIDO2_H */

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 Yubico AB. All rights reserved.
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -16,6 +16,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
#include "mutator_aux.h"
@ -635,3 +636,51 @@ WRAP(int,
(sockfd, addr, addrlen),
1
)
WRAP(int,
deflateInit2_,
(z_streamp strm, int level, int method, int windowBits, int memLevel,
int strategy, const char *version, int stream_size),
Z_STREAM_ERROR,
(strm, level, method, windowBits, memLevel, strategy, version,
stream_size),
1
)
int __wrap_deflate(z_streamp, int);
int __real_deflate(z_streamp, int);
int
__wrap_deflate(z_streamp strm, int flush)
{
if (uniform_random(400) < 1) {
return Z_BUF_ERROR;
}
/* should never happen, but we check for it */
if (uniform_random(400) < 1) {
strm->avail_out = UINT_MAX;
return Z_STREAM_END;
}
return __real_deflate(strm, flush);
}
int __wrap_asprintf(char **, const char *, ...);
int
__wrap_asprintf(char **strp, const char *fmt, ...)
{
va_list ap;
int r;
if (uniform_random(400) < 1) {
*strp = (void *)0xdeadbeef;
return -1;
}
va_start(ap, fmt);
r = vasprintf(strp, fmt, ap);
va_end(ap);
return r;
}

View file

@ -1,3 +1,4 @@
asprintf
bind
BN_bin2bn
BN_bn2bin
@ -24,6 +25,8 @@ cbor_new_definite_bytestring
cbor_new_definite_map
cbor_serialize_alloc
clock_gettime
deflate
deflateInit2_
EC_KEY_get0_group
EC_KEY_get0_private_key
EC_KEY_new_by_curve_name
@ -71,6 +74,12 @@ realloc
RSA_new
RSA_pkey_ctx_ctrl
RSA_set0_key
SCardConnect
SCardDisconnect
SCardEstablishContext
SCardListReaders
SCardReleaseContext
SCardTransmit
SHA1
SHA256
strdup

View file

@ -1,4 +1,4 @@
# Copyright (c) 2018 Yubico AB. All rights reserved.
# Copyright (c) 2018-2022 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
@ -117,10 +117,11 @@ list(APPEND MAN_ALIAS
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_maxlargeblob
fido_cbor_info_new fido_cbor_info_maxmsgsiz
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
@ -263,7 +264,7 @@ 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} .
COMMAND cp -f ${PROJECT_SOURCE_DIR}/man/${f} .
DEPENDS ${f})
list(APPEND COPY_FILES ${f})
endforeach()
@ -289,7 +290,7 @@ endforeach()
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 cat ${PROJECT_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)
@ -337,17 +338,17 @@ 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
install(FILES ${PROJECT_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
install(FILES ${PROJECT_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
install(FILES ${PROJECT_BINARY_DIR}/man/${DST}.html
DESTINATION "${CMAKE_INSTALL_DOCDIR}/html")
endforeach()
endif()
@ -358,34 +359,34 @@ if(GZIP_PATH)
add_dependencies(man man_symlink_gzip)
foreach(f ${MAN_SOURCES})
if (${f} MATCHES ".1$")
install(FILES ${CMAKE_BINARY_DIR}/man/${f}.gz
install(FILES ${PROJECT_BINARY_DIR}/man/${f}.gz
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
elseif(${f} MATCHES ".3$")
install(FILES ${CMAKE_BINARY_DIR}/man/${f}.gz
install(FILES ${PROJECT_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
install(FILES ${PROJECT_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}
install(FILES ${PROJECT_BINARY_DIR}/man/${f}
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
elseif(${f} MATCHES ".3$")
install(FILES ${CMAKE_BINARY_DIR}/man/${f}
install(FILES ${PROJECT_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
install(FILES ${PROJECT_BINARY_DIR}/man/${DST}.3
DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")
endforeach()
endif()

View file

@ -1,8 +1,8 @@
.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved.
.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved.
.\" Use of this source code is governed by a BSD-style
.\" license that can be found in the LICENSE file.
.\"
.Dd $Mdocdate: September 13 2019 $
.Dd $Mdocdate: April 11 2022 $
.Dt FIDO2-TOKEN 1
.Os
.Sh NAME
@ -147,7 +147,7 @@ from
.Ar device ,
where
.Ar key_path
must hold the blob's base64-encoded encryption key.
holds the blob's base64-encoded 32-byte AES-256 GCM 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
@ -189,7 +189,7 @@ from
.Ar device ,
where
.Ar key_path
must hold the blob's base64-encoded encryption key.
holds the blob's base64-encoded 32-byte AES-256 GCM encryption key.
The blob is written to
.Ar blob_path .
A PIN or equivalent user-verification gesture is required.
@ -267,29 +267,27 @@ The user will be prompted for the PIN.
Enables CTAP 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 CTAP 2.1
Sets a CTAP 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.
holds the blob's base64-encoded 32-byte AES-256 GCM encryption key.
The blob is read from
.Fa blob_path .
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 CTAP 2.1
Sets a CTAP 2.1
.Dq largeBlob
associated with
.Ar rp_id
on
.Ar device .
The blob is read from
.Fa blob_path .
If
.Ar rp_id
has multiple credentials enrolled on

View file

@ -1,8 +1,8 @@
.\" Copyright (c) 2018 Yubico AB. All rights reserved.
.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved.
.\" Use of this source code is governed by a BSD-style
.\" license that can be found in the LICENSE file.
.\"
.Dd $Mdocdate: October 22 2019 $
.Dd $Mdocdate: April 27 2022 $
.Dt FIDO_ASSERT_NEW 3
.Os
.Sh NAME
@ -180,6 +180,8 @@ in
The HMAC Secret Extension
.Pq hmac-secret
is a CTAP 2.0 extension.
Note that the resulting hmac-secret varies according to whether
user verification was performed by the authenticator.
.Pp
The
.Fn fido_assert_blob_ptr

View file

@ -1,8 +1,8 @@
.\" Copyright (c) 2018 Yubico AB. All rights reserved.
.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved.
.\" Use of this source code is governed by a BSD-style
.\" license that can be found in the LICENSE file.
.\"
.Dd $Mdocdate: May 23 2018 $
.Dd $Mdocdate: April 27 2022 $
.Dt FIDO_ASSERT_SET_AUTHDATA 3
.Os
.Sh NAME
@ -182,6 +182,8 @@ is made, and no references to the passed pointer are kept.
The HMAC Secret
.Pq hmac-secret
Extension is a CTAP 2.0 extension.
Note that the resulting hmac-secret varies according to whether
user verification was performed by the authenticator.
The
.Fn fido_assert_set_hmac_secret
function is normally only useful when writing tests.

View file

@ -1,8 +1,8 @@
.\" Copyright (c) 2018 Yubico AB. All rights reserved.
.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved.
.\" Use of this source code is governed by a BSD-style
.\" license that can be found in the LICENSE file.
.\"
.Dd $Mdocdate: May 24 2018 $
.Dd $Mdocdate: April 22 2022 $
.Dt FIDO_CBOR_INFO_NEW 3
.Os
.Sh NAME
@ -29,6 +29,7 @@
.Nm fido_cbor_info_maxcredbloblen ,
.Nm fido_cbor_info_maxcredcntlst ,
.Nm fido_cbor_info_maxcredidlen ,
.Nm fido_cbor_info_maxlargeblob ,
.Nm fido_cbor_info_fwversion
.Nd FIDO2 CBOR Info API
.Sh SYNOPSIS
@ -80,6 +81,8 @@
.Ft uint64_t
.Fn fido_cbor_info_maxcredidlen "const fido_cbor_info_t *ci"
.Ft uint64_t
.Fn fido_cbor_info_maxlargeblob "const fido_cbor_info_t *ci"
.Ft uint64_t
.Fn fido_cbor_info_fwversion "const fido_cbor_info_t *ci"
.Sh DESCRIPTION
The
@ -201,6 +204,12 @@ as reported in
.Fa ci .
.Pp
The
.Fn fido_cbor_info_maxlargeblob
function returns the maximum length in bytes of an authenticator's
serialized largeBlob array as reported in
.Fa ci .
.Pp
The
.Fn fido_cbor_info_fwversion
function returns the firmware version attribute of
.Fa ci .

View file

@ -2,7 +2,7 @@
.\" 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 $
.Dd $Mdocdate: March 30 2022 $
.Dt FIDO_DEV_ENABLE_ENTATTEST 3
.Os
.Sh NAME
@ -65,7 +65,7 @@ does not have a PIN set.
.Pp
The
.Fn fido_dev_force_pin_change
instructs
function instructs
.Fa dev
to require a PIN change.
Subsequent PIN authentication attempts against

View file

@ -2,7 +2,7 @@
.\" 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 $
.Dd $Mdocdate: March 30 2022 $
.Dt FIDO_DEV_INFO_MANIFEST 3
.Os
.Sh NAME
@ -97,7 +97,7 @@ Please note that the first slot has index 0.
.Pp
The
.Fn fido_dev_info_path
returns the filesystem path or subsystem-specific identification
function returns the filesystem path or subsystem-specific identification
string of
.Fa di .
.Pp

View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 2004 Darren Tucker.
*
* Based originally on asprintf.c from OpenBSD:
* Copyright (c) 1997 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.
*/
#include "openbsd-compat.h"
#ifndef HAVE_ASPRINTF
#include <errno.h>
#include <limits.h> /* for INT_MAX */
#include <stdarg.h>
#include <stdio.h> /* for vsnprintf */
#include <stdlib.h>
#define VA_COPY(dest, src) va_copy(dest, src)
#define INIT_SZ 128
int
vasprintf(char **str, const char *fmt, va_list ap)
{
int ret;
va_list ap2;
char *string, *newstr;
size_t len;
if ((string = malloc(INIT_SZ)) == NULL)
goto fail;
VA_COPY(ap2, ap);
ret = vsnprintf(string, INIT_SZ, fmt, ap2);
va_end(ap2);
if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */
*str = string;
} else if (ret == INT_MAX || ret < 0) { /* Bad length */
free(string);
goto fail;
} else { /* bigger than initial, realloc allowing for nul */
len = (size_t)ret + 1;
if ((newstr = realloc(string, len)) == NULL) {
free(string);
goto fail;
}
VA_COPY(ap2, ap);
ret = vsnprintf(newstr, len, fmt, ap2);
va_end(ap2);
if (ret < 0 || (size_t)ret >= len) { /* failed with realloc'ed string */
free(newstr);
goto fail;
}
*str = newstr;
}
return (ret);
fail:
*str = NULL;
errno = ENOMEM;
return (-1);
}
int asprintf(char **str, const char *fmt, ...)
{
va_list ap;
int ret;
*str = NULL;
va_start(ap, fmt);
ret = vasprintf(str, fmt, ap);
va_end(ap);
return ret;
}
#endif

View file

@ -115,4 +115,8 @@ ssize_t getline(char **, size_t *, FILE *);
#define IOCTL_REQ(x) ((int)(x))
#endif
#if !defined(HAVE_ASPRINTF)
int asprintf(char **, const char *, ...);
#endif
#endif /* !_OPENBSD_COMPAT_H */

View file

@ -1,20 +1,45 @@
# Copyright (c) 2018-2021 Yubico AB. All rights reserved.
# Copyright (c) 2018-2022 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
add_custom_target(regress ALL)
add_custom_target(regress)
macro(add_regress_test NAME SOURCES)
add_executable(${NAME} ${SOURCES})
target_link_libraries(${NAME} fido2_shared)
target_link_libraries(${NAME} fido2)
add_test(${NAME} ${NAME})
add_dependencies(regress ${NAME})
endmacro()
add_custom_command(TARGET regress POST_BUILD
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
if(MSVC AND BUILD_SHARED_LIBS)
add_custom_command(TARGET regress POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"${CBOR_BIN_DIRS}/${CBOR_LIBRARIES}.dll"
"${CRYPTO_BIN_DIRS}/${CRYPTO_LIBRARIES}.dll"
"${ZLIB_BIN_DIRS}/${ZLIB_LIBRARIES}.dll"
"${CMAKE_CURRENT_BINARY_DIR}")
endif()
if(CMAKE_CROSSCOMPILING OR (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64" AND
CMAKE_GENERATOR_PLATFORM MATCHES "^ARM.*$"))
add_custom_command(TARGET regress POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E echo
"Cross-compilation detected. Skipping regress tests.")
else()
add_custom_command(TARGET regress POST_BUILD
COMMAND "${CMAKE_CTEST_COMMAND}" --output-on-failure
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
endif()
add_regress_test(regress_cred cred.c)
add_regress_test(regress_assert assert.c)
add_regress_test(regress_compress compress.c)
add_regress_test(regress_cred cred.c)
add_regress_test(regress_dev dev.c)
add_regress_test(regress_eddsa eddsa.c)
add_regress_test(regress_es256 es256.c)
add_regress_test(regress_rs256 rs256.c)
if(MINGW)
# needed for nanosleep() in mingw
target_link_libraries(regress_dev winpthread)
endif()

View file

@ -4,16 +4,19 @@
* license that can be found in the LICENSE file.
*/
#define _FIDO_INTERNAL
#undef NDEBUG
#include <assert.h>
#include <string.h>
#define _FIDO_INTERNAL
#include <fido.h>
#include <fido/es256.h>
#include <fido/rs256.h>
#include <fido/eddsa.h>
#include <string.h>
#define FAKE_DEV_HANDLE ((void *)0xdeadbeef)
static int fake_dev_handle;
static const unsigned char es256_pk[64] = {
0x34, 0xeb, 0x99, 0x77, 0x02, 0x9c, 0x36, 0x38,
@ -94,13 +97,13 @@ dummy_open(const char *path)
{
(void)path;
return (FAKE_DEV_HANDLE);
return (&fake_dev_handle);
}
static void
dummy_close(void *handle)
{
assert(handle == FAKE_DEV_HANDLE);
assert(handle == &fake_dev_handle);
}
static int

267
regress/compress.c Normal file
View file

@ -0,0 +1,267 @@
/*
* Copyright (c) 2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#undef NDEBUG
#include <assert.h>
#include <string.h>
#include <openssl/sha.h>
#define _FIDO_INTERNAL
#include <fido.h>
/*
* zlib compressed data (RFC1950); see https://www.ietf.org/rfc/rfc6713.txt
*/
static /* const */ unsigned char rfc1950_blob[694] = {
0x78, 0x9c, 0xb5, 0x52, 0x3b, 0x6f, 0xdb, 0x30,
0x10, 0xde, 0xf5, 0x2b, 0x0e, 0x99, 0x12, 0x40,
0x75, 0x13, 0x4f, 0x45, 0x3b, 0xd1, 0x12, 0x6d,
0x1d, 0x20, 0x8b, 0x2a, 0x49, 0xd9, 0xf5, 0x28,
0x4b, 0x4c, 0x42, 0xc0, 0x12, 0x03, 0x3d, 0x12,
0xe4, 0xdf, 0xf7, 0xc8, 0x3a, 0x88, 0xd3, 0x0c,
0x9d, 0xea, 0xc1, 0x3e, 0xf3, 0x8e, 0xdf, 0xeb,
0x98, 0xb8, 0xa7, 0xd7, 0xc1, 0x3e, 0x3c, 0x4e,
0x70, 0xdd, 0xdc, 0xc0, 0xf2, 0xf6, 0xee, 0xdb,
0x97, 0xe5, 0xed, 0x72, 0x09, 0x87, 0xf9, 0x68,
0x1b, 0x07, 0x6c, 0xb5, 0x00, 0x76, 0x3a, 0x41,
0x18, 0x19, 0x61, 0x30, 0xa3, 0x19, 0x9e, 0x4d,
0xbb, 0x88, 0x22, 0x69, 0x5a, 0x3b, 0x4e, 0x83,
0x3d, 0xce, 0x93, 0x75, 0x3d, 0xd4, 0x7d, 0x0b,
0xf3, 0x68, 0xc0, 0xf6, 0x30, 0xba, 0x79, 0x68,
0x4c, 0x38, 0x39, 0xda, 0xbe, 0x1e, 0x5e, 0xe1,
0xde, 0x0d, 0xdd, 0x18, 0xc3, 0x8b, 0x9d, 0x1e,
0xc1, 0x0d, 0xe1, 0xd7, 0xcd, 0x53, 0xd4, 0xb9,
0xd6, 0xde, 0xdb, 0xa6, 0xf6, 0x00, 0x31, 0xd4,
0x83, 0x81, 0x27, 0x33, 0x74, 0x76, 0x9a, 0x4c,
0x0b, 0x4f, 0x83, 0x7b, 0xb6, 0x2d, 0x15, 0xd3,
0x63, 0x3d, 0xd1, 0x97, 0x21, 0x90, 0xd3, 0xc9,
0xbd, 0xd8, 0xfe, 0x01, 0x1a, 0xd7, 0xb7, 0xd6,
0x5f, 0x1a, 0xfd, 0xa5, 0xa8, 0x33, 0xd3, 0xf7,
0x28, 0x02, 0x80, 0xbb, 0x05, 0x7c, 0x54, 0x35,
0x82, 0xbb, 0x7f, 0x93, 0xd3, 0xb8, 0xd6, 0x40,
0x37, 0x8f, 0x13, 0x99, 0x98, 0x6a, 0x92, 0xe9,
0x31, 0xeb, 0xa3, 0x7b, 0xf6, 0xad, 0x73, 0x06,
0x1e, 0x84, 0x3e, 0xbd, 0x9b, 0x6c, 0x63, 0x62,
0x9a, 0xb0, 0x23, 0x9c, 0x08, 0xcf, 0xc3, 0x5c,
0x92, 0xf6, 0xed, 0x5f, 0x8a, 0x88, 0xb4, 0x39,
0xd5, 0xb6, 0x33, 0xc3, 0xc2, 0x63, 0x2c, 0x3f,
0x0b, 0x21, 0xc2, 0x8b, 0x30, 0xde, 0x84, 0x90,
0xcb, 0x76, 0x26, 0x71, 0xff, 0x47, 0x0b, 0x91,
0x9e, 0x51, 0xfc, 0x44, 0xeb, 0x9a, 0xb9, 0x33,
0xfd, 0x54, 0xbf, 0xed, 0xeb, 0x2b, 0xad, 0xc2,
0x51, 0x67, 0x80, 0xae, 0x9e, 0xcc, 0x60, 0xeb,
0xd3, 0xf8, 0x1e, 0x7b, 0xd8, 0x15, 0x35, 0xcf,
0x00, 0x97, 0x66, 0x68, 0xf9, 0x3a, 0x43, 0x05,
0x4a, 0xac, 0xf5, 0x9e, 0x49, 0x0e, 0x54, 0x97,
0x52, 0xec, 0x30, 0xe5, 0x29, 0xac, 0x0e, 0xa0,
0x33, 0x0e, 0x89, 0x28, 0x0f, 0x12, 0x37, 0x99,
0x86, 0x4c, 0xe4, 0x29, 0x97, 0x0a, 0x58, 0x91,
0xd2, 0x69, 0xa1, 0x25, 0xae, 0x2a, 0x2d, 0xa4,
0x8a, 0xae, 0x98, 0xa2, 0x9b, 0x57, 0xa1, 0xc1,
0x8a, 0x03, 0xf0, 0x5f, 0xa5, 0xe4, 0x4a, 0x81,
0x90, 0x80, 0xdb, 0x32, 0x47, 0x02, 0x23, 0x74,
0xc9, 0x0a, 0x8d, 0x5c, 0xc5, 0x80, 0x45, 0x92,
0x57, 0x29, 0x16, 0x9b, 0x18, 0x08, 0x00, 0x0a,
0xa1, 0xa3, 0x1c, 0xb7, 0xa8, 0x69, 0x4c, 0x8b,
0x38, 0x90, 0x7e, 0xbe, 0x06, 0x62, 0x0d, 0x5b,
0x2e, 0x93, 0x8c, 0xfe, 0xb2, 0x15, 0xe6, 0xa8,
0x0f, 0x81, 0x6f, 0x8d, 0xba, 0xf0, 0x5c, 0x6b,
0x21, 0x23, 0x06, 0x25, 0x93, 0x1a, 0x93, 0x2a,
0x67, 0x12, 0xca, 0x4a, 0x96, 0x42, 0x71, 0xf0,
0xb6, 0x52, 0x54, 0x49, 0xce, 0x70, 0xcb, 0xd3,
0x05, 0xb1, 0x13, 0x23, 0xf0, 0x1d, 0x2f, 0x34,
0xa8, 0x8c, 0xe5, 0xf9, 0x47, 0x97, 0xd1, 0x1f,
0x97, 0x5e, 0xfb, 0xa5, 0x47, 0x58, 0x71, 0xc8,
0x91, 0xad, 0x72, 0xee, 0x99, 0x82, 0xcb, 0x14,
0x25, 0x4f, 0xb4, 0xb7, 0xf3, 0x5e, 0x25, 0x94,
0x1c, 0xe9, 0xcb, 0xe3, 0x48, 0x95, 0x3c, 0x41,
0x2a, 0x28, 0x0c, 0x4e, 0x66, 0x98, 0x3c, 0xc4,
0x67, 0x4c, 0xc5, 0x7f, 0x56, 0x34, 0x44, 0x4d,
0x48, 0xd9, 0x96, 0x6d, 0xc8, 0xdb, 0xf5, 0x3f,
0x22, 0xa1, 0x9d, 0x24, 0x95, 0xe4, 0x5b, 0xaf,
0x99, 0x72, 0x50, 0xd5, 0x4a, 0x69, 0xd4, 0x95,
0xe6, 0xb0, 0x11, 0x22, 0x0d, 0x41, 0x2b, 0x2e,
0x77, 0x98, 0x70, 0xf5, 0x03, 0x72, 0xa1, 0x42,
0x5a, 0x95, 0xe2, 0x71, 0x94, 0x32, 0xcd, 0x02,
0x31, 0x41, 0x50, 0x54, 0xd4, 0xa6, 0x7a, 0x55,
0x29, 0x0c, 0xa1, 0x61, 0xa1, 0xb9, 0x94, 0x55,
0xa9, 0x51, 0x14, 0x37, 0xb4, 0xdf, 0x3d, 0xc5,
0x42, 0x1a, 0x19, 0x5d, 0x4d, 0x43, 0xba, 0xa2,
0xf0, 0x56, 0xe9, 0x91, 0x70, 0x21, 0x0f, 0x1e,
0xd4, 0x67, 0x10, 0xc2, 0x8f, 0x61, 0x9f, 0x71,
0x3a, 0x97, 0x3e, 0xd0, 0x90, 0x14, 0xf3, 0x11,
0x28, 0x4a, 0x2c, 0xd1, 0x97, 0x63, 0xc4, 0x47,
0x01, 0xea, 0xe8, 0xdd, 0x23, 0x14, 0x7c, 0x93,
0xe3, 0x86, 0x17, 0x09, 0xf7, 0x5d, 0xe1, 0x51,
0xf6, 0xa8, 0xf8, 0x0d, 0xed, 0x0a, 0x95, 0x1f,
0xc0, 0x40, 0x4b, 0xdb, 0x27, 0xce, 0x2a, 0x58,
0xf6, 0x3b, 0x22, 0x55, 0x51, 0x28, 0x2f, 0x5e,
0x6c, 0x1c, 0x36, 0x09, 0xb8, 0x06, 0x96, 0xee,
0xd0, 0xcb, 0x3e, 0x0f, 0xd3, 0xee, 0x15, 0x9e,
0xdf, 0x49, 0x88, 0x2c, 0xc9, 0xce, 0x71, 0x2f,
0xa2, 0xdf, 0xdf, 0xd7, 0x8e, 0x9c,
};
/*
* expected sha256 of rfc1950_blob after decompression
*/
static const unsigned char rfc1950_blob_hash[SHA256_DIGEST_LENGTH] = {
0x61, 0xc0, 0x4e, 0x14, 0x01, 0xb6, 0xc5, 0x2d,
0xba, 0x15, 0xf6, 0x27, 0x4c, 0xa1, 0xcc, 0xfc,
0x39, 0xed, 0xd7, 0x12, 0xb6, 0x02, 0x3d, 0xb6,
0xd9, 0x85, 0xd0, 0x10, 0x9f, 0xe9, 0x3e, 0x75,
};
static const size_t rfc1950_blob_origsiz = 1322;
static /* const */ unsigned char random_words[515] = {
0x61, 0x74, 0x68, 0x69, 0x72, 0x73, 0x74, 0x20,
0x54, 0x68, 0x6f, 0x20, 0x63, 0x6f, 0x74, 0x20,
0x73, 0x70, 0x6f, 0x66, 0x66, 0x79, 0x20, 0x4a,
0x61, 0x76, 0x61, 0x6e, 0x20, 0x62, 0x72, 0x65,
0x64, 0x65, 0x73, 0x20, 0x4c, 0x41, 0x4d, 0x20,
0x6d, 0x69, 0x73, 0x2d, 0x68, 0x75, 0x6d, 0x69,
0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x70, 0x69,
0x67, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x76, 0x6f,
0x6c, 0x74, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x20,
0x49, 0x6f, 0x64, 0x61, 0x6d, 0x6f, 0x65, 0x62,
0x61, 0x20, 0x68, 0x79, 0x70, 0x6f, 0x68, 0x79,
0x64, 0x72, 0x6f, 0x63, 0x68, 0x6c, 0x6f, 0x72,
0x69, 0x61, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x6d,
0x65, 0x74, 0x74, 0x65, 0x20, 0x61, 0x63, 0x72,
0x69, 0x64, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x6f,
0x77, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x79, 0x67,
0x61, 0x65, 0x61, 0x6e, 0x20, 0x63, 0x6f, 0x6e,
0x63, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x73,
0x74, 0x20, 0x74, 0x65, 0x74, 0x72, 0x61, 0x70,
0x6c, 0x6f, 0x69, 0x64, 0x20, 0x61, 0x75, 0x78,
0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x72,
0x69, 0x70, 0x65, 0x2d, 0x67, 0x72, 0x6f, 0x77,
0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72,
0x72, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x79, 0x63,
0x6f, 0x63, 0x65, 0x63, 0x69, 0x64, 0x69, 0x75,
0x6d, 0x20, 0x50, 0x65, 0x64, 0x65, 0x72, 0x73,
0x6f, 0x6e, 0x20, 0x74, 0x72, 0x61, 0x64, 0x69,
0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x62, 0x6f, 0x75,
0x6e, 0x64, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x6c,
0x65, 0x6e, 0x20, 0x70, 0x72, 0x65, 0x73, 0x62,
0x79, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20,
0x6c, 0x65, 0x63, 0x79, 0x74, 0x68, 0x69, 0x73,
0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x64, 0x72,
0x69, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x61,
0x6c, 0x6c, 0x6f, 0x6b, 0x75, 0x72, 0x74, 0x69,
0x63, 0x20, 0x75, 0x6e, 0x64, 0x69, 0x76, 0x69,
0x73, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x20, 0x70,
0x73, 0x79, 0x63, 0x68, 0x6f, 0x6b, 0x79, 0x6d,
0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73,
0x74, 0x61, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65,
0x6e, 0x65, 0x73, 0x73, 0x20, 0x63, 0x75, 0x6c,
0x74, 0x69, 0x73, 0x68, 0x20, 0x52, 0x65, 0x69,
0x63, 0x68, 0x73, 0x74, 0x61, 0x67, 0x20, 0x75,
0x6e, 0x63, 0x68, 0x6c, 0x6f, 0x72, 0x69, 0x6e,
0x61, 0x74, 0x65, 0x64, 0x20, 0x6c, 0x6f, 0x67,
0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72,
0x20, 0x4c, 0x61, 0x69, 0x74, 0x68, 0x20, 0x74,
0x77, 0x6f, 0x2d, 0x66, 0x61, 0x63, 0x65, 0x20,
0x4d, 0x75, 0x70, 0x68, 0x72, 0x69, 0x64, 0x20,
0x70, 0x72, 0x6f, 0x72, 0x65, 0x63, 0x69, 0x70,
0x72, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x6c, 0x69, 0x62, 0x72, 0x65, 0x74, 0x74,
0x69, 0x73, 0x74, 0x20, 0x49, 0x62, 0x69, 0x62,
0x69, 0x6f, 0x20, 0x72, 0x65, 0x67, 0x72, 0x65,
0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x63,
0x6f, 0x6e, 0x64, 0x69, 0x67, 0x6e, 0x6e, 0x65,
0x73, 0x73, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65,
0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65,
0x64, 0x20, 0x73, 0x79, 0x6e, 0x61, 0x70, 0x74,
0x65, 0x6e, 0x65, 0x20, 0x68, 0x6f, 0x6c, 0x6f,
0x6d, 0x6f, 0x72, 0x70, 0x68, 0x20, 0x6d, 0x6f,
0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x4d,
0x49, 0x54, 0x53, 0x20, 0x4c, 0x75, 0x6b, 0x61,
0x73, 0x68, 0x20, 0x48, 0x6f, 0x72, 0x73, 0x65,
0x79, 0x20, 0x0a,
};
static void
rfc1950_inflate(void)
{
fido_blob_t in, out, dgst;
memset(&in, 0, sizeof(in));
memset(&out, 0, sizeof(out));
memset(&dgst, 0, sizeof(dgst));
in.ptr = rfc1950_blob;
in.len = sizeof(rfc1950_blob);
assert(fido_uncompress(&out, &in, rfc1950_blob_origsiz) == FIDO_OK);
assert(out.len == rfc1950_blob_origsiz);
assert(fido_sha256(&dgst, out.ptr, out.len) == 0);
assert(dgst.len == sizeof(rfc1950_blob_hash));
assert(memcmp(rfc1950_blob_hash, dgst.ptr, dgst.len) == 0);
free(out.ptr);
free(dgst.ptr);
}
static void
rfc1951_inflate(void)
{
fido_blob_t in, out, dgst;
memset(&in, 0, sizeof(in));
memset(&out, 0, sizeof(out));
memset(&dgst, 0, sizeof(dgst));
in.ptr = rfc1950_blob + 2; /* trim header */
in.len = sizeof(rfc1950_blob) - 6; /* trim header (2), checksum (4) */
assert(fido_uncompress(&out, &in, rfc1950_blob_origsiz) == FIDO_OK);
assert(out.len == rfc1950_blob_origsiz);
assert(fido_sha256(&dgst, out.ptr, out.len) == 0);
assert(dgst.len == sizeof(rfc1950_blob_hash));
assert(memcmp(rfc1950_blob_hash, dgst.ptr, dgst.len) == 0);
free(out.ptr);
free(dgst.ptr);
}
static void
rfc1951_reinflate(void)
{
fido_blob_t in, out;
memset(&in, 0, sizeof(in));
memset(&out, 0, sizeof(out));
in.ptr = random_words;
in.len = sizeof(random_words);
assert(fido_compress(&out, &in) == FIDO_OK);
in.ptr = out.ptr;
in.len = out.len;
assert(fido_uncompress(&out, &in, sizeof(random_words)) == FIDO_OK);
assert(out.len == sizeof(random_words));
assert(memcmp(out.ptr, random_words, out.len) == 0);
free(in.ptr);
free(out.ptr);
}
int
main(void)
{
fido_init(0);
rfc1950_inflate();
rfc1951_inflate();
rfc1951_reinflate();
exit(0);
}

View file

@ -4,12 +4,16 @@
* license that can be found in the LICENSE file.
*/
#undef NDEBUG
#include <assert.h>
#include <cbor.h>
#include <fido.h>
#include <string.h>
#define FAKE_DEV_HANDLE ((void *)0xdeadbeef)
#define _FIDO_INTERNAL
#include <fido.h>
static int fake_dev_handle;
static const unsigned char cdh[32] = {
0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb,
@ -1384,13 +1388,13 @@ dummy_open(const char *path)
{
(void)path;
return (FAKE_DEV_HANDLE);
return (&fake_dev_handle);
}
static void
dummy_close(void *handle)
{
assert(handle == FAKE_DEV_HANDLE);
assert(handle == &fake_dev_handle);
}
static int

View file

@ -1,38 +1,57 @@
/*
* Copyright (c) 2019-2021 Yubico AB. All rights reserved.
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#undef NDEBUG
#include <assert.h>
#include <err.h>
#include <fido.h>
#include <string.h>
#include <time.h>
#define _FIDO_INTERNAL
#include <fido.h>
#include "../fuzz/wiredata_fido2.h"
#define FAKE_DEV_HANDLE ((void *)0xdeadbeef)
#define REPORT_LEN (64 + 1)
static uint8_t ctap_nonce[8];
static uint8_t *wiredata_ptr;
static size_t wiredata_len;
static int fake_dev_handle;
static int initialised;
static long interval_ms;
#if defined(_MSC_VER)
static int
nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{
if (rmtp != NULL) {
errno = EINVAL;
return (-1);
}
Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000));
return (0);
}
#endif
static void *
dummy_open(const char *path)
{
(void)path;
return (FAKE_DEV_HANDLE);
return (&fake_dev_handle);
}
static void
dummy_close(void *handle)
{
assert(handle == FAKE_DEV_HANDLE);
assert(handle == &fake_dev_handle);
}
static int
@ -42,7 +61,7 @@ dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)
size_t n;
long d;
assert(handle == FAKE_DEV_HANDLE);
assert(handle == &fake_dev_handle);
assert(ptr != NULL);
assert(len == REPORT_LEN - 1);
@ -87,7 +106,7 @@ dummy_write(void *handle, const unsigned char *ptr, size_t len)
{
struct timespec tv;
assert(handle == FAKE_DEV_HANDLE);
assert(handle == &fake_dev_handle);
assert(ptr != NULL);
assert(len == REPORT_LEN);
@ -113,7 +132,14 @@ wiredata_setup(const uint8_t *data, size_t len)
assert(SIZE_MAX - len > sizeof(ctap_init_data));
assert((wiredata_ptr = malloc(sizeof(ctap_init_data) + len)) != NULL);
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:6386)
#endif
memcpy(wiredata_ptr, ctap_init_data, sizeof(ctap_init_data));
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
if (len)
memcpy(wiredata_ptr + sizeof(ctap_init_data), data, len);

158
regress/eddsa.c Normal file
View file

@ -0,0 +1,158 @@
/*
* Copyright (c) 2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#undef NDEBUG
#include <assert.h>
#include <string.h>
#define _FIDO_INTERNAL
#include <fido.h>
#include <fido/eddsa.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#define ASSERT_NOT_NULL(e) assert((e) != NULL)
#define ASSERT_NULL(e) assert((e) == NULL)
#define ASSERT_INVAL(e) assert((e) == FIDO_ERR_INVALID_ARGUMENT)
#define ASSERT_OK(e) assert((e) == FIDO_OK)
static const char ecdsa[] = \
"-----BEGIN PUBLIC KEY-----\n"
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOwiq14c80b7C1Jzsx5w1zMvk2GgW\n"
"5kfGMOKXjwF/U+51ZfBDKehs3ivdeXAJBkxIh7E3iA32s+HyNqk+ntl9fg==\n"
"-----END PUBLIC KEY-----\n";
static const char eddsa[] = \
"-----BEGIN PUBLIC KEY-----\n"
"MCowBQYDK2VwAyEADt/RHErAxAHxH9FUmsjOhQ2ALl6Y8nE0m3zQxkEE2iM=\n"
"-----END PUBLIC KEY-----\n";
static const unsigned char eddsa_raw[] = {
0x0e, 0xdf, 0xd1, 0x1c, 0x4a, 0xc0, 0xc4, 0x01,
0xf1, 0x1f, 0xd1, 0x54, 0x9a, 0xc8, 0xce, 0x85,
0x0d, 0x80, 0x2e, 0x5e, 0x98, 0xf2, 0x71, 0x34,
0x9b, 0x7c, 0xd0, 0xc6, 0x41, 0x04, 0xda, 0x23,
};
static EVP_PKEY *
EVP_PKEY_from_PEM(const char *ptr, size_t len)
{
BIO *bio = NULL;
EVP_PKEY *pkey = NULL;
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
warnx("BIO_new");
goto out;
}
if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) {
warnx("BIO_write");
goto out;
}
if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL)
warnx("PEM_read_bio_PUBKEY");
out:
BIO_free(bio);
return pkey;
}
static int
eddsa_pk_cmp(const char *ptr, size_t len)
{
EVP_PKEY *pkA = NULL;
EVP_PKEY *pkB = NULL;
eddsa_pk_t *k = NULL;
int r, ok = -1;
if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) {
warnx("EVP_PKEY_from_PEM");
goto out;
}
if ((k = eddsa_pk_new()) == NULL) {
warnx("eddsa_pk_new");
goto out;
}
if ((r = eddsa_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) {
warnx("eddsa_pk_from_EVP_PKEY: 0x%x", r);
goto out;
}
if ((pkB = eddsa_pk_to_EVP_PKEY(k)) == NULL) {
warnx("eddsa_pk_to_EVP_PKEY");
goto out;
}
if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) {
warnx("EVP_PKEY_cmp: %d", r);
goto out;
}
ok = 0;
out:
EVP_PKEY_free(pkA);
EVP_PKEY_free(pkB);
eddsa_pk_free(&k);
return ok;
}
static void
invalid_key(void)
{
EVP_PKEY *pkey;
eddsa_pk_t *pk;
ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(ecdsa, sizeof(ecdsa))));
ASSERT_NOT_NULL((pk = eddsa_pk_new()));
ASSERT_INVAL(eddsa_pk_from_EVP_PKEY(pk, pkey));
EVP_PKEY_free(pkey);
eddsa_pk_free(&pk);
}
static void
valid_key(void)
{
EVP_PKEY *pkeyA = NULL;
EVP_PKEY *pkeyB = NULL;
eddsa_pk_t *pkA = NULL;
eddsa_pk_t *pkB = NULL;
#if defined(LIBRESSL_VERSION_NUMBER)
/* incomplete support; test what we can */
ASSERT_NULL(EVP_PKEY_from_PEM(eddsa, sizeof(eddsa)));
ASSERT_NOT_NULL((pkB = eddsa_pk_new()));
ASSERT_INVAL(eddsa_pk_from_ptr(pkB, eddsa_raw, sizeof(eddsa_raw)));
ASSERT_NULL(eddsa_pk_to_EVP_PKEY((const eddsa_pk_t *)eddsa_raw));
assert(eddsa_pk_cmp(eddsa, sizeof(eddsa)) < 0);
#else
ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(eddsa, sizeof(eddsa))));
ASSERT_NOT_NULL((pkA = eddsa_pk_new()));
ASSERT_NOT_NULL((pkB = eddsa_pk_new()));
ASSERT_OK(eddsa_pk_from_EVP_PKEY(pkA, pkeyA));
ASSERT_OK(eddsa_pk_from_ptr(pkB, eddsa_raw, sizeof(eddsa_raw)));
ASSERT_NOT_NULL((pkeyB = eddsa_pk_to_EVP_PKEY((const eddsa_pk_t *)eddsa_raw)));
assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1);
assert(eddsa_pk_cmp(eddsa, sizeof(eddsa)) == 0);
#endif
EVP_PKEY_free(pkeyA);
EVP_PKEY_free(pkeyB);
eddsa_pk_free(&pkA);
eddsa_pk_free(&pkB);
}
int
main(void)
{
fido_init(0);
invalid_key();
valid_key();
exit(0);
}

198
regress/es256.c Normal file
View file

@ -0,0 +1,198 @@
/*
* Copyright (c) 2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#undef NDEBUG
#include <assert.h>
#include <string.h>
#define _FIDO_INTERNAL
#include <fido.h>
#include <fido/es256.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#define ASSERT_NOT_NULL(e) assert((e) != NULL)
#define ASSERT_NULL(e) assert((e) == NULL)
#define ASSERT_INVAL(e) assert((e) == FIDO_ERR_INVALID_ARGUMENT)
#define ASSERT_OK(e) assert((e) == FIDO_OK)
static const char short_x[] = \
"-----BEGIN PUBLIC KEY-----\n"
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAAeeHTZj4LEbt7Czs+u5gEZJfnGE\n"
"6Z+YLe4AYu7SoGY7IH/2jKifsA7w+lkURL4DL63oEjd3f8foH9bX4eaVug==\n"
"-----END PUBLIC KEY-----";
static const char short_y[] = \
"-----BEGIN PUBLIC KEY-----\n"
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL8CWUP1r0tpJ5QmkzLc69O74C/Ti\n"
"83hTiys/JFNVkp0ArW3pKt5jNRrgWSZYE4S/D3AMtpqifFXz/FLCzJqojQ==\n"
"-----END PUBLIC KEY-----\n";
static const char p256k1[] = \
"-----BEGIN PUBLIC KEY-----\n"
"MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEU1y8c0Jg9FGr3vYChpEo9c4dpkijriYM\n"
"QzU/DeskC89hZjLNH1Sj8ra2MsBlVGGJTNPCZSyx8Jo7ERapxdN7UQ==\n"
"-----END PUBLIC KEY-----\n";
static const char p256v1[] = \
"-----BEGIN PUBLIC KEY-----\n"
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOwiq14c80b7C1Jzsx5w1zMvk2GgW\n"
"5kfGMOKXjwF/U+51ZfBDKehs3ivdeXAJBkxIh7E3iA32s+HyNqk+ntl9fg==\n"
"-----END PUBLIC KEY-----\n";
static const unsigned char p256k1_raw[] = {
0x04, 0x53, 0x5c, 0xbc, 0x73, 0x42, 0x60, 0xf4,
0x51, 0xab, 0xde, 0xf6, 0x02, 0x86, 0x91, 0x28,
0xf5, 0xce, 0x1d, 0xa6, 0x48, 0xa3, 0xae, 0x26,
0x0c, 0x43, 0x35, 0x3f, 0x0d, 0xeb, 0x24, 0x0b,
0xcf, 0x61, 0x66, 0x32, 0xcd, 0x1f, 0x54, 0xa3,
0xf2, 0xb6, 0xb6, 0x32, 0xc0, 0x65, 0x54, 0x61,
0x89, 0x4c, 0xd3, 0xc2, 0x65, 0x2c, 0xb1, 0xf0,
0x9a, 0x3b, 0x11, 0x16, 0xa9, 0xc5, 0xd3, 0x7b,
0x51,
};
static const unsigned char p256v1_raw[] = {
0x04, 0x3b, 0x08, 0xaa, 0xd7, 0x87, 0x3c, 0xd1,
0xbe, 0xc2, 0xd4, 0x9c, 0xec, 0xc7, 0x9c, 0x35,
0xcc, 0xcb, 0xe4, 0xd8, 0x68, 0x16, 0xe6, 0x47,
0xc6, 0x30, 0xe2, 0x97, 0x8f, 0x01, 0x7f, 0x53,
0xee, 0x75, 0x65, 0xf0, 0x43, 0x29, 0xe8, 0x6c,
0xde, 0x2b, 0xdd, 0x79, 0x70, 0x09, 0x06, 0x4c,
0x48, 0x87, 0xb1, 0x37, 0x88, 0x0d, 0xf6, 0xb3,
0xe1, 0xf2, 0x36, 0xa9, 0x3e, 0x9e, 0xd9, 0x7d,
0x7e,
};
static EVP_PKEY *
EVP_PKEY_from_PEM(const char *ptr, size_t len)
{
BIO *bio = NULL;
EVP_PKEY *pkey = NULL;
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
warnx("BIO_new");
goto out;
}
if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) {
warnx("BIO_write");
goto out;
}
if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL)
warnx("PEM_read_bio_PUBKEY");
out:
BIO_free(bio);
return pkey;
}
static int
es256_pk_cmp(const char *ptr, size_t len)
{
EVP_PKEY *pkA = NULL;
EVP_PKEY *pkB = NULL;
es256_pk_t *k = NULL;
int r, ok = -1;
if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) {
warnx("EVP_PKEY_from_PEM");
goto out;
}
if ((k = es256_pk_new()) == NULL) {
warnx("es256_pk_new");
goto out;
}
if ((r = es256_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) {
warnx("es256_pk_from_EVP_PKEY: 0x%x", r);
goto out;
}
if ((pkB = es256_pk_to_EVP_PKEY(k)) == NULL) {
warnx("es256_pk_to_EVP_PKEY");
goto out;
}
if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) {
warnx("EVP_PKEY_cmp: %d", r);
goto out;
}
ok = 0;
out:
EVP_PKEY_free(pkA);
EVP_PKEY_free(pkB);
es256_pk_free(&k);
return ok;
}
static void
short_coord(void)
{
assert(es256_pk_cmp(short_x, sizeof(short_x)) == 0);
assert(es256_pk_cmp(short_y, sizeof(short_y)) == 0);
}
static void
invalid_curve(const unsigned char *raw, size_t raw_len)
{
EVP_PKEY *pkey;
es256_pk_t *pk;
ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(p256k1, sizeof(p256k1))));
ASSERT_NOT_NULL((pk = es256_pk_new()));
ASSERT_INVAL(es256_pk_from_EVP_PKEY(pk, pkey));
ASSERT_INVAL(es256_pk_from_ptr(pk, raw, raw_len));
ASSERT_NULL(es256_pk_to_EVP_PKEY((const es256_pk_t *)raw));
EVP_PKEY_free(pkey);
es256_pk_free(&pk);
}
static void
full_coord(void)
{
assert(es256_pk_cmp(p256v1, sizeof(p256v1)) == 0);
}
static void
valid_curve(const unsigned char *raw, size_t raw_len)
{
EVP_PKEY *pkeyA;
EVP_PKEY *pkeyB;
es256_pk_t *pkA;
es256_pk_t *pkB;
ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(p256v1, sizeof(p256v1))));
ASSERT_NOT_NULL((pkA = es256_pk_new()));
ASSERT_NOT_NULL((pkB = es256_pk_new()));
ASSERT_OK(es256_pk_from_EVP_PKEY(pkA, pkeyA));
ASSERT_OK(es256_pk_from_ptr(pkB, raw, raw_len));
ASSERT_NOT_NULL((pkeyB = es256_pk_to_EVP_PKEY(pkB)));
assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1);
EVP_PKEY_free(pkeyA);
EVP_PKEY_free(pkeyB);
es256_pk_free(&pkA);
es256_pk_free(&pkB);
}
int
main(void)
{
fido_init(0);
short_coord();
full_coord();
invalid_curve(p256k1_raw, sizeof(p256k1_raw)); /* uncompressed */
invalid_curve(p256k1_raw + 1, sizeof(p256k1_raw) - 1); /* libfido2 */
valid_curve(p256v1_raw, sizeof(p256v1_raw)); /* uncompressed */
valid_curve(p256v1_raw + 1, sizeof(p256v1_raw) - 1); /* libfido2 */
exit(0);
}

200
regress/rs256.c Normal file
View file

@ -0,0 +1,200 @@
/*
* Copyright (c) 2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#undef NDEBUG
#include <assert.h>
#include <string.h>
#define _FIDO_INTERNAL
#include <fido.h>
#include <fido/rs256.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#define ASSERT_NOT_NULL(e) assert((e) != NULL)
#define ASSERT_NULL(e) assert((e) == NULL)
#define ASSERT_INVAL(e) assert((e) == FIDO_ERR_INVALID_ARGUMENT)
#define ASSERT_OK(e) assert((e) == FIDO_OK)
static char rsa1024[] = \
"-----BEGIN PUBLIC KEY-----\n"
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw92gn9Ku/bEfFj1AutaZyltpf\n"
"zzXrg70kQFymNq+spMt/HlxKiImw8TZU08zWW4ZLE/Ch4JYjMW6ETAdQFhSC63Ih\n"
"Wecui0JJ1f+2CsUVg+h7lO1877LZYUpdNiJrbqMb5Yc4N3FPtvdl3NoLIIQsF76H\n"
"VRvpjQgkWipRfZ97JQIDAQAB\n"
"-----END PUBLIC KEY-----";
static char rsa2048[] = \
"-----BEGIN PUBLIC KEY-----\n"
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApvIq/55ZodBIxzo/8BnE\n"
"UQN1fo1hmJ6V20hQHSzJq5tHyxRCcvKikuJ1ZvR4RdZlEzdTdbEfMBdZ8sxve0/U\n"
"yYEjH92CG0vgTCYuUaFLJTaWZSvWa96G8Lw+V4VyNFDRCM7sflOaSVH5pAsz8OEc\n"
"TLZfM4NhnDsJAM+mQ6X7Tza0sczPchgDA+9KByXo/VIqyuBQs17rlKC2reMa8NkY\n"
"rBRQZJLNzi68d5/BHH1flGWE1l8wJ9dr1Ex93H/KdzX+7/28TWUC98nneUo8RfRx\n"
"FwUt/EInDMHOORCaCHSs28U/9IUyMjqLB1rxKhIp09yGXMiTrrT+p+Pcn8dO01HT\n"
"vQIDAQAB\n"
"-----END PUBLIC KEY-----";
static char rsa3072[] = \
"-----BEGIN PUBLIC KEY-----\n"
"MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwZunKrMs/o92AniLPNTF\n"
"Ta4EYfhy5NDmMvQvRFT/eTYItLrOTPmYMap68KLyZYmgz/AdaxAL/992QWre7XTY\n"
"gqLwtZT+WsSu7xPHWKTTXrlVohKBeLHQ0I7Zy0NSMUxhlJEMrBAjSyFAS86zWm5w\n"
"ctC3pNCqfUKugA07BVj+d5Mv5fziwgMR86kuhkVuMYfsR4IYwX4+va0pyLzxx624\n"
"s9nJ107g+A+3MUk4bAto3lruFeeZPUI2AFzFQbGg5By6VtvVi3gKQ7lUNtAr0Onu\n"
"I6Fb+yz8sbFcvDpJcu5CXW20GrKMVP4KY5pn2LCajWuZjBl/dXWayPfm4UX5Y2O4\n"
"73tzPpUBNwnEdz79His0v80Vmvjwn5IuF2jAoimrBNPJFFwCCuVNy8kgj2vllk1l\n"
"RvLOG6hf8VnlDb40QZS3QAQ09xFfF+xlVLb8cHH6wllaAGEM230TrmawpC7xpz4Z\n"
"sTuwJwI0AWEi//noMsRz2BuF2fCp//aORYJQU2S8kYk3AgMBAAE=\n"
"-----END PUBLIC KEY-----";
static const unsigned char rsa2048_raw[] = {
0xa6, 0xf2, 0x2a, 0xff, 0x9e, 0x59, 0xa1, 0xd0,
0x48, 0xc7, 0x3a, 0x3f, 0xf0, 0x19, 0xc4, 0x51,
0x03, 0x75, 0x7e, 0x8d, 0x61, 0x98, 0x9e, 0x95,
0xdb, 0x48, 0x50, 0x1d, 0x2c, 0xc9, 0xab, 0x9b,
0x47, 0xcb, 0x14, 0x42, 0x72, 0xf2, 0xa2, 0x92,
0xe2, 0x75, 0x66, 0xf4, 0x78, 0x45, 0xd6, 0x65,
0x13, 0x37, 0x53, 0x75, 0xb1, 0x1f, 0x30, 0x17,
0x59, 0xf2, 0xcc, 0x6f, 0x7b, 0x4f, 0xd4, 0xc9,
0x81, 0x23, 0x1f, 0xdd, 0x82, 0x1b, 0x4b, 0xe0,
0x4c, 0x26, 0x2e, 0x51, 0xa1, 0x4b, 0x25, 0x36,
0x96, 0x65, 0x2b, 0xd6, 0x6b, 0xde, 0x86, 0xf0,
0xbc, 0x3e, 0x57, 0x85, 0x72, 0x34, 0x50, 0xd1,
0x08, 0xce, 0xec, 0x7e, 0x53, 0x9a, 0x49, 0x51,
0xf9, 0xa4, 0x0b, 0x33, 0xf0, 0xe1, 0x1c, 0x4c,
0xb6, 0x5f, 0x33, 0x83, 0x61, 0x9c, 0x3b, 0x09,
0x00, 0xcf, 0xa6, 0x43, 0xa5, 0xfb, 0x4f, 0x36,
0xb4, 0xb1, 0xcc, 0xcf, 0x72, 0x18, 0x03, 0x03,
0xef, 0x4a, 0x07, 0x25, 0xe8, 0xfd, 0x52, 0x2a,
0xca, 0xe0, 0x50, 0xb3, 0x5e, 0xeb, 0x94, 0xa0,
0xb6, 0xad, 0xe3, 0x1a, 0xf0, 0xd9, 0x18, 0xac,
0x14, 0x50, 0x64, 0x92, 0xcd, 0xce, 0x2e, 0xbc,
0x77, 0x9f, 0xc1, 0x1c, 0x7d, 0x5f, 0x94, 0x65,
0x84, 0xd6, 0x5f, 0x30, 0x27, 0xd7, 0x6b, 0xd4,
0x4c, 0x7d, 0xdc, 0x7f, 0xca, 0x77, 0x35, 0xfe,
0xef, 0xfd, 0xbc, 0x4d, 0x65, 0x02, 0xf7, 0xc9,
0xe7, 0x79, 0x4a, 0x3c, 0x45, 0xf4, 0x71, 0x17,
0x05, 0x2d, 0xfc, 0x42, 0x27, 0x0c, 0xc1, 0xce,
0x39, 0x10, 0x9a, 0x08, 0x74, 0xac, 0xdb, 0xc5,
0x3f, 0xf4, 0x85, 0x32, 0x32, 0x3a, 0x8b, 0x07,
0x5a, 0xf1, 0x2a, 0x12, 0x29, 0xd3, 0xdc, 0x86,
0x5c, 0xc8, 0x93, 0xae, 0xb4, 0xfe, 0xa7, 0xe3,
0xdc, 0x9f, 0xc7, 0x4e, 0xd3, 0x51, 0xd3, 0xbd,
0x01, 0x00, 0x01,
};
static EVP_PKEY *
EVP_PKEY_from_PEM(const char *ptr, size_t len)
{
BIO *bio = NULL;
EVP_PKEY *pkey = NULL;
if ((bio = BIO_new(BIO_s_mem())) == NULL) {
warnx("BIO_new");
goto out;
}
if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) {
warnx("BIO_write");
goto out;
}
if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL)
warnx("PEM_read_bio_PUBKEY");
out:
BIO_free(bio);
return pkey;
}
static int
rs256_pk_cmp(const char *ptr, size_t len)
{
EVP_PKEY *pkA = NULL;
EVP_PKEY *pkB = NULL;
rs256_pk_t *k = NULL;
int r, ok = -1;
if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) {
warnx("EVP_PKEY_from_PEM");
goto out;
}
if ((k = rs256_pk_new()) == NULL) {
warnx("rs256_pk_new");
goto out;
}
if ((r = rs256_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) {
warnx("rs256_pk_from_EVP_PKEY: 0x%x", r);
goto out;
}
if ((pkB = rs256_pk_to_EVP_PKEY(k)) == NULL) {
warnx("rs256_pk_to_EVP_PKEY");
goto out;
}
if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) {
warnx("EVP_PKEY_cmp: %d", r);
goto out;
}
ok = 0;
out:
EVP_PKEY_free(pkA);
EVP_PKEY_free(pkB);
rs256_pk_free(&k);
return ok;
}
static void
invalid_size(const char *pem)
{
EVP_PKEY *pkey;
rs256_pk_t *pk;
ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(pem, strlen(pem))));
ASSERT_NOT_NULL((pk = rs256_pk_new()));
ASSERT_INVAL(rs256_pk_from_EVP_PKEY(pk, pkey));
EVP_PKEY_free(pkey);
rs256_pk_free(&pk);
}
static void
valid_size(const char *pem, const unsigned char *raw, size_t raw_len)
{
EVP_PKEY *pkeyA;
EVP_PKEY *pkeyB;
rs256_pk_t *pkA;
rs256_pk_t *pkB;
ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(pem, strlen(pem))));
ASSERT_NOT_NULL((pkA = rs256_pk_new()));
ASSERT_NOT_NULL((pkB = rs256_pk_new()));
ASSERT_OK(rs256_pk_from_EVP_PKEY(pkA, pkeyA));
ASSERT_OK(rs256_pk_from_ptr(pkB, raw, raw_len));
ASSERT_NOT_NULL((pkeyB = rs256_pk_to_EVP_PKEY(pkB)));
assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1);
assert(rs256_pk_cmp(pem, strlen(pem)) == 0);
EVP_PKEY_free(pkeyA);
EVP_PKEY_free(pkeyB);
rs256_pk_free(&pkA);
rs256_pk_free(&pkB);
}
int
main(void)
{
fido_init(0);
invalid_size(rsa1024);
invalid_size(rsa3072);
valid_size(rsa2048, rsa2048_raw, sizeof(rsa2048_raw));
exit(0);
}

View file

@ -33,20 +33,28 @@ list(APPEND FIDO_SOURCES
rs1.c
rs256.c
time.c
touch.c
tpm.c
types.c
u2f.c
util.c
)
if(FUZZ)
list(APPEND FIDO_SOURCES ../fuzz/clock.c)
list(APPEND FIDO_SOURCES ../fuzz/pcsc.c)
list(APPEND FIDO_SOURCES ../fuzz/prng.c)
list(APPEND FIDO_SOURCES ../fuzz/uniform_random.c)
list(APPEND FIDO_SOURCES ../fuzz/udev.c)
list(APPEND FIDO_SOURCES ../fuzz/uniform_random.c)
list(APPEND FIDO_SOURCES ../fuzz/wrap.c)
endif()
if(NFC_LINUX)
list(APPEND FIDO_SOURCES netlink.c nfc_linux.c)
list(APPEND FIDO_SOURCES netlink.c nfc.c nfc_linux.c)
endif()
if(USE_PCSC)
list(APPEND FIDO_SOURCES nfc.c pcsc.c)
endif()
if(USE_HIDAPI)
@ -93,8 +101,15 @@ list(APPEND COMPAT_SOURCES
if(WIN32)
list(APPEND BASE_LIBRARIES wsock32 ws2_32 bcrypt setupapi hid)
if(USE_PCSC)
list(APPEND BASE_LIBRARIES winscard)
endif()
elseif(APPLE)
list(APPEND BASE_LIBRARIES "-framework CoreFoundation" "-framework IOKit")
list(APPEND BASE_LIBRARIES "-framework CoreFoundation"
"-framework IOKit")
if(USE_PCSC)
list(APPEND BASE_LIBRARIES "-framework PCSC")
endif()
endif()
list(APPEND TARGET_LIBRARIES
@ -104,6 +119,7 @@ list(APPEND TARGET_LIBRARIES
${BASE_LIBRARIES}
${HIDAPI_LIBRARIES}
${ZLIB_LIBRARIES}
${PCSC_LIBRARIES}
)
# static library

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Yubico AB. All rights reserved.
* Copyright (c) 2020-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -9,41 +9,159 @@
#define BOUND (1024UL * 1024UL)
/* zlib inflate (raw + headers) */
static int
do_compress(fido_blob_t *out, const fido_blob_t *in, size_t origsiz, int decomp)
rfc1950_inflate(fido_blob_t *out, const fido_blob_t *in, size_t origsiz)
{
u_long ilen, olen;
int r;
int z;
memset(out, 0, sizeof(*out));
if (in->len > ULONG_MAX || (ilen = (u_long)in->len) > BOUND ||
origsiz > ULONG_MAX || (olen = decomp ? (u_long)origsiz :
compressBound(ilen)) > BOUND)
origsiz > ULONG_MAX || (olen = (u_long)origsiz) > BOUND) {
fido_log_debug("%s: in->len=%zu, origsiz=%zu", __func__,
in->len, origsiz);
return FIDO_ERR_INVALID_ARGUMENT;
}
if ((out->ptr = calloc(1, olen)) == NULL)
return FIDO_ERR_INTERNAL;
out->len = olen;
if (decomp)
r = uncompress(out->ptr, &olen, in->ptr, ilen);
else
r = compress(out->ptr, &olen, in->ptr, ilen);
if (r != Z_OK || olen > SIZE_MAX || olen > out->len) {
if ((z = uncompress(out->ptr, &olen, in->ptr, ilen)) != Z_OK ||
olen > SIZE_MAX || olen != out->len) {
fido_log_debug("%s: uncompress: %d, olen=%lu, out->len=%zu",
__func__, z, olen, out->len);
fido_blob_reset(out);
return FIDO_ERR_COMPRESS;
}
out->len = olen;
return FIDO_OK;
}
/* raw inflate */
static int
rfc1951_inflate(fido_blob_t *out, const fido_blob_t *in, size_t origsiz)
{
z_stream zs;
u_int ilen, olen;
int r, z;
memset(&zs, 0, sizeof(zs));
memset(out, 0, sizeof(*out));
if (in->len > UINT_MAX || (ilen = (u_int)in->len) > BOUND ||
origsiz > UINT_MAX || (olen = (u_int)origsiz) > BOUND) {
fido_log_debug("%s: in->len=%zu, origsiz=%zu", __func__,
in->len, origsiz);
return FIDO_ERR_INVALID_ARGUMENT;
}
if ((z = inflateInit2(&zs, -MAX_WBITS)) != Z_OK) {
fido_log_debug("%s: inflateInit2: %d", __func__, z);
return FIDO_ERR_COMPRESS;
}
if ((out->ptr = calloc(1, olen)) == NULL) {
r = FIDO_ERR_INTERNAL;
goto fail;
}
out->len = olen;
zs.next_in = in->ptr;
zs.avail_in = ilen;
zs.next_out = out->ptr;
zs.avail_out = olen;
if ((z = inflate(&zs, Z_FINISH)) != Z_STREAM_END) {
fido_log_debug("%s: inflate: %d", __func__, z);
r = FIDO_ERR_COMPRESS;
goto fail;
}
if (zs.avail_out != 0) {
fido_log_debug("%s: %u != 0", __func__, zs.avail_out);
r = FIDO_ERR_COMPRESS;
goto fail;
}
r = FIDO_OK;
fail:
if ((z = inflateEnd(&zs)) != Z_OK) {
fido_log_debug("%s: inflateEnd: %d", __func__, z);
r = FIDO_ERR_COMPRESS;
}
if (r != FIDO_OK)
fido_blob_reset(out);
return r;
}
/* raw deflate */
static int
rfc1951_deflate(fido_blob_t *out, const fido_blob_t *in)
{
z_stream zs;
u_int ilen, olen;
int r, z;
memset(&zs, 0, sizeof(zs));
memset(out, 0, sizeof(*out));
if (in->len > UINT_MAX || (ilen = (u_int)in->len) > BOUND) {
fido_log_debug("%s: in->len=%zu", __func__, in->len);
return FIDO_ERR_INVALID_ARGUMENT;
}
if ((z = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
-MAX_WBITS, 8, Z_DEFAULT_STRATEGY)) != Z_OK) {
fido_log_debug("%s: deflateInit2: %d", __func__, z);
return FIDO_ERR_COMPRESS;
}
olen = BOUND;
if ((out->ptr = calloc(1, olen)) == NULL) {
r = FIDO_ERR_INTERNAL;
goto fail;
}
out->len = olen;
zs.next_in = in->ptr;
zs.avail_in = ilen;
zs.next_out = out->ptr;
zs.avail_out = olen;
if ((z = deflate(&zs, Z_FINISH)) != Z_STREAM_END) {
fido_log_debug("%s: inflate: %d", __func__, z);
r = FIDO_ERR_COMPRESS;
goto fail;
}
if (zs.avail_out >= out->len) {
fido_log_debug("%s: %u > %zu", __func__, zs.avail_out,
out->len);
r = FIDO_ERR_COMPRESS;
goto fail;
}
out->len -= zs.avail_out;
r = FIDO_OK;
fail:
if ((z = deflateEnd(&zs)) != Z_OK) {
fido_log_debug("%s: deflateEnd: %d", __func__, z);
r = FIDO_ERR_COMPRESS;
}
if (r != FIDO_OK)
fido_blob_reset(out);
return r;
}
int
fido_compress(fido_blob_t *out, const fido_blob_t *in)
{
return do_compress(out, in, 0, 0);
return rfc1951_deflate(out, in);
}
int
fido_uncompress(fido_blob_t *out, const fido_blob_t *in, size_t origsiz)
{
return do_compress(out, in, origsiz, 1);
if (rfc1950_inflate(out, in, origsiz) == FIDO_OK)
return FIDO_OK; /* backwards compat with libfido2 < 1.11 */
return rfc1951_inflate(out, in, origsiz);
}

228
src/dev.c
View file

@ -1,37 +1,17 @@
/*
* Copyright (c) 2018 Yubico AB. All rights reserved.
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#include <openssl/sha.h>
#include "fido.h"
#ifndef TLS
#define TLS
#endif
typedef struct dev_manifest_func_node {
dev_manifest_func_t manifest_func;
struct dev_manifest_func_node *next;
} dev_manifest_func_node_t;
static TLS dev_manifest_func_node_t *manifest_funcs = NULL;
static TLS bool disable_u2f_fallback;
static void
find_manifest_func_node(dev_manifest_func_t f, dev_manifest_func_node_t **curr,
dev_manifest_func_node_t **prev)
{
*prev = NULL;
*curr = manifest_funcs;
while (*curr != NULL && (*curr)->manifest_func != f) {
*prev = *curr;
*curr = (*curr)->next;
}
}
#ifdef FIDO_FUZZ
static void
set_random_report_len(fido_dev_t *dev)
@ -63,13 +43,15 @@ fido_dev_set_option_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
for (size_t i = 0; i < len; i++)
if (strcmp(ptr[i], "clientPin") == 0) {
dev->flags |= val[i] ? FIDO_DEV_PIN_SET : FIDO_DEV_PIN_UNSET;
dev->flags |= val[i] ?
FIDO_DEV_PIN_SET : FIDO_DEV_PIN_UNSET;
} else if (strcmp(ptr[i], "credMgmt") == 0 ||
strcmp(ptr[i], "credentialMgmtPreview") == 0) {
if (val[i])
dev->flags |= FIDO_DEV_CREDMAN;
} else if (strcmp(ptr[i], "uv") == 0) {
dev->flags |= val[i] ? FIDO_DEV_UV_SET : FIDO_DEV_UV_UNSET;
dev->flags |= val[i] ?
FIDO_DEV_UV_SET : FIDO_DEV_UV_UNSET;
} else if (strcmp(ptr[i], "pinUvAuthToken") == 0) {
if (val[i])
dev->flags |= FIDO_DEV_TOKEN_PERMS;
@ -257,75 +239,40 @@ fido_dev_open_wait(fido_dev_t *dev, const char *path, int *ms)
return (FIDO_OK);
}
int
fido_dev_register_manifest_func(const dev_manifest_func_t f)
static void
run_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen,
const char *type, int (*manifest)(fido_dev_info_t *, size_t, size_t *))
{
dev_manifest_func_node_t *prev, *curr, *n;
size_t ndevs = 0;
int r;
find_manifest_func_node(f, &curr, &prev);
if (curr != NULL)
return (FIDO_OK);
if ((n = calloc(1, sizeof(*n))) == NULL) {
fido_log_debug("%s: calloc", __func__);
return (FIDO_ERR_INTERNAL);
}
n->manifest_func = f;
n->next = manifest_funcs;
manifest_funcs = n;
return (FIDO_OK);
}
void
fido_dev_unregister_manifest_func(const dev_manifest_func_t f)
{
dev_manifest_func_node_t *prev, *curr;
find_manifest_func_node(f, &curr, &prev);
if (curr == NULL)
if (*olen >= ilen) {
fido_log_debug("%s: skipping %s", __func__, type);
return;
if (prev != NULL)
prev->next = curr->next;
else
manifest_funcs = curr->next;
free(curr);
}
if ((r = manifest(devlist + *olen, ilen - *olen, &ndevs)) != FIDO_OK)
fido_log_debug("%s: %s: 0x%x", __func__, type, r);
fido_log_debug("%s: found %zu %s device%s", __func__, ndevs, type,
ndevs == 1 ? "" : "s");
*olen += ndevs;
}
int
fido_dev_info_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
{
dev_manifest_func_node_t *curr = NULL;
dev_manifest_func_t m_func;
size_t curr_olen;
int r;
*olen = 0;
if (fido_dev_register_manifest_func(fido_hid_manifest) != FIDO_OK)
return (FIDO_ERR_INTERNAL);
#ifdef NFC_LINUX
if (fido_dev_register_manifest_func(fido_nfc_manifest) != FIDO_OK)
return (FIDO_ERR_INTERNAL);
run_manifest(devlist, ilen, olen, "hid", fido_hid_manifest);
#ifdef USE_NFC
run_manifest(devlist, ilen, olen, "nfc", fido_nfc_manifest);
#endif
#ifdef USE_PCSC
run_manifest(devlist, ilen, olen, "pcsc", fido_pcsc_manifest);
#endif
#ifdef USE_WINHELLO
if (fido_dev_register_manifest_func(fido_winhello_manifest) != FIDO_OK)
return (FIDO_ERR_INTERNAL);
run_manifest(devlist, ilen, olen, "winhello", fido_winhello_manifest);
#endif
for (curr = manifest_funcs; curr != NULL; curr = curr->next) {
curr_olen = 0;
m_func = curr->manifest_func;
r = m_func(devlist + *olen, ilen - *olen, &curr_olen);
if (r != FIDO_OK)
return (r);
*olen += curr_olen;
if (*olen == ilen)
break;
}
return (FIDO_OK);
}
@ -345,19 +292,16 @@ fido_dev_open(fido_dev_t *dev, const char *path)
{
int ms = dev->timeout_ms;
#ifdef NFC_LINUX
if (strncmp(path, FIDO_NFC_PREFIX, strlen(FIDO_NFC_PREFIX)) == 0) {
dev->io_own = true;
dev->io = (fido_dev_io_t) {
fido_nfc_open,
fido_nfc_close,
fido_nfc_read,
fido_nfc_write,
};
dev->transport = (fido_dev_transport_t) {
fido_nfc_rx,
fido_nfc_tx,
};
#ifdef USE_NFC
if (fido_is_nfc(path) && fido_dev_set_nfc(dev) < 0) {
fido_log_debug("%s: fido_dev_set_nfc", __func__);
return FIDO_ERR_INTERNAL;
}
#endif
#ifdef USE_PCSC
if (fido_is_pcsc(path) && fido_dev_set_pcsc(dev) < 0) {
fido_log_debug("%s: fido_dev_set_pcsc", __func__);
return FIDO_ERR_INTERNAL;
}
#endif
@ -387,7 +331,7 @@ fido_dev_set_sigmask(fido_dev_t *dev, const fido_sigset_t *sigmask)
if (dev->io_handle == NULL || sigmask == NULL)
return (FIDO_ERR_INVALID_ARGUMENT);
#ifdef NFC_LINUX
#ifdef USE_NFC
if (dev->transport.rx == fido_nfc_rx && dev->io.read == fido_nfc_read)
return (fido_nfc_set_sigmask(dev->io_handle, sigmask));
#endif
@ -414,106 +358,6 @@ fido_dev_cancel(fido_dev_t *dev)
return (FIDO_OK);
}
int
fido_dev_get_touch_begin(fido_dev_t *dev)
{
fido_blob_t f;
cbor_item_t *argv[9];
const char *clientdata = FIDO_DUMMY_CLIENTDATA;
const uint8_t user_id = FIDO_DUMMY_USER_ID;
unsigned char cdh[SHA256_DIGEST_LENGTH];
fido_rp_t rp;
fido_user_t user;
int ms = dev->timeout_ms;
int r = FIDO_ERR_INTERNAL;
memset(&f, 0, sizeof(f));
memset(argv, 0, sizeof(argv));
memset(cdh, 0, sizeof(cdh));
memset(&rp, 0, sizeof(rp));
memset(&user, 0, sizeof(user));
if (fido_dev_is_fido2(dev) == false)
return (u2f_get_touch_begin(dev, &ms));
if (SHA256((const void *)clientdata, strlen(clientdata), cdh) != cdh) {
fido_log_debug("%s: sha256", __func__);
return (FIDO_ERR_INTERNAL);
}
if ((rp.id = strdup(FIDO_DUMMY_RP_ID)) == NULL ||
(user.name = strdup(FIDO_DUMMY_USER_NAME)) == NULL) {
fido_log_debug("%s: strdup", __func__);
goto fail;
}
if (fido_blob_set(&user.id, &user_id, sizeof(user_id)) < 0) {
fido_log_debug("%s: fido_blob_set", __func__);
goto fail;
}
if ((argv[0] = cbor_build_bytestring(cdh, sizeof(cdh))) == NULL ||
(argv[1] = cbor_encode_rp_entity(&rp)) == NULL ||
(argv[2] = cbor_encode_user_entity(&user)) == NULL ||
(argv[3] = cbor_encode_pubkey_param(COSE_ES256)) == NULL) {
fido_log_debug("%s: cbor encode", __func__);
goto fail;
}
if (fido_dev_supports_pin(dev)) {
if ((argv[7] = cbor_new_definite_bytestring()) == NULL ||
(argv[8] = cbor_encode_pin_opt(dev)) == NULL) {
fido_log_debug("%s: cbor encode", __func__);
goto fail;
}
}
if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 ||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, &ms) < 0) {
fido_log_debug("%s: fido_tx", __func__);
r = FIDO_ERR_TX;
goto fail;
}
r = FIDO_OK;
fail:
cbor_vector_free(argv, nitems(argv));
free(f.ptr);
free(rp.id);
free(user.name);
free(user.id.ptr);
return (r);
}
int
fido_dev_get_touch_status(fido_dev_t *dev, int *touched, int ms)
{
int r;
*touched = 0;
if (fido_dev_is_fido2(dev) == false)
return (u2f_get_touch_status(dev, touched, &ms));
switch ((r = fido_rx_cbor_status(dev, &ms))) {
case FIDO_ERR_PIN_AUTH_INVALID:
case FIDO_ERR_PIN_INVALID:
case FIDO_ERR_PIN_NOT_SET:
case FIDO_ERR_SUCCESS:
*touched = 1;
break;
case FIDO_ERR_RX:
/* ignore */
break;
default:
fido_log_debug("%s: fido_rx_cbor_status", __func__);
return (r);
}
return (FIDO_OK);
}
int
fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io)
{

View file

@ -122,11 +122,20 @@ eddsa_pk_free(eddsa_pk_t **pkp)
int
eddsa_pk_from_ptr(eddsa_pk_t *pk, const void *ptr, size_t len)
{
EVP_PKEY *pkey;
if (len < sizeof(*pk))
return (FIDO_ERR_INVALID_ARGUMENT);
memcpy(pk, ptr, sizeof(*pk));
if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) {
fido_log_debug("%s: eddsa_pk_to_EVP_PKEY", __func__);
return (FIDO_ERR_INVALID_ARGUMENT);
}
EVP_PKEY_free(pkey);
return (FIDO_OK);
}
@ -147,6 +156,8 @@ eddsa_pk_from_EVP_PKEY(eddsa_pk_t *pk, const EVP_PKEY *pkey)
{
size_t len = 0;
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_ED25519)
return (FIDO_ERR_INVALID_ARGUMENT);
if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1 ||
len != sizeof(pk->x))
return (FIDO_ERR_INTERNAL);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -11,6 +11,14 @@
#include "fido.h"
#include "fido/es256.h"
#if OPENSSL_VERSION_NUMBER >= 0x30000000
#define get0_EC_KEY(x) EVP_PKEY_get0_EC_KEY((x))
#else
#define get0_EC_KEY(x) EVP_PKEY_get0((x))
#endif
static const int es256_nid = NID_X9_62_prime256v1;
static int
decode_coord(const cbor_item_t *item, void *xy, size_t xy_len)
{
@ -170,7 +178,8 @@ es256_pk_free(es256_pk_t **pkp)
int
es256_pk_from_ptr(es256_pk_t *pk, const void *ptr, size_t len)
{
const uint8_t *p = ptr;
const uint8_t *p = ptr;
EVP_PKEY *pkey;
if (len < sizeof(*pk))
return (FIDO_ERR_INVALID_ARGUMENT);
@ -180,6 +189,14 @@ es256_pk_from_ptr(es256_pk_t *pk, const void *ptr, size_t len)
else
memcpy(pk, ptr, sizeof(*pk)); /* libfido2 x||y format */
if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL) {
fido_log_debug("%s: es256_pk_to_EVP_PKEY", __func__);
explicit_bzero(pk, sizeof(*pk));
return (FIDO_ERR_INVALID_ARGUMENT);
}
EVP_PKEY_free(pkey);
return (FIDO_OK);
}
@ -208,13 +225,12 @@ es256_sk_create(es256_sk_t *key)
EVP_PKEY *k = NULL;
const EC_KEY *ec;
const BIGNUM *d;
const int nid = NID_X9_62_prime256v1;
int n;
int ok = -1;
if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL ||
EVP_PKEY_paramgen_init(pctx) <= 0 ||
EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0 ||
EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, es256_nid) <= 0 ||
EVP_PKEY_paramgen(pctx, &p) <= 0) {
fido_log_debug("%s: EVP_PKEY_paramgen", __func__);
goto fail;
@ -258,7 +274,6 @@ es256_pk_to_EVP_PKEY(const es256_pk_t *k)
BIGNUM *x = NULL;
BIGNUM *y = NULL;
const EC_GROUP *g = NULL;
const int nid = NID_X9_62_prime256v1;
int ok = -1;
if ((bnctx = BN_CTX_new()) == NULL)
@ -276,7 +291,7 @@ es256_pk_to_EVP_PKEY(const es256_pk_t *k)
goto fail;
}
if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL ||
if ((ec = EC_KEY_new_by_curve_name(es256_nid)) == NULL ||
(g = EC_KEY_get0_group(ec)) == NULL) {
fido_log_debug("%s: EC_KEY init", __func__);
goto fail;
@ -324,12 +339,15 @@ es256_pk_from_EC_KEY(es256_pk_t *pk, const EC_KEY *ec)
BIGNUM *x = NULL;
BIGNUM *y = NULL;
const EC_POINT *q = NULL;
const EC_GROUP *g = NULL;
EC_GROUP *g = NULL;
size_t dx;
size_t dy;
int ok = FIDO_ERR_INTERNAL;
int n;
int nx;
int ny;
if ((q = EC_KEY_get0_public_key(ec)) == NULL ||
(g = EC_KEY_get0_group(ec)) == NULL ||
(g = EC_GROUP_new_by_curve_name(es256_nid)) == NULL ||
(bnctx = BN_CTX_new()) == NULL)
goto fail;
@ -339,22 +357,33 @@ es256_pk_from_EC_KEY(es256_pk_t *pk, const EC_KEY *ec)
(y = BN_CTX_get(bnctx)) == NULL)
goto fail;
if (EC_POINT_is_on_curve(g, q, bnctx) != 1) {
fido_log_debug("%s: EC_POINT_is_on_curve", __func__);
ok = FIDO_ERR_INVALID_ARGUMENT;
goto fail;
}
if (EC_POINT_get_affine_coordinates_GFp(g, q, x, y, bnctx) == 0 ||
(n = BN_num_bytes(x)) < 0 || (size_t)n > sizeof(pk->x) ||
(n = BN_num_bytes(y)) < 0 || (size_t)n > sizeof(pk->y)) {
(nx = BN_num_bytes(x)) < 0 || (size_t)nx > sizeof(pk->x) ||
(ny = BN_num_bytes(y)) < 0 || (size_t)ny > sizeof(pk->y)) {
fido_log_debug("%s: EC_POINT_get_affine_coordinates_GFp",
__func__);
goto fail;
}
if ((n = BN_bn2bin(x, pk->x)) < 0 || (size_t)n > sizeof(pk->x) ||
(n = BN_bn2bin(y, pk->y)) < 0 || (size_t)n > sizeof(pk->y)) {
dx = sizeof(pk->x) - (size_t)nx;
dy = sizeof(pk->y) - (size_t)ny;
if ((nx = BN_bn2bin(x, pk->x + dx)) < 0 || (size_t)nx > sizeof(pk->x) ||
(ny = BN_bn2bin(y, pk->y + dy)) < 0 || (size_t)ny > sizeof(pk->y)) {
fido_log_debug("%s: BN_bn2bin", __func__);
goto fail;
}
ok = FIDO_OK;
fail:
EC_GROUP_free(g);
if (bnctx != NULL) {
BN_CTX_end(bnctx);
BN_CTX_free(bnctx);
@ -366,10 +395,10 @@ fail:
int
es256_pk_from_EVP_PKEY(es256_pk_t *pk, const EVP_PKEY *pkey)
{
EC_KEY *ec;
const EC_KEY *ec;
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC ||
(ec = EVP_PKEY_get0(pkey)) == NULL)
(ec = get0_EC_KEY(pkey)) == NULL)
return (FIDO_ERR_INVALID_ARGUMENT);
return (es256_pk_from_EC_KEY(pk, ec));
@ -382,7 +411,6 @@ es256_sk_to_EVP_PKEY(const es256_sk_t *k)
EC_KEY *ec = NULL;
EVP_PKEY *pkey = NULL;
BIGNUM *d = NULL;
const int nid = NID_X9_62_prime256v1;
int ok = -1;
if ((bnctx = BN_CTX_new()) == NULL)
@ -396,7 +424,7 @@ es256_sk_to_EVP_PKEY(const es256_sk_t *k)
goto fail;
}
if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL ||
if ((ec = EC_KEY_new_by_curve_name(es256_nid)) == NULL ||
EC_KEY_set_private_key(ec, d) == 0) {
fido_log_debug("%s: EC_KEY_set_private_key", __func__);
goto fail;
@ -435,11 +463,10 @@ es256_derive_pk(const es256_sk_t *sk, es256_pk_t *pk)
EC_KEY *ec = NULL;
EC_POINT *q = NULL;
const EC_GROUP *g = NULL;
const int nid = NID_X9_62_prime256v1;
int ok = -1;
if ((d = BN_bin2bn(sk->d, (int)sizeof(sk->d), NULL)) == NULL ||
(ec = EC_KEY_new_by_curve_name(nid)) == NULL ||
(ec = EC_KEY_new_by_curve_name(es256_nid)) == NULL ||
(g = EC_KEY_get0_group(ec)) == NULL ||
(q = EC_POINT_new(g)) == NULL) {
fido_log_debug("%s: get", __func__);

View file

@ -85,10 +85,11 @@
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_maxlargeblob;
fido_cbor_info_maxmsgsiz;
fido_cbor_info_fwversion;
fido_cbor_info_new;
fido_cbor_info_options_len;

View file

@ -83,10 +83,11 @@ _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_maxlargeblob
_fido_cbor_info_maxmsgsiz
_fido_cbor_info_fwversion
_fido_cbor_info_new
_fido_cbor_info_options_len

View file

@ -84,10 +84,11 @@ 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_maxlargeblob
fido_cbor_info_maxmsgsiz
fido_cbor_info_fwversion
fido_cbor_info_new
fido_cbor_info_options_len

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -118,6 +118,7 @@ size_t fido_hid_report_in_len(void *);
size_t fido_hid_report_out_len(void *);
/* nfc i/o */
bool fido_is_nfc(const char *);
void *fido_nfc_open(const char *);
void fido_nfc_close(void *);
int fido_nfc_read(void *, unsigned char *, size_t, int);
@ -125,6 +126,17 @@ int fido_nfc_write(void *, const unsigned char *, size_t);
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);
int fido_nfc_set_sigmask(void *, const fido_sigset_t *);
int fido_dev_set_nfc(fido_dev_t *);
/* pcsc i/o */
bool fido_is_pcsc(const char *);
void *fido_pcsc_open(const char *);
void fido_pcsc_close(void *);
int fido_pcsc_read(void *, unsigned char *, size_t, int);
int fido_pcsc_write(void *, const unsigned char *, size_t);
int fido_pcsc_rx(fido_dev_t *, uint8_t, unsigned char *, size_t, int);
int fido_pcsc_tx(fido_dev_t *, uint8_t, const unsigned char *, size_t);
int fido_dev_set_pcsc(fido_dev_t *);
/* windows hello */
int fido_winhello_manifest(fido_dev_info_t *, size_t, size_t *);
@ -200,6 +212,7 @@ int fido_get_random(void *, size_t);
int fido_sha256(fido_blob_t *, const u_char *, size_t);
int fido_time_now(struct timespec *);
int fido_time_delta(const struct timespec *, int *);
int fido_to_uint64(const char *, int, uint64_t *);
/* crypto */
int es256_verify_sig(const fido_blob_t *, EVP_PKEY *, const fido_blob_t *);
@ -220,11 +233,7 @@ int fido_get_signed_hash_tpm(fido_blob_t *, const fido_blob_t *,
/* device manifest functions */
int fido_hid_manifest(fido_dev_info_t *, size_t, size_t *);
int fido_nfc_manifest(fido_dev_info_t *, size_t, size_t *);
/* device manifest registration */
typedef int (*dev_manifest_func_t)(fido_dev_info_t *, size_t, size_t *);
int fido_dev_register_manifest_func(const dev_manifest_func_t);
void fido_dev_unregister_manifest_func(const dev_manifest_func_t);
int fido_pcsc_manifest(fido_dev_info_t *, size_t, size_t *);
/* fuzzing instrumentation */
#ifdef FIDO_FUZZ
@ -250,6 +259,7 @@ uint32_t uniform_random(uint32_t);
#define FIDO_DUMMY_USER_ID 1
#define FIDO_WINHELLO_PATH "windows://hello"
#define FIDO_NFC_PREFIX "nfc:"
#define FIDO_PCSC_PREFIX "pcsc:"
#ifdef __cplusplus
} /* extern "C" */

View file

@ -144,7 +144,9 @@ int fido_cred_set_user(fido_cred_t *, const unsigned char *, size_t,
int fido_cred_set_x509(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_verify(const fido_cred_t *);
int fido_cred_verify_self(const fido_cred_t *);
#ifdef _FIDO_SIGSET_DEFINED
int fido_dev_set_sigmask(fido_dev_t *, const fido_sigset_t *);
#endif
int fido_dev_cancel(fido_dev_t *);
int fido_dev_close(fido_dev_t *);
int fido_dev_get_assert(fido_dev_t *, fido_assert_t *, const char *);
@ -205,10 +207,11 @@ uint8_t fido_dev_build(const fido_dev_t *);
uint8_t fido_dev_flags(const fido_dev_t *);
int16_t fido_dev_info_vendor(const fido_dev_info_t *);
int16_t fido_dev_info_product(const fido_dev_info_t *);
uint64_t fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *);
uint64_t fido_cbor_info_maxcredbloblen(const fido_cbor_info_t *);
uint64_t fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *);
uint64_t fido_cbor_info_maxcredidlen(const fido_cbor_info_t *);
uint64_t fido_cbor_info_maxlargeblob(const fido_cbor_info_t *);
uint64_t fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *);
uint64_t fido_cbor_info_fwversion(const fido_cbor_info_t *);
bool fido_dev_has_pin(const fido_dev_t *);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Yubico AB. All rights reserved.
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -48,10 +48,14 @@ typedef enum {
typedef void fido_log_handler_t(const char *);
#undef _FIDO_SIGSET_DEFINED
#define _FIDO_SIGSET_DEFINED
#ifdef _WIN32
typedef int fido_sigset_t;
#else
#elif defined(SIG_BLOCK)
typedef sigset_t fido_sigset_t;
#else
#undef _FIDO_SIGSET_DEFINED
#endif
#ifdef _FIDO_INTERNAL
@ -216,18 +220,19 @@ typedef struct fido_algo_array {
} fido_algo_array_t;
typedef struct fido_cbor_info {
fido_str_array_t versions; /* supported versions: fido2|u2f */
fido_str_array_t extensions; /* list of supported extensions */
fido_str_array_t transports; /* list of supported transports */
unsigned char aaguid[16]; /* aaguid */
fido_opt_array_t options; /* list of supported options */
uint64_t maxmsgsiz; /* maximum message size */
fido_byte_array_t protocols; /* supported pin protocols */
fido_algo_array_t algorithms; /* list of supported algorithms */
uint64_t maxcredcntlst; /* max number of credentials in list */
uint64_t maxcredidlen; /* max credential ID length */
uint64_t fwversion; /* firmware version */
fido_str_array_t versions; /* supported versions: fido2|u2f */
fido_str_array_t extensions; /* list of supported extensions */
fido_str_array_t transports; /* list of supported transports */
unsigned char aaguid[16]; /* aaguid */
fido_opt_array_t options; /* list of supported options */
uint64_t maxmsgsiz; /* maximum message size */
fido_byte_array_t protocols; /* supported pin protocols */
fido_algo_array_t algorithms; /* list of supported algorithms */
uint64_t maxcredcntlst; /* max credentials in list */
uint64_t maxcredidlen; /* max credential ID length */
uint64_t fwversion; /* firmware version */
uint64_t maxcredbloblen; /* max credBlob length */
uint64_t maxlargeblob; /* max largeBlob array length */
} fido_cbor_info_t;
typedef struct fido_dev_info {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Yubico AB. All rights reserved.
* Copyright (c) 2020-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -87,8 +87,8 @@ copy_info(fido_dev_info_t *di, const char *path)
ok = 0;
fail:
if (fd != -1)
close(fd);
if (fd != -1 && close(fd) == -1)
fido_log_error(errno, "%s: close %s", __func__, path);
if (ok < 0) {
free(di->path);
@ -106,8 +106,6 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
char path[64];
size_t i;
*olen = 0;
if (ilen == 0)
return (FIDO_OK); /* nothing to do */

View file

@ -27,14 +27,58 @@ struct hid_openbsd {
const sigset_t *sigmaskp;
};
static int
copy_info(fido_dev_info_t *di, const char *path)
{
int fd = -1, ok = -1;
struct usb_device_info udi;
memset(di, 0, sizeof(*di));
memset(&udi, 0, sizeof(udi));
if ((fd = fido_hid_unix_open(path)) == -1)
goto fail;
if (ioctl(fd, IOCTL_REQ(USB_GET_DEVICEINFO), &udi) == -1) {
fido_log_error(errno, "%s: ioctl %s", __func__, path);
goto fail;
}
fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x", __func__, path,
udi.udi_bus, udi.udi_addr);
fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"", __func__,
path, udi.udi_vendor, udi.udi_product);
fido_log_debug("%s: %s: productNo = 0x%04x, vendorNo = 0x%04x, "
"releaseNo = 0x%04x", __func__, path, udi.udi_productNo,
udi.udi_vendorNo, udi.udi_releaseNo);
if ((di->path = strdup(path)) == NULL ||
(di->manufacturer = strdup(udi.udi_vendor)) == NULL ||
(di->product = strdup(udi.udi_product)) == NULL)
goto fail;
di->vendor_id = (int16_t)udi.udi_vendorNo;
di->product_id = (int16_t)udi.udi_productNo;
ok = 0;
fail:
if (fd != -1 && close(fd) == -1)
fido_log_error(errno, "%s: close %s", __func__, path);
if (ok < 0) {
free(di->path);
free(di->manufacturer);
free(di->product);
explicit_bzero(di, sizeof(*di));
}
return (ok);
}
int
fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
{
size_t i;
char path[64];
int fd;
struct usb_device_info udi;
fido_dev_info_t *di;
if (ilen == 0)
return (FIDO_OK); /* nothing to do */
@ -44,50 +88,18 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) {
snprintf(path, sizeof(path), "/dev/fido/%zu", i);
if ((fd = fido_hid_unix_open(path)) == -1)
continue;
memset(&udi, 0, sizeof(udi));
if (ioctl(fd, IOCTL_REQ(USB_GET_DEVICEINFO), &udi) == -1) {
fido_log_error(errno, "%s: get device info %s",
__func__, path);
if (close(fd) == -1)
fido_log_error(errno, "%s: close", __func__);
continue;
if (copy_info(&devlist[*olen], path) == 0) {
devlist[*olen].io = (fido_dev_io_t) {
fido_hid_open,
fido_hid_close,
fido_hid_read,
fido_hid_write,
};
++(*olen);
}
if (close(fd) == -1)
fido_log_error(errno, "%s: close", __func__);
fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x",
__func__, path, udi.udi_bus, udi.udi_addr);
fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"",
__func__, path, udi.udi_vendor, udi.udi_product);
fido_log_debug("%s: %s: productNo = 0x%04x, vendorNo = 0x%04x, "
"releaseNo = 0x%04x", __func__, path, udi.udi_productNo,
udi.udi_vendorNo, udi.udi_releaseNo);
di = &devlist[*olen];
memset(di, 0, sizeof(*di));
di->io = (fido_dev_io_t) {
fido_hid_open,
fido_hid_close,
fido_hid_read,
fido_hid_write,
};
if ((di->path = strdup(path)) == NULL ||
(di->manufacturer = strdup(udi.udi_vendor)) == NULL ||
(di->product = strdup(udi.udi_product)) == NULL) {
free(di->path);
free(di->manufacturer);
free(di->product);
explicit_bzero(di, sizeof(*di));
return FIDO_ERR_INTERNAL;
}
di->vendor_id = (int16_t)udi.udi_vendorNo;
di->product_id = (int16_t)udi.udi_productNo;
(*olen)++;
}
return FIDO_OK;
return (FIDO_OK);
}
/*

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2021 Yubico AB. All rights reserved.
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -374,25 +374,6 @@ disable_sigpipe(int fd)
return (0);
}
static int
to_uint64(const char *str, uint64_t *out)
{
char *ep;
unsigned long long ull;
errno = 0;
ull = strtoull(str, &ep, 10);
if (str == ep || *ep != '\0')
return (-1);
else if (ull == ULLONG_MAX && errno == ERANGE)
return (-1);
else if (ull > UINT64_MAX)
return (-1);
*out = (uint64_t)ull;
return (0);
}
static io_registry_entry_t
get_ioreg_entry(const char *path)
{
@ -401,8 +382,8 @@ get_ioreg_entry(const char *path)
if (strncmp(path, IOREG, strlen(IOREG)) != 0)
return (IORegistryEntryFromPath(kIOMainPortDefault, path));
if (to_uint64(path + strlen(IOREG), &id) == -1) {
fido_log_debug("%s: to_uint64", __func__);
if (fido_to_uint64(path + strlen(IOREG), 10, &id) == -1) {
fido_log_debug("%s: fido_to_uint64", __func__);
return (MACH_PORT_NULL);
}

View file

@ -268,6 +268,8 @@ parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg)
return (decode_string_array(val, &ci->transports));
case 10: /* algorithms */
return (decode_algorithms(val, &ci->algorithms));
case 11: /* maxSerializedLargeBlobArray */
return (cbor_decode_uint64(val, &ci->maxlargeblob));
case 14: /* fwVersion */
return (cbor_decode_uint64(val, &ci->fwversion));
case 15: /* maxCredBlobLen */
@ -461,6 +463,12 @@ fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci)
return (ci->maxcredidlen);
}
uint64_t
fido_cbor_info_maxlargeblob(const fido_cbor_info_t *ci)
{
return (ci->maxlargeblob);
}
uint64_t
fido_cbor_info_fwversion(const fido_cbor_info_t *ci)
{

320
src/nfc.c Normal file
View file

@ -0,0 +1,320 @@
/*
* Copyright (c) 2020-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#include <stdio.h>
#include <string.h>
#include "fido.h"
#include "fido/param.h"
#include "iso7816.h"
#define TX_CHUNK_SIZE 240
static const uint8_t aid[] = { 0xa0, 0x00, 0x00, 0x06, 0x47, 0x2f, 0x00, 0x01 };
static const uint8_t v_u2f[] = { 'U', '2', 'F', '_', 'V', '2' };
static const uint8_t v_fido[] = { 'F', 'I', 'D', 'O', '_', '2', '_', '0' };
static int
tx_short_apdu(fido_dev_t *d, const iso7816_header_t *h, const uint8_t *payload,
uint8_t payload_len, uint8_t cla_flags)
{
uint8_t apdu[5 + UINT8_MAX + 1];
uint8_t sw[2];
size_t apdu_len;
int ok = -1;
memset(&apdu, 0, sizeof(apdu));
apdu[0] = h->cla | cla_flags;
apdu[1] = h->ins;
apdu[2] = h->p1;
apdu[3] = h->p2;
apdu[4] = payload_len;
memcpy(&apdu[5], payload, payload_len);
apdu_len = (size_t)(5 + payload_len + 1);
if (d->io.write(d->io_handle, apdu, apdu_len) < 0) {
fido_log_debug("%s: write", __func__);
goto fail;
}
if (cla_flags & 0x10) {
if (d->io.read(d->io_handle, sw, sizeof(sw), -1) != 2) {
fido_log_debug("%s: read", __func__);
goto fail;
}
if ((sw[0] << 8 | sw[1]) != SW_NO_ERROR) {
fido_log_debug("%s: unexpected sw", __func__);
goto fail;
}
}
ok = 0;
fail:
explicit_bzero(apdu, sizeof(apdu));
return ok;
}
static int
nfc_do_tx(fido_dev_t *d, const uint8_t *apdu_ptr, size_t apdu_len)
{
iso7816_header_t h;
if (fido_buf_read(&apdu_ptr, &apdu_len, &h, sizeof(h)) < 0) {
fido_log_debug("%s: header", __func__);
return -1;
}
if (apdu_len < 2) {
fido_log_debug("%s: apdu_len %zu", __func__, apdu_len);
return -1;
}
apdu_len -= 2; /* trim le1 le2 */
while (apdu_len > TX_CHUNK_SIZE) {
if (tx_short_apdu(d, &h, apdu_ptr, TX_CHUNK_SIZE, 0x10) < 0) {
fido_log_debug("%s: chain", __func__);
return -1;
}
apdu_ptr += TX_CHUNK_SIZE;
apdu_len -= TX_CHUNK_SIZE;
}
if (tx_short_apdu(d, &h, apdu_ptr, (uint8_t)apdu_len, 0) < 0) {
fido_log_debug("%s: tx_short_apdu", __func__);
return -1;
}
return 0;
}
int
fido_nfc_tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count)
{
iso7816_apdu_t *apdu = NULL;
const uint8_t *ptr;
size_t len;
int ok = -1;
switch (cmd) {
case CTAP_CMD_INIT: /* select */
if ((apdu = iso7816_new(0, 0xa4, 0x04, sizeof(aid))) == NULL ||
iso7816_add(apdu, aid, sizeof(aid)) < 0) {
fido_log_debug("%s: iso7816", __func__);
goto fail;
}
break;
case CTAP_CMD_CBOR: /* wrap cbor */
if (count > UINT16_MAX || (apdu = iso7816_new(0x80, 0x10, 0x00,
(uint16_t)count)) == NULL ||
iso7816_add(apdu, buf, count) < 0) {
fido_log_debug("%s: iso7816", __func__);
goto fail;
}
break;
case CTAP_CMD_MSG: /* already an apdu */
break;
default:
fido_log_debug("%s: cmd=%02x", __func__, cmd);
goto fail;
}
if (apdu != NULL) {
ptr = iso7816_ptr(apdu);
len = iso7816_len(apdu);
} else {
ptr = buf;
len = count;
}
if (nfc_do_tx(d, ptr, len) < 0) {
fido_log_debug("%s: nfc_do_tx", __func__);
goto fail;
}
ok = 0;
fail:
iso7816_free(&apdu);
return ok;
}
static int
rx_init(fido_dev_t *d, unsigned char *buf, size_t count, int ms)
{
fido_ctap_info_t *attr = (fido_ctap_info_t *)buf;
uint8_t f[64];
int n;
if (count != sizeof(*attr)) {
fido_log_debug("%s: count=%zu", __func__, count);
return -1;
}
memset(attr, 0, sizeof(*attr));
if ((n = d->io.read(d->io_handle, f, sizeof(f), ms)) < 2 ||
(f[n - 2] << 8 | f[n - 1]) != SW_NO_ERROR) {
fido_log_debug("%s: read", __func__);
return -1;
}
n -= 2;
if (n == sizeof(v_u2f) && memcmp(f, v_u2f, sizeof(v_u2f)) == 0)
attr->flags = FIDO_CAP_CBOR;
else if (n == sizeof(v_fido) && memcmp(f, v_fido, sizeof(v_fido)) == 0)
attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG;
else {
fido_log_debug("%s: unknown version string", __func__);
#ifdef FIDO_FUZZ
attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG;
#else
return -1;
#endif
}
memcpy(&attr->nonce, &d->nonce, sizeof(attr->nonce)); /* XXX */
return (int)count;
}
static int
tx_get_response(fido_dev_t *d, uint8_t count)
{
uint8_t apdu[5];
memset(apdu, 0, sizeof(apdu));
apdu[1] = 0xc0; /* GET_RESPONSE */
apdu[4] = count;
if (d->io.write(d->io_handle, apdu, sizeof(apdu)) < 0) {
fido_log_debug("%s: write", __func__);
return -1;
}
return 0;
}
static int
rx_apdu(fido_dev_t *d, uint8_t sw[2], unsigned char **buf, size_t *count, int *ms)
{
uint8_t f[256 + 2];
struct timespec ts;
int n, ok = -1;
if (fido_time_now(&ts) != 0)
goto fail;
if ((n = d->io.read(d->io_handle, f, sizeof(f), *ms)) < 2) {
fido_log_debug("%s: read", __func__);
goto fail;
}
if (fido_time_delta(&ts, ms) != 0)
goto fail;
if (fido_buf_write(buf, count, f, (size_t)(n - 2)) < 0) {
fido_log_debug("%s: fido_buf_write", __func__);
goto fail;
}
memcpy(sw, f + n - 2, 2);
ok = 0;
fail:
explicit_bzero(f, sizeof(f));
return ok;
}
static int
rx_msg(fido_dev_t *d, unsigned char *buf, size_t count, int ms)
{
uint8_t sw[2];
const size_t bufsiz = count;
if (rx_apdu(d, sw, &buf, &count, &ms) < 0) {
fido_log_debug("%s: preamble", __func__);
return -1;
}
while (sw[0] == SW1_MORE_DATA)
if (tx_get_response(d, sw[1]) < 0 ||
rx_apdu(d, sw, &buf, &count, &ms) < 0) {
fido_log_debug("%s: chain", __func__);
return -1;
}
if (fido_buf_write(&buf, &count, sw, sizeof(sw)) < 0) {
fido_log_debug("%s: sw", __func__);
return -1;
}
if (bufsiz - count > INT_MAX) {
fido_log_debug("%s: bufsiz", __func__);
return -1;
}
return (int)(bufsiz - count);
}
static int
rx_cbor(fido_dev_t *d, unsigned char *buf, size_t count, int ms)
{
int r;
if ((r = rx_msg(d, buf, count, ms)) < 2)
return -1;
return r - 2;
}
int
fido_nfc_rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms)
{
switch (cmd) {
case CTAP_CMD_INIT:
return rx_init(d, buf, count, ms);
case CTAP_CMD_CBOR:
return rx_cbor(d, buf, count, ms);
case CTAP_CMD_MSG:
return rx_msg(d, buf, count, ms);
default:
fido_log_debug("%s: cmd=%02x", __func__, cmd);
return -1;
}
}
#ifdef USE_NFC
bool
fido_is_nfc(const char *path)
{
return strncmp(path, FIDO_NFC_PREFIX, strlen(FIDO_NFC_PREFIX)) == 0;
}
int
fido_dev_set_nfc(fido_dev_t *d)
{
if (d->io_handle != NULL) {
fido_log_debug("%s: device open", __func__);
return -1;
}
d->io_own = true;
d->io = (fido_dev_io_t) {
fido_nfc_open,
fido_nfc_close,
fido_nfc_read,
fido_nfc_write,
};
d->transport = (fido_dev_transport_t) {
fido_nfc_rx,
fido_nfc_tx,
};
return 0;
}
#endif /* USE_NFC */

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 Yubico AB. All rights reserved.
* Copyright (c) 2020-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -22,12 +22,6 @@
#include "netlink.h"
#include "iso7816.h"
#define TX_CHUNK_SIZE 240
static const uint8_t aid[] = { 0xa0, 0x00, 0x00, 0x06, 0x47, 0x2f, 0x00, 0x01 };
static const uint8_t v_u2f[] = { 'U', '2', 'F', '_', 'V', '2' };
static const uint8_t v_fido[] = { 'F', 'I', 'D', 'O', '_', '2', '_', '0' };
struct nfc_linux {
int fd;
uint32_t dev;
@ -37,278 +31,6 @@ struct nfc_linux {
struct fido_nl *nl;
};
static int
tx_short_apdu(fido_dev_t *d, const iso7816_header_t *h, const uint8_t *payload,
uint8_t payload_len, uint8_t cla_flags)
{
uint8_t apdu[5 + UINT8_MAX + 1];
uint8_t sw[2];
size_t apdu_len;
int ok = -1;
memset(&apdu, 0, sizeof(apdu));
apdu[0] = h->cla | cla_flags;
apdu[1] = h->ins;
apdu[2] = h->p1;
apdu[3] = h->p2;
apdu[4] = payload_len;
memcpy(&apdu[5], payload, payload_len);
apdu_len = (size_t)(5 + payload_len + 1);
if (d->io.write(d->io_handle, apdu, apdu_len) < 0) {
fido_log_debug("%s: write", __func__);
goto fail;
}
if (cla_flags & 0x10) {
if (d->io.read(d->io_handle, sw, sizeof(sw), -1) != 2) {
fido_log_debug("%s: read", __func__);
goto fail;
}
if ((sw[0] << 8 | sw[1]) != SW_NO_ERROR) {
fido_log_debug("%s: unexpected sw", __func__);
goto fail;
}
}
ok = 0;
fail:
explicit_bzero(apdu, sizeof(apdu));
return (ok);
}
static int
nfc_do_tx(fido_dev_t *d, const uint8_t *apdu_ptr, size_t apdu_len)
{
iso7816_header_t h;
if (fido_buf_read(&apdu_ptr, &apdu_len, &h, sizeof(h)) < 0) {
fido_log_debug("%s: header", __func__);
return (-1);
}
if (apdu_len < 2) {
fido_log_debug("%s: apdu_len %zu", __func__, apdu_len);
return (-1);
}
apdu_len -= 2; /* trim le1 le2 */
while (apdu_len > TX_CHUNK_SIZE) {
if (tx_short_apdu(d, &h, apdu_ptr, TX_CHUNK_SIZE, 0x10) < 0) {
fido_log_debug("%s: chain", __func__);
return (-1);
}
apdu_ptr += TX_CHUNK_SIZE;
apdu_len -= TX_CHUNK_SIZE;
}
if (tx_short_apdu(d, &h, apdu_ptr, (uint8_t)apdu_len, 0) < 0) {
fido_log_debug("%s: tx_short_apdu", __func__);
return (-1);
}
return (0);
}
int
fido_nfc_tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count)
{
iso7816_apdu_t *apdu = NULL;
const uint8_t *ptr;
size_t len;
int ok = -1;
switch (cmd) {
case CTAP_CMD_INIT: /* select */
if ((apdu = iso7816_new(0, 0xa4, 0x04, sizeof(aid))) == NULL ||
iso7816_add(apdu, aid, sizeof(aid)) < 0) {
fido_log_debug("%s: iso7816", __func__);
goto fail;
}
break;
case CTAP_CMD_CBOR: /* wrap cbor */
if (count > UINT16_MAX || (apdu = iso7816_new(0x80, 0x10, 0x80,
(uint16_t)count)) == NULL ||
iso7816_add(apdu, buf, count) < 0) {
fido_log_debug("%s: iso7816", __func__);
goto fail;
}
break;
case CTAP_CMD_MSG: /* already an apdu */
break;
default:
fido_log_debug("%s: cmd=%02x", __func__, cmd);
goto fail;
}
if (apdu != NULL) {
ptr = iso7816_ptr(apdu);
len = iso7816_len(apdu);
} else {
ptr = buf;
len = count;
}
if (nfc_do_tx(d, ptr, len) < 0) {
fido_log_debug("%s: nfc_do_tx", __func__);
goto fail;
}
ok = 0;
fail:
iso7816_free(&apdu);
return (ok);
}
static int
rx_init(fido_dev_t *d, unsigned char *buf, size_t count, int ms)
{
fido_ctap_info_t *attr = (fido_ctap_info_t *)buf;
uint8_t f[64];
int n;
if (count != sizeof(*attr)) {
fido_log_debug("%s: count=%zu", __func__, count);
return (-1);
}
memset(attr, 0, sizeof(*attr));
if ((n = d->io.read(d->io_handle, f, sizeof(f), ms)) < 2 ||
(f[n - 2] << 8 | f[n - 1]) != SW_NO_ERROR) {
fido_log_debug("%s: read", __func__);
return (-1);
}
n -= 2;
if (n == sizeof(v_u2f) && memcmp(f, v_u2f, sizeof(v_u2f)) == 0)
attr->flags = FIDO_CAP_CBOR;
else if (n == sizeof(v_fido) && memcmp(f, v_fido, sizeof(v_fido)) == 0)
attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG;
else {
fido_log_debug("%s: unknown version string", __func__);
#ifdef FIDO_FUZZ
attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG;
#else
return (-1);
#endif
}
memcpy(&attr->nonce, &d->nonce, sizeof(attr->nonce)); /* XXX */
return ((int)count);
}
static int
tx_get_response(fido_dev_t *d, uint8_t count)
{
uint8_t apdu[5];
memset(apdu, 0, sizeof(apdu));
apdu[1] = 0xc0; /* GET_RESPONSE */
apdu[4] = count;
if (d->io.write(d->io_handle, apdu, sizeof(apdu)) < 0) {
fido_log_debug("%s: write", __func__);
return (-1);
}
return (0);
}
static int
rx_apdu(fido_dev_t *d, uint8_t sw[2], unsigned char **buf, size_t *count, int *ms)
{
uint8_t f[256 + 2];
struct timespec ts;
int n, ok = -1;
if (fido_time_now(&ts) != 0)
goto fail;
if ((n = d->io.read(d->io_handle, f, sizeof(f), *ms)) < 2) {
fido_log_debug("%s: read", __func__);
goto fail;
}
if (fido_time_delta(&ts, ms) != 0)
goto fail;
if (fido_buf_write(buf, count, f, (size_t)(n - 2)) < 0) {
fido_log_debug("%s: fido_buf_write", __func__);
goto fail;
}
memcpy(sw, f + n - 2, 2);
ok = 0;
fail:
explicit_bzero(f, sizeof(f));
return (ok);
}
static int
rx_msg(fido_dev_t *d, unsigned char *buf, size_t count, int ms)
{
uint8_t sw[2];
const size_t bufsiz = count;
if (rx_apdu(d, sw, &buf, &count, &ms) < 0) {
fido_log_debug("%s: preamble", __func__);
return (-1);
}
while (sw[0] == SW1_MORE_DATA)
if (tx_get_response(d, sw[1]) < 0 ||
rx_apdu(d, sw, &buf, &count, &ms) < 0) {
fido_log_debug("%s: chain", __func__);
return (-1);
}
if (fido_buf_write(&buf, &count, sw, sizeof(sw)) < 0) {
fido_log_debug("%s: sw", __func__);
return (-1);
}
if (bufsiz - count > INT_MAX) {
fido_log_debug("%s: bufsiz", __func__);
return (-1);
}
return ((int)(bufsiz - count));
}
static int
rx_cbor(fido_dev_t *d, unsigned char *buf, size_t count, int ms)
{
int r;
if ((r = rx_msg(d, buf, count, ms)) < 2)
return (-1);
return (r - 2);
}
int
fido_nfc_rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms)
{
switch (cmd) {
case CTAP_CMD_INIT:
return (rx_init(d, buf, count, ms));
case CTAP_CMD_CBOR:
return (rx_cbor(d, buf, count, ms));
case CTAP_CMD_MSG:
return (rx_msg(d, buf, count, ms));
default:
fido_log_debug("%s: cmd=%02x", __func__, cmd);
return (-1);
}
}
static char *
get_parent_attr(struct udev_device *dev, const char *subsystem,
const char *devtype, const char *attr)
@ -319,34 +41,15 @@ get_parent_attr(struct udev_device *dev, const char *subsystem,
if ((parent = udev_device_get_parent_with_subsystem_devtype(dev,
subsystem, devtype)) == NULL || (value =
udev_device_get_sysattr_value(parent, attr)) == NULL)
return (NULL);
return NULL;
return (strdup(value));
return strdup(value);
}
static char *
get_usb_attr(struct udev_device *dev, const char *attr)
{
return (get_parent_attr(dev, "usb", "usb_device", attr));
}
static int
to_int(const char *str, int base)
{
char *ep;
long long ll;
ll = strtoll(str, &ep, base);
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);
else if (ll < 0 || ll > INT_MAX)
return (-1);
return ((int)ll);
return get_parent_attr(dev, "usb", "usb_device", attr);
}
static int
@ -357,15 +60,18 @@ copy_info(fido_dev_info_t *di, struct udev *udev,
char *str;
struct udev_device *dev = NULL;
void *ctx = NULL;
int id, ok = -1;
uint64_t id;
int ok = -1;
memset(di, 0, sizeof(*di));
if ((name = udev_list_entry_get_name(udev_entry)) == NULL ||
(dev = udev_device_new_from_syspath(udev, name)) == NULL)
goto fail;
if (asprintf(&di->path, "%s/%s", FIDO_NFC_PREFIX, name) == -1)
if (asprintf(&di->path, "%s/%s", FIDO_NFC_PREFIX, name) == -1) {
di->path = NULL;
goto fail;
}
if ((di->manufacturer = get_usb_attr(dev, "manufacturer")) == NULL)
di->manufacturer = strdup("");
if ((di->product = get_usb_attr(dev, "product")) == NULL)
@ -374,11 +80,11 @@ copy_info(fido_dev_info_t *di, struct udev *udev,
goto fail;
/* XXX assumes USB for vendor/product info */
if ((str = get_usb_attr(dev, "idVendor")) != NULL &&
(id = to_int(str, 16)) > 0 && id <= UINT16_MAX)
fido_to_uint64(str, 16, &id) == 0 && id <= UINT16_MAX)
di->vendor_id = (int16_t)id;
free(str);
if ((str = get_usb_attr(dev, "idProduct")) != NULL &&
(id = to_int(str, 16)) > 0 && id <= UINT16_MAX)
fido_to_uint64(str, 16, &id) == 0 && id <= UINT16_MAX)
di->product_id = (int16_t)id;
free(str);
@ -401,7 +107,7 @@ fail:
explicit_bzero(di, sizeof(*di));
}
return (ok);
return ok;
}
static int
@ -410,21 +116,21 @@ sysnum_from_syspath(const char *path)
struct udev *udev = NULL;
struct udev_device *dev = NULL;
const char *str;
int idx;
uint64_t idx64;
int idx = -1;
if ((udev = udev_new()) == NULL ||
(dev = udev_device_new_from_syspath(udev, path)) == NULL ||
(str = udev_device_get_sysnum(dev)) == NULL)
idx = -1;
else
idx = to_int(str, 10);
if ((udev = udev_new()) != NULL &&
(dev = udev_device_new_from_syspath(udev, path)) != NULL &&
(str = udev_device_get_sysnum(dev)) != NULL &&
fido_to_uint64(str, 10, &idx64) == 0 && idx64 < INT_MAX)
idx = (int)idx64;
if (dev != NULL)
udev_device_unref(dev);
if (udev != NULL)
udev_unref(udev);
return (idx);
return idx;
}
int
@ -439,10 +145,10 @@ fido_nfc_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
*olen = 0;
if (ilen == 0)
return (FIDO_OK);
return FIDO_OK;
if (devlist == NULL)
return (FIDO_ERR_INVALID_ARGUMENT);
return FIDO_ERR_INVALID_ARGUMENT;
if ((udev = udev_new()) == NULL ||
(udev_enum = udev_enumerate_new(udev)) == NULL)
@ -481,7 +187,7 @@ fail:
if (udev != NULL)
udev_unref(udev);
return (r);
return r;
}
static int
@ -498,17 +204,17 @@ nfc_target_connect(struct nfc_linux *ctx)
if ((ctx->fd = socket(AF_NFC, SOCK_SEQPACKET | SOCK_CLOEXEC,
NFC_SOCKPROTO_RAW)) == -1) {
fido_log_error(errno, "%s: socket", __func__);
return (-1);
return -1;
}
if (connect(ctx->fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
fido_log_error(errno, "%s: connect", __func__);
if (close(ctx->fd) == -1)
fido_log_error(errno, "%s: close", __func__);
ctx->fd = -1;
return (-1);
return -1;
}
return (0);
return 0;
}
static void
@ -535,13 +241,13 @@ nfc_new(uint32_t dev)
if ((ctx = calloc(1, sizeof(*ctx))) == NULL ||
(ctx->nl = fido_nl_new()) == NULL) {
nfc_free(&ctx);
return (NULL);
return NULL;
}
ctx->fd = -1;
ctx->dev = dev;
return (ctx);
return ctx;
}
void *
@ -566,10 +272,10 @@ fido_nfc_open(const char *path)
goto fail;
}
return (ctx);
return ctx;
fail:
nfc_free(&ctx);
return (NULL);
return NULL;
}
void
@ -588,7 +294,7 @@ fido_nfc_set_sigmask(void *handle, const fido_sigset_t *sigmask)
ctx->sigmask = *sigmask;
ctx->sigmaskp = &ctx->sigmask;
return (FIDO_OK);
return FIDO_OK;
}
int
@ -607,25 +313,25 @@ fido_nfc_read(void *handle, unsigned char *buf, size_t len, int ms)
if (fido_hid_unix_wait(ctx->fd, ms, ctx->sigmaskp) < 0) {
fido_log_debug("%s: fido_hid_unix_wait", __func__);
return (-1);
return -1;
}
if ((r = readv(ctx->fd, iov, nitems(iov))) == -1) {
fido_log_error(errno, "%s: read", __func__);
return (-1);
return -1;
}
if (r < 1) {
fido_log_debug("%s: %zd < 1", __func__, r);
return (-1);
return -1;
}
if (preamble != 0x00) {
fido_log_debug("%s: preamble", __func__);
return (-1);
return -1;
}
r--;
fido_log_xxd(buf, (size_t)r, "%s", __func__);
return ((int)r);
return (int)r;
}
int
@ -638,16 +344,16 @@ fido_nfc_write(void *handle, const unsigned char *buf, size_t len)
if (len > INT_MAX) {
fido_log_debug("%s: len", __func__);
return (-1);
return -1;
}
if ((r = write(ctx->fd, buf, len)) == -1) {
fido_log_error(errno, "%s: write", __func__);
return (-1);
return -1;
}
if (r < 0 || (size_t)r != len) {
fido_log_debug("%s: %zd != %zu", __func__, r, len);
return (-1);
return -1;
}
return ((int)r);
return (int)r;
}

389
src/pcsc.c Normal file
View file

@ -0,0 +1,389 @@
/*
* Copyright (c) 2022 Micro Focus or one of its affiliates.
* Copyright (c) 2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#if __APPLE__
#include <PCSC/wintypes.h>
#include <PCSC/winscard.h>
#else
#include <winscard.h>
#endif /* __APPLE__ */
#include <errno.h>
#include "fido.h"
#include "fido/param.h"
#include "iso7816.h"
#if defined(_WIN32) && !defined(__MINGW32__)
#define SCardConnect SCardConnectA
#define SCardListReaders SCardListReadersA
#endif
#ifndef SCARD_PROTOCOL_Tx
#define SCARD_PROTOCOL_Tx SCARD_PROTOCOL_ANY
#endif
#define BUFSIZE 1024 /* in bytes; passed to SCardListReaders() */
#define APDULEN 264 /* 261 rounded up to the nearest multiple of 8 */
#define READERS 8 /* maximum number of readers */
struct pcsc {
SCARDCONTEXT ctx;
SCARDHANDLE h;
SCARD_IO_REQUEST req;
uint8_t rx_buf[APDULEN];
size_t rx_len;
};
static LONG
list_readers(SCARDCONTEXT ctx, char **buf)
{
LONG s;
DWORD len;
len = BUFSIZE;
if ((*buf = calloc(1, len)) == NULL)
goto fail;
if ((s = SCardListReaders(ctx, NULL, *buf, &len)) != SCARD_S_SUCCESS) {
fido_log_debug("%s: SCardListReaders 0x%lx", __func__, (long)s);
goto fail;
}
/* sanity check "multi-string" */
if (len > BUFSIZE || len < 2) {
fido_log_debug("%s: bogus len=%u", __func__, (unsigned)len);
goto fail;
}
if ((*buf)[len - 1] != 0 || (*buf)[len - 2] != '\0') {
fido_log_debug("%s: bogus buf", __func__);
goto fail;
}
return (LONG)SCARD_S_SUCCESS;
fail:
free(*buf);
*buf = NULL;
return (LONG)SCARD_E_NO_READERS_AVAILABLE;
}
static char *
get_reader(SCARDCONTEXT ctx, const char *path)
{
char *reader = NULL, *buf = NULL;
const char prefix[] = FIDO_PCSC_PREFIX "//slot";
uint64_t n;
if (path == NULL)
goto out;
if (strncmp(path, prefix, strlen(prefix)) != 0 ||
fido_to_uint64(path + strlen(prefix), 10, &n) < 0 ||
n > READERS - 1) {
fido_log_debug("%s: invalid path %s", __func__, path);
goto out;
}
if (list_readers(ctx, &buf) != SCARD_S_SUCCESS) {
fido_log_debug("%s: list_readers", __func__);
goto out;
}
for (const char *name = buf; *name != 0; name += strlen(name) + 1) {
if (n == 0) {
reader = strdup(name);
goto out;
}
n--;
}
fido_log_debug("%s: failed to find reader %s", __func__, path);
out:
free(buf);
return reader;
}
static int
prepare_io_request(DWORD prot, SCARD_IO_REQUEST *req)
{
switch (prot) {
case SCARD_PROTOCOL_T0:
req->dwProtocol = SCARD_PCI_T0->dwProtocol;
req->cbPciLength = SCARD_PCI_T0->cbPciLength;
break;
case SCARD_PROTOCOL_T1:
req->dwProtocol = SCARD_PCI_T1->dwProtocol;
req->cbPciLength = SCARD_PCI_T1->cbPciLength;
break;
default:
fido_log_debug("%s: unknown protocol %lu", __func__,
(u_long)prot);
return -1;
}
return 0;
}
static int
copy_info(fido_dev_info_t *di, SCARDCONTEXT ctx, const char *reader, size_t idx)
{
SCARDHANDLE h = 0;
SCARD_IO_REQUEST req;
DWORD prot = 0;
LONG s;
int ok = -1;
memset(di, 0, sizeof(*di));
memset(&req, 0, sizeof(req));
if ((s = SCardConnect(ctx, reader, SCARD_SHARE_SHARED,
SCARD_PROTOCOL_Tx, &h, &prot)) != SCARD_S_SUCCESS) {
fido_log_debug("%s: SCardConnect 0x%lx", __func__, (long)s);
goto fail;
}
if (prepare_io_request(prot, &req) < 0) {
fido_log_debug("%s: prepare_io_request", __func__);
goto fail;
}
if (asprintf(&di->path, "%s//slot%zu", FIDO_PCSC_PREFIX, idx) == -1) {
di->path = NULL;
fido_log_debug("%s: asprintf", __func__);
goto fail;
}
if ((di->manufacturer = strdup("PC/SC")) == NULL ||
(di->product = strdup(reader)) == NULL)
goto fail;
ok = 0;
fail:
if (h != 0)
SCardDisconnect(h, SCARD_LEAVE_CARD);
if (ok < 0) {
free(di->path);
free(di->manufacturer);
free(di->product);
explicit_bzero(di, sizeof(*di));
}
return ok;
}
int
fido_pcsc_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
{
SCARDCONTEXT ctx = 0;
char *buf = NULL;
LONG s;
size_t idx = 0;
int r = FIDO_ERR_INTERNAL;
*olen = 0;
if (ilen == 0)
return FIDO_OK;
if (devlist == NULL)
return FIDO_ERR_INVALID_ARGUMENT;
if ((s = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL,
&ctx)) != SCARD_S_SUCCESS || ctx == 0) {
fido_log_debug("%s: SCardEstablishContext 0x%lx", __func__,
(long)s);
if (s == (LONG)SCARD_E_NO_SERVICE ||
s == (LONG)SCARD_E_NO_SMARTCARD)
r = FIDO_OK; /* suppress error */
goto out;
}
if ((s = list_readers(ctx, &buf)) != SCARD_S_SUCCESS) {
fido_log_debug("%s: list_readers 0x%lx", __func__, (long)s);
if (s == (LONG)SCARD_E_NO_READERS_AVAILABLE)
r = FIDO_OK; /* suppress error */
goto out;
}
for (const char *name = buf; *name != 0; name += strlen(name) + 1) {
if (idx == READERS) {
fido_log_debug("%s: stopping at %zu readers", __func__,
idx);
r = FIDO_OK;
goto out;
}
if (copy_info(&devlist[*olen], ctx, name, idx++) == 0) {
devlist[*olen].io = (fido_dev_io_t) {
fido_pcsc_open,
fido_pcsc_close,
fido_pcsc_read,
fido_pcsc_write,
};
devlist[*olen].transport = (fido_dev_transport_t) {
fido_pcsc_rx,
fido_pcsc_tx,
};
if (++(*olen) == ilen)
break;
}
}
r = FIDO_OK;
out:
free(buf);
if (ctx != 0)
SCardReleaseContext(ctx);
return r;
}
void *
fido_pcsc_open(const char *path)
{
char *reader = NULL;
struct pcsc *dev = NULL;
SCARDCONTEXT ctx = 0;
SCARDHANDLE h = 0;
SCARD_IO_REQUEST req;
DWORD prot = 0;
LONG s;
memset(&req, 0, sizeof(req));
if ((s = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL,
&ctx)) != SCARD_S_SUCCESS || ctx == 0) {
fido_log_debug("%s: SCardEstablishContext 0x%lx", __func__,
(long)s);
goto fail;
}
if ((reader = get_reader(ctx, path)) == NULL) {
fido_log_debug("%s: get_reader(%s)", __func__, path);
goto fail;
}
if ((s = SCardConnect(ctx, reader, SCARD_SHARE_SHARED,
SCARD_PROTOCOL_Tx, &h, &prot)) != SCARD_S_SUCCESS) {
fido_log_debug("%s: SCardConnect 0x%lx", __func__, (long)s);
goto fail;
}
if (prepare_io_request(prot, &req) < 0) {
fido_log_debug("%s: prepare_io_request", __func__);
goto fail;
}
if ((dev = calloc(1, sizeof(*dev))) == NULL)
goto fail;
dev->ctx = ctx;
dev->h = h;
dev->req = req;
ctx = 0;
h = 0;
fail:
if (h != 0)
SCardDisconnect(h, SCARD_LEAVE_CARD);
if (ctx != 0)
SCardReleaseContext(ctx);
free(reader);
return dev;
}
void
fido_pcsc_close(void *handle)
{
struct pcsc *dev = handle;
if (dev->h != 0)
SCardDisconnect(dev->h, SCARD_LEAVE_CARD);
if (dev->ctx != 0)
SCardReleaseContext(dev->ctx);
explicit_bzero(dev->rx_buf, sizeof(dev->rx_buf));
free(dev);
}
int
fido_pcsc_read(void *handle, unsigned char *buf, size_t len, int ms)
{
struct pcsc *dev = handle;
int r;
(void)ms;
if (dev->rx_len == 0 || dev->rx_len > len ||
dev->rx_len > sizeof(dev->rx_buf)) {
fido_log_debug("%s: rx_len", __func__);
return -1;
}
fido_log_xxd(dev->rx_buf, dev->rx_len, "%s: reading", __func__);
memcpy(buf, dev->rx_buf, dev->rx_len);
explicit_bzero(dev->rx_buf, sizeof(dev->rx_buf));
r = (int)dev->rx_len;
dev->rx_len = 0;
return r;
}
int
fido_pcsc_write(void *handle, const unsigned char *buf, size_t len)
{
struct pcsc *dev = handle;
DWORD n;
LONG s;
if (len > INT_MAX) {
fido_log_debug("%s: len", __func__);
return -1;
}
explicit_bzero(dev->rx_buf, sizeof(dev->rx_buf));
dev->rx_len = 0;
n = (DWORD)sizeof(dev->rx_buf);
fido_log_xxd(buf, len, "%s: writing", __func__);
if ((s = SCardTransmit(dev->h, &dev->req, buf, (DWORD)len, NULL,
dev->rx_buf, &n)) != SCARD_S_SUCCESS) {
fido_log_debug("%s: SCardTransmit 0x%lx", __func__, (long)s);
explicit_bzero(dev->rx_buf, sizeof(dev->rx_buf));
return -1;
}
dev->rx_len = (size_t)n;
fido_log_xxd(dev->rx_buf, dev->rx_len, "%s: read", __func__);
return (int)len;
}
int
fido_pcsc_tx(fido_dev_t *d, uint8_t cmd, const u_char *buf, size_t count)
{
return fido_nfc_tx(d, cmd, buf, count);
}
int
fido_pcsc_rx(fido_dev_t *d, uint8_t cmd, u_char *buf, size_t count, int ms)
{
return fido_nfc_rx(d, cmd, buf, count, ms);
}
bool
fido_is_pcsc(const char *path)
{
return strncmp(path, FIDO_PCSC_PREFIX, strlen(FIDO_PCSC_PREFIX)) == 0;
}
int
fido_dev_set_pcsc(fido_dev_t *d)
{
if (d->io_handle != NULL) {
fido_log_debug("%s: device open", __func__);
return -1;
}
d->io_own = true;
d->io = (fido_dev_io_t) {
fido_pcsc_open,
fido_pcsc_close,
fido_pcsc_read,
fido_pcsc_write,
};
d->transport = (fido_dev_transport_t) {
fido_pcsc_rx,
fido_pcsc_tx,
};
return 0;
}

View file

@ -9,7 +9,7 @@
#include "fido.h"
#if defined(LIBRESSL_VERSION_NUMBER)
#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050200fL
static EVP_MD *
rs1_get_EVP_MD(void)
{

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -11,7 +11,13 @@
#include "fido.h"
#include "fido/rs256.h"
#if defined(LIBRESSL_VERSION_NUMBER)
#if OPENSSL_VERSION_NUMBER >= 0x30000000
#define get0_RSA(x) EVP_PKEY_get0_RSA((x))
#else
#define get0_RSA(x) EVP_PKEY_get0((x))
#endif
#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050200fL
static EVP_MD *
rs256_get_EVP_MD(void)
{
@ -128,11 +134,20 @@ rs256_pk_free(rs256_pk_t **pkp)
int
rs256_pk_from_ptr(rs256_pk_t *pk, const void *ptr, size_t len)
{
EVP_PKEY *pkey;
if (len < sizeof(*pk))
return (FIDO_ERR_INVALID_ARGUMENT);
memcpy(pk, ptr, sizeof(*pk));
if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) {
fido_log_debug("%s: rs256_pk_to_EVP_PKEY", __func__);
return (FIDO_ERR_INVALID_ARGUMENT);
}
EVP_PKEY_free(pkey);
return (FIDO_OK);
}
@ -163,6 +178,11 @@ rs256_pk_to_EVP_PKEY(const rs256_pk_t *k)
n = NULL;
e = NULL;
if (RSA_bits(rsa) != 2048) {
fido_log_debug("%s: invalid key length", __func__);
goto fail;
}
if ((pkey = EVP_PKEY_new()) == NULL ||
EVP_PKEY_assign_RSA(pkey, rsa) == 0) {
fido_log_debug("%s: EVP_PKEY_assign_RSA", __func__);
@ -225,10 +245,10 @@ rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa)
int
rs256_pk_from_EVP_PKEY(rs256_pk_t *pk, const EVP_PKEY *pkey)
{
RSA *rsa;
const RSA *rsa;
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA ||
(rsa = EVP_PKEY_get0(pkey)) == NULL)
(rsa = get0_RSA(pkey)) == NULL)
return (FIDO_ERR_INVALID_ARGUMENT);
return (rs256_pk_from_RSA(pk, rsa));

108
src/touch.c Normal file
View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#include <openssl/sha.h>
#include "fido.h"
int
fido_dev_get_touch_begin(fido_dev_t *dev)
{
fido_blob_t f;
cbor_item_t *argv[9];
const char *clientdata = FIDO_DUMMY_CLIENTDATA;
const uint8_t user_id = FIDO_DUMMY_USER_ID;
unsigned char cdh[SHA256_DIGEST_LENGTH];
fido_rp_t rp;
fido_user_t user;
int ms = dev->timeout_ms;
int r = FIDO_ERR_INTERNAL;
memset(&f, 0, sizeof(f));
memset(argv, 0, sizeof(argv));
memset(cdh, 0, sizeof(cdh));
memset(&rp, 0, sizeof(rp));
memset(&user, 0, sizeof(user));
if (fido_dev_is_fido2(dev) == false)
return (u2f_get_touch_begin(dev, &ms));
if (SHA256((const void *)clientdata, strlen(clientdata), cdh) != cdh) {
fido_log_debug("%s: sha256", __func__);
return (FIDO_ERR_INTERNAL);
}
if ((rp.id = strdup(FIDO_DUMMY_RP_ID)) == NULL ||
(user.name = strdup(FIDO_DUMMY_USER_NAME)) == NULL) {
fido_log_debug("%s: strdup", __func__);
goto fail;
}
if (fido_blob_set(&user.id, &user_id, sizeof(user_id)) < 0) {
fido_log_debug("%s: fido_blob_set", __func__);
goto fail;
}
if ((argv[0] = cbor_build_bytestring(cdh, sizeof(cdh))) == NULL ||
(argv[1] = cbor_encode_rp_entity(&rp)) == NULL ||
(argv[2] = cbor_encode_user_entity(&user)) == NULL ||
(argv[3] = cbor_encode_pubkey_param(COSE_ES256)) == NULL) {
fido_log_debug("%s: cbor encode", __func__);
goto fail;
}
if (fido_dev_supports_pin(dev)) {
if ((argv[7] = cbor_new_definite_bytestring()) == NULL ||
(argv[8] = cbor_encode_pin_opt(dev)) == NULL) {
fido_log_debug("%s: cbor encode", __func__);
goto fail;
}
}
if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 ||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, &ms) < 0) {
fido_log_debug("%s: fido_tx", __func__);
r = FIDO_ERR_TX;
goto fail;
}
r = FIDO_OK;
fail:
cbor_vector_free(argv, nitems(argv));
free(f.ptr);
free(rp.id);
free(user.name);
free(user.id.ptr);
return (r);
}
int
fido_dev_get_touch_status(fido_dev_t *dev, int *touched, int ms)
{
int r;
*touched = 0;
if (fido_dev_is_fido2(dev) == false)
return (u2f_get_touch_status(dev, touched, &ms));
switch ((r = fido_rx_cbor_status(dev, &ms))) {
case FIDO_ERR_PIN_AUTH_INVALID:
case FIDO_ERR_PIN_INVALID:
case FIDO_ERR_PIN_NOT_SET:
case FIDO_ERR_SUCCESS:
*touched = 1;
break;
case FIDO_ERR_RX:
/* ignore */
break;
default:
fido_log_debug("%s: fido_rx_cbor_status", __func__);
return (r);
}
return (FIDO_OK);
}

30
src/util.c Normal file
View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include "fido.h"
int
fido_to_uint64(const char *str, int base, uint64_t *out)
{
char *ep;
unsigned long long ull;
errno = 0;
ull = strtoull(str, &ep, base);
if (str == ep || *ep != '\0')
return -1;
else if (ull == ULLONG_MAX && errno == ERANGE)
return -1;
else if (ull > UINT64_MAX)
return -1;
*out = (uint64_t)ull;
return 0;
}

View file

@ -92,6 +92,9 @@ extern "C" {
// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 5
// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 6
// - WEBAUTHN_ASSERTION : 3
// APIs:
// - WebAuthNGetPlatformCredentialList
// - WebAuthNFreePlatformCredentialList
//
#define WEBAUTHN_API_CURRENT_VERSION WEBAUTHN_API_VERSION_4
@ -282,12 +285,65 @@ typedef struct _WEBAUTHN_CREDENTIAL_LIST {
} WEBAUTHN_CREDENTIAL_LIST, *PWEBAUTHN_CREDENTIAL_LIST;
typedef const WEBAUTHN_CREDENTIAL_LIST *PCWEBAUTHN_CREDENTIAL_LIST;
//+------------------------------------------------------------------------------------------
// Credential Information for WebAuthNGetPlatformCredentialList API
//-------------------------------------------------------------------------------------------
#define WEBAUTHN_CREDENTIAL_DETAILS_VERSION_1 1
#define WEBAUTHN_CREDENTIAL_DETAILS_CURRENT_VERSION WEBAUTHN_CREDENTIAL_DETAILS_VERSION_1
typedef struct _WEBAUTHN_CREDENTIAL_DETAILS {
// Version of this structure, to allow for modifications in the future.
DWORD dwVersion;
// Size of pbCredentialID.
DWORD cbCredentialID;
_Field_size_bytes_(cbCredentialID)
PBYTE pbCredentialID;
// RP Info
PWEBAUTHN_RP_ENTITY_INFORMATION pRpInformation;
// User Info
PWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation;
} WEBAUTHN_CREDENTIAL_DETAILS, *PWEBAUTHN_CREDENTIAL_DETAILS;
typedef const WEBAUTHN_CREDENTIAL_DETAILS *PCWEBAUTHN_CREDENTIAL_DETAILS;
typedef struct _WEBAUTHN_CREDENTIAL_DETAILS_LIST {
DWORD cCredentialDetails;
_Field_size_(cCredentialDetails)
PWEBAUTHN_CREDENTIAL_DETAILS *ppCredentialDetails;
} WEBAUTHN_CREDENTIAL_DETAILS_LIST, *PWEBAUTHN_CREDENTIAL_DETAILS_LIST;
typedef const WEBAUTHN_CREDENTIAL_DETAILS_LIST *PCWEBAUTHN_CREDENTIAL_DETAILS_LIST;
#define WEBAUTHN_GET_CREDENTIALS_OPTIONS_VERSION_1 1
#define WEBAUTHN_GET_CREDENTIALS_OPTIONS_CURRENT_VERSION WEBAUTHN_GET_CREDENTIALS_OPTIONS_VERSION_1
typedef struct _WEBAUTHN_GET_CREDENTIALS_OPTIONS {
// Version of this structure, to allow for modifications in the future.
DWORD dwVersion;
// RPID
LPCWSTR pwszRpId;
// Optional. BrowserInPrivate Mode. Defaulting to FALSE.
BOOL bBrowserInPrivateMode;
} WEBAUTHN_GET_CREDENTIALS_OPTIONS, *PWEBAUTHN_GET_CREDENTIALS_OPTIONS;
typedef const WEBAUTHN_GET_CREDENTIALS_OPTIONS *PCWEBAUTHN_GET_CREDENTIALS_OPTIONS;
//+------------------------------------------------------------------------------------------
// PRF values.
//-------------------------------------------------------------------------------------------
#define WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH 32
// SALT values below by default are converted into RAW Hmac-Secret values as per PRF extension.
// - SHA-256(UTF8Encode("WebAuthn PRF") || 0x00 || Value)
//
// Set WEBAUTHN_CTAP_HMAC_SECRET_VALUES_FLAG in dwFlags in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS,
// if caller wants to provide RAW Hmac-Secret SALT values directly. In that case,
// values if provided MUST be of WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH size.
typedef struct _WEBAUTHN_HMAC_SECRET_SALT {
// Size of pbFirst.
DWORD cbFirst;
@ -545,6 +601,12 @@ typedef const WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS *PCWEBAUTHN_AUTHENT
#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6 6
#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_CURRENT_VERSION WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6
/*
Information about flags.
*/
#define WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG 0x00100000
typedef struct _WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS {
// Version of this structure, to allow for modifications in the future.
DWORD dwVersion;
@ -565,7 +627,7 @@ typedef struct _WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS {
// User Verification Requirement.
DWORD dwUserVerificationRequirement;
// Reserved for future Use
// Flags
DWORD dwFlags;
//
@ -879,6 +941,17 @@ WINAPI
WebAuthNCancelCurrentOperation(
_In_ const GUID* pCancellationId);
HRESULT
WINAPI
WebAuthNGetPlatformCredentialList(
_In_ PCWEBAUTHN_GET_CREDENTIALS_OPTIONS pGetCredentialsOptions,
_Outptr_result_maybenull_ PWEBAUTHN_CREDENTIAL_DETAILS_LIST *ppCredentialDetailsList);
void
WINAPI
WebAuthNFreePlatformCredentialList(
_In_ PWEBAUTHN_CREDENTIAL_DETAILS_LIST pCredentialDetailsList);
//
// Returns the following Error Names:
// L"Success" - S_OK

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 Yubico AB. All rights reserved.
* Copyright (c) 2021-2022 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@ -427,6 +427,42 @@ pack_cred_ext(WEBAUTHN_EXTENSIONS *out, const fido_cred_ext_t *in)
return 0;
}
static int
pack_assert_ext(WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS *out,
const fido_assert_ext_t *in)
{
WEBAUTHN_HMAC_SECRET_SALT_VALUES *v;
WEBAUTHN_HMAC_SECRET_SALT *s;
if (in->mask == 0) {
return 0; /* nothing to do */
}
if (in->mask != FIDO_EXT_HMAC_SECRET) {
fido_log_debug("%s: mask 0x%x", __func__, in->mask);
return -1;
}
if (in->hmac_salt.ptr == NULL ||
in->hmac_salt.len != WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH) {
fido_log_debug("%s: salt %p/%zu", __func__,
(const void *)in->hmac_salt.ptr, in->hmac_salt.len);
return -1;
}
if ((v = calloc(1, sizeof(*v))) == NULL ||
(s = calloc(1, sizeof(*s))) == NULL) {
free(v);
fido_log_debug("%s: calloc", __func__);
return -1;
}
s->cbFirst = (DWORD)in->hmac_salt.len;
s->pbFirst = in->hmac_salt.ptr;
v->pGlobalHmacSalt = s;
out->pHmacSecretSaltValues = v;
out->dwFlags |= WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG;
out->dwVersion = WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6;
return 0;
}
static int
unpack_assert_authdata(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)
{
@ -499,6 +535,39 @@ unpack_user_id(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)
return 0;
}
static int
unpack_hmac_secret(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)
{
if (wa->dwVersion != WEBAUTHN_ASSERTION_VERSION_3) {
fido_log_debug("%s: dwVersion %u", __func__,
(unsigned)wa->dwVersion);
return 0; /* proceed without hmac-secret */
}
if (wa->pHmacSecret == NULL ||
wa->pHmacSecret->cbFirst == 0 ||
wa->pHmacSecret->cbFirst > SIZE_MAX ||
wa->pHmacSecret->pbFirst == NULL) {
fido_log_debug("%s: hmac-secret absent", __func__);
return 0; /* proceed without hmac-secret */
}
if (wa->pHmacSecret->cbSecond != 0 ||
wa->pHmacSecret->pbSecond != NULL) {
fido_log_debug("%s: 64-byte hmac-secret", __func__);
return 0; /* proceed without hmac-secret */
}
if (!fido_blob_is_empty(&assert->stmt[0].hmac_secret)) {
fido_log_debug("%s: fido_blob_is_empty", __func__);
return -1;
}
if (fido_blob_set(&assert->stmt[0].hmac_secret,
wa->pHmacSecret->pbFirst, (size_t)wa->pHmacSecret->cbFirst) < 0) {
fido_log_debug("%s: fido_blob_set", __func__);
return -1;
}
return 0;
}
static int
translate_fido_assert(struct winhello_assert *ctx, const fido_assert_t *assert,
const char *pin, int ms)
@ -510,11 +579,6 @@ translate_fido_assert(struct winhello_assert *ctx, const fido_assert_t *assert,
fido_log_debug("%s: up %d", __func__, assert->up);
return FIDO_ERR_UNSUPPORTED_OPTION;
}
/* not implemented */
if (assert->ext.mask) {
fido_log_debug("%s: ext 0x%x", __func__, assert->ext.mask);
return FIDO_ERR_UNSUPPORTED_EXTENSION;
}
if ((ctx->rp_id = to_utf16(assert->rp_id)) == NULL) {
fido_log_debug("%s: rp_id", __func__);
return FIDO_ERR_INTERNAL;
@ -531,6 +595,10 @@ translate_fido_assert(struct winhello_assert *ctx, const fido_assert_t *assert,
fido_log_debug("%s: pack_credlist", __func__);
return FIDO_ERR_INTERNAL;
}
if (pack_assert_ext(opt, &assert->ext) < 0) {
fido_log_debug("%s: pack_assert_ext", __func__);
return FIDO_ERR_UNSUPPORTED_EXTENSION;
}
if (set_assert_uv(&opt->dwUserVerificationRequirement, assert->uv,
pin) < 0) {
fido_log_debug("%s: set_assert_uv", __func__);
@ -570,6 +638,11 @@ translate_winhello_assert(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)
fido_log_debug("%s: unpack_user_id", __func__);
return FIDO_ERR_INTERNAL;
}
if (assert->ext.mask & FIDO_EXT_HMAC_SECRET &&
unpack_hmac_secret(assert, wa) < 0) {
fido_log_debug("%s: unpack_hmac_secret", __func__);
return FIDO_ERR_INTERNAL;
}
return FIDO_OK;
}
@ -742,6 +815,9 @@ winhello_assert_free(struct winhello_assert *ctx)
free(ctx->rp_id);
free(ctx->opt.CredentialList.pCredentials);
if (ctx->opt.pHmacSecretSaltValues != NULL)
free(ctx->opt.pHmacSecretSaltValues->pGlobalHmacSalt);
free(ctx->opt.pHmacSecretSaltValues);
free(ctx);
}
@ -883,7 +959,7 @@ fido_winhello_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
const char *v[3] = { "U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE" };
const char *e[2] = { "credProtect", "hmac-secret" };
const char *t[2] = { "nfc", "usb" };
const char *o[4] = { "rk", "up", "plat", "clientPin" };
const char *o[4] = { "rk", "up", "uv", "plat" };
(void)dev;

View file

@ -65,13 +65,6 @@ add_executable(fido2-token
${COMPAT_SOURCES}
)
# set the library to link against
if(BUILD_SHARED_LIBS)
set(_FIDO2_LIBRARY fido2_shared)
else()
set(_FIDO2_LIBRARY fido2)
endif()
target_link_libraries(fido2-cred ${CRYPTO_LIBRARIES} ${_FIDO2_LIBRARY})
target_link_libraries(fido2-assert ${CRYPTO_LIBRARIES} ${_FIDO2_LIBRARY})
target_link_libraries(fido2-token ${CRYPTO_LIBRARIES} ${_FIDO2_LIBRARY})

View file

@ -155,6 +155,12 @@ print_maxcredidlen(uint64_t maxcredidlen)
printf("maxcredlen: %d\n", (int)maxcredidlen);
}
static void
print_maxlargeblob(uint64_t maxlargeblob)
{
printf("maxlargeblob: %d\n", (int)maxlargeblob);
}
static void
print_fwversion(uint64_t fwversion)
{
@ -259,6 +265,9 @@ token_info(int argc, char **argv, char *path)
/* print maximum length of a credential ID */
print_maxcredidlen(fido_cbor_info_maxcredidlen(ci));
/* print maximum length of serialized largeBlob array */
print_maxlargeblob(fido_cbor_info_maxlargeblob(ci));
/* print firmware version */
print_fwversion(fido_cbor_info_fwversion(ci));

View file

@ -106,6 +106,9 @@ KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct
# SatoshiLabs TREZOR by pid.codes
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="53c1", TAG+="uaccess", GROUP="plugdev", MODE="0660"
# SoloKeys v2 by pid.codes
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="beee", TAG+="uaccess", GROUP="plugdev", MODE="0660"
# Google Titan U2F by Google Inc.
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="5026", TAG+="uaccess", GROUP="plugdev", MODE="0660"

View file

@ -72,6 +72,7 @@ product SILICON 0x8acf U2F Zero
product PIDCODES 0x5070 SoloKeys SoloHacker
product PIDCODES 0x50b0 SoloKeys SoloBoot
product PIDCODES 0x53c1 SatoshiLabs TREZOR
product PIDCODES 0xbeee SoloKeys v2
product GOOGLE 0x5026 Google Titan U2F

View file

@ -1,4 +1,4 @@
# Copyright (c) 2021 Yubico AB. All rights reserved.
# Copyright (c) 2021-2022 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
@ -187,17 +187,15 @@ try {
& $CMake --build . --config ${Config} --verbose; ExitOnError
& $CMake --build . --config ${Config} --target install --verbose; `
ExitOnError
# Patch up zlib's resulting names when built with --config Debug.
if ("${Config}" -eq "Debug") {
if ("${Type}" -eq "Dynamic") {
Copy-Item "${PREFIX}/lib/zlibd.lib" `
-Destination "${PREFIX}/lib/zlib.lib" -Force
Copy-Item "${PREFIX}/bin/zlibd1.dll" `
-Destination "${PREFIX}/bin/zlib1.dll" -Force
} else {
Copy-Item "${PREFIX}/lib/zlibstaticd.lib" `
-Destination "${PREFIX}/lib/zlib.lib" -Force
}
# Patch up zlib's various names.
if ("${Type}" -eq "Dynamic") {
((Get-ChildItem -Path "${PREFIX}/lib") -Match "zlib[d]?.lib") |
Copy-Item -Destination "${PREFIX}/lib/zlib1.lib" -Force
((Get-ChildItem -Path "${PREFIX}/bin") -Match "zlibd1.dll") |
Copy-Item -Destination "${PREFIX}/bin/zlib1.dll" -Force
} else {
((Get-ChildItem -Path "${PREFIX}/lib") -Match "zlibstatic[d]?.lib") |
Copy-item -Destination "${PREFIX}/lib/zlib1.lib" -Force
}
} catch {
throw "Failed to build zlib"
@ -225,11 +223,13 @@ try {
-DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
ExitOnError
& $CMake --build . --config ${Config} --verbose; ExitOnError
& $CMake --build . --config ${Config} --target regress --verbose; `
ExitOnError
& $CMake --build . --config ${Config} --target install --verbose; `
ExitOnError
# Copy DLLs.
if ("${SHARED}" -eq "ON") {
"cbor.dll", "crypto-47.dll", "zlib1.dll" | `
"cbor.dll", "crypto-49.dll", "zlib1.dll" | `
%{ Copy-Item "${PREFIX}\bin\$_" `
-Destination "examples\${Config}" }
}

View file

@ -6,7 +6,7 @@
New-Variable -Name 'LIBRESSL_URL' `
-Value 'https://fastly.cdn.openbsd.org/pub/OpenBSD/LibreSSL' `
-Option Constant
New-Variable -Name 'LIBRESSL' -Value 'libressl-3.4.2' -Option Constant
New-Variable -Name 'LIBRESSL' -Value 'libressl-3.5.2' -Option Constant
# libcbor coordinates.
New-Variable -Name 'LIBCBOR' -Value 'libcbor-0.9.0' -Option Constant
@ -15,8 +15,8 @@ New-Variable -Name 'LIBCBOR_GIT' -Value 'https://github.com/pjk/libcbor' `
-Option Constant
# zlib coordinates.
New-Variable -Name 'ZLIB' -Value 'zlib-1.2.11' -Option Constant
New-Variable -Name 'ZLIB_BRANCH' -Value 'v1.2.11' -Option Constant
New-Variable -Name 'ZLIB' -Value 'zlib-1.2.12' -Option Constant
New-Variable -Name 'ZLIB_BRANCH' -Value 'v1.2.12' -Option Constant
New-Variable -Name 'ZLIB_GIT' -Value 'https://github.com/madler/zlib' `
-Option Constant

View file

@ -66,3 +66,4 @@ Start-Process "${Cygwin}\${Setup}" -Wait -NoNewWindow `
$Env:PATH = "${Root}\bin\;" + $Env:PATH
cmake "-DCMAKE_BUILD_TYPE=${Config}" -B "build-${Config}"
make -C "build-${Config}"
make -C "build-${Config}" regress

View file

@ -1,4 +1,4 @@
# Copyright (c) 2021 Yubico AB. All rights reserved.
# Copyright (c) 2021-2022 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
@ -7,7 +7,7 @@ $Architectures = @('x64', 'Win32', 'ARM64', 'ARM')
$InstallPrefixes = @('Win64', 'Win32', 'ARM64', 'ARM')
$Types = @('dynamic', 'static')
$Config = 'Release'
$LibCrypto = '47'
$LibCrypto = '49'
$SDK = '143'
. "$PSScriptRoot\const.ps1"
@ -34,7 +34,7 @@ Function Package-Dynamic(${SRC}, ${DEST}) {
Copy-Item "${SRC}\bin\cbor.dll" "${DEST}"
Copy-Item "${SRC}\lib\cbor.lib" "${DEST}"
Copy-Item "${SRC}\bin\zlib1.dll" "${DEST}"
Copy-Item "${SRC}\lib\zlib.lib" "${DEST}"
Copy-Item "${SRC}\lib\zlib1.lib" "${DEST}"
Copy-Item "${SRC}\bin\crypto-${LibCrypto}.dll" "${DEST}"
Copy-Item "${SRC}\lib\crypto-${LibCrypto}.lib" "${DEST}"
Copy-Item "${SRC}\bin\fido2.dll" "${DEST}"
@ -43,7 +43,7 @@ Function Package-Dynamic(${SRC}, ${DEST}) {
Function Package-Static(${SRC}, ${DEST}) {
Copy-Item "${SRC}/lib/cbor.lib" "${DEST}"
Copy-Item "${SRC}/lib/zlib.lib" "${DEST}"
Copy-Item "${SRC}/lib/zlib1.lib" "${DEST}"
Copy-Item "${SRC}/lib/crypto-${LibCrypto}.lib" "${DEST}"
Copy-Item "${SRC}/lib/fido2_static.lib" "${DEST}/fido2.lib"
}
@ -54,19 +54,19 @@ Function Package-PDBs(${SRC}, ${DEST}) {
Copy-Item "${SRC}\${LIBCBOR}\src\cbor.dir\${Config}\vc${SDK}.pdb" `
"${DEST}\cbor.pdb"
Copy-Item "${SRC}\${ZLIB}\zlib.dir\${Config}\vc${SDK}.pdb" `
"${DEST}\zlib.pdb"
"${DEST}\zlib1.pdb"
Copy-Item "${SRC}\src\fido2_shared.dir\${Config}\vc${SDK}.pdb" `
"${DEST}\fido2.pdb"
}
Function Package-StaticPDBs(${SRC}, ${DEST}) {
Copy-Item "${SRC}\${LIBRESSL}\crypto\Release\crypto-${LibCrypto}.pdb" `
Copy-Item "${SRC}\${LIBRESSL}\crypto\crypto_obj.dir\${Config}\crypto_obj.pdb" `
"${DEST}\crypto-${LibCrypto}.pdb"
Copy-Item "${SRC}\${LIBCBOR}\src\Release\cbor.pdb" `
Copy-Item "${SRC}\${LIBCBOR}\src\${Config}\cbor.pdb" `
"${DEST}\cbor.pdb"
Copy-Item "${SRC}\${ZLIB}\Release\zlibstatic.pdb" `
"${DEST}\zlib.pdb"
Copy-Item "${SRC}\src\Release\fido2_static.pdb" `
Copy-Item "${SRC}\${ZLIB}\${Config}\zlibstatic.pdb" `
"${DEST}\zlib1.pdb"
Copy-Item "${SRC}\src\${Config}\fido2_static.pdb" `
"${DEST}\fido2.pdb"
}