diff options
72 files changed, 3462 insertions, 986 deletions
| diff --git a/CMakeLists.txt b/CMakeLists.txt index 11a51ac5a645..2f10727d40e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018-2021 Yubico AB. All rights reserved. +# Copyright (c) 2018-2022 Yubico AB. All rights reserved.  # Use of this source code is governed by a BSD-style  # license that can be found in the LICENSE file. @@ -28,18 +28,19 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)  set(CMAKE_COLOR_MAKEFILE OFF)  set(CMAKE_VERBOSE_MAKEFILE ON)  set(FIDO_MAJOR "1") -set(FIDO_MINOR "10") +set(FIDO_MINOR "11")  set(FIDO_PATCH "0")  set(FIDO_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}.${FIDO_PATCH})  option(BUILD_EXAMPLES    "Build example programs"                  ON)  option(BUILD_MANPAGES    "Build man pages"                         ON) -option(BUILD_SHARED_LIBS "Build the shared library"                ON) -option(BUILD_STATIC_LIBS "Build the static library"                ON) +option(BUILD_SHARED_LIBS "Build a shared library"                  ON) +option(BUILD_STATIC_LIBS "Build a static library"                  ON)  option(BUILD_TOOLS       "Build tool programs"                     ON)  option(FUZZ              "Enable fuzzing instrumentation"          OFF)  option(LIBFUZZER         "Build libfuzzer harnesses"               OFF)  option(USE_HIDAPI        "Use hidapi as the HID backend"           OFF) +option(USE_PCSC          "Enable experimental PCSC support"        OFF)  option(USE_WINHELLO      "Abstract Windows Hello as a FIDO device" ON)  option(NFC_LINUX         "Enable NFC support on Linux"             ON) @@ -91,6 +92,7 @@ check_include_files(sys/random.h HAVE_SYS_RANDOM_H)  check_include_files(unistd.h HAVE_UNISTD_H)  check_symbol_exists(arc4random_buf stdlib.h HAVE_ARC4RANDOM_BUF) +check_symbol_exists(asprintf stdio.h HAVE_ASPRINTF)  check_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME)  check_symbol_exists(explicit_bzero string.h HAVE_EXPLICIT_BZERO)  check_symbol_exists(freezero stdlib.h HAVE_FREEZERO) @@ -116,6 +118,7 @@ try_compile(HAVE_POSIX_IOCTL  list(APPEND CHECK_VARIABLES  	HAVE_ARC4RANDOM_BUF +	HAVE_ASPRINTF  	HAVE_CBOR_H  	HAVE_CLOCK_GETTIME  	HAVE_ENDIAN_H @@ -166,8 +169,8 @@ if(MSVC)  		   "building under msvc")  	endif()  	set(CBOR_LIBRARIES cbor) -	set(ZLIB_LIBRARIES zlib) -	set(CRYPTO_LIBRARIES crypto-47) +	set(ZLIB_LIBRARIES zlib1) +	set(CRYPTO_LIBRARIES crypto-49)  	set(MSVC_DISABLED_WARNINGS_LIST  		"C4152" # nonstandard extension used: function/data pointer  			# conversion in expression; @@ -237,6 +240,17 @@ else()  		add_compile_options(-Wno-unused-parameter)  	endif() +	if(FUZZ) +		set(USE_PCSC ON) +		add_definitions(-DFIDO_FUZZ) +	endif() + +	# If building with PCSC, look for pcsc-lite. +	if(USE_PCSC AND NOT (APPLE OR CYGWIN OR MSYS OR MINGW)) +		pkg_search_module(PCSC libpcsclite REQUIRED) +		set(PCSC_LIBRARIES pcsclite) +	endif() +  	if(USE_HIDAPI)  		add_definitions(-DUSE_HIDAPI)  		pkg_search_module(HIDAPI hidapi${HIDAPI_SUFFIX} REQUIRED) @@ -244,7 +258,7 @@ else()  	endif()  	if(NFC_LINUX) -		add_definitions(-DNFC_LINUX) +		add_definitions(-DUSE_NFC)  	endif()  	if(WIN32) @@ -285,10 +299,6 @@ else()  		add_definitions(-DOPENSSL_API_COMPAT=0x10100000L)  	endif() -	if(FUZZ) -		add_definitions(-DFIDO_FUZZ) -	endif() -  	if(LIBFUZZER)  		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link")  	endif() @@ -309,6 +319,10 @@ elseif(WIN32)  endif()  add_definitions(-DTLS=${TLS}) +if(USE_PCSC) +	add_definitions(-DUSE_PCSC) +endif() +  # export list  if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR     CMAKE_C_COMPILER_ID STREQUAL "AppleClang")) @@ -345,16 +359,18 @@ else()  	    " /def:\"${CMAKE_CURRENT_SOURCE_DIR}/src/export.msvc\"")  endif() -include_directories(${CMAKE_SOURCE_DIR}/src) +include_directories(${PROJECT_SOURCE_DIR}/src)  include_directories(${CBOR_INCLUDE_DIRS})  include_directories(${CRYPTO_INCLUDE_DIRS})  include_directories(${HIDAPI_INCLUDE_DIRS}) +include_directories(${PCSC_INCLUDE_DIRS})  include_directories(${UDEV_INCLUDE_DIRS})  include_directories(${ZLIB_INCLUDE_DIRS})  link_directories(${CBOR_LIBRARY_DIRS})  link_directories(${CRYPTO_LIBRARY_DIRS})  link_directories(${HIDAPI_LIBRARY_DIRS}) +link_directories(${PCSC_LIBRARY_DIRS})  link_directories(${UDEV_LIBRARY_DIRS})  link_directories(${ZLIB_LIBRARY_DIRS}) @@ -372,9 +388,14 @@ message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")  message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")  message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}")  message(STATUS "CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") +message(STATUS "CMAKE_CROSSCOMPILING: ${CMAKE_CROSSCOMPILING}") +message(STATUS "CMAKE_GENERATOR_PLATFORM: ${CMAKE_GENERATOR_PLATFORM}") +message(STATUS "CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}") +message(STATUS "CMAKE_HOST_SYSTEM_PROCESSOR: ${CMAKE_HOST_SYSTEM_PROCESSOR}")  message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}")  message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")  message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}") +message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")  message(STATUS "CMAKE_SYSTEM_VERSION: ${CMAKE_SYSTEM_VERSION}")  message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}")  message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}") @@ -392,6 +413,10 @@ if(USE_HIDAPI)  	message(STATUS "HIDAPI_LIBRARY_DIRS: ${HIDAPI_LIBRARY_DIRS}")  	message(STATUS "HIDAPI_VERSION: ${HIDAPI_VERSION}")  endif() +message(STATUS "PCSC_INCLUDE_DIRS: ${PCSC_INCLUDE_DIRS}") +message(STATUS "PCSC_LIBRARIES: ${PCSC_LIBRARIES}") +message(STATUS "PCSC_LIBRARY_DIRS: ${PCSC_LIBRARY_DIRS}") +message(STATUS "PCSC_VERSION: ${PCSC_VERSION}")  message(STATUS "LIBFUZZER: ${LIBFUZZER}")  message(STATUS "TLS: ${TLS}")  message(STATUS "UDEV_INCLUDE_DIRS: ${UDEV_INCLUDE_DIRS}") @@ -400,10 +425,22 @@ message(STATUS "UDEV_LIBRARY_DIRS: ${UDEV_LIBRARY_DIRS}")  message(STATUS "UDEV_RULES_DIR: ${UDEV_RULES_DIR}")  message(STATUS "UDEV_VERSION: ${UDEV_VERSION}")  message(STATUS "USE_HIDAPI: ${USE_HIDAPI}") +message(STATUS "USE_PCSC: ${USE_PCSC}")  message(STATUS "USE_WINHELLO: ${USE_WINHELLO}")  message(STATUS "NFC_LINUX: ${NFC_LINUX}") +if(BUILD_SHARED_LIBS) +	set(_FIDO2_LIBRARY fido2_shared) +elseif(BUILD_STATIC_LIBS) +	set(_FIDO2_LIBRARY fido2) +else() +	message(FATAL_ERROR "Nothing to build (BUILD_*_LIBS=OFF)") +endif() + +enable_testing() +  subdirs(src) +subdirs(regress)  if(BUILD_EXAMPLES)  	subdirs(examples)  endif() @@ -415,10 +452,6 @@ if(BUILD_MANPAGES)  endif()  if(NOT WIN32) -	if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT FUZZ) -		enable_testing() -		subdirs(regress) -	endif()  	if(FUZZ)  		subdirs(fuzz)  	endif() @@ -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 --git a/README.adoc b/README.adoc index 114cc5eed762..c9cdafb5fea8 100644 --- a/README.adoc +++ b/README.adoc @@ -7,7 +7,7 @@ image:https://github.com/yubico/libfido2/workflows/fuzzer/badge.svg["Fuzz Status  image:https://oss-fuzz-build-logs.storage.googleapis.com/badges/libfido2.svg["Fuzz Status (oss-fuzz)", link="https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:libfido2"]  *libfido2* provides library functionality and command-line tools to -communicate with a FIDO device over USB, and to verify attestation and +communicate with a FIDO device over USB or NFC, and to verify attestation and  assertion signatures.  *libfido2* supports the FIDO U2F (CTAP 1) and FIDO2 (CTAP 2) protocols. @@ -23,8 +23,6 @@ file for the full license text.  *libfido2* is known to work on Linux, macOS, Windows, OpenBSD, and FreeBSD. -NFC support is available on Linux and Windows. -  === Documentation  Documentation is available in troff and HTML formats. An @@ -38,19 +36,29 @@ is also available.  * Perl: https://github.com/jacquesg/p5-FIDO-Raw[p5-FIDO-Raw]  * Rust: https://github.com/PvdBerg1998/libfido2[libfido2] +=== Releases + +The current release of *libfido2* is 1.11.0. Signed release tarballs are +available at Yubico's +https://developers.yubico.com/libfido2/Releases[release page]. + +=== Dependencies + +*libfido2* depends on https://github.com/pjk/libcbor[libcbor], +https://www.openssl.org[OpenSSL] 1.1 or newer, and https://zlib.net[zlib]. +On Linux, libudev +(part of https://www.freedesktop.org/wiki/Software/systemd[systemd]) is also +required. +  === Installation -==== Releases +==== Fedora 35 and 34 -The current release of *libfido2* is 1.10.0. Please consult Yubico's -https://developers.yubico.com/libfido2/Releases[release page] for source -and binary releases. +  $ sudo dnf install libfido2 libfido2-devel fido2-tools -==== Ubuntu 20.04 (Focal) +==== Ubuntu 22.04 (Jammy) and 20.04 (Focal) -  $ sudo apt install libfido2-1 -  $ sudo apt install libfido2-dev -  $ sudo apt install libfido2-doc +  $ sudo apt install libfido2-1 libfido2-dev libfido2-doc fido2-tools  Alternatively, newer versions of *libfido2* are available in Yubico's PPA.  Follow the instructions for Ubuntu 18.04 (Bionic) below. @@ -60,13 +68,31 @@ Follow the instructions for Ubuntu 18.04 (Bionic) below.    $ sudo apt install software-properties-common    $ sudo apt-add-repository ppa:yubico/stable    $ sudo apt update -  $ sudo apt install libfido2-dev +  $ sudo apt install libfido2-1 libfido2-dev libfido2-doc fido2-tools + +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 @@ Or from source, on UNIX-like systems:  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 --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index ad3d44faad6b..e558b620fd6e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -13,17 +13,6 @@ if(WIN32 AND BUILD_SHARED_LIBS AND NOT CYGWIN AND NOT MSYS)  	list(APPEND COMPAT_SOURCES ../openbsd-compat/posix_win.c)  endif() -# set the library to link against -if(BUILD_STATIC_LIBS) -	# drop -rdynamic -	set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -	set(_FIDO2_LIBRARY fido2) -elseif(BUILD_SHARED_LIBS) -	set(_FIDO2_LIBRARY fido2_shared) -else() -	set(_FIDO2_LIBRARY ${CRYPTO_LIBRARIES} fido2) -endif() -  # enable -Wconversion -Wsign-conversion  if(NOT MSVC)  	set_source_files_properties(assert.c cred.c info.c manifest.c reset.c diff --git a/examples/info.c b/examples/info.c index 72b786a8bd83..1098580eec6f 100644 --- a/examples/info.c +++ b/examples/info.c @@ -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 @@ print_maxcredidlen(uint64_t maxcredidlen)  }  /* + * Auxiliary function to print the maximum size of an authenticator's + * serialized largeBlob array. + */ +static void +print_maxlargeblob(uint64_t maxlargeblob) +{ +	printf("maxlargeblob: %d\n", (int)maxlargeblob); +} + +/*   * Auxiliary function to print an authenticator's firmware version on stdout.   */  static void @@ -264,6 +274,9 @@ getinfo(const char *path)  	/* print maximum length of a credential ID */  	print_maxcredidlen(fido_cbor_info_maxcredidlen(ci)); +	/* print maximum length of largeBlob array */ +	print_maxlargeblob(fido_cbor_info_maxlargeblob(ci)); +  	/* print firmware version */  	print_fwversion(fido_cbor_info_fwversion(ci)); diff --git a/examples/select.c b/examples/select.c index 6ede9b490a95..05f6a331fd4c 100644 --- a/examples/select.c +++ b/examples/select.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2020 Yubico AB. All rights reserved. + * Copyright (c) 2020-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -23,7 +23,7 @@ nanosleep(const struct timespec *rqtp, struct timespec *rmtp)  		return (-1);  	} -	Sleep(rqtp->tv_nsec / 1000000); +	Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000));  	return (0);  } diff --git a/examples/setpin.c b/examples/setpin.c index 4b9e792769d9..7fa0dcc764f3 100644 --- a/examples/setpin.c +++ b/examples/setpin.c @@ -29,7 +29,7 @@ setpin(const char *path, const char *pin, const char *oldpin)  		errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);  	if ((r = fido_dev_set_pin(dev, pin, oldpin)) != FIDO_OK) -		errx(1, "fido_setpin: %s (0x%x)", fido_strerr(r), r); +		errx(1, "fido_dev_set_pin: %s (0x%x)", fido_strerr(r), r);  	if ((r = fido_dev_close(dev)) != FIDO_OK)  		errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r); diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index b1eebd55481b..4b6fdfbfca4f 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt @@ -61,3 +61,9 @@ add_executable(fuzz_largeblob fuzz_largeblob.c ${COMMON_SOURCES} ${COMPAT_SOURCE  target_compile_options(fuzz_largeblob PRIVATE ${FUZZ_LDFLAGS})  set_target_properties(fuzz_largeblob PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS})  target_link_libraries(fuzz_largeblob fido2_shared) + +# fuzz_pcsc +add_executable(fuzz_pcsc fuzz_pcsc.c ${COMMON_SOURCES} ${COMPAT_SOURCES}) +target_compile_options(fuzz_pcsc PRIVATE ${FUZZ_LDFLAGS}) +set_target_properties(fuzz_pcsc PROPERTIES LINK_FLAGS ${FUZZ_LDFLAGS}) +target_link_libraries(fuzz_pcsc fido2_shared) diff --git a/fuzz/Dockerfile b/fuzz/Dockerfile index aefe1980ada4..a899df2c3ddd 100644 --- a/fuzz/Dockerfile +++ b/fuzz/Dockerfile @@ -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 --git a/fuzz/Makefile b/fuzz/Makefile index ce3fee73c69c..6abf59c3e69d 100644 --- a/fuzz/Makefile +++ b/fuzz/Makefile @@ -1,13 +1,13 @@ -# Copyright (c) 2019-2021 Yubico AB. All rights reserved. +# Copyright (c) 2019-2022 Yubico AB. All rights reserved.  # Use of this source code is governed by a BSD-style  # license that can be found in the LICENSE file. -IMAGE		:= libfido2-coverage:1.10.0 +IMAGE		:= libfido2-coverage:1.11.2  RUNNER		:= libfido2-runner -PROFDATA	:= llvm-profdata-12 -COV		:= llvm-cov-12 +PROFDATA	:= llvm-profdata-14 +COV		:= llvm-cov-14  TARGETS		:= fuzz_assert fuzz_bio fuzz_cred fuzz_credman fuzz_hid \ -		   fuzz_largeblob fuzz_netlink fuzz_mgmt +		   fuzz_largeblob fuzz_netlink fuzz_mgmt fuzz_pcsc  CORPORA		:= $(foreach f,${TARGETS},${f}/corpus)  MINIFY		:= $(foreach f,${TARGETS},/minify/${f}/corpus)  REMOTE		:= gs://libfido2-corpus.clusterfuzz-external.appspot.com @@ -24,7 +24,7 @@ run: build  sync: run  	tar Ccf .. - src fuzz | docker exec -i ${RUNNER} tar Cxf /libfido2 - -	docker exec ${RUNNER} make -C libfido2/build +	docker exec ${RUNNER} make -C /libfido2/build  corpus: sync  	docker exec ${RUNNER} /bin/sh -c 'cd /libfido2/fuzz && rm -rf ${TARGETS}' @@ -45,23 +45,24 @@ corpus.tgz-: ${MINIFY}  profdata: run  	docker exec ${RUNNER} /bin/sh -c 'rm -f /$@ && ${PROFDATA} \ -		merge -sparse profraw/* -o $@' +		merge -sparse /profraw/* -o /$@'  report.tgz: profdata  	docker exec ${RUNNER} /bin/sh -c 'rm -rf /report && mkdir /report && \  		${COV} show -format=html -tab-size=8 -instr-profile=/$< \ -		--show-branch-summary=false -output-dir=/report \ -		/libfido2/build/src/libfido2.so' +		-ignore-filename-regex=pcsclite.h --show-branch-summary=false \ +		-output-dir=/report /libfido2/build/src/libfido2.so'  	docker exec -i ${RUNNER} tar Czcf / - report > $@  summary.txt: profdata  	docker exec ${RUNNER} ${COV} report -use-color=false \ -		--show-branch-summary=false /libfido2/build/src/libfido2.so \ -		-instr-profile=/$< > $@ +		-ignore-filename-regex=pcsclite.h --show-branch-summary=false \ +		/libfido2/build/src/libfido2.so -instr-profile=/$< > $@  functions.txt: profdata  	docker exec ${RUNNER} /bin/sh -c '${COV} report -use-color=false \ -		-show-functions --show-branch-summary=false -instr-profile=/$< \ +		-ignore-filename-regex=pcsclite.h -show-functions \ +		--show-branch-summary=false -instr-profile=/$< \  		/libfido2/build/src/libfido2.so /libfido2/src/*.[ch]' > $@  clean: run diff --git a/fuzz/dummy.h b/fuzz/dummy.h index 95744eba634b..b0225440e5da 100644 --- a/fuzz/dummy.h +++ b/fuzz/dummy.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2020 Yubico AB. All rights reserved. + * Copyright (c) 2020-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -18,6 +18,8 @@ const char dummy_rp_name[] = "sweet home localhost";  const char dummy_user_icon[] = "an icon";  const char dummy_user_name[] = "john smith";  const char dummy_user_nick[] = "jsmith"; +const char dummy_pcsc_list[] = "reader1\0reader2\0reader3\0\0"; +const char dummy_pcsc_path[] = "pcsc://slot7";  const uint8_t dummy_id[] = { 0x5e, 0xd2 };  const uint8_t dummy_user_id[] = { diff --git a/fuzz/export.gnu b/fuzz/export.gnu index cac142ae970e..0ce72434fbd8 100644 --- a/fuzz/export.gnu +++ b/fuzz/export.gnu @@ -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 --git a/fuzz/functions.txt b/fuzz/functions.txt index 946682d07d00..9c1a03cffb0b 100644 --- a/fuzz/functions.txt +++ b/fuzz/functions.txt @@ -1,16 +1,16 @@  File '/libfido2/src/aes256.c':  Name                         Regions    Miss   Cover     Lines    Miss   Cover  -------------------------------------------------------------------------------------------------------- -aes256_cbc_enc                     3       0 100.00%         4       0 100.00% -aes256_cbc_dec                     3       0 100.00%         4       0 100.00% +aes256_cbc_enc                     4       0 100.00%         4       0 100.00% +aes256_cbc_dec                     4       0 100.00%         4       0 100.00%  aes256_gcm_enc                     1       0 100.00%         3       0 100.00%  aes256_gcm_dec                     1       0 100.00%         3       0 100.00%  aes256.c:aes256_cbc_fips          26       2  92.31%        42       7  83.33%  aes256.c:aes256_cbc               29       1  96.55%        36       3  91.67%  aes256.c:aes256_cbc_proto1         1       0 100.00%         5       0 100.00% -aes256.c:aes256_gcm               51       1  98.04%        60       4  93.33% +aes256.c:aes256_gcm               52       1  98.08%        60       4  93.33%  -------------------------------------------------------------------------------------------------------- -TOTAL                            115       4  96.52%       157      14  91.08% +TOTAL                            118       4  96.61%       157      14  91.08%  File '/libfido2/src/assert.c':  Name                                  Regions    Miss   Cover     Lines    Miss   Cover @@ -18,7 +18,7 @@ Name                                  Regions    Miss   Cover     Lines    Miss  fido_dev_get_assert                        40       0 100.00%        35       0 100.00%  fido_check_flags                           13       0 100.00%        15       0 100.00%  fido_get_signed_hash                       36       0 100.00%        46       0 100.00% -fido_assert_verify                         48       4  91.67%        67       5  92.54% +fido_assert_verify                         48       4  91.67%        67       7  89.55%  fido_assert_set_clientdata                 12      12   0.00%        11      11   0.00%  fido_assert_set_clientdata_hash             8       0 100.00%         6       0 100.00%  fido_assert_set_hmac_salt                  10       0 100.00%         6       0 100.00% @@ -26,7 +26,7 @@ fido_assert_set_hmac_secret                12      12   0.00%         7       7  fido_assert_set_rp                         12       0 100.00%        11       0 100.00%  fido_assert_allow_cred                     13       2  84.62%        22       3  86.36%  fido_assert_set_extensions                 14       0 100.00%        10       0 100.00% -fido_assert_set_options                     6       6   0.00%         5       5   0.00% +fido_assert_set_options                     8       8   0.00%         5       5   0.00%  fido_assert_set_up                          2       0 100.00%         4       0 100.00%  fido_assert_set_uv                          2       0 100.00%         4       0 100.00%  fido_assert_clientdata_hash_ptr             1       0 100.00%         3       0 100.00% @@ -72,7 +72,7 @@ assert.c:check_extensions                   5       0 100.00%         9       0  assert.c:fido_assert_reset_extattr          1       0 100.00%         5       0 100.00%  assert.c:fido_assert_clean_authdata         1       0 100.00%         5       0 100.00%  ----------------------------------------------------------------------------------------------------------------- -TOTAL                                     563      40  92.90%       694      40  94.24% +TOTAL                                     565      42  92.57%       694      42  93.95%  File '/libfido2/src/authkey.c':  Name                                  Regions    Miss   Cover     Lines    Miss   Cover @@ -88,10 +88,10 @@ TOTAL                                      44       0 100.00%        59       0  File '/libfido2/src/bio.c':  Name                                  Regions    Miss   Cover     Lines    Miss   Cover  ----------------------------------------------------------------------------------------------------------------- -fido_bio_dev_get_template_array             5       2  60.00%         6       0 100.00% +fido_bio_dev_get_template_array             5       2  60.00%         6       1  83.33%  fido_bio_dev_set_template_name              7       0 100.00%         6       0 100.00% -fido_bio_dev_enroll_begin                  25       2  92.00%        31       0 100.00% -fido_bio_dev_enroll_continue                5       2  60.00%         6       0 100.00% +fido_bio_dev_enroll_begin                  25       2  92.00%        31       1  96.77% +fido_bio_dev_enroll_continue                5       2  60.00%         6       1  83.33%  fido_bio_dev_enroll_cancel                  1       1   0.00%         4       4   0.00%  fido_bio_dev_enroll_remove                  1       0 100.00%         4       0 100.00%  fido_bio_dev_get_info                       1       0 100.00%         4       0 100.00% @@ -138,7 +138,7 @@ bio.c:bio_reset_template_array              4       0 100.00%         7       0  bio.c:bio_reset_template                    1       0 100.00%         5       0 100.00%  bio.c:bio_reset_enroll                      3       0 100.00%         6       0 100.00%  ----------------------------------------------------------------------------------------------------------------- -TOTAL                                     419      20  95.23%       559      21  96.24% +TOTAL                                     419      20  95.23%       559      24  95.71%  File '/libfido2/src/blob.c':  Name                                  Regions    Miss   Cover     Lines    Miss   Cover @@ -187,9 +187,9 @@ cbor_encode_str_array                       18       0 100.00%        19       0  cbor_encode_cred_ext                        55       0 100.00%        50       0 100.00%  cbor_encode_cred_opt                        13       0 100.00%        11       0 100.00%  cbor_encode_assert_opt                      13       0 100.00%        11       0 100.00% -cbor_encode_pin_auth                        20       1  95.00%        22       3  86.36% +cbor_encode_pin_auth                        21       1  95.24%        22       3  86.36%  cbor_encode_pin_opt                          4       0 100.00%         8       0 100.00% -cbor_encode_change_pin_auth                 31       1  96.77%        36       3  91.67% +cbor_encode_change_pin_auth                 32       1  96.88%        36       3  91.67%  cbor_encode_assert_ext                      33       0 100.00%        32       0 100.00%  cbor_decode_fmt                             13       0 100.00%        15       0 100.00%  cbor_decode_pubkey                          21       1  95.24%        30       2  93.33% @@ -200,7 +200,7 @@ cbor_decode_uint64                           4       0 100.00%         8       0  cbor_decode_cred_id                          8       0 100.00%         9       0 100.00%  cbor_decode_user                             8       0 100.00%         9       0 100.00%  cbor_decode_rp_entity                        8       0 100.00%         9       0 100.00% -cbor_build_uint                             10       1  90.00%         9       2  77.78% +cbor_build_uint                             10       1  90.00%         9       1  88.89%  cbor_array_append                           17       0 100.00%        21       0 100.00%  cbor_array_drop                             18       2  88.89%        17       3  82.35%  cbor.c:ctap_check_cbor                      28       0 100.00%        26       0 100.00% @@ -222,16 +222,18 @@ cbor.c:decode_cred_id_entry                 10       0 100.00%        19       0  cbor.c:decode_user_entry                    25       0 100.00%        35       0 100.00%  cbor.c:decode_rp_entity_entry               15       0 100.00%        25       0 100.00%  ------------------------------------------------------------------------------------------------------------------ -TOTAL                                     1047      23  97.80%      1237      46  96.28% +TOTAL                                     1049      23  97.81%      1237      45  96.36%  File '/libfido2/src/compress.c':  Name                                   Regions    Miss   Cover     Lines    Miss   Cover  ------------------------------------------------------------------------------------------------------------------  fido_compress                                1       0 100.00%         3       0 100.00% -fido_uncompress                              1       0 100.00%         3       0 100.00% -compress.c:do_compress                      32       4  87.50%        22       3  86.36% +fido_uncompress                              6       0 100.00%         5       0 100.00% +compress.c:rfc1951_deflate                  33       2  93.94%        47       3  93.62% +compress.c:rfc1950_inflate                  27       2  92.59%        22       4  81.82% +compress.c:rfc1951_inflate                  38      10  73.68%        45      17  62.22%  ------------------------------------------------------------------------------------------------------------------ -TOTAL                                       34       4  88.24%        28       3  89.29% +TOTAL                                      105      14  86.67%       122      24  80.33%  File '/libfido2/src/config.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover @@ -255,8 +257,8 @@ Name                                    Regions    Miss   Cover     Lines    Mis  -------------------------------------------------------------------------------------------------------------------  fido_dev_make_cred                           12       0 100.00%        10       0 100.00%  fido_check_rp_id                              4       0 100.00%        11       0 100.00% -fido_cred_verify                             56       2  96.43%        72       5  93.06% -fido_cred_verify_self                        58       4  93.10%        83       5  93.98% +fido_cred_verify                             56       2  96.43%        72       4  94.44% +fido_cred_verify_self                        58       4  93.10%        83       7  91.57%  fido_cred_new                                 1       0 100.00%         3       0 100.00%  fido_cred_reset_tx                            1       0 100.00%        19       0 100.00%  fido_cred_reset_rx                            1       0 100.00%         7       0 100.00% @@ -273,13 +275,13 @@ fido_cred_set_clientdata_hash                 8       0 100.00%         6  fido_cred_set_rp                             18       0 100.00%        22       0 100.00%  fido_cred_set_user                           32       0 100.00%        41       0 100.00%  fido_cred_set_extensions                     16       0 100.00%        10       0 100.00% -fido_cred_set_options                         6       6   0.00%         5       5   0.00% +fido_cred_set_options                         8       8   0.00%         5       5   0.00%  fido_cred_set_rk                              2       0 100.00%         4       0 100.00%  fido_cred_set_uv                              2       0 100.00%         4       0 100.00%  fido_cred_set_prot                           21       0 100.00%        14       0 100.00%  fido_cred_set_pin_minlen                      7       0 100.00%         8       0 100.00%  fido_cred_set_blob                           13       2  84.62%         8       1  87.50% -fido_cred_set_fmt                            20       4  80.00%        12       1  91.67% +fido_cred_set_fmt                            20       4  80.00%        12       2  83.33%  fido_cred_set_type                           17       0 100.00%         7       0 100.00%  fido_cred_type                                1       0 100.00%         3       0 100.00%  fido_cred_flags                               1       0 100.00%         3       0 100.00% @@ -319,11 +321,11 @@ cred.c:fido_dev_make_cred_rx                 29       0 100.00%        32  cred.c:parse_makecred_reply                  14       0 100.00%        27       0 100.00%  cred.c:check_extensions                       2       0 100.00%         6       0 100.00%  cred.c:get_signed_hash_u2f                   27       0 100.00%        26       0 100.00% -cred.c:verify_attstmt                        23       2  91.30%        40       5  87.50% +cred.c:verify_attstmt                        23       2  91.30%        40       6  85.00%  cred.c:fido_cred_clean_authdata               1       0 100.00%         8       0 100.00%  cred.c:fido_cred_clean_attstmt                1       0 100.00%         8       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                       632      34  94.62%       830      36  95.66% +TOTAL                                       634      36  94.32%       830      39  95.30%  File '/libfido2/src/credman.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover @@ -334,15 +336,15 @@ fido_credman_del_dev_rk                       1       0 100.00%         4  fido_credman_get_dev_rp                       1       0 100.00%         4       0 100.00%  fido_credman_set_dev_rk                       1       0 100.00%         4       0 100.00%  fido_credman_rk_new                           1       0 100.00%         3       0 100.00% -fido_credman_rk_free                          6       1  83.33%         8       0 100.00% +fido_credman_rk_free                          6       1  83.33%         8       1  87.50%  fido_credman_rk_count                         1       0 100.00%         3       0 100.00%  fido_credman_rk                               4       0 100.00%         5       0 100.00%  fido_credman_metadata_new                     1       0 100.00%         3       0 100.00% -fido_credman_metadata_free                    6       1  83.33%         7       0 100.00% +fido_credman_metadata_free                    6       1  83.33%         7       1  85.71%  fido_credman_rk_existing                      1       0 100.00%         3       0 100.00%  fido_credman_rk_remaining                     1       0 100.00%         3       0 100.00%  fido_credman_rp_new                           1       0 100.00%         3       0 100.00% -fido_credman_rp_free                          6       1  83.33%         8       0 100.00% +fido_credman_rp_free                          6       1  83.33%         8       1  87.50%  fido_credman_rp_count                         1       0 100.00%         3       0 100.00%  fido_credman_rp_id                            4       0 100.00%         5       0 100.00%  fido_credman_rp_name                          4       0 100.00%         5       0 100.00% @@ -369,21 +371,17 @@ credman.c:credman_set_dev_rk_wait            11       0 100.00%         8  credman.c:credman_reset_rk                    4       0 100.00%         9       0 100.00%  credman.c:credman_reset_rp                    4       0 100.00%        12       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                       382      10  97.38%       518      15  97.10% +TOTAL                                       382      10  97.38%       518      18  96.53%  File '/libfido2/src/dev.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover  ------------------------------------------------------------------------------------------------------------------- -fido_dev_register_manifest_func              10       2  80.00%        14       3  78.57% -fido_dev_unregister_manifest_func             7       7   0.00%        11      11   0.00% -fido_dev_info_manifest                       22       4  81.82%        24       0 100.00% +fido_dev_info_manifest                        2       0 100.00%        11       0 100.00%  fido_dev_open_with_info                       5       5   0.00%         6       6   0.00% -fido_dev_open                                 5       1  80.00%        19      12  36.84% -fido_dev_close                                9       2  77.78%         8       0 100.00% +fido_dev_open                                13       6  53.85%        16       6  62.50% +fido_dev_close                                9       2  77.78%         8       1  87.50%  fido_dev_set_sigmask                         18      18   0.00%        11      11   0.00%  fido_dev_cancel                              11       0 100.00%         8       0 100.00% -fido_dev_get_touch_begin                     50       0 100.00%        59       0 100.00% -fido_dev_get_touch_status                    17       0 100.00%        20       0 100.00%  fido_dev_set_io_functions                    18       4  77.78%        14       6  57.14%  fido_dev_set_transport_functions              6       2  66.67%         9       3  66.67%  fido_dev_io_handle                            1       1   0.00%         3       3   0.00% @@ -410,17 +408,17 @@ fido_dev_force_fido2                          2       2   0.00%         3  fido_dev_get_pin_protocol                    11       0 100.00%         7       0 100.00%  fido_dev_maxmsgsize                           1       0 100.00%         3       0 100.00%  fido_dev_set_timeout                          6       2  66.67%         6       1  83.33% -dev.c:find_manifest_func_node                 5       0 100.00%         8       0 100.00% +dev.c:run_manifest                           10       0 100.00%        13       0 100.00%  dev.c:fido_dev_open_wait                     10       0 100.00%         7       0 100.00%  dev.c:fido_dev_open_tx                       56      15  73.21%        56      26  53.57%  dev.c:set_random_report_len                  11       0 100.00%         6       0 100.00%  dev.c:fido_dev_open_rx                       36       1  97.22%        53       1  98.11%  dev.c:fido_dev_set_flags                      1       0 100.00%         5       0 100.00%  dev.c:fido_dev_set_extension_flags            7       0 100.00%         7       0 100.00% -dev.c:fido_dev_set_option_flags              29       0 100.00%        18       0 100.00% +dev.c:fido_dev_set_option_flags              31       0 100.00%        20       0 100.00%  dev.c:fido_dev_set_protocol_flags            11       0 100.00%        17       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                       421      79  81.24%       491     105  78.62% +TOTAL                                       332      71  78.61%       378      86  77.25%  File '/libfido2/src/ecdh.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover @@ -438,15 +436,15 @@ Name                                    Regions    Miss   Cover     Lines    Mis  eddsa_pk_decode                               8       0 100.00%         9       0 100.00%  eddsa_pk_new                                  1       0 100.00%         3       0 100.00%  eddsa_pk_free                                 6       0 100.00%         7       0 100.00% -eddsa_pk_from_ptr                             6       0 100.00%         6       0 100.00% +eddsa_pk_from_ptr                            10       0 100.00%        12       0 100.00%  eddsa_pk_to_EVP_PKEY                          3       0 100.00%         7       0 100.00% -eddsa_pk_from_EVP_PKEY                       14       0 100.00%        10       0 100.00% +eddsa_pk_from_EVP_PKEY                       18       2  88.89%        12       1  91.67%  eddsa_verify_sig                             19       2  89.47%        30       6  80.00%  eddsa_pk_verify_sig                           7       1  85.71%        13       2  84.62%  eddsa.c:decode_pubkey_point                   8       0 100.00%        11       0 100.00%  eddsa.c:decode_coord                          8       0 100.00%        10       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                        80       3  96.25%       106       8  92.45% +TOTAL                                        88       5  94.32%       114       9  92.11%  File '/libfido2/src/err.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover @@ -464,21 +462,21 @@ es256_sk_new                                  1       0 100.00%         3  es256_sk_free                                 6       0 100.00%         7       0 100.00%  es256_pk_new                                  1       0 100.00%         3       0 100.00%  es256_pk_free                                 6       0 100.00%         7       0 100.00% -es256_pk_from_ptr                            11       0 100.00%        10       0 100.00% +es256_pk_from_ptr                            15       0 100.00%        17       0 100.00%  es256_pk_set_x                                1       0 100.00%         4       0 100.00%  es256_pk_set_y                                1       0 100.00%         4       0 100.00% -es256_sk_create                              39       0 100.00%        41       0 100.00% -es256_pk_to_EVP_PKEY                         42       0 100.00%        54       0 100.00% -es256_pk_from_EC_KEY                         38       0 100.00%        36       0 100.00% -es256_pk_from_EVP_PKEY                        7       2  71.43%         7       0 100.00% -es256_sk_to_EVP_PKEY                         28       0 100.00%        40       0 100.00% -es256_derive_pk                              25       0 100.00%        30       0 100.00% +es256_sk_create                              39       0 100.00%        40       0 100.00% +es256_pk_to_EVP_PKEY                         42       0 100.00%        53       0 100.00% +es256_pk_from_EC_KEY                         42       2  95.24%        47       4  91.49% +es256_pk_from_EVP_PKEY                        8       2  75.00%         7       1  85.71% +es256_sk_to_EVP_PKEY                         28       0 100.00%        39       0 100.00% +es256_derive_pk                              25       0 100.00%        29       0 100.00%  es256_verify_sig                             12       2  83.33%        19       5  73.68%  es256_pk_verify_sig                           7       1  85.71%        13       2  84.62%  es256.c:decode_pubkey_point                   9       0 100.00%        13       0 100.00%  es256.c:decode_coord                          8       0 100.00%        10       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                       306       5  98.37%       358       7  98.04% +TOTAL                                       315       7  97.78%       372      12  96.77%  File '/libfido2/src/extern.h':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover @@ -511,7 +509,7 @@ TOTAL                                        87       2  97.70%       145  File '/libfido2/src/hid_linux.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover  ------------------------------------------------------------------------------------------------------------------- -fido_hid_manifest                            35       4  88.57%        41       1  97.56% +fido_hid_manifest                            35       4  88.57%        41       2  95.12%  fido_hid_open                                27      27   0.00%        40      40   0.00%  fido_hid_close                                3       3   0.00%         6       6   0.00%  fido_hid_set_sigmask                          2       2   0.00%         6       6   0.00% @@ -526,15 +524,15 @@ hid_linux.c:parse_uevent                     12       0 100.00%        24  hid_linux.c:get_usb_attr                      1       0 100.00%         3       0 100.00%  hid_linux.c:get_report_descriptor            14       1  92.86%        17       3  82.35%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                       173      68  60.69%       250     104  58.40% +TOTAL                                       173      68  60.69%       250     105  58.00%  File '/libfido2/src/hid_unix.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover  -------------------------------------------------------------------------------------------------------------------  fido_hid_unix_open                           18      11  38.89%        22      14  36.36% -fido_hid_unix_wait                           10       9  10.00%        21      10  52.38% +fido_hid_unix_wait                           11      10   9.09%        21      12  42.86%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                        28      20  28.57%        43      24  44.19% +TOTAL                                        29      21  27.59%        43      26  39.53%  File '/libfido2/src/info.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover @@ -559,6 +557,7 @@ fido_cbor_info_maxcredbloblen                 1       0 100.00%         3  fido_cbor_info_maxmsgsiz                      1       0 100.00%         3       0 100.00%  fido_cbor_info_maxcredcntlst                  1       0 100.00%         3       0 100.00%  fido_cbor_info_maxcredidlen                   1       0 100.00%         3       0 100.00% +fido_cbor_info_maxlargeblob                   1       0 100.00%         3       0 100.00%  fido_cbor_info_fwversion                      1       0 100.00%         3       0 100.00%  fido_cbor_info_protocols_ptr                  1       0 100.00%         3       0 100.00%  fido_cbor_info_protocols_len                  1       0 100.00%         3       0 100.00% @@ -567,7 +566,7 @@ fido_cbor_info_algorithm_type                 4       0 100.00%         5  fido_cbor_info_algorithm_cose                 4       0 100.00%         5       0 100.00%  info.c:fido_dev_get_cbor_info_tx              8       0 100.00%         9       0 100.00%  info.c:fido_dev_get_cbor_info_rx              6       0 100.00%        14       0 100.00% -info.c:parse_reply_element                   19       0 100.00%        37       0 100.00% +info.c:parse_reply_element                   20       0 100.00%        39       0 100.00%  info.c:decode_string_array                   12       0 100.00%        17       0 100.00%  info.c:decode_string                          4       0 100.00%        10       0 100.00%  info.c:decode_aaguid                          8       0 100.00%        10       0 100.00% @@ -579,37 +578,37 @@ info.c:decode_algorithms                     12       0 100.00%        17  info.c:decode_algorithm                       9       0 100.00%        17       0 100.00%  info.c:decode_algorithm_entry                20       0 100.00%        27       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                       184       0 100.00%       316       0 100.00% +TOTAL                                       186       0 100.00%       321       0 100.00%  File '/libfido2/src/io.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover  ------------------------------------------------------------------------------------------------------------------- -fido_tx                                      13       0 100.00%        11       0 100.00% +fido_tx                                      14       0 100.00%        11       0 100.00%  fido_rx                                      13       1  92.31%        14       3  78.57%  fido_rx_cbor_status                           8       0 100.00%        10       0 100.00%  io.c:transport_tx                             7       0 100.00%        10       0 100.00%  io.c:tx_empty                                 9       0 100.00%        14       0 100.00%  io.c:tx_pkt                                   7       0 100.00%        10       0 100.00%  io.c:tx                                      13       0 100.00%        19       0 100.00% -io.c:tx_preamble                             16       1  93.75%        20       1  95.00% -io.c:tx_frame                                15       1  93.33%        18       1  94.44% +io.c:tx_preamble                             17       1  94.12%        20       1  95.00% +io.c:tx_frame                                16       1  93.75%        18       1  94.44%  io.c:transport_rx                             7       0 100.00%        10       0 100.00% -io.c:rx                                      40       2  95.00%        52       1  98.08% +io.c:rx                                      40       2  95.00%        52       2  96.15%  io.c:rx_preamble                             23       2  91.30%        22       5  77.27%  io.c:rx_frame                                11       0 100.00%        11       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                       182       7  96.15%       221      11  95.02% +TOTAL                                       185       7  96.22%       221      12  94.57%  File '/libfido2/src/iso7816.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover  -------------------------------------------------------------------------------------------------------------------  iso7816_new                                   4       0 100.00%        16       0 100.00%  iso7816_free                                  6       0 100.00%         7       0 100.00% -iso7816_add                                   6       1  83.33%         8       0 100.00% +iso7816_add                                   6       1  83.33%         8       1  87.50%  iso7816_ptr                                   1       0 100.00%         3       0 100.00%  iso7816_len                                   1       0 100.00%         4       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                        18       1  94.44%        38       0 100.00% +TOTAL                                        18       1  94.44%        38       1  97.37%  File '/libfido2/src/largeblob.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover @@ -620,7 +619,7 @@ fido_dev_largeblob_remove                    12       0 100.00%        18  fido_dev_largeblob_get_array                 15       2  86.67%        27       4  85.19%  fido_dev_largeblob_set_array                 14       0 100.00%        19       0 100.00%  largeblob.c:largeblob_get_array              32       0 100.00%        36       0 100.00% -largeblob.c:get_chunklen                      9       1  88.89%         9       0 100.00% +largeblob.c:get_chunklen                     10       1  90.00%         9       1  88.89%  largeblob.c:largeblob_get_tx                 19       0 100.00%        24       0 100.00%  largeblob.c:largeblob_get_rx                 15       0 100.00%        21       0 100.00%  largeblob.c:parse_largeblob_reply             8       0 100.00%         9       0 100.00% @@ -629,7 +628,7 @@ largeblob.c:largeblob_array_digest           10       0 100.00%         9  largeblob.c:largeblob_array_load             14       2  85.71%        19       7  63.16%  largeblob.c:largeblob_array_lookup           25       0 100.00%        33       0 100.00%  largeblob.c:largeblob_decode                 16       2  87.50%        16       6  62.50% -largeblob.c:largeblob_do_decode              27       3  88.89%        30       5  83.33% +largeblob.c:largeblob_do_decode              27       3  88.89%        30       7  76.67%  largeblob.c:largeblob_decrypt                15       0 100.00%        24       0 100.00%  largeblob.c:largeblob_aad                     1       0 100.00%        10       0 100.00%  largeblob.c:largeblob_reset                   1       0 100.00%         5       0 100.00% @@ -645,34 +644,34 @@ largeblob.c:largeblob_get_uv_token           19       0 100.00%        23  largeblob.c:largeblob_set_tx                 35       0 100.00%        36       0 100.00%  largeblob.c:prepare_hmac                     13       2  84.62%        23       7  69.57%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                       513      19  96.30%       684      43  93.71% +TOTAL                                       514      19  96.30%       684      46  93.27%  File '/libfido2/src/log.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover  -------------------------------------------------------------------------------------------------------------------  fido_log_init                                 1       0 100.00%         4       0 100.00% -fido_log_debug                                6       1  83.33%         8       0 100.00% -fido_log_xxd                                 16       1  93.75%        24       0 100.00% -fido_log_error                                8       2  75.00%        11       1  90.91% +fido_log_debug                                6       1  83.33%         8       1  87.50% +fido_log_xxd                                 16       1  93.75%        24       1  95.83% +fido_log_error                                8       2  75.00%        11       2  81.82%  fido_set_log_handler                          3       0 100.00%         4       0 100.00%  log.c:log_on_stderr                           1       1   0.00%         3       3   0.00%  log.c:do_log                                  4       0 100.00%         9       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                        39       5  87.18%        63       4  93.65% +TOTAL                                        39       5  87.18%        63       7  88.89%  File '/libfido2/src/netlink.c':  Name                                    Regions    Miss   Cover     Lines    Miss   Cover  -------------------------------------------------------------------------------------------------------------------  fido_nl_power_nfc                            18       1  94.44%        24       3  87.50%  fido_nl_get_nfc_target                       17       1  94.12%        31       3  90.32% -fido_nl_free                                 10       2  80.00%         9       1  88.89% +fido_nl_free                                 10       2  80.00%         9       2  77.78%  fido_nl_new                                  16       1  93.75%        26       3  88.46%  set_netlink_io_functions                      1       0 100.00%         4       0 100.00%  netlink.c:nlmsg_new                           8       0 100.00%        15       0 100.00%  netlink.c:nlmsg_set_genl                      1       0 100.00%         7       0 100.00%  netlink.c:nlmsg_write                         6       1  83.33%         7       1  85.71%  netlink.c:nlmsg_set_u32                       1       0 100.00%         3       0 100.00% -netlink.c:nlmsg_setattr                      14       1  92.86%        17       0 100.00% +netlink.c:nlmsg_setattr                      15       1  93.33%        17       0 100.00%  netlink.c:nlmsg_tx                           10       1  90.00%        13       3  76.92%  netlink.c:nlmsg_ptr                           1       0 100.00%         3       0 100.00%  netlink.c:nlmsg_len                           1       0 100.00%         3       0 100.00% @@ -704,36 +703,62 @@ netlink.c:parse_mcastgrps                     1       0 100.00%         3  netlink.c:parse_mcastgrp                     15       0 100.00%        24       0 100.00%  netlink.c:nla_get_str                        10       0 100.00%        11       0 100.00%  ------------------------------------------------------------------------------------------------------------------- -TOTAL                                       328      14  95.73%       498      32  93.57% +TOTAL                                       329      14  95.74%       498      33  93.37% -File '/libfido2/src/nfc_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_set_pin                                1       0 100.00%         4  fido_dev_get_retry_count                        1       0 100.00%         4       0 100.00%  fido_dev_get_uv_retry_count                     1       0 100.00%         4       0 100.00%  cbor_add_uv_params                             17       0 100.00%        23       0 100.00% -pin.c:uv_token_wait                            14       2  85.71%        12       0 100.00% +pin.c:uv_token_wait                            14       2  85.71%        12       1  91.67%  pin.c:ctap21_uv_token_tx                       49       0 100.00%        53       0 100.00%  pin.c:pin_sha256_enc                           19       0 100.00%        24       0 100.00%  pin.c:encode_uv_permission                     20       1  95.00%        19       3  84.21% @@ -765,7 +790,7 @@ pin.c:fido_dev_get_uv_retry_count_wait         10       0 100.00%         7  pin.c:fido_dev_get_uv_retry_count_rx           11       0 100.00%        17       0 100.00%  pin.c:parse_uv_retry_count                      1       0 100.00%         3       0 100.00%  --------------------------------------------------------------------------------------------------------------------- -TOTAL                                         403       3  99.26%       495       3  99.39% +TOTAL                                         403       3  99.26%       495       4  99.19%  File '/libfido2/src/random.c':  Name                                      Regions    Miss   Cover     Lines    Miss   Cover @@ -786,11 +811,11 @@ TOTAL                                          24       0 100.00%        23  File '/libfido2/src/rs1.c':  Name                                      Regions    Miss   Cover     Lines    Miss   Cover  --------------------------------------------------------------------------------------------------------------------- -rs1_verify_sig                                 20       0 100.00%        30       0 100.00% -rs1.c:rs1_get_EVP_MD                            4       0 100.00%         6       0 100.00% +rs1_verify_sig                                 20       1  95.00%        30       3  90.00% +rs1.c:rs1_get_EVP_MD                            4       1  75.00%         6       1  83.33%  rs1.c:rs1_free_EVP_MD                           1       0 100.00%         3       0 100.00%  --------------------------------------------------------------------------------------------------------------------- -TOTAL                                          25       0 100.00%        39       0 100.00% +TOTAL                                          25       2  92.00%        39       4  89.74%  File '/libfido2/src/rs256.c':  Name                                      Regions    Miss   Cover     Lines    Miss   Cover @@ -801,7 +826,7 @@ rs256_pk_free                                   6       0 100.00%         7  rs256_pk_from_ptr                               6       0 100.00%         6       0 100.00%  rs256_pk_to_EVP_PKEY                           32       0 100.00%        39       0 100.00%  rs256_pk_from_RSA                              32       4  87.50%        26       6  76.92% -rs256_pk_from_EVP_PKEY                          7       2  71.43%         7       0 100.00% +rs256_pk_from_EVP_PKEY                          7       2  71.43%         7       1  85.71%  rs256_verify_sig                               20       1  95.00%        30       2  93.33%  rs256_pk_verify_sig                             7       1  85.71%        13       2  84.62%  rs256.c:decode_rsa_pubkey                       9       0 100.00%        13       0 100.00% @@ -809,31 +834,39 @@ rs256.c:decode_bignum                           8       0 100.00%        10  rs256.c:rs256_get_EVP_MD                        4       0 100.00%         6       0 100.00%  rs256.c:rs256_free_EVP_MD                       1       0 100.00%         3       0 100.00%  --------------------------------------------------------------------------------------------------------------------- -TOTAL                                         141       8  94.33%       172      10  94.19% +TOTAL                                         141       8  94.33%       172      11  93.60%  File '/libfido2/src/time.c':  Name                                      Regions    Miss   Cover     Lines    Miss   Cover  ---------------------------------------------------------------------------------------------------------------------  fido_time_now                                   4       0 100.00%         7       0 100.00%  fido_time_delta                                23       1  95.65%        23       0 100.00% -time.c:timespec_to_ms                          16       2  87.50%        13       1  92.31% +time.c:timespec_to_ms                          16       2  87.50%        13       2  84.62%  --------------------------------------------------------------------------------------------------------------------- -TOTAL                                          43       3  93.02%        43       1  97.67% +TOTAL                                          43       3  93.02%        43       2  95.35% + +File '/libfido2/src/touch.c': +Name                                      Regions    Miss   Cover     Lines    Miss   Cover +--------------------------------------------------------------------------------------------------------------------- +fido_dev_get_touch_begin                       50       0 100.00%        59       0 100.00% +fido_dev_get_touch_status                      17       0 100.00%        20       0 100.00% +--------------------------------------------------------------------------------------------------------------------- +TOTAL                                          67       0 100.00%        79       0 100.00%  File '/libfido2/src/tpm.c':  Name                                      Regions    Miss   Cover     Lines    Miss   Cover  --------------------------------------------------------------------------------------------------------------------- -fido_get_signed_hash_tpm                       25       0 100.00%        39       0 100.00% -tpm.c:check_es256_pubarea                      18       0 100.00%        30       0 100.00% +fido_get_signed_hash_tpm                       25       1  96.00%        39       3  92.31% +tpm.c:check_es256_pubarea                      19       1  94.74%        30       3  90.00%  tpm.c:bswap_es256_pubarea                       1       0 100.00%        12       0 100.00% -tpm.c:check_rs256_pubarea                      16       0 100.00%        28       0 100.00% +tpm.c:check_rs256_pubarea                      17       1  94.12%        28       3  89.29%  tpm.c:bswap_rs256_pubarea                       1       0 100.00%        10       0 100.00% -tpm.c:check_sha1_certinfo                      14       0 100.00%        38       0 100.00% +tpm.c:check_sha1_certinfo                      15       0 100.00%        38       0 100.00%  tpm.c:get_signed_sha1                          17       0 100.00%        19       0 100.00%  tpm.c:get_signed_name                           7       0 100.00%        10       0 100.00%  tpm.c:bswap_sha1_certinfo                       1       0 100.00%         8       0 100.00%  --------------------------------------------------------------------------------------------------------------------- -TOTAL                                         100       0 100.00%       194       0 100.00% +TOTAL                                         103       3  97.09%       194       9  95.36%  File '/libfido2/src/types.c':  Name                                      Regions    Miss   Cover     Lines    Miss   Cover @@ -869,3 +902,10 @@ u2f.c:parse_auth_reply                         23       0 100.00%        23  u2f.c:authdata_fake                            12       0 100.00%        27       0 100.00%  ---------------------------------------------------------------------------------------------------------------------  TOTAL                                         528       4  99.24%       685      12  98.25% + +File '/libfido2/src/util.c': +Name                                      Regions    Miss   Cover     Lines    Miss   Cover +--------------------------------------------------------------------------------------------------------------------- +fido_to_uint64                                 14       1  92.86%        14       1  92.86% +--------------------------------------------------------------------------------------------------------------------- +TOTAL                                          14       1  92.86%        14       1  92.86% diff --git a/fuzz/fuzz_mgmt.c b/fuzz/fuzz_mgmt.c index 7c28979fb624..41077e23766c 100644 --- a/fuzz/fuzz_mgmt.c +++ b/fuzz/fuzz_mgmt.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2019 Yubico AB. All rights reserved. + * Copyright (c) 2019-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -288,6 +288,9 @@ dev_get_cbor_info(const struct param *p)  	n = fido_cbor_info_maxcredidlen(ci);  	consume(&n, sizeof(n)); +	n = fido_cbor_info_maxlargeblob(ci); +	consume(&n, sizeof(n)); +  	n = fido_cbor_info_fwversion(ci);  	consume(&n, sizeof(n)); diff --git a/fuzz/fuzz_pcsc.c b/fuzz/fuzz_pcsc.c new file mode 100644 index 000000000000..4a066ec32e1f --- /dev/null +++ b/fuzz/fuzz_pcsc.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#define _FIDO_INTERNAL + +#include <assert.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <winscard.h> + +#include "mutator_aux.h" +#include "wiredata_fido2.h" +#include "dummy.h" + +#include "../src/extern.h" + +struct param { +	int seed; +	char path[MAXSTR]; +	struct blob pcsc_list; +	struct blob tx_apdu; +	struct blob wiredata_init; +	struct blob wiredata_msg; +}; + +static const uint8_t dummy_tx_apdu[] = { WIREDATA_CTAP_EXTENDED_APDU }; +static const uint8_t dummy_wiredata_init[] = { WIREDATA_CTAP_NFC_INIT }; +static const uint8_t dummy_wiredata_msg[] = { WIREDATA_CTAP_NFC_MSG }; + +struct param * +unpack(const uint8_t *ptr, size_t len) +{ +	cbor_item_t *item = NULL, **v; +	struct cbor_load_result cbor; +	struct param *p; +	int ok = -1; + +	if ((p = calloc(1, sizeof(*p))) == NULL || +	    (item = cbor_load(ptr, len, &cbor)) == NULL || +	    cbor.read != len || +	    cbor_isa_array(item) == false || +	    cbor_array_is_definite(item) == false || +	    cbor_array_size(item) != 6 || +	    (v = cbor_array_handle(item)) == NULL) +		goto fail; + +	if (unpack_int(v[0], &p->seed) < 0 || +	    unpack_string(v[1], p->path) < 0 || +	    unpack_blob(v[2], &p->pcsc_list) < 0 || +	    unpack_blob(v[3], &p->tx_apdu) < 0 || +	    unpack_blob(v[4], &p->wiredata_init) < 0 || +	    unpack_blob(v[5], &p->wiredata_msg) < 0) +		goto fail; + +	ok = 0; +fail: +	if (ok < 0) { +		free(p); +		p = NULL; +	} + +	if (item) +		cbor_decref(&item); + +	return p; +} + +size_t +pack(uint8_t *ptr, size_t len, const struct param *p) +{ +	cbor_item_t *argv[6], *array = NULL; +	size_t cbor_alloc_len, cbor_len = 0; +	unsigned char *cbor = NULL; + +	memset(argv, 0, sizeof(argv)); + +	if ((array = cbor_new_definite_array(6)) == NULL || +	    (argv[0] = pack_int(p->seed)) == NULL || +	    (argv[1] = pack_string(p->path)) == NULL || +	    (argv[2] = pack_blob(&p->pcsc_list)) == NULL || +	    (argv[3] = pack_blob(&p->tx_apdu)) == NULL || +	    (argv[4] = pack_blob(&p->wiredata_init)) == NULL || +	    (argv[5] = pack_blob(&p->wiredata_msg)) == NULL) +		goto fail; + +	for (size_t i = 0; i < 6; i++) +		if (cbor_array_push(array, argv[i]) == false) +			goto fail; + +	if ((cbor_len = cbor_serialize_alloc(array, &cbor, +	    &cbor_alloc_len)) > len) { +		cbor_len = 0; +		goto fail; +	} + +	memcpy(ptr, cbor, cbor_len); +fail: +	for (size_t i = 0; i < 6; i++) +		if (argv[i]) +			cbor_decref(&argv[i]); + +	if (array) +		cbor_decref(&array); + +	free(cbor); + +	return cbor_len; +} + +size_t +pack_dummy(uint8_t *ptr, size_t len) +{ +	struct param dummy; +	uint8_t	blob[4096]; +	size_t blob_len; + +	memset(&dummy, 0, sizeof(dummy)); + +	strlcpy(dummy.path, dummy_pcsc_path, sizeof(dummy.path)); + +	dummy.pcsc_list.len = sizeof(dummy_pcsc_list); +	memcpy(&dummy.pcsc_list.body, &dummy_pcsc_list, dummy.pcsc_list.len); + +	dummy.tx_apdu.len = sizeof(dummy_tx_apdu); +	memcpy(&dummy.tx_apdu.body, &dummy_tx_apdu, dummy.tx_apdu.len); + +	dummy.wiredata_init.len = sizeof(dummy_wiredata_init); +	memcpy(&dummy.wiredata_init.body, &dummy_wiredata_init, +	    dummy.wiredata_init.len); + +	dummy.wiredata_msg.len = sizeof(dummy_wiredata_msg); +	memcpy(&dummy.wiredata_msg.body, &dummy_wiredata_msg, +	    dummy.wiredata_msg.len); + +	assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); + +	if (blob_len > len) { +		memcpy(ptr, blob, len); +		return len; +	} + +	memcpy(ptr, blob, blob_len); + +	return blob_len; +} + +static void +test_manifest(void) +{ +	size_t ndevs, nfound; +	fido_dev_info_t *devlist = NULL; +	int16_t vendor_id, product_id; +	int r; + +	r = fido_pcsc_manifest(NULL, 0, &nfound); +	assert(r == FIDO_OK && nfound == 0); +	r = fido_pcsc_manifest(NULL, 1, &nfound); +	assert(r == FIDO_ERR_INVALID_ARGUMENT); + +	ndevs = uniform_random(64); +	if ((devlist = fido_dev_info_new(ndevs)) == NULL || +	    fido_pcsc_manifest(devlist, ndevs, &nfound) != FIDO_OK) +		goto out; + +	for (size_t i = 0; i < nfound; i++) { +		const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i); +		consume_str(fido_dev_info_path(di)); +		consume_str(fido_dev_info_manufacturer_string(di)); +		consume_str(fido_dev_info_product_string(di)); +		vendor_id = fido_dev_info_vendor(di); +		product_id = fido_dev_info_product(di); +		consume(&vendor_id, sizeof(vendor_id)); +		consume(&product_id, sizeof(product_id)); +	} + +out: +	fido_dev_info_free(&devlist, ndevs); +} + +static void +test_tx(const char *path, const struct blob *apdu, uint8_t cmd, u_char *rx_buf, +    size_t rx_len) +{ +	fido_dev_t dev; +	const u_char *tx_ptr = NULL; +	size_t tx_len = 0; +	int n; + +	memset(&dev, 0, sizeof(dev)); + +	if (fido_dev_set_pcsc(&dev) < 0) +		return; +	if ((dev.io_handle = fido_pcsc_open(path)) == NULL) +		return; + +	if (apdu) { +		tx_ptr = apdu->body; +		tx_len = apdu->len; +	} + +	fido_pcsc_tx(&dev, cmd, tx_ptr, tx_len); + +	if ((n = fido_pcsc_rx(&dev, cmd, rx_buf, rx_len, -1)) >= 0) +		consume(rx_buf, n); + +	fido_pcsc_close(dev.io_handle); +} + +static void +test_misc(void) +{ +	assert(fido_pcsc_open(NULL) == NULL); +	assert(fido_pcsc_write(NULL, NULL, INT_MAX + 1LL) == -1); +} + +void +test(const struct param *p) +{ +	u_char buf[512]; + +	prng_init((unsigned int)p->seed); +	fuzz_clock_reset(); +	fido_init(FIDO_DEBUG); +	fido_set_log_handler(consume_str); + +	set_pcsc_parameters(&p->pcsc_list); +	set_pcsc_io_functions(nfc_read, nfc_write, consume); + +	test_manifest(); +	test_misc(); + +	set_wire_data(p->wiredata_init.body, p->wiredata_init.len); +	test_tx(p->path, NULL, CTAP_CMD_INIT, buf, uniform_random(20)); + +	set_wire_data(p->wiredata_msg.body, p->wiredata_msg.len); +	test_tx(p->path, &p->tx_apdu, CTAP_CMD_MSG, buf, sizeof(buf)); + +	set_wire_data(p->wiredata_msg.body, p->wiredata_msg.len); +	test_tx(p->path, &p->tx_apdu, CTAP_CMD_CBOR, buf, sizeof(buf)); + +	set_wire_data(p->wiredata_msg.body, p->wiredata_msg.len); +	test_tx(p->path, &p->tx_apdu, CTAP_CMD_LOCK, buf, sizeof(buf)); +} + +void +mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN +{ +	if (flags & MUTATE_SEED) +		p->seed = (int)seed; + +	if (flags & MUTATE_PARAM) { +		mutate_string(p->path); +		mutate_blob(&p->pcsc_list); +		mutate_blob(&p->tx_apdu); +	} +  +	if (flags & MUTATE_WIREDATA) { +		mutate_blob(&p->wiredata_init); +		mutate_blob(&p->wiredata_msg); +	} +} diff --git a/fuzz/mutator_aux.c b/fuzz/mutator_aux.c index 92a67be78106..660fbe4e67e7 100644 --- a/fuzz/mutator_aux.c +++ b/fuzz/mutator_aux.c @@ -15,9 +15,6 @@  #include "mutator_aux.h" -#define HID_DEV_HANDLE	0x68696421 -#define NFC_DEV_HANDLE	0x6e666321 -  int fido_nfc_rx(fido_dev_t *, uint8_t, unsigned char *, size_t, int);  int fido_nfc_tx(fido_dev_t *, uint8_t, const unsigned char *, size_t);  size_t LLVMFuzzerMutate(uint8_t *, size_t, size_t); @@ -241,16 +238,16 @@ nfc_close(void *handle)  	assert(handle == (void *)NFC_DEV_HANDLE);  } -static int +int  nfc_read(void *handle, unsigned char *ptr, size_t len, int ms)  {  	assert(handle == (void *)NFC_DEV_HANDLE); -	assert(len > 0 && len <= 256 + 2); +	assert(len > 0 && len <= 264);  	return buf_read(ptr, len, ms);  } -static int +int  nfc_write(void *handle, const unsigned char *ptr, size_t len)  {  	assert(handle == (void *)NFC_DEV_HANDLE); diff --git a/fuzz/mutator_aux.h b/fuzz/mutator_aux.h index a9bebe232bae..730f58635b16 100644 --- a/fuzz/mutator_aux.h +++ b/fuzz/mutator_aux.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2019-2021 Yubico AB. All rights reserved. + * Copyright (c) 2019-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -51,6 +51,9 @@  #define MAXSTR	1024  #define MAXBLOB	3600 +#define HID_DEV_HANDLE	0x68696421 +#define NFC_DEV_HANDLE	0x6e666321 +  struct blob {  	uint8_t body[MAXBLOB];  	size_t len; @@ -85,6 +88,9 @@ void mutate_string(char *);  ssize_t fd_read(int, void *, size_t);  ssize_t fd_write(int, const void *, size_t); +int nfc_read(void *, unsigned char *, size_t, int); +int nfc_write(void *, const unsigned char *, size_t); +  fido_dev_t *open_dev(int);  void set_wire_data(const uint8_t *, size_t); @@ -94,4 +100,8 @@ unsigned long prng_uint32(void);  uint32_t uniform_random(uint32_t); +void set_pcsc_parameters(const struct blob *); +void set_pcsc_io_functions(int (*)(void *, u_char *, size_t, int), +    int (*)(void *, const u_char *, size_t), void (*)(const void *, size_t)); +  #endif /* !_MUTATOR_AUX_H */ diff --git a/fuzz/pcsc.c b/fuzz/pcsc.c new file mode 100644 index 000000000000..f8400a5e766d --- /dev/null +++ b/fuzz/pcsc.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#include <assert.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <winscard.h> + +#include "mutator_aux.h" + +static const struct blob *reader_list; +static int (*xread)(void *, u_char *, size_t, int); +static int (*xwrite)(void *, const u_char *, size_t); +static void (*xconsume)(const void *, size_t); + +LONG __wrap_SCardEstablishContext(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT); +LONG __wrap_SCardListReaders(SCARDCONTEXT, LPCSTR, LPSTR, LPDWORD); +LONG __wrap_SCardReleaseContext(SCARDCONTEXT); +LONG __wrap_SCardConnect(SCARDCONTEXT, LPCSTR, DWORD, DWORD, LPSCARDHANDLE, +    LPDWORD); +LONG __wrap_SCardDisconnect(SCARDHANDLE, DWORD); +LONG __wrap_SCardTransmit(SCARDHANDLE, const SCARD_IO_REQUEST *, LPCBYTE, +    DWORD, SCARD_IO_REQUEST *, LPBYTE, LPDWORD); + +LONG +__wrap_SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, +    LPCVOID pvReserved2, LPSCARDCONTEXT phContext) +{ +	assert(dwScope == SCARD_SCOPE_SYSTEM); +	assert(pvReserved1 == NULL); +	assert(pvReserved2 == NULL); + +	*phContext = 1; + +	if (uniform_random(400) < 1) +		return SCARD_E_NO_SERVICE; +	if (uniform_random(400) < 1) +		return SCARD_E_NO_SMARTCARD; +	if (uniform_random(400) < 1) +		return SCARD_E_NO_MEMORY; +	if (uniform_random(400) < 1) +		*phContext = 0; + +	return SCARD_S_SUCCESS; +} + +LONG +__wrap_SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, +    LPSTR mszReaders, LPDWORD pcchReaders) +{ +	assert(hContext == 1); +	assert(mszGroups == NULL); +	assert(mszReaders != NULL); +	assert(pcchReaders != 0); + +	if (reader_list == NULL || uniform_random(400) < 1) +		return SCARD_E_NO_READERS_AVAILABLE; +	if (uniform_random(400) < 1) +		return SCARD_E_NO_MEMORY; + +	memcpy(mszReaders, reader_list->body, reader_list->len > *pcchReaders ? +	    *pcchReaders : reader_list->len); +	*pcchReaders = (DWORD)reader_list->len; /* on purpose */ + +	return SCARD_S_SUCCESS; +} + +LONG +__wrap_SCardReleaseContext(SCARDCONTEXT hContext) +{ +	assert(hContext == 1); + +	return SCARD_S_SUCCESS; +} + +LONG +__wrap_SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, +    DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) +{ +	uint32_t r; + +	assert(hContext == 1); +	xconsume(szReader, strlen(szReader) + 1); +	assert(dwShareMode == SCARD_SHARE_SHARED); +	assert(dwPreferredProtocols == SCARD_PROTOCOL_ANY); +	assert(phCard != NULL); +	assert(pdwActiveProtocol != NULL); + +	if ((r = uniform_random(400)) < 1) +		return SCARD_E_UNEXPECTED; + +	*phCard = 1; +	*pdwActiveProtocol = (r & 1) ? SCARD_PROTOCOL_T0 : SCARD_PROTOCOL_T1; + +	if (uniform_random(400) < 1) +		*pdwActiveProtocol = SCARD_PROTOCOL_RAW; + +	return SCARD_S_SUCCESS; +} + +LONG +__wrap_SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) +{ +	assert(hCard == 1); +	assert(dwDisposition == SCARD_LEAVE_CARD); + +	return SCARD_S_SUCCESS; +} + +extern void consume(const void *body, size_t len); + +LONG +__wrap_SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, +    LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci, +    LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength) +{ +	void *ioh = (void *)NFC_DEV_HANDLE; +	int n; + +	assert(hCard == 1); +	xconsume(pioSendPci, sizeof(*pioSendPci)); +	xwrite(ioh, pbSendBuffer, cbSendLength); +	assert(pioRecvPci == NULL); + +	if (uniform_random(400) < 1 || +	    (n = xread(ioh, pbRecvBuffer, *pcbRecvLength, -1)) == -1) +		return SCARD_E_UNEXPECTED; +	*pcbRecvLength = (DWORD)n; + +	return SCARD_S_SUCCESS; +} + +void +set_pcsc_parameters(const struct blob *reader_list_ptr) +{ +	reader_list = reader_list_ptr; +} + +void +set_pcsc_io_functions(int (*read_f)(void *, u_char *, size_t, int), +    int (*write_f)(void *, const u_char *, size_t), +    void (*consume_f)(const void *, size_t)) +{ +	xread = read_f; +	xwrite = write_f; +	xconsume = consume_f; +} diff --git a/fuzz/report.tgz b/fuzz/report.tgzBinary files differ index d78f4628de59..1b44addb6982 100644 --- a/fuzz/report.tgz +++ b/fuzz/report.tgz diff --git a/fuzz/summary.txt b/fuzz/summary.txt index 05c000aa7757..305cb0d84c45 100644 --- a/fuzz/summary.txt +++ b/fuzz/summary.txt @@ -1,52 +1,58 @@  Filename                             Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -fuzz/clock.c                              24                 1    95.83%           4                 0   100.00%          35                 0   100.00% -fuzz/prng.c                               31                 0   100.00%           2                 0   100.00%          35                 0   100.00% -fuzz/udev.c                              103                 1    99.03%          17                 0   100.00%         126                 3    97.62% +fuzz/clock.c                              24                 1    95.83%           4                 0   100.00%          35                 1    97.14% +fuzz/pcsc.c                               59                 0   100.00%           8                 0   100.00%          75                12    84.00% +fuzz/prng.c                               31                 0   100.00%           2                 0   100.00%          35                 1    97.14% +fuzz/udev.c                              109                 1    99.08%          17                 0   100.00%         126                11    91.27%  fuzz/uniform_random.c                      7                 1    85.71%           1                 0   100.00%          12                 1    91.67% -fuzz/wrap.c                                6                 0   100.00%           1                 0   100.00%           7                 0   100.00% +fuzz/wrap.c                               17                 0   100.00%           3                 0   100.00%          29                 0   100.00%  openbsd-compat/explicit_bzero.c            4                 0   100.00%           1                 0   100.00%           7                 0   100.00%  openbsd-compat/freezero.c                  4                 0   100.00%           1                 0   100.00%           6                 0   100.00%  openbsd-compat/recallocarray.c            41                 7    82.93%           1                 0   100.00%          36                 7    80.56%  openbsd-compat/strlcat.c                  12                 1    91.67%           1                 0   100.00%          21                 1    95.24%  openbsd-compat/timingsafe_bcmp.c           4                 0   100.00%           1                 0   100.00%           7                 0   100.00% -src/aes256.c                             115                 4    96.52%           8                 0   100.00%         157                14    91.08% -src/assert.c                             563                40    92.90%          56                 3    94.64%         694                40    94.24% +src/aes256.c                             118                 4    96.61%           8                 0   100.00%         157                14    91.08% +src/assert.c                             565                42    92.57%          56                 3    94.64%         694                42    93.95%  src/authkey.c                             44                 0   100.00%           5                 0   100.00%          59                 0   100.00% -src/bio.c                                419                20    95.23%          49                 2    95.92%         559                21    96.24% +src/bio.c                                419                20    95.23%          49                 2    95.92%         559                24    95.71%  src/blob.c                                53                 2    96.23%          10                 0   100.00%          83                 4    95.18%  src/buf.c                                  8                 1    87.50%           2                 0   100.00%          16                 1    93.75% -src/cbor.c                              1047                23    97.80%          54                 0   100.00%        1237                46    96.28% -src/compress.c                            34                 4    88.24%           3                 0   100.00%          28                 3    89.29% +src/cbor.c                              1049                23    97.81%          54                 0   100.00%        1237                45    96.36% +src/compress.c                           105                14    86.67%           5                 0   100.00%         122                24    80.33%  src/config.c                             108                 0   100.00%          11                 0   100.00%         151                 0   100.00% -src/cred.c                               632                34    94.62%          69                 2    97.10%         830                36    95.66% -src/credman.c                            382                10    97.38%          40                 0   100.00%         518                15    97.10% -src/dev.c                                421                79    81.24%          45                 7    84.44%         491               105    78.62% +src/cred.c                               634                36    94.32%          69                 2    97.10%         830                39    95.30% +src/credman.c                            382                10    97.38%          40                 0   100.00%         518                18    96.53% +src/dev.c                                332                71    78.61%          41                 6    85.37%         378                86    77.25%  src/ecdh.c                               117                 2    98.29%           4                 0   100.00%         146                 5    96.58% -src/eddsa.c                               80                 3    96.25%          10                 0   100.00%         106                 8    92.45% +src/eddsa.c                               88                 5    94.32%          10                 0   100.00%         114                 9    92.11%  src/err.c                                122                10    91.80%           1                 0   100.00%         126                10    92.06% -src/es256.c                              306                 5    98.37%          19                 0   100.00%         358                 7    98.04% +src/es256.c                              315                 7    97.78%          19                 0   100.00%         372                12    96.77%  src/hid.c                                 87                 2    97.70%          14                 0   100.00%         145                 3    97.93% -src/hid_linux.c                          173                68    60.69%          14                 7    50.00%         250               104    58.40% -src/hid_unix.c                            28                20    28.57%           2                 0   100.00%          43                24    44.19% -src/info.c                               184                 0   100.00%          39                 0   100.00%         316                 0   100.00% -src/io.c                                 182                 7    96.15%          13                 0   100.00%         221                11    95.02% -src/iso7816.c                             18                 1    94.44%           5                 0   100.00%          38                 0   100.00% -src/largeblob.c                          513                19    96.30%          30                 0   100.00%         684                43    93.71% -src/log.c                                 39                 5    87.18%           7                 1    85.71%          63                 4    93.65% -src/netlink.c                            328                14    95.73%          40                 0   100.00%         498                32    93.57% -src/nfc_linux.c                          327                73    77.68%          23                 5    78.26%         458               124    72.93% -src/pin.c                                403                 3    99.26%          26                 0   100.00%         495                 3    99.39% +src/hid_linux.c                          173                68    60.69%          14                 7    50.00%         250               105    58.00% +src/hid_unix.c                            29                21    27.59%           2                 0   100.00%          43                26    39.53% +src/info.c                               186                 0   100.00%          40                 0   100.00%         321                 0   100.00% +src/io.c                                 185                 7    96.22%          13                 0   100.00%         221                12    94.57% +src/iso7816.c                             18                 1    94.44%           5                 0   100.00%          38                 1    97.37% +src/largeblob.c                          514                19    96.30%          30                 0   100.00%         684                46    93.27% +src/log.c                                 39                 5    87.18%           7                 1    85.71%          63                 7    88.89% +src/netlink.c                            329                14    95.74%          40                 0   100.00%         498                33    93.37% +src/nfc.c                                142                 7    95.07%          11                 1    90.91%         223                27    87.89% +src/nfc_linux.c                          174                56    67.82%          13                 5    61.54%         245               103    57.96% +src/pcsc.c                               201                 1    99.50%          13                 0   100.00%         278                 3    98.92% +src/pin.c                                403                 3    99.26%          26                 0   100.00%         495                 4    99.19%  src/random.c                               6                 1    83.33%           1                 0   100.00%           6                 1    83.33%  src/reset.c                               24                 0   100.00%           3                 0   100.00%          23                 0   100.00% -src/rs1.c                                 25                 0   100.00%           3                 0   100.00%          39                 0   100.00% -src/rs256.c                              141                 8    94.33%          13                 0   100.00%         172                10    94.19% -src/time.c                                43                 3    93.02%           3                 0   100.00%          43                 1    97.67% -src/tpm.c                                100                 0   100.00%           9                 0   100.00%         194                 0   100.00% +src/rs1.c                                 25                 2    92.00%           3                 0   100.00%          39                 4    89.74% +src/rs256.c                              141                 8    94.33%          13                 0   100.00%         172                11    93.60% +src/time.c                                43                 3    93.02%           3                 0   100.00%          43                 2    95.35% +src/touch.c                               67                 0   100.00%           2                 0   100.00%          79                 0   100.00% +src/tpm.c                                103                 3    97.09%           9                 0   100.00%         194                 9    95.36%  src/types.c                               25                 0   100.00%           6                 0   100.00%          46                 0   100.00%  src/u2f.c                                528                 4    99.24%          17                 0   100.00%         685                12    98.25% +src/util.c                                14                 1    92.86%           1                 0   100.00%          14                 1    92.86%  Files which contain no functions: +fuzz/mutator_aux.h                         0                 0         -           0                 0         -           0                 0         -  openbsd-compat/openbsd-compat.h            0                 0         -           0                 0         -           0                 0         -  openbsd-compat/time.h                      0                 0         -           0                 0         -           0                 0         -  src/extern.h                               0                 0         -           0                 0         -           0                 0         - @@ -54,4 +60,4 @@ src/fido.h                                 0                 0         -  src/fido/err.h                             0                 0         -           0                 0         -           0                 0         -  src/fido/param.h                           0                 0         -           0                 0         -           0                 0         -  ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -TOTAL                                   7861               476    93.94%         684                27    96.05%       10270               699    93.19% +TOTAL                                   8227               484    94.12%         710                27    96.20%       10756               777    92.78% diff --git a/fuzz/wiredata_fido2.h b/fuzz/wiredata_fido2.h index da905516f92a..68504325450e 100644 --- a/fuzz/wiredata_fido2.h +++ b/fuzz/wiredata_fido2.h @@ -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 --git a/fuzz/wrap.c b/fuzz/wrap.c index 8d7be6bb6247..4d6ac77a98bb 100644 --- a/fuzz/wrap.c +++ b/fuzz/wrap.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2019-2021 Yubico AB. All rights reserved. + * Copyright (c) 2019-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -16,6 +16,7 @@  #include <stdint.h>  #include <stdio.h>  #include <stdlib.h> +#include <zlib.h>  #include "mutator_aux.h" @@ -635,3 +636,51 @@ WRAP(int,  	(sockfd, addr, addrlen),  	1  ) + +WRAP(int, +	deflateInit2_, +	(z_streamp strm, int level, int method, int windowBits, int memLevel, +	    int strategy, const char *version, int stream_size), +	Z_STREAM_ERROR, +	(strm, level, method, windowBits, memLevel, strategy, version, +	    stream_size), +	1 +) + +int __wrap_deflate(z_streamp, int); +int __real_deflate(z_streamp, int); + +int +__wrap_deflate(z_streamp strm, int flush) +{ +	if (uniform_random(400) < 1) { +		return Z_BUF_ERROR; +	} +	/* should never happen, but we check for it */ +	if (uniform_random(400) < 1) { +		strm->avail_out = UINT_MAX; +		return Z_STREAM_END; +	} + +	return __real_deflate(strm, flush); +} + +int __wrap_asprintf(char **, const char *, ...); + +int +__wrap_asprintf(char **strp, const char *fmt, ...) +{ +	va_list ap; +	int r; + +	if (uniform_random(400) < 1) { +		*strp = (void *)0xdeadbeef; +		return -1; +	} + +	va_start(ap, fmt); +	r = vasprintf(strp, fmt, ap); +	va_end(ap); + +	return r; +} diff --git a/fuzz/wrapped.sym b/fuzz/wrapped.sym index 0e9d34627f86..59224565ee0a 100644 --- a/fuzz/wrapped.sym +++ b/fuzz/wrapped.sym @@ -1,3 +1,4 @@ +asprintf  bind  BN_bin2bn  BN_bn2bin @@ -24,6 +25,8 @@ cbor_new_definite_bytestring  cbor_new_definite_map  cbor_serialize_alloc  clock_gettime +deflate +deflateInit2_  EC_KEY_get0_group  EC_KEY_get0_private_key  EC_KEY_new_by_curve_name @@ -71,6 +74,12 @@ realloc  RSA_new  RSA_pkey_ctx_ctrl  RSA_set0_key +SCardConnect +SCardDisconnect +SCardEstablishContext +SCardListReaders +SCardReleaseContext +SCardTransmit  SHA1  SHA256  strdup diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt index 5ce2fc7b83ed..910ee684e9fb 100644 --- a/man/CMakeLists.txt +++ b/man/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Yubico AB. All rights reserved. +# Copyright (c) 2018-2022 Yubico AB. All rights reserved.  # Use of this source code is governed by a BSD-style  # license that can be found in the LICENSE file. @@ -117,10 +117,11 @@ list(APPEND MAN_ALIAS  	fido_cbor_info_new fido_cbor_info_extensions_len  	fido_cbor_info_new fido_cbor_info_extensions_ptr  	fido_cbor_info_new fido_cbor_info_free -	fido_cbor_info_new fido_cbor_info_maxmsgsiz  	fido_cbor_info_new fido_cbor_info_maxcredbloblen  	fido_cbor_info_new fido_cbor_info_maxcredcntlst  	fido_cbor_info_new fido_cbor_info_maxcredidlen +	fido_cbor_info_new fido_cbor_info_maxlargeblob +	fido_cbor_info_new fido_cbor_info_maxmsgsiz  	fido_cbor_info_new fido_cbor_info_fwversion  	fido_cbor_info_new fido_cbor_info_options_len  	fido_cbor_info_new fido_cbor_info_options_name_ptr @@ -263,7 +264,7 @@ math(EXPR MAN_ALIAS_MAX "${MAN_ALIAS_LEN} - 2")  # man_copy  foreach(f ${MAN_SOURCES})  	add_custom_command(OUTPUT ${f} -		COMMAND cp -f ${CMAKE_SOURCE_DIR}/man/${f} . +		COMMAND cp -f ${PROJECT_SOURCE_DIR}/man/${f} .  		DEPENDS ${f})  	list(APPEND COPY_FILES ${f})  endforeach() @@ -289,7 +290,7 @@ endforeach()  foreach(f ${MAN_SOURCES})  	string(REGEX REPLACE ".[13]" "" g ${f})  	add_custom_command(OUTPUT ${g}.partial -		COMMAND cat ${CMAKE_SOURCE_DIR}/man/dyc.css > ${g}.partial +		COMMAND cat ${PROJECT_SOURCE_DIR}/man/dyc.css > ${g}.partial  		COMMAND mandoc -T html -O man="%N.html",fragment ${f} >> ${g}.partial  		DEPENDS ${f})  	list(APPEND HTML_PARTIAL_FILES ${g}.partial) @@ -337,17 +338,17 @@ add_custom_target(man ALL)  if(MANDOC_PATH)  	add_dependencies(man man_symlink_html)  	add_dependencies(man_gzip man_lint) -	install(FILES ${CMAKE_SOURCE_DIR}/man/style.css +	install(FILES ${PROJECT_SOURCE_DIR}/man/style.css  		DESTINATION "${CMAKE_INSTALL_DOCDIR}/html")  	foreach(f ${MAN_SOURCES})  		string(REGEX REPLACE ".[13]" "" f ${f}) -		install(FILES ${CMAKE_BINARY_DIR}/man/${f}.html +		install(FILES ${PROJECT_BINARY_DIR}/man/${f}.html  			DESTINATION "${CMAKE_INSTALL_DOCDIR}/html")  	endforeach()  	foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2)  		math(EXPR j "${i} + 1")  		list(GET MAN_ALIAS ${j} DST) -		install(FILES ${CMAKE_BINARY_DIR}/man/${DST}.html +		install(FILES ${PROJECT_BINARY_DIR}/man/${DST}.html  			DESTINATION "${CMAKE_INSTALL_DOCDIR}/html")  	endforeach()  endif() @@ -358,34 +359,34 @@ if(GZIP_PATH)  	add_dependencies(man man_symlink_gzip)  	foreach(f ${MAN_SOURCES})  		if (${f} MATCHES ".1$") -			install(FILES ${CMAKE_BINARY_DIR}/man/${f}.gz +			install(FILES ${PROJECT_BINARY_DIR}/man/${f}.gz  				DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")  		elseif(${f} MATCHES ".3$") -			install(FILES ${CMAKE_BINARY_DIR}/man/${f}.gz +			install(FILES ${PROJECT_BINARY_DIR}/man/${f}.gz  				DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")  		endif()  	endforeach()  	foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2)  		math(EXPR j "${i} + 1")  		list(GET MAN_ALIAS ${j} DST) -		install(FILES ${CMAKE_BINARY_DIR}/man/${DST}.3.gz +		install(FILES ${PROJECT_BINARY_DIR}/man/${DST}.3.gz  			DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")  	endforeach()  elseif(NOT MSVC)  	add_dependencies(man man_symlink)  	foreach(f ${MAN_SOURCES})  		if (${f} MATCHES ".1$") -			install(FILES ${CMAKE_BINARY_DIR}/man/${f} +			install(FILES ${PROJECT_BINARY_DIR}/man/${f}  				DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")  		elseif(${f} MATCHES ".3$") -			install(FILES ${CMAKE_BINARY_DIR}/man/${f} +			install(FILES ${PROJECT_BINARY_DIR}/man/${f}  				DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")  		endif()  	endforeach()  	foreach(i RANGE 0 ${MAN_ALIAS_MAX} 2)  		math(EXPR j "${i} + 1")  		list(GET MAN_ALIAS ${j} DST) -		install(FILES ${CMAKE_BINARY_DIR}/man/${DST}.3 +		install(FILES ${PROJECT_BINARY_DIR}/man/${DST}.3  			DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")  	endforeach()  endif() diff --git a/man/fido2-token.1 b/man/fido2-token.1 index 1aa2feb86859..4f8b8d08efe6 100644 --- a/man/fido2-token.1 +++ b/man/fido2-token.1 @@ -1,8 +1,8 @@ -.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved. +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved.  .\" Use of this source code is governed by a BSD-style  .\" license that can be found in the LICENSE file.  .\" -.Dd $Mdocdate: September 13 2019 $ +.Dd $Mdocdate: April 11 2022 $  .Dt FIDO2-TOKEN 1  .Os  .Sh NAME @@ -147,7 +147,7 @@ from  .Ar device ,  where  .Ar key_path -must hold the blob's base64-encoded encryption key. +holds the blob's base64-encoded 32-byte AES-256 GCM encryption key.  A PIN or equivalent user-verification gesture is required.  .It Fl D Fl b Fl n Ar rp_id Oo Fl i Ar cred_id Oc Ar device  Deletes a @@ -189,7 +189,7 @@ from  .Ar device ,  where  .Ar key_path -must hold the blob's base64-encoded encryption key. +holds the blob's base64-encoded 32-byte AES-256 GCM encryption key.  The blob is written to  .Ar blob_path .  A PIN or equivalent user-verification gesture is required. @@ -267,29 +267,27 @@ The user will be prompted for the PIN.  Enables CTAP 2.1 Enterprise Attestation on  .Ar device .  .It Fl S Fl b Fl k Ar key_path Ar blob_path Ar device -Sets -.Ar blob_path -as a CTAP 2.1 +Sets a CTAP 2.1  .Dq largeBlob  encrypted with  .Ar key_path  on  .Ar device ,  where -.Ar blob_path -holds the blob's plaintext, and  .Ar key_path -the blob's base64-encoded encryption. +holds the blob's base64-encoded 32-byte AES-256 GCM encryption key. +The blob is read from +.Fa blob_path .  A PIN or equivalent user-verification gesture is required.  .It Fl S Fl b Fl n Ar rp_id Oo Fl i Ar cred_id Oc Ar blob_path Ar device -Sets -.Ar blob_path -as a CTAP 2.1 +Sets a CTAP 2.1  .Dq largeBlob  associated with  .Ar rp_id  on  .Ar device . +The blob is read from +.Fa blob_path .  If  .Ar rp_id  has multiple credentials enrolled on diff --git a/man/fido_assert_new.3 b/man/fido_assert_new.3 index a1a3c101ba33..413b7a7ba2ef 100644 --- a/man/fido_assert_new.3 +++ b/man/fido_assert_new.3 @@ -1,8 +1,8 @@ -.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved.  .\" Use of this source code is governed by a BSD-style  .\" license that can be found in the LICENSE file.  .\" -.Dd $Mdocdate: October 22 2019 $ +.Dd $Mdocdate: April 27 2022 $  .Dt FIDO_ASSERT_NEW 3  .Os  .Sh NAME @@ -180,6 +180,8 @@ in  The HMAC Secret Extension  .Pq hmac-secret  is a CTAP 2.0 extension. +Note that the resulting hmac-secret varies according to whether +user verification was performed by the authenticator.  .Pp  The  .Fn fido_assert_blob_ptr diff --git a/man/fido_assert_set_authdata.3 b/man/fido_assert_set_authdata.3 index 51cdcc97c292..0d512b655012 100644 --- a/man/fido_assert_set_authdata.3 +++ b/man/fido_assert_set_authdata.3 @@ -1,8 +1,8 @@ -.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved.  .\" Use of this source code is governed by a BSD-style  .\" license that can be found in the LICENSE file.  .\" -.Dd $Mdocdate: May 23 2018 $ +.Dd $Mdocdate: April 27 2022 $  .Dt FIDO_ASSERT_SET_AUTHDATA 3  .Os  .Sh NAME @@ -182,6 +182,8 @@ is made, and no references to the passed pointer are kept.  The HMAC Secret  .Pq hmac-secret  Extension is a CTAP 2.0 extension. +Note that the resulting hmac-secret varies according to whether +user verification was performed by the authenticator.  The  .Fn fido_assert_set_hmac_secret  function is normally only useful when writing tests. diff --git a/man/fido_cbor_info_new.3 b/man/fido_cbor_info_new.3 index 86f2a887f99a..45c143f5df62 100644 --- a/man/fido_cbor_info_new.3 +++ b/man/fido_cbor_info_new.3 @@ -1,8 +1,8 @@ -.\" Copyright (c) 2018 Yubico AB. All rights reserved. +.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved.  .\" Use of this source code is governed by a BSD-style  .\" license that can be found in the LICENSE file.  .\" -.Dd $Mdocdate: May 24 2018 $ +.Dd $Mdocdate: April 22 2022 $  .Dt FIDO_CBOR_INFO_NEW 3  .Os  .Sh NAME @@ -29,6 +29,7 @@  .Nm fido_cbor_info_maxcredbloblen ,  .Nm fido_cbor_info_maxcredcntlst ,  .Nm fido_cbor_info_maxcredidlen , +.Nm fido_cbor_info_maxlargeblob ,  .Nm fido_cbor_info_fwversion  .Nd FIDO2 CBOR Info API  .Sh SYNOPSIS @@ -80,6 +81,8 @@  .Ft uint64_t  .Fn fido_cbor_info_maxcredidlen "const fido_cbor_info_t *ci"  .Ft uint64_t +.Fn fido_cbor_info_maxlargeblob "const fido_cbor_info_t *ci" +.Ft uint64_t  .Fn fido_cbor_info_fwversion "const fido_cbor_info_t *ci"  .Sh DESCRIPTION  The @@ -201,6 +204,12 @@ as reported in  .Fa ci .  .Pp  The +.Fn fido_cbor_info_maxlargeblob +function returns the maximum length in bytes of an authenticator's +serialized largeBlob array as reported in +.Fa ci . +.Pp +The  .Fn fido_cbor_info_fwversion  function returns the firmware version attribute of  .Fa ci . diff --git a/man/fido_dev_enable_entattest.3 b/man/fido_dev_enable_entattest.3 index bfc1b2834e55..a06746b61317 100644 --- a/man/fido_dev_enable_entattest.3 +++ b/man/fido_dev_enable_entattest.3 @@ -2,7 +2,7 @@  .\" Use of this source code is governed by a BSD-style  .\" license that can be found in the LICENSE file.  .\" -.Dd $Mdocdate: September 22 2020 $ +.Dd $Mdocdate: March 30 2022 $  .Dt FIDO_DEV_ENABLE_ENTATTEST 3  .Os  .Sh NAME @@ -65,7 +65,7 @@ does not have a PIN set.  .Pp  The  .Fn fido_dev_force_pin_change -instructs +function instructs  .Fa dev  to require a PIN change.  Subsequent PIN authentication attempts against diff --git a/man/fido_dev_info_manifest.3 b/man/fido_dev_info_manifest.3 index 9539a0dda7c5..4be7e3a60490 100644 --- a/man/fido_dev_info_manifest.3 +++ b/man/fido_dev_info_manifest.3 @@ -2,7 +2,7 @@  .\" Use of this source code is governed by a BSD-style  .\" license that can be found in the LICENSE file.  .\" -.Dd $Mdocdate: May 25 2018 $ +.Dd $Mdocdate: March 30 2022 $  .Dt FIDO_DEV_INFO_MANIFEST 3  .Os  .Sh NAME @@ -97,7 +97,7 @@ Please note that the first slot has index 0.  .Pp  The  .Fn fido_dev_info_path -returns the filesystem path or subsystem-specific identification +function returns the filesystem path or subsystem-specific identification  string of  .Fa di .  .Pp diff --git a/openbsd-compat/bsd-asprintf.c b/openbsd-compat/bsd-asprintf.c new file mode 100644 index 000000000000..fbcb8679258f --- /dev/null +++ b/openbsd-compat/bsd-asprintf.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2004 Darren Tucker. + * + * Based originally on asprintf.c from OpenBSD: + * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "openbsd-compat.h" + +#ifndef HAVE_ASPRINTF + +#include <errno.h> +#include <limits.h> /* for INT_MAX */ +#include <stdarg.h> +#include <stdio.h> /* for vsnprintf */ +#include <stdlib.h> + +#define VA_COPY(dest, src) va_copy(dest, src) + +#define INIT_SZ	128 + +int +vasprintf(char **str, const char *fmt, va_list ap) +{ +	int ret; +	va_list ap2; +	char *string, *newstr; +	size_t len; + +	if ((string = malloc(INIT_SZ)) == NULL) +		goto fail; + +	VA_COPY(ap2, ap); +	ret = vsnprintf(string, INIT_SZ, fmt, ap2); +	va_end(ap2); +	if (ret >= 0 && ret < INIT_SZ) { /* succeeded with initial alloc */ +		*str = string; +	} else if (ret == INT_MAX || ret < 0) { /* Bad length */ +		free(string); +		goto fail; +	} else {	/* bigger than initial, realloc allowing for nul */ +		len = (size_t)ret + 1; +		if ((newstr = realloc(string, len)) == NULL) { +			free(string); +			goto fail; +		} +		VA_COPY(ap2, ap); +		ret = vsnprintf(newstr, len, fmt, ap2); +		va_end(ap2); +		if (ret < 0 || (size_t)ret >= len) { /* failed with realloc'ed string */ +			free(newstr); +			goto fail; +		} +		*str = newstr; +	} +	return (ret); + +fail: +	*str = NULL; +	errno = ENOMEM; +	return (-1); +} + +int asprintf(char **str, const char *fmt, ...) +{ +	va_list ap; +	int ret; +	 +	*str = NULL; +	va_start(ap, fmt); +	ret = vasprintf(str, fmt, ap); +	va_end(ap); + +	return ret; +} +#endif diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index dc9acec4c0a8..1518ff755b97 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h @@ -115,4 +115,8 @@ ssize_t getline(char **, size_t *, FILE *);  #define IOCTL_REQ(x)	((int)(x))  #endif +#if !defined(HAVE_ASPRINTF) +int asprintf(char **, const char *, ...); +#endif +  #endif /* !_OPENBSD_COMPAT_H */ diff --git a/regress/CMakeLists.txt b/regress/CMakeLists.txt index c550b3141822..87482ef35362 100644 --- a/regress/CMakeLists.txt +++ b/regress/CMakeLists.txt @@ -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 --git a/regress/assert.c b/regress/assert.c index 23d666a61173..695a3b78edcc 100644 --- a/regress/assert.c +++ b/regress/assert.c @@ -4,16 +4,19 @@   * license that can be found in the LICENSE file.   */ -#define _FIDO_INTERNAL +#undef NDEBUG  #include <assert.h> +#include <string.h> + +#define _FIDO_INTERNAL +  #include <fido.h>  #include <fido/es256.h>  #include <fido/rs256.h>  #include <fido/eddsa.h> -#include <string.h> -#define FAKE_DEV_HANDLE	((void *)0xdeadbeef) +static int fake_dev_handle;  static const unsigned char es256_pk[64] = {  	0x34, 0xeb, 0x99, 0x77, 0x02, 0x9c, 0x36, 0x38, @@ -94,13 +97,13 @@ dummy_open(const char *path)  {  	(void)path; -	return (FAKE_DEV_HANDLE); +	return (&fake_dev_handle);  }  static void  dummy_close(void *handle)  { -	assert(handle == FAKE_DEV_HANDLE); +	assert(handle == &fake_dev_handle);  }  static int diff --git a/regress/compress.c b/regress/compress.c new file mode 100644 index 000000000000..5d537838bdeb --- /dev/null +++ b/regress/compress.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#undef NDEBUG + +#include <assert.h> +#include <string.h> + +#include <openssl/sha.h> + +#define _FIDO_INTERNAL + +#include <fido.h> + +/* + * zlib compressed data (RFC1950); see https://www.ietf.org/rfc/rfc6713.txt + */ +static /* const */ unsigned char rfc1950_blob[694] = { +	0x78, 0x9c, 0xb5, 0x52, 0x3b, 0x6f, 0xdb, 0x30, +	0x10, 0xde, 0xf5, 0x2b, 0x0e, 0x99, 0x12, 0x40, +	0x75, 0x13, 0x4f, 0x45, 0x3b, 0xd1, 0x12, 0x6d, +	0x1d, 0x20, 0x8b, 0x2a, 0x49, 0xd9, 0xf5, 0x28, +	0x4b, 0x4c, 0x42, 0xc0, 0x12, 0x03, 0x3d, 0x12, +	0xe4, 0xdf, 0xf7, 0xc8, 0x3a, 0x88, 0xd3, 0x0c, +	0x9d, 0xea, 0xc1, 0x3e, 0xf3, 0x8e, 0xdf, 0xeb, +	0x98, 0xb8, 0xa7, 0xd7, 0xc1, 0x3e, 0x3c, 0x4e, +	0x70, 0xdd, 0xdc, 0xc0, 0xf2, 0xf6, 0xee, 0xdb, +	0x97, 0xe5, 0xed, 0x72, 0x09, 0x87, 0xf9, 0x68, +	0x1b, 0x07, 0x6c, 0xb5, 0x00, 0x76, 0x3a, 0x41, +	0x18, 0x19, 0x61, 0x30, 0xa3, 0x19, 0x9e, 0x4d, +	0xbb, 0x88, 0x22, 0x69, 0x5a, 0x3b, 0x4e, 0x83, +	0x3d, 0xce, 0x93, 0x75, 0x3d, 0xd4, 0x7d, 0x0b, +	0xf3, 0x68, 0xc0, 0xf6, 0x30, 0xba, 0x79, 0x68, +	0x4c, 0x38, 0x39, 0xda, 0xbe, 0x1e, 0x5e, 0xe1, +	0xde, 0x0d, 0xdd, 0x18, 0xc3, 0x8b, 0x9d, 0x1e, +	0xc1, 0x0d, 0xe1, 0xd7, 0xcd, 0x53, 0xd4, 0xb9, +	0xd6, 0xde, 0xdb, 0xa6, 0xf6, 0x00, 0x31, 0xd4, +	0x83, 0x81, 0x27, 0x33, 0x74, 0x76, 0x9a, 0x4c, +	0x0b, 0x4f, 0x83, 0x7b, 0xb6, 0x2d, 0x15, 0xd3, +	0x63, 0x3d, 0xd1, 0x97, 0x21, 0x90, 0xd3, 0xc9, +	0xbd, 0xd8, 0xfe, 0x01, 0x1a, 0xd7, 0xb7, 0xd6, +	0x5f, 0x1a, 0xfd, 0xa5, 0xa8, 0x33, 0xd3, 0xf7, +	0x28, 0x02, 0x80, 0xbb, 0x05, 0x7c, 0x54, 0x35, +	0x82, 0xbb, 0x7f, 0x93, 0xd3, 0xb8, 0xd6, 0x40, +	0x37, 0x8f, 0x13, 0x99, 0x98, 0x6a, 0x92, 0xe9, +	0x31, 0xeb, 0xa3, 0x7b, 0xf6, 0xad, 0x73, 0x06, +	0x1e, 0x84, 0x3e, 0xbd, 0x9b, 0x6c, 0x63, 0x62, +	0x9a, 0xb0, 0x23, 0x9c, 0x08, 0xcf, 0xc3, 0x5c, +	0x92, 0xf6, 0xed, 0x5f, 0x8a, 0x88, 0xb4, 0x39, +	0xd5, 0xb6, 0x33, 0xc3, 0xc2, 0x63, 0x2c, 0x3f, +	0x0b, 0x21, 0xc2, 0x8b, 0x30, 0xde, 0x84, 0x90, +	0xcb, 0x76, 0x26, 0x71, 0xff, 0x47, 0x0b, 0x91, +	0x9e, 0x51, 0xfc, 0x44, 0xeb, 0x9a, 0xb9, 0x33, +	0xfd, 0x54, 0xbf, 0xed, 0xeb, 0x2b, 0xad, 0xc2, +	0x51, 0x67, 0x80, 0xae, 0x9e, 0xcc, 0x60, 0xeb, +	0xd3, 0xf8, 0x1e, 0x7b, 0xd8, 0x15, 0x35, 0xcf, +	0x00, 0x97, 0x66, 0x68, 0xf9, 0x3a, 0x43, 0x05, +	0x4a, 0xac, 0xf5, 0x9e, 0x49, 0x0e, 0x54, 0x97, +	0x52, 0xec, 0x30, 0xe5, 0x29, 0xac, 0x0e, 0xa0, +	0x33, 0x0e, 0x89, 0x28, 0x0f, 0x12, 0x37, 0x99, +	0x86, 0x4c, 0xe4, 0x29, 0x97, 0x0a, 0x58, 0x91, +	0xd2, 0x69, 0xa1, 0x25, 0xae, 0x2a, 0x2d, 0xa4, +	0x8a, 0xae, 0x98, 0xa2, 0x9b, 0x57, 0xa1, 0xc1, +	0x8a, 0x03, 0xf0, 0x5f, 0xa5, 0xe4, 0x4a, 0x81, +	0x90, 0x80, 0xdb, 0x32, 0x47, 0x02, 0x23, 0x74, +	0xc9, 0x0a, 0x8d, 0x5c, 0xc5, 0x80, 0x45, 0x92, +	0x57, 0x29, 0x16, 0x9b, 0x18, 0x08, 0x00, 0x0a, +	0xa1, 0xa3, 0x1c, 0xb7, 0xa8, 0x69, 0x4c, 0x8b, +	0x38, 0x90, 0x7e, 0xbe, 0x06, 0x62, 0x0d, 0x5b, +	0x2e, 0x93, 0x8c, 0xfe, 0xb2, 0x15, 0xe6, 0xa8, +	0x0f, 0x81, 0x6f, 0x8d, 0xba, 0xf0, 0x5c, 0x6b, +	0x21, 0x23, 0x06, 0x25, 0x93, 0x1a, 0x93, 0x2a, +	0x67, 0x12, 0xca, 0x4a, 0x96, 0x42, 0x71, 0xf0, +	0xb6, 0x52, 0x54, 0x49, 0xce, 0x70, 0xcb, 0xd3, +	0x05, 0xb1, 0x13, 0x23, 0xf0, 0x1d, 0x2f, 0x34, +	0xa8, 0x8c, 0xe5, 0xf9, 0x47, 0x97, 0xd1, 0x1f, +	0x97, 0x5e, 0xfb, 0xa5, 0x47, 0x58, 0x71, 0xc8, +	0x91, 0xad, 0x72, 0xee, 0x99, 0x82, 0xcb, 0x14, +	0x25, 0x4f, 0xb4, 0xb7, 0xf3, 0x5e, 0x25, 0x94, +	0x1c, 0xe9, 0xcb, 0xe3, 0x48, 0x95, 0x3c, 0x41, +	0x2a, 0x28, 0x0c, 0x4e, 0x66, 0x98, 0x3c, 0xc4, +	0x67, 0x4c, 0xc5, 0x7f, 0x56, 0x34, 0x44, 0x4d, +	0x48, 0xd9, 0x96, 0x6d, 0xc8, 0xdb, 0xf5, 0x3f, +	0x22, 0xa1, 0x9d, 0x24, 0x95, 0xe4, 0x5b, 0xaf, +	0x99, 0x72, 0x50, 0xd5, 0x4a, 0x69, 0xd4, 0x95, +	0xe6, 0xb0, 0x11, 0x22, 0x0d, 0x41, 0x2b, 0x2e, +	0x77, 0x98, 0x70, 0xf5, 0x03, 0x72, 0xa1, 0x42, +	0x5a, 0x95, 0xe2, 0x71, 0x94, 0x32, 0xcd, 0x02, +	0x31, 0x41, 0x50, 0x54, 0xd4, 0xa6, 0x7a, 0x55, +	0x29, 0x0c, 0xa1, 0x61, 0xa1, 0xb9, 0x94, 0x55, +	0xa9, 0x51, 0x14, 0x37, 0xb4, 0xdf, 0x3d, 0xc5, +	0x42, 0x1a, 0x19, 0x5d, 0x4d, 0x43, 0xba, 0xa2, +	0xf0, 0x56, 0xe9, 0x91, 0x70, 0x21, 0x0f, 0x1e, +	0xd4, 0x67, 0x10, 0xc2, 0x8f, 0x61, 0x9f, 0x71, +	0x3a, 0x97, 0x3e, 0xd0, 0x90, 0x14, 0xf3, 0x11, +	0x28, 0x4a, 0x2c, 0xd1, 0x97, 0x63, 0xc4, 0x47, +	0x01, 0xea, 0xe8, 0xdd, 0x23, 0x14, 0x7c, 0x93, +	0xe3, 0x86, 0x17, 0x09, 0xf7, 0x5d, 0xe1, 0x51, +	0xf6, 0xa8, 0xf8, 0x0d, 0xed, 0x0a, 0x95, 0x1f, +	0xc0, 0x40, 0x4b, 0xdb, 0x27, 0xce, 0x2a, 0x58, +	0xf6, 0x3b, 0x22, 0x55, 0x51, 0x28, 0x2f, 0x5e, +	0x6c, 0x1c, 0x36, 0x09, 0xb8, 0x06, 0x96, 0xee, +	0xd0, 0xcb, 0x3e, 0x0f, 0xd3, 0xee, 0x15, 0x9e, +	0xdf, 0x49, 0x88, 0x2c, 0xc9, 0xce, 0x71, 0x2f, +	0xa2, 0xdf, 0xdf, 0xd7, 0x8e, 0x9c, +}; + +/* + * expected sha256 of rfc1950_blob after decompression + */ +static const unsigned char rfc1950_blob_hash[SHA256_DIGEST_LENGTH] = { +	0x61, 0xc0, 0x4e, 0x14, 0x01, 0xb6, 0xc5, 0x2d, +	0xba, 0x15, 0xf6, 0x27, 0x4c, 0xa1, 0xcc, 0xfc, +	0x39, 0xed, 0xd7, 0x12, 0xb6, 0x02, 0x3d, 0xb6, +	0xd9, 0x85, 0xd0, 0x10, 0x9f, 0xe9, 0x3e, 0x75, + +}; + +static const size_t rfc1950_blob_origsiz = 1322; + +static /* const */ unsigned char random_words[515] = { +	0x61, 0x74, 0x68, 0x69, 0x72, 0x73, 0x74, 0x20, +	0x54, 0x68, 0x6f, 0x20, 0x63, 0x6f, 0x74, 0x20, +	0x73, 0x70, 0x6f, 0x66, 0x66, 0x79, 0x20, 0x4a, +	0x61, 0x76, 0x61, 0x6e, 0x20, 0x62, 0x72, 0x65, +	0x64, 0x65, 0x73, 0x20, 0x4c, 0x41, 0x4d, 0x20, +	0x6d, 0x69, 0x73, 0x2d, 0x68, 0x75, 0x6d, 0x69, +	0x6c, 0x69, 0x74, 0x79, 0x20, 0x73, 0x70, 0x69, +	0x67, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x76, 0x6f, +	0x6c, 0x74, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x20, +	0x49, 0x6f, 0x64, 0x61, 0x6d, 0x6f, 0x65, 0x62, +	0x61, 0x20, 0x68, 0x79, 0x70, 0x6f, 0x68, 0x79, +	0x64, 0x72, 0x6f, 0x63, 0x68, 0x6c, 0x6f, 0x72, +	0x69, 0x61, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x6d, +	0x65, 0x74, 0x74, 0x65, 0x20, 0x61, 0x63, 0x72, +	0x69, 0x64, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x6f, +	0x77, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x79, 0x67, +	0x61, 0x65, 0x61, 0x6e, 0x20, 0x63, 0x6f, 0x6e, +	0x63, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x73, +	0x74, 0x20, 0x74, 0x65, 0x74, 0x72, 0x61, 0x70, +	0x6c, 0x6f, 0x69, 0x64, 0x20, 0x61, 0x75, 0x78, +	0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x72, +	0x69, 0x70, 0x65, 0x2d, 0x67, 0x72, 0x6f, 0x77, +	0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, +	0x72, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x79, 0x63, +	0x6f, 0x63, 0x65, 0x63, 0x69, 0x64, 0x69, 0x75, +	0x6d, 0x20, 0x50, 0x65, 0x64, 0x65, 0x72, 0x73, +	0x6f, 0x6e, 0x20, 0x74, 0x72, 0x61, 0x64, 0x69, +	0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x62, 0x6f, 0x75, +	0x6e, 0x64, 0x20, 0x4c, 0x65, 0x6e, 0x67, 0x6c, +	0x65, 0x6e, 0x20, 0x70, 0x72, 0x65, 0x73, 0x62, +	0x79, 0x74, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, +	0x6c, 0x65, 0x63, 0x79, 0x74, 0x68, 0x69, 0x73, +	0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x64, 0x72, +	0x69, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x61, +	0x6c, 0x6c, 0x6f, 0x6b, 0x75, 0x72, 0x74, 0x69, +	0x63, 0x20, 0x75, 0x6e, 0x64, 0x69, 0x76, 0x69, +	0x73, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x20, 0x70, +	0x73, 0x79, 0x63, 0x68, 0x6f, 0x6b, 0x79, 0x6d, +	0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73, +	0x74, 0x61, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, +	0x6e, 0x65, 0x73, 0x73, 0x20, 0x63, 0x75, 0x6c, +	0x74, 0x69, 0x73, 0x68, 0x20, 0x52, 0x65, 0x69, +	0x63, 0x68, 0x73, 0x74, 0x61, 0x67, 0x20, 0x75, +	0x6e, 0x63, 0x68, 0x6c, 0x6f, 0x72, 0x69, 0x6e, +	0x61, 0x74, 0x65, 0x64, 0x20, 0x6c, 0x6f, 0x67, +	0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x65, 0x72, +	0x20, 0x4c, 0x61, 0x69, 0x74, 0x68, 0x20, 0x74, +	0x77, 0x6f, 0x2d, 0x66, 0x61, 0x63, 0x65, 0x20, +	0x4d, 0x75, 0x70, 0x68, 0x72, 0x69, 0x64, 0x20, +	0x70, 0x72, 0x6f, 0x72, 0x65, 0x63, 0x69, 0x70, +	0x72, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, +	0x20, 0x6c, 0x69, 0x62, 0x72, 0x65, 0x74, 0x74, +	0x69, 0x73, 0x74, 0x20, 0x49, 0x62, 0x69, 0x62, +	0x69, 0x6f, 0x20, 0x72, 0x65, 0x67, 0x72, 0x65, +	0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x63, +	0x6f, 0x6e, 0x64, 0x69, 0x67, 0x6e, 0x6e, 0x65, +	0x73, 0x73, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, +	0x2d, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, +	0x64, 0x20, 0x73, 0x79, 0x6e, 0x61, 0x70, 0x74, +	0x65, 0x6e, 0x65, 0x20, 0x68, 0x6f, 0x6c, 0x6f, +	0x6d, 0x6f, 0x72, 0x70, 0x68, 0x20, 0x6d, 0x6f, +	0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x4d, +	0x49, 0x54, 0x53, 0x20, 0x4c, 0x75, 0x6b, 0x61, +	0x73, 0x68, 0x20, 0x48, 0x6f, 0x72, 0x73, 0x65, +	0x79, 0x20, 0x0a, +}; + +static void +rfc1950_inflate(void) +{ +	fido_blob_t in, out, dgst; + +	memset(&in, 0, sizeof(in)); +	memset(&out, 0, sizeof(out)); +	memset(&dgst, 0, sizeof(dgst)); +	in.ptr = rfc1950_blob; +	in.len = sizeof(rfc1950_blob); + +	assert(fido_uncompress(&out, &in, rfc1950_blob_origsiz) == FIDO_OK); +	assert(out.len == rfc1950_blob_origsiz); +	assert(fido_sha256(&dgst, out.ptr, out.len) == 0); +	assert(dgst.len == sizeof(rfc1950_blob_hash)); +	assert(memcmp(rfc1950_blob_hash, dgst.ptr, dgst.len) == 0); + +	free(out.ptr); +	free(dgst.ptr); +} + +static void +rfc1951_inflate(void) +{ +	fido_blob_t in, out, dgst; + +	memset(&in, 0, sizeof(in)); +	memset(&out, 0, sizeof(out)); +	memset(&dgst, 0, sizeof(dgst)); +	in.ptr = rfc1950_blob + 2; /*  trim header */ +	in.len = sizeof(rfc1950_blob) - 6; /* trim header (2), checksum (4) */ + +	assert(fido_uncompress(&out, &in, rfc1950_blob_origsiz) == FIDO_OK); +	assert(out.len == rfc1950_blob_origsiz); +	assert(fido_sha256(&dgst, out.ptr, out.len) == 0); +	assert(dgst.len == sizeof(rfc1950_blob_hash)); +	assert(memcmp(rfc1950_blob_hash, dgst.ptr, dgst.len) == 0); + +	free(out.ptr); +	free(dgst.ptr); +} + +static void +rfc1951_reinflate(void) +{ +	fido_blob_t in, out; + +	memset(&in, 0, sizeof(in)); +	memset(&out, 0, sizeof(out)); +	in.ptr = random_words; +	in.len = sizeof(random_words); + +	assert(fido_compress(&out, &in) == FIDO_OK); + +	in.ptr = out.ptr; +	in.len = out.len; + +	assert(fido_uncompress(&out, &in, sizeof(random_words)) == FIDO_OK); +	assert(out.len == sizeof(random_words)); +	assert(memcmp(out.ptr, random_words, out.len) == 0); + +	free(in.ptr); +	free(out.ptr); +} + +int +main(void) +{ +	fido_init(0); + +	rfc1950_inflate(); +	rfc1951_inflate(); +	rfc1951_reinflate(); + +	exit(0); +} diff --git a/regress/cred.c b/regress/cred.c index 07a2ca0c0237..c62ff8e4dcb4 100644 --- a/regress/cred.c +++ b/regress/cred.c @@ -4,12 +4,16 @@   * license that can be found in the LICENSE file.   */ +#undef NDEBUG +  #include <assert.h> -#include <cbor.h> -#include <fido.h>  #include <string.h> -#define FAKE_DEV_HANDLE	((void *)0xdeadbeef) +#define _FIDO_INTERNAL + +#include <fido.h> + +static int fake_dev_handle;  static const unsigned char cdh[32] = {  	0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb, @@ -1384,13 +1388,13 @@ dummy_open(const char *path)  {  	(void)path; -	return (FAKE_DEV_HANDLE); +	return (&fake_dev_handle);  }  static void  dummy_close(void *handle)  { -	assert(handle == FAKE_DEV_HANDLE); +	assert(handle == &fake_dev_handle);  }  static int diff --git a/regress/dev.c b/regress/dev.c index a5dc8d6e4529..92031e17066c 100644 --- a/regress/dev.c +++ b/regress/dev.c @@ -1,38 +1,57 @@  /* - * Copyright (c) 2019-2021 Yubico AB. All rights reserved. + * Copyright (c) 2019-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ +#undef NDEBUG +  #include <assert.h> -#include <err.h> -#include <fido.h>  #include <string.h>  #include <time.h> +#define _FIDO_INTERNAL + +#include <fido.h> +  #include "../fuzz/wiredata_fido2.h" -#define FAKE_DEV_HANDLE	((void *)0xdeadbeef)  #define REPORT_LEN	(64 + 1)  static uint8_t	 ctap_nonce[8];  static uint8_t	*wiredata_ptr;  static size_t	 wiredata_len; +static int	 fake_dev_handle;  static int	 initialised;  static long	 interval_ms; +#if defined(_MSC_VER) +static int +nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ +	if (rmtp != NULL) { +		errno = EINVAL; +		return (-1); +	} + +	Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000)); + +	return (0); +} +#endif +  static void *  dummy_open(const char *path)  {  	(void)path; -	return (FAKE_DEV_HANDLE); +	return (&fake_dev_handle);  }  static void  dummy_close(void *handle)  { -	assert(handle == FAKE_DEV_HANDLE); +	assert(handle == &fake_dev_handle);  }  static int @@ -42,7 +61,7 @@ dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)  	size_t		n;  	long		d; -	assert(handle == FAKE_DEV_HANDLE); +	assert(handle == &fake_dev_handle);  	assert(ptr != NULL);  	assert(len == REPORT_LEN - 1); @@ -87,7 +106,7 @@ dummy_write(void *handle, const unsigned char *ptr, size_t len)  {  	struct timespec tv; -	assert(handle == FAKE_DEV_HANDLE); +	assert(handle == &fake_dev_handle);  	assert(ptr != NULL);  	assert(len == REPORT_LEN); @@ -113,7 +132,14 @@ wiredata_setup(const uint8_t *data, size_t len)  	assert(SIZE_MAX - len > sizeof(ctap_init_data));  	assert((wiredata_ptr = malloc(sizeof(ctap_init_data) + len)) != NULL); +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:6386) +#endif  	memcpy(wiredata_ptr, ctap_init_data, sizeof(ctap_init_data)); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif  	if (len)  		memcpy(wiredata_ptr + sizeof(ctap_init_data), data, len); diff --git a/regress/eddsa.c b/regress/eddsa.c new file mode 100644 index 000000000000..42236ea58adf --- /dev/null +++ b/regress/eddsa.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#undef NDEBUG + +#include <assert.h> +#include <string.h> + +#define _FIDO_INTERNAL + +#include <fido.h> +#include <fido/eddsa.h> + +#include <openssl/bio.h> +#include <openssl/pem.h> + +#define ASSERT_NOT_NULL(e)	assert((e) != NULL) +#define ASSERT_NULL(e)		assert((e) == NULL) +#define ASSERT_INVAL(e)		assert((e) == FIDO_ERR_INVALID_ARGUMENT) +#define ASSERT_OK(e)		assert((e) == FIDO_OK) + +static const char ecdsa[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOwiq14c80b7C1Jzsx5w1zMvk2GgW\n" +"5kfGMOKXjwF/U+51ZfBDKehs3ivdeXAJBkxIh7E3iA32s+HyNqk+ntl9fg==\n" +"-----END PUBLIC KEY-----\n"; + +static const char eddsa[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MCowBQYDK2VwAyEADt/RHErAxAHxH9FUmsjOhQ2ALl6Y8nE0m3zQxkEE2iM=\n" +"-----END PUBLIC KEY-----\n"; + +static const unsigned char eddsa_raw[] = { +	0x0e, 0xdf, 0xd1, 0x1c, 0x4a, 0xc0, 0xc4, 0x01, +	0xf1, 0x1f, 0xd1, 0x54, 0x9a, 0xc8, 0xce, 0x85, +	0x0d, 0x80, 0x2e, 0x5e, 0x98, 0xf2, 0x71, 0x34, +	0x9b, 0x7c, 0xd0, 0xc6, 0x41, 0x04, 0xda, 0x23, +}; + +static EVP_PKEY * +EVP_PKEY_from_PEM(const char *ptr, size_t len) +{ +	BIO *bio = NULL; +	EVP_PKEY *pkey = NULL; + +	if ((bio = BIO_new(BIO_s_mem())) == NULL) { +		warnx("BIO_new"); +		goto out; +	} +	if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) { +		warnx("BIO_write"); +		goto out; +	} +	if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) +		warnx("PEM_read_bio_PUBKEY"); +out: +	BIO_free(bio); + +	return pkey; +} + +static int +eddsa_pk_cmp(const char *ptr, size_t len) +{ +	EVP_PKEY *pkA = NULL; +	EVP_PKEY *pkB = NULL; +	eddsa_pk_t *k = NULL; +	int r, ok = -1; + +	if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) { +		warnx("EVP_PKEY_from_PEM"); +		goto out; +	} +	if ((k = eddsa_pk_new()) == NULL) { +		warnx("eddsa_pk_new"); +		goto out; +	} +	if ((r = eddsa_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) { +		warnx("eddsa_pk_from_EVP_PKEY: 0x%x", r); +		goto out; +	} +	if ((pkB = eddsa_pk_to_EVP_PKEY(k)) == NULL) { +		warnx("eddsa_pk_to_EVP_PKEY"); +		goto out; +	} +	if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) { +		warnx("EVP_PKEY_cmp: %d", r); +		goto out; +	} + +	ok = 0; +out: +	EVP_PKEY_free(pkA); +	EVP_PKEY_free(pkB); +	eddsa_pk_free(&k); + +	return ok; +} + +static void +invalid_key(void) +{ +	EVP_PKEY *pkey; +	eddsa_pk_t *pk; + +	ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(ecdsa, sizeof(ecdsa)))); +	ASSERT_NOT_NULL((pk = eddsa_pk_new())); +	ASSERT_INVAL(eddsa_pk_from_EVP_PKEY(pk, pkey)); + +	EVP_PKEY_free(pkey); +	eddsa_pk_free(&pk); +} + +static void +valid_key(void) +{ +	EVP_PKEY *pkeyA = NULL; +	EVP_PKEY *pkeyB = NULL; +	eddsa_pk_t *pkA = NULL; +	eddsa_pk_t *pkB = NULL; + +#if defined(LIBRESSL_VERSION_NUMBER) +	/* incomplete support; test what we can */ +	ASSERT_NULL(EVP_PKEY_from_PEM(eddsa, sizeof(eddsa))); +	ASSERT_NOT_NULL((pkB = eddsa_pk_new())); +	ASSERT_INVAL(eddsa_pk_from_ptr(pkB, eddsa_raw, sizeof(eddsa_raw))); +	ASSERT_NULL(eddsa_pk_to_EVP_PKEY((const eddsa_pk_t *)eddsa_raw)); +	assert(eddsa_pk_cmp(eddsa, sizeof(eddsa)) < 0); +#else +	ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(eddsa, sizeof(eddsa)))); +	ASSERT_NOT_NULL((pkA = eddsa_pk_new())); +	ASSERT_NOT_NULL((pkB = eddsa_pk_new())); +	ASSERT_OK(eddsa_pk_from_EVP_PKEY(pkA, pkeyA)); +	ASSERT_OK(eddsa_pk_from_ptr(pkB, eddsa_raw, sizeof(eddsa_raw))); +	ASSERT_NOT_NULL((pkeyB = eddsa_pk_to_EVP_PKEY((const eddsa_pk_t *)eddsa_raw))); +	assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1); +	assert(eddsa_pk_cmp(eddsa, sizeof(eddsa)) == 0); +#endif + +	EVP_PKEY_free(pkeyA); +	EVP_PKEY_free(pkeyB); +	eddsa_pk_free(&pkA); +	eddsa_pk_free(&pkB); +} + +int +main(void) +{ +	fido_init(0); + +	invalid_key(); +	valid_key(); + +	exit(0); +} diff --git a/regress/es256.c b/regress/es256.c new file mode 100644 index 000000000000..17ef27fd4c98 --- /dev/null +++ b/regress/es256.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#undef NDEBUG + +#include <assert.h> +#include <string.h> + +#define _FIDO_INTERNAL + +#include <fido.h> +#include <fido/es256.h> + +#include <openssl/bio.h> +#include <openssl/pem.h> + +#define ASSERT_NOT_NULL(e)	assert((e) != NULL) +#define ASSERT_NULL(e)		assert((e) == NULL) +#define ASSERT_INVAL(e)		assert((e) == FIDO_ERR_INVALID_ARGUMENT) +#define ASSERT_OK(e)		assert((e) == FIDO_OK) + +static const char short_x[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAAeeHTZj4LEbt7Czs+u5gEZJfnGE\n" +"6Z+YLe4AYu7SoGY7IH/2jKifsA7w+lkURL4DL63oEjd3f8foH9bX4eaVug==\n" +"-----END PUBLIC KEY-----"; + +static const char short_y[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL8CWUP1r0tpJ5QmkzLc69O74C/Ti\n" +"83hTiys/JFNVkp0ArW3pKt5jNRrgWSZYE4S/D3AMtpqifFXz/FLCzJqojQ==\n" +"-----END PUBLIC KEY-----\n"; + +static const char p256k1[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEU1y8c0Jg9FGr3vYChpEo9c4dpkijriYM\n" +"QzU/DeskC89hZjLNH1Sj8ra2MsBlVGGJTNPCZSyx8Jo7ERapxdN7UQ==\n" +"-----END PUBLIC KEY-----\n"; + +static const char p256v1[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOwiq14c80b7C1Jzsx5w1zMvk2GgW\n" +"5kfGMOKXjwF/U+51ZfBDKehs3ivdeXAJBkxIh7E3iA32s+HyNqk+ntl9fg==\n" +"-----END PUBLIC KEY-----\n"; + +static const unsigned char p256k1_raw[] = { +	0x04, 0x53, 0x5c, 0xbc, 0x73, 0x42, 0x60, 0xf4, +	0x51, 0xab, 0xde, 0xf6, 0x02, 0x86, 0x91, 0x28, +	0xf5, 0xce, 0x1d, 0xa6, 0x48, 0xa3, 0xae, 0x26, +	0x0c, 0x43, 0x35, 0x3f, 0x0d, 0xeb, 0x24, 0x0b, +	0xcf, 0x61, 0x66, 0x32, 0xcd, 0x1f, 0x54, 0xa3, +	0xf2, 0xb6, 0xb6, 0x32, 0xc0, 0x65, 0x54, 0x61, +	0x89, 0x4c, 0xd3, 0xc2, 0x65, 0x2c, 0xb1, 0xf0, +	0x9a, 0x3b, 0x11, 0x16, 0xa9, 0xc5, 0xd3, 0x7b, +	0x51, +}; + +static const unsigned char p256v1_raw[] = { +	0x04, 0x3b, 0x08, 0xaa, 0xd7, 0x87, 0x3c, 0xd1, +	0xbe, 0xc2, 0xd4, 0x9c, 0xec, 0xc7, 0x9c, 0x35, +	0xcc, 0xcb, 0xe4, 0xd8, 0x68, 0x16, 0xe6, 0x47, +	0xc6, 0x30, 0xe2, 0x97, 0x8f, 0x01, 0x7f, 0x53, +	0xee, 0x75, 0x65, 0xf0, 0x43, 0x29, 0xe8, 0x6c, +	0xde, 0x2b, 0xdd, 0x79, 0x70, 0x09, 0x06, 0x4c, +	0x48, 0x87, 0xb1, 0x37, 0x88, 0x0d, 0xf6, 0xb3, +	0xe1, 0xf2, 0x36, 0xa9, 0x3e, 0x9e, 0xd9, 0x7d, +	0x7e, +}; + +static EVP_PKEY * +EVP_PKEY_from_PEM(const char *ptr, size_t len) +{ +	BIO *bio = NULL; +	EVP_PKEY *pkey = NULL; + +	if ((bio = BIO_new(BIO_s_mem())) == NULL) { +		warnx("BIO_new"); +		goto out; +	} +	if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) { +		warnx("BIO_write"); +		goto out; +	} +	if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) +		warnx("PEM_read_bio_PUBKEY"); +out: +	BIO_free(bio); + +	return pkey; +} + +static int +es256_pk_cmp(const char *ptr, size_t len) +{ +	EVP_PKEY *pkA = NULL; +	EVP_PKEY *pkB = NULL; +	es256_pk_t *k = NULL; +	int r, ok = -1; + +	if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) { +		warnx("EVP_PKEY_from_PEM"); +		goto out; +	} +	if ((k = es256_pk_new()) == NULL) { +		warnx("es256_pk_new"); +		goto out; +	} +	if ((r = es256_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) { +		warnx("es256_pk_from_EVP_PKEY: 0x%x", r); +		goto out; +	} +	if ((pkB = es256_pk_to_EVP_PKEY(k)) == NULL) { +		warnx("es256_pk_to_EVP_PKEY"); +		goto out; +	} +	if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) { +		warnx("EVP_PKEY_cmp: %d", r); +		goto out; +	} + +	ok = 0; +out: +	EVP_PKEY_free(pkA); +	EVP_PKEY_free(pkB); +	es256_pk_free(&k); + +	return ok; +} + +static void +short_coord(void) +{ +	assert(es256_pk_cmp(short_x, sizeof(short_x)) == 0); +	assert(es256_pk_cmp(short_y, sizeof(short_y)) == 0); +} + +static void +invalid_curve(const unsigned char *raw, size_t raw_len) +{ +	EVP_PKEY *pkey; +	es256_pk_t *pk; + +	ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(p256k1, sizeof(p256k1)))); +	ASSERT_NOT_NULL((pk = es256_pk_new())); +	ASSERT_INVAL(es256_pk_from_EVP_PKEY(pk, pkey)); +	ASSERT_INVAL(es256_pk_from_ptr(pk, raw, raw_len)); +	ASSERT_NULL(es256_pk_to_EVP_PKEY((const es256_pk_t *)raw)); + +	EVP_PKEY_free(pkey); +	es256_pk_free(&pk); +} + +static void +full_coord(void) +{ +	assert(es256_pk_cmp(p256v1, sizeof(p256v1)) == 0); +} + +static void +valid_curve(const unsigned char *raw, size_t raw_len) +{ +	EVP_PKEY *pkeyA; +	EVP_PKEY *pkeyB; +	es256_pk_t *pkA; +	es256_pk_t *pkB; + +	ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(p256v1, sizeof(p256v1)))); +	ASSERT_NOT_NULL((pkA = es256_pk_new())); +	ASSERT_NOT_NULL((pkB = es256_pk_new())); +	ASSERT_OK(es256_pk_from_EVP_PKEY(pkA, pkeyA)); +	ASSERT_OK(es256_pk_from_ptr(pkB, raw, raw_len)); +	ASSERT_NOT_NULL((pkeyB = es256_pk_to_EVP_PKEY(pkB))); +	assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1); + +	EVP_PKEY_free(pkeyA); +	EVP_PKEY_free(pkeyB); +	es256_pk_free(&pkA); +	es256_pk_free(&pkB); +} + +int +main(void) +{ +	fido_init(0); + +	short_coord(); +	full_coord(); + +	invalid_curve(p256k1_raw, sizeof(p256k1_raw)); /* uncompressed */ +	invalid_curve(p256k1_raw + 1, sizeof(p256k1_raw) - 1); /* libfido2 */ +	valid_curve(p256v1_raw, sizeof(p256v1_raw)); /* uncompressed */ +	valid_curve(p256v1_raw + 1, sizeof(p256v1_raw) - 1); /* libfido2 */ + +	exit(0); +} diff --git a/regress/rs256.c b/regress/rs256.c new file mode 100644 index 000000000000..f6e685a11da8 --- /dev/null +++ b/regress/rs256.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#undef NDEBUG + +#include <assert.h> +#include <string.h> + +#define _FIDO_INTERNAL + +#include <fido.h> +#include <fido/rs256.h> + +#include <openssl/bio.h> +#include <openssl/pem.h> + +#define ASSERT_NOT_NULL(e)	assert((e) != NULL) +#define ASSERT_NULL(e)		assert((e) == NULL) +#define ASSERT_INVAL(e)		assert((e) == FIDO_ERR_INVALID_ARGUMENT) +#define ASSERT_OK(e)		assert((e) == FIDO_OK) + +static char rsa1024[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw92gn9Ku/bEfFj1AutaZyltpf\n" +"zzXrg70kQFymNq+spMt/HlxKiImw8TZU08zWW4ZLE/Ch4JYjMW6ETAdQFhSC63Ih\n" +"Wecui0JJ1f+2CsUVg+h7lO1877LZYUpdNiJrbqMb5Yc4N3FPtvdl3NoLIIQsF76H\n" +"VRvpjQgkWipRfZ97JQIDAQAB\n" +"-----END PUBLIC KEY-----"; + +static char rsa2048[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApvIq/55ZodBIxzo/8BnE\n" +"UQN1fo1hmJ6V20hQHSzJq5tHyxRCcvKikuJ1ZvR4RdZlEzdTdbEfMBdZ8sxve0/U\n" +"yYEjH92CG0vgTCYuUaFLJTaWZSvWa96G8Lw+V4VyNFDRCM7sflOaSVH5pAsz8OEc\n" +"TLZfM4NhnDsJAM+mQ6X7Tza0sczPchgDA+9KByXo/VIqyuBQs17rlKC2reMa8NkY\n" +"rBRQZJLNzi68d5/BHH1flGWE1l8wJ9dr1Ex93H/KdzX+7/28TWUC98nneUo8RfRx\n" +"FwUt/EInDMHOORCaCHSs28U/9IUyMjqLB1rxKhIp09yGXMiTrrT+p+Pcn8dO01HT\n" +"vQIDAQAB\n" +"-----END PUBLIC KEY-----"; + +static char rsa3072[] = \ +"-----BEGIN PUBLIC KEY-----\n" +"MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwZunKrMs/o92AniLPNTF\n" +"Ta4EYfhy5NDmMvQvRFT/eTYItLrOTPmYMap68KLyZYmgz/AdaxAL/992QWre7XTY\n" +"gqLwtZT+WsSu7xPHWKTTXrlVohKBeLHQ0I7Zy0NSMUxhlJEMrBAjSyFAS86zWm5w\n" +"ctC3pNCqfUKugA07BVj+d5Mv5fziwgMR86kuhkVuMYfsR4IYwX4+va0pyLzxx624\n" +"s9nJ107g+A+3MUk4bAto3lruFeeZPUI2AFzFQbGg5By6VtvVi3gKQ7lUNtAr0Onu\n" +"I6Fb+yz8sbFcvDpJcu5CXW20GrKMVP4KY5pn2LCajWuZjBl/dXWayPfm4UX5Y2O4\n" +"73tzPpUBNwnEdz79His0v80Vmvjwn5IuF2jAoimrBNPJFFwCCuVNy8kgj2vllk1l\n" +"RvLOG6hf8VnlDb40QZS3QAQ09xFfF+xlVLb8cHH6wllaAGEM230TrmawpC7xpz4Z\n" +"sTuwJwI0AWEi//noMsRz2BuF2fCp//aORYJQU2S8kYk3AgMBAAE=\n" +"-----END PUBLIC KEY-----"; + +static const unsigned char rsa2048_raw[] = { +	0xa6, 0xf2, 0x2a, 0xff, 0x9e, 0x59, 0xa1, 0xd0, +	0x48, 0xc7, 0x3a, 0x3f, 0xf0, 0x19, 0xc4, 0x51, +	0x03, 0x75, 0x7e, 0x8d, 0x61, 0x98, 0x9e, 0x95, +	0xdb, 0x48, 0x50, 0x1d, 0x2c, 0xc9, 0xab, 0x9b, +	0x47, 0xcb, 0x14, 0x42, 0x72, 0xf2, 0xa2, 0x92, +	0xe2, 0x75, 0x66, 0xf4, 0x78, 0x45, 0xd6, 0x65, +	0x13, 0x37, 0x53, 0x75, 0xb1, 0x1f, 0x30, 0x17, +	0x59, 0xf2, 0xcc, 0x6f, 0x7b, 0x4f, 0xd4, 0xc9, +	0x81, 0x23, 0x1f, 0xdd, 0x82, 0x1b, 0x4b, 0xe0, +	0x4c, 0x26, 0x2e, 0x51, 0xa1, 0x4b, 0x25, 0x36, +	0x96, 0x65, 0x2b, 0xd6, 0x6b, 0xde, 0x86, 0xf0, +	0xbc, 0x3e, 0x57, 0x85, 0x72, 0x34, 0x50, 0xd1, +	0x08, 0xce, 0xec, 0x7e, 0x53, 0x9a, 0x49, 0x51, +	0xf9, 0xa4, 0x0b, 0x33, 0xf0, 0xe1, 0x1c, 0x4c, +	0xb6, 0x5f, 0x33, 0x83, 0x61, 0x9c, 0x3b, 0x09, +	0x00, 0xcf, 0xa6, 0x43, 0xa5, 0xfb, 0x4f, 0x36, +	0xb4, 0xb1, 0xcc, 0xcf, 0x72, 0x18, 0x03, 0x03, +	0xef, 0x4a, 0x07, 0x25, 0xe8, 0xfd, 0x52, 0x2a, +	0xca, 0xe0, 0x50, 0xb3, 0x5e, 0xeb, 0x94, 0xa0, +	0xb6, 0xad, 0xe3, 0x1a, 0xf0, 0xd9, 0x18, 0xac, +	0x14, 0x50, 0x64, 0x92, 0xcd, 0xce, 0x2e, 0xbc, +	0x77, 0x9f, 0xc1, 0x1c, 0x7d, 0x5f, 0x94, 0x65, +	0x84, 0xd6, 0x5f, 0x30, 0x27, 0xd7, 0x6b, 0xd4, +	0x4c, 0x7d, 0xdc, 0x7f, 0xca, 0x77, 0x35, 0xfe, +	0xef, 0xfd, 0xbc, 0x4d, 0x65, 0x02, 0xf7, 0xc9, +	0xe7, 0x79, 0x4a, 0x3c, 0x45, 0xf4, 0x71, 0x17, +	0x05, 0x2d, 0xfc, 0x42, 0x27, 0x0c, 0xc1, 0xce, +	0x39, 0x10, 0x9a, 0x08, 0x74, 0xac, 0xdb, 0xc5, +	0x3f, 0xf4, 0x85, 0x32, 0x32, 0x3a, 0x8b, 0x07, +	0x5a, 0xf1, 0x2a, 0x12, 0x29, 0xd3, 0xdc, 0x86, +	0x5c, 0xc8, 0x93, 0xae, 0xb4, 0xfe, 0xa7, 0xe3, +	0xdc, 0x9f, 0xc7, 0x4e, 0xd3, 0x51, 0xd3, 0xbd, +	0x01, 0x00, 0x01, +}; + +static EVP_PKEY * +EVP_PKEY_from_PEM(const char *ptr, size_t len) +{ +	BIO *bio = NULL; +	EVP_PKEY *pkey = NULL; + +	if ((bio = BIO_new(BIO_s_mem())) == NULL) { +		warnx("BIO_new"); +		goto out; +	} +	if (len > INT_MAX || BIO_write(bio, ptr, (int)len) != (int)len) { +		warnx("BIO_write"); +		goto out; +	} +	if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) +		warnx("PEM_read_bio_PUBKEY"); +out: +	BIO_free(bio); + +	return pkey; +} + +static int +rs256_pk_cmp(const char *ptr, size_t len) +{ +	EVP_PKEY *pkA = NULL; +	EVP_PKEY *pkB = NULL; +	rs256_pk_t *k = NULL; +	int r, ok = -1; + +	if ((pkA = EVP_PKEY_from_PEM(ptr, len)) == NULL) { +		warnx("EVP_PKEY_from_PEM"); +		goto out; +	} +	if ((k = rs256_pk_new()) == NULL) { +		warnx("rs256_pk_new"); +		goto out; +	} +	if ((r = rs256_pk_from_EVP_PKEY(k, pkA)) != FIDO_OK) { +		warnx("rs256_pk_from_EVP_PKEY: 0x%x", r); +		goto out; +	} +	if ((pkB = rs256_pk_to_EVP_PKEY(k)) == NULL) { +		warnx("rs256_pk_to_EVP_PKEY"); +		goto out; +	} +	if ((r = EVP_PKEY_cmp(pkA, pkB)) != 1) { +		warnx("EVP_PKEY_cmp: %d", r); +		goto out; +	} + +	ok = 0; +out: +	EVP_PKEY_free(pkA); +	EVP_PKEY_free(pkB); +	rs256_pk_free(&k); + +	return ok; +} + +static void +invalid_size(const char *pem) +{ +	EVP_PKEY *pkey; +	rs256_pk_t *pk; + +	ASSERT_NOT_NULL((pkey = EVP_PKEY_from_PEM(pem, strlen(pem)))); +	ASSERT_NOT_NULL((pk = rs256_pk_new())); +	ASSERT_INVAL(rs256_pk_from_EVP_PKEY(pk, pkey)); + +	EVP_PKEY_free(pkey); +	rs256_pk_free(&pk); +} + +static void +valid_size(const char *pem, const unsigned char *raw, size_t raw_len) +{ +	EVP_PKEY *pkeyA; +	EVP_PKEY *pkeyB; +	rs256_pk_t *pkA; +	rs256_pk_t *pkB; + +	ASSERT_NOT_NULL((pkeyA = EVP_PKEY_from_PEM(pem, strlen(pem)))); +	ASSERT_NOT_NULL((pkA = rs256_pk_new())); +	ASSERT_NOT_NULL((pkB = rs256_pk_new())); +	ASSERT_OK(rs256_pk_from_EVP_PKEY(pkA, pkeyA)); +	ASSERT_OK(rs256_pk_from_ptr(pkB, raw, raw_len)); +	ASSERT_NOT_NULL((pkeyB = rs256_pk_to_EVP_PKEY(pkB))); +	assert(EVP_PKEY_cmp(pkeyA, pkeyB) == 1); +	assert(rs256_pk_cmp(pem, strlen(pem)) == 0); + +	EVP_PKEY_free(pkeyA); +	EVP_PKEY_free(pkeyB); +	rs256_pk_free(&pkA); +	rs256_pk_free(&pkB); +} + +int +main(void) +{ +	fido_init(0); + +	invalid_size(rsa1024);  +	invalid_size(rsa3072);  +	valid_size(rsa2048, rsa2048_raw, sizeof(rsa2048_raw)); + +	exit(0); +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 796ec69a9dbe..44a87282869e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,20 +33,28 @@ list(APPEND FIDO_SOURCES  	rs1.c  	rs256.c  	time.c +	touch.c  	tpm.c  	types.c  	u2f.c +	util.c  )  if(FUZZ)  	list(APPEND FIDO_SOURCES ../fuzz/clock.c) +	list(APPEND FIDO_SOURCES ../fuzz/pcsc.c)  	list(APPEND FIDO_SOURCES ../fuzz/prng.c) -	list(APPEND FIDO_SOURCES ../fuzz/uniform_random.c)  	list(APPEND FIDO_SOURCES ../fuzz/udev.c) +	list(APPEND FIDO_SOURCES ../fuzz/uniform_random.c)  	list(APPEND FIDO_SOURCES ../fuzz/wrap.c)  endif() +  if(NFC_LINUX) -	list(APPEND FIDO_SOURCES netlink.c nfc_linux.c) +	list(APPEND FIDO_SOURCES netlink.c nfc.c nfc_linux.c) +endif() + +if(USE_PCSC) +	list(APPEND FIDO_SOURCES nfc.c pcsc.c)  endif()  if(USE_HIDAPI) @@ -93,8 +101,15 @@ list(APPEND COMPAT_SOURCES  if(WIN32)  	list(APPEND BASE_LIBRARIES wsock32 ws2_32 bcrypt setupapi hid) +	if(USE_PCSC) +		list(APPEND BASE_LIBRARIES winscard) +	endif()  elseif(APPLE) -	list(APPEND BASE_LIBRARIES "-framework CoreFoundation" "-framework IOKit") +	list(APPEND BASE_LIBRARIES "-framework CoreFoundation" +	    "-framework IOKit") +	if(USE_PCSC) +		list(APPEND BASE_LIBRARIES "-framework PCSC") +	endif()  endif()  list(APPEND TARGET_LIBRARIES @@ -104,6 +119,7 @@ list(APPEND TARGET_LIBRARIES  	${BASE_LIBRARIES}  	${HIDAPI_LIBRARIES}  	${ZLIB_LIBRARIES} +	${PCSC_LIBRARIES}  )  # static library diff --git a/src/compress.c b/src/compress.c index ee5501b4a4a1..074bca876489 100644 --- a/src/compress.c +++ b/src/compress.c @@ -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 --git a/src/dev.c b/src/dev.c index fb8faba0a06c..635e41714759 100644 --- a/src/dev.c +++ b/src/dev.c @@ -1,37 +1,17 @@  /* - * Copyright (c) 2018 Yubico AB. All rights reserved. + * Copyright (c) 2018-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ -#include <openssl/sha.h>  #include "fido.h"  #ifndef TLS  #define TLS  #endif -typedef struct dev_manifest_func_node { -	dev_manifest_func_t manifest_func; -	struct dev_manifest_func_node *next; -} dev_manifest_func_node_t; - -static TLS dev_manifest_func_node_t *manifest_funcs = NULL;  static TLS bool disable_u2f_fallback; -static void -find_manifest_func_node(dev_manifest_func_t f, dev_manifest_func_node_t **curr, -    dev_manifest_func_node_t **prev) -{ -	*prev = NULL; -	*curr = manifest_funcs; - -	while (*curr != NULL && (*curr)->manifest_func != f) { -		*prev = *curr; -		*curr = (*curr)->next; -	} -} -  #ifdef FIDO_FUZZ  static void  set_random_report_len(fido_dev_t *dev) @@ -63,13 +43,15 @@ fido_dev_set_option_flags(fido_dev_t *dev, const fido_cbor_info_t *info)  	for (size_t i = 0; i < len; i++)  		if (strcmp(ptr[i], "clientPin") == 0) { -			dev->flags |= val[i] ? FIDO_DEV_PIN_SET : FIDO_DEV_PIN_UNSET; +			dev->flags |= val[i] ? +			    FIDO_DEV_PIN_SET : FIDO_DEV_PIN_UNSET;  		} else if (strcmp(ptr[i], "credMgmt") == 0 ||  			   strcmp(ptr[i], "credentialMgmtPreview") == 0) {  			if (val[i])  				dev->flags |= FIDO_DEV_CREDMAN;  		} else if (strcmp(ptr[i], "uv") == 0) { -			dev->flags |= val[i] ? FIDO_DEV_UV_SET : FIDO_DEV_UV_UNSET; +			dev->flags |= val[i] ? +			    FIDO_DEV_UV_SET : FIDO_DEV_UV_UNSET;  		} else if (strcmp(ptr[i], "pinUvAuthToken") == 0) {  			if (val[i])  				dev->flags |= FIDO_DEV_TOKEN_PERMS; @@ -257,75 +239,40 @@ fido_dev_open_wait(fido_dev_t *dev, const char *path, int *ms)  	return (FIDO_OK);  } -int -fido_dev_register_manifest_func(const dev_manifest_func_t f) -{ -	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 @@ fido_dev_open(fido_dev_t *dev, const char *path)  {  	int ms = dev->timeout_ms; -#ifdef NFC_LINUX -	if (strncmp(path, FIDO_NFC_PREFIX, strlen(FIDO_NFC_PREFIX)) == 0) { -		dev->io_own = true; -		dev->io = (fido_dev_io_t) { -			fido_nfc_open, -			fido_nfc_close, -			fido_nfc_read, -			fido_nfc_write, -		}; -		dev->transport = (fido_dev_transport_t) { -			fido_nfc_rx, -			fido_nfc_tx, -		}; +#ifdef USE_NFC +	if (fido_is_nfc(path) && fido_dev_set_nfc(dev) < 0) { +		fido_log_debug("%s: fido_dev_set_nfc", __func__); +		return FIDO_ERR_INTERNAL; +	} +#endif +#ifdef USE_PCSC +	if (fido_is_pcsc(path) && fido_dev_set_pcsc(dev) < 0) { +		fido_log_debug("%s: fido_dev_set_pcsc", __func__); +		return FIDO_ERR_INTERNAL;  	}  #endif @@ -387,7 +331,7 @@ fido_dev_set_sigmask(fido_dev_t *dev, const fido_sigset_t *sigmask)  	if (dev->io_handle == NULL || sigmask == NULL)  		return (FIDO_ERR_INVALID_ARGUMENT); -#ifdef NFC_LINUX +#ifdef USE_NFC  	if (dev->transport.rx == fido_nfc_rx && dev->io.read == fido_nfc_read)  		return (fido_nfc_set_sigmask(dev->io_handle, sigmask));  #endif @@ -415,106 +359,6 @@ fido_dev_cancel(fido_dev_t *dev)  }  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)  {  	if (dev->io_handle != NULL) { diff --git a/src/eddsa.c b/src/eddsa.c index a7b4f4f900ce..a94ae3023917 100644 --- a/src/eddsa.c +++ b/src/eddsa.c @@ -122,11 +122,20 @@ eddsa_pk_free(eddsa_pk_t **pkp)  int  eddsa_pk_from_ptr(eddsa_pk_t *pk, const void *ptr, size_t len)  { +	EVP_PKEY *pkey; +  	if (len < sizeof(*pk))  		return (FIDO_ERR_INVALID_ARGUMENT);  	memcpy(pk, ptr, sizeof(*pk)); +	if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) { +		fido_log_debug("%s: eddsa_pk_to_EVP_PKEY", __func__); +		return (FIDO_ERR_INVALID_ARGUMENT); +	} + +	EVP_PKEY_free(pkey); +  	return (FIDO_OK);  } @@ -147,6 +156,8 @@ eddsa_pk_from_EVP_PKEY(eddsa_pk_t *pk, const EVP_PKEY *pkey)  {  	size_t len = 0; +	if (EVP_PKEY_base_id(pkey) != EVP_PKEY_ED25519) +		return (FIDO_ERR_INVALID_ARGUMENT);  	if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1 ||  	    len != sizeof(pk->x))  		return (FIDO_ERR_INTERNAL); diff --git a/src/es256.c b/src/es256.c index eb4cc63525aa..4d6e86f8a26d 100644 --- a/src/es256.c +++ b/src/es256.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2018-2021 Yubico AB. All rights reserved. + * Copyright (c) 2018-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -11,6 +11,14 @@  #include "fido.h"  #include "fido/es256.h" +#if OPENSSL_VERSION_NUMBER >= 0x30000000 +#define get0_EC_KEY(x)	EVP_PKEY_get0_EC_KEY((x)) +#else +#define get0_EC_KEY(x)	EVP_PKEY_get0((x)) +#endif + +static const int es256_nid = NID_X9_62_prime256v1; +  static int  decode_coord(const cbor_item_t *item, void *xy, size_t xy_len)  { @@ -170,7 +178,8 @@ es256_pk_free(es256_pk_t **pkp)  int  es256_pk_from_ptr(es256_pk_t *pk, const void *ptr, size_t len)  { -	const uint8_t *p = ptr; +	const uint8_t	*p = ptr; +	EVP_PKEY	*pkey;  	if (len < sizeof(*pk))  		return (FIDO_ERR_INVALID_ARGUMENT); @@ -180,6 +189,14 @@ es256_pk_from_ptr(es256_pk_t *pk, const void *ptr, size_t len)  	else  		memcpy(pk, ptr, sizeof(*pk)); /* libfido2 x||y format */ +	if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL) { +		fido_log_debug("%s: es256_pk_to_EVP_PKEY", __func__); +		explicit_bzero(pk, sizeof(*pk)); +		return (FIDO_ERR_INVALID_ARGUMENT); +	} + +	EVP_PKEY_free(pkey); +  	return (FIDO_OK);  } @@ -208,13 +225,12 @@ es256_sk_create(es256_sk_t *key)  	EVP_PKEY	*k = NULL;  	const EC_KEY	*ec;  	const BIGNUM	*d; -	const int	 nid = NID_X9_62_prime256v1;  	int		 n;  	int		 ok = -1;  	if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL ||  	    EVP_PKEY_paramgen_init(pctx) <= 0 || -	    EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) <= 0 || +	    EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, es256_nid) <= 0 ||  	    EVP_PKEY_paramgen(pctx, &p) <= 0) {  		fido_log_debug("%s: EVP_PKEY_paramgen", __func__);  		goto fail; @@ -258,7 +274,6 @@ es256_pk_to_EVP_PKEY(const es256_pk_t *k)  	BIGNUM		*x = NULL;  	BIGNUM		*y = NULL;  	const EC_GROUP	*g = NULL; -	const int	 nid = NID_X9_62_prime256v1;  	int		 ok = -1;  	if ((bnctx = BN_CTX_new()) == NULL) @@ -276,7 +291,7 @@ es256_pk_to_EVP_PKEY(const es256_pk_t *k)  		goto fail;  	} -	if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL || +	if ((ec = EC_KEY_new_by_curve_name(es256_nid)) == NULL ||  	    (g = EC_KEY_get0_group(ec)) == NULL) {  		fido_log_debug("%s: EC_KEY init", __func__);  		goto fail; @@ -324,12 +339,15 @@ es256_pk_from_EC_KEY(es256_pk_t *pk, const EC_KEY *ec)  	BIGNUM		*x = NULL;  	BIGNUM		*y = NULL;  	const EC_POINT	*q = NULL; -	const EC_GROUP	*g = NULL; +	EC_GROUP	*g = NULL; +	size_t		 dx; +	size_t		 dy;  	int		 ok = FIDO_ERR_INTERNAL; -	int		 n; +	int		 nx; +	int		 ny;  	if ((q = EC_KEY_get0_public_key(ec)) == NULL || -	    (g = EC_KEY_get0_group(ec)) == NULL || +	    (g = EC_GROUP_new_by_curve_name(es256_nid)) == NULL ||  	    (bnctx = BN_CTX_new()) == NULL)  		goto fail; @@ -339,22 +357,33 @@ es256_pk_from_EC_KEY(es256_pk_t *pk, const EC_KEY *ec)  	    (y = BN_CTX_get(bnctx)) == NULL)  		goto fail; +	if (EC_POINT_is_on_curve(g, q, bnctx) != 1) { +		fido_log_debug("%s: EC_POINT_is_on_curve", __func__); +		ok = FIDO_ERR_INVALID_ARGUMENT; +		goto fail; +	} +  	if (EC_POINT_get_affine_coordinates_GFp(g, q, x, y, bnctx) == 0 || -	    (n = BN_num_bytes(x)) < 0 || (size_t)n > sizeof(pk->x) || -	    (n = BN_num_bytes(y)) < 0 || (size_t)n > sizeof(pk->y)) { +	    (nx = BN_num_bytes(x)) < 0 || (size_t)nx > sizeof(pk->x) || +	    (ny = BN_num_bytes(y)) < 0 || (size_t)ny > sizeof(pk->y)) {  		fido_log_debug("%s: EC_POINT_get_affine_coordinates_GFp",  		    __func__);  		goto fail;  	} -	if ((n = BN_bn2bin(x, pk->x)) < 0 || (size_t)n > sizeof(pk->x) || -	    (n = BN_bn2bin(y, pk->y)) < 0 || (size_t)n > sizeof(pk->y)) { +	dx = sizeof(pk->x) - (size_t)nx; +	dy = sizeof(pk->y) - (size_t)ny; + +	if ((nx = BN_bn2bin(x, pk->x + dx)) < 0 || (size_t)nx > sizeof(pk->x) || +	    (ny = BN_bn2bin(y, pk->y + dy)) < 0 || (size_t)ny > sizeof(pk->y)) {  		fido_log_debug("%s: BN_bn2bin", __func__);  		goto fail;  	}  	ok = FIDO_OK;  fail: +	EC_GROUP_free(g); +  	if (bnctx != NULL) {  		BN_CTX_end(bnctx);  		BN_CTX_free(bnctx); @@ -366,10 +395,10 @@ fail:  int  es256_pk_from_EVP_PKEY(es256_pk_t *pk, const EVP_PKEY *pkey)  { -	EC_KEY *ec; +	const EC_KEY *ec;  	if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC || -	    (ec = EVP_PKEY_get0(pkey)) == NULL) +	    (ec = get0_EC_KEY(pkey)) == NULL)  		return (FIDO_ERR_INVALID_ARGUMENT);  	return (es256_pk_from_EC_KEY(pk, ec)); @@ -382,7 +411,6 @@ es256_sk_to_EVP_PKEY(const es256_sk_t *k)  	EC_KEY		*ec = NULL;  	EVP_PKEY	*pkey = NULL;  	BIGNUM		*d = NULL; -	const int	 nid = NID_X9_62_prime256v1;  	int		 ok = -1;  	if ((bnctx = BN_CTX_new()) == NULL) @@ -396,7 +424,7 @@ es256_sk_to_EVP_PKEY(const es256_sk_t *k)  		goto fail;  	} -	if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL || +	if ((ec = EC_KEY_new_by_curve_name(es256_nid)) == NULL ||  	    EC_KEY_set_private_key(ec, d) == 0) {  		fido_log_debug("%s: EC_KEY_set_private_key", __func__);  		goto fail; @@ -435,11 +463,10 @@ es256_derive_pk(const es256_sk_t *sk, es256_pk_t *pk)  	EC_KEY		*ec = NULL;  	EC_POINT	*q = NULL;  	const EC_GROUP	*g = NULL; -	const int	 nid = NID_X9_62_prime256v1;  	int		 ok = -1;  	if ((d = BN_bin2bn(sk->d, (int)sizeof(sk->d), NULL)) == NULL || -	    (ec = EC_KEY_new_by_curve_name(nid)) == NULL || +	    (ec = EC_KEY_new_by_curve_name(es256_nid)) == NULL ||  	    (g = EC_KEY_get0_group(ec)) == NULL ||  	    (q = EC_POINT_new(g)) == NULL) {  		fido_log_debug("%s: get", __func__); diff --git a/src/export.gnu b/src/export.gnu index 0a8d46a20fad..8fc94af31c92 100644 --- a/src/export.gnu +++ b/src/export.gnu @@ -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 --git a/src/export.llvm b/src/export.llvm index 80507346edee..df9a667f7477 100644 --- a/src/export.llvm +++ b/src/export.llvm @@ -83,10 +83,11 @@ _fido_cbor_info_algorithm_type  _fido_cbor_info_extensions_len  _fido_cbor_info_extensions_ptr  _fido_cbor_info_free -_fido_cbor_info_maxmsgsiz  _fido_cbor_info_maxcredbloblen  _fido_cbor_info_maxcredcntlst  _fido_cbor_info_maxcredidlen +_fido_cbor_info_maxlargeblob +_fido_cbor_info_maxmsgsiz  _fido_cbor_info_fwversion  _fido_cbor_info_new  _fido_cbor_info_options_len diff --git a/src/export.msvc b/src/export.msvc index 14602164fd45..a9082152f5cc 100644 --- a/src/export.msvc +++ b/src/export.msvc @@ -84,10 +84,11 @@ fido_cbor_info_algorithm_type  fido_cbor_info_extensions_len  fido_cbor_info_extensions_ptr  fido_cbor_info_free -fido_cbor_info_maxmsgsiz  fido_cbor_info_maxcredbloblen  fido_cbor_info_maxcredcntlst  fido_cbor_info_maxcredidlen +fido_cbor_info_maxlargeblob +fido_cbor_info_maxmsgsiz  fido_cbor_info_fwversion  fido_cbor_info_new  fido_cbor_info_options_len diff --git a/src/extern.h b/src/extern.h index 6f86d7642950..84536d58b6f8 100644 --- a/src/extern.h +++ b/src/extern.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2018-2021 Yubico AB. All rights reserved. + * Copyright (c) 2018-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -118,6 +118,7 @@ size_t fido_hid_report_in_len(void *);  size_t fido_hid_report_out_len(void *);  /* nfc i/o */ +bool fido_is_nfc(const char *);  void *fido_nfc_open(const char *);  void  fido_nfc_close(void *);  int fido_nfc_read(void *, unsigned char *, size_t, int); @@ -125,6 +126,17 @@ int fido_nfc_write(void *, const unsigned char *, size_t);  int fido_nfc_rx(fido_dev_t *, uint8_t, unsigned char *, size_t, int);  int fido_nfc_tx(fido_dev_t *, uint8_t, const unsigned char *, size_t);  int fido_nfc_set_sigmask(void *, const fido_sigset_t *); +int fido_dev_set_nfc(fido_dev_t *); + +/* pcsc i/o */ +bool fido_is_pcsc(const char *); +void *fido_pcsc_open(const char *); +void  fido_pcsc_close(void *); +int fido_pcsc_read(void *, unsigned char *, size_t, int); +int fido_pcsc_write(void *, const unsigned char *, size_t); +int fido_pcsc_rx(fido_dev_t *, uint8_t, unsigned char *, size_t, int); +int fido_pcsc_tx(fido_dev_t *, uint8_t, const unsigned char *, size_t); +int fido_dev_set_pcsc(fido_dev_t *);  /* windows hello */  int fido_winhello_manifest(fido_dev_info_t *, size_t, size_t *); @@ -200,6 +212,7 @@ int fido_get_random(void *, size_t);  int fido_sha256(fido_blob_t *, const u_char *, size_t);  int fido_time_now(struct timespec *);  int fido_time_delta(const struct timespec *, int *); +int fido_to_uint64(const char *, int, uint64_t *);  /* crypto */  int es256_verify_sig(const fido_blob_t *, EVP_PKEY *, const fido_blob_t *); @@ -220,11 +233,7 @@ int fido_get_signed_hash_tpm(fido_blob_t *, const fido_blob_t *,  /* device manifest functions */  int fido_hid_manifest(fido_dev_info_t *, size_t, size_t *);  int fido_nfc_manifest(fido_dev_info_t *, size_t, size_t *); - -/* device manifest registration */ -typedef int (*dev_manifest_func_t)(fido_dev_info_t *, size_t, size_t *); -int fido_dev_register_manifest_func(const dev_manifest_func_t); -void fido_dev_unregister_manifest_func(const dev_manifest_func_t); +int fido_pcsc_manifest(fido_dev_info_t *, size_t, size_t *);  /* fuzzing instrumentation */  #ifdef FIDO_FUZZ @@ -250,6 +259,7 @@ uint32_t uniform_random(uint32_t);  #define FIDO_DUMMY_USER_ID	1  #define FIDO_WINHELLO_PATH	"windows://hello"  #define FIDO_NFC_PREFIX		"nfc:" +#define FIDO_PCSC_PREFIX	"pcsc:"  #ifdef __cplusplus  } /* extern "C" */ diff --git a/src/fido.h b/src/fido.h index 4bd2aeebfccb..63d6de87b5aa 100644 --- a/src/fido.h +++ b/src/fido.h @@ -144,7 +144,9 @@ int fido_cred_set_user(fido_cred_t *, const unsigned char *, size_t,  int fido_cred_set_x509(fido_cred_t *, const unsigned char *, size_t);  int fido_cred_verify(const fido_cred_t *);  int fido_cred_verify_self(const fido_cred_t *); +#ifdef _FIDO_SIGSET_DEFINED  int fido_dev_set_sigmask(fido_dev_t *, const fido_sigset_t *); +#endif  int fido_dev_cancel(fido_dev_t *);  int fido_dev_close(fido_dev_t *);  int fido_dev_get_assert(fido_dev_t *, fido_assert_t *, const char *); @@ -205,10 +207,11 @@ uint8_t  fido_dev_build(const fido_dev_t *);  uint8_t  fido_dev_flags(const fido_dev_t *);  int16_t  fido_dev_info_vendor(const fido_dev_info_t *);  int16_t  fido_dev_info_product(const fido_dev_info_t *); -uint64_t fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *);  uint64_t fido_cbor_info_maxcredbloblen(const fido_cbor_info_t *);  uint64_t fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *);  uint64_t fido_cbor_info_maxcredidlen(const fido_cbor_info_t *); +uint64_t fido_cbor_info_maxlargeblob(const fido_cbor_info_t *); +uint64_t fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *);  uint64_t fido_cbor_info_fwversion(const fido_cbor_info_t *);  bool fido_dev_has_pin(const fido_dev_t *); diff --git a/src/fido/types.h b/src/fido/types.h index 4a216b4b9786..593a6a6b4813 100644 --- a/src/fido/types.h +++ b/src/fido/types.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2018 Yubico AB. All rights reserved. + * Copyright (c) 2018-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -48,10 +48,14 @@ typedef enum {  typedef void fido_log_handler_t(const char *); +#undef  _FIDO_SIGSET_DEFINED +#define _FIDO_SIGSET_DEFINED  #ifdef _WIN32  typedef int fido_sigset_t; -#else +#elif defined(SIG_BLOCK)  typedef sigset_t fido_sigset_t; +#else +#undef _FIDO_SIGSET_DEFINED  #endif  #ifdef _FIDO_INTERNAL @@ -216,18 +220,19 @@ typedef struct fido_algo_array {  } fido_algo_array_t;  typedef struct fido_cbor_info { -	fido_str_array_t  versions;      /* supported versions: fido2|u2f */ -	fido_str_array_t  extensions;    /* list of supported extensions */ -	fido_str_array_t  transports;    /* list of supported transports */ -	unsigned char     aaguid[16];    /* aaguid */ -	fido_opt_array_t  options;       /* list of supported options */ -	uint64_t          maxmsgsiz;     /* maximum message size */ -	fido_byte_array_t protocols;     /* supported pin protocols */ -	fido_algo_array_t algorithms;    /* list of supported algorithms */ -	uint64_t          maxcredcntlst; /* max number of credentials in list */ -	uint64_t          maxcredidlen;  /* max credential ID length */ -	uint64_t          fwversion;     /* firmware version */ +	fido_str_array_t  versions;       /* supported versions: fido2|u2f */ +	fido_str_array_t  extensions;     /* list of supported extensions */ +	fido_str_array_t  transports;     /* list of supported transports */ +	unsigned char     aaguid[16];     /* aaguid */ +	fido_opt_array_t  options;        /* list of supported options */ +	uint64_t          maxmsgsiz;      /* maximum message size */ +	fido_byte_array_t protocols;      /* supported pin protocols */ +	fido_algo_array_t algorithms;     /* list of supported algorithms */ +	uint64_t          maxcredcntlst;  /* max credentials in list */ +	uint64_t          maxcredidlen;   /* max credential ID length */ +	uint64_t          fwversion;      /* firmware version */  	uint64_t          maxcredbloblen; /* max credBlob length */ +	uint64_t          maxlargeblob;   /* max largeBlob array length */  } fido_cbor_info_t;  typedef struct fido_dev_info { diff --git a/src/hid_freebsd.c b/src/hid_freebsd.c index 5aefe69c1bec..21e408ffd53f 100644 --- a/src/hid_freebsd.c +++ b/src/hid_freebsd.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2020 Yubico AB. All rights reserved. + * Copyright (c) 2020-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -87,8 +87,8 @@ copy_info(fido_dev_info_t *di, const char *path)  	ok = 0;  fail: -	if (fd != -1) -		close(fd); +	if (fd != -1 && close(fd) == -1) +		fido_log_error(errno, "%s: close %s", __func__, path);  	if (ok < 0) {  		free(di->path); @@ -106,8 +106,6 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)  	char	path[64];  	size_t	i; -	*olen = 0; -  	if (ilen == 0)  		return (FIDO_OK); /* nothing to do */ diff --git a/src/hid_openbsd.c b/src/hid_openbsd.c index d3d3bff0fc8b..2993d10dad9d 100644 --- a/src/hid_openbsd.c +++ b/src/hid_openbsd.c @@ -27,14 +27,58 @@ struct hid_openbsd {  	const sigset_t *sigmaskp;  }; +static int +copy_info(fido_dev_info_t *di, const char *path) +{ +	int fd = -1, ok = -1; +	struct usb_device_info udi; + +	memset(di, 0, sizeof(*di)); +	memset(&udi, 0, sizeof(udi)); + +	if ((fd = fido_hid_unix_open(path)) == -1) +		goto fail; +	if (ioctl(fd, IOCTL_REQ(USB_GET_DEVICEINFO), &udi) == -1) { +		fido_log_error(errno, "%s: ioctl %s", __func__, path); +		goto fail; +	} + +	fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x", __func__, path, +	    udi.udi_bus, udi.udi_addr); +	fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"", __func__, +	    path, udi.udi_vendor, udi.udi_product); +	fido_log_debug("%s: %s: productNo = 0x%04x, vendorNo = 0x%04x, " +	    "releaseNo = 0x%04x", __func__, path, udi.udi_productNo, +	    udi.udi_vendorNo, udi.udi_releaseNo); + +	if ((di->path = strdup(path)) == NULL || +	    (di->manufacturer = strdup(udi.udi_vendor)) == NULL || +	    (di->product = strdup(udi.udi_product)) == NULL) +		goto fail; + +	di->vendor_id = (int16_t)udi.udi_vendorNo; +	di->product_id = (int16_t)udi.udi_productNo; + +	ok = 0; +fail: +	if (fd != -1 && close(fd) == -1) +		fido_log_error(errno, "%s: close %s", __func__, path); + +	if (ok < 0) { +		free(di->path); +		free(di->manufacturer); +		free(di->product); +		explicit_bzero(di, sizeof(*di)); +	} + +	return (ok); +} +  int  fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)  {  	size_t i;  	char path[64]; -	int fd; -	struct usb_device_info udi; -	fido_dev_info_t *di;  	if (ilen == 0)  		return (FIDO_OK); /* nothing to do */ @@ -44,50 +88,18 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)  	for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) {  		snprintf(path, sizeof(path), "/dev/fido/%zu", i); -		if ((fd = fido_hid_unix_open(path)) == -1) -			continue; -		memset(&udi, 0, sizeof(udi)); -		if (ioctl(fd, IOCTL_REQ(USB_GET_DEVICEINFO), &udi) == -1) { -			fido_log_error(errno, "%s: get device info %s", -			    __func__, path); -			if (close(fd) == -1) -				fido_log_error(errno, "%s: close", __func__); -			continue; +		if (copy_info(&devlist[*olen], path) == 0) { +			devlist[*olen].io = (fido_dev_io_t) { +				fido_hid_open, +				fido_hid_close, +				fido_hid_read, +				fido_hid_write, +			}; +			++(*olen);  		} -		if (close(fd) == -1) -			fido_log_error(errno, "%s: close", __func__); - -		fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x", -		    __func__, path, udi.udi_bus, udi.udi_addr); -		fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"", -		    __func__, path, udi.udi_vendor, udi.udi_product); -		fido_log_debug("%s: %s: productNo = 0x%04x, vendorNo = 0x%04x, " -		    "releaseNo = 0x%04x", __func__, path, udi.udi_productNo, -		    udi.udi_vendorNo, udi.udi_releaseNo); - -		di = &devlist[*olen]; -		memset(di, 0, sizeof(*di)); -		di->io = (fido_dev_io_t) { -			fido_hid_open, -			fido_hid_close, -			fido_hid_read, -			fido_hid_write, -		}; -		if ((di->path = strdup(path)) == NULL || -		    (di->manufacturer = strdup(udi.udi_vendor)) == NULL || -		    (di->product = strdup(udi.udi_product)) == NULL) { -			free(di->path); -			free(di->manufacturer); -			free(di->product); -			explicit_bzero(di, sizeof(*di)); -			return FIDO_ERR_INTERNAL; -		} -		di->vendor_id = (int16_t)udi.udi_vendorNo; -		di->product_id = (int16_t)udi.udi_productNo; -		(*olen)++;  	} -	return FIDO_OK; +	return (FIDO_OK);  }  /* diff --git a/src/hid_osx.c b/src/hid_osx.c index 7f3652e39620..a5fa8281f81e 100644 --- a/src/hid_osx.c +++ b/src/hid_osx.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2019-2021 Yubico AB. All rights reserved. + * Copyright (c) 2019-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -374,25 +374,6 @@ disable_sigpipe(int fd)  	return (0);  } -static int -to_uint64(const char *str, uint64_t *out) -{ -	char *ep; -	unsigned long long ull; - -	errno = 0; -	ull = strtoull(str, &ep, 10); -	if (str == ep || *ep != '\0') -		return (-1); -	else if (ull == ULLONG_MAX && errno == ERANGE) -		return (-1); -	else if (ull > UINT64_MAX) -		return (-1); -	*out = (uint64_t)ull; - -	return (0); -} -  static io_registry_entry_t  get_ioreg_entry(const char *path)  { @@ -401,8 +382,8 @@ get_ioreg_entry(const char *path)  	if (strncmp(path, IOREG, strlen(IOREG)) != 0)  		return (IORegistryEntryFromPath(kIOMainPortDefault, path)); -	if (to_uint64(path + strlen(IOREG), &id) == -1) { -		fido_log_debug("%s: to_uint64", __func__); +	if (fido_to_uint64(path + strlen(IOREG), 10, &id) == -1) { +		fido_log_debug("%s: fido_to_uint64", __func__);  		return (MACH_PORT_NULL);  	} diff --git a/src/info.c b/src/info.c index 167a1d30ecaa..ea26f22297a6 100644 --- a/src/info.c +++ b/src/info.c @@ -268,6 +268,8 @@ parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg)  		return (decode_string_array(val, &ci->transports));  	case 10: /* algorithms */  		return (decode_algorithms(val, &ci->algorithms)); +	case 11: /* maxSerializedLargeBlobArray */ +		return (cbor_decode_uint64(val, &ci->maxlargeblob));  	case 14: /* fwVersion */  		return (cbor_decode_uint64(val, &ci->fwversion));  	case 15: /* maxCredBlobLen */ @@ -462,6 +464,12 @@ fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci)  }  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 --git a/src/nfc.c b/src/nfc.c new file mode 100644 index 000000000000..8e1221bb5057 --- /dev/null +++ b/src/nfc.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2020-2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#include <stdio.h> +#include <string.h> + +#include "fido.h" +#include "fido/param.h" +#include "iso7816.h" + +#define TX_CHUNK_SIZE	240 + +static const uint8_t aid[] = { 0xa0, 0x00, 0x00, 0x06, 0x47, 0x2f, 0x00, 0x01 }; +static const uint8_t v_u2f[] = { 'U', '2', 'F', '_', 'V', '2' }; +static const uint8_t v_fido[] = { 'F', 'I', 'D', 'O', '_', '2', '_', '0' }; + +static int +tx_short_apdu(fido_dev_t *d, const iso7816_header_t *h, const uint8_t *payload, +    uint8_t payload_len, uint8_t cla_flags) +{ +	uint8_t apdu[5 + UINT8_MAX + 1]; +	uint8_t sw[2]; +	size_t apdu_len; +	int ok = -1; + +	memset(&apdu, 0, sizeof(apdu)); +	apdu[0] = h->cla | cla_flags; +	apdu[1] = h->ins; +	apdu[2] = h->p1; +	apdu[3] = h->p2; +	apdu[4] = payload_len; +	memcpy(&apdu[5], payload, payload_len); +	apdu_len = (size_t)(5 + payload_len + 1); + +	if (d->io.write(d->io_handle, apdu, apdu_len) < 0) { +		fido_log_debug("%s: write", __func__); +		goto fail; +	} + +	if (cla_flags & 0x10) { +		if (d->io.read(d->io_handle, sw, sizeof(sw), -1) != 2) { +			fido_log_debug("%s: read", __func__); +			goto fail; +		} +		if ((sw[0] << 8 | sw[1]) != SW_NO_ERROR) { +			fido_log_debug("%s: unexpected sw", __func__); +			goto fail; +		} +	} + +	ok = 0; +fail: +	explicit_bzero(apdu, sizeof(apdu)); + +	return ok; +} + +static int +nfc_do_tx(fido_dev_t *d, const uint8_t *apdu_ptr, size_t apdu_len) +{ +	iso7816_header_t h; + +	if (fido_buf_read(&apdu_ptr, &apdu_len, &h, sizeof(h)) < 0) { +		fido_log_debug("%s: header", __func__); +		return -1; +	} +	if (apdu_len < 2) { +		fido_log_debug("%s: apdu_len %zu", __func__, apdu_len); +		return -1; +	} + +	apdu_len -= 2; /* trim le1 le2 */ + +	while (apdu_len > TX_CHUNK_SIZE) { +		if (tx_short_apdu(d, &h, apdu_ptr, TX_CHUNK_SIZE, 0x10) < 0) { +			fido_log_debug("%s: chain", __func__); +			return -1; +		} +		apdu_ptr += TX_CHUNK_SIZE; +		apdu_len -= TX_CHUNK_SIZE; +	} + +	if (tx_short_apdu(d, &h, apdu_ptr, (uint8_t)apdu_len, 0) < 0) { +		fido_log_debug("%s: tx_short_apdu", __func__); +		return -1; +	} + +	return 0; +} + +int +fido_nfc_tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count) +{ +	iso7816_apdu_t *apdu = NULL; +	const uint8_t *ptr; +	size_t len; +	int ok = -1; + +	switch (cmd) { +	case CTAP_CMD_INIT: /* select */ +		if ((apdu = iso7816_new(0, 0xa4, 0x04, sizeof(aid))) == NULL || +		    iso7816_add(apdu, aid, sizeof(aid)) < 0) { +			fido_log_debug("%s: iso7816", __func__); +			goto fail; +		} +		break; +	case CTAP_CMD_CBOR: /* wrap cbor */ +		if (count > UINT16_MAX || (apdu = iso7816_new(0x80, 0x10, 0x00, +		    (uint16_t)count)) == NULL || +		    iso7816_add(apdu, buf, count) < 0) { +			fido_log_debug("%s: iso7816", __func__); +			goto fail; +		} +		break; +	case CTAP_CMD_MSG: /* already an apdu */ +		break; +	default: +		fido_log_debug("%s: cmd=%02x", __func__, cmd); +		goto fail; +	} + +	if (apdu != NULL) { +		ptr = iso7816_ptr(apdu); +		len = iso7816_len(apdu); +	} else { +		ptr = buf; +		len = count; +	} + +	if (nfc_do_tx(d, ptr, len) < 0) { +		fido_log_debug("%s: nfc_do_tx", __func__); +		goto fail; +	} + +	ok = 0; +fail: +	iso7816_free(&apdu); + +	return ok; +} + +static int +rx_init(fido_dev_t *d, unsigned char *buf, size_t count, int ms) +{ +	fido_ctap_info_t *attr = (fido_ctap_info_t *)buf; +	uint8_t f[64]; +	int n; + +	if (count != sizeof(*attr)) { +		fido_log_debug("%s: count=%zu", __func__, count); +		return -1; +	} + +	memset(attr, 0, sizeof(*attr)); + +	if ((n = d->io.read(d->io_handle, f, sizeof(f), ms)) < 2 || +	    (f[n - 2] << 8 | f[n - 1]) != SW_NO_ERROR) { +		fido_log_debug("%s: read", __func__); +		return -1; +	} + +	n -= 2; + +	if (n == sizeof(v_u2f) && memcmp(f, v_u2f, sizeof(v_u2f)) == 0) +		attr->flags = FIDO_CAP_CBOR; +	else if (n == sizeof(v_fido) && memcmp(f, v_fido, sizeof(v_fido)) == 0) +		attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG; +	else { +		fido_log_debug("%s: unknown version string", __func__); +#ifdef FIDO_FUZZ +		attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG; +#else +		return -1; +#endif +	} + +	memcpy(&attr->nonce, &d->nonce, sizeof(attr->nonce)); /* XXX */ + +	return (int)count; +} + +static int +tx_get_response(fido_dev_t *d, uint8_t count) +{ +	uint8_t apdu[5]; + +	memset(apdu, 0, sizeof(apdu)); +	apdu[1] = 0xc0; /* GET_RESPONSE */ +	apdu[4] = count; + +	if (d->io.write(d->io_handle, apdu, sizeof(apdu)) < 0) { +		fido_log_debug("%s: write", __func__); +		return -1; +	} + +	return 0; +} + +static int +rx_apdu(fido_dev_t *d, uint8_t sw[2], unsigned char **buf, size_t *count, int *ms) +{ +	uint8_t f[256 + 2]; +	struct timespec ts; +	int n, ok = -1; + +	if (fido_time_now(&ts) != 0) +		goto fail; + +	if ((n = d->io.read(d->io_handle, f, sizeof(f), *ms)) < 2) { +		fido_log_debug("%s: read", __func__); +		goto fail; +	} + +	if (fido_time_delta(&ts, ms) != 0) +		goto fail; + +	if (fido_buf_write(buf, count, f, (size_t)(n - 2)) < 0) { +		fido_log_debug("%s: fido_buf_write", __func__); +		goto fail; +	} + +	memcpy(sw, f + n - 2, 2); + +	ok = 0; +fail: +	explicit_bzero(f, sizeof(f)); + +	return ok; +} + +static int +rx_msg(fido_dev_t *d, unsigned char *buf, size_t count, int ms) +{ +	uint8_t sw[2]; +	const size_t bufsiz = count; + +	if (rx_apdu(d, sw, &buf, &count, &ms) < 0) { +		fido_log_debug("%s: preamble", __func__); +		return -1; +	} + +	while (sw[0] == SW1_MORE_DATA) +		if (tx_get_response(d, sw[1]) < 0 || +		    rx_apdu(d, sw, &buf, &count, &ms) < 0) { +			fido_log_debug("%s: chain", __func__); +			return -1; +		} + +	if (fido_buf_write(&buf, &count, sw, sizeof(sw)) < 0) { +		fido_log_debug("%s: sw", __func__); +		return -1; +	} + +	if (bufsiz - count > INT_MAX) { +		fido_log_debug("%s: bufsiz", __func__); +		return -1; +	} + +	return (int)(bufsiz - count); +} + +static int +rx_cbor(fido_dev_t *d, unsigned char *buf, size_t count, int ms) +{ +	int r; + +	if ((r = rx_msg(d, buf, count, ms)) < 2) +		return -1; + +	return r - 2; +} + +int +fido_nfc_rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) +{ +	switch (cmd) { +	case CTAP_CMD_INIT: +		return rx_init(d, buf, count, ms); +	case CTAP_CMD_CBOR: +		return rx_cbor(d, buf, count, ms); +	case CTAP_CMD_MSG: +		return rx_msg(d, buf, count, ms); +	default: +		fido_log_debug("%s: cmd=%02x", __func__, cmd); +		return -1; +	} +} + +#ifdef USE_NFC +bool +fido_is_nfc(const char *path) +{ +	return strncmp(path, FIDO_NFC_PREFIX, strlen(FIDO_NFC_PREFIX)) == 0; +} + +int +fido_dev_set_nfc(fido_dev_t *d) +{ +	if (d->io_handle != NULL) { +		fido_log_debug("%s: device open", __func__); +		return -1; +	} +	d->io_own = true; +	d->io = (fido_dev_io_t) { +		fido_nfc_open, +		fido_nfc_close, +		fido_nfc_read, +		fido_nfc_write, +	}; +	d->transport = (fido_dev_transport_t) { +		fido_nfc_rx, +		fido_nfc_tx, +	}; + +	return 0; +} +#endif /* USE_NFC */ diff --git a/src/nfc_linux.c b/src/nfc_linux.c index d5f9ec048052..4673dc2b7d18 100644 --- a/src/nfc_linux.c +++ b/src/nfc_linux.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2020 Yubico AB. All rights reserved. + * Copyright (c) 2020-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -22,12 +22,6 @@  #include "netlink.h"  #include "iso7816.h" -#define TX_CHUNK_SIZE	240 - -static const uint8_t aid[] = { 0xa0, 0x00, 0x00, 0x06, 0x47, 0x2f, 0x00, 0x01 }; -static const uint8_t v_u2f[] = { 'U', '2', 'F', '_', 'V', '2' }; -static const uint8_t v_fido[] = { 'F', 'I', 'D', 'O', '_', '2', '_', '0' }; -  struct nfc_linux {  	int             fd;  	uint32_t        dev; @@ -37,278 +31,6 @@ struct nfc_linux {  	struct fido_nl *nl;  }; -static int -tx_short_apdu(fido_dev_t *d, const iso7816_header_t *h, const uint8_t *payload, -    uint8_t payload_len, uint8_t cla_flags) -{ -	uint8_t apdu[5 + UINT8_MAX + 1]; -	uint8_t sw[2]; -	size_t apdu_len; -	int ok = -1; - -	memset(&apdu, 0, sizeof(apdu)); -	apdu[0] = h->cla | cla_flags; -	apdu[1] = h->ins; -	apdu[2] = h->p1; -	apdu[3] = h->p2; -	apdu[4] = payload_len; -	memcpy(&apdu[5], payload, payload_len); -	apdu_len = (size_t)(5 + payload_len + 1); - -	if (d->io.write(d->io_handle, apdu, apdu_len) < 0) { -		fido_log_debug("%s: write", __func__); -		goto fail; -	} - -	if (cla_flags & 0x10) { -		if (d->io.read(d->io_handle, sw, sizeof(sw), -1) != 2) { -			fido_log_debug("%s: read", __func__); -			goto fail; -		} -		if ((sw[0] << 8 | sw[1]) != SW_NO_ERROR) { -			fido_log_debug("%s: unexpected sw", __func__); -			goto fail; -		} -	} - -	ok = 0; -fail: -	explicit_bzero(apdu, sizeof(apdu)); - -	return (ok); -} - -static int -nfc_do_tx(fido_dev_t *d, const uint8_t *apdu_ptr, size_t apdu_len) -{ -	iso7816_header_t h; - -	if (fido_buf_read(&apdu_ptr, &apdu_len, &h, sizeof(h)) < 0) { -		fido_log_debug("%s: header", __func__); -		return (-1); -	} -	if (apdu_len < 2) { -		fido_log_debug("%s: apdu_len %zu", __func__, apdu_len); -		return (-1); -	} - -	apdu_len -= 2; /* trim le1 le2 */ - -	while (apdu_len > TX_CHUNK_SIZE) { -		if (tx_short_apdu(d, &h, apdu_ptr, TX_CHUNK_SIZE, 0x10) < 0) { -			fido_log_debug("%s: chain", __func__); -			return (-1); -		} -		apdu_ptr += TX_CHUNK_SIZE; -		apdu_len -= TX_CHUNK_SIZE; -	} - -	if (tx_short_apdu(d, &h, apdu_ptr, (uint8_t)apdu_len, 0) < 0) { -		fido_log_debug("%s: tx_short_apdu", __func__); -		return (-1); -	} -  -	return (0); -} - -int -fido_nfc_tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count) -{ -	iso7816_apdu_t *apdu = NULL; -	const uint8_t *ptr; -	size_t len; -	int ok = -1; - -	switch (cmd) { -	case CTAP_CMD_INIT: /* select */ -		if ((apdu = iso7816_new(0, 0xa4, 0x04, sizeof(aid))) == NULL || -		    iso7816_add(apdu, aid, sizeof(aid)) < 0) { -			fido_log_debug("%s: iso7816", __func__); -			goto fail; -		} -		break; -	case CTAP_CMD_CBOR: /* wrap cbor */ -		if (count > UINT16_MAX || (apdu = iso7816_new(0x80, 0x10, 0x80, -		    (uint16_t)count)) == NULL || -		    iso7816_add(apdu, buf, count) < 0) { -			fido_log_debug("%s: iso7816", __func__); -			goto fail; -		} -		break; -	case CTAP_CMD_MSG: /* already an apdu */ -		break; -	default: -		fido_log_debug("%s: cmd=%02x", __func__, cmd); -		goto fail; -	} - -	if (apdu != NULL) { -		ptr = iso7816_ptr(apdu); -		len = iso7816_len(apdu); -	} else { -		ptr = buf; -		len = count; -	} - -	if (nfc_do_tx(d, ptr, len) < 0) { -		fido_log_debug("%s: nfc_do_tx", __func__); -		goto fail; -	} - -	ok = 0; -fail: -	iso7816_free(&apdu); - -	return (ok); -} - -static int -rx_init(fido_dev_t *d, unsigned char *buf, size_t count, int ms) -{ -	fido_ctap_info_t *attr = (fido_ctap_info_t *)buf; -	uint8_t f[64]; -	int n; - -	if (count != sizeof(*attr)) { -		fido_log_debug("%s: count=%zu", __func__, count); -		return (-1); -	} - -	memset(attr, 0, sizeof(*attr)); - -	if ((n = d->io.read(d->io_handle, f, sizeof(f), ms)) < 2 || -	    (f[n - 2] << 8 | f[n - 1]) != SW_NO_ERROR) { -		fido_log_debug("%s: read", __func__); -		return (-1); -	} - -	n -= 2; - -	if (n == sizeof(v_u2f) && memcmp(f, v_u2f, sizeof(v_u2f)) == 0) -		attr->flags = FIDO_CAP_CBOR; -	else if (n == sizeof(v_fido) && memcmp(f, v_fido, sizeof(v_fido)) == 0) -		attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG; -	else { -		fido_log_debug("%s: unknown version string", __func__); -#ifdef FIDO_FUZZ -		attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG; -#else -		return (-1); -#endif -	} - -	memcpy(&attr->nonce, &d->nonce, sizeof(attr->nonce)); /* XXX */ - -	return ((int)count); -} - -static int -tx_get_response(fido_dev_t *d, uint8_t count) -{ -	uint8_t apdu[5]; - -	memset(apdu, 0, sizeof(apdu)); -	apdu[1] = 0xc0; /* GET_RESPONSE */ -	apdu[4] = count; - -	if (d->io.write(d->io_handle, apdu, sizeof(apdu)) < 0) { -		fido_log_debug("%s: write", __func__); -		return (-1); -	} - -	return (0); -} - -static int -rx_apdu(fido_dev_t *d, uint8_t sw[2], unsigned char **buf, size_t *count, int *ms) -{ -	uint8_t f[256 + 2]; -	struct timespec ts; -	int n, ok = -1; - -	if (fido_time_now(&ts) != 0) -		goto fail; - -	if ((n = d->io.read(d->io_handle, f, sizeof(f), *ms)) < 2) { -		fido_log_debug("%s: read", __func__); -		goto fail; -	} - -	if (fido_time_delta(&ts, ms) != 0) -		goto fail; - -	if (fido_buf_write(buf, count, f, (size_t)(n - 2)) < 0) { -		fido_log_debug("%s: fido_buf_write", __func__); -		goto fail; -	} - -	memcpy(sw, f + n - 2, 2); - -	ok = 0; -fail: -	explicit_bzero(f, sizeof(f)); - -	return (ok); -} - -static int -rx_msg(fido_dev_t *d, unsigned char *buf, size_t count, int ms) -{ -	uint8_t sw[2]; -	const size_t bufsiz = count; - -	if (rx_apdu(d, sw, &buf, &count, &ms) < 0) { -		fido_log_debug("%s: preamble", __func__); -		return (-1); -	} - -	while (sw[0] == SW1_MORE_DATA) -		if (tx_get_response(d, sw[1]) < 0 || -		    rx_apdu(d, sw, &buf, &count, &ms) < 0) { -			fido_log_debug("%s: chain", __func__); -			return (-1); -		} - -	if (fido_buf_write(&buf, &count, sw, sizeof(sw)) < 0) { -		fido_log_debug("%s: sw", __func__); -		return (-1); -	} - -	if (bufsiz - count > INT_MAX) { -		fido_log_debug("%s: bufsiz", __func__); -		return (-1); -	} - -	return ((int)(bufsiz - count)); -} - -static int -rx_cbor(fido_dev_t *d, unsigned char *buf, size_t count, int ms) -{ -	int r; - -	if ((r = rx_msg(d, buf, count, ms)) < 2) -		return (-1); - -	return (r - 2); -} - -int -fido_nfc_rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) -{ -	switch (cmd) { -	case CTAP_CMD_INIT: -		return (rx_init(d, buf, count, ms)); -	case CTAP_CMD_CBOR: -		return (rx_cbor(d, buf, count, ms)); -	case CTAP_CMD_MSG: -		return (rx_msg(d, buf, count, ms)); -	default: -		fido_log_debug("%s: cmd=%02x", __func__, cmd); -		return (-1); -	} -} -  static char *  get_parent_attr(struct udev_device *dev, const char *subsystem,      const char *devtype, const char *attr) @@ -319,34 +41,15 @@ get_parent_attr(struct udev_device *dev, const char *subsystem,  	if ((parent = udev_device_get_parent_with_subsystem_devtype(dev,  	    subsystem, devtype)) == NULL || (value =  	    udev_device_get_sysattr_value(parent, attr)) == NULL) -		return (NULL); +		return NULL; -	return (strdup(value)); +	return strdup(value);  }  static char *  get_usb_attr(struct udev_device *dev, const char *attr)  { -	return (get_parent_attr(dev, "usb", "usb_device", attr)); -} - -static int -to_int(const char *str, int base) -{ -	char *ep; -	long long ll; - -	ll = strtoll(str, &ep, base); -	if (str == ep || *ep != '\0') -		return (-1); -	else if (ll == LLONG_MIN && errno == ERANGE) -		return (-1); -	else if (ll == LLONG_MAX && errno == ERANGE) -		return (-1); -	else if (ll < 0 || ll > INT_MAX) -		return (-1); - -	return ((int)ll); +	return get_parent_attr(dev, "usb", "usb_device", attr);  }  static int @@ -357,15 +60,18 @@ copy_info(fido_dev_info_t *di, struct udev *udev,  	char *str;  	struct udev_device *dev = NULL;  	void *ctx = NULL; -	int id, ok = -1; +	uint64_t id; +	int ok = -1;  	memset(di, 0, sizeof(*di));  	if ((name = udev_list_entry_get_name(udev_entry)) == NULL ||  	    (dev = udev_device_new_from_syspath(udev, name)) == NULL)  		goto fail; -	if (asprintf(&di->path, "%s/%s", FIDO_NFC_PREFIX, name) == -1) +	if (asprintf(&di->path, "%s/%s", FIDO_NFC_PREFIX, name) == -1) { +		di->path = NULL;  		goto fail; +	}  	if ((di->manufacturer = get_usb_attr(dev, "manufacturer")) == NULL)  		di->manufacturer = strdup("");  	if ((di->product = get_usb_attr(dev, "product")) == NULL) @@ -374,11 +80,11 @@ copy_info(fido_dev_info_t *di, struct udev *udev,  		goto fail;  	/* XXX assumes USB for vendor/product info */  	if ((str = get_usb_attr(dev, "idVendor")) != NULL && -	    (id = to_int(str, 16)) > 0 && id <= UINT16_MAX) +	    fido_to_uint64(str, 16, &id) == 0 && id <= UINT16_MAX)  		di->vendor_id = (int16_t)id;  	free(str);  	if ((str = get_usb_attr(dev, "idProduct")) != NULL && -	    (id = to_int(str, 16)) > 0 && id <= UINT16_MAX) +	    fido_to_uint64(str, 16, &id) == 0 && id <= UINT16_MAX)  		di->product_id = (int16_t)id;  	free(str); @@ -401,7 +107,7 @@ fail:  		explicit_bzero(di, sizeof(*di));  	} -	return (ok); +	return ok;  }  static int @@ -410,21 +116,21 @@ sysnum_from_syspath(const char *path)  	struct udev *udev = NULL;  	struct udev_device *dev = NULL;  	const char *str; -	int idx; +	uint64_t idx64; +	int idx = -1; -	if ((udev = udev_new()) == NULL || -	    (dev = udev_device_new_from_syspath(udev, path)) == NULL || -	    (str = udev_device_get_sysnum(dev)) == NULL) -		idx = -1; -	else -		idx = to_int(str, 10); +	if ((udev = udev_new()) != NULL && +	    (dev = udev_device_new_from_syspath(udev, path)) != NULL && +	    (str = udev_device_get_sysnum(dev)) != NULL && +	    fido_to_uint64(str, 10, &idx64) == 0 && idx64 < INT_MAX) +		idx = (int)idx64;  	if (dev != NULL)  		udev_device_unref(dev);  	if (udev != NULL)  		udev_unref(udev); -	return (idx); +	return idx;  }  int @@ -439,10 +145,10 @@ fido_nfc_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)  	*olen = 0;  	if (ilen == 0) -		return (FIDO_OK); +		return FIDO_OK;  	if (devlist == NULL) -		return (FIDO_ERR_INVALID_ARGUMENT); +		return FIDO_ERR_INVALID_ARGUMENT;  	if ((udev = udev_new()) == NULL ||  	    (udev_enum = udev_enumerate_new(udev)) == NULL) @@ -481,7 +187,7 @@ fail:  	if (udev != NULL)  		udev_unref(udev); -	return (r); +	return r;  }  static int @@ -498,17 +204,17 @@ nfc_target_connect(struct nfc_linux *ctx)  	if ((ctx->fd = socket(AF_NFC, SOCK_SEQPACKET | SOCK_CLOEXEC,  	    NFC_SOCKPROTO_RAW)) == -1) {  		fido_log_error(errno, "%s: socket", __func__); -		return (-1); +		return -1;  	}  	if (connect(ctx->fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {  		fido_log_error(errno, "%s: connect", __func__);  		if (close(ctx->fd) == -1)  			fido_log_error(errno, "%s: close", __func__);  		ctx->fd = -1; -		return (-1); +		return -1;  	} -	return (0); +	return 0;  }  static void @@ -535,13 +241,13 @@ nfc_new(uint32_t dev)  	if ((ctx = calloc(1, sizeof(*ctx))) == NULL ||  	    (ctx->nl = fido_nl_new()) == NULL) {  		nfc_free(&ctx); -		return (NULL); +		return NULL;  	}  	ctx->fd = -1;  	ctx->dev = dev; -	return (ctx); +	return ctx;  }  void * @@ -566,10 +272,10 @@ fido_nfc_open(const char *path)  		goto fail;  	} -	return (ctx); +	return ctx;  fail:  	nfc_free(&ctx); -	return (NULL); +	return NULL;  }  void @@ -588,7 +294,7 @@ fido_nfc_set_sigmask(void *handle, const fido_sigset_t *sigmask)  	ctx->sigmask = *sigmask;  	ctx->sigmaskp = &ctx->sigmask; -	return (FIDO_OK); +	return FIDO_OK;  }  int @@ -607,25 +313,25 @@ fido_nfc_read(void *handle, unsigned char *buf, size_t len, int ms)  	if (fido_hid_unix_wait(ctx->fd, ms, ctx->sigmaskp) < 0) {  		fido_log_debug("%s: fido_hid_unix_wait", __func__); -		return (-1); +		return -1;  	}  	if ((r = readv(ctx->fd, iov, nitems(iov))) == -1) {  		fido_log_error(errno, "%s: read", __func__); -		return (-1); +		return -1;  	}  	if (r < 1) {  		fido_log_debug("%s: %zd < 1", __func__, r); -		return (-1); +		return -1;  	}  	if (preamble != 0x00) {  		fido_log_debug("%s: preamble", __func__); -		return (-1); +		return -1;  	}  	r--;  	fido_log_xxd(buf, (size_t)r, "%s", __func__); -	return ((int)r); +	return (int)r;  }  int @@ -638,16 +344,16 @@ fido_nfc_write(void *handle, const unsigned char *buf, size_t len)  	if (len > INT_MAX) {  		fido_log_debug("%s: len", __func__); -		return (-1); +		return -1;  	}  	if ((r = write(ctx->fd, buf, len)) == -1) {  		fido_log_error(errno, "%s: write", __func__); -		return (-1); +		return -1;  	}  	if (r < 0 || (size_t)r != len) {  		fido_log_debug("%s: %zd != %zu", __func__, r, len); -		return (-1); +		return -1;  	} -	return ((int)r); +	return (int)r;  } diff --git a/src/pcsc.c b/src/pcsc.c new file mode 100644 index 000000000000..c02251e9bfe1 --- /dev/null +++ b/src/pcsc.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2022 Micro Focus or one of its affiliates. + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#if __APPLE__ +#include <PCSC/wintypes.h> +#include <PCSC/winscard.h> +#else +#include <winscard.h> +#endif /* __APPLE__ */ + +#include <errno.h> + +#include "fido.h" +#include "fido/param.h" +#include "iso7816.h" + +#if defined(_WIN32) && !defined(__MINGW32__) +#define SCardConnect SCardConnectA +#define SCardListReaders SCardListReadersA +#endif + +#ifndef SCARD_PROTOCOL_Tx +#define SCARD_PROTOCOL_Tx SCARD_PROTOCOL_ANY +#endif + +#define BUFSIZE 1024	/* in bytes; passed to SCardListReaders() */ +#define APDULEN 264	/* 261 rounded up to the nearest multiple of 8 */ +#define READERS 8	/* maximum number of readers */ + +struct pcsc { +	SCARDCONTEXT     ctx; +	SCARDHANDLE      h; +	SCARD_IO_REQUEST req; +	uint8_t          rx_buf[APDULEN]; +	size_t           rx_len; +}; + +static LONG +list_readers(SCARDCONTEXT ctx, char **buf) +{ +	LONG s; +	DWORD len; + +	len = BUFSIZE; +	if ((*buf = calloc(1, len)) == NULL) +		goto fail; +	if ((s = SCardListReaders(ctx, NULL, *buf, &len)) != SCARD_S_SUCCESS) { +		fido_log_debug("%s: SCardListReaders 0x%lx", __func__, (long)s); +		goto fail; +	} +	/* sanity check "multi-string" */ +	if (len > BUFSIZE || len < 2) { +		fido_log_debug("%s: bogus len=%u", __func__, (unsigned)len); +		goto fail; +	} +	if ((*buf)[len - 1] != 0 || (*buf)[len - 2] != '\0') { +		fido_log_debug("%s: bogus buf", __func__); +		goto fail; +	} +	return (LONG)SCARD_S_SUCCESS; +fail: +	free(*buf); +	*buf = NULL; + +	return (LONG)SCARD_E_NO_READERS_AVAILABLE; +} + +static char * +get_reader(SCARDCONTEXT ctx, const char *path) +{ +	char *reader = NULL, *buf = NULL; +	const char prefix[] = FIDO_PCSC_PREFIX "//slot"; +	uint64_t n; + +	if (path == NULL) +		goto out; +	if (strncmp(path, prefix, strlen(prefix)) != 0 || +	    fido_to_uint64(path + strlen(prefix), 10, &n) < 0 || +	    n > READERS - 1) { +		fido_log_debug("%s: invalid path %s", __func__, path); +		goto out; +	} +	if (list_readers(ctx, &buf) != SCARD_S_SUCCESS) { +		fido_log_debug("%s: list_readers", __func__); +		goto out; +	} +	for (const char *name = buf; *name != 0; name += strlen(name) + 1) { +		if (n == 0) { +			reader = strdup(name); +			goto out; +		} +		n--; +	} +	fido_log_debug("%s: failed to find reader %s", __func__, path); +out: +	free(buf); + +	return reader; +} + +static int +prepare_io_request(DWORD prot, SCARD_IO_REQUEST *req) +{ +	switch (prot) { +	case SCARD_PROTOCOL_T0: +		req->dwProtocol = SCARD_PCI_T0->dwProtocol; +		req->cbPciLength = SCARD_PCI_T0->cbPciLength; +		break; +	case SCARD_PROTOCOL_T1: +		req->dwProtocol = SCARD_PCI_T1->dwProtocol; +		req->cbPciLength = SCARD_PCI_T1->cbPciLength; +		break; +	default: +		fido_log_debug("%s: unknown protocol %lu", __func__, +		    (u_long)prot); +		return -1; +	} + +	return 0; +} + +static int +copy_info(fido_dev_info_t *di, SCARDCONTEXT ctx, const char *reader, size_t idx) +{ +	SCARDHANDLE h = 0; +	SCARD_IO_REQUEST req; +	DWORD prot = 0; +	LONG s; +	int ok = -1; + +	memset(di, 0, sizeof(*di)); +	memset(&req, 0, sizeof(req)); + +	if ((s = SCardConnect(ctx, reader, SCARD_SHARE_SHARED, +	    SCARD_PROTOCOL_Tx, &h, &prot)) != SCARD_S_SUCCESS) { +		fido_log_debug("%s: SCardConnect 0x%lx", __func__, (long)s); +		goto fail; +	} +	if (prepare_io_request(prot, &req) < 0) { +		fido_log_debug("%s: prepare_io_request", __func__); +		goto fail; +	} +	if (asprintf(&di->path, "%s//slot%zu", FIDO_PCSC_PREFIX, idx) == -1) { +		di->path = NULL; +		fido_log_debug("%s: asprintf", __func__); +		goto fail; +	} +	if ((di->manufacturer = strdup("PC/SC")) == NULL || +	    (di->product = strdup(reader)) == NULL) +		goto fail; + +	ok = 0; +fail: +	if (h != 0) +		SCardDisconnect(h, SCARD_LEAVE_CARD); +	if (ok < 0) { +		free(di->path); +		free(di->manufacturer); +		free(di->product); +		explicit_bzero(di, sizeof(*di)); +	} + +	return ok; +} + +int +fido_pcsc_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) +{ +	SCARDCONTEXT ctx = 0; +	char *buf = NULL; +	LONG s; +	size_t idx = 0; +	int r = FIDO_ERR_INTERNAL; + +	*olen = 0; + +	if (ilen == 0) +		return FIDO_OK; +	if (devlist == NULL) +		return FIDO_ERR_INVALID_ARGUMENT; + +	if ((s = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, +	    &ctx)) != SCARD_S_SUCCESS || ctx == 0) { +		fido_log_debug("%s: SCardEstablishContext 0x%lx", __func__, +		    (long)s); +		if (s == (LONG)SCARD_E_NO_SERVICE || +		    s == (LONG)SCARD_E_NO_SMARTCARD) +			r = FIDO_OK; /* suppress error */ +		goto out; +	} +	if ((s = list_readers(ctx, &buf)) != SCARD_S_SUCCESS) { +		fido_log_debug("%s: list_readers 0x%lx", __func__, (long)s); +		if (s == (LONG)SCARD_E_NO_READERS_AVAILABLE) +			r = FIDO_OK; /* suppress error */ +		goto out; +	} + +	for (const char *name = buf; *name != 0; name += strlen(name) + 1) { +		if (idx == READERS) { +			fido_log_debug("%s: stopping at %zu readers", __func__, +			    idx); +			r = FIDO_OK; +			goto out; +		} +		if (copy_info(&devlist[*olen], ctx, name, idx++) == 0) { +			devlist[*olen].io = (fido_dev_io_t) { +				fido_pcsc_open, +				fido_pcsc_close, +				fido_pcsc_read, +				fido_pcsc_write, +			}; +			devlist[*olen].transport = (fido_dev_transport_t) { +				fido_pcsc_rx, +				fido_pcsc_tx, +			}; +			if (++(*olen) == ilen) +				break; +		} +	} + +	r = FIDO_OK; +out: +	free(buf); +	if (ctx != 0) +		SCardReleaseContext(ctx); + +	return r; +} + +void * +fido_pcsc_open(const char *path) +{ +	char *reader = NULL; +	struct pcsc *dev = NULL; +	SCARDCONTEXT ctx = 0; +	SCARDHANDLE h = 0; +	SCARD_IO_REQUEST req; +	DWORD prot = 0; +	LONG s; + +	memset(&req, 0, sizeof(req)); + +	if ((s = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, +	    &ctx)) != SCARD_S_SUCCESS || ctx == 0) { +		fido_log_debug("%s: SCardEstablishContext 0x%lx", __func__, +		    (long)s); +		goto fail; + +	} +	if ((reader = get_reader(ctx, path)) == NULL) { +		fido_log_debug("%s: get_reader(%s)", __func__, path); +		goto fail; +	} +	if ((s = SCardConnect(ctx, reader, SCARD_SHARE_SHARED, +	    SCARD_PROTOCOL_Tx, &h, &prot)) != SCARD_S_SUCCESS) { +		fido_log_debug("%s: SCardConnect 0x%lx", __func__, (long)s); +		goto fail; +	} +	if (prepare_io_request(prot, &req) < 0) { +		fido_log_debug("%s: prepare_io_request", __func__); +		goto fail; +	} +	if ((dev = calloc(1, sizeof(*dev))) == NULL) +		goto fail; + +	dev->ctx = ctx; +	dev->h = h; +	dev->req = req; +	ctx = 0; +	h = 0; +fail: +	if (h != 0) +		SCardDisconnect(h, SCARD_LEAVE_CARD); +	if (ctx != 0) +		SCardReleaseContext(ctx); +	free(reader); + +	return dev; +} + +void +fido_pcsc_close(void *handle) +{ +	struct pcsc *dev = handle; + +	if (dev->h != 0) +		SCardDisconnect(dev->h, SCARD_LEAVE_CARD); +	if (dev->ctx != 0) +		SCardReleaseContext(dev->ctx); + +	explicit_bzero(dev->rx_buf, sizeof(dev->rx_buf)); +	free(dev); +} + +int +fido_pcsc_read(void *handle, unsigned char *buf, size_t len, int ms) +{ +	struct pcsc *dev = handle; +	int r; + +	(void)ms; +	if (dev->rx_len == 0 || dev->rx_len > len || +	    dev->rx_len > sizeof(dev->rx_buf)) { +		fido_log_debug("%s: rx_len", __func__); +		return -1; +	} +	fido_log_xxd(dev->rx_buf, dev->rx_len, "%s: reading", __func__); +	memcpy(buf, dev->rx_buf, dev->rx_len); +	explicit_bzero(dev->rx_buf, sizeof(dev->rx_buf)); +	r = (int)dev->rx_len; +	dev->rx_len = 0; + +	return r; +} + +int +fido_pcsc_write(void *handle, const unsigned char *buf, size_t len) +{ +	struct pcsc *dev = handle; +	DWORD n; +	LONG s; + +	if (len > INT_MAX) { +		fido_log_debug("%s: len", __func__); +		return -1; +	} + +	explicit_bzero(dev->rx_buf, sizeof(dev->rx_buf)); +	dev->rx_len = 0; +	n = (DWORD)sizeof(dev->rx_buf); + +	fido_log_xxd(buf, len, "%s: writing", __func__); + +	if ((s = SCardTransmit(dev->h, &dev->req, buf, (DWORD)len, NULL, +	    dev->rx_buf, &n)) != SCARD_S_SUCCESS) { +		fido_log_debug("%s: SCardTransmit 0x%lx", __func__, (long)s); +		explicit_bzero(dev->rx_buf, sizeof(dev->rx_buf)); +		return -1; +	} +	dev->rx_len = (size_t)n; + +	fido_log_xxd(dev->rx_buf, dev->rx_len, "%s: read", __func__); + +	return (int)len; +} + +int +fido_pcsc_tx(fido_dev_t *d, uint8_t cmd, const u_char *buf, size_t count) +{ +	return fido_nfc_tx(d, cmd, buf, count); +} + +int +fido_pcsc_rx(fido_dev_t *d, uint8_t cmd, u_char *buf, size_t count, int ms) +{ +	return fido_nfc_rx(d, cmd, buf, count, ms); +} + +bool +fido_is_pcsc(const char *path) +{ +	return strncmp(path, FIDO_PCSC_PREFIX, strlen(FIDO_PCSC_PREFIX)) == 0; +} + +int +fido_dev_set_pcsc(fido_dev_t *d) +{ +	if (d->io_handle != NULL) { +		fido_log_debug("%s: device open", __func__); +		return -1; +	} +	d->io_own = true; +	d->io = (fido_dev_io_t) { +		fido_pcsc_open, +		fido_pcsc_close, +		fido_pcsc_read, +		fido_pcsc_write, +	}; +	d->transport = (fido_dev_transport_t) { +		fido_pcsc_rx, +		fido_pcsc_tx, +	}; + +	return 0; +} diff --git a/src/rs1.c b/src/rs1.c index 37aa9f073bed..134068b16747 100644 --- a/src/rs1.c +++ b/src/rs1.c @@ -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 --git a/src/rs256.c b/src/rs256.c index 29fcedbdee20..95bae167a177 100644 --- a/src/rs256.c +++ b/src/rs256.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2018-2021 Yubico AB. All rights reserved. + * Copyright (c) 2018-2022 Yubico AB. All rights reserved.   * Use of this source code is governed by a BSD-style   * license that can be found in the LICENSE file.   */ @@ -11,7 +11,13 @@  #include "fido.h"  #include "fido/rs256.h" -#if defined(LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER >= 0x30000000 +#define get0_RSA(x)	EVP_PKEY_get0_RSA((x)) +#else +#define get0_RSA(x)	EVP_PKEY_get0((x)) +#endif + +#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050200fL  static EVP_MD *  rs256_get_EVP_MD(void)  { @@ -128,11 +134,20 @@ rs256_pk_free(rs256_pk_t **pkp)  int  rs256_pk_from_ptr(rs256_pk_t *pk, const void *ptr, size_t len)  { +	EVP_PKEY *pkey; +  	if (len < sizeof(*pk))  		return (FIDO_ERR_INVALID_ARGUMENT);  	memcpy(pk, ptr, sizeof(*pk)); +	if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) { +		fido_log_debug("%s: rs256_pk_to_EVP_PKEY", __func__); +		return (FIDO_ERR_INVALID_ARGUMENT); +	} + +	EVP_PKEY_free(pkey); +  	return (FIDO_OK);  } @@ -163,6 +178,11 @@ rs256_pk_to_EVP_PKEY(const rs256_pk_t *k)  	n = NULL;  	e = NULL; +	if (RSA_bits(rsa) != 2048) { +		fido_log_debug("%s: invalid key length", __func__); +		goto fail; +	} +  	if ((pkey = EVP_PKEY_new()) == NULL ||  	    EVP_PKEY_assign_RSA(pkey, rsa) == 0) {  		fido_log_debug("%s: EVP_PKEY_assign_RSA", __func__); @@ -225,10 +245,10 @@ rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa)  int  rs256_pk_from_EVP_PKEY(rs256_pk_t *pk, const EVP_PKEY *pkey)  { -	RSA *rsa; +	const RSA *rsa;  	if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA || -	    (rsa = EVP_PKEY_get0(pkey)) == NULL) +	    (rsa = get0_RSA(pkey)) == NULL)  		return (FIDO_ERR_INVALID_ARGUMENT);  	return (rs256_pk_from_RSA(pk, rsa)); diff --git a/src/touch.c b/src/touch.c new file mode 100644 index 000000000000..66b1c3478c0a --- /dev/null +++ b/src/touch.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018-2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#include <openssl/sha.h> +#include "fido.h" + +int +fido_dev_get_touch_begin(fido_dev_t *dev) +{ +	fido_blob_t	 f; +	cbor_item_t	*argv[9]; +	const char	*clientdata = FIDO_DUMMY_CLIENTDATA; +	const uint8_t	 user_id = FIDO_DUMMY_USER_ID; +	unsigned char	 cdh[SHA256_DIGEST_LENGTH]; +	fido_rp_t	 rp; +	fido_user_t	 user; +	int		 ms = dev->timeout_ms; +	int		 r = FIDO_ERR_INTERNAL; + +	memset(&f, 0, sizeof(f)); +	memset(argv, 0, sizeof(argv)); +	memset(cdh, 0, sizeof(cdh)); +	memset(&rp, 0, sizeof(rp)); +	memset(&user, 0, sizeof(user)); + +	if (fido_dev_is_fido2(dev) == false) +		return (u2f_get_touch_begin(dev, &ms)); + +	if (SHA256((const void *)clientdata, strlen(clientdata), cdh) != cdh) { +		fido_log_debug("%s: sha256", __func__); +		return (FIDO_ERR_INTERNAL); +	} + +	if ((rp.id = strdup(FIDO_DUMMY_RP_ID)) == NULL || +	    (user.name = strdup(FIDO_DUMMY_USER_NAME)) == NULL) { +		fido_log_debug("%s: strdup", __func__); +		goto fail; +	} + +	if (fido_blob_set(&user.id, &user_id, sizeof(user_id)) < 0) { +		fido_log_debug("%s: fido_blob_set", __func__); +		goto fail; +	} + +	if ((argv[0] = cbor_build_bytestring(cdh, sizeof(cdh))) == NULL || +	    (argv[1] = cbor_encode_rp_entity(&rp)) == NULL || +	    (argv[2] = cbor_encode_user_entity(&user)) == NULL || +	    (argv[3] = cbor_encode_pubkey_param(COSE_ES256)) == NULL) { +		fido_log_debug("%s: cbor encode", __func__); +		goto fail; +	} + +	if (fido_dev_supports_pin(dev)) { +		if ((argv[7] = cbor_new_definite_bytestring()) == NULL || +		    (argv[8] = cbor_encode_pin_opt(dev)) == NULL) { +			fido_log_debug("%s: cbor encode", __func__); +			goto fail; +		} +	} + +	if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 || +	    fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, &ms) < 0) { +		fido_log_debug("%s: fido_tx", __func__); +		r = FIDO_ERR_TX; +		goto fail; +	} + +	r = FIDO_OK; +fail: +	cbor_vector_free(argv, nitems(argv)); +	free(f.ptr); +	free(rp.id); +	free(user.name); +	free(user.id.ptr); + +	return (r); +} + +int +fido_dev_get_touch_status(fido_dev_t *dev, int *touched, int ms) +{ +	int r; + +	*touched = 0; + +	if (fido_dev_is_fido2(dev) == false) +		return (u2f_get_touch_status(dev, touched, &ms)); + +	switch ((r = fido_rx_cbor_status(dev, &ms))) { +	case FIDO_ERR_PIN_AUTH_INVALID: +	case FIDO_ERR_PIN_INVALID: +	case FIDO_ERR_PIN_NOT_SET: +	case FIDO_ERR_SUCCESS: +		*touched = 1; +		break; +	case FIDO_ERR_RX: +		/* ignore */ +		break; +	default: +		fido_log_debug("%s: fido_rx_cbor_status", __func__); +		return (r); +	} + +	return (FIDO_OK); +} diff --git a/src/util.c b/src/util.c new file mode 100644 index 000000000000..61e120cfd06c --- /dev/null +++ b/src/util.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +#include <errno.h> +#include <stdint.h> +#include <stdlib.h> + +#include "fido.h" + +int +fido_to_uint64(const char *str, int base, uint64_t *out) +{ +	char *ep; +	unsigned long long ull; + +	errno = 0; +	ull = strtoull(str, &ep, base); +	if (str == ep || *ep != '\0') +		return -1; +	else if (ull == ULLONG_MAX && errno == ERANGE) +		return -1; +	else if (ull > UINT64_MAX) +		return -1; +	*out = (uint64_t)ull; + +	return 0; +} diff --git a/src/webauthn.h b/src/webauthn.h index 22bf6e346a73..e64236a0f6fe 100644 --- a/src/webauthn.h +++ b/src/webauthn.h @@ -92,6 +92,9 @@ extern "C" {  //          - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS    :   5
  //          - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS      :   6
  //          - WEBAUTHN_ASSERTION                                :   3
 +//      APIs:
 +//          - WebAuthNGetPlatformCredentialList
 +//          - WebAuthNFreePlatformCredentialList
  //
  #define WEBAUTHN_API_CURRENT_VERSION    WEBAUTHN_API_VERSION_4
 @@ -283,11 +286,64 @@ typedef struct _WEBAUTHN_CREDENTIAL_LIST {  typedef const WEBAUTHN_CREDENTIAL_LIST *PCWEBAUTHN_CREDENTIAL_LIST;
  //+------------------------------------------------------------------------------------------
 +// Credential Information for WebAuthNGetPlatformCredentialList API
 +//-------------------------------------------------------------------------------------------
 +
 +#define WEBAUTHN_CREDENTIAL_DETAILS_VERSION_1           1
 +#define WEBAUTHN_CREDENTIAL_DETAILS_CURRENT_VERSION     WEBAUTHN_CREDENTIAL_DETAILS_VERSION_1
 +
 +typedef struct _WEBAUTHN_CREDENTIAL_DETAILS {
 +    // Version of this structure, to allow for modifications in the future.
 +    DWORD dwVersion;
 +
 +    // Size of pbCredentialID.
 +    DWORD cbCredentialID;
 +    _Field_size_bytes_(cbCredentialID)
 +    PBYTE pbCredentialID;
 +
 +    // RP Info
 +    PWEBAUTHN_RP_ENTITY_INFORMATION     pRpInformation;
 +
 +    // User Info
 +    PWEBAUTHN_USER_ENTITY_INFORMATION   pUserInformation;
 +} WEBAUTHN_CREDENTIAL_DETAILS, *PWEBAUTHN_CREDENTIAL_DETAILS;
 +typedef const WEBAUTHN_CREDENTIAL_DETAILS *PCWEBAUTHN_CREDENTIAL_DETAILS;
 +
 +typedef struct _WEBAUTHN_CREDENTIAL_DETAILS_LIST {
 +    DWORD cCredentialDetails;
 +    _Field_size_(cCredentialDetails)
 +    PWEBAUTHN_CREDENTIAL_DETAILS *ppCredentialDetails;
 +} WEBAUTHN_CREDENTIAL_DETAILS_LIST, *PWEBAUTHN_CREDENTIAL_DETAILS_LIST;
 +typedef const WEBAUTHN_CREDENTIAL_DETAILS_LIST *PCWEBAUTHN_CREDENTIAL_DETAILS_LIST;
 +
 +#define WEBAUTHN_GET_CREDENTIALS_OPTIONS_VERSION_1          1
 +#define WEBAUTHN_GET_CREDENTIALS_OPTIONS_CURRENT_VERSION    WEBAUTHN_GET_CREDENTIALS_OPTIONS_VERSION_1
 +
 +typedef struct _WEBAUTHN_GET_CREDENTIALS_OPTIONS {
 +    // Version of this structure, to allow for modifications in the future.
 +    DWORD dwVersion;
 +
 +    // RPID
 +    LPCWSTR pwszRpId;
 +
 +    // Optional. BrowserInPrivate Mode. Defaulting to FALSE.
 +    BOOL bBrowserInPrivateMode;
 +} WEBAUTHN_GET_CREDENTIALS_OPTIONS, *PWEBAUTHN_GET_CREDENTIALS_OPTIONS;
 +typedef const WEBAUTHN_GET_CREDENTIALS_OPTIONS *PCWEBAUTHN_GET_CREDENTIALS_OPTIONS;
 +
 +//+------------------------------------------------------------------------------------------
  // PRF values.
  //-------------------------------------------------------------------------------------------
  #define WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH    32
 +// SALT values below by default are converted into RAW Hmac-Secret values as per PRF extension.
 +//   - SHA-256(UTF8Encode("WebAuthn PRF") || 0x00 || Value)
 +//
 +// Set WEBAUTHN_CTAP_HMAC_SECRET_VALUES_FLAG in dwFlags in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS,
 +//   if caller wants to provide RAW Hmac-Secret SALT values directly. In that case,
 +//   values if provided MUST be of WEBAUTHN_CTAP_ONE_HMAC_SECRET_LENGTH size.
 +
  typedef struct _WEBAUTHN_HMAC_SECRET_SALT {
      // Size of pbFirst.
      DWORD cbFirst;
 @@ -545,6 +601,12 @@ typedef const WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS *PCWEBAUTHN_AUTHENT  #define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6          6
  #define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_CURRENT_VERSION    WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_6
 +/*
 +    Information about flags.
 +*/
 +
 +#define WEBAUTHN_AUTHENTICATOR_HMAC_SECRET_VALUES_FLAG   0x00100000
 +
  typedef struct _WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS {
      // Version of this structure, to allow for modifications in the future.
      DWORD dwVersion;
 @@ -565,7 +627,7 @@ typedef struct _WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS {      // User Verification Requirement.
      DWORD dwUserVerificationRequirement;
 -    // Reserved for future Use
 +    // Flags
      DWORD dwFlags;
      //
 @@ -879,6 +941,17 @@ WINAPI  WebAuthNCancelCurrentOperation(
      _In_ const GUID* pCancellationId);
 +HRESULT
 +WINAPI
 +WebAuthNGetPlatformCredentialList(
 +    _In_    PCWEBAUTHN_GET_CREDENTIALS_OPTIONS                  pGetCredentialsOptions,
 +    _Outptr_result_maybenull_ PWEBAUTHN_CREDENTIAL_DETAILS_LIST *ppCredentialDetailsList);
 +
 +void
 +WINAPI
 +WebAuthNFreePlatformCredentialList(
 +    _In_ PWEBAUTHN_CREDENTIAL_DETAILS_LIST  pCredentialDetailsList);
 +
  //
  // Returns the following Error Names:
  //  L"Success"              - S_OK
 diff --git a/src/winhello.c b/src/winhello.c index 9de6c6c9b983..f9ab6061fd60 100644 --- a/src/winhello.c +++ b/src/winhello.c @@ -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 @@ pack_cred_ext(WEBAUTHN_EXTENSIONS *out, const fido_cred_ext_t *in)  }  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 @@ unpack_user_id(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)  }  static int +unpack_hmac_secret(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa) +{ +	if (wa->dwVersion != WEBAUTHN_ASSERTION_VERSION_3) { +		fido_log_debug("%s: dwVersion %u", __func__, +		    (unsigned)wa->dwVersion); +		return 0; /* proceed without hmac-secret */ +	} +	if (wa->pHmacSecret == NULL || +	    wa->pHmacSecret->cbFirst == 0 || +	    wa->pHmacSecret->cbFirst > SIZE_MAX || +	    wa->pHmacSecret->pbFirst == NULL) { +		fido_log_debug("%s: hmac-secret absent", __func__); +		return 0; /* proceed without hmac-secret */ +	} +	if (wa->pHmacSecret->cbSecond != 0 || +	    wa->pHmacSecret->pbSecond != NULL) { +		fido_log_debug("%s: 64-byte hmac-secret", __func__); +		return 0; /* proceed without hmac-secret */ +	} +	if (!fido_blob_is_empty(&assert->stmt[0].hmac_secret)) { +		fido_log_debug("%s: fido_blob_is_empty", __func__); +		return -1; +	} +	if (fido_blob_set(&assert->stmt[0].hmac_secret, +	    wa->pHmacSecret->pbFirst, (size_t)wa->pHmacSecret->cbFirst) < 0) { +		fido_log_debug("%s: fido_blob_set", __func__); +		return -1; +	} + +	return 0; +} + +static int  translate_fido_assert(struct winhello_assert *ctx, const fido_assert_t *assert,      const char *pin, int ms)  { @@ -510,11 +579,6 @@ translate_fido_assert(struct winhello_assert *ctx, const fido_assert_t *assert,  		fido_log_debug("%s: up %d", __func__, assert->up);  		return FIDO_ERR_UNSUPPORTED_OPTION;  	} -	/* not implemented */ -	if (assert->ext.mask) { -		fido_log_debug("%s: ext 0x%x", __func__, assert->ext.mask); -		return FIDO_ERR_UNSUPPORTED_EXTENSION; -	}  	if ((ctx->rp_id = to_utf16(assert->rp_id)) == NULL) {  		fido_log_debug("%s: rp_id", __func__);  		return FIDO_ERR_INTERNAL; @@ -531,6 +595,10 @@ translate_fido_assert(struct winhello_assert *ctx, const fido_assert_t *assert,  		fido_log_debug("%s: pack_credlist", __func__);  		return FIDO_ERR_INTERNAL;  	} +	if (pack_assert_ext(opt, &assert->ext) < 0) { +		fido_log_debug("%s: pack_assert_ext", __func__); +		return FIDO_ERR_UNSUPPORTED_EXTENSION; +	}  	if (set_assert_uv(&opt->dwUserVerificationRequirement, assert->uv,  	    pin) < 0) {  		fido_log_debug("%s: set_assert_uv", __func__); @@ -570,6 +638,11 @@ translate_winhello_assert(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)  		fido_log_debug("%s: unpack_user_id", __func__);  		return FIDO_ERR_INTERNAL;  	} +	if (assert->ext.mask & FIDO_EXT_HMAC_SECRET && +	    unpack_hmac_secret(assert, wa) < 0) { +		fido_log_debug("%s: unpack_hmac_secret", __func__); +		return FIDO_ERR_INTERNAL; +	}  	return FIDO_OK;  } @@ -742,6 +815,9 @@ winhello_assert_free(struct winhello_assert *ctx)  	free(ctx->rp_id);  	free(ctx->opt.CredentialList.pCredentials); +	if (ctx->opt.pHmacSecretSaltValues != NULL) +		free(ctx->opt.pHmacSecretSaltValues->pGlobalHmacSalt); +	free(ctx->opt.pHmacSecretSaltValues);  	free(ctx);  } @@ -883,7 +959,7 @@ fido_winhello_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)  	const char *v[3] = { "U2F_V2", "FIDO_2_0", "FIDO_2_1_PRE" };  	const char *e[2] = { "credProtect", "hmac-secret" };  	const char *t[2] = { "nfc", "usb" }; -	const char *o[4] = { "rk", "up", "plat", "clientPin" }; +	const char *o[4] = { "rk", "up", "uv", "plat" };  	(void)dev; diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index f37aa1d87c97..c81397f41fb9 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -65,13 +65,6 @@ add_executable(fido2-token  	${COMPAT_SOURCES}  ) -# set the library to link against -if(BUILD_SHARED_LIBS) -	set(_FIDO2_LIBRARY fido2_shared) -else() -	set(_FIDO2_LIBRARY fido2) -endif() -  target_link_libraries(fido2-cred ${CRYPTO_LIBRARIES} ${_FIDO2_LIBRARY})  target_link_libraries(fido2-assert ${CRYPTO_LIBRARIES} ${_FIDO2_LIBRARY})  target_link_libraries(fido2-token ${CRYPTO_LIBRARIES} ${_FIDO2_LIBRARY}) diff --git a/tools/token.c b/tools/token.c index 3d165623fdbf..9124e7b7fd29 100644 --- a/tools/token.c +++ b/tools/token.c @@ -156,6 +156,12 @@ print_maxcredidlen(uint64_t maxcredidlen)  }  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 @@ token_info(int argc, char **argv, char *path)  	/* print maximum length of a credential ID */  	print_maxcredidlen(fido_cbor_info_maxcredidlen(ci)); +	/* print maximum length of serialized largeBlob array */ +	print_maxlargeblob(fido_cbor_info_maxlargeblob(ci)); +  	/* print firmware version */  	print_fwversion(fido_cbor_info_fwversion(ci)); diff --git a/udev/70-u2f.rules b/udev/70-u2f.rules index 0dfc3e276c7a..6e1f88bbd042 100644 --- a/udev/70-u2f.rules +++ b/udev/70-u2f.rules @@ -106,6 +106,9 @@ KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct  # SatoshiLabs TREZOR by pid.codes  KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="53c1", TAG+="uaccess", GROUP="plugdev", MODE="0660" +# SoloKeys v2 by pid.codes +KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="beee", TAG+="uaccess", GROUP="plugdev", MODE="0660" +  # Google Titan U2F by Google Inc.  KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="5026", TAG+="uaccess", GROUP="plugdev", MODE="0660" diff --git a/udev/fidodevs b/udev/fidodevs index cea60a0be9fb..d519acd2ca73 100644 --- a/udev/fidodevs +++ b/udev/fidodevs @@ -72,6 +72,7 @@ product SILICON		0x8acf	U2F Zero  product PIDCODES	0x5070	SoloKeys SoloHacker  product PIDCODES	0x50b0	SoloKeys SoloBoot  product PIDCODES	0x53c1	SatoshiLabs TREZOR +product PIDCODES	0xbeee	SoloKeys v2  product GOOGLE		0x5026	Google Titan U2F diff --git a/windows/build.ps1 b/windows/build.ps1 index 56302444c80b..bd63c7f21095 100644 --- a/windows/build.ps1 +++ b/windows/build.ps1 @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Yubico AB. All rights reserved. +# Copyright (c) 2021-2022 Yubico AB. All rights reserved.  # Use of this source code is governed by a BSD-style  # license that can be found in the LICENSE file. @@ -187,17 +187,15 @@ try {  	& $CMake --build . --config ${Config} --verbose; ExitOnError  	& $CMake --build . --config ${Config} --target install --verbose; `  	    ExitOnError -	# Patch up zlib's resulting names when built with --config Debug. -	if ("${Config}" -eq "Debug") { -		if ("${Type}" -eq "Dynamic") { -			Copy-Item "${PREFIX}/lib/zlibd.lib" ` -			    -Destination "${PREFIX}/lib/zlib.lib" -Force -			Copy-Item "${PREFIX}/bin/zlibd1.dll" ` -			    -Destination "${PREFIX}/bin/zlib1.dll" -Force -		} else { -			Copy-Item "${PREFIX}/lib/zlibstaticd.lib" ` -			    -Destination "${PREFIX}/lib/zlib.lib" -Force -		} +	# Patch up zlib's various names. +	if ("${Type}" -eq "Dynamic") { +		((Get-ChildItem -Path "${PREFIX}/lib") -Match "zlib[d]?.lib") | +		    Copy-Item -Destination "${PREFIX}/lib/zlib1.lib" -Force +		((Get-ChildItem -Path "${PREFIX}/bin") -Match "zlibd1.dll") | +		    Copy-Item -Destination "${PREFIX}/bin/zlib1.dll" -Force +	} else { +		((Get-ChildItem -Path "${PREFIX}/lib") -Match "zlibstatic[d]?.lib") | +		    Copy-item -Destination "${PREFIX}/lib/zlib1.lib" -Force  	}  } catch {  	throw "Failed to build zlib" @@ -225,11 +223,13 @@ try {  	    -DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `  	    ExitOnError  	& $CMake --build . --config ${Config} --verbose; ExitOnError +	& $CMake --build . --config ${Config} --target regress --verbose; ` +	    ExitOnError  	& $CMake --build . --config ${Config} --target install --verbose; `  	    ExitOnError  	# Copy DLLs.  	if ("${SHARED}" -eq "ON") { -		"cbor.dll", "crypto-47.dll", "zlib1.dll" | ` +		"cbor.dll", "crypto-49.dll", "zlib1.dll" | `  		    %{ Copy-Item "${PREFIX}\bin\$_" `  		    -Destination "examples\${Config}" }  	} diff --git a/windows/const.ps1 b/windows/const.ps1 index 4aac8bb2853e..8acc2b2e829a 100644 --- a/windows/const.ps1 +++ b/windows/const.ps1 @@ -6,7 +6,7 @@  New-Variable -Name 'LIBRESSL_URL' `      -Value 'https://fastly.cdn.openbsd.org/pub/OpenBSD/LibreSSL' `      -Option Constant -New-Variable -Name 'LIBRESSL' -Value 'libressl-3.4.2' -Option Constant +New-Variable -Name 'LIBRESSL' -Value 'libressl-3.5.2' -Option Constant  # libcbor coordinates.  New-Variable -Name 'LIBCBOR' -Value 'libcbor-0.9.0' -Option Constant @@ -15,8 +15,8 @@ New-Variable -Name 'LIBCBOR_GIT' -Value 'https://github.com/pjk/libcbor' `      -Option Constant  # zlib coordinates. -New-Variable -Name 'ZLIB' -Value 'zlib-1.2.11' -Option Constant -New-Variable -Name 'ZLIB_BRANCH' -Value 'v1.2.11' -Option Constant +New-Variable -Name 'ZLIB' -Value 'zlib-1.2.12' -Option Constant +New-Variable -Name 'ZLIB_BRANCH' -Value 'v1.2.12' -Option Constant  New-Variable -Name 'ZLIB_GIT' -Value 'https://github.com/madler/zlib' `      -Option Constant diff --git a/windows/cygwin.ps1 b/windows/cygwin.ps1 index aada60b6f06f..6e602b6d9474 100755 --- a/windows/cygwin.ps1 +++ b/windows/cygwin.ps1 @@ -66,3 +66,4 @@ Start-Process "${Cygwin}\${Setup}" -Wait -NoNewWindow `  $Env:PATH = "${Root}\bin\;" + $Env:PATH  cmake "-DCMAKE_BUILD_TYPE=${Config}" -B "build-${Config}"  make -C "build-${Config}" +make -C "build-${Config}" regress diff --git a/windows/release.ps1 b/windows/release.ps1 index 9221bcaa3413..6f3f4e9600df 100644 --- a/windows/release.ps1 +++ b/windows/release.ps1 @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Yubico AB. All rights reserved. +# Copyright (c) 2021-2022 Yubico AB. All rights reserved.  # Use of this source code is governed by a BSD-style  # license that can be found in the LICENSE file. @@ -7,7 +7,7 @@ $Architectures = @('x64', 'Win32', 'ARM64', 'ARM')  $InstallPrefixes =  @('Win64', 'Win32', 'ARM64', 'ARM')  $Types = @('dynamic', 'static')  $Config = 'Release' -$LibCrypto = '47' +$LibCrypto = '49'  $SDK = '143'  . "$PSScriptRoot\const.ps1" @@ -34,7 +34,7 @@ Function Package-Dynamic(${SRC}, ${DEST}) {  	Copy-Item "${SRC}\bin\cbor.dll" "${DEST}"  	Copy-Item "${SRC}\lib\cbor.lib" "${DEST}"  	Copy-Item "${SRC}\bin\zlib1.dll" "${DEST}" -	Copy-Item "${SRC}\lib\zlib.lib" "${DEST}" +	Copy-Item "${SRC}\lib\zlib1.lib" "${DEST}"  	Copy-Item "${SRC}\bin\crypto-${LibCrypto}.dll" "${DEST}"  	Copy-Item "${SRC}\lib\crypto-${LibCrypto}.lib" "${DEST}"  	Copy-Item "${SRC}\bin\fido2.dll" "${DEST}" @@ -43,7 +43,7 @@ Function Package-Dynamic(${SRC}, ${DEST}) {  Function Package-Static(${SRC}, ${DEST}) {  	Copy-Item "${SRC}/lib/cbor.lib" "${DEST}" -	Copy-Item "${SRC}/lib/zlib.lib" "${DEST}" +	Copy-Item "${SRC}/lib/zlib1.lib" "${DEST}"  	Copy-Item "${SRC}/lib/crypto-${LibCrypto}.lib" "${DEST}"  	Copy-Item "${SRC}/lib/fido2_static.lib" "${DEST}/fido2.lib"  } @@ -54,19 +54,19 @@ Function Package-PDBs(${SRC}, ${DEST}) {  	Copy-Item "${SRC}\${LIBCBOR}\src\cbor.dir\${Config}\vc${SDK}.pdb" `  	    "${DEST}\cbor.pdb"  	Copy-Item "${SRC}\${ZLIB}\zlib.dir\${Config}\vc${SDK}.pdb" ` -	    "${DEST}\zlib.pdb" +	    "${DEST}\zlib1.pdb"  	Copy-Item "${SRC}\src\fido2_shared.dir\${Config}\vc${SDK}.pdb" `  	    "${DEST}\fido2.pdb"  }  Function Package-StaticPDBs(${SRC}, ${DEST}) { -	Copy-Item "${SRC}\${LIBRESSL}\crypto\Release\crypto-${LibCrypto}.pdb" ` +	Copy-Item "${SRC}\${LIBRESSL}\crypto\crypto_obj.dir\${Config}\crypto_obj.pdb" `  	    "${DEST}\crypto-${LibCrypto}.pdb" -	Copy-Item "${SRC}\${LIBCBOR}\src\Release\cbor.pdb" ` +	Copy-Item "${SRC}\${LIBCBOR}\src\${Config}\cbor.pdb" `  	    "${DEST}\cbor.pdb" -	Copy-Item "${SRC}\${ZLIB}\Release\zlibstatic.pdb" ` -	    "${DEST}\zlib.pdb" -	Copy-Item "${SRC}\src\Release\fido2_static.pdb" ` +	Copy-Item "${SRC}\${ZLIB}\${Config}\zlibstatic.pdb" ` +	    "${DEST}\zlib1.pdb" +	Copy-Item "${SRC}\src\${Config}\fido2_static.pdb" `  	    "${DEST}\fido2.pdb"  } | 
