libfido2: Update to 1.16.0

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Ed Maste
2026-04-07 09:14:41 -04:00
82 changed files with 3140 additions and 1406 deletions
+4 -2
View File
@@ -15,7 +15,7 @@ cat > "${MANIFEST}" <<- EOF
image: ${IMAGE}
packages:
- cmake
- llvm
- llvm${LLVM_VERSION:+%${LLVM_VERSION}}
- pcsc-lite
EOF
@@ -38,7 +38,7 @@ tasks:
else
SUDO=sudo
fi
SCAN="/usr/local/bin/scan-build --use-cc=/usr/bin/cc --status-bugs"
SCAN="/usr/local/bin/scan-build${LLVM_VERSION:+-${LLVM_VERSION}} --use-cc=/usr/bin/cc --status-bugs"
cd libfido2
for T in Debug Release; do
mkdir build-\$T
@@ -60,6 +60,7 @@ q() {
}
submit_job() {
# shellcheck disable=SC3043
local manifest="$1"
jq \
--compact-output --null-input \
@@ -71,6 +72,7 @@ submit_job() {
}
job_status() {
# shellcheck disable=SC3043
local id="$1"
jq \
--compact-output --null-input \
@@ -1,6 +1,6 @@
#!/bin/sh -eux
# Copyright (c) 2022-2023 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -23,7 +23,7 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
EOF
# Build and install libcbor.
git clone --depth=1 https://github.com/pjk/libcbor -b v0.10.1
git clone --depth=1 https://github.com/pjk/libcbor -b v0.12.0
cd libcbor
mkdir build
(cd build && cmake -DCMAKE_TOOLCHAIN_FILE=/tmp/mingw.cmake \
@@ -42,7 +42,7 @@ sudo make install_sw
cd ..
# Build and install zlib.
git clone --depth=1 https://github.com/madler/zlib -b v1.3
git clone --depth=1 https://github.com/madler/zlib -b v1.3.1
cd zlib
make -fwin32/Makefile.gcc PREFIX=i686-w64-mingw32-
sudo make -fwin32/Makefile.gcc PREFIX=i686-w64-mingw32- DESTDIR=/fakeroot \
@@ -1,6 +1,6 @@
#!/bin/sh -eux
# Copyright (c) 2022 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -12,8 +12,8 @@ FAKEROOT="$(mktemp -d)"
# Check exports.
(cd src && ./diff_exports.sh)
# Build and install OpenSSL 3.0.12.
git clone --branch openssl-3.0.12 \
# Build and install OpenSSL 3.0.15.
git clone --branch openssl-3.0.15 \
--depth=1 https://github.com/openssl/openssl
cd openssl
./Configure linux-x86_64-clang --prefix="${FAKEROOT}" \
@@ -1,6 +1,6 @@
#!/bin/sh -eux
# Copyright (c) 2022 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -8,8 +8,8 @@
${CC} --version
FAKEROOT="$(mktemp -d)"
# Build and install OpenSSL 3.0.12.
git clone --branch openssl-3.0.12 \
# Build and install OpenSSL 3.0.15.
git clone --branch openssl-3.0.15 \
--depth=1 https://github.com/openssl/openssl
cd openssl
./Configure linux-x86_64 --prefix="${FAKEROOT}" \
@@ -1,6 +1,6 @@
#!/bin/sh -eux
# Copyright (c) 2022-2023 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -23,7 +23,7 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
EOF
# Build and install libcbor.
git clone --depth=1 https://github.com/pjk/libcbor -b v0.10.1
git clone --depth=1 https://github.com/pjk/libcbor -b v0.12.0
cd libcbor
mkdir build
(cd build && cmake -DCMAKE_TOOLCHAIN_FILE=/tmp/mingw.cmake \
@@ -32,8 +32,8 @@ make -j"$(nproc)" -C build
sudo make -C build install
cd ..
# Build and install OpenSSL 3.0.11.
git clone --branch openssl-3.0.12 \
# Build and install OpenSSL 3.0.15.
git clone --branch openssl-3.0.15 \
--depth=1 https://github.com/openssl/openssl
cd openssl
./Configure mingw --prefix=/fakeroot --openssldir=/fakeroot/openssl \
@@ -43,7 +43,7 @@ sudo make install_sw
cd ..
# Build and install zlib.
git clone --depth=1 https://github.com/madler/zlib -b v1.3
git clone --depth=1 https://github.com/madler/zlib -b v1.3.1
cd zlib
make -fwin32/Makefile.gcc PREFIX=i686-w64-mingw32-
sudo make -fwin32/Makefile.gcc PREFIX=i686-w64-mingw32- DESTDIR=/fakeroot \
+2 -1
View File
@@ -5,7 +5,8 @@
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
export PKG_CONFIG_PATH="$(brew --prefix openssl@3.0)/lib/pkgconfig"
PKG_CONFIG_PATH="$(brew --prefix openssl@3.0)/lib/pkgconfig"
export PKG_CONFIG_PATH
SCAN="$(brew --prefix llvm)/bin/scan-build"
# Build, analyze, and install libfido2.
+7 -6
View File
@@ -1,18 +1,18 @@
#!/bin/sh -eux
# Copyright (c) 2020-2022 Yubico AB. All rights reserved.
# Copyright (c) 2020-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
LIBCBOR_URL="https://github.com/pjk/libcbor"
LIBCBOR_TAG="v0.10.2"
LIBCBOR_TAG="v0.12.0"
LIBCBOR_ASAN="address alignment bounds"
LIBCBOR_MSAN="memory"
OPENSSL_URL="https://github.com/openssl/openssl"
OPENSSL_TAG="openssl-3.0.12"
OPENSSL_TAG="openssl-3.0.15"
ZLIB_URL="https://github.com/madler/zlib"
ZLIB_TAG="v1.3"
ZLIB_TAG="v1.3.1"
ZLIB_ASAN="address alignment bounds undefined"
ZLIB_MSAN="memory"
FIDO2_ASAN="address bounds fuzzer-no-link implicit-conversion leak"
@@ -63,6 +63,7 @@ git clone --depth=1 "${OPENSSL_URL}" -b "${OPENSSL_TAG}"
cd openssl
./Configure linux-x86_64-clang "enable-$1" --prefix="${FAKEROOT}" \
--openssldir="${FAKEROOT}/openssl" --libdir=lib
make -j"$(nproc)" build_sw
make install_sw
cd -
@@ -71,7 +72,7 @@ git clone --depth=1 "${ZLIB_URL}" -b "${ZLIB_TAG}"
cd zlib
CFLAGS="${ZLIB_CFLAGS}" LDFLAGS="${ZLIB_CFLAGS}" ./configure \
--prefix="${FAKEROOT}"
make install
make -j"$(nproc)" install
cd -
# libfido2
@@ -87,7 +88,7 @@ mkdir corpus
curl -s https://storage.googleapis.com/yubico-libfido2/corpus.tgz |
tar -C corpus -zxf -
export UBSAN_OPTIONS ASAN_OPTIONS MSAN_OPTIONS
for f in assert bio cred credman hid largeblob mgmt netlink pcsc; do
for f in assert attobj bio cred credman hid largeblob mgmt netlink pcsc; do
build/fuzz/fuzz_${f} -use_value_profile=1 -reload=30 -print_pcs=1 \
-print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_${f}
done
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh -u
# Copyright (c) 2024 Google LLC. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
LIST="$(mktemp)"
trap 'rm -- $LIST' EXIT
git ls-files | while read -r file; do
if head -n1 "$file" | grep -q '^#!.*sh'; then
if ! shellcheck -Cnever --norc "$file"; then
echo "$file" >> "$LIST"
fi
fi
done
[ -s "$LIST" ] && {
echo "The following files contain errors:"
cat "$LIST"
exit 1
} 1>&2
exit 0
+2 -2
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2022-2023 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -16,7 +16,7 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
container: alpine:latest
strategy:
fail-fast: false
+6 -3
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2022 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -14,11 +14,13 @@ on:
jobs:
build:
if: github.repository == 'Yubico/libfido2'
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
image: [freebsd/13.x, openbsd/7.2]
include:
- { image: freebsd/14.x }
- { image: openbsd/7.6, llvm_version: 16 }
steps:
- uses: actions/checkout@v4
- name: dependencies
@@ -27,6 +29,7 @@ jobs:
sudo apt install -q -y curl jq
- name: build
env:
LLVM_VERSION: ${{ matrix.llvm_version }}
IMAGE: ${{ matrix.image }}
SOURCEHUT_TOKEN: ${{ secrets.SOURCEHUT_TOKEN }}
run: ./.actions/build-bsd
+3 -3
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2022 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -17,7 +17,7 @@ on:
jobs:
fuzzing:
if: github.repository == 'Yubico/libfido2'
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
@@ -39,7 +39,7 @@ jobs:
fuzz-seconds: 600
dry-run: false
- name: upload crash
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: failure()
with:
name: ${{ matrix.sanitizer }}-artifacts
+4 -4
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2022 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -22,14 +22,14 @@ permissions:
jobs:
codeql-build:
if: github.repository == 'Yubico/libfido2'
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: init codeql
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
- name: build
env:
CC: gcc
@@ -39,4 +39,4 @@ jobs:
libpcsclite-dev
./.actions/build-linux-gcc
- name: perform codeql analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
+7 -8
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2022 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -21,17 +21,16 @@ jobs:
fail-fast: false
matrix:
include:
- { os: ubuntu-20.04, cc: gcc-8 }
- { os: ubuntu-22.04, cc: gcc-9 }
- { os: ubuntu-22.04, cc: gcc-10 }
- { os: ubuntu-22.04, cc: gcc-11 }
- { os: ubuntu-22.04, cc: gcc-12 }
- { os: ubuntu-22.04, cc: clang-13 }
- { os: ubuntu-22.04, cc: clang-14 }
- { os: ubuntu-22.04, cc: clang-15 }
- { os: ubuntu-24.04, cc: gcc-12 }
- { os: ubuntu-24.04, cc: gcc-13 }
- { os: ubuntu-22.04, cc: clang-16 }
- { os: ubuntu-20.04, cc: i686-w64-mingw32-gcc-9 }
- { os: ubuntu-22.04, cc: clang-17 }
- { os: ubuntu-24.04, cc: clang-18 }
- { os: ubuntu-24.04, cc: clang-19 }
- { os: ubuntu-22.04, cc: i686-w64-mingw32-gcc-10 }
- { os: ubuntu-24.04, cc: i686-w64-mingw32-gcc-11 }
steps:
- uses: actions/checkout@v4
- name: dependencies
+3 -3
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2022 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -20,8 +20,8 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-22.04 ]
cc: [ clang-16 ]
os: [ ubuntu-24.04 ]
cc: [ clang-19 ]
sanitizer: [ asan, msan ]
steps:
- uses: actions/checkout@v4
+3 -1
View File
@@ -20,11 +20,13 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ macos-13, macos-12 ]
os: [ macos-15, macos-14, macos-13 ]
cc: [ clang ]
steps:
- uses: actions/checkout@v4
- name: dependencies
env:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
run: brew install libcbor llvm mandoc openssl@3.0 pkg-config zlib
- name: build
env:
+7 -7
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2022 Yubico AB. All rights reserved.
# Copyright (c) 2022-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -21,12 +21,12 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-22.04
cc: gcc-11
- os: ubuntu-22.04
cc: clang-16
- os: ubuntu-22.04
cc: i686-w64-mingw32-gcc-10
- os: ubuntu-24.04
cc: gcc-13
- os: ubuntu-24.04
cc: clang-19
- os: ubuntu-24.04
cc: i686-w64-mingw32-gcc-11
steps:
- uses: actions/checkout@v4
- name: dependencies
+27
View File
@@ -0,0 +1,27 @@
# Copyright (c) 2024 Google LLC. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
name: shellcheck
on:
pull_request:
branches:
- main
push:
branches:
- main
- '*-ci'
jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: dependencies
run: |
sudo apt -q update
sudo apt install -q -y shellcheck
- name: build
run: ./.actions/run-shellcheck
+10 -2
View File
@@ -28,8 +28,10 @@ endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_COLOR_MAKEFILE OFF)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(FIDO_MAJOR "1")
set(FIDO_MINOR "14")
set(FIDO_MINOR "16")
set(FIDO_PATCH "0")
set(FIDO_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}.${FIDO_PATCH})
@@ -190,6 +192,9 @@ if(MSVC)
if(NOT CRYPTO_LIBRARIES)
set(CRYPTO_LIBRARIES crypto)
endif()
if(NOT CRYPTO_DLL)
set(CRYPTO_DLL crypto)
endif()
set(MSVC_DISABLED_WARNINGS_LIST
"C4152" # nonstandard extension used: function/data pointer
@@ -435,6 +440,9 @@ message(STATUS "CRYPTO_LIBRARY_DIRS: ${CRYPTO_LIBRARY_DIRS}")
if(BUILD_TESTS)
message(STATUS "CRYPTO_BIN_DIRS: ${CRYPTO_BIN_DIRS}")
endif()
if(MSVC)
message(STATUS "CRYPTO_DLL: ${CRYPTO_DLL}")
endif()
message(STATUS "CRYPTO_VERSION: ${CRYPTO_VERSION}")
message(STATUS "FIDO_VERSION: ${FIDO_VERSION}")
message(STATUS "FUZZ: ${FUZZ}")
@@ -484,7 +492,7 @@ endif()
if(BUILD_TOOLS)
add_subdirectory(tools)
endif()
if(BUILD_MANPAGES)
if(BUILD_MANPAGES AND NOT MSVC)
add_subdirectory(man)
endif()
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2018-2023 Yubico AB. All rights reserved.
Copyright (c) 2018-2024 Yubico AB. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
+25 -3
View File
@@ -1,12 +1,34 @@
* Version 1.16.0 (2025-05-06)
** Added support for enterprise attestation.
** Improved handling of invalid key handles in U2F key lookup; gh#819.
** Fixed issue where storing small CTAP 2.1 largeBlobs failed; gh#826.
** Fixed APDU chaining issues for certain authenticators; gh#818, gh#855.
** Improved documentation and examples.
** New API calls:
- fido_cred_entattest;
- fido_cred_set_entattest.
* Version 1.15.0 (2024-06-13)
** 1.15.0 will be the last release to support OpenSSL 1.1.
** bio, credman: improved CTAP 2.1 support.
** hid_osx: fix issue where fido_hid_read() may block unnecessarily; gh#757.
** fido2-token -I: print maxcredbloblen.
** hid_linux: improved support for uhid devices.
** New API calls:
- fido_cred_set_attobj;
- fido_cred_x5c_list_count;
- fido_cred_x5c_list_len;
- fido_cred_x5c_list_ptr.
* Version 1.14.0 (2023-11-13)
** fido2-cred -M, fido2-token -G: support raw client data via -w flag.
** winhello: support U2F AppID extension for assertions.
** winhello: fix restrictive parsing of the hmac-secret on assertions.
** winhello: translate NTE_USER_CANCELLED to FIDO_ERR_OPERATION_DENIED; gh#685.
** New API calls:
** fido_assert_authdata_raw_len;
** fido_assert_authdata_raw_ptr;
** fido_assert_set_winhello_appid.
- fido_assert_authdata_raw_len;
- fido_assert_authdata_raw_ptr;
- fido_assert_set_winhello_appid.
* Version 1.13.0 (2023-02-20)
** Support for linking against OpenSSL on Windows; gh#668.
+3 -3
View File
@@ -38,7 +38,7 @@ is also available.
=== Releases
The current release of *libfido2* is 1.14.0. Signed release tarballs are
The current release of *libfido2* is 1.16.0. Signed release tarballs are
available at Yubico's
https://developers.yubico.com/libfido2/Releases[release page].
@@ -52,11 +52,11 @@ required.
=== Installation
==== Fedora 35 and 34
==== Fedora 34 and later
$ sudo dnf install libfido2 libfido2-devel fido2-tools
==== Ubuntu 22.04 (Jammy) and 20.04 (Focal)
==== Ubuntu 20.04 (Focal) and later
$ sudo apt install libfido2-1 libfido2-dev libfido2-doc fido2-tools
+1 -1
View File
@@ -2,4 +2,4 @@
To report security issues in libfido2, please contact security@yubico.com.
A PGP public key can be found at
https://www.yubico.com/support/security-advisories/issue-rating-system/.
https://www.yubico.com/support/issue-rating-system/.
+2 -1
View File
@@ -64,7 +64,8 @@ The following examples are provided:
The -T option may be used to enforce a timeout of <seconds>. If the
option -b is specified, the credential's "largeBlob" key is stored in
<blobkey>. If the option -c is specified the the generated credential
will be bound by the specified protection policy.
will be bound by the specified protection policy. If the option -a is
specified, enterprise attestation will be requested.
- assert [-t es256|es384|rs256|eddsa] [-a cred_id] [-h hmac_secret] [-P pin]
[-s hmac_salt] [-T seconds] [-b blobkey] [-puv] <pubkey> <device>
+22 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2023 Yubico AB. All rights reserved.
* Copyright (c) 2018-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -36,7 +36,8 @@ static void
usage(void)
{
fprintf(stderr, "usage: cred [-t es256|es384|rs256|eddsa] [-k pubkey] "
"[-ei cred_id] [-P pin] [-T seconds] [-b blobkey] [-c cred_protect] [-hruv] "
"[-ei cred_id] [-P pin] [-T seconds] [-b blobkey] [-c cred_protect] "
"[-a mode] [-hruv] "
"<device>\n");
exit(EXIT_FAILURE);
}
@@ -106,9 +107,13 @@ verify_cred(int type, const char *fmt, const unsigned char *authdata_ptr,
if (r != FIDO_OK)
errx(1, "fido_cred_set_attstmt: %s (0x%x)", fido_strerr(r), r);
r = fido_cred_verify(cred);
if (r != FIDO_OK)
errx(1, "fido_cred_verify: %s (0x%x)", fido_strerr(r), r);
if (fido_cred_x5c_ptr(cred) == NULL) {
if ((r = fido_cred_verify_self(cred)) != FIDO_OK)
errx(1, "fido_cred_verify_self: %s (0x%x)", fido_strerr(r), r);
} else {
if ((r = fido_cred_verify(cred)) != FIDO_OK)
errx(1, "fido_cred_verify: %s (0x%x)", fido_strerr(r), r);
}
out:
if (key_out != NULL) {
@@ -166,11 +171,12 @@ main(int argc, char **argv)
int ch;
int r;
long long cred_protect = 0;
long long ea = 0;
if ((cred = fido_cred_new()) == NULL)
errx(1, "fido_cred_new");
while ((ch = getopt(argc, argv, "P:T:b:e:hi:k:rt:uvc:")) != -1) {
while ((ch = getopt(argc, argv, "P:T:a:b:e:hi:k:rt:uvc:")) != -1) {
switch (ch) {
case 'P':
pin = optarg;
@@ -182,6 +188,12 @@ main(int argc, char **argv)
errx(1, "-T: %s must be in (0,30]", optarg);
ms *= 1000; /* seconds to milliseconds */
break;
case 'a':
if (base10(optarg, &ea) < 0)
errx(1, "base10: %s", optarg);
if (ea <= 0 || ea > 2)
errx(1, "-a: %s must be in (0,2]", optarg);
break;
case 'b':
ext |= FIDO_EXT_LARGEBLOB_KEY;
blobkey_out = optarg;
@@ -203,7 +215,7 @@ main(int argc, char **argv)
if (base10(optarg, &cred_protect) < 0)
errx(1, "base10: %s", optarg);
if (cred_protect <= 0 || cred_protect > 3)
errx(1, "-c: %s must be in (1,3)", optarg);
errx(1, "-c: %s must be in (0,3]", optarg);
ext |= FIDO_EXT_CRED_PROTECT;
break;
case 'i':
@@ -293,6 +305,9 @@ main(int argc, char **argv)
if (cred_protect != 0 && (r = fido_cred_set_prot(cred,
(int)cred_protect)) != FIDO_OK)
errx(1, "fido_cred_set_prot: %s (0x%x)", fido_strerr(r), r);
if (ea != 0 && (r = fido_cred_set_entattest(cred, (int)ea)) != FIDO_OK)
errx(1, "fido_cred_set_entattest: %s (0x%x)", fido_strerr(r), r);
/* timeout */
if (ms != 0 && (r = fido_dev_set_timeout(dev, (int)ms)) != FIDO_OK)
+12 -1
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2019-2023 Yubico AB. All rights reserved.
# Copyright (c) 2019-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -18,6 +18,10 @@ set(FUZZ_LINKER_LANGUAGE "C" CACHE STRING "Linker language for fuzz harnesses")
mark_as_advanced(FUZZ_LINKER_LANGUAGE)
enable_language(${FUZZ_LINKER_LANGUAGE})
if(NOT FUZZ_LDFLAGS)
message(FATAL_ERROR "Please define FUZZ_LDFLAGS")
endif()
# fuzz_cred
add_executable(fuzz_cred fuzz_cred.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
set_target_properties(fuzz_cred PROPERTIES
@@ -80,3 +84,10 @@ set_target_properties(fuzz_pcsc PROPERTIES
LINK_FLAGS ${FUZZ_LDFLAGS}
LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
target_link_libraries(fuzz_pcsc fido2_shared)
# fuzz_attobj
add_executable(fuzz_attobj fuzz_attobj.c ${COMMON_SOURCES} ${COMPAT_SOURCES})
set_target_properties(fuzz_attobj PROPERTIES
LINK_FLAGS ${FUZZ_LDFLAGS}
LINKER_LANGUAGE ${FUZZ_LINKER_LANGUAGE})
target_link_libraries(fuzz_attobj fido2_shared)
+1 -1
View File
@@ -10,7 +10,7 @@ RUN apk -q update
RUN apk add build-base clang clang-analyzer cmake compiler-rt coreutils
RUN apk add eudev-dev git linux-headers llvm openssl-dev pcsc-lite-dev
RUN apk add sudo tar zlib-dev
RUN git clone --branch v0.10.2 --depth=1 https://github.com/PJK/libcbor
RUN git clone --branch v0.12.0 --depth=1 https://github.com/PJK/libcbor
RUN git clone --depth=1 https://github.com/yubico/libfido2
WORKDIR /libfido2
RUN ./fuzz/build-coverage /libcbor /libfido2
+3 -3
View File
@@ -3,12 +3,12 @@
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
IMAGE := libfido2-coverage:1.14.0
IMAGE := libfido2-coverage:1.16.0
RUNNER := libfido2-runner
PROFDATA := llvm-profdata
COV := llvm-cov
TARGETS := fuzz_assert fuzz_bio fuzz_cred fuzz_credman fuzz_hid \
fuzz_largeblob fuzz_netlink fuzz_mgmt fuzz_pcsc
TARGETS := fuzz_assert fuzz_attobj fuzz_bio fuzz_cred fuzz_credman \
fuzz_hid fuzz_largeblob fuzz_netlink fuzz_mgmt fuzz_pcsc
CORPORA := $(foreach f,${TARGETS},${f}/corpus)
MINIFY := $(foreach f,${TARGETS},/minify/${f}/corpus)
REMOTE := gs://libfido2-corpus.clusterfuzz-external.appspot.com
+6
View File
@@ -127,6 +127,7 @@
fido_cred_clientdata_hash_len;
fido_cred_clientdata_hash_ptr;
fido_cred_display_name;
fido_cred_entattest;
fido_cred_exclude;
fido_cred_flags;
fido_cred_largeblob_key_len;
@@ -166,11 +167,13 @@
fido_cred_rp_id;
fido_cred_rp_name;
fido_cred_set_attstmt;
fido_cred_set_attobj;
fido_cred_set_authdata;
fido_cred_set_authdata_raw;
fido_cred_set_blob;
fido_cred_set_clientdata;
fido_cred_set_clientdata_hash;
fido_cred_set_entattest;
fido_cred_set_extensions;
fido_cred_set_fmt;
fido_cred_set_id;
@@ -193,6 +196,9 @@
fido_cred_verify;
fido_cred_verify_self;
fido_cred_x5c_len;
fido_cred_x5c_list_count;
fido_cred_x5c_list_len;
fido_cred_x5c_list_ptr;
fido_cred_x5c_ptr;
fido_dev_build;
fido_dev_cancel;
File diff suppressed because it is too large Load Diff
+333
View File
@@ -0,0 +1,333 @@
/*
* Copyright (c) 2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mutator_aux.h"
#include "wiredata_fido2.h"
#include "wiredata_u2f.h"
#include "dummy.h"
#include "../openbsd-compat/openbsd-compat.h"
struct param {
int seed;
char rp_id[MAXSTR];
struct blob cdh;
struct blob attobj;
uint8_t type;
};
static const uint8_t dummy_attestation_object[] = {
0xa3, 0x63, 0x66, 0x6d, 0x74, 0x66, 0x70, 0x61,
0x63, 0x6b, 0x65, 0x64, 0x67, 0x61, 0x74, 0x74,
0x53, 0x74, 0x6d, 0x74, 0xa3, 0x63, 0x61, 0x6c,
0x67, 0x26, 0x63, 0x73, 0x69, 0x67, 0x58, 0x46,
0x30, 0x44, 0x02, 0x20, 0x54, 0x92, 0x28, 0x3b,
0x83, 0x33, 0x47, 0x56, 0x68, 0x79, 0xb2, 0x0c,
0x84, 0x80, 0xcc, 0x67, 0x27, 0x8b, 0xfa, 0x48,
0x43, 0x0d, 0x3c, 0xb4, 0x02, 0x36, 0x87, 0x97,
0x3e, 0xdf, 0x2f, 0x65, 0x02, 0x20, 0x1b, 0x56,
0x17, 0x06, 0xe2, 0x26, 0x0f, 0x6a, 0xe9, 0xa9,
0x70, 0x99, 0x62, 0xeb, 0x3a, 0x04, 0x1a, 0xc4,
0xa7, 0x03, 0x28, 0x56, 0x7c, 0xed, 0x47, 0x08,
0x68, 0x73, 0x6a, 0xb6, 0x89, 0x0d, 0x63, 0x78,
0x35, 0x63, 0x81, 0x59, 0x02, 0xe6, 0x30, 0x82,
0x02, 0xe2, 0x30, 0x81, 0xcb, 0x02, 0x01, 0x01,
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30,
0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x12, 0x59, 0x75, 0x62, 0x69,
0x63, 0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, 0x54,
0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e,
0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x31, 0x35,
0x31, 0x32, 0x35, 0x38, 0x35, 0x34, 0x5a, 0x17,
0x0d, 0x31, 0x34, 0x30, 0x36, 0x31, 0x34, 0x31,
0x32, 0x35, 0x38, 0x35, 0x34, 0x5a, 0x30, 0x1d,
0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x12, 0x59, 0x75, 0x62, 0x69, 0x63,
0x6f, 0x20, 0x55, 0x32, 0x46, 0x20, 0x54, 0x65,
0x73, 0x74, 0x20, 0x45, 0x45, 0x30, 0x59, 0x30,
0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04,
0xdb, 0x0a, 0xdb, 0xf5, 0x21, 0xc7, 0x5c, 0xce,
0x63, 0xdc, 0xa6, 0xe1, 0xe8, 0x25, 0x06, 0x0d,
0x94, 0xe6, 0x27, 0x54, 0x19, 0x4f, 0x9d, 0x24,
0xaf, 0x26, 0x1a, 0xbe, 0xad, 0x99, 0x44, 0x1f,
0x95, 0xa3, 0x71, 0x91, 0x0a, 0x3a, 0x20, 0xe7,
0x3e, 0x91, 0x5e, 0x13, 0xe8, 0xbe, 0x38, 0x05,
0x7a, 0xd5, 0x7a, 0xa3, 0x7e, 0x76, 0x90, 0x8f,
0xaf, 0xe2, 0x8a, 0x94, 0xb6, 0x30, 0xeb, 0x9d,
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03,
0x82, 0x02, 0x01, 0x00, 0x95, 0x40, 0x6b, 0x50,
0x61, 0x7d, 0xad, 0x84, 0xa3, 0xb4, 0xeb, 0x88,
0x0f, 0xe3, 0x30, 0x0f, 0x2d, 0xa2, 0x0a, 0x00,
0xd9, 0x25, 0x04, 0xee, 0x72, 0xfa, 0x67, 0xdf,
0x58, 0x51, 0x0f, 0x0b, 0x47, 0x02, 0x9c, 0x3e,
0x41, 0x29, 0x4a, 0x93, 0xac, 0x29, 0x85, 0x89,
0x2d, 0xa4, 0x7a, 0x81, 0x32, 0x28, 0x57, 0x71,
0x01, 0xef, 0xa8, 0x42, 0x88, 0x16, 0x96, 0x37,
0x91, 0xd5, 0xdf, 0xe0, 0x8f, 0xc9, 0x3c, 0x8d,
0xb0, 0xcd, 0x89, 0x70, 0x82, 0xec, 0x79, 0xd3,
0xc6, 0x78, 0x73, 0x29, 0x32, 0xe5, 0xab, 0x6c,
0xbd, 0x56, 0x9f, 0xd5, 0x45, 0x91, 0xce, 0xc1,
0xdd, 0x8d, 0x64, 0xdc, 0xe9, 0x9c, 0x1f, 0x5e,
0x3c, 0xd2, 0xaf, 0x51, 0xa5, 0x82, 0x18, 0xaf,
0xe0, 0x37, 0xe7, 0x32, 0x9e, 0x76, 0x05, 0x77,
0x02, 0x7b, 0xe6, 0x24, 0xa0, 0x31, 0x56, 0x1b,
0xfd, 0x19, 0xc5, 0x71, 0xd3, 0xf0, 0x9e, 0xc0,
0x73, 0x05, 0x4e, 0xbc, 0x85, 0xb8, 0x53, 0x9e,
0xef, 0xc5, 0xbc, 0x9c, 0x56, 0xa3, 0xba, 0xd9,
0x27, 0x6a, 0xbb, 0xa9, 0x7a, 0x40, 0xd7, 0x47,
0x8b, 0x55, 0x72, 0x6b, 0xe3, 0xfe, 0x28, 0x49,
0x71, 0x24, 0xf4, 0x8f, 0xf4, 0x20, 0x81, 0xea,
0x38, 0xff, 0x7c, 0x0a, 0x4f, 0xdf, 0x02, 0x82,
0x39, 0x81, 0x82, 0x3b, 0xca, 0x09, 0xdd, 0xca,
0xaa, 0x0f, 0x27, 0xf5, 0xa4, 0x83, 0x55, 0x6c,
0x9a, 0x39, 0x9b, 0x15, 0x3a, 0x16, 0x63, 0xdc,
0x5b, 0xf9, 0xac, 0x5b, 0xbc, 0xf7, 0x9f, 0xbe,
0x0f, 0x8a, 0xa2, 0x3c, 0x31, 0x13, 0xa3, 0x32,
0x48, 0xca, 0x58, 0x87, 0xf8, 0x7b, 0xa0, 0xa1,
0x0a, 0x6a, 0x60, 0x96, 0x93, 0x5f, 0x5d, 0x26,
0x9e, 0x63, 0x1d, 0x09, 0xae, 0x9a, 0x41, 0xe5,
0xbd, 0x08, 0x47, 0xfe, 0xe5, 0x09, 0x9b, 0x20,
0xfd, 0x12, 0xe2, 0xe6, 0x40, 0x7f, 0xba, 0x4a,
0x61, 0x33, 0x66, 0x0d, 0x0e, 0x73, 0xdb, 0xb0,
0xd5, 0xa2, 0x9a, 0x9a, 0x17, 0x0d, 0x34, 0x30,
0x85, 0x6a, 0x42, 0x46, 0x9e, 0xff, 0x34, 0x8f,
0x5f, 0x87, 0x6c, 0x35, 0xe7, 0xa8, 0x4d, 0x35,
0xeb, 0xc1, 0x41, 0xaa, 0x8a, 0xd2, 0xda, 0x19,
0xaa, 0x79, 0xa2, 0x5f, 0x35, 0x2c, 0xa0, 0xfd,
0x25, 0xd3, 0xf7, 0x9d, 0x25, 0x18, 0x2d, 0xfa,
0xb4, 0xbc, 0xbb, 0x07, 0x34, 0x3c, 0x8d, 0x81,
0xbd, 0xf4, 0xe9, 0x37, 0xdb, 0x39, 0xe9, 0xd1,
0x45, 0x5b, 0x20, 0x41, 0x2f, 0x2d, 0x27, 0x22,
0xdc, 0x92, 0x74, 0x8a, 0x92, 0xd5, 0x83, 0xfd,
0x09, 0xfb, 0x13, 0x9b, 0xe3, 0x39, 0x7a, 0x6b,
0x5c, 0xfa, 0xe6, 0x76, 0x9e, 0xe0, 0xe4, 0xe3,
0xef, 0xad, 0xbc, 0xfd, 0x42, 0x45, 0x9a, 0xd4,
0x94, 0xd1, 0x7e, 0x8d, 0xa7, 0xd8, 0x05, 0xd5,
0xd3, 0x62, 0xcf, 0x15, 0xcf, 0x94, 0x7d, 0x1f,
0x5b, 0x58, 0x20, 0x44, 0x20, 0x90, 0x71, 0xbe,
0x66, 0xe9, 0x9a, 0xab, 0x74, 0x32, 0x70, 0x53,
0x1d, 0x69, 0xed, 0x87, 0x66, 0xf4, 0x09, 0x4f,
0xca, 0x25, 0x30, 0xc2, 0x63, 0x79, 0x00, 0x3c,
0xb1, 0x9b, 0x39, 0x3f, 0x00, 0xe0, 0xa8, 0x88,
0xef, 0x7a, 0x51, 0x5b, 0xe7, 0xbd, 0x49, 0x64,
0xda, 0x41, 0x7b, 0x24, 0xc3, 0x71, 0x22, 0xfd,
0xd1, 0xd1, 0x20, 0xb3, 0x3f, 0x97, 0xd3, 0x97,
0xb2, 0xaa, 0x18, 0x1c, 0x9e, 0x03, 0x77, 0x7b,
0x5b, 0x7e, 0xf9, 0xa3, 0xa0, 0xd6, 0x20, 0x81,
0x2c, 0x38, 0x8f, 0x9d, 0x25, 0xde, 0xe9, 0xc8,
0xf5, 0xdd, 0x6a, 0x47, 0x9c, 0x65, 0x04, 0x5a,
0x56, 0xe6, 0xc2, 0xeb, 0xf2, 0x02, 0x97, 0xe1,
0xb9, 0xd8, 0xe1, 0x24, 0x76, 0x9f, 0x23, 0x62,
0x39, 0x03, 0x4b, 0xc8, 0xf7, 0x34, 0x07, 0x49,
0xd6, 0xe7, 0x4d, 0x9a, 0x68, 0x61, 0x75, 0x74,
0x68, 0x44, 0x61, 0x74, 0x61, 0x58, 0xc4, 0x49,
0x96, 0x0d, 0xe5, 0x88, 0x0e, 0x8c, 0x68, 0x74,
0x34, 0x17, 0x0f, 0x64, 0x76, 0x60, 0x5b, 0x8f,
0xe4, 0xae, 0xb9, 0xa2, 0x86, 0x32, 0xc7, 0x99,
0x5c, 0xf3, 0xba, 0x83, 0x1d, 0x97, 0x63, 0x41,
0x00, 0x00, 0x00, 0x00, 0xf8, 0xa0, 0x11, 0xf3,
0x8c, 0x0a, 0x4d, 0x15, 0x80, 0x06, 0x17, 0x11,
0x1f, 0x9e, 0xdc, 0x7d, 0x00, 0x40, 0x53, 0xfb,
0xdf, 0xaa, 0xce, 0x63, 0xde, 0xc5, 0xfe, 0x47,
0xe6, 0x52, 0xeb, 0xf3, 0x5d, 0x53, 0xa8, 0xbf,
0x9d, 0xd6, 0x09, 0x6b, 0x5e, 0x7f, 0xe0, 0x0d,
0x51, 0x30, 0x85, 0x6a, 0xda, 0x68, 0x70, 0x85,
0xb0, 0xdb, 0x08, 0x0b, 0x83, 0x2c, 0xef, 0x44,
0xe2, 0x36, 0x88, 0xee, 0x76, 0x90, 0x6e, 0x7b,
0x50, 0x3e, 0x9a, 0xa0, 0xd6, 0x3c, 0x34, 0xe3,
0x83, 0xe7, 0xd1, 0xbd, 0x9f, 0x25, 0xa5, 0x01,
0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58, 0x20,
0x17, 0x5b, 0x27, 0xa6, 0x56, 0xb2, 0x26, 0x0c,
0x26, 0x0c, 0x55, 0x42, 0x78, 0x17, 0x5d, 0x4c,
0xf8, 0xa2, 0xfd, 0x1b, 0xb9, 0x54, 0xdf, 0xd5,
0xeb, 0xbf, 0x22, 0x64, 0xf5, 0x21, 0x9a, 0xc6,
0x22, 0x58, 0x20, 0x87, 0x5f, 0x90, 0xe6, 0xfd,
0x71, 0x27, 0x9f, 0xeb, 0xe3, 0x03, 0x44, 0xbc,
0x8d, 0x49, 0xc6, 0x1c, 0x31, 0x3b, 0x72, 0xae,
0xd4, 0x53, 0xb1, 0xfe, 0x5d, 0xe1, 0x30, 0xfc,
0x2b, 0x1e, 0xd2
};
struct param *
unpack(const uint8_t *ptr, size_t len)
{
cbor_item_t *item = NULL, **v;
struct cbor_load_result cbor;
struct param *p;
int ok = -1;
if ((p = calloc(1, sizeof(*p))) == NULL ||
(item = cbor_load(ptr, len, &cbor)) == NULL ||
cbor.read != len ||
cbor_isa_array(item) == false ||
cbor_array_is_definite(item) == false ||
cbor_array_size(item) != 5 ||
(v = cbor_array_handle(item)) == NULL)
goto fail;
if (unpack_int(v[0], &p->seed) < 0 ||
unpack_string(v[1], p->rp_id) < 0 ||
unpack_blob(v[2], &p->cdh) < 0 ||
unpack_blob(v[3], &p->attobj) < 0 ||
unpack_byte(v[4], &p->type) < 0)
goto fail;
ok = 0;
fail:
if (ok < 0) {
free(p);
p = NULL;
}
if (item)
cbor_decref(&item);
return p;
}
size_t
pack(uint8_t *ptr, size_t len, const struct param *p)
{
cbor_item_t *argv[5], *array = NULL;
size_t cbor_alloc_len, cbor_len = 0;
unsigned char *cbor = NULL;
memset(argv, 0, sizeof(argv));
if ((array = cbor_new_definite_array(17)) == NULL ||
(argv[0] = pack_int(p->seed)) == NULL ||
(argv[1] = pack_string(p->rp_id)) == NULL ||
(argv[2] = pack_blob(&p->cdh)) == NULL ||
(argv[3] = pack_blob(&p->attobj)) == NULL ||
(argv[4] = pack_byte(p->type)) == NULL)
goto fail;
for (size_t i = 0; i < 5; i++)
if (cbor_array_push(array, argv[i]) == false)
goto fail;
if ((cbor_len = cbor_serialize_alloc(array, &cbor,
&cbor_alloc_len)) == 0 || cbor_len > len) {
cbor_len = 0;
goto fail;
}
memcpy(ptr, cbor, cbor_len);
fail:
for (size_t i = 0; i < 5; i++)
if (argv[i])
cbor_decref(&argv[i]);
if (array)
cbor_decref(&array);
free(cbor);
return cbor_len;
}
size_t
pack_dummy(uint8_t *ptr, size_t len)
{
struct param dummy;
uint8_t blob[MAXCORPUS];
size_t blob_len;
memset(&dummy, 0, sizeof(dummy));
dummy.type = 1;
strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id));
dummy.cdh.len = sizeof(dummy_cdh);
dummy.attobj.len = sizeof(dummy_attestation_object);
memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len);
memcpy(&dummy.attobj.body, dummy_attestation_object, dummy.attobj.len);
assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
if (blob_len > len) {
memcpy(ptr, blob, len);
return len;
}
memcpy(ptr, blob, blob_len);
return blob_len;
}
void
mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
{
if (flags & MUTATE_SEED)
p->seed = (int)seed;
if (flags & MUTATE_PARAM) {
mutate_byte(&p->type);
p->attobj.len = sizeof(dummy_attestation_object);
memcpy(&p->attobj.body, &dummy_attestation_object,
p->attobj.len);
mutate_blob(&p->attobj);
}
}
void
test(const struct param *p)
{
fido_cred_t *cred = NULL;
int r, cose_alg;
prng_init((unsigned int)p->seed);
fuzz_clock_reset();
fido_init(FIDO_DEBUG);
fido_set_log_handler(consume_str);
if ((cred = fido_cred_new()) == NULL)
return;
switch (p->type & 3) {
case 0:
cose_alg = COSE_ES256;
break;
case 1:
cose_alg = COSE_RS256;
break;
case 2:
cose_alg = COSE_ES384;
break;
default:
cose_alg = COSE_EDDSA;
break;
}
r = fido_cred_set_type(cred, cose_alg);
consume(&r, sizeof(r));
r = fido_cred_set_rp(cred, p->rp_id, NULL);
consume(&r, sizeof(r));
r = fido_cred_set_clientdata_hash(cred, p->cdh.body, p->cdh.len);
consume(&r, sizeof(r));
r = fido_cred_set_attobj(cred, p->attobj.body, p->attobj.len);
consume(&r, sizeof(r));
consume_str(fido_cred_fmt(cred));
consume(fido_cred_attstmt_ptr(cred), fido_cred_attstmt_len(cred));
consume(fido_cred_authdata_ptr(cred), fido_cred_authdata_len(cred));
r = fido_cred_verify(cred);
consume(&r, sizeof(r));
fido_cred_free(&cred);
}
+12 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Copyright (c) 2019-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -248,6 +248,8 @@ make_cred(fido_cred_t *cred, uint8_t opt, int type, const struct blob *cdh,
fido_cred_set_uv(cred, FIDO_OPT_TRUE);
if (user_id->len)
fido_cred_set_prot(cred, user_id->body[0] & 0x03);
if (excl_cred->len)
fido_cred_set_entattest(cred, excl_cred->body[0] & 0x03);
/* repeat memory operations to trigger reallocation paths */
fido_cred_set_type(cred, type);
@@ -279,6 +281,7 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
uint8_t flags;
uint32_t sigcount;
int r;
bool ea;
if ((cred = fido_cred_new()) == NULL)
return;
@@ -309,6 +312,11 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
if (fmt)
fido_cred_set_fmt(cred, fmt);
/* XXX +1 on purpose */
for (size_t i = 0; i < fido_cred_x5c_list_count(cred) + 1; i++)
consume(fido_cred_x5c_list_ptr(cred, i),
fido_cred_x5c_list_len(cred, i));
/* repeat memory operations to trigger reallocation paths */
if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK)
fido_cred_set_authdata_raw(cred, authdata_raw_ptr,
@@ -343,6 +351,9 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
minpinlen = fido_cred_pin_minlen(cred);
consume(&minpinlen, sizeof(minpinlen));
ea = fido_cred_entattest(cred);
consume(&ea, sizeof(ea));
fido_cred_free(&cred);
}
+1
View File
@@ -9,6 +9,7 @@
#include <err.h>
#include <fcntl.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
+6
View File
@@ -135,12 +135,18 @@ void
mutate_byte(uint8_t *b)
{
LLVMFuzzerMutate(b, sizeof(*b), sizeof(*b));
#ifdef WITH_MSAN
__msan_unpoison(b, sizeof(*b));
#endif
}
void
mutate_int(int *i)
{
LLVMFuzzerMutate((uint8_t *)i, sizeof(*i), sizeof(*i));
#ifdef WITH_MSAN
__msan_unpoison(i, sizeof(*i));
#endif
}
void
Binary file not shown.
+47 -47
View File
@@ -1,55 +1,55 @@
Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
fuzz/clock.c 24 1 95.83% 4 0 100.00% 35 1 97.14%
fuzz/pcsc.c 59 0 100.00% 8 0 100.00% 75 12 84.00%
fuzz/prng.c 31 0 100.00% 2 0 100.00% 35 1 97.14%
fuzz/udev.c 110 2 98.18% 17 0 100.00% 126 12 90.48%
--------------------------------------------------------------------------------------------------------------------------------------------------------
fuzz/clock.c 29 1 96.55% 4 0 100.00% 35 1 97.14%
fuzz/pcsc.c 78 0 100.00% 8 0 100.00% 75 0 100.00%
fuzz/prng.c 32 0 100.00% 2 0 100.00% 35 0 100.00%
fuzz/udev.c 152 3 98.03% 17 0 100.00% 123 4 96.75%
fuzz/uniform_random.c 7 1 85.71% 1 0 100.00% 12 1 91.67%
fuzz/wrap.c 23 0 100.00% 3 0 100.00% 29 0 100.00%
fuzz/wrap.c 29 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/freezero.c 5 0 100.00% 1 0 100.00% 6 0 100.00%
openbsd-compat/recallocarray.c 54 17 68.52% 1 0 100.00% 36 7 80.56%
openbsd-compat/timingsafe_bcmp.c 4 0 100.00% 1 0 100.00% 7 0 100.00%
src/aes256.c 118 3 97.46% 8 0 100.00% 157 11 92.99%
src/assert.c 628 45 92.83% 63 4 93.65% 782 51 93.48%
src/authkey.c 52 0 100.00% 5 0 100.00% 66 0 100.00%
src/bio.c 451 20 95.57% 49 2 95.92% 587 24 95.91%
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 1070 12 98.88% 55 0 100.00% 1258 28 97.77%
src/compress.c 105 14 86.67% 5 0 100.00% 122 24 80.33%
src/config.c 112 0 100.00% 11 0 100.00% 154 0 100.00%
src/cred.c 653 36 94.49% 70 2 97.14% 853 39 95.43%
src/credman.c 422 10 97.63% 40 0 100.00% 557 20 96.41%
src/dev.c 332 65 80.42% 41 6 85.37% 378 80 78.84%
src/ecdh.c 117 2 98.29% 4 0 100.00% 146 5 96.58%
src/eddsa.c 88 5 94.32% 10 0 100.00% 114 9 92.11%
src/aes256.c 150 5 96.67% 8 0 100.00% 161 17 89.44%
src/assert.c 738 45 93.90% 63 4 93.65% 779 51 93.45%
src/authkey.c 58 0 100.00% 5 0 100.00% 66 0 100.00%
src/bio.c 557 23 95.87% 50 2 96.00% 586 24 95.90%
src/blob.c 75 2 97.33% 10 0 100.00% 81 4 95.06%
src/buf.c 8 0 100.00% 2 0 100.00% 16 0 100.00%
src/cbor.c 1402 16 98.86% 58 0 100.00% 1328 34 97.44%
src/compress.c 140 14 90.00% 5 0 100.00% 122 24 80.33%
src/config.c 137 0 100.00% 11 0 100.00% 154 0 100.00%
src/cred.c 860 37 95.70% 77 2 97.40% 928 42 95.47%
src/credman.c 496 10 97.98% 41 0 100.00% 557 20 96.41%
src/dev.c 394 80 79.70% 41 6 85.37% 382 80 79.06%
src/ecdh.c 169 2 98.82% 4 0 100.00% 146 5 96.58%
src/eddsa.c 125 5 96.00% 10 0 100.00% 113 9 92.04%
src/err.c 122 10 91.80% 1 0 100.00% 126 10 92.06%
src/es256.c 315 5 98.41% 19 0 100.00% 372 11 97.04%
src/es384.c 158 5 96.84% 11 0 100.00% 198 11 94.44%
src/hid.c 87 2 97.70% 14 0 100.00% 145 3 97.93%
src/hid_linux.c 184 73 60.33% 14 7 50.00% 263 115 56.27%
src/hid_unix.c 29 21 27.59% 2 0 100.00% 43 26 39.53%
src/info.c 232 0 100.00% 51 0 100.00% 409 0 100.00%
src/io.c 193 7 96.37% 13 0 100.00% 230 12 94.78%
src/iso7816.c 18 1 94.44% 5 0 100.00% 38 1 97.37%
src/largeblob.c 525 18 96.57% 30 0 100.00% 693 43 93.80%
src/log.c 39 5 87.18% 7 1 85.71% 63 7 88.89%
src/netlink.c 329 8 97.57% 40 0 100.00% 498 15 96.99%
src/nfc.c 155 5 96.77% 12 0 100.00% 244 15 93.85%
src/nfc_linux.c 172 77 55.23% 13 7 46.15% 242 126 47.93%
src/pcsc.c 204 1 99.51% 13 0 100.00% 282 3 98.94%
src/pin.c 426 3 99.30% 26 0 100.00% 514 4 99.22%
src/es256.c 478 4 99.16% 19 0 100.00% 370 8 97.84%
src/es384.c 236 5 97.88% 11 0 100.00% 197 11 94.42%
src/hid.c 106 2 98.11% 14 0 100.00% 144 3 97.92%
src/hid_linux.c 283 96 66.08% 14 7 50.00% 277 115 58.48%
src/hid_unix.c 46 33 28.26% 2 0 100.00% 43 26 39.53%
src/info.c 290 0 100.00% 51 0 100.00% 408 0 100.00%
src/io.c 206 7 96.60% 13 0 100.00% 230 12 94.78%
src/iso7816.c 27 1 96.30% 5 0 100.00% 36 1 97.22%
src/largeblob.c 633 22 96.52% 30 0 100.00% 692 43 93.79%
src/log.c 52 6 88.46% 7 1 85.71% 60 6 90.00%
src/netlink.c 428 10 97.66% 40 0 100.00% 497 15 96.98%
src/nfc.c 176 3 98.30% 12 0 100.00% 245 9 96.33%
src/nfc_linux.c 245 93 62.04% 13 6 53.85% 240 114 52.50%
src/pcsc.c 229 1 99.56% 13 0 100.00% 282 3 98.94%
src/pin.c 527 4 99.24% 26 0 100.00% 515 3 99.42%
src/random.c 6 0 100.00% 1 0 100.00% 6 0 100.00%
src/reset.c 24 0 100.00% 3 0 100.00% 23 0 100.00%
src/rs1.c 22 2 90.91% 3 0 100.00% 36 6 83.33%
src/rs256.c 146 9 93.84% 13 0 100.00% 179 16 91.06%
src/time.c 43 3 93.02% 3 0 100.00% 43 2 95.35%
src/touch.c 67 0 100.00% 2 0 100.00% 79 0 100.00%
src/tpm.c 103 0 100.00% 9 0 100.00% 194 0 100.00%
src/types.c 29 0 100.00% 7 0 100.00% 56 0 100.00%
src/u2f.c 572 4 99.30% 17 0 100.00% 726 12 98.35%
src/util.c 14 1 92.86% 1 0 100.00% 14 1 92.86%
src/rs1.c 31 1 96.77% 2 0 100.00% 35 3 91.43%
src/rs256.c 212 8 96.23% 12 0 100.00% 177 13 92.66%
src/time.c 50 3 94.00% 3 0 100.00% 43 2 95.35%
src/touch.c 82 0 100.00% 2 0 100.00% 79 0 100.00%
src/tpm.c 144 0 100.00% 9 0 100.00% 191 0 100.00%
src/types.c 39 0 100.00% 7 0 100.00% 50 0 100.00%
src/u2f.c 669 4 99.40% 17 0 100.00% 727 12 98.35%
src/util.c 21 1 95.24% 1 0 100.00% 14 1 92.86%
Files which contain no functions:
fuzz/mutator_aux.h 0 0 - 0 0 - 0 0 -
@@ -60,5 +60,5 @@ src/fallthrough.h 0 0 -
src/fido.h 0 0 - 0 0 - 0 0 -
src/fido/err.h 0 0 - 0 0 - 0 0 -
src/fido/param.h 0 0 - 0 0 - 0 0 -
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL 8730 486 94.43% 742 29 96.09% 11357 769 93.23%
--------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL 11065 575 94.80% 752 28 96.28% 11491 733 93.62%
+7 -1
View File
@@ -165,6 +165,7 @@ list(APPEND MAN_ALIAS
fido_cred_new fido_cred_clientdata_hash_len
fido_cred_new fido_cred_clientdata_hash_ptr
fido_cred_new fido_cred_display_name
fido_cred_new fido_cred_entattest
fido_cred_new fido_cred_flags
fido_cred_new fido_cred_fmt
fido_cred_new fido_cred_free
@@ -186,6 +187,9 @@ list(APPEND MAN_ALIAS
fido_cred_new fido_cred_user_id_ptr
fido_cred_new fido_cred_user_name
fido_cred_new fido_cred_x5c_len
fido_cred_new fido_cred_x5c_list_count
fido_cred_new fido_cred_x5c_list_len
fido_cred_new fido_cred_x5c_list_ptr
fido_cred_new fido_cred_x5c_ptr
fido_cred_verify fido_cred_verify_self
fido_credman_metadata_new fido_credman_del_dev_rk
@@ -208,10 +212,12 @@ list(APPEND MAN_ALIAS
fido_credman_metadata_new fido_credman_rp_new
fido_credman_metadata_new fido_credman_set_dev_rk
fido_cred_set_authdata fido_cred_set_attstmt
fido_cred_set_authdata fido_cred_set_attobj
fido_cred_set_authdata fido_cred_set_authdata_raw
fido_cred_set_authdata fido_cred_set_blob
fido_cred_set_authdata fido_cred_set_clientdata
fido_cred_set_authdata fido_cred_set_clientdata_hash
fido_cred_set_authdata fido_cred_set_entattest
fido_cred_set_authdata fido_cred_set_extensions
fido_cred_set_authdata fido_cred_set_fmt
fido_cred_set_authdata fido_cred_set_id
@@ -393,7 +399,7 @@ if(GZIP_PATH)
install(FILES ${PROJECT_BINARY_DIR}/man/${DST}.3.gz
DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")
endforeach()
elseif(NOT MSVC)
else()
add_dependencies(man man_symlink)
foreach(f ${MAN_SOURCES})
if (${f} MATCHES ".1$")
+1
View File
@@ -10,6 +10,7 @@ find . -maxdepth 1 -type f -name '*.3' -print0 > "$T/files"
xargs -0 awk '/^.Sh NAME/,/^.Nd/' < "$T/files" | \
awk '/^.Nm/ { print $2 }' | sort -u > "$T/Nm"
# shellcheck disable=SC2016
xargs -0 awk '/^.Fn/ { print $2 }' < "$T/files" | sort -u > "$T/Fn"
(cd "$T" && diff -u Nm Fn)
+4 -2
View File
@@ -89,6 +89,8 @@ where
may be
.Em es256
(denoting ECDSA over NIST P-256 with SHA-256),
.Em es384
(denoting ECDSA over NIST P-384 with SHA-384),
.Em rs256
(denoting 2048-bit RSA with PKCS#1.5 padding and SHA-256), or
.Em eddsa
@@ -224,7 +226,7 @@ client data hash (base64 blob);
.It
relying party id (UTF-8 string);
.It
authenticator data (base64 blob);
CBOR encoded authenticator data (base64 blob);
.It
assertion signature (base64 blob);
.El
@@ -248,7 +250,7 @@ client data hash (base64 blob);
.It
relying party id (UTF-8 string);
.It
authenticator data (base64 blob);
CBOR encoded authenticator data (base64 blob);
.It
assertion signature (base64 blob);
.It
+11 -3
View File
@@ -1,4 +1,4 @@
.\" Copyright (c) 2018-2023 Yubico AB. All rights reserved.
.\" Copyright (c) 2018-2024 Yubico AB. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions are
@@ -35,6 +35,7 @@
.Nm
.Fl M
.Op Fl bdhqruvw
.Op Fl a Ar mode
.Op Fl c Ar cred_protect
.Op Fl i Ar input_file
.Op Fl o Ar output_file
@@ -56,6 +57,8 @@ A credential
may be
.Em es256
(denoting ECDSA over NIST P-256 with SHA-256),
.Em es384
(denoting ECDSA over NIST P-384 with SHA-384),
.Em rs256
(denoting 2048-bit RSA with PKCS#1.5 padding and SHA-256), or
.Em eddsa
@@ -118,6 +121,11 @@ to verify a credential.
Request the credential's
.Dq largeBlobKey ,
a 32-byte symmetric key associated with the generated credential.
.It Fl a Ar mode
When making a credential, request enterprise attestation.
Please refer to
.In fido/param.h
for the set of possible values.
.It Fl c Ar cred_protect
If making a credential, set the credential's protection level to
.Ar cred_protect ,
@@ -218,7 +226,7 @@ relying party id (UTF-8 string);
.It
credential format (UTF-8 string);
.It
authenticator data (base64 blob);
CBOR encoded authenticator data (base64 blob);
.It
credential id (base64 blob);
.It
@@ -248,7 +256,7 @@ relying party id (UTF-8 string);
.It
credential format (UTF-8 string);
.It
authenticator data (base64 blob);
CBOR encoded authenticator data (base64 blob);
.It
credential id (base64 blob);
.It
+52 -2
View File
@@ -1,4 +1,4 @@
.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved.
.\" Copyright (c) 2018-2024 Yubico AB. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions are
@@ -47,6 +47,8 @@
.Nm fido_cred_pubkey_ptr ,
.Nm fido_cred_sig_ptr ,
.Nm fido_cred_user_id_ptr ,
.Nm fido_cred_x5c_list_count ,
.Nm fido_cred_x5c_list_ptr ,
.Nm fido_cred_x5c_ptr ,
.Nm fido_cred_attstmt_ptr ,
.Nm fido_cred_authdata_len ,
@@ -58,8 +60,10 @@
.Nm fido_cred_pubkey_len ,
.Nm fido_cred_sig_len ,
.Nm fido_cred_user_id_len ,
.Nm fido_cred_x5c_list_len ,
.Nm fido_cred_x5c_len ,
.Nm fido_cred_attstmt_len ,
.Nm fido_cred_entattest ,
.Nm fido_cred_type ,
.Nm fido_cred_flags ,
.Nm fido_cred_sigcount
@@ -102,6 +106,10 @@
.Fn fido_cred_sig_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_user_id_ptr "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_x5c_list_count "const fido_cred_t *cred"
.Ft const unsigned char *
.Fn fido_cred_x5c_list_ptr "const fido_cred_t *cred" "size_t idx"
.Ft const unsigned char *
.Fn fido_cred_x5c_ptr "const fido_cred_t *cred"
.Ft const unsigned char *
@@ -125,9 +133,13 @@
.Ft size_t
.Fn fido_cred_user_id_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_x5c_list_len "const fido_cred_t *cred" "size_t idx"
.Ft size_t
.Fn fido_cred_x5c_len "const fido_cred_t *cred"
.Ft size_t
.Fn fido_cred_attstmt_len "const fido_cred_t *cred"
.Ft bool
.Fn fido_cred_entattest "const fido_cred_t *cred"
.Ft int
.Fn fido_cred_type "const fido_cred_t *cred"
.Ft uint8_t
@@ -246,7 +258,7 @@ and
functions return pointers to the CBOR-encoded and raw authenticator
data, client data hash, ID, authenticator attestation GUID,
.Dq largeBlobKey ,
public key, signature, user ID, x509 certificate, and attestation
public key, signature, user ID, x509 leaf certificate, and attestation
statement parts of
.Fa cred ,
or NULL if the respective entry is not set.
@@ -265,10 +277,48 @@ The corresponding length can be obtained by
and
.Fn fido_cred_attstmt_len .
.Pp
The
.Fn fido_cred_x5c_list_count
function returns the length of the x509 certificate chain in
.Fa cred
and the
.Fn fido_cred_x5c_list_ptr
and
.Fn fido_cred_x5c_list_len
functions return a pointer to and length of the x509 certificate at index
.Fa idx
respectively.
Please note that the leaf certificate has an
.Fa idx
(index) value of 0 and calling
.Fn fido_cred_x5c_list_ptr cred 0
and
.Fn fido_cred_x5c_list_len cred 0
is equivalent to
.Fn fido_cred_x5c_ptr cred
and
.Fn fido_cred_x5c_len cred
respectively.
If
.Fa idx
exceeds the return value of
.Fn fido_cred_x5c_list_count ,
.Fn fido_cred_x5c_list_ptr
returns NULL and
.Fn fido_cred_x5c_list_len
returns 0.
.Pp
The authenticator data, x509 certificate, and signature parts of a
credential are typically passed to a FIDO2 server for verification.
.Pp
The
.Fn fido_cred_entattest
function returns
.Dv true
if an enterprise attestation was returned for
.Fa cred .
.Pp
The
.Fn fido_cred_type
function returns the COSE algorithm of
.Fa cred .
+45 -3
View File
@@ -1,4 +1,4 @@
.\" Copyright (c) 2018-2022 Yubico AB. All rights reserved.
.\" Copyright (c) 2018-2024 Yubico AB. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions are
@@ -32,6 +32,7 @@
.Nm fido_cred_set_authdata ,
.Nm fido_cred_set_authdata_raw ,
.Nm fido_cred_set_attstmt ,
.Nm fido_cred_set_attobj ,
.Nm fido_cred_set_x509 ,
.Nm fido_cred_set_sig ,
.Nm fido_cred_set_id ,
@@ -39,6 +40,7 @@
.Nm fido_cred_set_clientdata_hash ,
.Nm fido_cred_set_rp ,
.Nm fido_cred_set_user ,
.Nm fido_cred_set_entattest ,
.Nm fido_cred_set_extensions ,
.Nm fido_cred_set_blob ,
.Nm fido_cred_set_pin_minlen ,
@@ -64,6 +66,8 @@ typedef enum {
.Ft int
.Fn fido_cred_set_attstmt "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_attobj "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_x509 "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
.Ft int
.Fn fido_cred_set_sig "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
@@ -78,6 +82,8 @@ typedef enum {
.Ft int
.Fn fido_cred_set_user "fido_cred_t *cred" "const unsigned char *user_id" "size_t user_id_len" "const char *name" "const char *display_name" "const char *icon"
.Ft int
.Fn fido_cred_set_entattest "fido_cred_t *cred" "int ea"
.Ft int
.Fn fido_cred_set_extensions "fido_cred_t *cred" "int flags"
.Ft int
.Fn fido_cred_set_blob "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
@@ -110,14 +116,15 @@ of its constituent parts, please refer to the Web Authentication
The
.Fn fido_cred_set_authdata ,
.Fn fido_cred_set_attstmt ,
.Fn fido_cred_set_attobj ,
.Fn fido_cred_set_x509 ,
.Fn fido_cred_set_sig ,
.Fn fido_cred_set_id ,
and
.Fn fido_cred_set_clientdata_hash
functions set the authenticator data, attestation statement,
attestation certificate, attestation signature, id, and client
data hash parts of
attestation object, attestation certificate, attestation signature,
id, and client data hash parts of
.Fa cred
to
.Fa ptr ,
@@ -157,6 +164,26 @@ The latter two are meant to be used in contexts where the
credential's complete attestation statement is not available or
required.
.Pp
The attestation object passed to
.Fn fido_cred_set_attobj
must be a CBOR-encoded map containing
.Dq authData ,
.Dq fmt ,
and
.Dq attStmt .
An application calling
.Fn fido_cred_set_attobj
does not need to call
.Fn fido_cred_set_fmt ,
.Fn fido_cred_set_attstmt ,
.Fn fido_cred_set_authdata ,
or
.Fn fido_cred_set_authdata_raw .
.Fn fido_cred_set_attobj
may be useful in applications interfacing with the WebAuthn API,
removing the need to first parse the attestation object to verify the
credential.
.Pp
The
.Fn fido_cred_set_clientdata
function allows an application to set the client data hash of
@@ -219,6 +246,21 @@ and
parameters may be NULL.
.Pp
The
.Fn fido_cred_set_entattest
function sets the enterprise attestation mode of
.Fa cred
to
.Fa ea .
At the moment, only the
.Dv FIDO_ENTATTEST_VENDOR
and
.Dv FIDO_ENTATTEST_PLATFORM
modes are supported.
By default, or if
.Fa ea
is zero, no enterprise attestation is requested.
.Pp
The
.Fn fido_cred_set_extensions
function sets the extensions of
.Fa cred
+17 -14
View File
@@ -1,22 +1,24 @@
# Copyright (c) 2018-2022 Yubico AB. All rights reserved.
# Copyright (c) 2018-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
add_custom_target(regress)
macro(add_regress_test NAME SOURCES LIB)
add_executable(${NAME} ${SOURCES})
function(add_regress_test NAME)
set(MULTIVAL_KEYWORDS "SOURCES" "LIBS")
cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "${MULTIVAL_KEYWORDS}")
add_executable(${NAME} ${arg_SOURCES})
add_test(${NAME} ${NAME})
add_dependencies(regress ${NAME})
target_link_libraries(${NAME} ${LIB})
endmacro()
target_link_libraries(${NAME} ${arg_LIBS})
endfunction()
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"
"${CRYPTO_BIN_DIRS}/${CRYPTO_DLL}.dll"
"${ZLIB_BIN_DIRS}/${ZLIB_LIBRARIES}.dll"
"$<TARGET_FILE:${_FIDO2_LIBRARY}>"
"${CMAKE_CURRENT_BINARY_DIR}")
@@ -40,18 +42,19 @@ else()
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
endif()
add_regress_test(regress_assert assert.c ${_FIDO2_LIBRARY})
add_regress_test(regress_cred cred.c ${_FIDO2_LIBRARY})
add_regress_test(regress_dev dev.c ${_FIDO2_LIBRARY})
add_regress_test(regress_eddsa eddsa.c ${_FIDO2_LIBRARY})
add_regress_test(regress_es256 es256.c ${_FIDO2_LIBRARY})
add_regress_test(regress_es384 es384.c ${_FIDO2_LIBRARY})
add_regress_test(regress_rs256 rs256.c ${_FIDO2_LIBRARY})
add_regress_test(regress_assert SOURCES assert.c LIBS ${_FIDO2_LIBRARY})
add_regress_test(regress_cred SOURCES cred.c mock.c LIBS ${_FIDO2_LIBRARY})
add_regress_test(regress_dev SOURCES dev.c mock.c LIBS ${_FIDO2_LIBRARY})
add_regress_test(regress_eddsa SOURCES eddsa.c LIBS ${_FIDO2_LIBRARY})
add_regress_test(regress_es256 SOURCES es256.c LIBS ${_FIDO2_LIBRARY})
add_regress_test(regress_es384 SOURCES es384.c LIBS ${_FIDO2_LIBRARY})
add_regress_test(regress_rs256 SOURCES rs256.c LIBS ${_FIDO2_LIBRARY})
if(BUILD_STATIC_LIBS)
add_regress_test(regress_compress compress.c fido2)
add_regress_test(regress_compress SOURCES compress.c LIBS fido2)
endif()
if(MINGW)
# needed for nanosleep() in mingw
target_link_libraries(regress_dev winpthread)
target_link_libraries(regress_cred winpthread)
endif()
File diff suppressed because it is too large Load Diff
+14 -220
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Copyright (c) 2019-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -16,166 +16,16 @@
#include <fido.h>
#include "../fuzz/wiredata_fido2.h"
#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);
}
static void
dummy_close(void *handle)
{
assert(handle == &fake_dev_handle);
}
static int
dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)
{
struct timespec tv;
size_t n;
long d;
assert(handle == &fake_dev_handle);
assert(ptr != NULL);
assert(len == REPORT_LEN - 1);
if (wiredata_ptr == NULL)
return (-1);
if (!initialised) {
assert(wiredata_len >= REPORT_LEN - 1);
memcpy(&wiredata_ptr[7], &ctap_nonce, sizeof(ctap_nonce));
initialised = 1;
}
if (ms >= 0 && ms < interval_ms)
d = ms;
else
d = interval_ms;
if (d) {
tv.tv_sec = d / 1000;
tv.tv_nsec = (d % 1000) * 1000000;
if (nanosleep(&tv, NULL) == -1)
err(1, "nanosleep");
}
if (d != interval_ms)
return (-1); /* timeout */
if (wiredata_len < len)
n = wiredata_len;
else
n = len;
memcpy(ptr, wiredata_ptr, n);
wiredata_ptr += n;
wiredata_len -= n;
return ((int)n);
}
static int
dummy_write(void *handle, const unsigned char *ptr, size_t len)
{
struct timespec tv;
assert(handle == &fake_dev_handle);
assert(ptr != NULL);
assert(len == REPORT_LEN);
if (!initialised)
memcpy(&ctap_nonce, &ptr[8], sizeof(ctap_nonce));
if (interval_ms) {
tv.tv_sec = interval_ms / 1000;
tv.tv_nsec = (interval_ms % 1000) * 1000000;
if (nanosleep(&tv, NULL) == -1)
err(1, "nanosleep");
}
return ((int)len);
}
static uint8_t *
wiredata_setup(const uint8_t *data, size_t len)
{
const uint8_t ctap_init_data[] = { WIREDATA_CTAP_INIT };
assert(wiredata_ptr == NULL);
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);
wiredata_len = sizeof(ctap_init_data) + len;
return (wiredata_ptr);
}
static void
wiredata_clear(uint8_t **wiredata)
{
free(*wiredata);
*wiredata = NULL;
wiredata_ptr = NULL;
wiredata_len = 0;
initialised = 0;
}
#include "extern.h"
/* gh#56 */
static void
open_iff_ok(void)
{
fido_dev_t *dev = NULL;
fido_dev_io_t io;
memset(&io, 0, sizeof(io));
io.open = dummy_open;
io.close = dummy_close;
io.read = dummy_read;
io.write = dummy_write;
assert((dev = fido_dev_new()) != NULL);
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
setup_dummy_io(dev);
assert(fido_dev_open(dev, "dummy") == FIDO_ERR_RX);
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
@@ -188,18 +38,10 @@ reopen(void)
const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
uint8_t *wiredata;
fido_dev_t *dev = NULL;
fido_dev_io_t io;
memset(&io, 0, sizeof(io));
io.open = dummy_open;
io.close = dummy_close;
io.read = dummy_read;
io.write = dummy_write;
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
assert((dev = fido_dev_new()) != NULL);
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
setup_dummy_io(dev);
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
assert(fido_dev_close(dev) == FIDO_OK);
wiredata_clear(&wiredata);
@@ -217,18 +59,10 @@ double_open(void)
const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
uint8_t *wiredata;
fido_dev_t *dev = NULL;
fido_dev_io_t io;
memset(&io, 0, sizeof(io));
io.open = dummy_open;
io.close = dummy_close;
io.read = dummy_read;
io.write = dummy_write;
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
assert((dev = fido_dev_new()) != NULL);
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
setup_dummy_io(dev);
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
assert(fido_dev_open(dev, "dummy") == FIDO_ERR_INVALID_ARGUMENT);
assert(fido_dev_close(dev) == FIDO_OK);
@@ -242,19 +76,11 @@ double_close(void)
const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
uint8_t *wiredata;
fido_dev_t *dev = NULL;
fido_dev_io_t io;
memset(&io, 0, sizeof(io));
io.open = dummy_open;
io.close = dummy_close;
io.read = dummy_read;
io.write = dummy_write;
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
assert((dev = fido_dev_new()) != NULL);
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
setup_dummy_io(dev);
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
assert(fido_dev_close(dev) == FIDO_OK);
@@ -269,18 +95,10 @@ is_fido2(void)
const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
uint8_t *wiredata;
fido_dev_t *dev = NULL;
fido_dev_io_t io;
memset(&io, 0, sizeof(io));
io.open = dummy_open;
io.close = dummy_close;
io.read = dummy_read;
io.write = dummy_write;
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
assert((dev = fido_dev_new()) != NULL);
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
setup_dummy_io(dev);
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
assert(fido_dev_is_fido2(dev) == true);
assert(fido_dev_supports_pin(dev) == true);
@@ -313,18 +131,10 @@ has_pin(void)
};
uint8_t *wiredata;
fido_dev_t *dev = NULL;
fido_dev_io_t io;
memset(&io, 0, sizeof(io));
io.open = dummy_open;
io.close = dummy_close;
io.read = dummy_read;
io.write = dummy_write;
wiredata = wiredata_setup(set_pin_data, sizeof(set_pin_data));
assert((dev = fido_dev_new()) != NULL);
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
setup_dummy_io(dev);
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
assert(fido_dev_has_pin(dev) == false);
assert(fido_dev_set_pin(dev, "top secret", NULL) == FIDO_OK);
@@ -350,26 +160,18 @@ timeout_rx(void)
};
uint8_t *wiredata;
fido_dev_t *dev = NULL;
fido_dev_io_t io;
memset(&io, 0, sizeof(io));
io.open = dummy_open;
io.close = dummy_close;
io.read = dummy_read;
io.write = dummy_write;
wiredata = wiredata_setup(timeout_rx_data, sizeof(timeout_rx_data));
assert((dev = fido_dev_new()) != NULL);
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
setup_dummy_io(dev);
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK);
interval_ms = 1000;
set_read_interval(1000);
assert(fido_dev_reset(dev) == FIDO_ERR_RX);
assert(fido_dev_close(dev) == FIDO_OK);
fido_dev_free(&dev);
wiredata_clear(&wiredata);
interval_ms = 0;
set_read_interval(0);
}
static void
@@ -386,26 +188,18 @@ timeout_ok(void)
};
uint8_t *wiredata;
fido_dev_t *dev = NULL;
fido_dev_io_t io;
memset(&io, 0, sizeof(io));
io.open = dummy_open;
io.close = dummy_close;
io.read = dummy_read;
io.write = dummy_write;
wiredata = wiredata_setup(timeout_ok_data, sizeof(timeout_ok_data));
assert((dev = fido_dev_new()) != NULL);
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
setup_dummy_io(dev);
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
assert(fido_dev_set_timeout(dev, 30 * 1000) == FIDO_OK);
interval_ms = 1000;
set_read_interval(1000);
assert(fido_dev_reset(dev) == FIDO_OK);
assert(fido_dev_close(dev) == FIDO_OK);
fido_dev_free(&dev);
wiredata_clear(&wiredata);
interval_ms = 0;
set_read_interval(0);
}
static void
+17
View File
@@ -0,0 +1,17 @@
/*
* Copyright (c) 2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef REGRESS_EXTERN_H
#define REGRESS_EXTERN_H
#include <fido.h>
void setup_dummy_io(fido_dev_t *);
void set_read_interval(long);
uint8_t *wiredata_setup(const uint8_t *, size_t);
void wiredata_clear(uint8_t **);
#endif
+182
View File
@@ -0,0 +1,182 @@
/*
* Copyright (c) 2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
*/
#undef NDEBUG
#include <assert.h>
#include <string.h>
#include <time.h>
#include <stdint.h>
#define _FIDO_INTERNAL
#include <fido.h>
#include "extern.h"
#include "../fuzz/wiredata_fido2.h"
#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);
}
static void
dummy_close(void *handle)
{
assert(handle == &fake_dev_handle);
}
static int
dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)
{
struct timespec tv;
size_t n;
long d;
assert(handle == &fake_dev_handle);
assert(ptr != NULL);
assert(len == REPORT_LEN - 1);
if (wiredata_ptr == NULL)
return (-1);
if (!initialised) {
assert(wiredata_len >= REPORT_LEN - 1);
memcpy(&wiredata_ptr[7], &ctap_nonce, sizeof(ctap_nonce));
initialised = 1;
}
if (ms >= 0 && ms < interval_ms)
d = ms;
else
d = interval_ms;
if (d) {
tv.tv_sec = d / 1000;
tv.tv_nsec = (d % 1000) * 1000000;
if (nanosleep(&tv, NULL) == -1)
err(1, "nanosleep");
}
if (d != interval_ms)
return (-1); /* timeout */
if (wiredata_len < len)
n = wiredata_len;
else
n = len;
memcpy(ptr, wiredata_ptr, n);
wiredata_ptr += n;
wiredata_len -= n;
return ((int)n);
}
static int
dummy_write(void *handle, const unsigned char *ptr, size_t len)
{
struct timespec tv;
assert(handle == &fake_dev_handle);
assert(ptr != NULL);
assert(len == REPORT_LEN);
if (!initialised)
memcpy(&ctap_nonce, &ptr[8], sizeof(ctap_nonce));
if (interval_ms) {
tv.tv_sec = interval_ms / 1000;
tv.tv_nsec = (interval_ms % 1000) * 1000000;
if (nanosleep(&tv, NULL) == -1)
err(1, "nanosleep");
}
return ((int)len);
}
uint8_t *
wiredata_setup(const uint8_t *data, size_t len)
{
const uint8_t ctap_init_data[] = { WIREDATA_CTAP_INIT };
assert(wiredata_ptr == NULL);
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);
wiredata_len = sizeof(ctap_init_data) + len;
return (wiredata_ptr);
}
void
wiredata_clear(uint8_t **wiredata)
{
free(*wiredata);
*wiredata = NULL;
wiredata_ptr = NULL;
wiredata_len = 0;
initialised = 0;
}
void
setup_dummy_io(fido_dev_t *dev)
{
fido_dev_io_t io;
memset(&io, 0, sizeof(io));
io.open = dummy_open;
io.close = dummy_close;
io.read = dummy_read;
io.write = dummy_write;
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
}
void
set_read_interval(long ms)
{
interval_ms = ms;
}
+3 -5
View File
@@ -151,8 +151,6 @@ endif()
install(FILES fido.h DESTINATION include)
install(DIRECTORY fido DESTINATION include)
if(NOT MSVC)
configure_file(libfido2.pc.in libfido2.pc @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libfido2.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
endif()
configure_file(libfido2.pc.in libfido2.pc @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libfido2.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+5 -1
View File
@@ -128,7 +128,11 @@ aes256_gcm(const fido_blob_t *key, const fido_blob_t *nonce,
nonce->len, key->len, aad->len);
goto fail;
}
if (in->len > UINT_MAX || in->len > SIZE_MAX - 16 || in->len < 16) {
if (in->len > UINT_MAX || in->len > SIZE_MAX - 16) {
fido_log_debug("%s: invalid input len %zu", __func__, in->len);
goto fail;
}
if (!encrypt && in->len < 16) {
fido_log_debug("%s: invalid input len %zu", __func__, in->len);
goto fail;
}
+10 -1
View File
@@ -57,6 +57,15 @@ bio_prepare_hmac(uint8_t cmd, cbor_item_t **argv, size_t argc,
return (ok);
}
static uint8_t
bio_get_cmd(const fido_dev_t *dev)
{
if (dev->flags & (FIDO_DEV_BIO_SET|FIDO_DEV_BIO_UNSET))
return (CTAP_CBOR_BIO_ENROLL);
return (CTAP_CBOR_BIO_ENROLL_PRE);
}
static int
bio_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **sub_argv, size_t sub_argc,
const char *pin, const fido_blob_t *token, int *ms)
@@ -66,7 +75,7 @@ bio_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **sub_argv, size_t sub_argc,
fido_blob_t *ecdh = NULL;
fido_blob_t f;
fido_blob_t hmac;
const uint8_t cmd = CTAP_CBOR_BIO_ENROLL_PRE;
const uint8_t cmd = bio_get_cmd(dev);
int r = FIDO_ERR_INTERNAL;
memset(&f, 0, sizeof(f));
+98 -7
View File
@@ -1132,6 +1132,64 @@ decode_attcred(const unsigned char **buf, size_t *len, int cose_alg,
return (ok);
}
static int
decode_attobj(const cbor_item_t *key, const cbor_item_t *val, void *arg)
{
fido_cred_t *cred = arg;
char *name = NULL;
int ok = -1;
if (cbor_string_copy(key, &name) < 0) {
fido_log_debug("%s: cbor type", __func__);
ok = 0; /* ignore */
goto fail;
}
if (!strcmp(name, "fmt")) {
if (cbor_decode_fmt(val, &cred->fmt) < 0) {
fido_log_debug("%s: cbor_decode_fmt", __func__);
goto fail;
}
} else if (!strcmp(name, "attStmt")) {
if (cbor_decode_attstmt(val, &cred->attstmt) < 0) {
fido_log_debug("%s: cbor_decode_attstmt", __func__);
goto fail;
}
} else if (!strcmp(name, "authData")) {
if (fido_blob_decode(val, &cred->authdata_raw) < 0) {
fido_log_debug("%s: fido_blob_decode", __func__);
goto fail;
}
if (cbor_decode_cred_authdata(val, cred->type,
&cred->authdata_cbor, &cred->authdata, &cred->attcred,
&cred->authdata_ext) < 0) {
fido_log_debug("%s: cbor_decode_cred_authdata",
__func__);
goto fail;
}
}
ok = 0;
fail:
free(name);
return (ok);
}
/* XXX introduce fido_attobj_t? */
int
cbor_decode_attobj(const cbor_item_t *item, fido_cred_t *cred)
{
if (cbor_isa_map(item) == false ||
cbor_map_is_definite(item) == false ||
cbor_map_iter(item, cred, decode_attobj) < 0) {
fido_log_debug("%s: cbor type", __func__);
return (-1);
}
return (0);
}
static int
decode_cred_extension(const cbor_item_t *key, const cbor_item_t *val, void *arg)
{
@@ -1386,12 +1444,47 @@ cbor_decode_assert_authdata(const cbor_item_t *item, fido_blob_t *authdata_cbor,
static int
decode_x5c(const cbor_item_t *item, void *arg)
{
fido_blob_t *x5c = arg;
fido_blob_array_t *x5c = arg;
fido_blob_t *list_ptr = NULL;
fido_blob_t x5c_blob;
if (x5c->len)
return (0); /* ignore */
memset(&x5c_blob, 0, sizeof(x5c_blob));
return (fido_blob_decode(item, x5c));
if (fido_blob_decode(item, &x5c_blob) < 0) {
fido_log_debug("%s: fido_blob_decode", __func__);
return (-1);
}
if (x5c->len == SIZE_MAX) {
fido_blob_reset(&x5c_blob);
return (-1);
}
if ((list_ptr = recallocarray(x5c->ptr, x5c->len,
x5c->len + 1, sizeof(x5c_blob))) == NULL) {
fido_blob_reset(&x5c_blob);
return (-1);
}
list_ptr[x5c->len++] = x5c_blob;
x5c->ptr = list_ptr;
return (0);
}
static int
decode_x5c_array(const cbor_item_t *item, fido_blob_array_t *arr)
{
if (arr->len) {
fido_log_debug("%s: dup", __func__);
return (-1);
}
if (cbor_isa_array(item) == false ||
cbor_array_is_definite(item) == false) {
fido_log_debug("%s: cbor", __func__);
return (-1);
}
return (cbor_array_iter(item, arr, decode_x5c));
}
static int
@@ -1427,9 +1520,7 @@ decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
goto out;
}
} else if (!strcmp(name, "x5c")) {
if (cbor_isa_array(val) == false ||
cbor_array_is_definite(val) == false ||
cbor_array_iter(val, &attstmt->x5c, decode_x5c) < 0) {
if (decode_x5c_array(val, &attstmt->x5c)) {
fido_log_debug("%s: x5c", __func__);
goto out;
}
+130 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Copyright (c) 2018-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -39,6 +39,8 @@ parse_makecred_reply(const cbor_item_t *key, const cbor_item_t *val, void *arg)
&cred->authdata_ext));
case 3: /* attestation statement */
return (cbor_decode_attstmt(val, &cred->attstmt));
case 4: /* enterprise attestation */
return (cbor_decode_bool(val, &cred->ea.att));
case 5: /* large blob key */
return (fido_blob_decode(val, &cred->largeblob_key));
default: /* ignore */
@@ -55,7 +57,7 @@ fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
fido_blob_t *ecdh = NULL;
fido_opt_t uv = cred->uv;
es256_pk_t *pk = NULL;
cbor_item_t *argv[9];
cbor_item_t *argv[10];
const uint8_t cmd = CTAP_CBOR_MAKECRED;
int r;
@@ -118,6 +120,15 @@ fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
goto fail;
}
/* enterprise attestation */
if (cred->ea.mode != 0)
if ((argv[9] = cbor_build_uint8((uint8_t)cred->ea.mode)) ==
NULL) {
fido_log_debug("%s: cbor_build_uint8", __func__);
r = FIDO_ERR_INTERNAL;
goto fail;
}
/* framing and transmission */
if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
@@ -284,15 +295,21 @@ verify_attstmt(const fido_blob_t *dgst, const fido_attstmt_t *attstmt)
EVP_PKEY *pkey = NULL;
int ok = -1;
/* openssl needs ints */
if (attstmt->x5c.len > INT_MAX) {
if (!attstmt->x5c.len) {
fido_log_debug("%s: x5c.len=%zu", __func__, attstmt->x5c.len);
return (-1);
}
/* openssl needs ints */
if (attstmt->x5c.ptr[0].len > INT_MAX) {
fido_log_debug("%s: x5c[0].len=%zu", __func__,
attstmt->x5c.ptr[0].len);
return (-1);
}
/* fetch key from x509 */
if ((rawcert = BIO_new_mem_buf(attstmt->x5c.ptr,
(int)attstmt->x5c.len)) == NULL ||
if ((rawcert = BIO_new_mem_buf(attstmt->x5c.ptr[0].ptr,
(int)attstmt->x5c.ptr[0].len)) == NULL ||
(cert = d2i_X509_bio(rawcert, NULL)) == NULL ||
(pkey = X509_get_pubkey(cert)) == NULL) {
fido_log_debug("%s: x509 key", __func__);
@@ -543,12 +560,21 @@ fido_cred_clean_attstmt(fido_attstmt_t *attstmt)
fido_blob_reset(&attstmt->certinfo);
fido_blob_reset(&attstmt->pubarea);
fido_blob_reset(&attstmt->cbor);
fido_blob_reset(&attstmt->x5c);
fido_free_blob_array(&attstmt->x5c);
fido_blob_reset(&attstmt->sig);
memset(attstmt, 0, sizeof(*attstmt));
}
static void
fido_cred_clean_attobj(fido_cred_t *cred)
{
free(cred->fmt);
cred->fmt = NULL;
fido_cred_clean_authdata(cred);
fido_cred_clean_attstmt(&cred->attstmt);
}
void
fido_cred_reset_tx(fido_cred_t *cred)
{
@@ -571,16 +597,15 @@ fido_cred_reset_tx(fido_cred_t *cred)
cred->type = 0;
cred->rk = FIDO_OPT_OMIT;
cred->uv = FIDO_OPT_OMIT;
cred->ea.mode = 0;
}
void
fido_cred_reset_rx(fido_cred_t *cred)
{
free(cred->fmt);
cred->fmt = NULL;
fido_cred_clean_authdata(cred);
fido_cred_clean_attstmt(&cred->attstmt);
fido_cred_clean_attobj(cred);
fido_blob_reset(&cred->largeblob_key);
cred->ea.att = false;
}
void
@@ -688,9 +713,30 @@ fido_cred_set_id(fido_cred_t *cred, const unsigned char *ptr, size_t len)
int
fido_cred_set_x509(fido_cred_t *cred, const unsigned char *ptr, size_t len)
{
if (fido_blob_set(&cred->attstmt.x5c, ptr, len) < 0)
fido_blob_t x5c_blob;
fido_blob_t *list_ptr = NULL;
memset(&x5c_blob, 0, sizeof(x5c_blob));
fido_free_blob_array(&cred->attstmt.x5c);
if (fido_blob_set(&x5c_blob, ptr, len) < 0)
return (FIDO_ERR_INVALID_ARGUMENT);
if (cred->attstmt.x5c.len == SIZE_MAX) {
fido_blob_reset(&x5c_blob);
return (FIDO_ERR_INVALID_ARGUMENT);
}
if ((list_ptr = recallocarray(cred->attstmt.x5c.ptr,
cred->attstmt.x5c.len, cred->attstmt.x5c.len + 1,
sizeof(x5c_blob))) == NULL) {
fido_blob_reset(&x5c_blob);
return (FIDO_ERR_INTERNAL);
}
list_ptr[cred->attstmt.x5c.len++] = x5c_blob;
cred->attstmt.x5c.ptr = list_ptr;
return (FIDO_OK);
}
@@ -736,6 +782,35 @@ fido_cred_set_attstmt(fido_cred_t *cred, const unsigned char *ptr, size_t len)
return (r);
}
int
fido_cred_set_attobj(fido_cred_t *cred, const unsigned char *ptr, size_t len)
{
cbor_item_t *item = NULL;
struct cbor_load_result cbor;
int r = FIDO_ERR_INVALID_ARGUMENT;
fido_cred_clean_attobj(cred);
if (ptr == NULL || len == 0)
goto fail;
if ((item = cbor_load(ptr, len, &cbor)) == NULL) {
fido_log_debug("%s: cbor_load", __func__);
goto fail;
}
if (cbor_decode_attobj(item, cred) != 0) {
fido_log_debug("%s: cbor_decode_attobj", __func__);
goto fail;
}
r = FIDO_OK;
fail:
if (item != NULL)
cbor_decref(&item);
return (r);
}
int
fido_cred_exclude(fido_cred_t *cred, const unsigned char *id_ptr, size_t id_len)
{
@@ -919,6 +994,18 @@ fido_cred_set_uv(fido_cred_t *cred, fido_opt_t uv)
return (FIDO_OK);
}
int
fido_cred_set_entattest(fido_cred_t *cred, int ea)
{
if (ea != 0 && ea != FIDO_ENTATTEST_VENDOR &&
ea != FIDO_ENTATTEST_PLATFORM)
return (FIDO_ERR_INVALID_ARGUMENT);
cred->ea.mode = ea;
return (FIDO_OK);
}
int
fido_cred_set_prot(fido_cred_t *cred, int prot)
{
@@ -1030,15 +1117,39 @@ fido_cred_clientdata_hash_len(const fido_cred_t *cred)
const unsigned char *
fido_cred_x5c_ptr(const fido_cred_t *cred)
{
return (cred->attstmt.x5c.ptr);
return (fido_cred_x5c_list_ptr(cred, 0));
}
size_t
fido_cred_x5c_len(const fido_cred_t *cred)
{
return (fido_cred_x5c_list_len(cred, 0));
}
size_t
fido_cred_x5c_list_count(const fido_cred_t *cred)
{
return (cred->attstmt.x5c.len);
}
const unsigned char *
fido_cred_x5c_list_ptr(const fido_cred_t *cred, size_t i)
{
if (i >= cred->attstmt.x5c.len)
return (NULL);
return (cred->attstmt.x5c.ptr[i].ptr);
}
size_t
fido_cred_x5c_list_len(const fido_cred_t *cred, size_t i)
{
if (i >= cred->attstmt.x5c.len)
return (0);
return (cred->attstmt.x5c.ptr[i].len);
}
const unsigned char *
fido_cred_sig_ptr(const fido_cred_t *cred)
{
@@ -1228,3 +1339,9 @@ fido_cred_largeblob_key_len(const fido_cred_t *cred)
{
return (cred->largeblob_key.len);
}
bool
fido_cred_entattest(const fido_cred_t *cred)
{
return (cred->ea.att);
}
+10 -1
View File
@@ -111,6 +111,15 @@ credman_prepare_hmac(uint8_t cmd, const void *body, cbor_item_t **param,
return (ok);
}
static uint8_t
credman_get_cmd(const fido_dev_t *dev)
{
if (dev->flags & FIDO_DEV_CREDMAN)
return (CTAP_CBOR_CRED_MGMT);
return (CTAP_CBOR_CRED_MGMT_PRE);
}
static int
credman_tx(fido_dev_t *dev, uint8_t subcmd, const void *param, const char *pin,
const char *rp_id, fido_opt_t uv, int *ms)
@@ -120,7 +129,7 @@ credman_tx(fido_dev_t *dev, uint8_t subcmd, const void *param, const char *pin,
fido_blob_t hmac;
es256_pk_t *pk = NULL;
cbor_item_t *argv[4];
const uint8_t cmd = CTAP_CBOR_CRED_MGMT_PRE;
const uint8_t cmd = credman_get_cmd(dev);
int r = FIDO_ERR_INTERNAL;
memset(&f, 0, sizeof(f));
+8 -3
View File
@@ -46,16 +46,21 @@ fido_dev_set_option_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
if (strcmp(ptr[i], "clientPin") == 0) {
dev->flags |= val[i] ?
FIDO_DEV_PIN_SET : FIDO_DEV_PIN_UNSET;
} else if (strcmp(ptr[i], "credMgmt") == 0 ||
strcmp(ptr[i], "credentialMgmtPreview") == 0) {
} else if (strcmp(ptr[i], "credMgmt") == 0) {
if (val[i])
dev->flags |= FIDO_DEV_CREDMAN;
} else if (strcmp(ptr[i], "credentialMgmtPreview") == 0) {
if (val[i])
dev->flags |= FIDO_DEV_CREDMAN_PRE;
} else if (strcmp(ptr[i], "uv") == 0) {
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;
} else if (strcmp(ptr[i], "bioEnroll") == 0) {
dev->flags |= val[i] ?
FIDO_DEV_BIO_SET : FIDO_DEV_BIO_UNSET;
}
}
@@ -538,7 +543,7 @@ fido_dev_supports_cred_prot(const fido_dev_t *dev)
bool
fido_dev_supports_credman(const fido_dev_t *dev)
{
return (dev->flags & FIDO_DEV_CREDMAN);
return (dev->flags & (FIDO_DEV_CREDMAN|FIDO_DEV_CREDMAN_PRE));
}
bool
+6
View File
@@ -130,6 +130,7 @@
fido_cred_clientdata_hash_ptr;
fido_cred_display_name;
fido_cred_empty_exclude_list;
fido_cred_entattest;
fido_cred_exclude;
fido_cred_flags;
fido_cred_largeblob_key_len;
@@ -169,11 +170,13 @@
fido_cred_rp_id;
fido_cred_rp_name;
fido_cred_set_attstmt;
fido_cred_set_attobj;
fido_cred_set_authdata;
fido_cred_set_authdata_raw;
fido_cred_set_blob;
fido_cred_set_clientdata;
fido_cred_set_clientdata_hash;
fido_cred_set_entattest;
fido_cred_set_extensions;
fido_cred_set_fmt;
fido_cred_set_id;
@@ -196,6 +199,9 @@
fido_cred_verify;
fido_cred_verify_self;
fido_cred_x5c_len;
fido_cred_x5c_list_count;
fido_cred_x5c_list_len;
fido_cred_x5c_list_ptr;
fido_cred_x5c_ptr;
fido_dev_build;
fido_dev_cancel;
+6
View File
@@ -128,6 +128,7 @@ _fido_cred_clientdata_hash_len
_fido_cred_clientdata_hash_ptr
_fido_cred_display_name
_fido_cred_empty_exclude_list
_fido_cred_entattest
_fido_cred_exclude
_fido_cred_flags
_fido_cred_largeblob_key_len
@@ -167,11 +168,13 @@ _fido_cred_pubkey_ptr
_fido_cred_rp_id
_fido_cred_rp_name
_fido_cred_set_attstmt
_fido_cred_set_attobj
_fido_cred_set_authdata
_fido_cred_set_authdata_raw
_fido_cred_set_blob
_fido_cred_set_clientdata
_fido_cred_set_clientdata_hash
_fido_cred_set_entattest
_fido_cred_set_extensions
_fido_cred_set_fmt
_fido_cred_set_id
@@ -194,6 +197,9 @@ _fido_cred_user_name
_fido_cred_verify
_fido_cred_verify_self
_fido_cred_x5c_len
_fido_cred_x5c_list_count
_fido_cred_x5c_list_len
_fido_cred_x5c_list_ptr
_fido_cred_x5c_ptr
_fido_dev_build
_fido_dev_cancel
+6
View File
@@ -129,6 +129,7 @@ fido_cred_clientdata_hash_len
fido_cred_clientdata_hash_ptr
fido_cred_display_name
fido_cred_empty_exclude_list
fido_cred_entattest
fido_cred_exclude
fido_cred_flags
fido_cred_largeblob_key_len
@@ -168,11 +169,13 @@ fido_cred_pubkey_ptr
fido_cred_rp_id
fido_cred_rp_name
fido_cred_set_attstmt
fido_cred_set_attobj
fido_cred_set_authdata
fido_cred_set_authdata_raw
fido_cred_set_blob
fido_cred_set_clientdata
fido_cred_set_clientdata_hash
fido_cred_set_entattest
fido_cred_set_extensions
fido_cred_set_fmt
fido_cred_set_id
@@ -195,6 +198,9 @@ fido_cred_user_name
fido_cred_verify
fido_cred_verify_self
fido_cred_x5c_len
fido_cred_x5c_list_count
fido_cred_x5c_list_len
fido_cred_x5c_list_ptr
fido_cred_x5c_ptr
fido_dev_build
fido_dev_cancel
+14 -10
View File
@@ -58,6 +58,7 @@ cbor_item_t *es256_pk_encode(const es256_pk_t *, int);
/* cbor decoding functions */
int cbor_decode_attstmt(const cbor_item_t *, fido_attstmt_t *);
int cbor_decode_attobj(const cbor_item_t *, fido_cred_t *);
int cbor_decode_bool(const cbor_item_t *, bool *);
int cbor_decode_cred_authdata(const cbor_item_t *, int, fido_blob_t *,
fido_authdata_t *, fido_attcred_t *, fido_cred_ext_t *);
@@ -249,16 +250,19 @@ uint32_t uniform_random(uint32_t);
#endif
/* internal device capability flags */
#define FIDO_DEV_PIN_SET 0x001
#define FIDO_DEV_PIN_UNSET 0x002
#define FIDO_DEV_CRED_PROT 0x004
#define FIDO_DEV_CREDMAN 0x008
#define FIDO_DEV_PIN_PROTOCOL1 0x010
#define FIDO_DEV_PIN_PROTOCOL2 0x020
#define FIDO_DEV_UV_SET 0x040
#define FIDO_DEV_UV_UNSET 0x080
#define FIDO_DEV_TOKEN_PERMS 0x100
#define FIDO_DEV_WINHELLO 0x200
#define FIDO_DEV_PIN_SET 0x0001
#define FIDO_DEV_PIN_UNSET 0x0002
#define FIDO_DEV_CRED_PROT 0x0004
#define FIDO_DEV_CREDMAN 0x0008
#define FIDO_DEV_PIN_PROTOCOL1 0x0010
#define FIDO_DEV_PIN_PROTOCOL2 0x0020
#define FIDO_DEV_UV_SET 0x0040
#define FIDO_DEV_UV_UNSET 0x0080
#define FIDO_DEV_TOKEN_PERMS 0x0100
#define FIDO_DEV_WINHELLO 0x0200
#define FIDO_DEV_CREDMAN_PRE 0x0400
#define FIDO_DEV_BIO_SET 0x0800
#define FIDO_DEV_BIO_UNSET 0x1000
/* miscellanea */
#define FIDO_DUMMY_CLIENTDATA ""
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Copyright (c) 2018-2024 Yubico AB. All rights reserved.
* SPDX-License-Identifier: BSD-2-Clause
*
* Redistribution and use in source and binary forms, with or without
@@ -124,6 +124,7 @@ const unsigned char *fido_cred_pubkey_ptr(const fido_cred_t *);
const unsigned char *fido_cred_sig_ptr(const fido_cred_t *);
const unsigned char *fido_cred_user_id_ptr(const fido_cred_t *);
const unsigned char *fido_cred_x5c_ptr(const fido_cred_t *);
const unsigned char *fido_cred_x5c_list_ptr(const fido_cred_t *, size_t);
int fido_assert_allow_cred(fido_assert_t *, const unsigned char *, size_t);
int fido_assert_empty_allow_list(fido_assert_t *);
@@ -148,14 +149,17 @@ int fido_assert_set_winhello_appid(fido_assert_t *, const char *);
int fido_assert_verify(const fido_assert_t *, size_t, int, const void *);
int fido_cbor_info_algorithm_cose(const fido_cbor_info_t *, size_t);
int fido_cred_empty_exclude_list(fido_cred_t *);
bool fido_cred_entattest(const fido_cred_t *);
int fido_cred_exclude(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_prot(const fido_cred_t *);
int fido_cred_set_attstmt(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_attobj(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_authdata(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_authdata_raw(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_blob(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_clientdata(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_clientdata_hash(fido_cred_t *, const unsigned char *, size_t);
int fido_cred_set_entattest(fido_cred_t *, int);
int fido_cred_set_extensions(fido_cred_t *, int);
int fido_cred_set_fmt(fido_cred_t *, const char *);
int fido_cred_set_id(fido_cred_t *, const unsigned char *, size_t);
@@ -226,6 +230,8 @@ size_t fido_cred_pubkey_len(const fido_cred_t *);
size_t fido_cred_sig_len(const fido_cred_t *);
size_t fido_cred_user_id_len(const fido_cred_t *);
size_t fido_cred_x5c_len(const fido_cred_t *);
size_t fido_cred_x5c_list_count(const fido_cred_t *);
size_t fido_cred_x5c_list_len(const fido_cred_t *, size_t);
uint8_t fido_assert_flags(const fido_assert_t *, size_t);
uint32_t fido_assert_sigcount(const fido_assert_t *, size_t);
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Copyright (c) 2018-2024 Yubico AB. All rights reserved.
* SPDX-License-Identifier: BSD-2-Clause
*
* Redistribution and use in source and binary forms, with or without
@@ -53,6 +53,8 @@
#define CTAP_CBOR_CLIENT_PIN 0x06
#define CTAP_CBOR_RESET 0x07
#define CTAP_CBOR_NEXT_ASSERT 0x08
#define CTAP_CBOR_BIO_ENROLL 0x09
#define CTAP_CBOR_CRED_MGMT 0x0a
#define CTAP_CBOR_LARGEBLOB 0x0c
#define CTAP_CBOR_CONFIG 0x0d
#define CTAP_CBOR_BIO_ENROLL_PRE 0x40
@@ -72,6 +74,7 @@
/* ISO7816-4 status words. */
#define SW1_MORE_DATA 0x61
#define SW_WRONG_LENGTH 0x6700
#define SW_CONDITIONS_NOT_SATISFIED 0x6985
#define SW_WRONG_DATA 0x6a80
#define SW_NO_ERROR 0x9000
@@ -134,6 +137,10 @@
#define FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID 0x02
#define FIDO_CRED_PROT_UV_REQUIRED 0x03
/* Supported enterprise attestation modes. */
#define FIDO_ENTATTEST_VENDOR 1
#define FIDO_ENTATTEST_PLATFORM 2
#ifdef _FIDO_INTERNAL
#define FIDO_EXT_ASSERT_MASK (FIDO_EXT_HMAC_SECRET|FIDO_EXT_LARGEBLOB_KEY| \
FIDO_EXT_CRED_BLOB)
+13 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2022 Yubico AB. All rights reserved.
* Copyright (c) 2018-2024 Yubico AB. All rights reserved.
* SPDX-License-Identifier: BSD-2-Clause
*
* Redistribution and use in source and binary forms, with or without
@@ -140,12 +140,12 @@ typedef struct fido_attcred {
} fido_attcred_t;
typedef struct fido_attstmt {
fido_blob_t certinfo; /* tpm attestation TPMS_ATTEST structure */
fido_blob_t pubarea; /* tpm attestation TPMT_PUBLIC structure */
fido_blob_t cbor; /* cbor-encoded attestation statement */
fido_blob_t x5c; /* attestation certificate */
fido_blob_t sig; /* attestation signature */
int alg; /* attestation algorithm (cose) */
fido_blob_t certinfo; /* tpm attestation TPMS_ATTEST structure */
fido_blob_t pubarea; /* tpm attestation TPMT_PUBLIC structure */
fido_blob_t cbor; /* cbor-encoded attestation statement */
fido_blob_array_t x5c; /* attestation certificate chain */
fido_blob_t sig; /* attestation signature */
int alg; /* attestation algorithm (cose) */
} fido_attstmt_t;
typedef struct fido_rp {
@@ -166,6 +166,11 @@ typedef struct fido_cred_ext {
size_t minpinlen; /* minimum pin length */
} fido_cred_ext_t;
typedef struct fido_cred_ea {
int mode;
bool att;
} fido_cred_ea_t;
typedef struct fido_cred {
fido_blob_t cd; /* client data */
fido_blob_t cdh; /* client data hash */
@@ -185,6 +190,7 @@ typedef struct fido_cred {
fido_attstmt_t attstmt; /* attestation statement (x509 + sig) */
fido_blob_t largeblob_key; /* decoded large blob key */
fido_blob_t blob; /* CTAP 2.1 credBlob */
fido_cred_ea_t ea; /* enterprise attestation */
} fido_cred_t;
typedef struct fido_assert_extattr {
+26 -10
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Copyright (c) 2019-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -77,12 +77,13 @@ is_fido(const char *path)
static int
parse_uevent(const char *uevent, int *bus, int16_t *vendor_id,
int16_t *product_id)
int16_t *product_id, char **hid_name)
{
char *cp;
char *p;
char *s;
int ok = -1;
bool found_id = false;
bool found_name = false;
short unsigned int x;
short unsigned int y;
short unsigned int z;
@@ -91,20 +92,25 @@ parse_uevent(const char *uevent, int *bus, int16_t *vendor_id,
return (-1);
while ((p = strsep(&cp, "\n")) != NULL && *p != '\0') {
if (strncmp(p, "HID_ID=", 7) == 0) {
if (!found_id && strncmp(p, "HID_ID=", 7) == 0) {
if (sscanf(p + 7, "%hx:%hx:%hx", &x, &y, &z) == 3) {
*bus = (int)x;
*vendor_id = (int16_t)y;
*product_id = (int16_t)z;
ok = 0;
break;
found_id = true;
}
} else if (!found_name && strncmp(p, "HID_NAME=", 9) == 0) {
if ((*hid_name = strdup(p + 9)) != NULL)
found_name = true;
}
}
free(s);
return (ok);
if (!found_name || !found_id)
return (-1);
return (0);
}
static char *
@@ -137,6 +143,7 @@ copy_info(fido_dev_info_t *di, struct udev *udev,
char *uevent = NULL;
struct udev_device *dev = NULL;
int bus = 0;
char *hid_name = NULL;
int ok = -1;
memset(di, 0, sizeof(*di));
@@ -148,7 +155,8 @@ copy_info(fido_dev_info_t *di, struct udev *udev,
goto fail;
if ((uevent = get_parent_attr(dev, "hid", NULL, "uevent")) == NULL ||
parse_uevent(uevent, &bus, &di->vendor_id, &di->product_id) < 0) {
parse_uevent(uevent, &bus, &di->vendor_id, &di->product_id,
&hid_name) < 0) {
fido_log_debug("%s: uevent", __func__);
goto fail;
}
@@ -161,9 +169,16 @@ copy_info(fido_dev_info_t *di, struct udev *udev,
#endif
di->path = strdup(path);
if ((di->manufacturer = get_usb_attr(dev, "manufacturer")) == NULL)
di->manufacturer = get_usb_attr(dev, "manufacturer");
di->product = get_usb_attr(dev, "product");
if (di->manufacturer == NULL && di->product == NULL) {
di->product = hid_name; /* fallback */
hid_name = NULL;
}
if (di->manufacturer == NULL)
di->manufacturer = strdup("");
if ((di->product = get_usb_attr(dev, "product")) == NULL)
if (di->product == NULL)
di->product = strdup("");
if (di->path == NULL || di->manufacturer == NULL || di->product == NULL)
goto fail;
@@ -174,6 +189,7 @@ copy_info(fido_dev_info_t *di, struct udev *udev,
udev_device_unref(dev);
free(uevent);
free(hid_name);
if (ok < 0) {
free(di->path);
+3 -3
View File
@@ -127,14 +127,14 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
char path[64];
size_t i;
if (devlist == NULL || olen == NULL)
return (FIDO_ERR_INVALID_ARGUMENT);
*olen = 0;
if (ilen == 0)
return (FIDO_OK); /* nothing to do */
if (devlist == NULL || olen == NULL)
return (FIDO_ERR_INVALID_ARGUMENT);
for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) {
snprintf(path, sizeof(path), "/dev/uhid%zu", i);
if (copy_info(&devlist[*olen], path) == 0) {
+28 -14
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
* Copyright (c) 2019-2023 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -523,6 +523,21 @@ fido_hid_set_sigmask(void *handle, const fido_sigset_t *sigmask)
return (FIDO_ERR_INTERNAL);
}
static void
schedule_io_loop(struct hid_osx *ctx, int ms)
{
IOHIDDeviceScheduleWithRunLoop(ctx->ref, CFRunLoopGetCurrent(),
ctx->loop_id);
if (ms == -1)
ms = 5000; /* wait 5 seconds by default */
CFRunLoopRunInMode(ctx->loop_id, (double)ms/1000.0, true);
IOHIDDeviceUnscheduleFromRunLoop(ctx->ref, CFRunLoopGetCurrent(),
ctx->loop_id);
}
int
fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms)
{
@@ -537,20 +552,19 @@ fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms)
return (-1);
}
IOHIDDeviceScheduleWithRunLoop(ctx->ref, CFRunLoopGetCurrent(),
ctx->loop_id);
if (ms == -1)
ms = 5000; /* wait 5 seconds by default */
CFRunLoopRunInMode(ctx->loop_id, (double)ms/1000.0, true);
IOHIDDeviceUnscheduleFromRunLoop(ctx->ref, CFRunLoopGetCurrent(),
ctx->loop_id);
/* check for pending frame */
if ((r = read(ctx->report_pipe[0], buf, len)) == -1) {
fido_log_error(errno, "%s: read", __func__);
return (-1);
if (errno != EAGAIN && errno != EWOULDBLOCK) {
fido_log_error(errno, "%s: read", __func__);
return (-1);
}
schedule_io_loop(ctx, ms);
if ((r = read(ctx->report_pipe[0], buf, len)) == -1) {
fido_log_error(errno, "%s: read", __func__);
return (-1);
}
}
if (r < 0 || (size_t)r != len) {
+51 -47
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2022 Yubico AB. All rights reserved.
* Copyright (c) 2020-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -34,7 +34,10 @@ tx_short_apdu(fido_dev_t *d, const iso7816_header_t *h, const uint8_t *payload,
apdu[3] = h->p2;
apdu[4] = payload_len;
memcpy(&apdu[5], payload, payload_len);
apdu_len = (size_t)(5 + payload_len + 1);
apdu_len = (size_t)(5 + payload_len);
if (!(cla_flags & 0x10))
apdu_len += 1;
if (d->io.write(d->io_handle, apdu, apdu_len) < 0) {
fido_log_debug("%s: write", __func__);
@@ -144,51 +147,12 @@ fido_nfc_tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count)
}
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)
tx_get_response(fido_dev_t *d, uint8_t count, bool cbor)
{
uint8_t apdu[5];
memset(apdu, 0, sizeof(apdu));
apdu[0] = cbor ? 0x80 : 0x00;
apdu[1] = 0xc0; /* GET_RESPONSE */
apdu[4] = count;
@@ -233,7 +197,7 @@ rx_apdu(fido_dev_t *d, uint8_t sw[2], unsigned char **buf, size_t *count, int *m
}
static int
rx_msg(fido_dev_t *d, unsigned char *buf, size_t count, int ms)
rx_msg(fido_dev_t *d, unsigned char *buf, size_t count, int ms, bool cbor)
{
uint8_t sw[2];
const size_t bufsiz = count;
@@ -244,7 +208,7 @@ rx_msg(fido_dev_t *d, unsigned char *buf, size_t count, int ms)
}
while (sw[0] == SW1_MORE_DATA)
if (tx_get_response(d, sw[1]) < 0 ||
if (tx_get_response(d, sw[1], cbor) < 0 ||
rx_apdu(d, sw, &buf, &count, &ms) < 0) {
fido_log_debug("%s: chain", __func__);
return -1;
@@ -268,12 +232,52 @@ 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)
if ((r = rx_msg(d, buf, count, ms, true)) < 2)
return -1;
return r - 2;
}
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 = rx_msg(d, f, sizeof(f), ms, false)) < 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;
}
int
fido_nfc_rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms)
{
@@ -283,7 +287,7 @@ fido_nfc_rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms
case CTAP_CMD_CBOR:
return rx_cbor(d, buf, count, ms);
case CTAP_CMD_MSG:
return rx_msg(d, buf, count, ms);
return rx_msg(d, buf, count, ms, false);
default:
fido_log_debug("%s: cmd=%02x", __func__, cmd);
return -1;
+2
View File
@@ -131,12 +131,14 @@ encode_uv_permission(uint8_t cmd)
case CTAP_CBOR_ASSERT:
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_ASSERT));
case CTAP_CBOR_BIO_ENROLL_PRE:
case CTAP_CBOR_BIO_ENROLL:
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_BIO));
case CTAP_CBOR_CONFIG:
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_CONFIG));
case CTAP_CBOR_MAKECRED:
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_MAKECRED));
case CTAP_CBOR_CRED_MGMT_PRE:
case CTAP_CBOR_CRED_MGMT:
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_CRED_MGMT));
case CTAP_CBOR_LARGEBLOB:
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_LARGEBLOB));
+11 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Yubico AB. All rights reserved.
* Copyright (c) 2018-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -16,6 +16,13 @@
#include <unistd.h>
#endif
#if defined(__has_feature)
# if __has_feature(memory_sanitizer)
# include <sanitizer/msan_interface.h>
# define WITH_MSAN 1
# endif
#endif
#include "fido.h"
#if defined(_WIN32)
@@ -45,6 +52,9 @@ int
fido_get_random(void *buf, size_t len)
{
arc4random_buf(buf, len);
#ifdef WITH_MSAN
__msan_unpoison(buf, len); /* XXX */
#endif
return (0);
}
#elif defined(HAVE_GETRANDOM)
+9 -44
View File
@@ -10,55 +10,21 @@
#include "fido.h"
#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050200fL
static EVP_MD *
rs1_get_EVP_MD(void)
{
const EVP_MD *from;
EVP_MD *to = NULL;
if ((from = EVP_sha1()) != NULL && (to = malloc(sizeof(*to))) != NULL)
memcpy(to, from, sizeof(*to));
return (to);
}
static void
rs1_free_EVP_MD(EVP_MD *md)
{
freezero(md, sizeof(*md));
}
#elif OPENSSL_VERSION_NUMBER >= 0x30000000
static EVP_MD *
rs1_get_EVP_MD(void)
{
return (EVP_MD_fetch(NULL, "SHA-1", NULL));
}
static void
rs1_free_EVP_MD(EVP_MD *md)
{
EVP_MD_free(md);
}
#if defined(__GNUC__)
#define PRAGMA(s) _Pragma(s)
#else
#define PRAGMA(s)
#endif
static EVP_MD *
rs1_get_EVP_MD(void)
{
const EVP_MD *md;
if ((md = EVP_sha1()) == NULL)
return (NULL);
return (EVP_MD_meth_dup(md));
PRAGMA("GCC diagnostic push")
PRAGMA("GCC diagnostic ignored \"-Wcast-qual\"")
return ((EVP_MD *)EVP_sha1());
PRAGMA("GCC diagnostic pop")
}
static void
rs1_free_EVP_MD(EVP_MD *md)
{
EVP_MD_meth_free(md);
}
#endif /* LIBRESSL_VERSION_NUMBER */
int
rs1_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
const fido_blob_t *sig)
@@ -94,7 +60,6 @@ rs1_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
ok = 0;
fail:
EVP_PKEY_CTX_free(pctx);
rs1_free_EVP_MD(md);
return (ok);
}
+9 -44
View File
@@ -18,55 +18,21 @@
#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)
{
const EVP_MD *from;
EVP_MD *to = NULL;
if ((from = EVP_sha256()) != NULL && (to = malloc(sizeof(*to))) != NULL)
memcpy(to, from, sizeof(*to));
return (to);
}
static void
rs256_free_EVP_MD(EVP_MD *md)
{
freezero(md, sizeof(*md));
}
#elif OPENSSL_VERSION_NUMBER >= 0x30000000
static EVP_MD *
rs256_get_EVP_MD(void)
{
return (EVP_MD_fetch(NULL, "SHA2-256", NULL));
}
static void
rs256_free_EVP_MD(EVP_MD *md)
{
EVP_MD_free(md);
}
#if defined(__GNUC__)
#define PRAGMA(s) _Pragma(s)
#else
#define PRAGMA(s)
#endif
static EVP_MD *
rs256_get_EVP_MD(void)
{
const EVP_MD *md;
if ((md = EVP_sha256()) == NULL)
return (NULL);
return (EVP_MD_meth_dup(md));
PRAGMA("GCC diagnostic push")
PRAGMA("GCC diagnostic ignored \"-Wcast-qual\"")
return ((EVP_MD *)EVP_sha256());
PRAGMA("GCC diagnostic pop")
}
static void
rs256_free_EVP_MD(EVP_MD *md)
{
EVP_MD_meth_free(md);
}
#endif /* LIBRESSL_VERSION_NUMBER */
static int
decode_bignum(const cbor_item_t *item, void *ptr, size_t len)
{
@@ -290,7 +256,6 @@ rs256_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
ok = 0;
fail:
EVP_PKEY_CTX_free(pctx);
rs256_free_EVP_MD(md);
return (ok);
}
+1
View File
@@ -260,6 +260,7 @@ key_lookup(fido_dev_t *dev, const char *rp_id, const fido_blob_t *key_id,
*found = 1; /* key exists */
break;
case SW_WRONG_DATA:
case SW_WRONG_LENGTH:
*found = 0; /* key does not exist */
break;
default:
+9 -49
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022 Yubico AB. All rights reserved.
* Copyright (c) 2021-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -735,54 +735,14 @@ translate_fido_cred(struct winhello_cred *ctx, const fido_cred_t *cred,
if (cred->rk == FIDO_OPT_TRUE) {
opt->bRequireResidentKey = true;
}
if (cred->ea.mode != 0) {
opt->dwVersion = WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4;
opt->dwEnterpriseAttestation = (DWORD)cred->ea.mode;
}
return FIDO_OK;
}
static int
decode_attobj(const cbor_item_t *key, const cbor_item_t *val, void *arg)
{
fido_cred_t *cred = arg;
char *name = NULL;
int ok = -1;
if (cbor_string_copy(key, &name) < 0) {
fido_log_debug("%s: cbor type", __func__);
ok = 0; /* ignore */
goto fail;
}
if (!strcmp(name, "fmt")) {
if (cbor_decode_fmt(val, &cred->fmt) < 0) {
fido_log_debug("%s: cbor_decode_fmt", __func__);
goto fail;
}
} else if (!strcmp(name, "attStmt")) {
if (cbor_decode_attstmt(val, &cred->attstmt) < 0) {
fido_log_debug("%s: cbor_decode_attstmt", __func__);
goto fail;
}
} else if (!strcmp(name, "authData")) {
if (fido_blob_decode(val, &cred->authdata_raw) < 0) {
fido_log_debug("%s: fido_blob_decode", __func__);
goto fail;
}
if (cbor_decode_cred_authdata(val, cred->type,
&cred->authdata_cbor, &cred->authdata, &cred->attcred,
&cred->authdata_ext) < 0) {
fido_log_debug("%s: cbor_decode_cred_authdata",
__func__);
goto fail;
}
}
ok = 0;
fail:
free(name);
return (ok);
}
static int
translate_winhello_cred(fido_cred_t *cred,
const WEBAUTHN_CREDENTIAL_ATTESTATION *att)
@@ -800,12 +760,12 @@ translate_winhello_cred(fido_cred_t *cred,
fido_log_debug("%s: cbor_load", __func__);
goto fail;
}
if (cbor_isa_map(item) == false ||
cbor_map_is_definite(item) == false ||
cbor_map_iter(item, cred, decode_attobj) < 0) {
fido_log_debug("%s: cbor type", __func__);
if (cbor_decode_attobj(item, cred) != 0) {
fido_log_debug("%s: cbor_decode_attobj", __func__);
goto fail;
}
if (att->dwVersion >= WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4)
cred->ea.att = att->bEpAtt;
r = FIDO_OK;
fail:
+12 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2023 Yubico AB. All rights reserved.
* Copyright (c) 2018-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -151,11 +151,16 @@ cred_make(int argc, char **argv)
int type = COSE_ES256;
int flags = 0;
int cred_protect = -1;
int ea = 0;
int ch;
int r;
while ((ch = getopt(argc, argv, "bc:dhi:o:qruvw")) != -1) {
while ((ch = getopt(argc, argv, "a:bc:dhi:o:qruvw")) != -1) {
switch (ch) {
case 'a':
if ((ea = base10(optarg)) < 0)
errx(1, "-a: invalid argument '%s'", optarg);
break;
case 'b':
flags |= FLAG_LARGEBLOB;
break;
@@ -221,6 +226,11 @@ cred_make(int argc, char **argv)
errx(1, "fido_cred_set_prot: %s", fido_strerr(r));
}
}
if (ea > 0) {
r = fido_cred_set_entattest(cred, ea);
if (r != FIDO_OK)
errx(1, "fido_cred_set_entattest: %s", fido_strerr(r));
}
r = fido_dev_make_cred(dev, cred, NULL);
if (r == FIDO_ERR_PIN_REQUIRED && !(flags & FLAG_QUIET)) {
+5 -2
View File
@@ -119,6 +119,7 @@ print_rk(const fido_credman_rk_t *rk, size_t idx)
char *user_id = NULL;
const char *type;
const char *prot;
int r = -1;
if ((cred = fido_credman_rk(rk, idx)) == NULL) {
warnx("fido_credman_rk");
@@ -128,7 +129,7 @@ print_rk(const fido_credman_rk_t *rk, size_t idx)
&id) < 0 || base64_encode(fido_cred_user_id_ptr(cred),
fido_cred_user_id_len(cred), &user_id) < 0) {
warnx("output error");
return -1;
goto out;
}
type = cose_string(fido_cred_type(cred));
@@ -137,10 +138,12 @@ print_rk(const fido_credman_rk_t *rk, size_t idx)
printf("%02u: %s %s %s %s %s\n", (unsigned)idx, id,
fido_cred_display_name(cred), user_id, type, prot);
r = 0;
out:
free(user_id);
free(id);
return 0;
return r;
}
int
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2023 Yubico AB. All rights reserved.
* Copyright (c) 2018-2024 Yubico AB. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
* SPDX-License-Identifier: BSD-2-Clause
@@ -27,7 +27,7 @@ void
usage(void)
{
fprintf(stderr,
"usage: fido2-cred -M [-bdhqruvw] [-c cred_protect] [-i input_file] [-o output_file] device [type]\n"
"usage: fido2-cred -M [-bdhqruvw] [-a mode] [-c cred_protect] [-i input_file] [-o output_file] device [type]\n"
" fido2-cred -V [-dhv] [-c cred_protect] [-i input_file] [-o output_file] [type]\n"
);
+21 -18
View File
@@ -6,53 +6,56 @@
# SPDX-License-Identifier: BSD-2-Clause
if [ $(uname) != "Linux" ] ; then
if [ "$(uname)" != "Linux" ] ; then
echo "Can only run on Linux"
exit 1
fi
TOKEN_VERSION=$(${FIDO_TOOLS_PREFIX}fido2-token -V 2>&1)
if [ $? -ne 0 ] ; then
if ! TOKEN_VERSION=$("${FIDO_TOOLS_PREFIX}"fido2-token -V 2>&1); then
echo "Please install libfido2 1.5.0 or higher"
exit
exit 1
fi
TOKEN_VERSION_MAJOR=$(echo "$TOKEN_VERSION" | cut -d. -f1)
TOKEN_VERSION_MINOR=$(echo "$TOKEN_VERSION" | cut -d. -f2)
if [ $TOKEN_VERSION_MAJOR -eq 0 -o $TOKEN_VERSION_MAJOR -eq 1 -a $TOKEN_VERSION_MINOR -lt 5 ] ; then
if [ "$TOKEN_VERSION_MAJOR" -eq 0 ] ; then
echo "Please install libfido2 1.5.0 or higher (current version: $TOKEN_VERSION)"
exit 1
fi
if [ "$TOKEN_VERSION_MAJOR" -eq 1 ] && [ "$TOKEN_VERSION_MINOR" -lt 5 ] ; then
echo "Please install libfido2 1.5.0 or higher (current version: $TOKEN_VERSION)"
exit 1
fi
set -e
TOKEN_OUTPUT=$(${FIDO_TOOLS_PREFIX}fido2-token -L)
TOKEN_OUTPUT=$("${FIDO_TOOLS_PREFIX}"fido2-token -L)
DEV_PATH_NAMES=$(echo "$TOKEN_OUTPUT" | sed -r 's/^(.*): .*\((.*)\)$/\1 \2/g')
DEV_COUNT=$(echo "$DEV_PATH_NAMES" | wc -l)
for i in $(seq 1 $DEV_COUNT)
for i in $(seq 1 "$DEV_COUNT")
do
DEV_PATH_NAME=$(echo "$DEV_PATH_NAMES" | sed "${i}q;d")
DEV_PATH=$(echo "$DEV_PATH_NAME" | cut -d' ' -f1)
DEV_NAME=$(echo "$DEV_PATH_NAME" | cut -d' ' -f1 --complement)
DEV_PRETTY=$(echo "$DEV_NAME (at '$DEV_PATH')")
if expr match "$(${FIDO_TOOLS_PREFIX}fido2-token -I $DEV_PATH)" ".* credMgmt.* clientPin.*\|.* clientPin.* credMgmt.*" > /dev/null ; then
printf "Enter PIN for $DEV_PRETTY once (ignore further prompts): "
DEV_PRETTY="$DEV_NAME (at '$DEV_PATH')"
if expr "$("${FIDO_TOOLS_PREFIX}"fido2-token -I "$DEV_PATH")" : ".* credMgmt.* clientPin.*\|.* clientPin.* credMgmt.*" > /dev/null ; then
printf "Enter PIN for %s once (ignore further prompts): " "$DEV_PRETTY"
stty -echo
read PIN
IFS= read -r PIN
stty echo
printf "\n"
RESIDENT_RPS=$(echo "${PIN}\n" | setsid -w ${FIDO_TOOLS_PREFIX}fido2-token -L -r $DEV_PATH | cut -d' ' -f3)
RESIDENT_RPS=$(printf "%s\n" "$PIN" | setsid -w "${FIDO_TOOLS_PREFIX}"fido2-token -L -r "$DEV_PATH" | cut -d' ' -f3)
printf "\n"
RESIDENT_RPS_COUNT=$(echo "$RESIDENT_RPS" | wc -l)
FOUND=0
for j in $(seq 1 $DEV_RESIDENT_RPS_COUNT)
for j in $(seq 1 "$RESIDENT_RPS_COUNT")
do
RESIDENT_RP=$(echo "$RESIDENT_RPS" | sed "${j}q;d")
UNPROT_CREDS=$(echo "${PIN}\n" | setsid -w ${FIDO_TOOLS_PREFIX}fido2-token -L -k $RESIDENT_RP $DEV_PATH | grep ' uvopt$' | cut -d' ' -f2,3,4)
UNPROT_CREDS=$(printf "%s\n" "$PIN" | setsid -w "${FIDO_TOOLS_PREFIX}"fido2-token -L -k "$RESIDENT_RP" "$DEV_PATH" | grep ' uvopt$' | cut -d' ' -f2,3,4)
printf "\n"
UNPROT_CREDS_COUNT=$(echo "$UNPROT_CREDS" | wc -l)
if [ $UNPROT_CREDS_COUNT -gt 0 ] ; then
if [ "$UNPROT_CREDS_COUNT" -gt 0 ] ; then
FOUND=1
echo "Unprotected credentials on $DEV_PRETTY for '$RESIDENT_RP':"
echo "$UNPROT_CREDS"
@@ -64,9 +67,9 @@ do
else
echo "$DEV_PRETTY cannot enumerate credentials"
echo "Discovering unprotected SSH credentials only..."
STUB_HASH=$(echo -n "" | openssl sha256 -binary | base64)
printf "$STUB_HASH\nssh:\n" | ${FIDO_TOOLS_PREFIX}fido2-assert -G -r -t up=false $DEV_PATH 2> /dev/null || ASSERT_EXIT_CODE=$?
if [ $ASSERT_EXIT_CODE -eq 0 ] ; then
STUB_HASH=$(printf "" | openssl sha256 -binary | base64)
printf "%s\nssh:\n" "$STUB_HASH" | "${FIDO_TOOLS_PREFIX}"fido2-assert -G -r -t up=false "$DEV_PATH" 2> /dev/null || ASSERT_EXIT_CODE=$?
if [ "$ASSERT_EXIT_CODE" -eq 0 ] ; then
echo "Found an unprotected SSH credential on $DEV_PRETTY!"
else
echo "No unprotected SSH credentials (default settings) on $DEV_PRETTY"
+12 -5
View File
@@ -1,15 +1,22 @@
#!/bin/sh
#!/bin/sh -u
# Copyright (c) 2019 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
SKIP='(webauthn.h)'
check() {
for f in $(find $1 -maxdepth 1 -name '*.h'); do
echo "#include \"$f\"" | \
cc $CFLAGS -Isrc -xc -c - -o /dev/null 2>&1
echo "$f $CFLAGS $?"
try="cc $CFLAGS -Isrc -xc -c - -o /dev/null 2>&1"
git ls-files "$1" | grep '.*\.h$' | while read -r header; do
if echo "$header" | grep -Eq "$SKIP"; then
echo "Skipping $header"
else
body="#include \"$header\""
echo "echo $body | $try"
echo "$body" | eval "$try"
fi
done
}
+75 -70
View File
@@ -13,7 +13,7 @@
# - should pass as-is on a YubiKey with a PIN set;
# - may otherwise require set +e above;
# - can be executed with UV=1 to run additional UV tests;
# - was last tested on 2022-01-11 with firmware 5.4.3.
# - was last tested on 2024-06-15 with firmware 5.7.1.
cd "$1"
DEV="$2"
@@ -28,11 +28,11 @@ $1
some user name
$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64)
EOF
fido2-cred -M $2 "${DEV}" "${TYPE}" > "$3" < cred_param
fido2-cred -M "$2" "${DEV}" "${TYPE}" > "$3" < cred_param
}
verify_cred() {
fido2-cred -V $1 "${TYPE}" > cred_out < "$2"
fido2-cred -V "$1" "${TYPE}" > cred_out < "$2" || return 1
head -1 cred_out > "$3"
tail -n +2 cred_out > "$4"
}
@@ -41,79 +41,84 @@ get_assert() {
sed /^$/d > assert_param << EOF
$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64)
$1
$(cat $3)
$(cat $4)
$(cat "$3")
$(cat "$4")
EOF
# we want to expand $2
# shellcheck disable=SC2086
fido2-assert -G $2 "${DEV}" > "$5" < assert_param
}
verify_assert() {
fido2-assert -V $1 "$2" "${TYPE}" < "$3"
fido2-assert -V "$1" "$2" "${TYPE}" < "$3"
}
dd if=/dev/urandom bs=32 count=1 | base64 > hmac-salt
# u2f
if [ "x${TYPE}" = "xes256" ]; then
if [ "${TYPE}" = "es256" ]; then
make_cred no.tld "-u" u2f
! make_cred no.tld "-ru" /dev/null
! make_cred no.tld "-uc1" /dev/null
! make_cred no.tld "-uc2" /dev/null
make_cred no.tld "-ru" /dev/null && exit 1
make_cred no.tld "-uc1" /dev/null && exit 1
make_cred no.tld "-uc2" /dev/null && exit 1
verify_cred "--" u2f u2f-cred u2f-pubkey
! verify_cred "-h" u2f /dev/null /dev/null
! verify_cred "-v" u2f /dev/null /dev/null
verify_cred "-h" u2f /dev/null /dev/null && exit 1
verify_cred "-v" u2f /dev/null /dev/null && exit 1
verify_cred "-c0" u2f /dev/null /dev/null
! verify_cred "-c1" u2f /dev/null /dev/null
! verify_cred "-c2" u2f /dev/null /dev/null
! verify_cred "-c3" u2f /dev/null /dev/null
verify_cred "-c1" u2f /dev/null /dev/null && exit 1
verify_cred "-c2" u2f /dev/null /dev/null && exit 1
verify_cred "-c3" u2f /dev/null /dev/null && exit 1
fi
# wrap (non-resident)
make_cred no.tld "--" wrap
verify_cred "--" wrap wrap-cred wrap-pubkey
! verify_cred "-h" wrap /dev/null /dev/null
! verify_cred "-v" wrap /dev/null /dev/null
verify_cred "--" wrap wrap-cred wrap-pubkey
verify_cred "-h" wrap /dev/null /dev/null && exit 1
verify_cred "-v" wrap /dev/null /dev/null && exit 1
verify_cred "-c0" wrap /dev/null /dev/null
! verify_cred "-c1" wrap /dev/null /dev/null
! verify_cred "-c2" wrap /dev/null /dev/null
! verify_cred "-c3" wrap /dev/null /dev/null
verify_cred "-c1" wrap /dev/null /dev/null && exit 1
verify_cred "-c2" wrap /dev/null /dev/null && exit 1
verify_cred "-c3" wrap /dev/null /dev/null && exit 1
# wrap (non-resident) + hmac-secret
make_cred no.tld "-h" wrap-hs
! verify_cred "--" wrap-hs /dev/null /dev/null
verify_cred "--" wrap-hs /dev/null /dev/null && exit 1
verify_cred "-h" wrap-hs wrap-hs-cred wrap-hs-pubkey
! verify_cred "-v" wrap-hs /dev/null /dev/null
verify_cred "-v" wrap-hs /dev/null /dev/null && exit 1
verify_cred "-hv" wrap-hs /dev/null /dev/null && exit 1
verify_cred "-hc0" wrap-hs /dev/null /dev/null
! verify_cred "-c0" wrap-hs /dev/null /dev/null
! verify_cred "-c1" wrap-hs /dev/null /dev/null
! verify_cred "-c2" wrap-hs /dev/null /dev/null
! verify_cred "-c3" wrap-hs /dev/null /dev/null
verify_cred "-c0" wrap-hs /dev/null /dev/null && exit 1
verify_cred "-c1" wrap-hs /dev/null /dev/null && exit 1
verify_cred "-c2" wrap-hs /dev/null /dev/null && exit 1
verify_cred "-c3" wrap-hs /dev/null /dev/null && exit 1
# resident
make_cred no.tld "-r" rk
verify_cred "--" rk rk-cred rk-pubkey
! verify_cred "-h" rk /dev/null /dev/null
! verify_cred "-v" rk /dev/null /dev/null
verify_cred "-h" rk /dev/null /dev/null && exit 1
verify_cred "-v" rk /dev/null /dev/null
verify_cred "-hv" rk /dev/null /dev/null && exit 1
verify_cred "-c0" rk /dev/null /dev/null
! verify_cred "-c1" rk /dev/null /dev/null
! verify_cred "-c2" rk /dev/null /dev/null
! verify_cred "-c3" rk /dev/null /dev/null
verify_cred "-c1" rk /dev/null /dev/null && exit 1
verify_cred "-c2" rk /dev/null /dev/null && exit 1
verify_cred "-c3" rk /dev/null /dev/null && exit 1
# resident + hmac-secret
make_cred no.tld "-hr" rk-hs
! verify_cred "--" rk-hs rk-hs-cred rk-hs-pubkey
verify_cred "--" rk-hs rk-hs-cred rk-hs-pubkey && exit 1
verify_cred "-h" rk-hs /dev/null /dev/null
! verify_cred "-v" rk-hs /dev/null /dev/null
verify_cred "-v" rk-hs /dev/null /dev/null && exit 1
verify_cred "-hv" rk-hs /dev/null /dev/null
verify_cred "-hc0" rk-hs /dev/null /dev/null
! verify_cred "-c0" rk-hs /dev/null /dev/null
! verify_cred "-c1" rk-hs /dev/null /dev/null
! verify_cred "-c2" rk-hs /dev/null /dev/null
! verify_cred "-c3" rk-hs /dev/null /dev/null
verify_cred "-c0" rk-hs /dev/null /dev/null && exit 1
verify_cred "-c1" rk-hs /dev/null /dev/null && exit 1
verify_cred "-c2" rk-hs /dev/null /dev/null && exit 1
verify_cred "-c3" rk-hs /dev/null /dev/null && exit 1
# u2f
if [ "x${TYPE}" = "xes256" ]; then
if [ "${TYPE}" = "es256" ]; then
get_assert no.tld "-u" u2f-cred /dev/null u2f-assert
! get_assert no.tld "-u -t up=false" u2f-cred /dev/null /dev/null
get_assert no.tld "-u -t up=false" u2f-cred /dev/null /dev/null && exit 1
verify_assert "--" u2f-pubkey u2f-assert
verify_assert "-p" u2f-pubkey u2f-assert
fi
@@ -138,40 +143,40 @@ verify_assert "--" wrap-pubkey wrap-assert
verify_assert "-p" wrap-pubkey wrap-assert
get_assert no.tld "-t up=false" wrap-cred /dev/null wrap-assert
verify_assert "--" wrap-pubkey wrap-assert
! verify_assert "-p" wrap-pubkey wrap-assert
verify_assert "-p" wrap-pubkey wrap-assert && exit 1
get_assert no.tld "-t up=false -t pin=true" wrap-cred /dev/null wrap-assert
! verify_assert "-p" wrap-pubkey wrap-assert
verify_assert "-p" wrap-pubkey wrap-assert && exit 1
verify_assert "-v" wrap-pubkey wrap-assert
! verify_assert "-pv" wrap-pubkey wrap-assert
verify_assert "-pv" wrap-pubkey wrap-assert && exit 1
get_assert no.tld "-t up=false -t pin=false" wrap-cred /dev/null wrap-assert
! verify_assert "-p" wrap-pubkey wrap-assert
verify_assert "-p" wrap-pubkey wrap-assert && exit 1
get_assert no.tld "-h" wrap-cred hmac-salt wrap-assert
! verify_assert "--" wrap-pubkey wrap-assert
verify_assert "--" wrap-pubkey wrap-assert && exit 1
verify_assert "-h" wrap-pubkey wrap-assert
get_assert no.tld "-h -t pin=true" wrap-cred hmac-salt wrap-assert
! verify_assert "--" wrap-pubkey wrap-assert
verify_assert "--" wrap-pubkey wrap-assert && exit 1
verify_assert "-h" wrap-pubkey wrap-assert
verify_assert "-hv" wrap-pubkey wrap-assert
get_assert no.tld "-h -t pin=false" wrap-cred hmac-salt wrap-assert
! verify_assert "--" wrap-pubkey wrap-assert
verify_assert "--" wrap-pubkey wrap-assert && exit 1
verify_assert "-h" wrap-pubkey wrap-assert
get_assert no.tld "-h -t up=true" wrap-cred hmac-salt wrap-assert
! verify_assert "--" wrap-pubkey wrap-assert
verify_assert "--" wrap-pubkey wrap-assert && exit 1
verify_assert "-h" wrap-pubkey wrap-assert
verify_assert "-hp" wrap-pubkey wrap-assert
get_assert no.tld "-h -t up=true -t pin=true" wrap-cred hmac-salt wrap-assert
! verify_assert "--" wrap-pubkey wrap-assert
verify_assert "--" wrap-pubkey wrap-assert && exit 1
verify_assert "-h" wrap-pubkey wrap-assert
verify_assert "-hp" wrap-pubkey wrap-assert
verify_assert "-hv" wrap-pubkey wrap-assert
verify_assert "-hpv" wrap-pubkey wrap-assert
get_assert no.tld "-h -t up=true -t pin=false" wrap-cred hmac-salt wrap-assert
! verify_assert "--" wrap-pubkey wrap-assert
verify_assert "--" wrap-pubkey wrap-assert && exit 1
verify_assert "-h" wrap-pubkey wrap-assert
verify_assert "-hp" wrap-pubkey wrap-assert
! get_assert no.tld "-h -t up=false" wrap-cred hmac-salt wrap-assert
! get_assert no.tld "-h -t up=false -t pin=true" wrap-cred hmac-salt wrap-assert
! get_assert no.tld "-h -t up=false -t pin=false" wrap-cred hmac-salt wrap-assert
get_assert no.tld "-h -t up=false" wrap-cred hmac-salt wrap-assert && exit 1
get_assert no.tld "-h -t up=false -t pin=true" wrap-cred hmac-salt wrap-assert && exit 1
get_assert no.tld "-h -t up=false -t pin=false" wrap-cred hmac-salt wrap-assert && exit 1
if [ "x${UV}" != "x" ]; then
get_assert no.tld "-t uv=true" wrap-cred /dev/null wrap-assert
@@ -205,11 +210,11 @@ if [ "x${UV}" != "x" ]; then
get_assert no.tld "-t up=false -t uv=true -t pin=false" wrap-cred /dev/null wrap-assert
verify_assert "-v" wrap-pubkey wrap-assert
get_assert no.tld "-t up=false -t uv=false" wrap-cred /dev/null wrap-assert
! verify_assert "--" wrap-pubkey wrap-assert
verify_assert "--" wrap-pubkey wrap-assert && exit 1
get_assert no.tld "-t up=false -t uv=false -t pin=true" wrap-cred /dev/null wrap-assert
verify_assert "-v" wrap-pubkey wrap-assert
get_assert no.tld "-t up=false -t uv=false -t pin=false" wrap-cred /dev/null wrap-assert
! verify_assert "--" wrap-pubkey wrap-assert
verify_assert "--" wrap-pubkey wrap-assert && exit 1
get_assert no.tld "-h -t uv=true" wrap-cred hmac-salt wrap-assert
verify_assert "-hv" wrap-pubkey wrap-assert
get_assert no.tld "-h -t uv=true -t pin=true" wrap-cred hmac-salt wrap-assert
@@ -234,12 +239,12 @@ if [ "x${UV}" != "x" ]; then
verify_assert "-hpv" wrap-pubkey wrap-assert
get_assert no.tld "-h -t up=true -t uv=false -t pin=false" wrap-cred hmac-salt wrap-assert
verify_assert "-hp" wrap-pubkey wrap-assert
! get_assert no.tld "-h -t up=false -t uv=true" wrap-cred hmac-salt wrap-assert
! get_assert no.tld "-h -t up=false -t uv=true -t pin=true" wrap-cred hmac-salt wrap-assert
! get_assert no.tld "-h -t up=false -t uv=true -t pin=false" wrap-cred hmac-salt wrap-assert
! get_assert no.tld "-h -t up=false -t uv=false" wrap-cred hmac-salt wrap-assert
! get_assert no.tld "-h -t up=false -t uv=false -t pin=true" wrap-cred hmac-salt wrap-assert
! get_assert no.tld "-h -t up=false -t uv=false -t pin=false" wrap-cred hmac-salt wrap-assert
get_assert no.tld "-h -t up=false -t uv=true" wrap-cred hmac-salt wrap-assert && exit 1
get_assert no.tld "-h -t up=false -t uv=true -t pin=true" wrap-cred hmac-salt wrap-assert && exit 1
get_assert no.tld "-h -t up=false -t uv=true -t pin=false" wrap-cred hmac-salt wrap-assert && exit 1
get_assert no.tld "-h -t up=false -t uv=false" wrap-cred hmac-salt wrap-assert && exit 1
get_assert no.tld "-h -t up=false -t uv=false -t pin=true" wrap-cred hmac-salt wrap-assert && exit 1
get_assert no.tld "-h -t up=false -t uv=false -t pin=false" wrap-cred hmac-salt wrap-assert && exit 1
fi
# resident
@@ -258,9 +263,9 @@ get_assert no.tld "-r -h -t pin=false" /dev/null hmac-salt wrap-assert
get_assert no.tld "-r -h -t up=true" /dev/null hmac-salt wrap-assert
get_assert no.tld "-r -h -t up=true -t pin=true" /dev/null hmac-salt wrap-assert
get_assert no.tld "-r -h -t up=true -t pin=false" /dev/null hmac-salt wrap-assert
! get_assert no.tld "-r -h -t up=false" /dev/null hmac-salt wrap-assert
! get_assert no.tld "-r -h -t up=false -t pin=true" /dev/null hmac-salt wrap-assert
! get_assert no.tld "-r -h -t up=false -t pin=false" /dev/null hmac-salt wrap-assert
get_assert no.tld "-r -h -t up=false" /dev/null hmac-salt wrap-assert && exit 1
get_assert no.tld "-r -h -t up=false -t pin=true" /dev/null hmac-salt wrap-assert && exit 1
get_assert no.tld "-r -h -t up=false -t pin=false" /dev/null hmac-salt wrap-assert && exit 1
if [ "x${UV}" != "x" ]; then
get_assert no.tld "-r -t uv=true" /dev/null /dev/null wrap-assert
@@ -293,12 +298,12 @@ if [ "x${UV}" != "x" ]; then
get_assert no.tld "-r -h -t up=true -t uv=false" /dev/null hmac-salt wrap-assert
get_assert no.tld "-r -h -t up=true -t uv=false -t pin=true" /dev/null hmac-salt wrap-assert
get_assert no.tld "-r -h -t up=true -t uv=false -t pin=false" /dev/null hmac-salt wrap-assert
! get_assert no.tld "-r -h -t up=false -t uv=true" /dev/null hmac-salt wrap-assert
! get_assert no.tld "-r -h -t up=false -t uv=true -t pin=true" /dev/null hmac-salt wrap-assert
! get_assert no.tld "-r -h -t up=false -t uv=true -t pin=false" /dev/null hmac-salt wrap-assert
! get_assert no.tld "-r -h -t up=false -t uv=false" /dev/null hmac-salt wrap-assert
! get_assert no.tld "-r -h -t up=false -t uv=false -t pin=true" /dev/null hmac-salt wrap-assert
! get_assert no.tld "-r -h -t up=false -t uv=false -t pin=false" /dev/null hmac-salt wrap-assert
get_assert no.tld "-r -h -t up=false -t uv=true" /dev/null hmac-salt wrap-assert && exit 1
get_assert no.tld "-r -h -t up=false -t uv=true -t pin=true" /dev/null hmac-salt wrap-assert && exit 1
get_assert no.tld "-r -h -t up=false -t uv=true -t pin=false" /dev/null hmac-salt wrap-assert && exit 1
get_assert no.tld "-r -h -t up=false -t uv=false" /dev/null hmac-salt wrap-assert && exit 1
get_assert no.tld "-r -h -t up=false -t uv=false -t pin=true" /dev/null hmac-salt wrap-assert && exit 1
get_assert no.tld "-r -h -t up=false -t uv=false -t pin=false" /dev/null hmac-salt wrap-assert && exit 1
fi
exit 0
+9
View File
@@ -169,6 +169,12 @@ print_maxcredcntlst(uint64_t maxcredcntlst)
printf("maxcredcntlst: %d\n", (int)maxcredcntlst);
}
static void
print_maxcredblob(uint64_t maxcredblob)
{
printf("maxcredblob: %d\n", (int)maxcredblob);
}
static void
print_maxcredidlen(uint64_t maxcredidlen)
{
@@ -388,6 +394,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 credBlob */
print_maxcredblob(fido_cbor_info_maxcredbloblen(ci));
/* print maximum length of serialized largeBlob array */
print_maxlargeblob(fido_cbor_info_maxlargeblob(ci));
+2 -2
View File
@@ -1,12 +1,12 @@
#!/bin/sh -u
# Copyright (c) 2020 Yubico AB. All rights reserved.
# Copyright (c) 2020-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
sort_by_id() {
awk '{ printf "%d\n", $3 }' | sort -Cnu
awk '{ printf "%s\n", $3 }' | xargs printf '%d\n' | sort -Cnu
}
if ! grep '^vendor' "$1" | sort_by_id; then
+27 -14
View File
@@ -74,11 +74,9 @@ if (-Not (Test-Path $GPG)) {
throw "Unable to find GPG at $GPG"
}
# Override CMAKE_SYSTEM_VERSION if $WinSDK is set.
if (-Not ([string]::IsNullOrEmpty($WinSDK))) {
$CMAKE_SYSTEM_VERSION = "-DCMAKE_SYSTEM_VERSION='$WinSDK'"
} else {
$CMAKE_SYSTEM_VERSION = ''
# 10.0.261000.0 appear to have dropped ARM32 support, pin the SDK version
if ($Arch -eq "ARM" -and [string]::IsNullOrEmpty($WinSDK)) {
$WinSDK = '10.0.22621.0'
}
Write-Host "WinSDK: $WinSDK"
@@ -98,11 +96,23 @@ New-Item -Type Directory "${STAGE}\${LIBRESSL}" -Force
New-Item -Type Directory "${STAGE}\${LIBCBOR}" -Force
New-Item -Type Directory "${STAGE}\${ZLIB}" -Force
# Create GNUPGHOME with an empty common.conf to disable use-keyboxd.
# Recent default is to enable keyboxd which in turn ignores --keyring
# arguments.
$GpgHome = "${BUILD}\.gnupg"
New-Item -Type Directory "${GpgHome}" -Force
New-Item -Type File "${GpgHome}\common.conf" -Force
# Create output directories.
New-Item -Type Directory "${OUTPUT}" -Force
New-Item -Type Directory "${OUTPUT}\${Arch}" -Force
New-Item -Type Directory "${OUTPUT}\${Arch}\${Type}" -force
# Override Windows SDK version if $WinSDK is set.
if (-Not ([string]::IsNullOrEmpty($WinSDK))) {
$Arch = "$Arch,version=$WinSDK"
}
# Fetch and verify dependencies.
Push-Location ${BUILD}
try {
@@ -117,8 +127,9 @@ try {
}
Copy-Item "$PSScriptRoot\libressl.gpg" -Destination "${BUILD}"
& $GPG --list-keys
& $GPG --quiet --no-default-keyring --keyring ./libressl.gpg `
& $GPG --homedir ${GpgHome} --list-keys
& $GPG --homedir ${GpgHome} --quiet --no-default-keyring `
--keyring ./libressl.gpg `
--verify .\${LIBRESSL}.tar.gz.asc .\${LIBRESSL}.tar.gz
if ($LastExitCode -ne 0) {
throw "GPG signature verification failed"
@@ -144,9 +155,10 @@ Push-Location ${STAGE}\${LIBRESSL}
try {
& $CMake ..\..\..\${LIBRESSL} -A "${Arch}" `
-DBUILD_SHARED_LIBS="${SHARED}" -DLIBRESSL_TESTS=OFF `
-DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" `
-DLIBRESSL_APPS=OFF -DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" `
-DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" `
-DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
-DCMAKE_MSVC_RUNTIME_LIBRARY="${CMAKE_MSVC_RUNTIME_LIBRARY}" `
-DCMAKE_INSTALL_PREFIX="${PREFIX}"; `
ExitOnError
& $CMake --build . --config ${Config} --verbose; ExitOnError
& $CMake --build . --config ${Config} --target install --verbose; `
@@ -165,7 +177,7 @@ try {
-DBUILD_SHARED_LIBS="${SHARED}" `
-DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG} /wd4703" `
-DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE} /wd4703" `
-DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
-DCMAKE_INSTALL_PREFIX="${PREFIX}"; `
ExitOnError
& $CMake --build . --config ${Config} --verbose; ExitOnError
& $CMake --build . --config ${Config} --target install --verbose; `
@@ -184,7 +196,7 @@ try {
-DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" `
-DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" `
-DCMAKE_MSVC_RUNTIME_LIBRARY="${CMAKE_MSVC_RUNTIME_LIBRARY}" `
-DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
-DCMAKE_INSTALL_PREFIX="${PREFIX}"; `
ExitOnError
& $CMake --build . --config ${Config} --verbose; ExitOnError
& $CMake --build . --config ${Config} --target install --verbose; `
@@ -220,10 +232,11 @@ try {
-DCRYPTO_INCLUDE_DIRS="${PREFIX}\include" `
-DCRYPTO_LIBRARY_DIRS="${PREFIX}\lib" `
-DCRYPTO_BIN_DIRS="${PREFIX}\bin" `
-DCRYPTO_LIBRARIES="${CRYPTO_LIBRARIES}" `
-DCRYPTO_LIBRARIES="${CRYPTO_LIB}" `
-DCRYPTO_DLL="${CRYPTO_DLL}" `
-DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG} ${Fido2Flags}" `
-DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE} ${Fido2Flags}" `
-DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
-DCMAKE_INSTALL_PREFIX="${PREFIX}"; `
ExitOnError
& $CMake --build . --config ${Config} --verbose; ExitOnError
& $CMake --build . --config ${Config} --target regress --verbose; `
@@ -232,7 +245,7 @@ try {
ExitOnError
# Copy DLLs.
if ("${SHARED}" -eq "ON") {
"cbor.dll", "${CRYPTO_LIBRARIES}.dll", "zlib1.dll" | `
"cbor.dll", "${CRYPTO_DLL}.dll", "zlib1.dll" | `
%{ Copy-Item "${PREFIX}\bin\$_" `
-Destination "examples\${Config}" }
}
+9 -8
View File
@@ -1,24 +1,25 @@
# Copyright (c) 2021-2023 Yubico AB. All rights reserved.
# Copyright (c) 2021-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
# LibreSSL coordinates.
New-Variable -Name 'LIBRESSL_URL' `
-Value 'https://cloudflare.cdn.openbsd.org/pub/OpenBSD/LibreSSL' `
-Value 'https://ftp.openbsd.org/pub/OpenBSD/LibreSSL' `
-Option Constant
New-Variable -Name 'LIBRESSL' -Value 'libressl-3.7.3' -Option Constant
New-Variable -Name 'CRYPTO_LIBRARIES' -Value 'crypto-50' -Option Constant
New-Variable -Name 'LIBRESSL' -Value 'libressl-4.0.0' -Option Constant
New-Variable -Name 'CRYPTO_LIB' -Value 'crypto' -Option Constant
New-Variable -Name 'CRYPTO_DLL' -Value 'crypto-55' -Option Constant
# libcbor coordinates.
New-Variable -Name 'LIBCBOR' -Value 'libcbor-0.10.2' -Option Constant
New-Variable -Name 'LIBCBOR_BRANCH' -Value 'v0.10.2' -Option Constant
New-Variable -Name 'LIBCBOR' -Value 'libcbor-0.12.0' -Option Constant
New-Variable -Name 'LIBCBOR_BRANCH' -Value 'v0.12.0' -Option Constant
New-Variable -Name 'LIBCBOR_GIT' -Value 'https://github.com/pjk/libcbor' `
-Option Constant
# zlib coordinates.
New-Variable -Name 'ZLIB' -Value 'zlib-1.3' -Option Constant
New-Variable -Name 'ZLIB_BRANCH' -Value 'v1.3' -Option Constant
New-Variable -Name 'ZLIB' -Value 'zlib-1.3.1' -Option Constant
New-Variable -Name 'ZLIB_BRANCH' -Value 'v1.3.1' -Option Constant
New-Variable -Name 'ZLIB_GIT' -Value 'https://github.com/madler/zlib' `
-Option Constant
+9 -2
View File
@@ -38,6 +38,13 @@ Write-Host "GPG: $GPG"
New-Item -Type Directory "${Cygwin}" -Force
New-Item -Type Directory "${Root}" -Force
# Create GNUPGHOME with an empty common.conf to disable use-keyboxd.
# Recent default is to enable keyboxd which in turn ignores --keyring
# arguments.
$GpgHome = "${Cygwin}\.gnupg"
New-Item -Type Directory "${GpgHome}" -Force
New-Item -Type File "${GpgHome}\common.conf" -Force
# Fetch and verify Cygwin.
try {
if (-Not (Test-Path ${Cygwin}\${Setup} -PathType leaf)) {
@@ -48,8 +55,8 @@ try {
Invoke-WebRequest ${URL}/${Setup}.sig `
-OutFile ${Cygwin}\${Setup}.sig
}
& $GPG --list-keys
& $GPG --quiet --no-default-keyring `
& $GPG --homedir ${GpgHome} --list-keys
& $GPG --homedir ${GpgHome} --quiet --no-default-keyring `
--keyring ${PSScriptRoot}/cygwin.gpg `
--verify ${Cygwin}\${Setup}.sig ${Cygwin}\${Setup}
if ($LastExitCode -ne 0) {
+10 -12
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2021-2022 Yubico AB. All rights reserved.
# Copyright (c) 2021-2024 Yubico AB. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# SPDX-License-Identifier: BSD-2-Clause
@@ -35,8 +35,8 @@ Function Package-Dynamic(${SRC}, ${DEST}) {
Copy-Item "${SRC}\lib\cbor.lib" "${DEST}"
Copy-Item "${SRC}\bin\zlib1.dll" "${DEST}"
Copy-Item "${SRC}\lib\zlib1.lib" "${DEST}"
Copy-Item "${SRC}\bin\${CRYPTO_LIBRARIES}.dll" "${DEST}"
Copy-Item "${SRC}\lib\${CRYPTO_LIBRARIES}.lib" "${DEST}"
Copy-Item "${SRC}\bin\${CRYPTO_DLL}.dll" "${DEST}"
Copy-Item "${SRC}\lib\${CRYPTO_LIB}.lib" "${DEST}"
Copy-Item "${SRC}\bin\fido2.dll" "${DEST}"
Copy-Item "${SRC}\lib\fido2.lib" "${DEST}"
}
@@ -44,13 +44,13 @@ Function Package-Dynamic(${SRC}, ${DEST}) {
Function Package-Static(${SRC}, ${DEST}) {
Copy-Item "${SRC}/lib/cbor.lib" "${DEST}"
Copy-Item "${SRC}/lib/zlib1.lib" "${DEST}"
Copy-Item "${SRC}/lib/${CRYPTO_LIBRARIES}.lib" "${DEST}"
Copy-Item "${SRC}/lib/${CRYPTO_LIB}.lib" "${DEST}"
Copy-Item "${SRC}/lib/fido2_static.lib" "${DEST}/fido2.lib"
}
Function Package-PDBs(${SRC}, ${DEST}) {
Copy-Item "${SRC}\${LIBRESSL}\crypto\crypto_obj.dir\${Config}\crypto_obj.pdb" `
"${DEST}\${CRYPTO_LIBRARIES}.pdb"
"${DEST}\${CRYPTO_LIB}.pdb"
Copy-Item "${SRC}\${LIBCBOR}\src\cbor.dir\${Config}\vc${SDK}.pdb" `
"${DEST}\cbor.pdb"
Copy-Item "${SRC}\${ZLIB}\zlib.dir\${Config}\vc${SDK}.pdb" `
@@ -60,14 +60,12 @@ Function Package-PDBs(${SRC}, ${DEST}) {
}
Function Package-StaticPDBs(${SRC}, ${DEST}) {
# NOTE: original file names must be preserved
Copy-Item "${SRC}\${LIBRESSL}\crypto\crypto_obj.dir\${Config}\crypto_obj.pdb" `
"${DEST}\${CRYPTO_LIBRARIES}.pdb"
Copy-Item "${SRC}\${LIBCBOR}\src\${Config}\cbor.pdb" `
"${DEST}\cbor.pdb"
Copy-Item "${SRC}\${ZLIB}\${Config}\zlibstatic.pdb" `
"${DEST}\zlib1.pdb"
Copy-Item "${SRC}\src\${Config}\fido2_static.pdb" `
"${DEST}\fido2.pdb"
"${DEST}"
Copy-Item "${SRC}\${LIBCBOR}\src\${Config}\cbor.pdb" "${DEST}"
Copy-Item "${SRC}\${ZLIB}\${Config}\zlibstatic.pdb" "${DEST}"
Copy-Item "${SRC}\src\${Config}\fido2_static.pdb" "${DEST}"
}
Function Package-Tools(${SRC}, ${DEST}) {