diff -Nru libfido2-1.10.0/CMakeLists.txt libfido2-1.11.0/CMakeLists.txt --- libfido2-1.10.0/CMakeLists.txt 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/CMakeLists.txt 2022-05-03 07:10:36.000000000 +0000 @@ -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_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(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 @@ list(APPEND CHECK_VARIABLES HAVE_ARC4RANDOM_BUF + HAVE_ASPRINTF HAVE_CBOR_H HAVE_CLOCK_GETTIME HAVE_ENDIAN_H @@ -166,8 +169,8 @@ "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 @@ 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 @@ endif() if(NFC_LINUX) - add_definitions(-DNFC_LINUX) + add_definitions(-DUSE_NFC) endif() if(WIN32) @@ -285,10 +299,6 @@ 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 @@ 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 @@ " /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_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 @@ 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_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 @@ endif() if(NOT WIN32) - if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT FUZZ) - enable_testing() - subdirs(regress) - endif() if(FUZZ) subdirs(fuzz) endif() diff -Nru libfido2-1.10.0/debian/changelog libfido2-1.11.0/debian/changelog --- libfido2-1.10.0/debian/changelog 2022-01-20 14:28:29.000000000 +0000 +++ libfido2-1.11.0/debian/changelog 2022-05-10 23:51:00.000000000 +0000 @@ -1,3 +1,10 @@ +libfido2 (1.11.0-1) unstable; urgency=medium + + * New upstream release. + * Speed up debian/run-regression-tests.sh. + + -- Colin Watson Wed, 11 May 2022 00:51:00 +0100 + libfido2 (1.10.0-1) unstable; urgency=medium * New upstream release. diff -Nru libfido2-1.10.0/debian/control libfido2-1.11.0/debian/control --- libfido2-1.10.0/debian/control 2022-01-20 14:28:29.000000000 +0000 +++ libfido2-1.11.0/debian/control 2022-05-10 23:51:00.000000000 +0000 @@ -24,9 +24,9 @@ Multi-Arch: same Depends: ${shlibs:Depends}, ${misc:Depends} Description: library for generating and verifying FIDO 2.0 objects - A library for communicating with a FIDO device over USB, and for verifying - attestation and assertion signatures. FIDO U2F (CTAP 1) and FIDO 2.0 (CTAP 2) - are supported. + A library for communicating with a FIDO device over USB or NFC, and for + verifying attestation and assertion signatures. FIDO U2F (CTAP 1) and FIDO + 2.0 (CTAP 2) are supported. . This package contains the library. @@ -36,9 +36,9 @@ Multi-Arch: same Depends: libfido2-1 (= ${binary:Version}), libssl-dev, ${misc:Depends} Description: library for generating and verifying FIDO 2.0 objects -- headers - A library for communicating with a FIDO device over USB, and for verifying - attestation and assertion signatures. FIDO U2F (CTAP 1) and FIDO 2.0 (CTAP 2) - are supported. + A library for communicating with a FIDO device over USB or NFC, and for + verifying attestation and assertion signatures. FIDO U2F (CTAP 1) and FIDO + 2.0 (CTAP 2) are supported. . This package contains the library's development headers. @@ -50,9 +50,9 @@ libfido2-dev (<< ${source:Version}.1~), libfido2-dev (>= ${source:Version}) Description: library for generating and verifying FIDO 2.0 objects -- documentation - A library for communicating with a FIDO device over USB, and for verifying - attestation and assertion signatures. FIDO U2F (CTAP 1) and FIDO 2.0 (CTAP 2) - are supported. + A library for communicating with a FIDO device over USB or NFC, and for + verifying attestation and assertion signatures. FIDO U2F (CTAP 1) and FIDO + 2.0 (CTAP 2) are supported. . This package contains the library's documentation (manpages & HTML). diff -Nru libfido2-1.10.0/debian/libfido2-1.symbols libfido2-1.11.0/debian/libfido2-1.symbols --- libfido2-1.10.0/debian/libfido2-1.symbols 2022-01-20 14:28:29.000000000 +0000 +++ libfido2-1.11.0/debian/libfido2-1.symbols 2022-05-10 23:51:00.000000000 +0000 @@ -89,6 +89,7 @@ fido_cbor_info_maxcredbloblen@Base 1.7.0 fido_cbor_info_maxcredcntlst@Base 1.5.0 fido_cbor_info_maxcredidlen@Base 1.5.0 + fido_cbor_info_maxlargeblob@Base 1.11.0 fido_cbor_info_maxmsgsiz@Base 1.1.0 fido_cbor_info_new@Base 1.1.0 fido_cbor_info_options_len@Base 1.1.0 diff -Nru libfido2-1.10.0/debian/run-regression-tests.sh libfido2-1.11.0/debian/run-regression-tests.sh --- libfido2-1.10.0/debian/run-regression-tests.sh 2022-01-20 14:28:29.000000000 +0000 +++ libfido2-1.11.0/debian/run-regression-tests.sh 2022-05-10 23:51:00.000000000 +0000 @@ -28,6 +28,7 @@ cd ${regression_test_dir} cmake -DCMAKE_BUILD_TYPE=Debug ../../ make +make regress echo "SUCCESS: regression tests passed" # the way the tests are run, by just calling the built binary in a @@ -45,12 +46,10 @@ echo "ERROR: failure was not injected correctly into regress/cred.c" exit $result fi -rm -rf ${regression_test_dir} -mkdir ${regression_test_dir} cd ${regression_test_dir} -cmake -DCMAKE_BUILD_TYPE=Debug ../../ +make result=0 -make || result=$? +make regress || result=$? if [ "$result" -ne 0 ]; then echo "SUCCESS: the expected failure happened" result=0 diff -Nru libfido2-1.10.0/examples/CMakeLists.txt libfido2-1.11.0/examples/CMakeLists.txt --- libfido2-1.10.0/examples/CMakeLists.txt 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/examples/CMakeLists.txt 2022-05-03 07:10:36.000000000 +0000 @@ -13,17 +13,6 @@ 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 diff -Nru libfido2-1.10.0/examples/info.c libfido2-1.11.0/examples/info.c --- libfido2-1.10.0/examples/info.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/examples/info.c 2022-05-03 07:10:36.000000000 +0000 @@ -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. */ @@ -183,6 +183,16 @@ } /* + * 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. */ static void @@ -264,6 +274,9 @@ /* 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)); diff -Nru libfido2-1.10.0/examples/select.c libfido2-1.11.0/examples/select.c --- libfido2-1.10.0/examples/select.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/examples/select.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ return (-1); } - Sleep(rqtp->tv_nsec / 1000000); + Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000)); return (0); } diff -Nru libfido2-1.10.0/examples/setpin.c libfido2-1.11.0/examples/setpin.c --- libfido2-1.10.0/examples/setpin.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/examples/setpin.c 2022-05-03 07:10:36.000000000 +0000 @@ -29,7 +29,7 @@ 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); diff -Nru libfido2-1.10.0/fuzz/CMakeLists.txt libfido2-1.11.0/fuzz/CMakeLists.txt --- libfido2-1.10.0/fuzz/CMakeLists.txt 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/CMakeLists.txt 2022-05-03 07:10:36.000000000 +0000 @@ -61,3 +61,9 @@ 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) diff -Nru libfido2-1.10.0/fuzz/Dockerfile libfido2-1.11.0/fuzz/Dockerfile --- libfido2-1.10.0/fuzz/Dockerfile 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/Dockerfile 2022-05-03 07:10:36.000000000 +0000 @@ -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 diff -Nru libfido2-1.10.0/fuzz/dummy.h libfido2-1.11.0/fuzz/dummy.h --- libfido2-1.10.0/fuzz/dummy.h 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/dummy.h 2022-05-03 07:10:36.000000000 +0000 @@ -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_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[] = { diff -Nru libfido2-1.10.0/fuzz/export.gnu libfido2-1.11.0/fuzz/export.gnu --- libfido2-1.10.0/fuzz/export.gnu 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/export.gnu 2022-05-03 07:10:36.000000000 +0000 @@ -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: diff -Nru libfido2-1.10.0/fuzz/functions.txt libfido2-1.11.0/fuzz/functions.txt --- libfido2-1.10.0/fuzz/functions.txt 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/functions.txt 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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_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: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 @@ 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 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_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_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_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 @@ ------------------------------------------------------------------------------------------------------------------- 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_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: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_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_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_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 @@ 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_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 @@ 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: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_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_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_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_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_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_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_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_linux.c': +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 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_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_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_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_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 @@ 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_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: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 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 43 3 93.02% 43 1 97.67% +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: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% diff -Nru libfido2-1.10.0/fuzz/fuzz_mgmt.c libfido2-1.11.0/fuzz/fuzz_mgmt.c --- libfido2-1.10.0/fuzz/fuzz_mgmt.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/fuzz_mgmt.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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)); diff -Nru libfido2-1.10.0/fuzz/fuzz_pcsc.c libfido2-1.11.0/fuzz/fuzz_pcsc.c --- libfido2-1.10.0/fuzz/fuzz_pcsc.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/fuzz/fuzz_pcsc.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#include +#include +#include +#include +#include + +#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); + } +} diff -Nru libfido2-1.10.0/fuzz/Makefile libfido2-1.11.0/fuzz/Makefile --- libfido2-1.10.0/fuzz/Makefile 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/Makefile 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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 @@ 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 diff -Nru libfido2-1.10.0/fuzz/mutator_aux.c libfido2-1.11.0/fuzz/mutator_aux.c --- libfido2-1.10.0/fuzz/mutator_aux.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/mutator_aux.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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); diff -Nru libfido2-1.10.0/fuzz/mutator_aux.h libfido2-1.11.0/fuzz/mutator_aux.h --- libfido2-1.10.0/fuzz/mutator_aux.h 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/mutator_aux.h 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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 @@ uint32_t uniform_random(uint32_t); +void set_pcsc_parameters(const struct blob *); +void set_pcsc_io_functions(int (*)(void *, u_char *, size_t, int), + int (*)(void *, const u_char *, size_t), void (*)(const void *, size_t)); + #endif /* !_MUTATOR_AUX_H */ diff -Nru libfido2-1.10.0/fuzz/pcsc.c libfido2-1.11.0/fuzz/pcsc.c --- libfido2-1.10.0/fuzz/pcsc.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/fuzz/pcsc.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#include +#include +#include +#include +#include + +#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 files /tmp/tmp2e6v0yvg/w_ESyb0Ty_/libfido2-1.10.0/fuzz/report.tgz and /tmp/tmp2e6v0yvg/CdSAWq7cd9/libfido2-1.11.0/fuzz/report.tgz differ diff -Nru libfido2-1.10.0/fuzz/summary.txt libfido2-1.11.0/fuzz/summary.txt --- libfido2-1.10.0/fuzz/summary.txt 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/summary.txt 2022-05-03 07:10:36.000000000 +0000 @@ -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/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% diff -Nru libfido2-1.10.0/fuzz/wiredata_fido2.h libfido2-1.11.0/fuzz/wiredata_fido2.h --- libfido2-1.10.0/fuzz/wiredata_fido2.h 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/wiredata_fido2.h 2022-05-03 07:10:36.000000000 +0000 @@ -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 */ diff -Nru libfido2-1.10.0/fuzz/wrap.c libfido2-1.11.0/fuzz/wrap.c --- libfido2-1.10.0/fuzz/wrap.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/wrap.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 #include #include +#include #include "mutator_aux.h" @@ -635,3 +636,51 @@ (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; +} diff -Nru libfido2-1.10.0/fuzz/wrapped.sym libfido2-1.11.0/fuzz/wrapped.sym --- libfido2-1.10.0/fuzz/wrapped.sym 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/fuzz/wrapped.sym 2022-05-03 07:10:36.000000000 +0000 @@ -1,3 +1,4 @@ +asprintf bind BN_bin2bn BN_bn2bin @@ -24,6 +25,8 @@ 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 @@ RSA_new RSA_pkey_ctx_ctrl RSA_set0_key +SCardConnect +SCardDisconnect +SCardEstablishContext +SCardListReaders +SCardReleaseContext +SCardTransmit SHA1 SHA256 strdup diff -Nru libfido2-1.10.0/man/CMakeLists.txt libfido2-1.11.0/man/CMakeLists.txt --- libfido2-1.10.0/man/CMakeLists.txt 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/man/CMakeLists.txt 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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 @@ # 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 @@ 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 @@ 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 @@ 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() diff -Nru libfido2-1.10.0/man/fido2-token.1 libfido2-1.11.0/man/fido2-token.1 --- libfido2-1.10.0/man/fido2-token.1 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/man/fido2-token.1 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ .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 @@ .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 @@ 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 diff -Nru libfido2-1.10.0/man/fido_assert_new.3 libfido2-1.11.0/man/fido_assert_new.3 --- libfido2-1.10.0/man/fido_assert_new.3 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/man/fido_assert_new.3 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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 diff -Nru libfido2-1.10.0/man/fido_assert_set_authdata.3 libfido2-1.11.0/man/fido_assert_set_authdata.3 --- libfido2-1.10.0/man/fido_assert_set_authdata.3 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/man/fido_assert_set_authdata.3 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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. diff -Nru libfido2-1.10.0/man/fido_cbor_info_new.3 libfido2-1.11.0/man/fido_cbor_info_new.3 --- libfido2-1.10.0/man/fido_cbor_info_new.3 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/man/fido_cbor_info_new.3 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ .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 . diff -Nru libfido2-1.10.0/man/fido_dev_enable_entattest.3 libfido2-1.11.0/man/fido_dev_enable_entattest.3 --- libfido2-1.10.0/man/fido_dev_enable_entattest.3 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/man/fido_dev_enable_entattest.3 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ .Pp The .Fn fido_dev_force_pin_change -instructs +function instructs .Fa dev to require a PIN change. Subsequent PIN authentication attempts against diff -Nru libfido2-1.10.0/man/fido_dev_info_manifest.3 libfido2-1.11.0/man/fido_dev_info_manifest.3 --- libfido2-1.10.0/man/fido_dev_info_manifest.3 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/man/fido_dev_info_manifest.3 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ .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 diff -Nru libfido2-1.10.0/NEWS libfido2-1.11.0/NEWS --- libfido2-1.10.0/NEWS 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/NEWS 2022-05-03 07:10:36.000000000 +0000 @@ -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. diff -Nru libfido2-1.10.0/openbsd-compat/bsd-asprintf.c libfido2-1.11.0/openbsd-compat/bsd-asprintf.c --- libfido2-1.10.0/openbsd-compat/bsd-asprintf.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/openbsd-compat/bsd-asprintf.c 2022-05-03 07:10:36.000000000 +0000 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2004 Darren Tucker. + * + * Based originally on asprintf.c from OpenBSD: + * Copyright (c) 1997 Todd C. Miller + * + * 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 +#include /* for INT_MAX */ +#include +#include /* for vsnprintf */ +#include + +#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 diff -Nru libfido2-1.10.0/openbsd-compat/openbsd-compat.h libfido2-1.11.0/openbsd-compat/openbsd-compat.h --- libfido2-1.10.0/openbsd-compat/openbsd-compat.h 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/openbsd-compat/openbsd-compat.h 2022-05-03 07:10:36.000000000 +0000 @@ -115,4 +115,8 @@ #define IOCTL_REQ(x) ((int)(x)) #endif +#if !defined(HAVE_ASPRINTF) +int asprintf(char **, const char *, ...); +#endif + #endif /* !_OPENBSD_COMPAT_H */ diff -Nru libfido2-1.10.0/README.adoc libfido2-1.11.0/README.adoc --- libfido2-1.10.0/README.adoc 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/README.adoc 2022-05-03 07:10:36.000000000 +0000 @@ -7,7 +7,7 @@ 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 @@ *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 @@ * 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,13 +68,31 @@ $ 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 + +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. + +KERNEL=="hidraw*", SUBSYSTEM=="hidraw", \ + MODE="0664", GROUP="plugdev", ATTRS{idVendor}=="1050" +---- ==== macOS $ brew install libfido2 -Or from source, on UNIX-like systems: +==== 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 @@ -74,23 +100,46 @@ 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: - ----- -#udev rule for allowing HID access to Yubico devices for FIDO support. - -KERNEL=="hidraw*", SUBSYSTEM=="hidraw", \ - MODE="0664", GROUP="plugdev", ATTRS{idVendor}=="1050" ----- +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/. diff -Nru libfido2-1.10.0/regress/assert.c libfido2-1.11.0/regress/assert.c --- libfido2-1.10.0/regress/assert.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/regress/assert.c 2022-05-03 07:10:36.000000000 +0000 @@ -4,16 +4,19 @@ * license that can be found in the LICENSE file. */ -#define _FIDO_INTERNAL +#undef NDEBUG #include +#include + +#define _FIDO_INTERNAL + #include #include #include #include -#include -#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 @@ { (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 diff -Nru libfido2-1.10.0/regress/CMakeLists.txt libfido2-1.11.0/regress/CMakeLists.txt --- libfido2-1.10.0/regress/CMakeLists.txt 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/regress/CMakeLists.txt 2022-05-03 07:10:36.000000000 +0000 @@ -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() diff -Nru libfido2-1.10.0/regress/compress.c libfido2-1.11.0/regress/compress.c --- libfido2-1.10.0/regress/compress.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/regress/compress.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#include + +#include + +#define _FIDO_INTERNAL + +#include + +/* + * 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); +} diff -Nru libfido2-1.10.0/regress/cred.c libfido2-1.11.0/regress/cred.c --- libfido2-1.10.0/regress/cred.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/regress/cred.c 2022-05-03 07:10:36.000000000 +0000 @@ -4,12 +4,16 @@ * license that can be found in the LICENSE file. */ +#undef NDEBUG + #include -#include -#include #include -#define FAKE_DEV_HANDLE ((void *)0xdeadbeef) +#define _FIDO_INTERNAL + +#include + +static int fake_dev_handle; static const unsigned char cdh[32] = { 0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb, @@ -1384,13 +1388,13 @@ { (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 diff -Nru libfido2-1.10.0/regress/dev.c libfido2-1.11.0/regress/dev.c --- libfido2-1.10.0/regress/dev.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/regress/dev.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 -#include -#include #include #include +#define _FIDO_INTERNAL + +#include + #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 @@ 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 @@ { struct timespec tv; - assert(handle == FAKE_DEV_HANDLE); + assert(handle == &fake_dev_handle); assert(ptr != NULL); assert(len == REPORT_LEN); @@ -113,7 +132,14 @@ 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); diff -Nru libfido2-1.10.0/regress/eddsa.c libfido2-1.11.0/regress/eddsa.c --- libfido2-1.10.0/regress/eddsa.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/regress/eddsa.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#include + +#define _FIDO_INTERNAL + +#include +#include + +#include +#include + +#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); +} diff -Nru libfido2-1.10.0/regress/es256.c libfido2-1.11.0/regress/es256.c --- libfido2-1.10.0/regress/es256.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/regress/es256.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#include + +#define _FIDO_INTERNAL + +#include +#include + +#include +#include + +#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); +} diff -Nru libfido2-1.10.0/regress/rs256.c libfido2-1.11.0/regress/rs256.c --- libfido2-1.10.0/regress/rs256.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/regress/rs256.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#include + +#define _FIDO_INTERNAL + +#include +#include + +#include +#include + +#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); +} diff -Nru libfido2-1.10.0/src/CMakeLists.txt libfido2-1.11.0/src/CMakeLists.txt --- libfido2-1.10.0/src/CMakeLists.txt 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/CMakeLists.txt 2022-05-03 07:10:36.000000000 +0000 @@ -33,20 +33,28 @@ 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 @@ 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 @@ ${BASE_LIBRARIES} ${HIDAPI_LIBRARIES} ${ZLIB_LIBRARIES} + ${PCSC_LIBRARIES} ) # static library diff -Nru libfido2-1.10.0/src/compress.c libfido2-1.11.0/src/compress.c --- libfido2-1.10.0/src/compress.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/compress.c 2022-05-03 07:10:36.000000000 +0000 @@ -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); } diff -Nru libfido2-1.10.0/src/dev.c libfido2-1.11.0/src/dev.c --- libfido2-1.10.0/src/dev.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/dev.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 #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 @@ 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 @@ return (FIDO_OK); } -int -fido_dev_register_manifest_func(const dev_manifest_func_t f) -{ - dev_manifest_func_node_t *prev, *curr, *n; - - 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) +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; + size_t ndevs = 0; + int r; - 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 @@ { 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 @@ 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 @@ -413,106 +357,6 @@ 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) diff -Nru libfido2-1.10.0/src/eddsa.c libfido2-1.11.0/src/eddsa.c --- libfido2-1.10.0/src/eddsa.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/eddsa.c 2022-05-03 07:10:36.000000000 +0000 @@ -122,11 +122,20 @@ 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 @@ { 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); diff -Nru libfido2-1.10.0/src/es256.c libfido2-1.11.0/src/es256.c --- libfido2-1.10.0/src/es256.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/es256.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ (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 @@ 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 @@ 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 @@ 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 @@ 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__); diff -Nru libfido2-1.10.0/src/export.gnu libfido2-1.11.0/src/export.gnu --- libfido2-1.10.0/src/export.gnu 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/export.gnu 2022-05-03 07:10:36.000000000 +0000 @@ -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; diff -Nru libfido2-1.10.0/src/export.llvm libfido2-1.11.0/src/export.llvm --- libfido2-1.10.0/src/export.llvm 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/export.llvm 2022-05-03 07:10:36.000000000 +0000 @@ -83,10 +83,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 diff -Nru libfido2-1.10.0/src/export.msvc libfido2-1.11.0/src/export.msvc --- libfido2-1.10.0/src/export.msvc 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/export.msvc 2022-05-03 07:10:36.000000000 +0000 @@ -84,10 +84,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 diff -Nru libfido2-1.10.0/src/extern.h libfido2-1.11.0/src/extern.h --- libfido2-1.10.0/src/extern.h 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/extern.h 2022-05-03 07:10:36.000000000 +0000 @@ -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_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_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_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 @@ /* 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 @@ #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" */ diff -Nru libfido2-1.10.0/src/fido/types.h libfido2-1.11.0/src/fido/types.h --- libfido2-1.10.0/src/fido/types.h 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/fido/types.h 2022-05-03 07:10:36.000000000 +0000 @@ -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 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 @@ } 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 { diff -Nru libfido2-1.10.0/src/fido.h libfido2-1.11.0/src/fido.h --- libfido2-1.10.0/src/fido.h 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/fido.h 2022-05-03 07:10:36.000000000 +0000 @@ -144,7 +144,9 @@ 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_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 *); diff -Nru libfido2-1.10.0/src/hid_freebsd.c libfido2-1.11.0/src/hid_freebsd.c --- libfido2-1.10.0/src/hid_freebsd.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/hid_freebsd.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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 @@ char path[64]; size_t i; - *olen = 0; - if (ilen == 0) return (FIDO_OK); /* nothing to do */ diff -Nru libfido2-1.10.0/src/hid_openbsd.c libfido2-1.11.0/src/hid_openbsd.c --- libfido2-1.10.0/src/hid_openbsd.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/hid_openbsd.c 2022-05-03 07:10:36.000000000 +0000 @@ -27,14 +27,58 @@ 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 @@ 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 (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; + 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); } - di->vendor_id = (int16_t)udi.udi_vendorNo; - di->product_id = (int16_t)udi.udi_productNo; - (*olen)++; } - return FIDO_OK; + return (FIDO_OK); } /* diff -Nru libfido2-1.10.0/src/hid_osx.c libfido2-1.11.0/src/hid_osx.c --- libfido2-1.10.0/src/hid_osx.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/hid_osx.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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 @@ 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); } diff -Nru libfido2-1.10.0/src/info.c libfido2-1.11.0/src/info.c --- libfido2-1.10.0/src/info.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/info.c 2022-05-03 07:10:36.000000000 +0000 @@ -268,6 +268,8 @@ 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 */ @@ -462,6 +464,12 @@ } 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) { return (ci->fwversion); diff -Nru libfido2-1.10.0/src/nfc.c libfido2-1.11.0/src/nfc.c --- libfido2-1.10.0/src/nfc.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/src/nfc.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#include + +#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 */ diff -Nru libfido2-1.10.0/src/nfc_linux.c libfido2-1.11.0/src/nfc_linux.c --- libfido2-1.10.0/src/nfc_linux.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/nfc_linux.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 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 @@ 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 @@ 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 @@ 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 @@ explicit_bzero(di, sizeof(*di)); } - return (ok); + return ok; } static int @@ -410,21 +116,21 @@ 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 @@ *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 @@ if (udev != NULL) udev_unref(udev); - return (r); + return r; } static int @@ -498,17 +204,17 @@ 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 @@ 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 @@ goto fail; } - return (ctx); + return ctx; fail: nfc_free(&ctx); - return (NULL); + return NULL; } void @@ -588,7 +294,7 @@ ctx->sigmask = *sigmask; ctx->sigmaskp = &ctx->sigmask; - return (FIDO_OK); + return FIDO_OK; } int @@ -607,25 +313,25 @@ 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 @@ 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; } diff -Nru libfido2-1.10.0/src/pcsc.c libfido2-1.11.0/src/pcsc.c --- libfido2-1.10.0/src/pcsc.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/src/pcsc.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#include +#else +#include +#endif /* __APPLE__ */ + +#include + +#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; +} diff -Nru libfido2-1.10.0/src/rs1.c libfido2-1.11.0/src/rs1.c --- libfido2-1.10.0/src/rs1.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/rs1.c 2022-05-03 07:10:36.000000000 +0000 @@ -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) { diff -Nru libfido2-1.10.0/src/rs256.c libfido2-1.11.0/src/rs256.c --- libfido2-1.10.0/src/rs256.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/rs256.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ 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 @@ 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 @@ 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)); diff -Nru libfido2-1.10.0/src/touch.c libfido2-1.11.0/src/touch.c --- libfido2-1.10.0/src/touch.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/src/touch.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#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); +} diff -Nru libfido2-1.10.0/src/util.c libfido2-1.11.0/src/util.c --- libfido2-1.10.0/src/util.c 1970-01-01 00:00:00.000000000 +0000 +++ libfido2-1.11.0/src/util.c 2022-05-03 07:10:36.000000000 +0000 @@ -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 +#include +#include + +#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; +} diff -Nru libfido2-1.10.0/src/webauthn.h libfido2-1.11.0/src/webauthn.h --- libfido2-1.10.0/src/webauthn.h 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/webauthn.h 2022-05-03 07:10:36.000000000 +0000 @@ -92,6 +92,9 @@ // - 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 @@ -283,11 +286,64 @@ 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 @@ #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 @@ // User Verification Requirement. DWORD dwUserVerificationRequirement; - // Reserved for future Use + // Flags DWORD dwFlags; // @@ -879,6 +941,17 @@ 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 diff -Nru libfido2-1.10.0/src/winhello.c libfido2-1.11.0/src/winhello.c --- libfido2-1.10.0/src/winhello.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/src/winhello.c 2022-05-03 07:10:36.000000000 +0000 @@ -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. */ @@ -428,6 +428,42 @@ } 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) { int r; @@ -500,6 +536,39 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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; diff -Nru libfido2-1.10.0/tools/CMakeLists.txt libfido2-1.11.0/tools/CMakeLists.txt --- libfido2-1.10.0/tools/CMakeLists.txt 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/tools/CMakeLists.txt 2022-05-03 07:10:36.000000000 +0000 @@ -65,13 +65,6 @@ ${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}) diff -Nru libfido2-1.10.0/tools/token.c libfido2-1.11.0/tools/token.c --- libfido2-1.10.0/tools/token.c 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/tools/token.c 2022-05-03 07:10:36.000000000 +0000 @@ -156,6 +156,12 @@ } static void +print_maxlargeblob(uint64_t maxlargeblob) +{ + printf("maxlargeblob: %d\n", (int)maxlargeblob); +} + +static void print_fwversion(uint64_t fwversion) { printf("fwversion: 0x%x\n", (int)fwversion); @@ -259,6 +265,9 @@ /* 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)); diff -Nru libfido2-1.10.0/udev/70-u2f.rules libfido2-1.11.0/udev/70-u2f.rules --- libfido2-1.10.0/udev/70-u2f.rules 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/udev/70-u2f.rules 2022-05-03 07:10:36.000000000 +0000 @@ -106,6 +106,9 @@ # 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" diff -Nru libfido2-1.10.0/udev/fidodevs libfido2-1.11.0/udev/fidodevs --- libfido2-1.10.0/udev/fidodevs 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/udev/fidodevs 2022-05-03 07:10:36.000000000 +0000 @@ -72,6 +72,7 @@ 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 diff -Nru libfido2-1.10.0/windows/build.ps1 libfido2-1.11.0/windows/build.ps1 --- libfido2-1.10.0/windows/build.ps1 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/windows/build.ps1 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ & $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 @@ -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}" } } diff -Nru libfido2-1.10.0/windows/const.ps1 libfido2-1.11.0/windows/const.ps1 --- libfido2-1.10.0/windows/const.ps1 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/windows/const.ps1 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ -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 diff -Nru libfido2-1.10.0/windows/cygwin.ps1 libfido2-1.11.0/windows/cygwin.ps1 --- libfido2-1.10.0/windows/cygwin.ps1 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/windows/cygwin.ps1 2022-05-03 07:10:36.000000000 +0000 @@ -66,3 +66,4 @@ $Env:PATH = "${Root}\bin\;" + $Env:PATH cmake "-DCMAKE_BUILD_TYPE=${Config}" -B "build-${Config}" make -C "build-${Config}" +make -C "build-${Config}" regress diff -Nru libfido2-1.10.0/windows/release.ps1 libfido2-1.11.0/windows/release.ps1 --- libfido2-1.10.0/windows/release.ps1 2022-01-17 12:42:03.000000000 +0000 +++ libfido2-1.11.0/windows/release.ps1 2022-05-03 07:10:36.000000000 +0000 @@ -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 @@ $InstallPrefixes = @('Win64', 'Win32', 'ARM64', 'ARM') $Types = @('dynamic', 'static') $Config = 'Release' -$LibCrypto = '47' +$LibCrypto = '49' $SDK = '143' . "$PSScriptRoot\const.ps1" @@ -34,7 +34,7 @@ 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-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 @@ 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" }