diff options
115 files changed, 4489 insertions, 2867 deletions
diff --git a/.github/workflows/cifuzz_oss.yml b/.github/workflows/cifuzz_oss.yml deleted file mode 100644 index cbb334c..0000000 --- a/.github/workflows/cifuzz_oss.yml +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | name: CIFuzz | ||
2 | on: [pull_request] | ||
3 | jobs: | ||
4 | Fuzzing: | ||
5 | runs-on: ubuntu-latest | ||
6 | steps: | ||
7 | - name: Build Fuzzers | ||
8 | uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master | ||
9 | with: | ||
10 | oss-fuzz-project-name: 'libfido2' | ||
11 | dry-run: false | ||
12 | - name: Run Fuzzers | ||
13 | uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master | ||
14 | with: | ||
15 | oss-fuzz-project-name: 'libfido2' | ||
16 | fuzz-seconds: 600 | ||
17 | dry-run: false | ||
18 | - name: Upload Crash | ||
19 | uses: actions/upload-artifact@v1 | ||
20 | if: failure() | ||
21 | with: | ||
22 | name: artifacts | ||
23 | path: ./out/artifacts | ||
diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml deleted file mode 100644 index 008961b..0000000 --- a/.github/workflows/scan.yml +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | name: static code analysis | ||
2 | |||
3 | on: | ||
4 | push: | ||
5 | schedule: | ||
6 | - cron: '0 0 * * 1' | ||
7 | |||
8 | env: | ||
9 | SCAN_IMG: | ||
10 | yes-docker-local.artifactory.in.yubico.org/static-code-analysis/c:v1 | ||
11 | SECRET: ${{ secrets.ARTIFACTORY_READER_TOKEN }} | ||
12 | |||
13 | jobs: | ||
14 | build: | ||
15 | runs-on: ubuntu-latest | ||
16 | |||
17 | steps: | ||
18 | - uses: actions/checkout@master | ||
19 | |||
20 | - name: Scan but do not fail on warnings | ||
21 | run: | | ||
22 | if [ "${SECRET}" != "" ]; then | ||
23 | docker login yes-docker-local.artifactory.in.yubico.org/ \ | ||
24 | -u svc-static-code-analysis-reader \ | ||
25 | -p ${{ secrets.ARTIFACTORY_READER_TOKEN }} | ||
26 | docker pull ${SCAN_IMG} | ||
27 | docker run -v${PWD}:/k -e COMPILE_DEPS="${COMPILE_DEPS}" \ | ||
28 | -e PROJECT_NAME=${GITHUB_REPOSITORY#Yubico/} -t ${SCAN_IMG} | ||
29 | fi | ||
30 | continue-on-error: true | ||
31 | |||
32 | - uses: actions/upload-artifact@master | ||
33 | if: failure() | ||
34 | with: | ||
35 | name: suppression_files | ||
36 | path: suppression_files | ||
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index eb953db..0000000 --- a/.github/workflows/windows.yml +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | name: windows | ||
2 | |||
3 | on: [push] | ||
4 | |||
5 | jobs: | ||
6 | build: | ||
7 | |||
8 | runs-on: windows-latest | ||
9 | |||
10 | steps: | ||
11 | - uses: actions/checkout@v1 | ||
12 | - name: build | ||
13 | run: .\windows\build.ps1 | ||
14 | |||
diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0915625..0000000 --- a/.gitignore +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | build/ | ||
2 | cscope.out | ||
3 | fuzz/build/ | ||
4 | fuzz/corpus.tgz- | ||
5 | fuzz/fuzz_*/ | ||
6 | fuzz/obj/ | ||
7 | fuzz/report | ||
8 | fuzz/*.so | ||
9 | output/ | ||
diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c2bff78..0000000 --- a/.travis.yml +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | language: c | ||
2 | |||
3 | matrix: | ||
4 | include: | ||
5 | - os: linux | ||
6 | compiler: clang-7 | ||
7 | dist: xenial | ||
8 | sudo: required | ||
9 | addons: | ||
10 | apt: | ||
11 | sources: | ||
12 | - ubuntu-toolchain-r-test | ||
13 | - llvm-toolchain-xenial-7 | ||
14 | packages: | ||
15 | - clang-7 | ||
16 | - cmake | ||
17 | - libssl-dev | ||
18 | - libudev-dev | ||
19 | script: /bin/sh -eux .travis/build-linux-clang | ||
20 | - os: linux | ||
21 | compiler: gcc-7 | ||
22 | dist: xenial | ||
23 | sudo: required | ||
24 | addons: | ||
25 | apt: | ||
26 | sources: | ||
27 | - ubuntu-toolchain-r-test | ||
28 | packages: | ||
29 | - gcc-7 | ||
30 | - cmake | ||
31 | - libssl-dev | ||
32 | - libudev-dev | ||
33 | script: /bin/sh -eux .travis/build-linux-gcc | ||
34 | - os: linux | ||
35 | compiler: i686-w64-mingw32-gcc-4.8 | ||
36 | dist: xenial | ||
37 | sudo: required | ||
38 | addons: | ||
39 | apt: | ||
40 | sources: | ||
41 | - ubuntu-toolchain-r-test | ||
42 | packages: | ||
43 | - binutils-mingw-w64-i686 | ||
44 | - gcc-mingw-w64 | ||
45 | - g++-mingw-w64 | ||
46 | - mingw-w64-i686-dev | ||
47 | - cmake | ||
48 | script: /bin/sh -eux .travis/build-linux-mingw | ||
49 | - os: osx | ||
50 | osx_image: xcode10.2 | ||
51 | compiler: clang | ||
52 | sudo: required | ||
53 | script: /bin/sh -eux .travis/build-osx-clang | ||
54 | - os: linux | ||
55 | compiler: clang-7 | ||
56 | dist: bionic | ||
57 | sudo: required | ||
58 | addons: | ||
59 | apt: | ||
60 | sources: | ||
61 | - ubuntu-toolchain-r-test | ||
62 | - llvm-toolchain-xenial-7 | ||
63 | packages: | ||
64 | - clang-7 | ||
65 | - cmake | ||
66 | - libssl-dev | ||
67 | - libudev-dev | ||
68 | script: /bin/sh -eux .travis/fuzz-linux-asan | ||
69 | - os: linux | ||
70 | compiler: clang-7 | ||
71 | dist: bionic | ||
72 | sudo: required | ||
73 | addons: | ||
74 | apt: | ||
75 | sources: | ||
76 | - ubuntu-toolchain-r-test | ||
77 | - llvm-toolchain-xenial-7 | ||
78 | packages: | ||
79 | - clang-7 | ||
80 | - cmake | ||
81 | - libssl-dev | ||
82 | - libudev-dev | ||
83 | script: /bin/sh -eux .travis/fuzz-linux-msan | ||
84 | |||
85 | notifications: | ||
86 | email: false | ||
diff --git a/.travis/build-linux-clang b/.travis/build-linux-clang deleted file mode 100644 index 8938461..0000000 --- a/.travis/build-linux-clang +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | #!/bin/sh -eux | ||
2 | |||
3 | ${CC} --version | ||
4 | |||
5 | # Check exports. | ||
6 | (cd src && ./diff_exports.sh) | ||
7 | |||
8 | # Build and install libcbor. | ||
9 | git clone git://github.com/pjk/libcbor | ||
10 | cd libcbor | ||
11 | git checkout v0.5.0 | ||
12 | mkdir build | ||
13 | (cd build && cmake ..) | ||
14 | make -C build | ||
15 | sudo make -C build install | ||
16 | cd .. | ||
17 | |||
18 | # Build, analyze, and install libfido2. | ||
19 | mkdir build | ||
20 | (cd build && scan-build cmake -DCMAKE_BUILD_TYPE=Debug ..) | ||
21 | scan-build --status-bugs make -C build | ||
22 | sudo make -C build install | ||
diff --git a/.travis/build-linux-gcc b/.travis/build-linux-gcc deleted file mode 100644 index be1e0a9..0000000 --- a/.travis/build-linux-gcc +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | #!/bin/sh -eux | ||
2 | |||
3 | ${CC} --version | ||
4 | |||
5 | # Build and install libcbor. | ||
6 | git clone git://github.com/pjk/libcbor | ||
7 | cd libcbor | ||
8 | git checkout v0.5.0 | ||
9 | mkdir build | ||
10 | (cd build && cmake ..) | ||
11 | make -C build | ||
12 | sudo make -C build install | ||
13 | cd .. | ||
14 | |||
15 | # Build and install libfido2. | ||
16 | mkdir build | ||
17 | (cd build && cmake -DCMAKE_BUILD_TYPE=Debug ..) | ||
18 | make -C build | ||
19 | sudo make -C build install | ||
diff --git a/.travis/build-linux-mingw b/.travis/build-linux-mingw deleted file mode 100644 index c88ddca..0000000 --- a/.travis/build-linux-mingw +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | #!/bin/sh -eux | ||
2 | |||
3 | # XXX defining CC and cross-compiling confuses OpenSSL's build. | ||
4 | unset CC | ||
5 | |||
6 | sudo mkdir /fakeroot | ||
7 | sudo chmod 755 /fakeroot | ||
8 | |||
9 | cat << EOF > /tmp/mingw.cmake | ||
10 | SET(CMAKE_SYSTEM_NAME Windows) | ||
11 | SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc) | ||
12 | SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) | ||
13 | SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) | ||
14 | SET(CMAKE_FIND_ROOT_PATH /fakeroot) | ||
15 | SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | ||
16 | SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | ||
17 | SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | ||
18 | EOF | ||
19 | |||
20 | # Build and install libcbor. | ||
21 | git clone git://github.com/pjk/libcbor | ||
22 | cd libcbor | ||
23 | git checkout v0.5.0 | ||
24 | mkdir build | ||
25 | (cd build && cmake -DCMAKE_TOOLCHAIN_FILE=/tmp/mingw.cmake \ | ||
26 | -DCMAKE_INSTALL_PREFIX=/fakeroot ..) | ||
27 | make -C build | ||
28 | sudo make -C build install | ||
29 | cd .. | ||
30 | |||
31 | # Build and install OpenSSL 1.1.0j. | ||
32 | git clone git://github.com/openssl/openssl | ||
33 | cd openssl | ||
34 | git checkout OpenSSL_1_1_0j | ||
35 | ./Configure mingw --prefix=/fakeroot --openssldir=/fakeroot/openssl \ | ||
36 | --cross-compile-prefix=i686-w64-mingw32- | ||
37 | make | ||
38 | sudo make install_sw | ||
39 | cd .. | ||
40 | |||
41 | # Build and install libfido2. | ||
42 | export PKG_CONFIG_PATH=/fakeroot/lib/pkgconfig | ||
43 | mkdir build | ||
44 | (cd build && cmake -DCMAKE_TOOLCHAIN_FILE=/tmp/mingw.cmake \ | ||
45 | -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/fakeroot ..) | ||
46 | make -C build | ||
47 | sudo make -C build install | ||
diff --git a/.travis/build-osx-clang b/.travis/build-osx-clang deleted file mode 100644 index 69a784c..0000000 --- a/.travis/build-osx-clang +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | #!/bin/sh -eux | ||
2 | |||
3 | ${CC} --version | ||
4 | |||
5 | # Build and install libcbor. | ||
6 | git clone git://github.com/pjk/libcbor | ||
7 | cd libcbor | ||
8 | git checkout v0.5.0 | ||
9 | mkdir build | ||
10 | (cd build && cmake ..) | ||
11 | make -C build | ||
12 | sudo make -C build install | ||
13 | cd .. | ||
14 | |||
15 | # Install mandoc from Homebrew. | ||
16 | brew install mandoc | ||
17 | |||
18 | # Build and install libfido2. | ||
19 | export PKG_CONFIG_PATH=/usr/local/opt/openssl@1.1/lib/pkgconfig | ||
20 | mkdir build | ||
21 | (cd build && cmake -DCMAKE_BUILD_TYPE=Debug ..) | ||
22 | make -C build | ||
23 | make -C build man_symlink_html | ||
24 | sudo make -C build install | ||
diff --git a/.travis/fuzz-linux-asan b/.travis/fuzz-linux-asan deleted file mode 100644 index af8a08c..0000000 --- a/.travis/fuzz-linux-asan +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | #!/bin/sh -eux | ||
2 | |||
3 | ${CC} --version | ||
4 | |||
5 | FAKEROOT=/fakeroot | ||
6 | sudo mkdir ${FAKEROOT} | ||
7 | sudo chmod 755 ${FAKEROOT} | ||
8 | |||
9 | # Build and install libcbor. | ||
10 | git clone git://github.com/pjk/libcbor | ||
11 | cd libcbor | ||
12 | patch -p0 < ../fuzz/README | ||
13 | mkdir build | ||
14 | cd build | ||
15 | cmake -DCMAKE_C_FLAGS_DEBUG="-g2 -fno-omit-frame-pointer" \ | ||
16 | -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug \ | ||
17 | -DCMAKE_INSTALL_PREFIX=${FAKEROOT} -DSANITIZE=ON \ | ||
18 | -DCMAKE_INSTALL_LIBDIR=lib .. | ||
19 | make | ||
20 | sudo make install | ||
21 | cd ../.. | ||
22 | |||
23 | # Build and install OpenSSL 1.1.1b. | ||
24 | git clone git://github.com/openssl/openssl | ||
25 | cd openssl | ||
26 | git checkout OpenSSL_1_1_1b | ||
27 | ./Configure linux-x86_64-clang enable-asan --prefix=${FAKEROOT} \ | ||
28 | --openssldir=${FAKEROOT}/openssl | ||
29 | make clean | ||
30 | make | ||
31 | sudo make install_sw | ||
32 | cd .. | ||
33 | |||
34 | # Build libfido2. | ||
35 | mkdir build | ||
36 | cd build | ||
37 | export PKG_CONFIG_PATH=/fakeroot/lib/pkgconfig | ||
38 | cmake -DFUZZ=1 -DLIBFUZZER=1 -DASAN=1 -DUBSAN=1 -DCMAKE_C_COMPILER=clang \ | ||
39 | -DCRYPTO_INCLUDE_DIRS=${FAKEROOT}/include \ | ||
40 | -DCRYPTO_LIBRARY_DIRS=${FAKEROOT}/lib \ | ||
41 | -DCBOR_INCLUDE_DIRS=${FAKEROOT}/include \ | ||
42 | -DCBOR_LIBRARY_DIRS=${FAKEROOT}/lib \ | ||
43 | -DCMAKE_BUILD_TYPE=Debug .. | ||
44 | make | ||
45 | |||
46 | # Fuzz with ASAN. | ||
47 | mkdir corpus | ||
48 | curl -s https://ambientworks.net/tmp/corpus.tgz > ../fuzz/corpus.tgz | ||
49 | tar -C corpus -zxf ../fuzz/corpus.tgz | ||
50 | fuzz/fuzz_cred -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
51 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_cred | ||
52 | fuzz/fuzz_assert -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
53 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_assert | ||
54 | fuzz/fuzz_credman -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
55 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_credman | ||
56 | fuzz/fuzz_mgmt -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
57 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_mgmt | ||
58 | fuzz/fuzz_bio -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
59 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_bio | ||
diff --git a/.travis/fuzz-linux-msan b/.travis/fuzz-linux-msan deleted file mode 100644 index e67ab22..0000000 --- a/.travis/fuzz-linux-msan +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | #!/bin/sh -eux | ||
2 | |||
3 | ${CC} --version | ||
4 | |||
5 | FAKEROOT=/fakeroot | ||
6 | sudo mkdir ${FAKEROOT} | ||
7 | sudo chmod 755 ${FAKEROOT} | ||
8 | |||
9 | # Build and install libcbor. | ||
10 | git clone git://github.com/pjk/libcbor | ||
11 | cd libcbor | ||
12 | patch -p0 < ../fuzz/README | ||
13 | mkdir build | ||
14 | cd build | ||
15 | cmake -DCMAKE_C_FLAGS_DEBUG="-fsanitize=memory,undefined -g2 -fno-omit-frame-pointer" \ | ||
16 | -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug \ | ||
17 | -DCMAKE_INSTALL_PREFIX=${FAKEROOT} -DSANITIZE=OFF \ | ||
18 | -DCMAKE_INSTALL_LIBDIR=lib .. | ||
19 | make | ||
20 | sudo make install | ||
21 | cd ../.. | ||
22 | |||
23 | # Build and install OpenSSL 1.1.1b. | ||
24 | git clone git://github.com/openssl/openssl | ||
25 | cd openssl | ||
26 | git checkout OpenSSL_1_1_1b | ||
27 | ./Configure linux-x86_64-clang enable-msan --prefix=${FAKEROOT} \ | ||
28 | --openssldir=${FAKEROOT}/openssl | ||
29 | make clean | ||
30 | make | ||
31 | sudo make install_sw | ||
32 | cd .. | ||
33 | |||
34 | # Build libfido2. | ||
35 | mkdir build | ||
36 | cd build | ||
37 | export PKG_CONFIG_PATH=/fakeroot/lib/pkgconfig | ||
38 | cmake -DFUZZ=1 -DLIBFUZZER=1 -DMSAN=1 -DUBSAN=1 -DCMAKE_C_COMPILER=clang \ | ||
39 | -DCRYPTO_INCLUDE_DIRS=${FAKEROOT}/include \ | ||
40 | -DCRYPTO_LIBRARY_DIRS=${FAKEROOT}/lib \ | ||
41 | -DCBOR_INCLUDE_DIRS=${FAKEROOT}/include \ | ||
42 | -DCBOR_LIBRARY_DIRS=${FAKEROOT}/lib \ | ||
43 | -DCMAKE_BUILD_TYPE=Debug .. | ||
44 | make | ||
45 | |||
46 | # Fuzz with MSAN. | ||
47 | mkdir corpus | ||
48 | curl -s https://ambientworks.net/tmp/corpus.tgz > ../fuzz/corpus.tgz | ||
49 | tar -C corpus -zxf ../fuzz/corpus.tgz | ||
50 | fuzz/fuzz_cred -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
51 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_cred | ||
52 | fuzz/fuzz_assert -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
53 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_assert | ||
54 | fuzz/fuzz_credman -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
55 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_credman | ||
56 | fuzz/fuzz_mgmt -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
57 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_mgmt | ||
58 | fuzz/fuzz_bio -use_value_profile=1 -reload=30 -print_pcs=1 \ | ||
59 | -print_funcs=30 -timeout=10 -runs=1 corpus/fuzz_bio | ||
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bb2e87..dbd5fa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -10,6 +10,8 @@ cmake_minimum_required(VERSION 3.0) | |||
10 | 10 | ||
11 | include(CheckCCompilerFlag) | 11 | include(CheckCCompilerFlag) |
12 | include(CheckFunctionExists) | 12 | include(CheckFunctionExists) |
13 | include(CheckLibraryExists) | ||
14 | include(CheckSymbolExists) | ||
13 | include(CheckIncludeFiles) | 15 | include(CheckIncludeFiles) |
14 | include(CheckTypeSize) | 16 | include(CheckTypeSize) |
15 | include(GNUInstallDirs) | 17 | include(GNUInstallDirs) |
@@ -19,7 +21,7 @@ set(CMAKE_VERBOSE_MAKEFILE on) | |||
19 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) | 21 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) |
20 | 22 | ||
21 | set(FIDO_MAJOR "1") | 23 | set(FIDO_MAJOR "1") |
22 | set(FIDO_MINOR "4") | 24 | set(FIDO_MINOR "5") |
23 | set(FIDO_PATCH "0") | 25 | set(FIDO_PATCH "0") |
24 | set(FIDO_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}.${FIDO_PATCH}) | 26 | set(FIDO_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}.${FIDO_PATCH}) |
25 | 27 | ||
@@ -33,21 +35,12 @@ if(CYGWIN OR MSYS) | |||
33 | endif() | 35 | endif() |
34 | 36 | ||
35 | if(WIN32) | 37 | if(WIN32) |
36 | add_definitions(-DWIN32_LEAN_AND_MEAN) | 38 | add_definitions(-DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600) |
37 | endif() | 39 | endif() |
38 | 40 | ||
39 | if(APPLE) | 41 | if(APPLE) |
40 | set(CMAKE_INSTALL_NAME_DIR | 42 | set(CMAKE_INSTALL_NAME_DIR |
41 | "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") | 43 | "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") |
42 | endif() | ||
43 | |||
44 | # Observe OpenBSD's library versioning scheme. | ||
45 | if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") | ||
46 | set(LIB_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}) | ||
47 | set(LIB_SOVERSION ${LIB_VERSION}) | ||
48 | else() | ||
49 | set(LIB_VERSION ${FIDO_VERSION}) | ||
50 | set(LIB_SOVERSION ${FIDO_MAJOR}) | ||
51 | endif() | 44 | endif() |
52 | 45 | ||
53 | if(MSVC) | 46 | if(MSVC) |
@@ -58,7 +51,7 @@ if(MSVC) | |||
58 | "under msvc") | 51 | "under msvc") |
59 | endif() | 52 | endif() |
60 | set(CBOR_LIBRARIES cbor) | 53 | set(CBOR_LIBRARIES cbor) |
61 | set(CRYPTO_LIBRARIES crypto-45) | 54 | set(CRYPTO_LIBRARIES crypto-46) |
62 | set(MSVC_DISABLED_WARNINGS_LIST | 55 | set(MSVC_DISABLED_WARNINGS_LIST |
63 | "C4200" # nonstandard extension used: zero-sized array in | 56 | "C4200" # nonstandard extension used: zero-sized array in |
64 | # struct/union; | 57 | # struct/union; |
@@ -71,9 +64,9 @@ if(MSVC) | |||
71 | # The construction in the following 3 lines was taken from LibreSSL's | 64 | # The construction in the following 3 lines was taken from LibreSSL's |
72 | # CMakeLists.txt. | 65 | # CMakeLists.txt. |
73 | string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR | 66 | string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR |
74 | ${MSVC_DISABLED_WARNINGS_LIST}) | 67 | ${MSVC_DISABLED_WARNINGS_LIST}) |
75 | string(REGEX REPLACE "[/-]W[1234][ ]?" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) | 68 | string(REGEX REPLACE "[/-]W[1234][ ]?" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) |
76 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP -W4 ${MSVC_DISABLED_WARNINGS_STR}") | 69 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP -W4 -WX ${MSVC_DISABLED_WARNINGS_STR}") |
77 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7") | 70 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7") |
78 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi") | 71 | set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi") |
79 | else() | 72 | else() |
@@ -102,13 +95,18 @@ else() | |||
102 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux") | 95 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux") |
103 | pkg_search_module(UDEV libudev REQUIRED) | 96 | pkg_search_module(UDEV libudev REQUIRED) |
104 | set(UDEV_NAME "udev") | 97 | set(UDEV_NAME "udev") |
98 | include_directories(${UDEV_INCLUDE_DIRS}) | ||
99 | link_directories(${UDEV_LIBRARY_DIRS}) | ||
105 | # Define be32toh(). | 100 | # Define be32toh(). |
106 | add_definitions(-D_GNU_SOURCE) | 101 | add_definitions(-D_GNU_SOURCE) |
107 | # If using hidapi, use hidapi-hidraw. | 102 | # If using hidapi, use hidapi-hidraw. |
108 | set(HIDAPI_SUFFIX -hidraw) | 103 | set(HIDAPI_SUFFIX -hidraw) |
109 | elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR | 104 | # Look for clock_gettime in librt. |
110 | CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") | 105 | check_library_exists(rt clock_gettime "time.h" HAVE_CLOCK_GETTIME) |
111 | set(BASE_LIBRARIES usbhid) | 106 | if(HAVE_CLOCK_GETTIME) |
107 | set(BASE_LIBRARIES ${BASE_LIBRARIES} rt) | ||
108 | add_definitions(-DHAVE_CLOCK_GETTIME) | ||
109 | endif() | ||
112 | endif() | 110 | endif() |
113 | 111 | ||
114 | if(MINGW) | 112 | if(MINGW) |
@@ -122,6 +120,8 @@ else() | |||
122 | add_definitions(-DUSE_HIDAPI) | 120 | add_definitions(-DUSE_HIDAPI) |
123 | pkg_search_module(HIDAPI hidapi${HIDAPI_SUFFIX} REQUIRED) | 121 | pkg_search_module(HIDAPI hidapi${HIDAPI_SUFFIX} REQUIRED) |
124 | if(HIDAPI_FOUND) | 122 | if(HIDAPI_FOUND) |
123 | include_directories(${HIDAPI_INCLUDE_DIRS}) | ||
124 | link_directories(${HIDAPI_LIBRARY_DIRS}) | ||
125 | set(HIDAPI_LIBRARIES hidapi${HIDAPI_SUFFIX}) | 125 | set(HIDAPI_LIBRARIES hidapi${HIDAPI_SUFFIX}) |
126 | endif() | 126 | endif() |
127 | endif() | 127 | endif() |
@@ -153,24 +153,6 @@ else() | |||
153 | endif() | 153 | endif() |
154 | add_definitions(-DFIDO_FUZZ) | 154 | add_definitions(-DFIDO_FUZZ) |
155 | endif() | 155 | endif() |
156 | |||
157 | if(ASAN) | ||
158 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,leak") | ||
159 | endif() | ||
160 | |||
161 | if(MSAN) | ||
162 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory") | ||
163 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-memory-track-origins") | ||
164 | endif() | ||
165 | |||
166 | if(UBSAN) | ||
167 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined") | ||
168 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-trap=undefined") | ||
169 | endif() | ||
170 | |||
171 | if(COVERAGE) | ||
172 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-instr-generate -fcoverage-mapping") | ||
173 | endif() | ||
174 | endif() | 156 | endif() |
175 | 157 | ||
176 | # Use -Wshorten-64-to-32 if available. | 158 | # Use -Wshorten-64-to-32 if available. |
@@ -333,6 +315,20 @@ if(UNIX) | |||
333 | add_definitions(-DHAVE_DEV_URANDOM) | 315 | add_definitions(-DHAVE_DEV_URANDOM) |
334 | endif() | 316 | endif() |
335 | 317 | ||
318 | # clock_gettime | ||
319 | if(NOT HAVE_CLOCK_GETTIME) | ||
320 | check_function_exists(clock_gettime HAVE_CLOCK_GETTIME) | ||
321 | if(HAVE_CLOCK_GETTIME) | ||
322 | add_definitions(-DHAVE_CLOCK_GETTIME) | ||
323 | endif() | ||
324 | endif() | ||
325 | |||
326 | # timespecsub | ||
327 | check_symbol_exists(timespecsub sys/time.h HAVE_TIMESPECSUB) | ||
328 | if(HAVE_TIMESPECSUB) | ||
329 | add_definitions(-DHAVE_TIMESPECSUB) | ||
330 | endif() | ||
331 | |||
336 | # export list | 332 | # export list |
337 | if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR | 333 | if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR |
338 | CMAKE_C_COMPILER_ID STREQUAL "AppleClang")) | 334 | CMAKE_C_COMPILER_ID STREQUAL "AppleClang")) |
@@ -366,7 +362,7 @@ elseif(NOT MSVC) | |||
366 | endif() | 362 | endif() |
367 | else() | 363 | else() |
368 | string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} | 364 | string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} |
369 | " /def:\"${CMAKE_CURRENT_SOURCE_DIR}/src/export.msvc\"") | 365 | " /def:\"${CMAKE_CURRENT_SOURCE_DIR}/src/export.msvc\"") |
370 | endif() | 366 | endif() |
371 | 367 | ||
372 | include_directories(${CMAKE_SOURCE_DIR}/src) | 368 | include_directories(${CMAKE_SOURCE_DIR}/src) |
@@ -376,38 +372,33 @@ include_directories(${CRYPTO_INCLUDE_DIRS}) | |||
376 | link_directories(${CBOR_LIBRARY_DIRS}) | 372 | link_directories(${CBOR_LIBRARY_DIRS}) |
377 | link_directories(${CRYPTO_LIBRARY_DIRS}) | 373 | link_directories(${CRYPTO_LIBRARY_DIRS}) |
378 | 374 | ||
375 | message(STATUS "BASE_LIBRARIES: ${BASE_LIBRARIES}") | ||
376 | message(STATUS "CBOR_INCLUDE_DIRS: ${CBOR_INCLUDE_DIRS}") | ||
377 | message(STATUS "CBOR_LIBRARIES: ${CBOR_LIBRARIES}") | ||
378 | message(STATUS "CBOR_LIBRARY_DIRS: ${CBOR_LIBRARY_DIRS}") | ||
379 | message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") | ||
379 | message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}") | 380 | message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}") |
380 | message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}") | 381 | message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}") |
381 | message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") | ||
382 | message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}") | 382 | message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}") |
383 | message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") | 383 | message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}") |
384 | message(STATUS "CBOR_INCLUDE_DIRS: ${CBOR_INCLUDE_DIRS}") | ||
385 | message(STATUS "CBOR_LIBRARY_DIRS: ${CBOR_LIBRARY_DIRS}") | ||
386 | message(STATUS "CBOR_LIBRARIES: ${CBOR_LIBRARIES}") | ||
387 | message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}") | 384 | message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}") |
388 | message(STATUS "CRYPTO_LIBRARY_DIRS: ${CRYPTO_LIBRARY_DIRS}") | ||
389 | message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}") | 385 | message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}") |
390 | message(STATUS "BASE_LIBRARIES: ${BASE_LIBRARIES}") | 386 | message(STATUS "CRYPTO_LIBRARY_DIRS: ${CRYPTO_LIBRARY_DIRS}") |
391 | message(STATUS "HIDAPI_LIBRARIES: ${HIDAPI_LIBRARIES}") | 387 | message(STATUS "FIDO_VERSION: ${FIDO_VERSION}") |
392 | message(STATUS "VERSION: ${FIDO_VERSION}") | ||
393 | message(STATUS "LIB_VERSION: ${LIB_VERSION}") | ||
394 | message(STATUS "LIB_SOVERSION: ${LIB_SOVERSION}") | ||
395 | message(STATUS "FUZZ: ${FUZZ}") | 388 | message(STATUS "FUZZ: ${FUZZ}") |
396 | message(STATUS "AFL: ${AFL}") | 389 | if(USE_HIDAPI) |
390 | message(STATUS "HIDAPI_INCLUDE_DIRS: ${HIDAPI_INCLUDE_DIRS}") | ||
391 | message(STATUS "HIDAPI_LIBRARIES: ${HIDAPI_LIBRARIES}") | ||
392 | message(STATUS "HIDAPI_LIBRARY_DIRS: ${HIDAPI_LIBRARY_DIRS}") | ||
393 | endif() | ||
397 | message(STATUS "LIBFUZZER: ${LIBFUZZER}") | 394 | message(STATUS "LIBFUZZER: ${LIBFUZZER}") |
398 | message(STATUS "ASAN: ${ASAN}") | ||
399 | message(STATUS "MSAN: ${MSAN}") | ||
400 | message(STATUS "COVERAGE: ${COVERAGE}") | ||
401 | message(STATUS "TLS: ${TLS}") | 395 | message(STATUS "TLS: ${TLS}") |
396 | message(STATUS "UDEV_INCLUDE_DIRS: ${UDEV_INCLUDE_DIRS}") | ||
397 | message(STATUS "UDEV_LIBRARIES: ${UDEV_LIBRARIES}") | ||
398 | message(STATUS "UDEV_LIBRARY_DIRS: ${UDEV_LIBRARY_DIRS}") | ||
399 | message(STATUS "UDEV_RULES_DIR: ${UDEV_RULES_DIR}") | ||
402 | message(STATUS "USE_HIDAPI: ${USE_HIDAPI}") | 400 | message(STATUS "USE_HIDAPI: ${USE_HIDAPI}") |
403 | 401 | ||
404 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux") | ||
405 | message(STATUS "UDEV_INCLUDE_DIRS: ${UDEV_INCLUDE_DIRS}") | ||
406 | message(STATUS "UDEV_LIBRARY_DIRS: ${UDEV_LIBRARY_DIRS}") | ||
407 | message(STATUS "UDEV_LIBRARIES: ${UDEV_LIBRARIES}") | ||
408 | message(STATUS "UDEV_RULES_DIR: ${UDEV_RULES_DIR}") | ||
409 | endif() | ||
410 | |||
411 | subdirs(src) | 402 | subdirs(src) |
412 | subdirs(examples) | 403 | subdirs(examples) |
413 | subdirs(tools) | 404 | subdirs(tools) |
@@ -415,7 +406,7 @@ subdirs(man) | |||
415 | 406 | ||
416 | if(NOT WIN32) | 407 | if(NOT WIN32) |
417 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") | 408 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") |
418 | if(NOT MSAN AND NOT LIBFUZZER) | 409 | if(NOT LIBFUZZER AND NOT FUZZ) |
419 | subdirs(regress) | 410 | subdirs(regress) |
420 | endif() | 411 | endif() |
421 | endif() | 412 | endif() |
@@ -1,3 +1,21 @@ | |||
1 | * Version 1.5.0 (2020-09-01) | ||
2 | ** hid_linux: return FIDO_OK if no devices are found. | ||
3 | ** hid_osx: | ||
4 | - repair communication with U2F tokens, gh#166; | ||
5 | - reliability fixes. | ||
6 | ** fido2-{assert,cred}: new options to explicitly toggle UP, UV. | ||
7 | ** Support for configurable report lengths. | ||
8 | ** New API calls: | ||
9 | - fido_cbor_info_maxcredcntlst; | ||
10 | - fido_cbor_info_maxcredidlen; | ||
11 | - fido_cred_aaguid_len; | ||
12 | - fido_cred_aaguid_ptr; | ||
13 | - fido_dev_get_touch_begin; | ||
14 | - fido_dev_get_touch_status. | ||
15 | ** Use COSE_ECDH_ES256 with CTAP_CBOR_CLIENT_PIN; gh#154. | ||
16 | ** Allow CTAP messages up to 2048 bytes; gh#171. | ||
17 | ** Ensure we only list USB devices by default. | ||
18 | |||
1 | * Version 1.4.0 (2020-04-15) | 19 | * Version 1.4.0 (2020-04-15) |
2 | ** hid_hidapi: hidapi backend; enable with -DUSE_HIDAPI=1. | 20 | ** hid_hidapi: hidapi backend; enable with -DUSE_HIDAPI=1. |
3 | ** Fall back to U2F if the key claims to, but does not support FIDO2. | 21 | ** Fall back to U2F if the key claims to, but does not support FIDO2. |
diff --git a/README.adoc b/README.adoc index f389a83..6fe0272 100644 --- a/README.adoc +++ b/README.adoc | |||
@@ -1,8 +1,10 @@ | |||
1 | == libfido2 | 1 | == libfido2 |
2 | 2 | ||
3 | image:https://api.travis-ci.org/Yubico/libfido2.svg?branch=master["Build Status (Travis)", link="https://travis-ci.org/Yubico/libfido2"] | 3 | image:https://github.com/yubico/libfido2/workflows/linux/badge.svg["Linux Build Status (github actions)", link="https://github.com/Yubico/libfido2/actions"] |
4 | image:https://github.com/yubico/libfido2/workflows/windows/badge.svg["windows build status (github actions)", link="https://github.com/Yubico/libfido2/actions"] | 4 | image:https://github.com/yubico/libfido2/workflows/macos/badge.svg["macOS Build Status (github actions)", link="https://github.com/Yubico/libfido2/actions"] |
5 | image:https://img.shields.io/badge/license-BSD-blue.svg["License", link="https://raw.githubusercontent.com/Yubico/libfido2/master/LICENSE"] | 5 | image:https://github.com/yubico/libfido2/workflows/windows/badge.svg["Windows Build Status (github actions)", link="https://github.com/Yubico/libfido2/actions"] |
6 | image:https://github.com/yubico/libfido2/workflows/fuzzer/badge.svg["Fuzz Status (github actions)", link="https://github.com/Yubico/libfido2/actions"] | ||
7 | image:https://oss-fuzz-build-logs.storage.googleapis.com/badges/libfido2.svg["Fuzz Status (oss-fuzz)", link="https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:libfido2"] | ||
6 | 8 | ||
7 | *libfido2* provides library functionality and command-line tools to | 9 | *libfido2* provides library functionality and command-line tools to |
8 | communicate with a FIDO device over USB, and to verify attestation and | 10 | communicate with a FIDO device over USB, and to verify attestation and |
@@ -14,7 +16,7 @@ For usage, see the `examples/` directory. | |||
14 | 16 | ||
15 | === License | 17 | === License |
16 | 18 | ||
17 | *libfido2* is licensed under the BSD 2-clause license. See the _LICENSE_ | 19 | *libfido2* is licensed under the BSD 2-clause license. See the LICENSE |
18 | file for the full license text. | 20 | file for the full license text. |
19 | 21 | ||
20 | === Supported Platforms | 22 | === Supported Platforms |
@@ -31,11 +33,17 @@ is also available. | |||
31 | 33 | ||
32 | ==== Releases | 34 | ==== Releases |
33 | 35 | ||
34 | The current release of *libfido2* is 1.4.0. Please consult Yubico's | 36 | The current release of *libfido2* is 1.5.0. Please consult Yubico's |
35 | https://developers.yubico.com/libfido2/Releases[release page] for source | 37 | https://developers.yubico.com/libfido2/Releases[release page] for source |
36 | and binary releases. | 38 | and binary releases. |
37 | 39 | ||
38 | ==== Ubuntu | 40 | ==== Ubuntu 20.04 (Focal) |
41 | |||
42 | $ sudo apt install libfido2-1 | ||
43 | $ sudo apt install libfido2-dev | ||
44 | $ sudo apt install libfido2-doc | ||
45 | |||
46 | ==== Ubuntu 18.04 (Bionic) and 16.04 (Xenial) | ||
39 | 47 | ||
40 | $ sudo apt install software-properties-common | 48 | $ sudo apt install software-properties-common |
41 | $ sudo apt-add-repository ppa:yubico/stable | 49 | $ sudo apt-add-repository ppa:yubico/stable |
@@ -52,15 +60,16 @@ Or from source, on UNIX-like systems: | |||
52 | $ make -C build | 60 | $ make -C build |
53 | $ sudo make -C build install | 61 | $ sudo make -C build install |
54 | 62 | ||
55 | Depending on the platform, the PKG_CONFIG_PATH environment variable may need to | 63 | Depending on the platform, |
56 | be set. | 64 | https://www.freedesktop.org/wiki/Software/pkg-config/[pkg-config] may need to |
65 | be installed, or the PKG_CONFIG_PATH environment variable set. | ||
57 | 66 | ||
58 | *libfido2* depends on https://github.com/pjk/libcbor[libcbor] and | 67 | *libfido2* depends on https://github.com/pjk/libcbor[libcbor] and |
59 | https://www.openssl.org[OpenSSL]. On Linux, libudev (part of | 68 | https://www.openssl.org[OpenSSL]. On Linux, libudev (part of |
60 | https://www.freedesktop.org/wiki/Software/systemd[systemd]) is also required. | 69 | https://www.freedesktop.org/wiki/Software/systemd[systemd]) is also required. |
61 | 70 | ||
62 | For complete, OS-specific installation instructions, please refer to the | 71 | For complete, OS-specific installation instructions, please refer to the |
63 | `.travis/` (Linux, MacOS) and `windows/` directories. | 72 | `.actions/` (Linux, MacOS) and `windows/` directories. |
64 | 73 | ||
65 | On Linux, you will need to add a udev rule to be able to access the FIDO | 74 | On Linux, you will need to add a udev rule to be able to access the FIDO |
66 | device, or run as root. For example, the udev rule may contain the following: | 75 | device, or run as root. For example, the udev rule may contain the following: |
diff --git a/debian/changelog b/debian/changelog index a93d809..bac765a 100644 --- a/debian/changelog +++ b/debian/changelog | |||
@@ -1,3 +1,9 @@ | |||
1 | libfido2 (1.5.0-1) UNRELEASED; urgency=medium | ||
2 | |||
3 | * New upstream release. | ||
4 | |||
5 | -- Colin Watson <cjwatson@debian.org> Sun, 20 Sep 2020 16:15:26 +0100 | ||
6 | |||
1 | libfido2 (1.4.0-2) unstable; urgency=medium | 7 | libfido2 (1.4.0-2) unstable; urgency=medium |
2 | 8 | ||
3 | [ nicoo ] | 9 | [ nicoo ] |
diff --git a/debian/libfido2-1.symbols b/debian/libfido2-1.symbols index 810a8fb..2b34e9b 100644 --- a/debian/libfido2-1.symbols +++ b/debian/libfido2-1.symbols | |||
@@ -76,6 +76,8 @@ libfido2.so.1 libfido2-1 #MINVER# | |||
76 | fido_cbor_info_extensions_ptr@Base 1.1.0 | 76 | fido_cbor_info_extensions_ptr@Base 1.1.0 |
77 | fido_cbor_info_free@Base 1.1.0 | 77 | fido_cbor_info_free@Base 1.1.0 |
78 | fido_cbor_info_fwversion@Base 1.4.0 | 78 | fido_cbor_info_fwversion@Base 1.4.0 |
79 | fido_cbor_info_maxcredcntlst@Base 1.5.0 | ||
80 | fido_cbor_info_maxcredidlen@Base 1.5.0 | ||
79 | fido_cbor_info_maxmsgsiz@Base 1.1.0 | 81 | fido_cbor_info_maxmsgsiz@Base 1.1.0 |
80 | fido_cbor_info_new@Base 1.1.0 | 82 | fido_cbor_info_new@Base 1.1.0 |
81 | fido_cbor_info_options_len@Base 1.1.0 | 83 | fido_cbor_info_options_len@Base 1.1.0 |
@@ -85,6 +87,8 @@ libfido2.so.1 libfido2-1 #MINVER# | |||
85 | fido_cbor_info_protocols_ptr@Base 1.1.0 | 87 | fido_cbor_info_protocols_ptr@Base 1.1.0 |
86 | fido_cbor_info_versions_len@Base 1.1.0 | 88 | fido_cbor_info_versions_len@Base 1.1.0 |
87 | fido_cbor_info_versions_ptr@Base 1.1.0 | 89 | fido_cbor_info_versions_ptr@Base 1.1.0 |
90 | fido_cred_aaguid_len@Base 1.5.0 | ||
91 | fido_cred_aaguid_ptr@Base 1.5.0 | ||
88 | fido_cred_authdata_len@Base 1.1.0 | 92 | fido_cred_authdata_len@Base 1.1.0 |
89 | fido_cred_authdata_ptr@Base 1.1.0 | 93 | fido_cred_authdata_ptr@Base 1.1.0 |
90 | fido_cred_clientdata_hash_len@Base 1.1.0 | 94 | fido_cred_clientdata_hash_len@Base 1.1.0 |
@@ -155,6 +159,9 @@ libfido2.so.1 libfido2-1 #MINVER# | |||
155 | fido_dev_get_assert@Base 1.1.0 | 159 | fido_dev_get_assert@Base 1.1.0 |
156 | fido_dev_get_cbor_info@Base 1.1.0 | 160 | fido_dev_get_cbor_info@Base 1.1.0 |
157 | fido_dev_get_retry_count@Base 1.1.0 | 161 | fido_dev_get_retry_count@Base 1.1.0 |
162 | fido_dev_get_touch_begin@Base 1.5.0 | ||
163 | fido_dev_get_touch_status@Base 1.5.0 | ||
164 | fido_dev_has_pin@Base 1.5.0 | ||
158 | fido_dev_info_free@Base 1.1.0 | 165 | fido_dev_info_free@Base 1.1.0 |
159 | fido_dev_info_manifest@Base 1.1.0 | 166 | fido_dev_info_manifest@Base 1.1.0 |
160 | fido_dev_info_manufacturer_string@Base 1.1.0 | 167 | fido_dev_info_manufacturer_string@Base 1.1.0 |
@@ -172,6 +179,8 @@ libfido2.so.1 libfido2-1 #MINVER# | |||
172 | fido_dev_open@Base 1.1.0 | 179 | fido_dev_open@Base 1.1.0 |
173 | fido_dev_protocol@Base 1.1.0 | 180 | fido_dev_protocol@Base 1.1.0 |
174 | fido_dev_reset@Base 1.1.0 | 181 | fido_dev_reset@Base 1.1.0 |
182 | fido_dev_supports_cred_prot@Base 1.5.0 | ||
183 | fido_dev_supports_pin@Base 1.5.0 | ||
175 | fido_dev_set_io_functions@Base 1.1.0 | 184 | fido_dev_set_io_functions@Base 1.1.0 |
176 | fido_dev_set_pin@Base 1.1.0 | 185 | fido_dev_set_pin@Base 1.1.0 |
177 | fido_dev_set_transport_functions@Base 1.4.0 | 186 | fido_dev_set_transport_functions@Base 1.4.0 |
diff --git a/debian/libfido2-doc.links b/debian/libfido2-doc.links deleted file mode 100644 index d6a52ca..0000000 --- a/debian/libfido2-doc.links +++ /dev/null | |||
@@ -1,277 +0,0 @@ | |||
1 | /usr/share/man/man3/eddsa_pk_new.3 /usr/share/man/man3/eddsa_pk_free.3 | ||
2 | /usr/share/man/man3/eddsa_pk_new.3 /usr/share/man/man3/eddsa_pk_from_ptr.3 | ||
3 | /usr/share/man/man3/eddsa_pk_new.3 /usr/share/man/man3/eddsa_pk_to_EVP_PKEY.3 | ||
4 | /usr/share/man/man3/es256_pk_new.3 /usr/share/man/man3/es256_pk_free.3 | ||
5 | /usr/share/man/man3/es256_pk_new.3 /usr/share/man/man3/es256_pk_from_EC_KEY.3 | ||
6 | /usr/share/man/man3/es256_pk_new.3 /usr/share/man/man3/es256_pk_from_ptr.3 | ||
7 | /usr/share/man/man3/es256_pk_new.3 /usr/share/man/man3/es256_pk_to_EVP_PKEY.3 | ||
8 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_authdata_len.3 | ||
9 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_authdata_ptr.3 | ||
10 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_clientdata_hash_len.3 | ||
11 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_clientdata_hash_ptr.3 | ||
12 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_count.3 | ||
13 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_free.3 | ||
14 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_hmac_secret_len.3 | ||
15 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_hmac_secret_ptr.3 | ||
16 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_sigcount.3 | ||
17 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_sig_len.3 | ||
18 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_sig_ptr.3 | ||
19 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_user_display_name.3 | ||
20 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_user_icon.3 | ||
21 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_user_id_len.3 | ||
22 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_user_id_ptr.3 | ||
23 | /usr/share/man/man3/fido_assert_new.3 /usr/share/man/man3/fido_assert_user_name.3 | ||
24 | /usr/share/man/man3/fido_assert_set_authdata.3 /usr/share/man/man3/fido_assert_set_clientdata_hash.3 | ||
25 | /usr/share/man/man3/fido_assert_set_authdata.3 /usr/share/man/man3/fido_assert_set_count.3 | ||
26 | /usr/share/man/man3/fido_assert_set_authdata.3 /usr/share/man/man3/fido_assert_set_extensions.3 | ||
27 | /usr/share/man/man3/fido_assert_set_authdata.3 /usr/share/man/man3/fido_assert_set_hmac_salt.3 | ||
28 | /usr/share/man/man3/fido_assert_set_authdata.3 /usr/share/man/man3/fido_assert_set_rp.3 | ||
29 | /usr/share/man/man3/fido_assert_set_authdata.3 /usr/share/man/man3/fido_assert_set_sig.3 | ||
30 | /usr/share/man/man3/fido_assert_set_authdata.3 /usr/share/man/man3/fido_assert_set_up.3 | ||
31 | /usr/share/man/man3/fido_assert_set_authdata.3 /usr/share/man/man3/fido_assert_set_uv.3 | ||
32 | /usr/share/man/man3/fido_bio_dev_get_info.3 /usr/share/man/man3/fido_bio_dev_enroll_begin.3 | ||
33 | /usr/share/man/man3/fido_bio_dev_get_info.3 /usr/share/man/man3/fido_bio_dev_enroll_cancel.3 | ||
34 | /usr/share/man/man3/fido_bio_dev_get_info.3 /usr/share/man/man3/fido_bio_dev_enroll_continue.3 | ||
35 | /usr/share/man/man3/fido_bio_dev_get_info.3 /usr/share/man/man3/fido_bio_dev_enroll_remove.3 | ||
36 | /usr/share/man/man3/fido_bio_dev_get_info.3 /usr/share/man/man3/fido_bio_dev_get_template_array.3 | ||
37 | /usr/share/man/man3/fido_bio_dev_get_info.3 /usr/share/man/man3/fido_bio_dev_set_template_name.3 | ||
38 | /usr/share/man/man3/fido_bio_enroll_new.3 /usr/share/man/man3/fido_bio_enroll_free.3 | ||
39 | /usr/share/man/man3/fido_bio_enroll_new.3 /usr/share/man/man3/fido_bio_enroll_last_status.3 | ||
40 | /usr/share/man/man3/fido_bio_enroll_new.3 /usr/share/man/man3/fido_bio_enroll_remaining_samples.3 | ||
41 | /usr/share/man/man3/fido_bio_info_new.3 /usr/share/man/man3/fido_bio_info_free.3 | ||
42 | /usr/share/man/man3/fido_bio_info_new.3 /usr/share/man/man3/fido_bio_info_max_samples.3 | ||
43 | /usr/share/man/man3/fido_bio_info_new.3 /usr/share/man/man3/fido_bio_info_type.3 | ||
44 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_array_count.3 | ||
45 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_array_free.3 | ||
46 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_array_new.3 | ||
47 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_free.3 | ||
48 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_id_len.3 | ||
49 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_id_ptr.3 | ||
50 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_name.3 | ||
51 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_new.3 | ||
52 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_set_id.3 | ||
53 | /usr/share/man/man3/fido_bio_template.3 /usr/share/man/man3/fido_bio_template_set_name.3 | ||
54 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_aaguid_len.3 | ||
55 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_aaguid_ptr.3 | ||
56 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_extensions_len.3 | ||
57 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_extensions_ptr.3 | ||
58 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_free.3 | ||
59 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_fwversion.3 | ||
60 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_maxmsgsiz.3 | ||
61 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_options_len.3 | ||
62 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_options_name_ptr.3 | ||
63 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_options_value_ptr.3 | ||
64 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_protocols_len.3 | ||
65 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_protocols_ptr.3 | ||
66 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_versions_len.3 | ||
67 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_cbor_info_versions_ptr.3 | ||
68 | /usr/share/man/man3/fido_cbor_info_new.3 /usr/share/man/man3/fido_dev_get_cbor_info.3 | ||
69 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_authdata_len.3 | ||
70 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_authdata_ptr.3 | ||
71 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_clientdata_hash_len.3 | ||
72 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_clientdata_hash_ptr.3 | ||
73 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_fmt.3 | ||
74 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_free.3 | ||
75 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_id_len.3 | ||
76 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_id_ptr.3 | ||
77 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_prot.3 | ||
78 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_pubkey_len.3 | ||
79 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_pubkey_ptr.3 | ||
80 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_sig_len.3 | ||
81 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_sig_ptr.3 | ||
82 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_x5c_len.3 | ||
83 | /usr/share/man/man3/fido_cred_new.3 /usr/share/man/man3/fido_cred_x5c_ptr.3 | ||
84 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_del_dev_rk.3 | ||
85 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_get_dev_metadata.3 | ||
86 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_get_dev_rk.3 | ||
87 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_get_dev_rp.3 | ||
88 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_metadata_free.3 | ||
89 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rk.3 | ||
90 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rk_count.3 | ||
91 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rk_existing.3 | ||
92 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rk_free.3 | ||
93 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rk_new.3 | ||
94 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rk_remaining.3 | ||
95 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rp_count.3 | ||
96 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rp_free.3 | ||
97 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rp_id.3 | ||
98 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rp_id_hash_len.3 | ||
99 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rp_id_hash_ptr.3 | ||
100 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rp_name.3 | ||
101 | /usr/share/man/man3/fido_credman_metadata_new.3 /usr/share/man/man3/fido_credman_rp_new.3 | ||
102 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_authdata_raw.3 | ||
103 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_clientdata_hash.3 | ||
104 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_extensions.3 | ||
105 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_fmt.3 | ||
106 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_prot.3 | ||
107 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_rk.3 | ||
108 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_rp.3 | ||
109 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_sig.3 | ||
110 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_type.3 | ||
111 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_user.3 | ||
112 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_uv.3 | ||
113 | /usr/share/man/man3/fido_cred_set_authdata.3 /usr/share/man/man3/fido_cred_set_x509.3 | ||
114 | /usr/share/man/man3/fido_dev_info_manifest.3 /usr/share/man/man3/fido_dev_info_free.3 | ||
115 | /usr/share/man/man3/fido_dev_info_manifest.3 /usr/share/man/man3/fido_dev_info_manufacturer_string.3 | ||
116 | /usr/share/man/man3/fido_dev_info_manifest.3 /usr/share/man/man3/fido_dev_info_new.3 | ||
117 | /usr/share/man/man3/fido_dev_info_manifest.3 /usr/share/man/man3/fido_dev_info_path.3 | ||
118 | /usr/share/man/man3/fido_dev_info_manifest.3 /usr/share/man/man3/fido_dev_info_product.3 | ||
119 | /usr/share/man/man3/fido_dev_info_manifest.3 /usr/share/man/man3/fido_dev_info_product_string.3 | ||
120 | /usr/share/man/man3/fido_dev_info_manifest.3 /usr/share/man/man3/fido_dev_info_ptr.3 | ||
121 | /usr/share/man/man3/fido_dev_info_manifest.3 /usr/share/man/man3/fido_dev_info_vendor.3 | ||
122 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_build.3 | ||
123 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_cancel.3 | ||
124 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_close.3 | ||
125 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_flags.3 | ||
126 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_force_fido2.3 | ||
127 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_force_u2f.3 | ||
128 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_free.3 | ||
129 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_is_fido2.3 | ||
130 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_major.3 | ||
131 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_minor.3 | ||
132 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_new.3 | ||
133 | /usr/share/man/man3/fido_dev_open.3 /usr/share/man/man3/fido_dev_protocol.3 | ||
134 | /usr/share/man/man3/fido_dev_set_pin.3 /usr/share/man/man3/fido_dev_get_retry_count.3 | ||
135 | /usr/share/man/man3/fido_dev_set_pin.3 /usr/share/man/man3/fido_dev_reset.3 | ||
136 | /usr/share/man/man3/rs256_pk_new.3 /usr/share/man/man3/rs256_pk_free.3 | ||
137 | /usr/share/man/man3/rs256_pk_new.3 /usr/share/man/man3/rs256_pk_from_ptr.3 | ||
138 | /usr/share/man/man3/rs256_pk_new.3 /usr/share/man/man3/rs256_pk_from_RSA.3 | ||
139 | /usr/share/man/man3/rs256_pk_new.3 /usr/share/man/man3/rs256_pk_to_EVP_PKEY.3 | ||
140 | /usr/share/doc/libfido2/html/eddsa_pk_new.html /usr/share/doc/libfido2/html/eddsa_pk_free.html | ||
141 | /usr/share/doc/libfido2/html/eddsa_pk_new.html /usr/share/doc/libfido2/html/eddsa_pk_from_ptr.html | ||
142 | /usr/share/doc/libfido2/html/eddsa_pk_new.html /usr/share/doc/libfido2/html/eddsa_pk_to_EVP_PKEY.html | ||
143 | /usr/share/doc/libfido2/html/es256_pk_new.html /usr/share/doc/libfido2/html/es256_pk_free.html | ||
144 | /usr/share/doc/libfido2/html/es256_pk_new.html /usr/share/doc/libfido2/html/es256_pk_from_EC_KEY.html | ||
145 | /usr/share/doc/libfido2/html/es256_pk_new.html /usr/share/doc/libfido2/html/es256_pk_from_ptr.html | ||
146 | /usr/share/doc/libfido2/html/es256_pk_new.html /usr/share/doc/libfido2/html/es256_pk_to_EVP_PKEY.html | ||
147 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_authdata_len.html | ||
148 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_authdata_ptr.html | ||
149 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_clientdata_hash_len.html | ||
150 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_clientdata_hash_ptr.html | ||
151 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_count.html | ||
152 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_free.html | ||
153 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_hmac_secret_len.html | ||
154 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_hmac_secret_ptr.html | ||
155 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_sigcount.html | ||
156 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_sig_len.html | ||
157 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_sig_ptr.html | ||
158 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_user_display_name.html | ||
159 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_user_icon.html | ||
160 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_user_id_len.html | ||
161 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_user_id_ptr.html | ||
162 | /usr/share/doc/libfido2/html/fido_assert_new.html /usr/share/doc/libfido2/html/fido_assert_user_name.html | ||
163 | /usr/share/doc/libfido2/html/fido_assert_set_authdata.html /usr/share/doc/libfido2/html/fido_assert_set_clientdata_hash.html | ||
164 | /usr/share/doc/libfido2/html/fido_assert_set_authdata.html /usr/share/doc/libfido2/html/fido_assert_set_count.html | ||
165 | /usr/share/doc/libfido2/html/fido_assert_set_authdata.html /usr/share/doc/libfido2/html/fido_assert_set_extensions.html | ||
166 | /usr/share/doc/libfido2/html/fido_assert_set_authdata.html /usr/share/doc/libfido2/html/fido_assert_set_hmac_salt.html | ||
167 | /usr/share/doc/libfido2/html/fido_assert_set_authdata.html /usr/share/doc/libfido2/html/fido_assert_set_rp.html | ||
168 | /usr/share/doc/libfido2/html/fido_assert_set_authdata.html /usr/share/doc/libfido2/html/fido_assert_set_sig.html | ||
169 | /usr/share/doc/libfido2/html/fido_assert_set_authdata.html /usr/share/doc/libfido2/html/fido_assert_set_up.html | ||
170 | /usr/share/doc/libfido2/html/fido_assert_set_authdata.html /usr/share/doc/libfido2/html/fido_assert_set_uv.html | ||
171 | /usr/share/doc/libfido2/html/fido_bio_dev_get_info.html /usr/share/doc/libfido2/html/fido_bio_dev_enroll_begin.html | ||
172 | /usr/share/doc/libfido2/html/fido_bio_dev_get_info.html /usr/share/doc/libfido2/html/fido_bio_dev_enroll_cancel.html | ||
173 | /usr/share/doc/libfido2/html/fido_bio_dev_get_info.html /usr/share/doc/libfido2/html/fido_bio_dev_enroll_continue.html | ||
174 | /usr/share/doc/libfido2/html/fido_bio_dev_get_info.html /usr/share/doc/libfido2/html/fido_bio_dev_enroll_remove.html | ||
175 | /usr/share/doc/libfido2/html/fido_bio_dev_get_info.html /usr/share/doc/libfido2/html/fido_bio_dev_get_template_array.html | ||
176 | /usr/share/doc/libfido2/html/fido_bio_dev_get_info.html /usr/share/doc/libfido2/html/fido_bio_dev_set_template_name.html | ||
177 | /usr/share/doc/libfido2/html/fido_bio_enroll_new.html /usr/share/doc/libfido2/html/fido_bio_enroll_free.html | ||
178 | /usr/share/doc/libfido2/html/fido_bio_enroll_new.html /usr/share/doc/libfido2/html/fido_bio_enroll_last_status.html | ||
179 | /usr/share/doc/libfido2/html/fido_bio_enroll_new.html /usr/share/doc/libfido2/html/fido_bio_enroll_remaining_samples.html | ||
180 | /usr/share/doc/libfido2/html/fido_bio_info_new.html /usr/share/doc/libfido2/html/fido_bio_info_free.html | ||
181 | /usr/share/doc/libfido2/html/fido_bio_info_new.html /usr/share/doc/libfido2/html/fido_bio_info_max_samples.html | ||
182 | /usr/share/doc/libfido2/html/fido_bio_info_new.html /usr/share/doc/libfido2/html/fido_bio_info_type.html | ||
183 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_array_count.html | ||
184 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_array_free.html | ||
185 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_array_new.html | ||
186 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_free.html | ||
187 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_id_len.html | ||
188 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_id_ptr.html | ||
189 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_name.html | ||
190 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_new.html | ||
191 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_set_id.html | ||
192 | /usr/share/doc/libfido2/html/fido_bio_template.html /usr/share/doc/libfido2/html/fido_bio_template_set_name.html | ||
193 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_aaguid_len.html | ||
194 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_aaguid_ptr.html | ||
195 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_extensions_len.html | ||
196 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_extensions_ptr.html | ||
197 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_free.html | ||
198 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_maxmsgsiz.html | ||
199 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_options_len.html | ||
200 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_options_name_ptr.html | ||
201 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_options_value_ptr.html | ||
202 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_protocols_len.html | ||
203 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_protocols_ptr.html | ||
204 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_versions_len.html | ||
205 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_cbor_info_versions_ptr.html | ||
206 | /usr/share/doc/libfido2/html/fido_cbor_info_new.html /usr/share/doc/libfido2/html/fido_dev_get_cbor_info.html | ||
207 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_authdata_len.html | ||
208 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_authdata_ptr.html | ||
209 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_clientdata_hash_len.html | ||
210 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_clientdata_hash_ptr.html | ||
211 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_fmt.html | ||
212 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_free.html | ||
213 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_id_len.html | ||
214 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_id_ptr.html | ||
215 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_prot.html | ||
216 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_pubkey_len.html | ||
217 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_pubkey_ptr.html | ||
218 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_sig_len.html | ||
219 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_sig_ptr.html | ||
220 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_x5c_len.html | ||
221 | /usr/share/doc/libfido2/html/fido_cred_new.html /usr/share/doc/libfido2/html/fido_cred_x5c_ptr.html | ||
222 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_del_dev_rk.html | ||
223 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_get_dev_metadata.html | ||
224 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_get_dev_rk.html | ||
225 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_get_dev_rp.html | ||
226 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_metadata_free.html | ||
227 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rk.html | ||
228 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rk_count.html | ||
229 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rk_existing.html | ||
230 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rk_free.html | ||
231 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rk_new.html | ||
232 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rk_remaining.html | ||
233 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rp_count.html | ||
234 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rp_free.html | ||
235 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rp_id.html | ||
236 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rp_id_hash_len.html | ||
237 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rp_id_hash_ptr.html | ||
238 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rp_name.html | ||
239 | /usr/share/doc/libfido2/html/fido_credman_metadata_new.html /usr/share/doc/libfido2/html/fido_credman_rp_new.html | ||
240 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_authdata_raw.html | ||
241 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_clientdata_hash.html | ||
242 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_extensions.html | ||
243 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_fmt.html | ||
244 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_prot.html | ||
245 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_rk.html | ||
246 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_rp.html | ||
247 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_sig.html | ||
248 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_type.html | ||
249 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_user.html | ||
250 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_uv.html | ||
251 | /usr/share/doc/libfido2/html/fido_cred_set_authdata.html /usr/share/doc/libfido2/html/fido_cred_set_x509.html | ||
252 | /usr/share/doc/libfido2/html/fido_dev_info_manifest.html /usr/share/doc/libfido2/html/fido_dev_info_free.html | ||
253 | /usr/share/doc/libfido2/html/fido_dev_info_manifest.html /usr/share/doc/libfido2/html/fido_dev_info_manufacturer_string.html | ||
254 | /usr/share/doc/libfido2/html/fido_dev_info_manifest.html /usr/share/doc/libfido2/html/fido_dev_info_new.html | ||
255 | /usr/share/doc/libfido2/html/fido_dev_info_manifest.html /usr/share/doc/libfido2/html/fido_dev_info_path.html | ||
256 | /usr/share/doc/libfido2/html/fido_dev_info_manifest.html /usr/share/doc/libfido2/html/fido_dev_info_product.html | ||
257 | /usr/share/doc/libfido2/html/fido_dev_info_manifest.html /usr/share/doc/libfido2/html/fido_dev_info_product_string.html | ||
258 | /usr/share/doc/libfido2/html/fido_dev_info_manifest.html /usr/share/doc/libfido2/html/fido_dev_info_ptr.html | ||
259 | /usr/share/doc/libfido2/html/fido_dev_info_manifest.html /usr/share/doc/libfido2/html/fido_dev_info_vendor.html | ||
260 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_build.html | ||
261 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_cancel.html | ||
262 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_close.html | ||
263 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_flags.html | ||
264 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_force_fido2.html | ||
265 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_force_u2f.html | ||
266 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_free.html | ||
267 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_is_fido2.html | ||
268 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_major.html | ||
269 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_minor.html | ||
270 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_new.html | ||
271 | /usr/share/doc/libfido2/html/fido_dev_open.html /usr/share/doc/libfido2/html/fido_dev_protocol.html | ||
272 | /usr/share/doc/libfido2/html/fido_dev_set_pin.html /usr/share/doc/libfido2/html/fido_dev_get_retry_count.html | ||
273 | /usr/share/doc/libfido2/html/fido_dev_set_pin.html /usr/share/doc/libfido2/html/fido_dev_reset.html | ||
274 | /usr/share/doc/libfido2/html/rs256_pk_new.html /usr/share/doc/libfido2/html/rs256_pk_free.html | ||
275 | /usr/share/doc/libfido2/html/rs256_pk_new.html /usr/share/doc/libfido2/html/rs256_pk_from_ptr.html | ||
276 | /usr/share/doc/libfido2/html/rs256_pk_new.html /usr/share/doc/libfido2/html/rs256_pk_from_RSA.html | ||
277 | /usr/share/doc/libfido2/html/rs256_pk_new.html /usr/share/doc/libfido2/html/rs256_pk_to_EVP_PKEY.html | ||
diff --git a/docker/bionic/Dockerfile b/docker/bionic/Dockerfile deleted file mode 100644 index 9225ed8..0000000 --- a/docker/bionic/Dockerfile +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | # unlock-yk | ||
2 | # docker run --rm --volume=/home/pedro/projects/libfido2:/workdir \ | ||
3 | # --volume=$(gpgconf --list-dirs socketdir):/root/.gnupg \ | ||
4 | # --volume=$(gpgconf --list-dirs homedir)/pubring.kbx:/root/.gnupg/pubring.kbx \ | ||
5 | # -it libfido2-staging --install-deps --ppa martelletto/ppa \ | ||
6 | # --key pedro@yubico.com | ||
7 | FROM ubuntu:bionic | ||
8 | ENV DEBIAN_FRONTEND noninteractive | ||
9 | RUN apt-get -qq update && apt-get -qq upgrade | ||
10 | RUN apt-get install -qq packaging-dev debian-keyring devscripts equivs gnupg python sudo | ||
11 | ADD https://raw.githubusercontent.com/dainnilsson/scripts/master/make-ppa /make-ppa | ||
12 | RUN chmod +x /make-ppa | ||
13 | WORKDIR /workdir | ||
14 | ENTRYPOINT ["/make-ppa"] | ||
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 1203592..7228860 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt | |||
@@ -3,6 +3,7 @@ | |||
3 | # license that can be found in the LICENSE file. | 3 | # license that can be found in the LICENSE file. |
4 | 4 | ||
5 | list(APPEND COMPAT_SOURCES | 5 | list(APPEND COMPAT_SOURCES |
6 | ../openbsd-compat/clock_gettime.c | ||
6 | ../openbsd-compat/getopt_long.c | 7 | ../openbsd-compat/getopt_long.c |
7 | ../openbsd-compat/strlcat.c | 8 | ../openbsd-compat/strlcat.c |
8 | ../openbsd-compat/strlcpy.c | 9 | ../openbsd-compat/strlcpy.c |
@@ -15,6 +16,13 @@ endif() | |||
15 | # drop -rdynamic | 16 | # drop -rdynamic |
16 | set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") | 17 | set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") |
17 | 18 | ||
19 | # enable -Wconversion -Wsign-conversion | ||
20 | if(NOT MSVC) | ||
21 | set_source_files_properties(assert.c cred.c info.c manifest.c reset.c | ||
22 | retries.c setpin.c util.c PROPERTIES COMPILE_FLAGS | ||
23 | "-Wconversion -Wsign-conversion") | ||
24 | endif() | ||
25 | |||
18 | # manifest | 26 | # manifest |
19 | add_executable(manifest manifest.c ${COMPAT_SOURCES}) | 27 | add_executable(manifest manifest.c ${COMPAT_SOURCES}) |
20 | target_link_libraries(manifest fido2) | 28 | target_link_libraries(manifest fido2) |
@@ -42,3 +50,11 @@ target_link_libraries(setpin fido2) | |||
42 | # retries | 50 | # retries |
43 | add_executable(retries retries.c ${COMPAT_SOURCES}) | 51 | add_executable(retries retries.c ${COMPAT_SOURCES}) |
44 | target_link_libraries(retries fido2) | 52 | target_link_libraries(retries fido2) |
53 | |||
54 | # select | ||
55 | add_executable(select select.c ${COMPAT_SOURCES}) | ||
56 | target_link_libraries(select fido2) | ||
57 | if(MINGW) | ||
58 | # needed for nanosleep() in mingw | ||
59 | target_link_libraries(select winpthread) | ||
60 | endif() | ||
diff --git a/examples/README.adoc b/examples/README.adoc index 091c6bc..b7b73d8 100644 --- a/examples/README.adoc +++ b/examples/README.adoc | |||
@@ -77,5 +77,14 @@ The following examples are provided: | |||
77 | - retries <device> | 77 | - retries <device> |
78 | Get the number of PIN attempts left on <device> before lockout. | 78 | Get the number of PIN attempts left on <device> before lockout. |
79 | 79 | ||
80 | - select | ||
81 | |||
82 | Enumerates available FIDO devices and, if more than one is present, | ||
83 | simultaneously requests touch on all of them, printing information | ||
84 | about the device touched. | ||
85 | |||
80 | Debugging is possible through the use of the FIDO_DEBUG environment variable. | 86 | Debugging is possible through the use of the FIDO_DEBUG environment variable. |
81 | If set, libfido2 will produce a log of its transactions with the authenticator. | 87 | If set, libfido2 will produce a log of its transactions with the authenticator. |
88 | |||
89 | Additionally, an example of a WebAuthn client using libfido2 is available at | ||
90 | https://github.com/martelletto/fido2-webauthn-client. | ||
diff --git a/examples/assert.c b/examples/assert.c index a421a51..a18d8af 100644 --- a/examples/assert.c +++ b/examples/assert.c | |||
@@ -14,17 +14,12 @@ | |||
14 | #include <unistd.h> | 14 | #include <unistd.h> |
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | #include "../openbsd-compat/openbsd-compat.h" | ||
18 | |||
19 | #include "fido.h" | 17 | #include "fido.h" |
20 | #include "fido/es256.h" | 18 | #include "fido/es256.h" |
21 | #include "fido/rs256.h" | 19 | #include "fido/rs256.h" |
22 | #include "fido/eddsa.h" | 20 | #include "fido/eddsa.h" |
23 | #include "extern.h" | 21 | #include "extern.h" |
24 | 22 | #include "../openbsd-compat/openbsd-compat.h" | |
25 | #ifdef SIGNAL_EXAMPLE | ||
26 | extern volatile sig_atomic_t got_signal; | ||
27 | #endif | ||
28 | 23 | ||
29 | static const unsigned char cdh[32] = { | 24 | static const unsigned char cdh[32] = { |
30 | 0xec, 0x8d, 0x8f, 0x78, 0x42, 0x4a, 0x2b, 0xb7, | 25 | 0xec, 0x8d, 0x8f, 0x78, 0x42, 0x4a, 0x2b, 0xb7, |
@@ -188,13 +183,15 @@ main(int argc, char **argv) | |||
188 | break; | 183 | break; |
189 | case 'T': | 184 | case 'T': |
190 | #ifndef SIGNAL_EXAMPLE | 185 | #ifndef SIGNAL_EXAMPLE |
186 | (void)seconds; | ||
191 | errx(1, "-T not supported"); | 187 | errx(1, "-T not supported"); |
192 | #endif | 188 | #else |
193 | if (base10(optarg, &seconds) < 0) | 189 | if (base10(optarg, &seconds) < 0) |
194 | errx(1, "base10: %s", optarg); | 190 | errx(1, "base10: %s", optarg); |
195 | if (seconds <= 0 || seconds > 30) | 191 | if (seconds <= 0 || seconds > 30) |
196 | errx(1, "-T: %s must be in (0,30]", optarg); | 192 | errx(1, "-T: %s must be in (0,30]", optarg); |
197 | break; | 193 | break; |
194 | #endif | ||
198 | case 'a': | 195 | case 'a': |
199 | if (read_blob(optarg, &body, &len) < 0) | 196 | if (read_blob(optarg, &body, &len) < 0) |
200 | errx(1, "read_blob: %s", optarg); | 197 | errx(1, "read_blob: %s", optarg); |
@@ -312,6 +309,10 @@ main(int argc, char **argv) | |||
312 | errx(1, "fido_assert_count: %d signatures returned", | 309 | errx(1, "fido_assert_count: %d signatures returned", |
313 | (int)fido_assert_count(assert)); | 310 | (int)fido_assert_count(assert)); |
314 | 311 | ||
312 | /* when verifying, pin implies uv */ | ||
313 | if (pin) | ||
314 | uv = true; | ||
315 | |||
315 | verify_assert(type, fido_assert_authdata_ptr(assert, 0), | 316 | verify_assert(type, fido_assert_authdata_ptr(assert, 0), |
316 | fido_assert_authdata_len(assert, 0), fido_assert_sig_ptr(assert, 0), | 317 | fido_assert_authdata_len(assert, 0), fido_assert_sig_ptr(assert, 0), |
317 | fido_assert_sig_len(assert, 0), up, uv, ext, argv[0]); | 318 | fido_assert_sig_len(assert, 0), up, uv, ext, argv[0]); |
diff --git a/examples/cred.c b/examples/cred.c index 3e0a30f..6bd0faf 100644 --- a/examples/cred.c +++ b/examples/cred.c | |||
@@ -16,14 +16,9 @@ | |||
16 | #include <unistd.h> | 16 | #include <unistd.h> |
17 | #endif | 17 | #endif |
18 | 18 | ||
19 | #include "../openbsd-compat/openbsd-compat.h" | ||
20 | |||
21 | #include "fido.h" | 19 | #include "fido.h" |
22 | #include "extern.h" | 20 | #include "extern.h" |
23 | 21 | #include "../openbsd-compat/openbsd-compat.h" | |
24 | #ifdef SIGNAL_EXAMPLE | ||
25 | extern volatile sig_atomic_t got_signal; | ||
26 | #endif | ||
27 | 22 | ||
28 | static const unsigned char cdh[32] = { | 23 | static const unsigned char cdh[32] = { |
29 | 0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb, | 24 | 0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb, |
@@ -192,13 +187,15 @@ main(int argc, char **argv) | |||
192 | break; | 187 | break; |
193 | case 'T': | 188 | case 'T': |
194 | #ifndef SIGNAL_EXAMPLE | 189 | #ifndef SIGNAL_EXAMPLE |
190 | (void)seconds; | ||
195 | errx(1, "-T not supported"); | 191 | errx(1, "-T not supported"); |
196 | #endif | 192 | #else |
197 | if (base10(optarg, &seconds) < 0) | 193 | if (base10(optarg, &seconds) < 0) |
198 | errx(1, "base10: %s", optarg); | 194 | errx(1, "base10: %s", optarg); |
199 | if (seconds <= 0 || seconds > 30) | 195 | if (seconds <= 0 || seconds > 30) |
200 | errx(1, "-T: %s must be in (0,30]", optarg); | 196 | errx(1, "-T: %s must be in (0,30]", optarg); |
201 | break; | 197 | break; |
198 | #endif | ||
202 | case 'e': | 199 | case 'e': |
203 | if (read_blob(optarg, &body, &len) < 0) | 200 | if (read_blob(optarg, &body, &len) < 0) |
204 | errx(1, "read_blob: %s", optarg); | 201 | errx(1, "read_blob: %s", optarg); |
@@ -318,6 +315,10 @@ main(int argc, char **argv) | |||
318 | 315 | ||
319 | fido_dev_free(&dev); | 316 | fido_dev_free(&dev); |
320 | 317 | ||
318 | /* when verifying, pin implies uv */ | ||
319 | if (pin) | ||
320 | uv = true; | ||
321 | |||
321 | verify_cred(type, fido_cred_fmt(cred), fido_cred_authdata_ptr(cred), | 322 | verify_cred(type, fido_cred_fmt(cred), fido_cred_authdata_ptr(cred), |
322 | fido_cred_authdata_len(cred), fido_cred_x5c_ptr(cred), | 323 | fido_cred_authdata_len(cred), fido_cred_x5c_ptr(cred), |
323 | fido_cred_x5c_len(cred), fido_cred_sig_ptr(cred), | 324 | fido_cred_x5c_len(cred), fido_cred_sig_ptr(cred), |
diff --git a/examples/extern.h b/examples/extern.h index 578b8c4..0ea68c4 100644 --- a/examples/extern.h +++ b/examples/extern.h | |||
@@ -27,6 +27,7 @@ int write_rsa_pubkey(const char *, const void *, size_t); | |||
27 | int write_eddsa_pubkey(const char *, const void *, size_t); | 27 | int write_eddsa_pubkey(const char *, const void *, size_t); |
28 | #ifdef SIGNAL_EXAMPLE | 28 | #ifdef SIGNAL_EXAMPLE |
29 | void prepare_signal_handler(int); | 29 | void prepare_signal_handler(int); |
30 | extern volatile sig_atomic_t got_signal; | ||
30 | #endif | 31 | #endif |
31 | 32 | ||
32 | #endif /* _EXTERN_H_ */ | 33 | #endif /* _EXTERN_H_ */ |
diff --git a/examples/info.c b/examples/info.c index ef0d97e..d81de85 100644 --- a/examples/info.c +++ b/examples/info.c | |||
@@ -4,17 +4,14 @@ | |||
4 | * license that can be found in the LICENSE file. | 4 | * license that can be found in the LICENSE file. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <openssl/ec.h> | ||
8 | |||
9 | #include <stdbool.h> | 7 | #include <stdbool.h> |
10 | #include <stdint.h> | 8 | #include <stdint.h> |
11 | #include <stdio.h> | 9 | #include <stdio.h> |
12 | #include <stdlib.h> | 10 | #include <stdlib.h> |
13 | #include <string.h> | 11 | #include <string.h> |
14 | 12 | ||
15 | #include "../openbsd-compat/openbsd-compat.h" | ||
16 | |||
17 | #include "fido.h" | 13 | #include "fido.h" |
14 | #include "../openbsd-compat/openbsd-compat.h" | ||
18 | 15 | ||
19 | /* | 16 | /* |
20 | * Pretty-print a device's capabilities flags and return the result. | 17 | * Pretty-print a device's capabilities flags and return the result. |
@@ -131,6 +128,26 @@ print_maxmsgsiz(uint64_t maxmsgsiz) | |||
131 | } | 128 | } |
132 | 129 | ||
133 | /* | 130 | /* |
131 | * Auxiliary function to print an authenticator's maximum number of credentials | ||
132 | * in a credential list on stdout. | ||
133 | */ | ||
134 | static void | ||
135 | print_maxcredcntlst(uint64_t maxcredcntlst) | ||
136 | { | ||
137 | printf("maxcredcntlst: %d\n", (int)maxcredcntlst); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Auxiliary function to print an authenticator's maximum credential ID length | ||
142 | * on stdout. | ||
143 | */ | ||
144 | static void | ||
145 | print_maxcredidlen(uint64_t maxcredidlen) | ||
146 | { | ||
147 | printf("maxcredlen: %d\n", (int)maxcredidlen); | ||
148 | } | ||
149 | |||
150 | /* | ||
134 | * Auxiliary function to print an authenticator's firmware version on stdout. | 151 | * Auxiliary function to print an authenticator's firmware version on stdout. |
135 | */ | 152 | */ |
136 | static void | 153 | static void |
@@ -199,6 +216,12 @@ getinfo(const char *path) | |||
199 | /* print maximum message size */ | 216 | /* print maximum message size */ |
200 | print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci)); | 217 | print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci)); |
201 | 218 | ||
219 | /* print maximum number of credentials allowed in credential lists */ | ||
220 | print_maxcredcntlst(fido_cbor_info_maxcredcntlst(ci)); | ||
221 | |||
222 | /* print maximum length of a credential ID */ | ||
223 | print_maxcredidlen(fido_cbor_info_maxcredidlen(ci)); | ||
224 | |||
202 | /* print firmware version */ | 225 | /* print firmware version */ |
203 | print_fwversion(fido_cbor_info_fwversion(ci)); | 226 | print_fwversion(fido_cbor_info_fwversion(ci)); |
204 | 227 | ||
diff --git a/examples/manifest.c b/examples/manifest.c index 895447a..d5ebda2 100644 --- a/examples/manifest.c +++ b/examples/manifest.c | |||
@@ -4,15 +4,12 @@ | |||
4 | * license that can be found in the LICENSE file. | 4 | * license that can be found in the LICENSE file. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <openssl/ec.h> | ||
8 | |||
9 | #include <stdbool.h> | 7 | #include <stdbool.h> |
10 | #include <stdio.h> | 8 | #include <stdio.h> |
11 | #include <stdlib.h> | 9 | #include <stdlib.h> |
12 | 10 | ||
13 | #include "../openbsd-compat/openbsd-compat.h" | ||
14 | |||
15 | #include "fido.h" | 11 | #include "fido.h" |
12 | #include "../openbsd-compat/openbsd-compat.h" | ||
16 | 13 | ||
17 | int | 14 | int |
18 | main(void) | 15 | main(void) |
diff --git a/examples/reset.c b/examples/reset.c index 36a7de2..3e715c4 100644 --- a/examples/reset.c +++ b/examples/reset.c | |||
@@ -8,21 +8,14 @@ | |||
8 | * Perform a factory reset on a given authenticator. | 8 | * Perform a factory reset on a given authenticator. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <openssl/ec.h> | ||
12 | |||
13 | #include <stdbool.h> | 11 | #include <stdbool.h> |
14 | #include <stdint.h> | 12 | #include <stdint.h> |
15 | #include <stdio.h> | 13 | #include <stdio.h> |
16 | #include <stdlib.h> | 14 | #include <stdlib.h> |
17 | 15 | ||
18 | #include "../openbsd-compat/openbsd-compat.h" | ||
19 | |||
20 | #include "fido.h" | 16 | #include "fido.h" |
21 | #include "extern.h" | 17 | #include "extern.h" |
22 | 18 | #include "../openbsd-compat/openbsd-compat.h" | |
23 | #ifdef SIGNAL_EXAMPLE | ||
24 | extern volatile sig_atomic_t got_signal; | ||
25 | #endif | ||
26 | 19 | ||
27 | int | 20 | int |
28 | main(int argc, char **argv) | 21 | main(int argc, char **argv) |
diff --git a/examples/retries.c b/examples/retries.c index 3ed7558..5cc116c 100644 --- a/examples/retries.c +++ b/examples/retries.c | |||
@@ -8,15 +8,12 @@ | |||
8 | * Get an authenticator's number of PIN attempts left. | 8 | * Get an authenticator's number of PIN attempts left. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <openssl/ec.h> | ||
12 | |||
13 | #include <stdbool.h> | 11 | #include <stdbool.h> |
14 | #include <stdio.h> | 12 | #include <stdio.h> |
15 | #include <stdlib.h> | 13 | #include <stdlib.h> |
16 | 14 | ||
17 | #include "../openbsd-compat/openbsd-compat.h" | ||
18 | |||
19 | #include "fido.h" | 15 | #include "fido.h" |
16 | #include "../openbsd-compat/openbsd-compat.h" | ||
20 | 17 | ||
21 | int | 18 | int |
22 | main(int argc, char **argv) | 19 | main(int argc, char **argv) |
diff --git a/examples/select.c b/examples/select.c new file mode 100644 index 0000000..1fb2960 --- /dev/null +++ b/examples/select.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2020 Yubico AB. All rights reserved. | ||
3 | * Use of this source code is governed by a BSD-style | ||
4 | * license that can be found in the LICENSE file. | ||
5 | */ | ||
6 | |||
7 | #include <errno.h> | ||
8 | #include <stdbool.h> | ||
9 | #include <stdio.h> | ||
10 | #include <stdlib.h> | ||
11 | #include <time.h> | ||
12 | |||
13 | #include "fido.h" | ||
14 | #include "../openbsd-compat/openbsd-compat.h" | ||
15 | |||
16 | #define FIDO_POLL_MS 50 | ||
17 | |||
18 | #if defined(_MSC_VER) | ||
19 | static int | ||
20 | nanosleep(const struct timespec *rqtp, struct timespec *rmtp) | ||
21 | { | ||
22 | if (rmtp != NULL) { | ||
23 | errno = EINVAL; | ||
24 | return (-1); | ||
25 | } | ||
26 | |||
27 | Sleep(rqtp->tv_nsec / 1000000); | ||
28 | |||
29 | return (0); | ||
30 | } | ||
31 | #endif | ||
32 | |||
33 | static fido_dev_t * | ||
34 | open_dev(const fido_dev_info_t *di) | ||
35 | { | ||
36 | fido_dev_t *dev; | ||
37 | int r; | ||
38 | |||
39 | if ((dev = fido_dev_new()) == NULL) { | ||
40 | warnx("%s: fido_dev_new", __func__); | ||
41 | return (NULL); | ||
42 | } | ||
43 | |||
44 | if ((r = fido_dev_open(dev, fido_dev_info_path(di))) != FIDO_OK) { | ||
45 | warnx("%s: fido_dev_open %s: %s", __func__, | ||
46 | fido_dev_info_path(di), fido_strerr(r)); | ||
47 | fido_dev_free(&dev); | ||
48 | return (NULL); | ||
49 | } | ||
50 | |||
51 | printf("%s (0x%04x:0x%04x) is %s\n", fido_dev_info_path(di), | ||
52 | fido_dev_info_vendor(di), fido_dev_info_product(di), | ||
53 | fido_dev_is_fido2(dev) ? "fido2" : "u2f"); | ||
54 | |||
55 | return (dev); | ||
56 | } | ||
57 | |||
58 | static int | ||
59 | select_dev(const fido_dev_info_t *devlist, size_t ndevs, fido_dev_t **dev, | ||
60 | size_t *idx, int secs) | ||
61 | { | ||
62 | const fido_dev_info_t *di; | ||
63 | fido_dev_t **devtab; | ||
64 | struct timespec ts_start; | ||
65 | struct timespec ts_now; | ||
66 | struct timespec ts_delta; | ||
67 | struct timespec ts_pause; | ||
68 | size_t nopen = 0; | ||
69 | int touched; | ||
70 | int r; | ||
71 | long ms_remain; | ||
72 | |||
73 | *dev = NULL; | ||
74 | *idx = 0; | ||
75 | |||
76 | printf("%u authenticator(s) detected\n", (unsigned)ndevs); | ||
77 | |||
78 | if (ndevs == 0) | ||
79 | return (0); /* nothing to do */ | ||
80 | |||
81 | if ((devtab = calloc(ndevs, sizeof(*devtab))) == NULL) { | ||
82 | warn("%s: calloc", __func__); | ||
83 | return (-1); | ||
84 | } | ||
85 | |||
86 | for (size_t i = 0; i < ndevs; i++) { | ||
87 | di = fido_dev_info_ptr(devlist, i); | ||
88 | if ((devtab[i] = open_dev(di)) != NULL) { | ||
89 | *idx = i; | ||
90 | nopen++; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | printf("%u authenticator(s) opened\n", (unsigned)nopen); | ||
95 | |||
96 | if (nopen < 2) { | ||
97 | if (nopen == 1) | ||
98 | *dev = devtab[*idx]; /* single candidate */ | ||
99 | r = 0; | ||
100 | goto out; | ||
101 | } | ||
102 | |||
103 | for (size_t i = 0; i < ndevs; i++) { | ||
104 | di = fido_dev_info_ptr(devlist, i); | ||
105 | if (devtab[i] == NULL) | ||
106 | continue; /* failed to open */ | ||
107 | if ((r = fido_dev_get_touch_begin(devtab[i])) != FIDO_OK) { | ||
108 | warnx("%s: fido_dev_get_touch_begin %s: %s", __func__, | ||
109 | fido_dev_info_path(di), fido_strerr(r)); | ||
110 | r = -1; | ||
111 | goto out; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | if (clock_gettime(CLOCK_MONOTONIC, &ts_start) != 0) { | ||
116 | warn("%s: clock_gettime", __func__); | ||
117 | r = -1; | ||
118 | goto out; | ||
119 | } | ||
120 | |||
121 | ts_pause.tv_sec = 0; | ||
122 | ts_pause.tv_nsec = 200000000; /* 200ms */ | ||
123 | |||
124 | do { | ||
125 | nanosleep(&ts_pause, NULL); | ||
126 | |||
127 | for (size_t i = 0; i < ndevs; i++) { | ||
128 | di = fido_dev_info_ptr(devlist, i); | ||
129 | if (devtab[i] == NULL) { | ||
130 | /* failed to open or discarded */ | ||
131 | continue; | ||
132 | } | ||
133 | if ((r = fido_dev_get_touch_status(devtab[i], &touched, | ||
134 | FIDO_POLL_MS)) != FIDO_OK) { | ||
135 | warnx("%s: fido_dev_get_touch_status %s: %s", | ||
136 | __func__, fido_dev_info_path(di), | ||
137 | fido_strerr(r)); | ||
138 | fido_dev_close(devtab[i]); | ||
139 | fido_dev_free(&devtab[i]); | ||
140 | continue; /* discard */ | ||
141 | } | ||
142 | if (touched) { | ||
143 | *dev = devtab[i]; | ||
144 | *idx = i; | ||
145 | r = 0; | ||
146 | goto out; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | if (clock_gettime(CLOCK_MONOTONIC, &ts_now) != 0) { | ||
151 | warn("%s: clock_gettime", __func__); | ||
152 | r = -1; | ||
153 | goto out; | ||
154 | } | ||
155 | |||
156 | timespecsub(&ts_now, &ts_start, &ts_delta); | ||
157 | ms_remain = (secs * 1000) - ((long)ts_delta.tv_sec * 1000) + | ||
158 | ((long)ts_delta.tv_nsec / 1000000); | ||
159 | } while (ms_remain > FIDO_POLL_MS); | ||
160 | |||
161 | printf("timeout after %d seconds\n", secs); | ||
162 | r = -1; | ||
163 | out: | ||
164 | if (r != 0) { | ||
165 | *dev = NULL; | ||
166 | *idx = 0; | ||
167 | } | ||
168 | |||
169 | for (size_t i = 0; i < ndevs; i++) { | ||
170 | if (devtab[i] && devtab[i] != *dev) { | ||
171 | fido_dev_cancel(devtab[i]); | ||
172 | fido_dev_close(devtab[i]); | ||
173 | fido_dev_free(&devtab[i]); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | free(devtab); | ||
178 | |||
179 | return (r); | ||
180 | } | ||
181 | |||
182 | int | ||
183 | main(void) | ||
184 | { | ||
185 | const fido_dev_info_t *di; | ||
186 | fido_dev_info_t *devlist; | ||
187 | fido_dev_t *dev; | ||
188 | size_t idx; | ||
189 | size_t ndevs; | ||
190 | int r; | ||
191 | |||
192 | fido_init(0); | ||
193 | |||
194 | if ((devlist = fido_dev_info_new(64)) == NULL) | ||
195 | errx(1, "fido_dev_info_new"); | ||
196 | |||
197 | if ((r = fido_dev_info_manifest(devlist, 64, &ndevs)) != FIDO_OK) | ||
198 | errx(1, "fido_dev_info_manifest: %s (0x%x)", fido_strerr(r), r); | ||
199 | if (select_dev(devlist, ndevs, &dev, &idx, 15) != 0) | ||
200 | errx(1, "select_dev"); | ||
201 | if (dev == NULL) | ||
202 | errx(1, "no authenticator found"); | ||
203 | |||
204 | di = fido_dev_info_ptr(devlist, idx); | ||
205 | printf("%s: %s by %s (PIN %sset)\n", fido_dev_info_path(di), | ||
206 | fido_dev_info_product_string(di), | ||
207 | fido_dev_info_manufacturer_string(di), | ||
208 | fido_dev_has_pin(dev) ? "" : "un"); | ||
209 | |||
210 | fido_dev_close(dev); | ||
211 | fido_dev_free(&dev); | ||
212 | fido_dev_info_free(&devlist, ndevs); | ||
213 | |||
214 | exit(0); | ||
215 | } | ||
diff --git a/examples/setpin.c b/examples/setpin.c index 75d3d4a..5413bf9 100644 --- a/examples/setpin.c +++ b/examples/setpin.c | |||
@@ -8,16 +8,13 @@ | |||
8 | * Configure a PIN on a given authenticator. | 8 | * Configure a PIN on a given authenticator. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <openssl/ec.h> | ||
12 | |||
13 | #include <stdbool.h> | 11 | #include <stdbool.h> |
14 | #include <stdint.h> | 12 | #include <stdint.h> |
15 | #include <stdio.h> | 13 | #include <stdio.h> |
16 | #include <stdlib.h> | 14 | #include <stdlib.h> |
17 | 15 | ||
18 | #include "../openbsd-compat/openbsd-compat.h" | ||
19 | |||
20 | #include "fido.h" | 16 | #include "fido.h" |
17 | #include "../openbsd-compat/openbsd-compat.h" | ||
21 | 18 | ||
22 | static void | 19 | static void |
23 | setpin(const char *path, const char *pin, const char *oldpin) | 20 | setpin(const char *path, const char *pin, const char *oldpin) |
diff --git a/examples/util.c b/examples/util.c index 2f6a845..5291cd8 100644 --- a/examples/util.c +++ b/examples/util.c | |||
@@ -27,13 +27,12 @@ | |||
27 | #include "../openbsd-compat/posix_win.h" | 27 | #include "../openbsd-compat/posix_win.h" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #include "../openbsd-compat/openbsd-compat.h" | ||
31 | |||
32 | #include "fido.h" | 30 | #include "fido.h" |
33 | #include "fido/es256.h" | 31 | #include "fido/es256.h" |
34 | #include "fido/rs256.h" | 32 | #include "fido/rs256.h" |
35 | #include "fido/eddsa.h" | 33 | #include "fido/eddsa.h" |
36 | #include "extern.h" | 34 | #include "extern.h" |
35 | #include "../openbsd-compat/openbsd-compat.h" | ||
37 | 36 | ||
38 | #ifdef SIGNAL_EXAMPLE | 37 | #ifdef SIGNAL_EXAMPLE |
39 | volatile sig_atomic_t got_signal = 0; | 38 | volatile sig_atomic_t got_signal = 0; |
diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index 241cdc7..70c5eec 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt | |||
@@ -8,6 +8,7 @@ list(APPEND COMPAT_SOURCES | |||
8 | ) | 8 | ) |
9 | 9 | ||
10 | list(APPEND COMMON_SOURCES | 10 | list(APPEND COMMON_SOURCES |
11 | libfuzzer.c | ||
11 | mutator_aux.c | 12 | mutator_aux.c |
12 | ) | 13 | ) |
13 | 14 | ||
diff --git a/fuzz/Dockerfile b/fuzz/Dockerfile index 68afd99..f9152f8 100644 --- a/fuzz/Dockerfile +++ b/fuzz/Dockerfile | |||
@@ -2,9 +2,10 @@ | |||
2 | # Use of this source code is governed by a BSD-style | 2 | # Use of this source code is governed by a BSD-style |
3 | # license that can be found in the LICENSE file. | 3 | # license that can be found in the LICENSE file. |
4 | 4 | ||
5 | FROM ubuntu:bionic | 5 | FROM ubuntu:focal |
6 | ENV DEBIAN_FRONTEND=noninteractive | ||
6 | RUN apt-get update | 7 | RUN apt-get update |
7 | RUN apt-get install -y clang-9 cmake git libssl-dev libudev-dev make pkg-config | 8 | RUN apt-get install -y clang-10 cmake git libssl-dev libudev-dev make pkg-config |
8 | RUN git clone --branch v0.5.0 https://github.com/PJK/libcbor | 9 | RUN git clone --branch v0.7.0 https://github.com/PJK/libcbor |
9 | RUN git clone https://github.com/yubico/libfido2 | 10 | RUN git clone https://github.com/yubico/libfido2 |
10 | RUN CC=clang-9 /libfido2/fuzz/build-coverage /libcbor /libfido2 | 11 | RUN CC=clang-10 CXX=clang++-10 /libfido2/fuzz/build-coverage /libcbor /libfido2 |
diff --git a/fuzz/Makefile b/fuzz/Makefile index c8fe0b8..77699ac 100644 --- a/fuzz/Makefile +++ b/fuzz/Makefile | |||
@@ -2,10 +2,10 @@ | |||
2 | # Use of this source code is governed by a BSD-style | 2 | # Use of this source code is governed by a BSD-style |
3 | # license that can be found in the LICENSE file. | 3 | # license that can be found in the LICENSE file. |
4 | 4 | ||
5 | IMAGE := libfido2-coverage:1.3.0 | 5 | IMAGE := libfido2-coverage:1.5.0 |
6 | RUNNER := libfido2-runner | 6 | RUNNER := libfido2-runner |
7 | PROFDATA := llvm-profdata-9 | 7 | PROFDATA := llvm-profdata-10 |
8 | COV := llvm-cov-9 | 8 | COV := llvm-cov-10 |
9 | TARGETS := fuzz_assert fuzz_bio fuzz_cred fuzz_credman fuzz_mgmt | 9 | TARGETS := fuzz_assert fuzz_bio fuzz_cred fuzz_credman fuzz_mgmt |
10 | CORPORA := $(foreach f,${TARGETS},${f}/corpus) | 10 | CORPORA := $(foreach f,${TARGETS},${f}/corpus) |
11 | MINIFY := $(foreach f,${TARGETS},/minify/${f}/corpus) | 11 | MINIFY := $(foreach f,${TARGETS},/minify/${f}/corpus) |
@@ -26,16 +26,16 @@ sync: run | |||
26 | docker exec ${RUNNER} make -C libfido2/build | 26 | docker exec ${RUNNER} make -C libfido2/build |
27 | 27 | ||
28 | corpus: sync | 28 | corpus: sync |
29 | docker exec ${RUNNER} /bin/bash -c 'cd /libfido2/fuzz && rm -rf ${TARGETS}' | 29 | docker exec ${RUNNER} /bin/sh -c 'cd /libfido2/fuzz && rm -rf ${TARGETS}' |
30 | docker exec ${RUNNER} tar Czxf /libfido2/fuzz /libfido2/fuzz/corpus.tgz | 30 | docker exec ${RUNNER} tar Czxf /libfido2/fuzz /libfido2/fuzz/corpus.tgz |
31 | 31 | ||
32 | ${TARGETS}: corpus sync | 32 | ${TARGETS}: corpus sync |
33 | docker exec -e LLVM_PROFILE_FILE=/profraw/$@ ${RUNNER} \ | 33 | docker exec -e LLVM_PROFILE_FILE=/profraw/$@ ${RUNNER} \ |
34 | /bin/bash -c 'rm -f /profraw/$@ && /libfido2/build/fuzz/$@ \ | 34 | /bin/sh -c 'rm -f /profraw/$@ && /libfido2/build/fuzz/$@ \ |
35 | -runs=1 /libfido2/fuzz/$@' | 35 | -runs=1 /libfido2/fuzz/$@' |
36 | 36 | ||
37 | ${MINIFY}: /minify/%/corpus: % | 37 | ${MINIFY}: /minify/%/corpus: % |
38 | docker exec ${RUNNER} /bin/bash -c 'rm -rf $@ && mkdir -p $@ && \ | 38 | docker exec ${RUNNER} /bin/sh -c 'rm -rf $@ && mkdir -p $@ && \ |
39 | /libfido2/build/fuzz/$< -use_value_profile=1 -merge=1 $@ \ | 39 | /libfido2/build/fuzz/$< -use_value_profile=1 -merge=1 $@ \ |
40 | /libfido2/fuzz/$</corpus' | 40 | /libfido2/fuzz/$</corpus' |
41 | 41 | ||
@@ -43,11 +43,11 @@ corpus.tgz-: ${MINIFY} | |||
43 | docker exec -i ${RUNNER} tar Czcf /minify - ${TARGETS} > $@ | 43 | docker exec -i ${RUNNER} tar Czcf /minify - ${TARGETS} > $@ |
44 | 44 | ||
45 | profdata: run | 45 | profdata: run |
46 | docker exec ${RUNNER} /bin/bash -c 'rm -f /$@ && ${PROFDATA} \ | 46 | docker exec ${RUNNER} /bin/sh -c 'rm -f /$@ && ${PROFDATA} \ |
47 | merge -sparse profraw/* -o $@' | 47 | merge -sparse profraw/* -o $@' |
48 | 48 | ||
49 | report.tgz: profdata | 49 | report.tgz: profdata |
50 | docker exec ${RUNNER} /bin/bash -c 'rm -rf /report && mkdir /report && \ | 50 | docker exec ${RUNNER} /bin/sh -c 'rm -rf /report && mkdir /report && \ |
51 | ${COV} show -format=html -tab-size=8 -instr-profile=/$< \ | 51 | ${COV} show -format=html -tab-size=8 -instr-profile=/$< \ |
52 | -output-dir=/report /libfido2/build/src/libfido2.so' | 52 | -output-dir=/report /libfido2/build/src/libfido2.so' |
53 | docker exec -i ${RUNNER} tar Czcf / - report > $@ | 53 | docker exec -i ${RUNNER} tar Czcf / - report > $@ |
@@ -57,12 +57,12 @@ summary.txt: profdata | |||
57 | /libfido2/build/src/libfido2.so -instr-profile=/$< > $@ | 57 | /libfido2/build/src/libfido2.so -instr-profile=/$< > $@ |
58 | 58 | ||
59 | functions.txt: profdata | 59 | functions.txt: profdata |
60 | docker exec ${RUNNER} /bin/bash -c '${COV} report -use-color=false \ | 60 | docker exec ${RUNNER} /bin/sh -c '${COV} report -use-color=false \ |
61 | -show-functions -instr-profile=/$< \ | 61 | -show-functions -instr-profile=/$< \ |
62 | /libfido2/build/src/libfido2.so /libfido2/src/*.[ch]' > $@ | 62 | /libfido2/build/src/libfido2.so /libfido2/src/*.[ch]' > $@ |
63 | 63 | ||
64 | clean: run | 64 | clean: run |
65 | docker exec ${RUNNER} /bin/bash -c 'rm -rf /profraw /profdata && \ | 65 | docker exec ${RUNNER} /bin/sh -c 'rm -rf /profraw /profdata && \ |
66 | make -C /libfido2/build clean' | 66 | make -C /libfido2/build clean' |
67 | -docker stop ${RUNNER} | 67 | -docker stop ${RUNNER} |
68 | rm -rf ${TARGETS} | 68 | rm -rf ${TARGETS} |
diff --git a/fuzz/README b/fuzz/README index 42646e4..03de9d0 100644 --- a/fuzz/README +++ b/fuzz/README | |||
@@ -3,10 +3,8 @@ ASAN/MSAN/UBSAN. | |||
3 | 3 | ||
4 | AFL is more convenient when fuzzing the path from the authenticator to | 4 | AFL is more convenient when fuzzing the path from the authenticator to |
5 | libfido2 in an existing application. To do so, use preload-snoop.c with a real | 5 | libfido2 in an existing application. To do so, use preload-snoop.c with a real |
6 | authenticator to obtain an initial corpus, rebuild libfido2 with -DFUZZ=1 | 6 | authenticator to obtain an initial corpus, rebuild libfido2 with -DFUZZ=1, and |
7 | -DAFL=1, and use preload-fuzz.c to read device data from stdin. Examples of | 7 | use preload-fuzz.c to read device data from stdin. |
8 | this approach can be found in the harnesses under fuzz/harnesses/ that fuzz | ||
9 | the standalone examples and tools bundled with libfido2. | ||
10 | 8 | ||
11 | libFuzzer is better suited for bespoke fuzzers; see fuzz_cred.c, fuzz_credman.c, | 9 | libFuzzer is better suited for bespoke fuzzers; see fuzz_cred.c, fuzz_credman.c, |
12 | fuzz_assert.c, and fuzz_mgmt.c for examples. To build these harnesses, | 10 | fuzz_assert.c, and fuzz_mgmt.c for examples. To build these harnesses, |
@@ -15,129 +13,7 @@ use -DFUZZ=1 -DLIBFUZZER=1. | |||
15 | To run under ASAN/MSAN/UBSAN, libfido2 needs to be linked against flavours of | 13 | To run under ASAN/MSAN/UBSAN, libfido2 needs to be linked against flavours of |
16 | libcbor and OpenSSL built with the respective sanitiser. In order to keep | 14 | libcbor and OpenSSL built with the respective sanitiser. In order to keep |
17 | memory utilisation at a manageable level, you can either enforce limits at | 15 | memory utilisation at a manageable level, you can either enforce limits at |
18 | the OS level (e.g. cgroups on Linux) or, alternatively, patch libcbor with | 16 | the OS level (e.g. cgroups on Linux), or patch libcbor with the diff below. |
19 | the diff at the bottom of this file. | ||
20 | |||
21 | 1. Using ASAN + UBSAN | ||
22 | |||
23 | - Make sure you have libcbor built with -fsanitize=address; | ||
24 | - Make sure you have OpenSSL built with -fsanitize=address; | ||
25 | - Rebuild libfido2 with -DASAN=1 -DUBSAN=1. | ||
26 | |||
27 | 1.1 Decide where your workspace will live | ||
28 | |||
29 | $ export FAKEROOT=/home/pedro/fakeroot | ||
30 | $ mkdir -p ${FAKEROOT}/src | ||
31 | |||
32 | 1.2 Building libcbor with ASAN | ||
33 | |||
34 | $ git clone https://github.com/pjk/libcbor ${FAKEROOT}/src/libcbor | ||
35 | $ cd ${FAKEROOT}/src/libcbor | ||
36 | |||
37 | Assuming libfido2 is under ${FAKEROOT}/src/libfido2: | ||
38 | |||
39 | $ patch -p0 < ${FAKEROOT}/src/libfido2/fuzz/README | ||
40 | $ mkdir build | ||
41 | $ cd build | ||
42 | $ cmake -DCMAKE_C_FLAGS_DEBUG="-g2 -fno-omit-frame-pointer" \ | ||
43 | -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug \ | ||
44 | -DCMAKE_INSTALL_PREFIX=${FAKEROOT} -DSANITIZE=ON \ | ||
45 | -DCMAKE_INSTALL_LIBDIR=lib .. | ||
46 | $ make | ||
47 | $ make install | ||
48 | |||
49 | 1.3 Building OpenSSL with ASAN | ||
50 | |||
51 | $ git clone https://github.com/openssl/openssl ${FAKEROOT}/src/openssl | ||
52 | $ cd ${FAKEROOT}/src/openssl | ||
53 | $ ./Configure linux-x86_64-clang enable-asan --prefix=${FAKEROOT} \ | ||
54 | --openssldir=${FAKEROOT}/openssl | ||
55 | $ make clean | ||
56 | $ make | ||
57 | $ make install_sw | ||
58 | |||
59 | 1.4 Building libfido2 with libFuzzer and ASAN + UBSAN | ||
60 | |||
61 | $ cd ${FAKEROOT}/src/libfido2 | ||
62 | $ mkdir build | ||
63 | $ cd build | ||
64 | $ cmake -DFUZZ=1 -DLIBFUZZER=1 -DASAN=1 -DUBSAN=1 -DCMAKE_C_COMPILER=clang \ | ||
65 | -DCRYPTO_INCLUDE_DIRS=${FAKEROOT}/include \ | ||
66 | -DCRYPTO_LIBRARY_DIRS=${FAKEROOT}/lib \ | ||
67 | -DCBOR_INCLUDE_DIRS=${FAKEROOT}/include \ | ||
68 | -DCBOR_LIBRARY_DIRS=${FAKEROOT}/lib \ | ||
69 | -DCMAKE_BUILD_TYPE=Debug .. | ||
70 | $ make | ||
71 | |||
72 | 2. Using MSAN + UBSAN | ||
73 | |||
74 | - Make sure you have libcbor built with -fsanitize=memory; | ||
75 | - Make sure you have OpenSSL built with -fsanitize=memory; | ||
76 | - Rebuild libfido2 with -DMSAN=1 -DUBSAN=1. | ||
77 | |||
78 | 2.1 Decide where your workspace will live | ||
79 | |||
80 | $ export FAKEROOT=/home/pedro/fakeroot | ||
81 | $ mkdir -p ${FAKEROOT}/src | ||
82 | |||
83 | 2.2 Building libcbor with MSAN | ||
84 | |||
85 | $ git clone https://github.com/pjk/libcbor ${FAKEROOT}/src/libcbor | ||
86 | $ cd ${FAKEROOT}/src/libcbor | ||
87 | |||
88 | Assuming libfido2 is under ${FAKEROOT}/src/libfido2: | ||
89 | |||
90 | $ patch -p0 < ${FAKEROOT}/src/libfido2/fuzz/README | ||
91 | $ mkdir build | ||
92 | $ cd build | ||
93 | $ cmake -DCMAKE_C_FLAGS_DEBUG="-fsanitize=memory,undefined -g2 -fno-omit-frame-pointer" \ | ||
94 | -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug \ | ||
95 | -DCMAKE_INSTALL_PREFIX=${FAKEROOT} -DSANITIZE=OFF \ | ||
96 | -DCMAKE_INSTALL_LIBDIR=lib .. | ||
97 | $ make | ||
98 | $ make install | ||
99 | |||
100 | 2.2 Building OpenSSL with MSAN | ||
101 | |||
102 | $ mkdir -p ${FAKEROOT}/src | ||
103 | $ git clone https://github.com/openssl/openssl ${FAKEROOT}/src/openssl | ||
104 | $ cd ${FAKEROOT}/src/openssl | ||
105 | $ ./Configure linux-x86_64-clang enable-msan --prefix=${FAKEROOT} \ | ||
106 | --openssldir=${FAKEROOT}/openssl | ||
107 | $ make clean | ||
108 | $ make | ||
109 | $ make install_sw | ||
110 | |||
111 | 2.3 Building libfido2 with libFuzzer and MSAN + UBSAN | ||
112 | |||
113 | $ cd ${FAKEROOT}/src/libfido2 | ||
114 | $ mkdir build | ||
115 | $ cd build | ||
116 | $ cmake -DFUZZ=1 -DLIBFUZZER=1 -DMSAN=1 -DUBSAN=1 -DCMAKE_C_COMPILER=clang \ | ||
117 | -DCRYPTO_INCLUDE_DIRS=${FAKEROOT}/include \ | ||
118 | -DCRYPTO_LIBRARY_DIRS=${FAKEROOT}/lib \ | ||
119 | -DCBOR_INCLUDE_DIRS=${FAKEROOT}/include \ | ||
120 | -DCBOR_LIBRARY_DIRS=${FAKEROOT}/lib \ | ||
121 | -DCMAKE_BUILD_TYPE=Debug .. | ||
122 | $ make | ||
123 | |||
124 | 3. Running the libFuzzer harnesses | ||
125 | |||
126 | When running under ASAN, you may want to set ASAN_OPTIONS to | ||
127 | 'allocator_may_return_null=1:detect_stack_use_after_return=1'. | ||
128 | |||
129 | The recommended way to run the harnesses is: | ||
130 | |||
131 | $ fuzz_{assert,cred,credman,mgmt} -use_value_profile=1 -reload=30 \ | ||
132 | -print_pcs=1 -print_funcs=30 -timeout=10 CORPUS_DIR | ||
133 | |||
134 | You may want to use -jobs or -workers depending on the number of logical | ||
135 | cores available for fuzzing. | ||
136 | |||
137 | 4. Auxiliary scripts | ||
138 | |||
139 | A set of harnesses and auxiliary scripts can be found under harnesses/. To | ||
140 | compile coverage reports, adjust the harnesses to your setup and run 'report'. | ||
141 | 17 | ||
142 | diff --git src/cbor/internal/memory_utils.c src/cbor/internal/memory_utils.c | 18 | diff --git src/cbor/internal/memory_utils.c src/cbor/internal/memory_utils.c |
143 | index aa049a2..e294b38 100644 | 19 | index aa049a2..e294b38 100644 |
diff --git a/fuzz/build-coverage b/fuzz/build-coverage index af9f8df..0f8310d 100755 --- a/fuzz/build-coverage +++ b/fuzz/build-coverage | |||
@@ -1,27 +1,30 @@ | |||
1 | #!/bin/bash -eux | 1 | #!/bin/sh -eux |
2 | # | 2 | |
3 | # Copyright (c) 2019 Yubico AB. All rights reserved. | 3 | # Copyright (c) 2019 Yubico AB. All rights reserved. |
4 | # Use of this source code is governed by a BSD-style | 4 | # Use of this source code is governed by a BSD-style |
5 | # license that can be found in the LICENSE file. | 5 | # license that can be found in the LICENSE file. |
6 | 6 | ||
7 | LIBCBOR=$1 | 7 | LIBCBOR="$1" |
8 | LIBFIDO2=$2 | 8 | LIBFIDO2="$2" |
9 | 9 | ||
10 | CC=${CC:-clang} | 10 | CC="${CC:-clang}" |
11 | PKG_CONFIG_PATH=${PKG_CONFIG_PATH:-${LIBCBOR}/install/lib/pkgconfig} | 11 | CXX="${CXX:-clang++}" |
12 | PKG_CONFIG_PATH="${PKG_CONFIG_PATH:-${LIBCBOR}/install/lib/pkgconfig}" | ||
12 | export CC PKG_CONFIG_PATH | 13 | export CC PKG_CONFIG_PATH |
13 | 14 | ||
14 | # Clean up. | 15 | # Clean up. |
15 | rm -rf ${LIBCBOR}/build ${LIBCBOR}/install ${LIBFIDO2}/build | 16 | rm -rf "${LIBCBOR}/build" "${LIBCBOR}/install" "${LIBFIDO2}/build" |
16 | 17 | ||
17 | # Patch, build, and install libcbor. | 18 | # Patch, build, and install libcbor. |
18 | (cd ${LIBCBOR} && patch -N -l -s -p0 < ${LIBFIDO2}/fuzz/README) || true | 19 | (cd "${LIBCBOR}" && patch -N -l -s -p0 < "${LIBFIDO2}/fuzz/README") || true |
19 | mkdir ${LIBCBOR}/build ${LIBCBOR}/install | 20 | mkdir "${LIBCBOR}/build" "${LIBCBOR}/install" |
20 | (cd ${LIBCBOR}/build && cmake -DCMAKE_INSTALL_PREFIX=${LIBCBOR}/install ..) | 21 | (cd "${LIBCBOR}/build" && cmake -DCMAKE_INSTALL_PREFIX="${LIBCBOR}/install" ..) |
21 | make -C ${LIBCBOR}/build all install | 22 | make -C "${LIBCBOR}/build" all install |
22 | 23 | ||
23 | # Build libfido2. | 24 | # Build libfido2. |
24 | mkdir -p ${LIBFIDO2}/build | 25 | mkdir -p "${LIBFIDO2}/build" |
25 | (cd ${LIBFIDO2}/build && cmake -DFUZZ=1 -DLIBFUZZER=1 -DCOVERAGE=1 \ | 26 | export CFLAGS="-fprofile-instr-generate -fcoverage-mapping" |
26 | -DCMAKE_BUILD_TYPE=Debug ..) | 27 | export LDFLAGS="${CFLAGS}" |
27 | make -C ${LIBFIDO2}/build | 28 | (cd "${LIBFIDO2}/build" && cmake -DFUZZ=1 -DLIBFUZZER=1 \ |
29 | -DCMAKE_BUILD_TYPE=Debug ..) | ||
30 | make -C "${LIBFIDO2}/build" | ||
diff --git a/fuzz/dummy.h b/fuzz/dummy.h index a899e4a..981ccee 100644 --- a/fuzz/dummy.h +++ b/fuzz/dummy.h | |||
@@ -10,6 +10,8 @@ | |||
10 | #include <stdint.h> | 10 | #include <stdint.h> |
11 | 11 | ||
12 | const char dummy_name[] = "finger1"; | 12 | const char dummy_name[] = "finger1"; |
13 | const char dummy_pin1[] = "skepp cg0u3;Y.."; | ||
14 | const char dummy_pin2[] = "bastilha 6rJrfQZI."; | ||
13 | const char dummy_pin[] = "9}4gT:8d=A37Dh}U"; | 15 | const char dummy_pin[] = "9}4gT:8d=A37Dh}U"; |
14 | const char dummy_rp_id[] = "localhost"; | 16 | const char dummy_rp_id[] = "localhost"; |
15 | const char dummy_rp_name[] = "sweet home localhost"; | 17 | const char dummy_rp_name[] = "sweet home localhost"; |
@@ -17,8 +19,6 @@ const char dummy_user_icon[] = "an icon"; | |||
17 | const char dummy_user_name[] = "john smith"; | 19 | const char dummy_user_name[] = "john smith"; |
18 | const char dummy_user_nick[] = "jsmith"; | 20 | const char dummy_user_nick[] = "jsmith"; |
19 | const uint8_t dummy_id[] = { 0x5e, 0xd2 }; | 21 | const uint8_t dummy_id[] = { 0x5e, 0xd2 }; |
20 | const char dummy_pin1[] = "skepp cg0u3;Y.."; | ||
21 | const char dummy_pin2[] = "bastilha 6rJrfQZI."; | ||
22 | 22 | ||
23 | const uint8_t dummy_user_id[] = { | 23 | const uint8_t dummy_user_id[] = { |
24 | 0x78, 0x1c, 0x78, 0x60, 0xad, 0x88, 0xd2, 0x63, | 24 | 0x78, 0x1c, 0x78, 0x60, 0xad, 0x88, 0xd2, 0x63, |
diff --git a/fuzz/export.gnu b/fuzz/export.gnu index 68463ff..80941e4 100644 --- a/fuzz/export.gnu +++ b/fuzz/export.gnu | |||
@@ -76,6 +76,8 @@ | |||
76 | fido_cbor_info_extensions_ptr; | 76 | fido_cbor_info_extensions_ptr; |
77 | fido_cbor_info_free; | 77 | fido_cbor_info_free; |
78 | fido_cbor_info_maxmsgsiz; | 78 | fido_cbor_info_maxmsgsiz; |
79 | fido_cbor_info_maxcredcntlst; | ||
80 | fido_cbor_info_maxcredidlen; | ||
79 | fido_cbor_info_fwversion; | 81 | fido_cbor_info_fwversion; |
80 | fido_cbor_info_new; | 82 | fido_cbor_info_new; |
81 | fido_cbor_info_options_len; | 83 | fido_cbor_info_options_len; |
@@ -96,6 +98,8 @@ | |||
96 | fido_cred_free; | 98 | fido_cred_free; |
97 | fido_cred_id_len; | 99 | fido_cred_id_len; |
98 | fido_cred_id_ptr; | 100 | fido_cred_id_ptr; |
101 | fido_cred_aaguid_len; | ||
102 | fido_cred_aaguid_ptr; | ||
99 | fido_credman_del_dev_rk; | 103 | fido_credman_del_dev_rk; |
100 | fido_credman_get_dev_metadata; | 104 | fido_credman_get_dev_metadata; |
101 | fido_credman_get_dev_rk; | 105 | fido_credman_get_dev_rk; |
@@ -155,6 +159,9 @@ | |||
155 | fido_dev_get_assert; | 159 | fido_dev_get_assert; |
156 | fido_dev_get_cbor_info; | 160 | fido_dev_get_cbor_info; |
157 | fido_dev_get_retry_count; | 161 | fido_dev_get_retry_count; |
162 | fido_dev_get_touch_begin; | ||
163 | fido_dev_get_touch_status; | ||
164 | fido_dev_has_pin; | ||
158 | fido_dev_info_free; | 165 | fido_dev_info_free; |
159 | fido_dev_info_manifest; | 166 | fido_dev_info_manifest; |
160 | fido_dev_info_manufacturer_string; | 167 | fido_dev_info_manufacturer_string; |
@@ -174,6 +181,9 @@ | |||
174 | fido_dev_reset; | 181 | fido_dev_reset; |
175 | fido_dev_set_io_functions; | 182 | fido_dev_set_io_functions; |
176 | fido_dev_set_pin; | 183 | fido_dev_set_pin; |
184 | fido_dev_set_transport_functions; | ||
185 | fido_dev_supports_cred_prot; | ||
186 | fido_dev_supports_pin; | ||
177 | fido_init; | 187 | fido_init; |
178 | fido_set_log_handler; | 188 | fido_set_log_handler; |
179 | fido_strerr; | 189 | fido_strerr; |
diff --git a/fuzz/functions.txt b/fuzz/functions.txt index 27a9608..90284dd 100644 --- a/fuzz/functions.txt +++ b/fuzz/functions.txt | |||
@@ -9,16 +9,16 @@ TOTAL 56 0 100.00% 82 0 100.00% | |||
9 | File '/libfido2/src/assert.c': | 9 | File '/libfido2/src/assert.c': |
10 | Name Regions Miss Cover Lines Miss Cover | 10 | Name Regions Miss Cover Lines Miss Cover |
11 | --------------------------------------------------------------------------------------- | 11 | --------------------------------------------------------------------------------------- |
12 | fido_dev_get_assert 35 3 91.43% 38 4 89.47% | 12 | fido_dev_get_assert 35 0 100.00% 38 0 100.00% |
13 | fido_check_flags 13 0 100.00% 18 0 100.00% | 13 | fido_check_flags 13 0 100.00% 18 0 100.00% |
14 | fido_get_signed_hash 32 0 100.00% 46 0 100.00% | 14 | fido_get_signed_hash 32 0 100.00% 46 0 100.00% |
15 | fido_verify_sig_es256 17 2 88.24% 31 7 77.42% | 15 | fido_verify_sig_es256 17 2 88.24% 31 7 77.42% |
16 | fido_verify_sig_rs256 17 2 88.24% 31 7 77.42% | 16 | fido_verify_sig_rs256 17 2 88.24% 31 7 77.42% |
17 | fido_verify_sig_eddsa 23 4 82.61% 43 13 69.77% | 17 | fido_verify_sig_eddsa 23 2 91.30% 43 7 83.72% |
18 | fido_assert_verify 48 4 91.67% 79 4 94.94% | 18 | fido_assert_verify 48 4 91.67% 79 5 93.67% |
19 | fido_assert_set_clientdata_hash 6 0 100.00% 6 0 100.00% | 19 | fido_assert_set_clientdata_hash 6 0 100.00% 6 0 100.00% |
20 | fido_assert_set_hmac_salt 10 0 100.00% 7 0 100.00% | 20 | fido_assert_set_hmac_salt 10 0 100.00% 7 0 100.00% |
21 | fido_assert_set_rp 12 1 91.67% 14 3 78.57% | 21 | fido_assert_set_rp 12 0 100.00% 14 0 100.00% |
22 | fido_assert_allow_cred 13 2 84.62% 29 3 89.66% | 22 | fido_assert_allow_cred 13 2 84.62% 29 3 89.66% |
23 | fido_assert_set_extensions 9 0 100.00% 8 0 100.00% | 23 | fido_assert_set_extensions 9 0 100.00% 8 0 100.00% |
24 | fido_assert_set_options 6 6 0.00% 6 6 0.00% | 24 | fido_assert_set_options 6 6 0.00% 6 6 0.00% |
@@ -28,7 +28,7 @@ fido_assert_clientdata_hash_ptr 1 0 100.00% 3 0 | |||
28 | fido_assert_clientdata_hash_len 1 0 100.00% 3 0 100.00% | 28 | fido_assert_clientdata_hash_len 1 0 100.00% 3 0 100.00% |
29 | fido_assert_new 1 0 100.00% 3 0 100.00% | 29 | fido_assert_new 1 0 100.00% 3 0 100.00% |
30 | fido_assert_reset_tx 1 0 100.00% 15 0 100.00% | 30 | fido_assert_reset_tx 1 0 100.00% 15 0 100.00% |
31 | fido_assert_reset_rx 6 1 83.33% 24 3 87.50% | 31 | fido_assert_reset_rx 6 0 100.00% 24 0 100.00% |
32 | fido_assert_free 6 0 100.00% 13 0 100.00% | 32 | fido_assert_free 6 0 100.00% 13 0 100.00% |
33 | fido_assert_count 1 0 100.00% 3 0 100.00% | 33 | fido_assert_count 1 0 100.00% 3 0 100.00% |
34 | fido_assert_rp_id 1 0 100.00% 3 0 100.00% | 34 | fido_assert_rp_id 1 0 100.00% 3 0 100.00% |
@@ -48,22 +48,22 @@ fido_assert_user_display_name 4 0 100.00% 6 0 | |||
48 | fido_assert_hmac_secret_ptr 4 0 100.00% 6 0 100.00% | 48 | fido_assert_hmac_secret_ptr 4 0 100.00% 6 0 100.00% |
49 | fido_assert_hmac_secret_len 4 0 100.00% 6 0 100.00% | 49 | fido_assert_hmac_secret_len 4 0 100.00% 6 0 100.00% |
50 | fido_assert_set_authdata 24 0 100.00% 35 0 100.00% | 50 | fido_assert_set_authdata 24 0 100.00% 35 0 100.00% |
51 | fido_assert_set_authdata_raw 24 4 83.33% 34 7 79.41% | 51 | fido_assert_set_authdata_raw 24 0 100.00% 34 0 100.00% |
52 | fido_assert_set_sig 14 0 100.00% 17 0 100.00% | 52 | fido_assert_set_sig 14 0 100.00% 17 0 100.00% |
53 | fido_assert_set_count 10 0 100.00% 21 0 100.00% | 53 | fido_assert_set_count 10 0 100.00% 21 0 100.00% |
54 | assert.c:fido_dev_get_assert_wait 21 1 95.24% 16 2 87.50% | 54 | assert.c:fido_dev_get_assert_wait 21 0 100.00% 16 0 100.00% |
55 | assert.c:fido_dev_get_assert_tx 58 4 93.10% 84 11 86.90% | 55 | assert.c:fido_dev_get_assert_tx 58 4 93.10% 84 11 86.90% |
56 | assert.c:fido_dev_get_assert_rx 19 0 100.00% 38 0 100.00% | 56 | assert.c:fido_dev_get_assert_rx 19 0 100.00% 38 0 100.00% |
57 | assert.c:adjust_assert_count 24 0 100.00% 33 0 100.00% | 57 | assert.c:adjust_assert_count 24 0 100.00% 33 0 100.00% |
58 | assert.c:parse_assert_reply 11 0 100.00% 25 0 100.00% | 58 | assert.c:parse_assert_reply 11 0 100.00% 25 0 100.00% |
59 | assert.c:fido_get_next_assert_tx 8 2 75.00% 10 3 70.00% | 59 | assert.c:fido_get_next_assert_tx 8 0 100.00% 10 0 100.00% |
60 | assert.c:fido_get_next_assert_rx 15 4 73.33% 26 7 73.08% | 60 | assert.c:fido_get_next_assert_rx 15 2 86.67% 26 4 84.62% |
61 | assert.c:decrypt_hmac_secrets 9 3 66.67% 15 7 53.33% | 61 | assert.c:decrypt_hmac_secrets 9 0 100.00% 15 0 100.00% |
62 | assert.c:check_extensions 4 0 100.00% 9 0 100.00% | 62 | assert.c:check_extensions 4 0 100.00% 9 0 100.00% |
63 | assert.c:fido_assert_clean_authdata 1 0 100.00% 9 0 100.00% | 63 | assert.c:fido_assert_clean_authdata 1 0 100.00% 9 0 100.00% |
64 | assert.c:fido_assert_clean_sig 1 0 100.00% 5 0 100.00% | 64 | assert.c:fido_assert_clean_sig 1 0 100.00% 5 0 100.00% |
65 | --------------------------------------------------------------------------------------- | 65 | --------------------------------------------------------------------------------------- |
66 | TOTAL 566 43 92.40% 900 87 90.33% | 66 | TOTAL 566 24 95.76% 900 50 94.44% |
67 | 67 | ||
68 | File '/libfido2/src/authkey.c': | 68 | File '/libfido2/src/authkey.c': |
69 | Name Regions Miss Cover Lines Miss Cover | 69 | Name Regions Miss Cover Lines Miss Cover |
@@ -135,14 +135,14 @@ File '/libfido2/src/blob.c': | |||
135 | Name Regions Miss Cover Lines Miss Cover | 135 | Name Regions Miss Cover Lines Miss Cover |
136 | --------------------------------------------------------------------------------------- | 136 | --------------------------------------------------------------------------------------- |
137 | fido_blob_new 1 0 100.00% 3 0 100.00% | 137 | fido_blob_new 1 0 100.00% 3 0 100.00% |
138 | fido_blob_set 11 1 90.91% 25 4 84.00% | 138 | fido_blob_set 11 0 100.00% 25 0 100.00% |
139 | fido_blob_free 8 0 100.00% 16 0 100.00% | 139 | fido_blob_free 8 0 100.00% 16 0 100.00% |
140 | fido_free_blob_array 9 0 100.00% 17 0 100.00% | 140 | fido_free_blob_array 9 0 100.00% 17 0 100.00% |
141 | fido_blob_encode 6 0 100.00% 6 0 100.00% | 141 | fido_blob_encode 6 0 100.00% 6 0 100.00% |
142 | fido_blob_decode 1 0 100.00% 3 0 100.00% | 142 | fido_blob_decode 1 0 100.00% 3 0 100.00% |
143 | fido_blob_is_empty 3 0 100.00% 3 0 100.00% | 143 | fido_blob_is_empty 3 0 100.00% 3 0 100.00% |
144 | --------------------------------------------------------------------------------------- | 144 | --------------------------------------------------------------------------------------- |
145 | TOTAL 39 1 97.44% 73 4 94.52% | 145 | TOTAL 39 0 100.00% 73 0 100.00% |
146 | 146 | ||
147 | File '/libfido2/src/buf.c': | 147 | File '/libfido2/src/buf.c': |
148 | Name Regions Miss Cover Lines Miss Cover | 148 | Name Regions Miss Cover Lines Miss Cover |
@@ -155,7 +155,7 @@ TOTAL 8 1 87.50% 20 1 | |||
155 | File '/libfido2/src/cbor.c': | 155 | File '/libfido2/src/cbor.c': |
156 | Name Regions Miss Cover Lines Miss Cover | 156 | Name Regions Miss Cover Lines Miss Cover |
157 | --------------------------------------------------------------------------------------- | 157 | --------------------------------------------------------------------------------------- |
158 | cbor_map_iter 20 0 100.00% 30 0 100.00% | 158 | cbor_map_iter 20 1 95.00% 30 4 86.67% |
159 | cbor_array_iter 12 0 100.00% 20 0 100.00% | 159 | cbor_array_iter 12 0 100.00% 20 0 100.00% |
160 | cbor_parse_reply 27 0 100.00% 43 0 100.00% | 160 | cbor_parse_reply 27 0 100.00% 43 0 100.00% |
161 | cbor_vector_free 6 0 100.00% 5 0 100.00% | 161 | cbor_vector_free 6 0 100.00% 5 0 100.00% |
@@ -168,23 +168,23 @@ cbor_flatten_vector 14 1 92.86% 21 1 | |||
168 | cbor_build_frame 15 0 100.00% 32 0 100.00% | 168 | cbor_build_frame 15 0 100.00% 32 0 100.00% |
169 | cbor_encode_rp_entity 13 0 100.00% 14 0 100.00% | 169 | cbor_encode_rp_entity 13 0 100.00% 14 0 100.00% |
170 | cbor_encode_user_entity 21 0 100.00% 18 0 100.00% | 170 | cbor_encode_user_entity 21 0 100.00% 18 0 100.00% |
171 | cbor_encode_pubkey_param 36 1 97.22% 48 0 100.00% | 171 | cbor_encode_pubkey_param 36 0 100.00% 48 0 100.00% |
172 | cbor_encode_pubkey 10 0 100.00% 13 0 100.00% | 172 | cbor_encode_pubkey 10 0 100.00% 13 0 100.00% |
173 | cbor_encode_pubkey_list 18 1 94.44% 23 0 100.00% | 173 | cbor_encode_pubkey_list 18 0 100.00% 23 0 100.00% |
174 | cbor_encode_extensions 24 2 91.67% 26 3 88.46% | 174 | cbor_encode_extensions 28 0 100.00% 28 0 100.00% |
175 | cbor_encode_options 13 0 100.00% 14 0 100.00% | 175 | cbor_encode_options 13 0 100.00% 14 0 100.00% |
176 | cbor_encode_assert_options 13 0 100.00% 14 0 100.00% | 176 | cbor_encode_assert_options 13 0 100.00% 14 0 100.00% |
177 | cbor_encode_pin_auth 8 0 100.00% 12 0 100.00% | 177 | cbor_encode_pin_auth 8 0 100.00% 12 0 100.00% |
178 | cbor_encode_pin_opt 1 0 100.00% 3 0 100.00% | 178 | cbor_encode_pin_opt 1 0 100.00% 3 0 100.00% |
179 | cbor_encode_pin_enc 4 0 100.00% 12 0 100.00% | 179 | cbor_encode_pin_enc 4 0 100.00% 12 0 100.00% |
180 | cbor_encode_change_pin_auth 44 1 97.73% 69 3 95.65% | 180 | cbor_encode_change_pin_auth 39 0 100.00% 60 0 100.00% |
181 | cbor_encode_set_pin_auth 17 0 100.00% 28 0 100.00% | 181 | cbor_encode_set_pin_auth 17 0 100.00% 28 0 100.00% |
182 | cbor_encode_pin_hash_enc 15 0 100.00% 27 0 100.00% | 182 | cbor_encode_pin_hash_enc 15 0 100.00% 27 0 100.00% |
183 | cbor_encode_hmac_secret_param 41 2 95.12% 66 9 86.36% | 183 | cbor_encode_hmac_secret_param 41 1 97.56% 66 4 93.94% |
184 | cbor_decode_fmt 9 0 100.00% 18 0 100.00% | 184 | cbor_decode_fmt 9 0 100.00% 18 0 100.00% |
185 | cbor_decode_pubkey 21 6 71.43% 32 7 78.12% | 185 | cbor_decode_pubkey 21 1 95.24% 32 2 93.75% |
186 | cbor_decode_cred_authdata 31 0 100.00% 47 0 100.00% | 186 | cbor_decode_cred_authdata 31 0 100.00% 47 0 100.00% |
187 | cbor_decode_assert_authdata 23 2 91.30% 44 2 95.45% | 187 | cbor_decode_assert_authdata 23 0 100.00% 44 0 100.00% |
188 | cbor_decode_attstmt 8 0 100.00% 10 0 100.00% | 188 | cbor_decode_attstmt 8 0 100.00% 10 0 100.00% |
189 | cbor_decode_uint64 4 0 100.00% 10 0 100.00% | 189 | cbor_decode_uint64 4 0 100.00% 10 0 100.00% |
190 | cbor_decode_cred_id 8 0 100.00% 10 0 100.00% | 190 | cbor_decode_cred_id 8 0 100.00% 10 0 100.00% |
@@ -193,30 +193,30 @@ cbor_decode_rp_entity 8 0 100.00% 10 0 | |||
193 | cbor.c:ctap_check_cbor 28 0 100.00% 32 0 100.00% | 193 | cbor.c:ctap_check_cbor 28 0 100.00% 32 0 100.00% |
194 | cbor.c:check_key_type 8 0 100.00% 9 0 100.00% | 194 | cbor.c:check_key_type 8 0 100.00% 9 0 100.00% |
195 | cbor.c:cbor_add_arg 13 0 100.00% 28 0 100.00% | 195 | cbor.c:cbor_add_arg 13 0 100.00% 28 0 100.00% |
196 | cbor.c:cbor_add_uint8 14 1 92.86% 26 3 88.46% | 196 | cbor.c:cbor_add_uint8 14 0 100.00% 26 0 100.00% |
197 | cbor.c:sha256 7 0 100.00% 15 0 100.00% | 197 | cbor.c:sha256 7 0 100.00% 15 0 100.00% |
198 | cbor.c:get_cose_alg 36 6 83.33% 48 6 87.50% | 198 | cbor.c:get_cose_alg 36 0 100.00% 48 0 100.00% |
199 | cbor.c:find_cose_alg 35 0 100.00% 40 0 100.00% | 199 | cbor.c:find_cose_alg 35 0 100.00% 40 0 100.00% |
200 | cbor.c:decode_attcred 25 0 100.00% 58 0 100.00% | 200 | cbor.c:decode_attcred 25 0 100.00% 58 0 100.00% |
201 | cbor.c:decode_extensions 14 9 35.71% 34 13 61.76% | 201 | cbor.c:decode_extensions 14 0 100.00% 34 0 100.00% |
202 | cbor.c:decode_extension 27 27 0.00% 36 36 0.00% | 202 | cbor.c:decode_extension 27 2 92.59% 36 6 83.33% |
203 | cbor.c:decode_hmac_secret 16 4 75.00% 32 6 81.25% | 203 | cbor.c:decode_hmac_secret 16 0 100.00% 32 0 100.00% |
204 | cbor.c:decode_hmac_secret_aux 7 7 0.00% 17 17 0.00% | 204 | cbor.c:decode_hmac_secret_aux 7 0 100.00% 17 0 100.00% |
205 | cbor.c:decode_attstmt_entry 38 0 100.00% 45 0 100.00% | 205 | cbor.c:decode_attstmt_entry 38 0 100.00% 45 0 100.00% |
206 | cbor.c:decode_x5c 4 0 100.00% 8 0 100.00% | 206 | cbor.c:decode_x5c 4 0 100.00% 8 0 100.00% |
207 | cbor.c:decode_cred_id_entry 10 0 100.00% 23 0 100.00% | 207 | cbor.c:decode_cred_id_entry 10 0 100.00% 23 0 100.00% |
208 | cbor.c:decode_user_entry 25 0 100.00% 39 0 100.00% | 208 | cbor.c:decode_user_entry 25 0 100.00% 39 0 100.00% |
209 | cbor.c:decode_rp_entity_entry 15 0 100.00% 29 0 100.00% | 209 | cbor.c:decode_rp_entity_entry 15 0 100.00% 29 0 100.00% |
210 | --------------------------------------------------------------------------------------- | 210 | --------------------------------------------------------------------------------------- |
211 | TOTAL 884 70 92.08% 1371 106 92.27% | 211 | TOTAL 883 6 99.32% 1364 17 98.75% |
212 | 212 | ||
213 | File '/libfido2/src/cred.c': | 213 | File '/libfido2/src/cred.c': |
214 | Name Regions Miss Cover Lines Miss Cover | 214 | Name Regions Miss Cover Lines Miss Cover |
215 | --------------------------------------------------------------------------------------- | 215 | --------------------------------------------------------------------------------------- |
216 | fido_dev_make_cred 12 0 100.00% 10 0 100.00% | 216 | fido_dev_make_cred 12 0 100.00% 10 0 100.00% |
217 | fido_check_rp_id 4 0 100.00% 14 0 100.00% | 217 | fido_check_rp_id 4 0 100.00% 14 0 100.00% |
218 | fido_cred_verify 46 6 86.96% 71 11 84.51% | 218 | fido_cred_verify 46 2 95.65% 71 3 95.77% |
219 | fido_cred_verify_self 54 14 74.07% 90 22 75.56% | 219 | fido_cred_verify_self 54 4 92.59% 90 5 94.44% |
220 | fido_cred_new 1 0 100.00% 3 0 100.00% | 220 | fido_cred_new 1 0 100.00% 3 0 100.00% |
221 | fido_cred_reset_tx 1 0 100.00% 20 0 100.00% | 221 | fido_cred_reset_tx 1 0 100.00% 20 0 100.00% |
222 | fido_cred_reset_rx 1 0 100.00% 8 0 100.00% | 222 | fido_cred_reset_rx 1 0 100.00% 8 0 100.00% |
@@ -227,15 +227,15 @@ fido_cred_set_x509 12 0 100.00% 16 0 | |||
227 | fido_cred_set_sig 12 0 100.00% 16 0 100.00% | 227 | fido_cred_set_sig 12 0 100.00% 16 0 100.00% |
228 | fido_cred_exclude 14 2 85.71% 25 3 88.00% | 228 | fido_cred_exclude 14 2 85.71% 25 3 88.00% |
229 | fido_cred_set_clientdata_hash 6 0 100.00% 6 0 100.00% | 229 | fido_cred_set_clientdata_hash 6 0 100.00% 6 0 100.00% |
230 | fido_cred_set_rp 18 2 88.89% 26 6 76.92% | 230 | fido_cred_set_rp 18 0 100.00% 26 0 100.00% |
231 | fido_cred_set_user 33 4 87.88% 50 13 74.00% | 231 | fido_cred_set_user 33 0 100.00% 50 0 100.00% |
232 | fido_cred_set_extensions 15 0 100.00% 12 0 100.00% | 232 | fido_cred_set_extensions 15 0 100.00% 12 0 100.00% |
233 | fido_cred_set_options 6 6 0.00% 6 6 0.00% | 233 | fido_cred_set_options 6 6 0.00% 6 6 0.00% |
234 | fido_cred_set_rk 2 0 100.00% 5 0 100.00% | 234 | fido_cred_set_rk 2 0 100.00% 5 0 100.00% |
235 | fido_cred_set_uv 2 0 100.00% 5 0 100.00% | 235 | fido_cred_set_uv 2 0 100.00% 5 0 100.00% |
236 | fido_cred_set_prot 21 2 90.48% 16 0 100.00% | 236 | fido_cred_set_prot 21 0 100.00% 16 0 100.00% |
237 | fido_cred_set_fmt 16 4 75.00% 15 1 93.33% | 237 | fido_cred_set_fmt 16 4 75.00% 15 1 93.33% |
238 | fido_cred_set_type 17 2 88.24% 9 1 88.89% | 238 | fido_cred_set_type 17 0 100.00% 9 0 100.00% |
239 | fido_cred_type 1 0 100.00% 3 0 100.00% | 239 | fido_cred_type 1 0 100.00% 3 0 100.00% |
240 | fido_cred_flags 1 0 100.00% 3 0 100.00% | 240 | fido_cred_flags 1 0 100.00% 3 0 100.00% |
241 | fido_cred_clientdata_hash_ptr 1 0 100.00% 3 0 100.00% | 241 | fido_cred_clientdata_hash_ptr 1 0 100.00% 3 0 100.00% |
@@ -246,10 +246,12 @@ fido_cred_sig_ptr 1 0 100.00% 3 0 | |||
246 | fido_cred_sig_len 1 0 100.00% 3 0 100.00% | 246 | fido_cred_sig_len 1 0 100.00% 3 0 100.00% |
247 | fido_cred_authdata_ptr 1 0 100.00% 3 0 100.00% | 247 | fido_cred_authdata_ptr 1 0 100.00% 3 0 100.00% |
248 | fido_cred_authdata_len 1 0 100.00% 3 0 100.00% | 248 | fido_cred_authdata_len 1 0 100.00% 3 0 100.00% |
249 | fido_cred_pubkey_ptr 9 2 77.78% 20 2 90.00% | 249 | fido_cred_pubkey_ptr 9 0 100.00% 20 0 100.00% |
250 | fido_cred_pubkey_len 9 2 77.78% 20 2 90.00% | 250 | fido_cred_pubkey_len 9 0 100.00% 20 0 100.00% |
251 | fido_cred_id_ptr 1 0 100.00% 3 0 100.00% | 251 | fido_cred_id_ptr 1 0 100.00% 3 0 100.00% |
252 | fido_cred_id_len 1 0 100.00% 3 0 100.00% | 252 | fido_cred_id_len 1 0 100.00% 3 0 100.00% |
253 | fido_cred_aaguid_ptr 1 0 100.00% 3 0 100.00% | ||
254 | fido_cred_aaguid_len 1 0 100.00% 3 0 100.00% | ||
253 | fido_cred_prot 1 0 100.00% 3 0 100.00% | 255 | fido_cred_prot 1 0 100.00% 3 0 100.00% |
254 | fido_cred_fmt 1 0 100.00% 3 0 100.00% | 256 | fido_cred_fmt 1 0 100.00% 3 0 100.00% |
255 | fido_cred_rp_id 1 0 100.00% 3 0 100.00% | 257 | fido_cred_rp_id 1 0 100.00% 3 0 100.00% |
@@ -269,7 +271,7 @@ cred.c:fido_cred_clean_authdata 1 0 100.00% 9 0 | |||
269 | cred.c:fido_cred_clean_x509 1 0 100.00% 5 0 100.00% | 271 | cred.c:fido_cred_clean_x509 1 0 100.00% 5 0 100.00% |
270 | cred.c:fido_cred_clean_sig 1 0 100.00% 5 0 100.00% | 272 | cred.c:fido_cred_clean_sig 1 0 100.00% 5 0 100.00% |
271 | --------------------------------------------------------------------------------------- | 273 | --------------------------------------------------------------------------------------- |
272 | TOTAL 534 51 90.45% 830 78 90.60% | 274 | TOTAL 536 23 95.71% 836 29 96.53% |
273 | 275 | ||
274 | File '/libfido2/src/credman.c': | 276 | File '/libfido2/src/credman.c': |
275 | Name Regions Miss Cover Lines Miss Cover | 277 | Name Regions Miss Cover Lines Miss Cover |
@@ -295,14 +297,14 @@ fido_credman_rp_id_hash_len 4 0 100.00% 6 0 | |||
295 | fido_credman_rp_id_hash_ptr 4 0 100.00% 6 0 100.00% | 297 | fido_credman_rp_id_hash_ptr 4 0 100.00% 6 0 100.00% |
296 | credman.c:credman_get_metadata_wait 11 0 100.00% 9 0 100.00% | 298 | credman.c:credman_get_metadata_wait 11 0 100.00% 9 0 100.00% |
297 | credman.c:credman_tx 30 0 100.00% 53 0 100.00% | 299 | credman.c:credman_tx 30 0 100.00% 53 0 100.00% |
298 | credman.c:credman_prepare_hmac 21 1 95.24% 43 2 95.35% | 300 | credman.c:credman_prepare_hmac 21 1 95.24% 43 3 93.02% |
299 | credman.c:credman_rx_metadata 11 0 100.00% 21 0 100.00% | 301 | credman.c:credman_rx_metadata 11 0 100.00% 21 0 100.00% |
300 | credman.c:credman_parse_metadata 9 0 100.00% 19 0 100.00% | 302 | credman.c:credman_parse_metadata 9 0 100.00% 19 0 100.00% |
301 | credman.c:credman_get_rk_wait 27 0 100.00% 26 0 100.00% | 303 | credman.c:credman_get_rk_wait 27 0 100.00% 26 0 100.00% |
302 | credman.c:credman_rx_rk 19 0 100.00% 36 0 100.00% | 304 | credman.c:credman_rx_rk 19 0 100.00% 36 0 100.00% |
303 | credman.c:credman_parse_rk_count 16 0 100.00% 25 0 100.00% | 305 | credman.c:credman_parse_rk_count 16 0 100.00% 25 0 100.00% |
304 | credman.c:credman_grow_array 17 2 88.24% 28 5 82.14% | 306 | credman.c:credman_grow_array 17 2 88.24% 28 5 82.14% |
305 | credman.c:credman_parse_rk 13 0 100.00% 25 0 100.00% | 307 | credman.c:credman_parse_rk 22 0 100.00% 31 0 100.00% |
306 | credman.c:credman_rx_next_rk 15 2 86.67% 26 4 84.62% | 308 | credman.c:credman_rx_next_rk 15 2 86.67% 26 4 84.62% |
307 | credman.c:credman_del_rk_wait 16 0 100.00% 19 0 100.00% | 309 | credman.c:credman_del_rk_wait 16 0 100.00% 19 0 100.00% |
308 | credman.c:credman_get_rp_wait 23 0 100.00% 16 0 100.00% | 310 | credman.c:credman_get_rp_wait 23 0 100.00% 16 0 100.00% |
@@ -313,7 +315,7 @@ credman.c:credman_rx_next_rp 15 2 86.67% 26 4 | |||
313 | credman.c:credman_reset_rk 4 0 100.00% 10 0 100.00% | 315 | credman.c:credman_reset_rk 4 0 100.00% 10 0 100.00% |
314 | credman.c:credman_reset_rp 4 0 100.00% 15 0 100.00% | 316 | credman.c:credman_reset_rp 4 0 100.00% 15 0 100.00% |
315 | --------------------------------------------------------------------------------------- | 317 | --------------------------------------------------------------------------------------- |
316 | TOTAL 376 18 95.21% 589 15 97.45% | 318 | TOTAL 385 18 95.32% 595 16 97.31% |
317 | 319 | ||
318 | File '/libfido2/src/dev.c': | 320 | File '/libfido2/src/dev.c': |
319 | Name Regions Miss Cover Lines Miss Cover | 321 | Name Regions Miss Cover Lines Miss Cover |
@@ -324,9 +326,11 @@ fido_dev_info_manifest 17 17 0.00% 24 24 | |||
324 | fido_dev_open_with_info 5 5 0.00% 6 6 0.00% | 326 | fido_dev_open_with_info 5 5 0.00% 6 6 0.00% |
325 | fido_dev_open 1 0 100.00% 3 0 100.00% | 327 | fido_dev_open 1 0 100.00% 3 0 100.00% |
326 | fido_dev_close 8 2 75.00% 9 0 100.00% | 328 | fido_dev_close 8 2 75.00% 9 0 100.00% |
327 | fido_dev_cancel 7 0 100.00% 6 0 100.00% | 329 | fido_dev_cancel 11 0 100.00% 9 0 100.00% |
328 | fido_dev_set_io_functions 18 4 77.78% 16 6 62.50% | 330 | fido_dev_get_touch_begin 50 0 100.00% 68 0 100.00% |
329 | fido_dev_set_transport_functions 6 6 0.00% 10 10 0.00% | 331 | fido_dev_get_touch_status 17 0 100.00% 25 0 100.00% |
332 | fido_dev_set_io_functions 18 4 77.78% 17 6 64.71% | ||
333 | fido_dev_set_transport_functions 6 6 0.00% 11 11 0.00% | ||
330 | fido_init 7 1 85.71% 4 0 100.00% | 334 | fido_init 7 1 85.71% 4 0 100.00% |
331 | fido_dev_new 5 0 100.00% 16 0 100.00% | 335 | fido_dev_new 5 0 100.00% 16 0 100.00% |
332 | fido_dev_new_with_info 17 17 0.00% 26 26 0.00% | 336 | fido_dev_new_with_info 17 17 0.00% 26 26 0.00% |
@@ -337,15 +341,20 @@ fido_dev_minor 1 0 100.00% 3 0 | |||
337 | fido_dev_build 1 0 100.00% 3 0 100.00% | 341 | fido_dev_build 1 0 100.00% 3 0 100.00% |
338 | fido_dev_flags 1 0 100.00% 3 0 100.00% | 342 | fido_dev_flags 1 0 100.00% 3 0 100.00% |
339 | fido_dev_is_fido2 2 0 100.00% 3 0 100.00% | 343 | fido_dev_is_fido2 2 0 100.00% 3 0 100.00% |
340 | fido_dev_force_u2f 2 0 100.00% 3 0 100.00% | 344 | fido_dev_supports_pin 3 0 100.00% 3 0 100.00% |
345 | fido_dev_has_pin 2 0 100.00% 3 0 100.00% | ||
346 | fido_dev_supports_cred_prot 2 0 100.00% 3 0 100.00% | ||
347 | fido_dev_force_u2f 2 0 100.00% 4 0 100.00% | ||
341 | fido_dev_force_fido2 2 2 0.00% 3 3 0.00% | 348 | fido_dev_force_fido2 2 2 0.00% 3 3 0.00% |
342 | dev.c:find_manifest_func_node 5 5 0.00% 9 9 0.00% | 349 | dev.c:find_manifest_func_node 5 5 0.00% 9 9 0.00% |
343 | dev.c:fido_dev_open_wait 10 0 100.00% 9 0 100.00% | 350 | dev.c:fido_dev_open_wait 10 0 100.00% 9 0 100.00% |
344 | dev.c:fido_dev_open_tx 25 8 68.00% 32 12 62.50% | 351 | dev.c:fido_dev_open_tx 51 13 74.51% 63 23 63.49% |
345 | dev.c:obtain_nonce 4 1 75.00% 5 1 80.00% | 352 | dev.c:obtain_nonce 4 1 75.00% 5 1 80.00% |
346 | dev.c:fido_dev_open_rx 32 0 100.00% 53 0 100.00% | 353 | dev.c:set_random_report_len 11 0 100.00% 6 0 100.00% |
354 | dev.c:fido_dev_open_rx 33 0 100.00% 56 0 100.00% | ||
355 | dev.c:fido_dev_set_flags 17 0 100.00% 24 0 100.00% | ||
347 | --------------------------------------------------------------------------------------- | 356 | --------------------------------------------------------------------------------------- |
348 | TOTAL 201 85 57.71% 294 128 56.46% | 357 | TOTAL 334 90 73.05% 466 140 69.96% |
349 | 358 | ||
350 | File '/libfido2/src/ecdh.c': | 359 | File '/libfido2/src/ecdh.c': |
351 | Name Regions Miss Cover Lines Miss Cover | 360 | Name Regions Miss Cover Lines Miss Cover |
@@ -372,9 +381,9 @@ TOTAL 54 0 100.00% 79 0 | |||
372 | File '/libfido2/src/err.c': | 381 | File '/libfido2/src/err.c': |
373 | Name Regions Miss Cover Lines Miss Cover | 382 | Name Regions Miss Cover Lines Miss Cover |
374 | --------------------------------------------------------------------------------------- | 383 | --------------------------------------------------------------------------------------- |
375 | fido_strerr 108 108 0.00% 112 112 0.00% | 384 | fido_strerr 112 8 92.86% 116 8 93.10% |
376 | --------------------------------------------------------------------------------------- | 385 | --------------------------------------------------------------------------------------- |
377 | TOTAL 108 108 0.00% 112 112 0.00% | 386 | TOTAL 112 8 92.86% 116 8 93.10% |
378 | 387 | ||
379 | File '/libfido2/src/es256.c': | 388 | File '/libfido2/src/es256.c': |
380 | Name Regions Miss Cover Lines Miss Cover | 389 | Name Regions Miss Cover Lines Miss Cover |
@@ -389,14 +398,14 @@ es256_pk_from_ptr 11 0 100.00% 13 0 | |||
389 | es256_pk_set_x 1 0 100.00% 5 0 100.00% | 398 | es256_pk_set_x 1 0 100.00% 5 0 100.00% |
390 | es256_pk_set_y 1 0 100.00% 5 0 100.00% | 399 | es256_pk_set_y 1 0 100.00% 5 0 100.00% |
391 | es256_sk_create 39 0 100.00% 46 0 100.00% | 400 | es256_sk_create 39 0 100.00% 46 0 100.00% |
392 | es256_pk_to_EVP_PKEY 41 0 100.00% 58 0 100.00% | 401 | es256_pk_to_EVP_PKEY 42 0 100.00% 66 0 100.00% |
393 | es256_pk_from_EC_KEY 38 0 100.00% 39 0 100.00% | 402 | es256_pk_from_EC_KEY 38 0 100.00% 43 0 100.00% |
394 | es256_sk_to_EVP_PKEY 27 0 100.00% 41 0 100.00% | 403 | es256_sk_to_EVP_PKEY 28 0 100.00% 50 0 100.00% |
395 | es256_derive_pk 25 0 100.00% 34 0 100.00% | 404 | es256_derive_pk 25 0 100.00% 34 0 100.00% |
396 | es256.c:decode_pubkey_point 9 0 100.00% 16 0 100.00% | 405 | es256.c:decode_pubkey_point 9 0 100.00% 16 0 100.00% |
397 | es256.c:decode_coord 8 0 100.00% 12 0 100.00% | 406 | es256.c:decode_coord 8 0 100.00% 12 0 100.00% |
398 | --------------------------------------------------------------------------------------- | 407 | --------------------------------------------------------------------------------------- |
399 | TOTAL 278 0 100.00% 377 0 100.00% | 408 | TOTAL 280 0 100.00% 398 0 100.00% |
400 | 409 | ||
401 | File '/libfido2/src/extern.h': | 410 | File '/libfido2/src/extern.h': |
402 | Name Regions Miss Cover Lines Miss Cover | 411 | Name Regions Miss Cover Lines Miss Cover |
@@ -423,20 +432,27 @@ TOTAL 16 16 0.00% 38 38 | |||
423 | File '/libfido2/src/hid_linux.c': | 432 | File '/libfido2/src/hid_linux.c': |
424 | Name Regions Miss Cover Lines Miss Cover | 433 | Name Regions Miss Cover Lines Miss Cover |
425 | --------------------------------------------------------------------------------------- | 434 | --------------------------------------------------------------------------------------- |
426 | fido_hid_manifest 33 33 0.00% 46 46 0.00% | 435 | fido_hid_manifest 35 35 0.00% 50 50 0.00% |
427 | fido_hid_open 6 6 0.00% 11 11 0.00% | 436 | fido_hid_open 17 17 0.00% 22 22 0.00% |
428 | fido_hid_close 1 1 0.00% 6 6 0.00% | 437 | fido_hid_close 1 1 0.00% 6 6 0.00% |
429 | fido_hid_read 12 12 0.00% 16 16 0.00% | 438 | fido_hid_read 12 12 0.00% 21 21 0.00% |
430 | fido_hid_write 12 12 0.00% 16 16 0.00% | 439 | fido_hid_write 9 9 0.00% 16 16 0.00% |
431 | hid_linux.c:copy_info 35 35 0.00% 56 56 0.00% | 440 | fido_hid_report_in_len 1 1 0.00% 5 5 0.00% |
432 | hid_linux.c:is_fido 6 6 0.00% 14 14 0.00% | 441 | fido_hid_report_out_len 1 1 0.00% 5 5 0.00% |
433 | hid_linux.c:get_report_descriptor 17 17 0.00% 30 30 0.00% | 442 | hid_linux.c:copy_info 30 30 0.00% 52 52 0.00% |
434 | hid_linux.c:get_usage_info 16 16 0.00% 33 33 0.00% | 443 | hid_linux.c:is_fido 9 9 0.00% 23 23 0.00% |
444 | hid_linux.c:get_usage_info 16 16 0.00% 30 30 0.00% | ||
435 | hid_linux.c:get_key_len 6 6 0.00% 14 14 0.00% | 445 | hid_linux.c:get_key_len 6 6 0.00% 14 14 0.00% |
436 | hid_linux.c:get_key_val 6 6 0.00% 20 20 0.00% | 446 | hid_linux.c:get_key_val 6 6 0.00% 20 20 0.00% |
437 | hid_linux.c:parse_uevent 16 16 0.00% 30 30 0.00% | 447 | hid_linux.c:get_parent_attr 6 6 0.00% 11 11 0.00% |
438 | --------------------------------------------------------------------------------------- | 448 | hid_linux.c:parse_uevent 12 12 0.00% 28 28 0.00% |
439 | TOTAL 166 166 0.00% 292 292 0.00% | 449 | hid_linux.c:get_usb_attr 1 1 0.00% 3 3 0.00% |
450 | hid_linux.c:get_report_descriptor 11 11 0.00% 18 18 0.00% | ||
451 | hid_linux.c:get_report_sizes 19 19 0.00% 33 33 0.00% | ||
452 | hid_linux.c:waitfd 28 28 0.00% 43 43 0.00% | ||
453 | hid_linux.c:timespec_to_ms 15 15 0.00% 16 16 0.00% | ||
454 | --------------------------------------------------------------------------------------- | ||
455 | TOTAL 235 235 0.00% 416 416 0.00% | ||
440 | 456 | ||
441 | File '/libfido2/src/info.c': | 457 | File '/libfido2/src/info.c': |
442 | Name Regions Miss Cover Lines Miss Cover | 458 | Name Regions Miss Cover Lines Miss Cover |
@@ -455,11 +471,14 @@ fido_cbor_info_options_name_ptr 1 0 100.00% 3 0 | |||
455 | fido_cbor_info_options_value_ptr 1 0 100.00% 3 0 100.00% | 471 | fido_cbor_info_options_value_ptr 1 0 100.00% 3 0 100.00% |
456 | fido_cbor_info_options_len 1 0 100.00% 3 0 100.00% | 472 | fido_cbor_info_options_len 1 0 100.00% 3 0 100.00% |
457 | fido_cbor_info_maxmsgsiz 1 0 100.00% 3 0 100.00% | 473 | fido_cbor_info_maxmsgsiz 1 0 100.00% 3 0 100.00% |
474 | fido_cbor_info_maxcredcntlst 1 0 100.00% 3 0 100.00% | ||
475 | fido_cbor_info_maxcredidlen 1 0 100.00% 3 0 100.00% | ||
476 | fido_cbor_info_fwversion 1 0 100.00% 3 0 100.00% | ||
458 | fido_cbor_info_protocols_ptr 1 0 100.00% 3 0 100.00% | 477 | fido_cbor_info_protocols_ptr 1 0 100.00% 3 0 100.00% |
459 | fido_cbor_info_protocols_len 1 0 100.00% 3 0 100.00% | 478 | fido_cbor_info_protocols_len 1 0 100.00% 3 0 100.00% |
460 | info.c:fido_dev_get_cbor_info_tx 8 0 100.00% 12 0 100.00% | 479 | info.c:fido_dev_get_cbor_info_tx 8 0 100.00% 12 0 100.00% |
461 | info.c:fido_dev_get_cbor_info_rx 6 0 100.00% 18 0 100.00% | 480 | info.c:fido_dev_get_cbor_info_rx 6 0 100.00% 18 0 100.00% |
462 | info.c:parse_reply_element 13 0 100.00% 27 0 100.00% | 481 | info.c:parse_reply_element 16 0 100.00% 33 0 100.00% |
463 | info.c:decode_versions 12 0 100.00% 21 0 100.00% | 482 | info.c:decode_versions 12 0 100.00% 21 0 100.00% |
464 | info.c:decode_version 4 0 100.00% 14 0 100.00% | 483 | info.c:decode_version 4 0 100.00% 14 0 100.00% |
465 | info.c:decode_extensions 12 0 100.00% 21 0 100.00% | 484 | info.c:decode_extensions 12 0 100.00% 21 0 100.00% |
@@ -473,23 +492,23 @@ info.c:free_str_array 4 0 100.00% 8 0 | |||
473 | info.c:free_opt_array 4 0 100.00% 9 0 100.00% | 492 | info.c:free_opt_array 4 0 100.00% 9 0 100.00% |
474 | info.c:free_byte_array 1 0 100.00% 6 0 100.00% | 493 | info.c:free_byte_array 1 0 100.00% 6 0 100.00% |
475 | --------------------------------------------------------------------------------------- | 494 | --------------------------------------------------------------------------------------- |
476 | TOTAL 146 0 100.00% 304 0 100.00% | 495 | TOTAL 152 0 100.00% 319 0 100.00% |
477 | 496 | ||
478 | File '/libfido2/src/io.c': | 497 | File '/libfido2/src/io.c': |
479 | Name Regions Miss Cover Lines Miss Cover | 498 | Name Regions Miss Cover Lines Miss Cover |
480 | --------------------------------------------------------------------------------------- | 499 | --------------------------------------------------------------------------------------- |
481 | fido_tx 14 1 92.86% 18 0 100.00% | 500 | fido_tx 13 1 92.31% 14 0 100.00% |
482 | fido_rx 13 2 84.62% 21 3 85.71% | 501 | fido_rx 13 2 84.62% 19 3 84.21% |
483 | fido_rx_cbor_status 8 0 100.00% 12 0 100.00% | 502 | fido_rx_cbor_status 8 0 100.00% 12 0 100.00% |
484 | io.c:tx_empty 7 0 100.00% 16 0 100.00% | 503 | io.c:tx_empty 9 0 100.00% 17 0 100.00% |
485 | io.c:tx 13 0 100.00% 21 0 100.00% | 504 | io.c:tx 13 0 100.00% 21 0 100.00% |
486 | io.c:tx_preamble 10 0 100.00% 20 0 100.00% | 505 | io.c:tx_preamble 16 1 93.75% 24 1 95.83% |
487 | io.c:tx_frame 9 0 100.00% 18 0 100.00% | 506 | io.c:tx_frame 15 1 93.33% 22 1 95.45% |
488 | io.c:rx 25 1 96.00% 58 4 93.10% | 507 | io.c:rx 40 2 95.00% 68 1 98.53% |
489 | io.c:rx_preamble 18 1 94.44% 25 4 84.00% | 508 | io.c:rx_preamble 21 2 90.48% 28 5 82.14% |
490 | io.c:rx_frame 6 0 100.00% 9 0 100.00% | 509 | io.c:rx_frame 8 0 100.00% 11 0 100.00% |
491 | --------------------------------------------------------------------------------------- | 510 | --------------------------------------------------------------------------------------- |
492 | TOTAL 123 5 95.93% 218 11 94.95% | 511 | TOTAL 156 9 94.23% 236 11 95.34% |
493 | 512 | ||
494 | File '/libfido2/src/iso7816.c': | 513 | File '/libfido2/src/iso7816.c': |
495 | Name Regions Miss Cover Lines Miss Cover | 514 | Name Regions Miss Cover Lines Miss Cover |
@@ -547,32 +566,34 @@ TOTAL 19 0 100.00% 22 0 | |||
547 | File '/libfido2/src/rs256.c': | 566 | File '/libfido2/src/rs256.c': |
548 | Name Regions Miss Cover Lines Miss Cover | 567 | Name Regions Miss Cover Lines Miss Cover |
549 | --------------------------------------------------------------------------------------- | 568 | --------------------------------------------------------------------------------------- |
550 | rs256_pk_decode 8 8 0.00% 10 10 0.00% | 569 | rs256_pk_decode 8 0 100.00% 10 0 100.00% |
551 | rs256_pk_new 1 0 100.00% 3 0 100.00% | 570 | rs256_pk_new 1 0 100.00% 3 0 100.00% |
552 | rs256_pk_free 6 0 100.00% 11 0 100.00% | 571 | rs256_pk_free 6 0 100.00% 11 0 100.00% |
553 | rs256_pk_from_ptr 6 0 100.00% 8 0 100.00% | 572 | rs256_pk_from_ptr 6 0 100.00% 8 0 100.00% |
554 | rs256_pk_to_EVP_PKEY 32 0 100.00% 48 0 100.00% | 573 | rs256_pk_to_EVP_PKEY 32 0 100.00% 48 0 100.00% |
555 | rs256_pk_from_RSA 32 4 87.50% 32 6 81.25% | 574 | rs256_pk_from_RSA 32 4 87.50% 32 6 81.25% |
556 | rs256.c:decode_rsa_pubkey 9 9 0.00% 16 16 0.00% | 575 | rs256.c:decode_rsa_pubkey 9 1 88.89% 16 4 75.00% |
557 | rs256.c:decode_bignum 8 8 0.00% 12 12 0.00% | 576 | rs256.c:decode_bignum 8 1 87.50% 12 3 75.00% |
558 | --------------------------------------------------------------------------------------- | 577 | --------------------------------------------------------------------------------------- |
559 | TOTAL 102 29 71.57% 140 44 68.57% | 578 | TOTAL 102 6 94.12% 140 13 90.71% |
560 | 579 | ||
561 | File '/libfido2/src/u2f.c': | 580 | File '/libfido2/src/u2f.c': |
562 | Name Regions Miss Cover Lines Miss Cover | 581 | Name Regions Miss Cover Lines Miss Cover |
563 | --------------------------------------------------------------------------------------- | 582 | --------------------------------------------------------------------------------------- |
564 | u2f_register 70 5 92.86% 88 7 92.05% | 583 | u2f_register 70 1 98.57% 88 0 100.00% |
565 | u2f_authenticate 32 4 87.50% 44 2 95.45% | 584 | u2f_authenticate 32 0 100.00% 44 0 100.00% |
585 | u2f_get_touch_begin 30 0 100.00% 46 0 100.00% | ||
586 | u2f_get_touch_status 18 0 100.00% 29 0 100.00% | ||
566 | u2f.c:key_lookup 44 0 100.00% 69 0 100.00% | 587 | u2f.c:key_lookup 44 0 100.00% 69 0 100.00% |
567 | u2f.c:send_dummy_register 31 5 83.87% 49 8 83.67% | 588 | u2f.c:send_dummy_register 31 1 96.77% 49 0 100.00% |
568 | u2f.c:parse_register_reply 57 0 100.00% 83 0 100.00% | 589 | u2f.c:parse_register_reply 57 0 100.00% 83 0 100.00% |
569 | u2f.c:x5c_get 21 2 90.48% 37 6 83.78% | 590 | u2f.c:x5c_get 21 1 95.24% 37 3 91.89% |
570 | u2f.c:sig_get 8 1 87.50% 16 6 62.50% | 591 | u2f.c:sig_get 8 1 87.50% 16 6 62.50% |
571 | u2f.c:encode_cred_authdata 37 3 91.89% 82 9 89.02% | 592 | u2f.c:encode_cred_authdata 37 2 94.59% 82 6 92.68% |
572 | u2f.c:cbor_blob_from_ec_point 22 1 95.45% 39 3 92.31% | 593 | u2f.c:cbor_blob_from_ec_point 22 0 100.00% 39 0 100.00% |
573 | u2f.c:u2f_authenticate_single 36 2 94.44% 58 4 93.10% | 594 | u2f.c:u2f_authenticate_single 36 0 100.00% 58 0 100.00% |
574 | u2f.c:do_auth 50 3 94.00% 71 4 94.37% | 595 | u2f.c:do_auth 50 1 98.00% 71 0 100.00% |
575 | u2f.c:parse_auth_reply 23 2 91.30% 29 3 89.66% | 596 | u2f.c:parse_auth_reply 23 2 91.30% 29 3 89.66% |
576 | u2f.c:authdata_fake 12 0 100.00% 34 0 100.00% | 597 | u2f.c:authdata_fake 12 0 100.00% 34 0 100.00% |
577 | --------------------------------------------------------------------------------------- | 598 | --------------------------------------------------------------------------------------- |
578 | TOTAL 443 28 93.68% 699 52 92.56% | 599 | TOTAL 491 9 98.17% 774 18 97.67% |
diff --git a/fuzz/fuzz_assert.c b/fuzz/fuzz_assert.c index 5b72658..3ae54eb 100644 --- a/fuzz/fuzz_assert.c +++ b/fuzz/fuzz_assert.c | |||
@@ -23,39 +23,23 @@ | |||
23 | 23 | ||
24 | #include "../openbsd-compat/openbsd-compat.h" | 24 | #include "../openbsd-compat/openbsd-compat.h" |
25 | 25 | ||
26 | #define TAG_U2F 0x01 | ||
27 | #define TAG_TYPE 0x02 | ||
28 | #define TAG_CDH 0x03 | ||
29 | #define TAG_RP_ID 0x04 | ||
30 | #define TAG_EXT 0x05 | ||
31 | #define TAG_SEED 0x06 | ||
32 | #define TAG_UP 0x07 | ||
33 | #define TAG_UV 0x08 | ||
34 | #define TAG_WIRE_DATA 0x09 | ||
35 | #define TAG_CRED_COUNT 0x0a | ||
36 | #define TAG_CRED 0x0b | ||
37 | #define TAG_ES256 0x0c | ||
38 | #define TAG_RS256 0x0d | ||
39 | #define TAG_PIN 0x0e | ||
40 | #define TAG_EDDSA 0x0f | ||
41 | |||
42 | /* Parameter set defining a FIDO2 get assertion operation. */ | 26 | /* Parameter set defining a FIDO2 get assertion operation. */ |
43 | struct param { | 27 | struct param { |
44 | char pin[MAXSTR]; | 28 | char pin[MAXSTR]; |
45 | char rp_id[MAXSTR]; | 29 | char rp_id[MAXSTR]; |
46 | int ext; | 30 | int ext; |
47 | int seed; | 31 | int seed; |
48 | struct blob cdh; | 32 | struct blob cdh; |
49 | struct blob cred; | 33 | struct blob cred; |
50 | struct blob es256; | 34 | struct blob es256; |
51 | struct blob rs256; | 35 | struct blob rs256; |
52 | struct blob eddsa; | 36 | struct blob eddsa; |
53 | struct blob wire_data; | 37 | struct blob wire_data; |
54 | uint8_t cred_count; | 38 | uint8_t cred_count; |
55 | uint8_t type; | 39 | uint8_t type; |
56 | uint8_t u2f; | 40 | uint8_t u2f; |
57 | uint8_t up; | 41 | uint8_t up; |
58 | uint8_t uv; | 42 | uint8_t uv; |
59 | }; | 43 | }; |
60 | 44 | ||
61 | /* | 45 | /* |
@@ -83,73 +67,153 @@ static const uint8_t dummy_wire_data_u2f[] = { | |||
83 | WIREDATA_CTAP_U2F_AUTH, | 67 | WIREDATA_CTAP_U2F_AUTH, |
84 | }; | 68 | }; |
85 | 69 | ||
86 | int LLVMFuzzerTestOneInput(const uint8_t *, size_t); | 70 | struct param * |
87 | size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int); | 71 | unpack(const uint8_t *ptr, size_t len) |
88 | |||
89 | static int | ||
90 | unpack(const uint8_t *ptr, size_t len, struct param *p) NO_MSAN | ||
91 | { | 72 | { |
92 | uint8_t **pp = (void *)&ptr; | 73 | cbor_item_t *item = NULL, **v; |
93 | 74 | struct cbor_load_result cbor; | |
94 | if (unpack_byte(TAG_UV, pp, &len, &p->uv) < 0 || | 75 | struct param *p; |
95 | unpack_byte(TAG_UP, pp, &len, &p->up) < 0 || | 76 | int ok = -1; |
96 | unpack_byte(TAG_U2F, pp, &len, &p->u2f) < 0 || | 77 | |
97 | unpack_byte(TAG_TYPE, pp, &len, &p->type) < 0 || | 78 | if ((p = calloc(1, sizeof(*p))) == NULL || |
98 | unpack_byte(TAG_CRED_COUNT, pp, &len, &p->cred_count) < 0 || | 79 | (item = cbor_load(ptr, len, &cbor)) == NULL || |
99 | unpack_int(TAG_EXT, pp, &len, &p->ext) < 0 || | 80 | cbor.read != len || |
100 | unpack_int(TAG_SEED, pp, &len, &p->seed) < 0 || | 81 | cbor_isa_array(item) == false || |
101 | unpack_string(TAG_RP_ID, pp, &len, p->rp_id) < 0 || | 82 | cbor_array_is_definite(item) == false || |
102 | unpack_string(TAG_PIN, pp, &len, p->pin) < 0 || | 83 | cbor_array_size(item) != 15 || |
103 | unpack_blob(TAG_WIRE_DATA, pp, &len, &p->wire_data) < 0 || | 84 | (v = cbor_array_handle(item)) == NULL) |
104 | unpack_blob(TAG_RS256, pp, &len, &p->rs256) < 0 || | 85 | goto fail; |
105 | unpack_blob(TAG_ES256, pp, &len, &p->es256) < 0 || | 86 | |
106 | unpack_blob(TAG_EDDSA, pp, &len, &p->eddsa) < 0 || | 87 | if (unpack_byte(v[0], &p->uv) < 0 || |
107 | unpack_blob(TAG_CRED, pp, &len, &p->cred) < 0 || | 88 | unpack_byte(v[1], &p->up) < 0 || |
108 | unpack_blob(TAG_CDH, pp, &len, &p->cdh) < 0) | 89 | unpack_byte(v[2], &p->u2f) < 0 || |
109 | return (-1); | 90 | unpack_byte(v[3], &p->type) < 0 || |
110 | 91 | unpack_byte(v[4], &p->cred_count) < 0 || | |
111 | return (0); | 92 | unpack_int(v[5], &p->ext) < 0 || |
93 | unpack_int(v[6], &p->seed) < 0 || | ||
94 | unpack_string(v[7], p->rp_id) < 0 || | ||
95 | unpack_string(v[8], p->pin) < 0 || | ||
96 | unpack_blob(v[9], &p->wire_data) < 0 || | ||
97 | unpack_blob(v[10], &p->rs256) < 0 || | ||
98 | unpack_blob(v[11], &p->es256) < 0 || | ||
99 | unpack_blob(v[12], &p->eddsa) < 0 || | ||
100 | unpack_blob(v[13], &p->cred) < 0 || | ||
101 | unpack_blob(v[14], &p->cdh) < 0) | ||
102 | goto fail; | ||
103 | |||
104 | ok = 0; | ||
105 | fail: | ||
106 | if (ok < 0) { | ||
107 | free(p); | ||
108 | p = NULL; | ||
109 | } | ||
110 | |||
111 | if (item) | ||
112 | cbor_decref(&item); | ||
113 | |||
114 | return p; | ||
112 | } | 115 | } |
113 | 116 | ||
114 | static size_t | 117 | size_t |
115 | pack(uint8_t *ptr, size_t len, const struct param *p) | 118 | pack(uint8_t *ptr, size_t len, const struct param *p) |
116 | { | 119 | { |
117 | const size_t max = len; | 120 | cbor_item_t *argv[15], *array = NULL; |
118 | 121 | size_t cbor_alloc_len, cbor_len = 0; | |
119 | if (pack_byte(TAG_UV, &ptr, &len, p->uv) < 0 || | 122 | unsigned char *cbor = NULL; |
120 | pack_byte(TAG_UP, &ptr, &len, p->up) < 0 || | 123 | |
121 | pack_byte(TAG_U2F, &ptr, &len, p->u2f) < 0 || | 124 | memset(argv, 0, sizeof(argv)); |
122 | pack_byte(TAG_TYPE, &ptr, &len, p->type) < 0 || | 125 | |
123 | pack_byte(TAG_CRED_COUNT, &ptr, &len, p->cred_count) < 0 || | 126 | if ((array = cbor_new_definite_array(15)) == NULL || |
124 | pack_int(TAG_EXT, &ptr, &len, p->ext) < 0 || | 127 | (argv[0] = pack_byte(p->uv)) == NULL || |
125 | pack_int(TAG_SEED, &ptr, &len, p->seed) < 0 || | 128 | (argv[1] = pack_byte(p->up)) == NULL || |
126 | pack_string(TAG_RP_ID, &ptr, &len, p->rp_id) < 0 || | 129 | (argv[2] = pack_byte(p->u2f)) == NULL || |
127 | pack_string(TAG_PIN, &ptr, &len, p->pin) < 0 || | 130 | (argv[3] = pack_byte(p->type)) == NULL || |
128 | pack_blob(TAG_WIRE_DATA, &ptr, &len, &p->wire_data) < 0 || | 131 | (argv[4] = pack_byte(p->cred_count)) == NULL || |
129 | pack_blob(TAG_RS256, &ptr, &len, &p->rs256) < 0 || | 132 | (argv[5] = pack_int(p->ext)) == NULL || |
130 | pack_blob(TAG_ES256, &ptr, &len, &p->es256) < 0 || | 133 | (argv[6] = pack_int(p->seed)) == NULL || |
131 | pack_blob(TAG_EDDSA, &ptr, &len, &p->eddsa) < 0 || | 134 | (argv[7] = pack_string(p->rp_id)) == NULL || |
132 | pack_blob(TAG_CRED, &ptr, &len, &p->cred) < 0 || | 135 | (argv[8] = pack_string(p->pin)) == NULL || |
133 | pack_blob(TAG_CDH, &ptr, &len, &p->cdh) < 0) | 136 | (argv[9] = pack_blob(&p->wire_data)) == NULL || |
134 | return (0); | 137 | (argv[10] = pack_blob(&p->rs256)) == NULL || |
135 | 138 | (argv[11] = pack_blob(&p->es256)) == NULL || | |
136 | return (max - len); | 139 | (argv[12] = pack_blob(&p->eddsa)) == NULL || |
140 | (argv[13] = pack_blob(&p->cred)) == NULL || | ||
141 | (argv[14] = pack_blob(&p->cdh)) == NULL) | ||
142 | goto fail; | ||
143 | |||
144 | for (size_t i = 0; i < 15; i++) | ||
145 | if (cbor_array_push(array, argv[i]) == false) | ||
146 | goto fail; | ||
147 | |||
148 | if ((cbor_len = cbor_serialize_alloc(array, &cbor, | ||
149 | &cbor_alloc_len)) > len) { | ||
150 | cbor_len = 0; | ||
151 | goto fail; | ||
152 | } | ||
153 | |||
154 | memcpy(ptr, cbor, cbor_len); | ||
155 | fail: | ||
156 | for (size_t i = 0; i < 15; i++) | ||
157 | if (argv[i]) | ||
158 | cbor_decref(&argv[i]); | ||
159 | |||
160 | if (array) | ||
161 | cbor_decref(&array); | ||
162 | |||
163 | free(cbor); | ||
164 | |||
165 | return cbor_len; | ||
137 | } | 166 | } |
138 | 167 | ||
139 | static size_t | 168 | size_t |
140 | input_len(int max) | 169 | pack_dummy(uint8_t *ptr, size_t len) |
141 | { | 170 | { |
142 | return (5 * len_byte() + 2 * len_int() + 2 * len_string(max) + | 171 | struct param dummy; |
143 | 6 * len_blob(max)); | 172 | uint8_t blob[4096]; |
173 | size_t blob_len; | ||
174 | |||
175 | memset(&dummy, 0, sizeof(dummy)); | ||
176 | |||
177 | dummy.type = 1; /* rsa */ | ||
178 | dummy.ext = FIDO_EXT_HMAC_SECRET; | ||
179 | |||
180 | strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); | ||
181 | strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id)); | ||
182 | |||
183 | dummy.cred.len = sizeof(dummy_cdh); /* XXX */ | ||
184 | dummy.cdh.len = sizeof(dummy_cdh); | ||
185 | dummy.es256.len = sizeof(dummy_es256); | ||
186 | dummy.rs256.len = sizeof(dummy_rs256); | ||
187 | dummy.eddsa.len = sizeof(dummy_eddsa); | ||
188 | dummy.wire_data.len = sizeof(dummy_wire_data_fido); | ||
189 | |||
190 | memcpy(&dummy.cred.body, &dummy_cdh, dummy.cred.len); /* XXX */ | ||
191 | memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len); | ||
192 | memcpy(&dummy.wire_data.body, &dummy_wire_data_fido, | ||
193 | dummy.wire_data.len); | ||
194 | memcpy(&dummy.es256.body, &dummy_es256, dummy.es256.len); | ||
195 | memcpy(&dummy.rs256.body, &dummy_rs256, dummy.rs256.len); | ||
196 | memcpy(&dummy.eddsa.body, &dummy_eddsa, dummy.eddsa.len); | ||
197 | |||
198 | assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); | ||
199 | |||
200 | if (blob_len > len) { | ||
201 | memcpy(ptr, blob, len); | ||
202 | return len; | ||
203 | } | ||
204 | |||
205 | memcpy(ptr, blob, blob_len); | ||
206 | |||
207 | return blob_len; | ||
144 | } | 208 | } |
145 | 209 | ||
146 | static void | 210 | static void |
147 | get_assert(fido_assert_t *assert, uint8_t u2f, const struct blob *cdh, | 211 | get_assert(fido_assert_t *assert, uint8_t u2f, const struct blob *cdh, |
148 | const char *rp_id, int ext, uint8_t up, uint8_t uv, const char *pin, | 212 | const char *rp_id, int ext, uint8_t up, uint8_t uv, const char *pin, |
149 | uint8_t cred_count, struct blob *cred) | 213 | uint8_t cred_count, const struct blob *cred) |
150 | { | 214 | { |
151 | fido_dev_t *dev; | 215 | fido_dev_t *dev; |
152 | fido_dev_io_t io; | 216 | fido_dev_io_t io; |
153 | 217 | ||
154 | memset(&io, 0, sizeof(io)); | 218 | memset(&io, 0, sizeof(io)); |
155 | 219 | ||
@@ -166,21 +230,31 @@ get_assert(fido_assert_t *assert, uint8_t u2f, const struct blob *cdh, | |||
166 | 230 | ||
167 | if (u2f & 1) | 231 | if (u2f & 1) |
168 | fido_dev_force_u2f(dev); | 232 | fido_dev_force_u2f(dev); |
169 | |||
170 | for (uint8_t i = 0; i < cred_count; i++) | ||
171 | fido_assert_allow_cred(assert, cred->body, cred->len); | ||
172 | |||
173 | fido_assert_set_clientdata_hash(assert, cdh->body, cdh->len); | ||
174 | fido_assert_set_rp(assert, rp_id); | ||
175 | if (ext & 1) | 233 | if (ext & 1) |
176 | fido_assert_set_extensions(assert, FIDO_EXT_HMAC_SECRET); | 234 | fido_assert_set_extensions(assert, FIDO_EXT_HMAC_SECRET); |
177 | if (up & 1) | 235 | if (up & 1) |
178 | fido_assert_set_up(assert, FIDO_OPT_TRUE); | 236 | fido_assert_set_up(assert, FIDO_OPT_TRUE); |
237 | else if (u2f &1) | ||
238 | fido_assert_set_up(assert, FIDO_OPT_FALSE); | ||
179 | if (uv & 1) | 239 | if (uv & 1) |
180 | fido_assert_set_uv(assert, FIDO_OPT_TRUE); | 240 | fido_assert_set_uv(assert, FIDO_OPT_TRUE); |
181 | /* XXX reuse cred as hmac salt to keep struct param small */ | 241 | |
242 | for (uint8_t i = 0; i < cred_count; i++) | ||
243 | fido_assert_allow_cred(assert, cred->body, cred->len); | ||
244 | |||
245 | fido_assert_set_clientdata_hash(assert, cdh->body, cdh->len); | ||
246 | fido_assert_set_rp(assert, rp_id); | ||
247 | /* XXX reuse cred as hmac salt */ | ||
182 | fido_assert_set_hmac_salt(assert, cred->body, cred->len); | 248 | fido_assert_set_hmac_salt(assert, cred->body, cred->len); |
183 | 249 | ||
250 | /* repeat memory operations to trigger reallocation paths */ | ||
251 | fido_assert_set_clientdata_hash(assert, cdh->body, cdh->len); | ||
252 | fido_assert_set_rp(assert, rp_id); | ||
253 | fido_assert_set_hmac_salt(assert, cred->body, cred->len); | ||
254 | |||
255 | if (strlen(pin) == 0) | ||
256 | pin = NULL; | ||
257 | |||
184 | fido_dev_get_assert(dev, assert, u2f & 1 ? NULL : pin); | 258 | fido_dev_get_assert(dev, assert, u2f & 1 ? NULL : pin); |
185 | 259 | ||
186 | fido_dev_cancel(dev); | 260 | fido_dev_cancel(dev); |
@@ -194,7 +268,7 @@ verify_assert(int type, const unsigned char *cdh_ptr, size_t cdh_len, | |||
194 | const unsigned char *sig_ptr, size_t sig_len, uint8_t up, uint8_t uv, | 268 | const unsigned char *sig_ptr, size_t sig_len, uint8_t up, uint8_t uv, |
195 | int ext, void *pk) | 269 | int ext, void *pk) |
196 | { | 270 | { |
197 | fido_assert_t *assert = NULL; | 271 | fido_assert_t *assert = NULL; |
198 | 272 | ||
199 | if ((assert = fido_assert_new()) == NULL) | 273 | if ((assert = fido_assert_new()) == NULL) |
200 | return; | 274 | return; |
@@ -202,16 +276,30 @@ verify_assert(int type, const unsigned char *cdh_ptr, size_t cdh_len, | |||
202 | fido_assert_set_clientdata_hash(assert, cdh_ptr, cdh_len); | 276 | fido_assert_set_clientdata_hash(assert, cdh_ptr, cdh_len); |
203 | fido_assert_set_rp(assert, rp_id); | 277 | fido_assert_set_rp(assert, rp_id); |
204 | fido_assert_set_count(assert, 1); | 278 | fido_assert_set_count(assert, 1); |
279 | |||
205 | if (fido_assert_set_authdata(assert, 0, authdata_ptr, | 280 | if (fido_assert_set_authdata(assert, 0, authdata_ptr, |
206 | authdata_len) != FIDO_OK) { | 281 | authdata_len) != FIDO_OK) { |
207 | fido_assert_set_authdata_raw(assert, 0, authdata_ptr, | 282 | fido_assert_set_authdata_raw(assert, 0, authdata_ptr, |
208 | authdata_len); | 283 | authdata_len); |
209 | } | 284 | } |
285 | |||
286 | if (up & 1) | ||
287 | fido_assert_set_up(assert, FIDO_OPT_TRUE); | ||
288 | if (uv & 1) | ||
289 | fido_assert_set_uv(assert, FIDO_OPT_TRUE); | ||
290 | |||
210 | fido_assert_set_extensions(assert, ext); | 291 | fido_assert_set_extensions(assert, ext); |
211 | if (up & 1) fido_assert_set_up(assert, FIDO_OPT_TRUE); | ||
212 | if (uv & 1) fido_assert_set_uv(assert, FIDO_OPT_TRUE); | ||
213 | fido_assert_set_sig(assert, 0, sig_ptr, sig_len); | 292 | fido_assert_set_sig(assert, 0, sig_ptr, sig_len); |
214 | fido_assert_verify(assert, 0, type, pk); | 293 | |
294 | /* repeat memory operations to trigger reallocation paths */ | ||
295 | if (fido_assert_set_authdata(assert, 0, authdata_ptr, | ||
296 | authdata_len) != FIDO_OK) { | ||
297 | fido_assert_set_authdata_raw(assert, 0, authdata_ptr, | ||
298 | authdata_len); | ||
299 | } | ||
300 | fido_assert_set_sig(assert, 0, sig_ptr, sig_len); | ||
301 | |||
302 | assert(fido_assert_verify(assert, 0, type, pk) != FIDO_OK); | ||
215 | 303 | ||
216 | fido_assert_free(&assert); | 304 | fido_assert_free(&assert); |
217 | } | 305 | } |
@@ -262,38 +350,30 @@ out: | |||
262 | EVP_PKEY_free(pkey); | 350 | EVP_PKEY_free(pkey); |
263 | } | 351 | } |
264 | 352 | ||
265 | int | 353 | void |
266 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | 354 | test(const struct param *p) |
267 | { | 355 | { |
268 | struct param p; | 356 | fido_assert_t *assert = NULL; |
269 | fido_assert_t *assert = NULL; | 357 | es256_pk_t *es256_pk = NULL; |
270 | es256_pk_t *es256_pk = NULL; | 358 | rs256_pk_t *rs256_pk = NULL; |
271 | rs256_pk_t *rs256_pk = NULL; | 359 | eddsa_pk_t *eddsa_pk = NULL; |
272 | eddsa_pk_t *eddsa_pk = NULL; | 360 | uint8_t flags; |
273 | uint8_t flags; | 361 | uint32_t sigcount; |
274 | uint32_t sigcount; | 362 | int cose_alg = 0; |
275 | int cose_alg = 0; | 363 | void *pk; |
276 | void *pk; | 364 | |
277 | 365 | prng_init((unsigned int)p->seed); | |
278 | memset(&p, 0, sizeof(p)); | ||
279 | |||
280 | if (size < input_len(GETLEN_MIN) || size > input_len(GETLEN_MAX) || | ||
281 | unpack(data, size, &p) < 0) | ||
282 | return (0); | ||
283 | |||
284 | prng_init((unsigned int)p.seed); | ||
285 | |||
286 | fido_init(FIDO_DEBUG); | 366 | fido_init(FIDO_DEBUG); |
287 | fido_set_log_handler(consume_str); | 367 | fido_set_log_handler(consume_str); |
288 | 368 | ||
289 | switch (p.type & 3) { | 369 | switch (p->type & 3) { |
290 | case 0: | 370 | case 0: |
291 | cose_alg = COSE_ES256; | 371 | cose_alg = COSE_ES256; |
292 | 372 | ||
293 | if ((es256_pk = es256_pk_new()) == NULL) | 373 | if ((es256_pk = es256_pk_new()) == NULL) |
294 | return (0); | 374 | return; |
295 | 375 | ||
296 | es256_pk_from_ptr(es256_pk, p.es256.body, p.es256.len); | 376 | es256_pk_from_ptr(es256_pk, p->es256.body, p->es256.len); |
297 | pk = es256_pk; | 377 | pk = es256_pk; |
298 | 378 | ||
299 | break; | 379 | break; |
@@ -301,9 +381,9 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | |||
301 | cose_alg = COSE_RS256; | 381 | cose_alg = COSE_RS256; |
302 | 382 | ||
303 | if ((rs256_pk = rs256_pk_new()) == NULL) | 383 | if ((rs256_pk = rs256_pk_new()) == NULL) |
304 | return (0); | 384 | return; |
305 | 385 | ||
306 | rs256_pk_from_ptr(rs256_pk, p.rs256.body, p.rs256.len); | 386 | rs256_pk_from_ptr(rs256_pk, p->rs256.body, p->rs256.len); |
307 | pk = rs256_pk; | 387 | pk = rs256_pk; |
308 | 388 | ||
309 | rs256_convert(pk); | 389 | rs256_convert(pk); |
@@ -313,9 +393,9 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | |||
313 | cose_alg = COSE_EDDSA; | 393 | cose_alg = COSE_EDDSA; |
314 | 394 | ||
315 | if ((eddsa_pk = eddsa_pk_new()) == NULL) | 395 | if ((eddsa_pk = eddsa_pk_new()) == NULL) |
316 | return (0); | 396 | return; |
317 | 397 | ||
318 | eddsa_pk_from_ptr(eddsa_pk, p.eddsa.body, p.eddsa.len); | 398 | eddsa_pk_from_ptr(eddsa_pk, p->eddsa.body, p->eddsa.len); |
319 | pk = eddsa_pk; | 399 | pk = eddsa_pk; |
320 | 400 | ||
321 | eddsa_convert(pk); | 401 | eddsa_convert(pk); |
@@ -326,10 +406,10 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | |||
326 | if ((assert = fido_assert_new()) == NULL) | 406 | if ((assert = fido_assert_new()) == NULL) |
327 | goto out; | 407 | goto out; |
328 | 408 | ||
329 | set_wire_data(p.wire_data.body, p.wire_data.len); | 409 | set_wire_data(p->wire_data.body, p->wire_data.len); |
330 | 410 | ||
331 | get_assert(assert, p.u2f, &p.cdh, p.rp_id, p.ext, p.up, p.uv, p.pin, | 411 | get_assert(assert, p->u2f, &p->cdh, p->rp_id, p->ext, p->up, p->uv, |
332 | p.cred_count, &p.cred); | 412 | p->pin, p->cred_count, &p->cred); |
333 | 413 | ||
334 | /* XXX +1 on purpose */ | 414 | /* XXX +1 on purpose */ |
335 | for (size_t i = 0; i <= fido_assert_count(assert); i++) { | 415 | for (size_t i = 0; i <= fido_assert_count(assert); i++) { |
@@ -340,7 +420,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | |||
340 | fido_assert_authdata_ptr(assert, i), | 420 | fido_assert_authdata_ptr(assert, i), |
341 | fido_assert_authdata_len(assert, i), | 421 | fido_assert_authdata_len(assert, i), |
342 | fido_assert_sig_ptr(assert, i), | 422 | fido_assert_sig_ptr(assert, i), |
343 | fido_assert_sig_len(assert, i), p.up, p.uv, p.ext, pk); | 423 | fido_assert_sig_len(assert, i), p->up, p->uv, p->ext, pk); |
344 | consume(fido_assert_id_ptr(assert, i), | 424 | consume(fido_assert_id_ptr(assert, i), |
345 | fido_assert_id_len(assert, i)); | 425 | fido_assert_id_len(assert, i)); |
346 | consume(fido_assert_user_id_ptr(assert, i), | 426 | consume(fido_assert_user_id_ptr(assert, i), |
@@ -365,103 +445,40 @@ out: | |||
365 | eddsa_pk_free(&eddsa_pk); | 445 | eddsa_pk_free(&eddsa_pk); |
366 | 446 | ||
367 | fido_assert_free(&assert); | 447 | fido_assert_free(&assert); |
368 | |||
369 | return (0); | ||
370 | } | 448 | } |
371 | 449 | ||
372 | static size_t | 450 | void |
373 | pack_dummy(uint8_t *ptr, size_t len) | 451 | mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN |
374 | { | 452 | { |
375 | struct param dummy; | 453 | if (flags & MUTATE_SEED) |
376 | uint8_t blob[16384]; | 454 | p->seed = (int)seed; |
377 | size_t blob_len; | 455 | |
378 | 456 | if (flags & MUTATE_PARAM) { | |
379 | memset(&dummy, 0, sizeof(dummy)); | 457 | mutate_byte(&p->uv); |
380 | 458 | mutate_byte(&p->up); | |
381 | dummy.type = 1; /* rsa */ | 459 | mutate_byte(&p->u2f); |
382 | dummy.ext = FIDO_EXT_HMAC_SECRET; | 460 | mutate_byte(&p->type); |
383 | 461 | mutate_byte(&p->cred_count); | |
384 | strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); | 462 | mutate_int(&p->ext); |
385 | strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id)); | 463 | mutate_blob(&p->rs256); |
386 | 464 | mutate_blob(&p->es256); | |
387 | dummy.cred.len = sizeof(dummy_cdh); /* XXX */ | 465 | mutate_blob(&p->eddsa); |
388 | dummy.cdh.len = sizeof(dummy_cdh); | 466 | mutate_blob(&p->cred); |
389 | dummy.es256.len = sizeof(dummy_es256); | 467 | mutate_blob(&p->cdh); |
390 | dummy.rs256.len = sizeof(dummy_rs256); | 468 | mutate_string(p->rp_id); |
391 | dummy.eddsa.len = sizeof(dummy_eddsa); | 469 | mutate_string(p->pin); |
392 | dummy.wire_data.len = sizeof(dummy_wire_data_fido); | ||
393 | |||
394 | memcpy(&dummy.cred.body, &dummy_cdh, dummy.cred.len); /* XXX */ | ||
395 | memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len); | ||
396 | memcpy(&dummy.wire_data.body, &dummy_wire_data_fido, | ||
397 | dummy.wire_data.len); | ||
398 | memcpy(&dummy.es256.body, &dummy_es256, dummy.es256.len); | ||
399 | memcpy(&dummy.rs256.body, &dummy_rs256, dummy.rs256.len); | ||
400 | memcpy(&dummy.eddsa.body, &dummy_eddsa, dummy.eddsa.len); | ||
401 | |||
402 | blob_len = pack(blob, sizeof(blob), &dummy); | ||
403 | assert(blob_len != 0); | ||
404 | |||
405 | if (blob_len > len) { | ||
406 | memcpy(ptr, blob, len); | ||
407 | return (len); | ||
408 | } | 470 | } |
409 | 471 | ||
410 | memcpy(ptr, blob, blob_len); | 472 | if (flags & MUTATE_WIREDATA) { |
411 | 473 | if (p->u2f & 1) { | |
412 | return (blob_len); | 474 | p->wire_data.len = sizeof(dummy_wire_data_u2f); |
413 | } | 475 | memcpy(&p->wire_data.body, &dummy_wire_data_u2f, |
414 | 476 | p->wire_data.len); | |
415 | size_t | 477 | } else { |
416 | LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize, | 478 | p->wire_data.len = sizeof(dummy_wire_data_fido); |
417 | unsigned int seed) NO_MSAN | 479 | memcpy(&p->wire_data.body, &dummy_wire_data_fido, |
418 | { | 480 | p->wire_data.len); |
419 | struct param p; | 481 | } |
420 | uint8_t blob[16384]; | 482 | mutate_blob(&p->wire_data); |
421 | size_t blob_len; | ||
422 | |||
423 | (void)seed; | ||
424 | |||
425 | memset(&p, 0, sizeof(p)); | ||
426 | |||
427 | if (unpack(data, size, &p) < 0) | ||
428 | return (pack_dummy(data, maxsize)); | ||
429 | |||
430 | mutate_byte(&p.uv); | ||
431 | mutate_byte(&p.up); | ||
432 | mutate_byte(&p.u2f); | ||
433 | mutate_byte(&p.type); | ||
434 | mutate_byte(&p.cred_count); | ||
435 | |||
436 | mutate_int(&p.ext); | ||
437 | p.seed = (int)seed; | ||
438 | |||
439 | if (p.u2f & 1) { | ||
440 | p.wire_data.len = sizeof(dummy_wire_data_u2f); | ||
441 | memcpy(&p.wire_data.body, &dummy_wire_data_u2f, | ||
442 | p.wire_data.len); | ||
443 | } else { | ||
444 | p.wire_data.len = sizeof(dummy_wire_data_fido); | ||
445 | memcpy(&p.wire_data.body, &dummy_wire_data_fido, | ||
446 | p.wire_data.len); | ||
447 | } | 483 | } |
448 | |||
449 | mutate_blob(&p.wire_data); | ||
450 | mutate_blob(&p.rs256); | ||
451 | mutate_blob(&p.es256); | ||
452 | mutate_blob(&p.eddsa); | ||
453 | mutate_blob(&p.cred); | ||
454 | mutate_blob(&p.cdh); | ||
455 | |||
456 | mutate_string(p.rp_id); | ||
457 | mutate_string(p.pin); | ||
458 | |||
459 | blob_len = pack(blob, sizeof(blob), &p); | ||
460 | |||
461 | if (blob_len == 0 || blob_len > maxsize) | ||
462 | return (0); | ||
463 | |||
464 | memcpy(data, blob, blob_len); | ||
465 | |||
466 | return (blob_len); | ||
467 | } | 484 | } |
diff --git a/fuzz/fuzz_bio.c b/fuzz/fuzz_bio.c index 05f6ce3..5051a34 100644 --- a/fuzz/fuzz_bio.c +++ b/fuzz/fuzz_bio.c | |||
@@ -19,27 +19,17 @@ | |||
19 | 19 | ||
20 | #include "../openbsd-compat/openbsd-compat.h" | 20 | #include "../openbsd-compat/openbsd-compat.h" |
21 | 21 | ||
22 | #define TAG_PIN 0x01 | ||
23 | #define TAG_NAME 0x02 | ||
24 | #define TAG_SEED 0x03 | ||
25 | #define TAG_ID 0x04 | ||
26 | #define TAG_INFO_WIRE_DATA 0x05 | ||
27 | #define TAG_ENROLL_WIRE_DATA 0x06 | ||
28 | #define TAG_LIST_WIRE_DATA 0x07 | ||
29 | #define TAG_SET_NAME_WIRE_DATA 0x08 | ||
30 | #define TAG_REMOVE_WIRE_DATA 0x09 | ||
31 | |||
32 | /* Parameter set defining a FIDO2 credential management operation. */ | 22 | /* Parameter set defining a FIDO2 credential management operation. */ |
33 | struct param { | 23 | struct param { |
34 | char pin[MAXSTR]; | 24 | char pin[MAXSTR]; |
35 | char name[MAXSTR]; | 25 | char name[MAXSTR]; |
36 | int seed; | 26 | int seed; |
37 | struct blob id; | 27 | struct blob id; |
38 | struct blob info_wire_data; | 28 | struct blob info_wire_data; |
39 | struct blob enroll_wire_data; | 29 | struct blob enroll_wire_data; |
40 | struct blob list_wire_data; | 30 | struct blob list_wire_data; |
41 | struct blob set_name_wire_data; | 31 | struct blob set_name_wire_data; |
42 | struct blob remove_wire_data; | 32 | struct blob remove_wire_data; |
43 | }; | 33 | }; |
44 | 34 | ||
45 | /* | 35 | /* |
@@ -100,58 +90,141 @@ static const uint8_t dummy_remove_wire_data[] = { | |||
100 | WIREDATA_CTAP_CBOR_STATUS, | 90 | WIREDATA_CTAP_CBOR_STATUS, |
101 | }; | 91 | }; |
102 | 92 | ||
103 | int LLVMFuzzerTestOneInput(const uint8_t *, size_t); | 93 | struct param * |
104 | size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int); | 94 | unpack(const uint8_t *ptr, size_t len) |
105 | |||
106 | static int | ||
107 | unpack(const uint8_t *ptr, size_t len, struct param *p) NO_MSAN | ||
108 | { | 95 | { |
109 | uint8_t **pp = (void *)&ptr; | 96 | cbor_item_t *item = NULL, **v; |
110 | 97 | struct cbor_load_result cbor; | |
111 | if (unpack_string(TAG_PIN, pp, &len, p->pin) < 0 || | 98 | struct param *p; |
112 | unpack_string(TAG_NAME, pp, &len, p->name) < 0 || | 99 | int ok = -1; |
113 | unpack_int(TAG_SEED, pp, &len, &p->seed) < 0 || | 100 | |
114 | unpack_blob(TAG_ID, pp, &len, &p->id) < 0 || | 101 | if ((p = calloc(1, sizeof(*p))) == NULL || |
115 | unpack_blob(TAG_INFO_WIRE_DATA, pp, &len, &p->info_wire_data) < 0 || | 102 | (item = cbor_load(ptr, len, &cbor)) == NULL || |
116 | unpack_blob(TAG_ENROLL_WIRE_DATA, pp, &len, &p->enroll_wire_data) < 0 || | 103 | cbor.read != len || |
117 | unpack_blob(TAG_LIST_WIRE_DATA, pp, &len, &p->list_wire_data) < 0 || | 104 | cbor_isa_array(item) == false || |
118 | unpack_blob(TAG_SET_NAME_WIRE_DATA, pp, &len, &p->set_name_wire_data) < 0 || | 105 | cbor_array_is_definite(item) == false || |
119 | unpack_blob(TAG_REMOVE_WIRE_DATA, pp, &len, &p->remove_wire_data) < 0) | 106 | cbor_array_size(item) != 9 || |
120 | return (-1); | 107 | (v = cbor_array_handle(item)) == NULL) |
121 | 108 | goto fail; | |
122 | return (0); | 109 | |
110 | if (unpack_int(v[0], &p->seed) < 0 || | ||
111 | unpack_string(v[1], p->pin) < 0 || | ||
112 | unpack_string(v[2], p->name) < 0 || | ||
113 | unpack_blob(v[3], &p->id) < 0 || | ||
114 | unpack_blob(v[4], &p->info_wire_data) < 0 || | ||
115 | unpack_blob(v[5], &p->enroll_wire_data) < 0 || | ||
116 | unpack_blob(v[6], &p->list_wire_data) < 0 || | ||
117 | unpack_blob(v[7], &p->set_name_wire_data) < 0 || | ||
118 | unpack_blob(v[8], &p->remove_wire_data) < 0) | ||
119 | goto fail; | ||
120 | |||
121 | ok = 0; | ||
122 | fail: | ||
123 | if (ok < 0) { | ||
124 | free(p); | ||
125 | p = NULL; | ||
126 | } | ||
127 | |||
128 | if (item) | ||
129 | cbor_decref(&item); | ||
130 | |||
131 | return p; | ||
123 | } | 132 | } |
124 | 133 | ||
125 | static size_t | 134 | size_t |
126 | pack(uint8_t *ptr, size_t len, const struct param *p) | 135 | pack(uint8_t *ptr, size_t len, const struct param *p) |
127 | { | 136 | { |
128 | const size_t max = len; | 137 | cbor_item_t *argv[9], *array = NULL; |
129 | 138 | size_t cbor_alloc_len, cbor_len = 0; | |
130 | if (pack_string(TAG_PIN, &ptr, &len, p->pin) < 0 || | 139 | unsigned char *cbor = NULL; |
131 | pack_string(TAG_NAME, &ptr, &len, p->name) < 0 || | 140 | |
132 | pack_int(TAG_SEED, &ptr, &len, p->seed) < 0 || | 141 | memset(argv, 0, sizeof(argv)); |
133 | pack_blob(TAG_ID, &ptr, &len, &p->id) < 0 || | 142 | |
134 | pack_blob(TAG_INFO_WIRE_DATA, &ptr, &len, &p->info_wire_data) < 0 || | 143 | if ((array = cbor_new_definite_array(9)) == NULL || |
135 | pack_blob(TAG_ENROLL_WIRE_DATA, &ptr, &len, &p->enroll_wire_data) < 0 || | 144 | (argv[0] = pack_int(p->seed)) == NULL || |
136 | pack_blob(TAG_LIST_WIRE_DATA, &ptr, &len, &p->list_wire_data) < 0 || | 145 | (argv[1] = pack_string(p->pin)) == NULL || |
137 | pack_blob(TAG_SET_NAME_WIRE_DATA, &ptr, &len, &p->set_name_wire_data) < 0 || | 146 | (argv[2] = pack_string(p->name)) == NULL || |
138 | pack_blob(TAG_REMOVE_WIRE_DATA, &ptr, &len, &p->remove_wire_data) < 0) | 147 | (argv[3] = pack_blob(&p->id)) == NULL || |
139 | return (0); | 148 | (argv[4] = pack_blob(&p->info_wire_data)) == NULL || |
140 | 149 | (argv[5] = pack_blob(&p->enroll_wire_data)) == NULL || | |
141 | return (max - len); | 150 | (argv[6] = pack_blob(&p->list_wire_data)) == NULL || |
151 | (argv[7] = pack_blob(&p->set_name_wire_data)) == NULL || | ||
152 | (argv[8] = pack_blob(&p->remove_wire_data)) == NULL) | ||
153 | goto fail; | ||
154 | |||
155 | for (size_t i = 0; i < 9; i++) | ||
156 | if (cbor_array_push(array, argv[i]) == false) | ||
157 | goto fail; | ||
158 | |||
159 | if ((cbor_len = cbor_serialize_alloc(array, &cbor, | ||
160 | &cbor_alloc_len)) > len) { | ||
161 | cbor_len = 0; | ||
162 | goto fail; | ||
163 | } | ||
164 | |||
165 | memcpy(ptr, cbor, cbor_len); | ||
166 | fail: | ||
167 | for (size_t i = 0; i < 9; i++) | ||
168 | if (argv[i]) | ||
169 | cbor_decref(&argv[i]); | ||
170 | |||
171 | if (array) | ||
172 | cbor_decref(&array); | ||
173 | |||
174 | free(cbor); | ||
175 | |||
176 | return cbor_len; | ||
142 | } | 177 | } |
143 | 178 | ||
144 | static size_t | 179 | size_t |
145 | input_len(int max) | 180 | pack_dummy(uint8_t *ptr, size_t len) |
146 | { | 181 | { |
147 | return (2 * len_string(max) + len_int() + 6 * len_blob(max)); | 182 | struct param dummy; |
183 | uint8_t blob[4096]; | ||
184 | size_t blob_len; | ||
185 | |||
186 | memset(&dummy, 0, sizeof(dummy)); | ||
187 | |||
188 | strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); | ||
189 | strlcpy(dummy.name, dummy_name, sizeof(dummy.name)); | ||
190 | |||
191 | dummy.info_wire_data.len = sizeof(dummy_info_wire_data); | ||
192 | dummy.enroll_wire_data.len = sizeof(dummy_enroll_wire_data); | ||
193 | dummy.list_wire_data.len = sizeof(dummy_list_wire_data); | ||
194 | dummy.set_name_wire_data.len = sizeof(dummy_set_name_wire_data); | ||
195 | dummy.remove_wire_data.len = sizeof(dummy_remove_wire_data); | ||
196 | dummy.id.len = sizeof(dummy_id); | ||
197 | |||
198 | memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data, | ||
199 | dummy.info_wire_data.len); | ||
200 | memcpy(&dummy.enroll_wire_data.body, &dummy_enroll_wire_data, | ||
201 | dummy.enroll_wire_data.len); | ||
202 | memcpy(&dummy.list_wire_data.body, &dummy_list_wire_data, | ||
203 | dummy.list_wire_data.len); | ||
204 | memcpy(&dummy.set_name_wire_data.body, &dummy_set_name_wire_data, | ||
205 | dummy.set_name_wire_data.len); | ||
206 | memcpy(&dummy.remove_wire_data.body, &dummy_remove_wire_data, | ||
207 | dummy.remove_wire_data.len); | ||
208 | memcpy(&dummy.id.body, &dummy_id, dummy.id.len); | ||
209 | |||
210 | assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); | ||
211 | |||
212 | if (blob_len > len) { | ||
213 | memcpy(ptr, blob, len); | ||
214 | return len; | ||
215 | } | ||
216 | |||
217 | memcpy(ptr, blob, blob_len); | ||
218 | |||
219 | return blob_len; | ||
148 | } | 220 | } |
149 | 221 | ||
150 | static fido_dev_t * | 222 | static fido_dev_t * |
151 | prepare_dev() | 223 | prepare_dev(void) |
152 | { | 224 | { |
153 | fido_dev_t *dev; | 225 | fido_dev_t *dev; |
154 | fido_dev_io_t io; | 226 | fido_dev_io_t io; |
227 | bool x; | ||
155 | 228 | ||
156 | memset(&io, 0, sizeof(io)); | 229 | memset(&io, 0, sizeof(io)); |
157 | 230 | ||
@@ -163,26 +236,35 @@ prepare_dev() | |||
163 | if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev, | 236 | if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev, |
164 | &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) { | 237 | &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) { |
165 | fido_dev_free(&dev); | 238 | fido_dev_free(&dev); |
166 | return (NULL); | 239 | return NULL; |
167 | } | 240 | } |
168 | 241 | ||
169 | return (dev); | 242 | x = fido_dev_is_fido2(dev); |
243 | consume(&x, sizeof(x)); | ||
244 | x = fido_dev_supports_pin(dev); | ||
245 | consume(&x, sizeof(x)); | ||
246 | x = fido_dev_has_pin(dev); | ||
247 | consume(&x, sizeof(x)); | ||
248 | |||
249 | return dev; | ||
170 | } | 250 | } |
171 | 251 | ||
172 | static void | 252 | static void |
173 | get_info(struct param *p) | 253 | get_info(const struct param *p) |
174 | { | 254 | { |
175 | fido_dev_t *dev = NULL; | 255 | fido_dev_t *dev = NULL; |
176 | fido_bio_info_t *i = NULL; | 256 | fido_bio_info_t *i = NULL; |
177 | uint8_t type; | 257 | uint8_t type; |
178 | uint8_t max_samples; | 258 | uint8_t max_samples; |
259 | int r; | ||
179 | 260 | ||
180 | set_wire_data(p->info_wire_data.body, p->info_wire_data.len); | 261 | set_wire_data(p->info_wire_data.body, p->info_wire_data.len); |
181 | 262 | ||
182 | if ((dev = prepare_dev()) == NULL || (i = fido_bio_info_new()) == NULL) | 263 | if ((dev = prepare_dev()) == NULL || (i = fido_bio_info_new()) == NULL) |
183 | goto done; | 264 | goto done; |
184 | 265 | ||
185 | fido_bio_dev_get_info(dev, i); | 266 | r = fido_bio_dev_get_info(dev, i); |
267 | consume_str(fido_strerr(r)); | ||
186 | 268 | ||
187 | type = fido_bio_info_type(i); | 269 | type = fido_bio_info_type(i); |
188 | max_samples = fido_bio_info_max_samples(i); | 270 | max_samples = fido_bio_info_max_samples(i); |
@@ -217,7 +299,7 @@ consume_enroll(fido_bio_enroll_t *e) | |||
217 | } | 299 | } |
218 | 300 | ||
219 | static void | 301 | static void |
220 | enroll(struct param *p) | 302 | enroll(const struct param *p) |
221 | { | 303 | { |
222 | fido_dev_t *dev = NULL; | 304 | fido_dev_t *dev = NULL; |
223 | fido_bio_template_t *t = NULL; | 305 | fido_bio_template_t *t = NULL; |
@@ -252,7 +334,7 @@ done: | |||
252 | } | 334 | } |
253 | 335 | ||
254 | static void | 336 | static void |
255 | list(struct param *p) | 337 | list(const struct param *p) |
256 | { | 338 | { |
257 | fido_dev_t *dev = NULL; | 339 | fido_dev_t *dev = NULL; |
258 | fido_bio_template_array_t *ta = NULL; | 340 | fido_bio_template_array_t *ta = NULL; |
@@ -280,7 +362,7 @@ done: | |||
280 | } | 362 | } |
281 | 363 | ||
282 | static void | 364 | static void |
283 | set_name(struct param *p) | 365 | set_name(const struct param *p) |
284 | { | 366 | { |
285 | fido_dev_t *dev = NULL; | 367 | fido_dev_t *dev = NULL; |
286 | fido_bio_template_t *t = NULL; | 368 | fido_bio_template_t *t = NULL; |
@@ -306,10 +388,11 @@ done: | |||
306 | } | 388 | } |
307 | 389 | ||
308 | static void | 390 | static void |
309 | del(struct param *p) | 391 | del(const struct param *p) |
310 | { | 392 | { |
311 | fido_dev_t *dev = NULL; | 393 | fido_dev_t *dev = NULL; |
312 | fido_bio_template_t *t = NULL; | 394 | fido_bio_template_t *t = NULL; |
395 | int r; | ||
313 | 396 | ||
314 | set_wire_data(p->remove_wire_data.body, p->remove_wire_data.len); | 397 | set_wire_data(p->remove_wire_data.body, p->remove_wire_data.len); |
315 | 398 | ||
@@ -317,8 +400,9 @@ del(struct param *p) | |||
317 | (t = fido_bio_template_new()) == NULL) | 400 | (t = fido_bio_template_new()) == NULL) |
318 | goto done; | 401 | goto done; |
319 | 402 | ||
320 | fido_bio_template_set_id(t, p->id.body, p->id.len); | 403 | r = fido_bio_template_set_id(t, p->id.body, p->id.len); |
321 | consume_template(t); | 404 | consume_template(t); |
405 | consume_str(fido_strerr(r)); | ||
322 | 406 | ||
323 | fido_bio_dev_enroll_remove(dev, t, p->pin); | 407 | fido_bio_dev_enroll_remove(dev, t, p->pin); |
324 | 408 | ||
@@ -330,106 +414,37 @@ done: | |||
330 | fido_bio_template_free(&t); | 414 | fido_bio_template_free(&t); |
331 | } | 415 | } |
332 | 416 | ||
333 | int | 417 | void |
334 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | 418 | test(const struct param *p) |
335 | { | 419 | { |
336 | struct param p; | 420 | prng_init((unsigned int)p->seed); |
337 | |||
338 | memset(&p, 0, sizeof(p)); | ||
339 | |||
340 | if (size < input_len(GETLEN_MIN) || size > input_len(GETLEN_MAX) || | ||
341 | unpack(data, size, &p) < 0) | ||
342 | return (0); | ||
343 | |||
344 | prng_init((unsigned int)p.seed); | ||
345 | |||
346 | fido_init(FIDO_DEBUG); | 421 | fido_init(FIDO_DEBUG); |
347 | fido_set_log_handler(consume_str); | 422 | fido_set_log_handler(consume_str); |
348 | 423 | ||
349 | get_info(&p); | 424 | get_info(p); |
350 | enroll(&p); | 425 | enroll(p); |
351 | list(&p); | 426 | list(p); |
352 | set_name(&p); | 427 | set_name(p); |
353 | del(&p); | 428 | del(p); |
354 | |||
355 | return (0); | ||
356 | } | 429 | } |
357 | 430 | ||
358 | static size_t | 431 | void |
359 | pack_dummy(uint8_t *ptr, size_t len) | 432 | mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN |
360 | { | 433 | { |
361 | struct param dummy; | 434 | if (flags & MUTATE_SEED) |
362 | uint8_t blob[32768]; | 435 | p->seed = (int)seed; |
363 | size_t blob_len; | ||
364 | |||
365 | memset(&dummy, 0, sizeof(dummy)); | ||
366 | |||
367 | strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); | ||
368 | strlcpy(dummy.name, dummy_name, sizeof(dummy.name)); | ||
369 | |||
370 | dummy.info_wire_data.len = sizeof(dummy_info_wire_data); | ||
371 | dummy.enroll_wire_data.len = sizeof(dummy_enroll_wire_data); | ||
372 | dummy.list_wire_data.len = sizeof(dummy_list_wire_data); | ||
373 | dummy.set_name_wire_data.len = sizeof(dummy_set_name_wire_data); | ||
374 | dummy.remove_wire_data.len = sizeof(dummy_remove_wire_data); | ||
375 | dummy.id.len = sizeof(dummy_id); | ||
376 | |||
377 | memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data, | ||
378 | dummy.info_wire_data.len); | ||
379 | memcpy(&dummy.enroll_wire_data.body, &dummy_enroll_wire_data, | ||
380 | dummy.enroll_wire_data.len); | ||
381 | memcpy(&dummy.list_wire_data.body, &dummy_list_wire_data, | ||
382 | dummy.list_wire_data.len); | ||
383 | memcpy(&dummy.set_name_wire_data.body, &dummy_set_name_wire_data, | ||
384 | dummy.set_name_wire_data.len); | ||
385 | memcpy(&dummy.remove_wire_data.body, &dummy_remove_wire_data, | ||
386 | dummy.remove_wire_data.len); | ||
387 | memcpy(&dummy.id.body, &dummy_id, dummy.id.len); | ||
388 | |||
389 | blob_len = pack(blob, sizeof(blob), &dummy); | ||
390 | assert(blob_len != 0); | ||
391 | 436 | ||
392 | if (blob_len > len) { | 437 | if (flags & MUTATE_PARAM) { |
393 | memcpy(ptr, blob, len); | 438 | mutate_blob(&p->id); |
394 | return (len); | 439 | mutate_string(p->pin); |
440 | mutate_string(p->name); | ||
395 | } | 441 | } |
396 | 442 | ||
397 | memcpy(ptr, blob, blob_len); | 443 | if (flags & MUTATE_WIREDATA) { |
398 | 444 | mutate_blob(&p->info_wire_data); | |
399 | return (blob_len); | 445 | mutate_blob(&p->enroll_wire_data); |
400 | } | 446 | mutate_blob(&p->list_wire_data); |
401 | 447 | mutate_blob(&p->set_name_wire_data); | |
402 | size_t | 448 | mutate_blob(&p->remove_wire_data); |
403 | LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize, | 449 | } |
404 | unsigned int seed) NO_MSAN | ||
405 | { | ||
406 | struct param p; | ||
407 | uint8_t blob[16384]; | ||
408 | size_t blob_len; | ||
409 | |||
410 | memset(&p, 0, sizeof(p)); | ||
411 | |||
412 | if (unpack(data, size, &p) < 0) | ||
413 | return (pack_dummy(data, maxsize)); | ||
414 | |||
415 | p.seed = (int)seed; | ||
416 | |||
417 | mutate_blob(&p.id); | ||
418 | mutate_blob(&p.info_wire_data); | ||
419 | mutate_blob(&p.enroll_wire_data); | ||
420 | mutate_blob(&p.list_wire_data); | ||
421 | mutate_blob(&p.set_name_wire_data); | ||
422 | mutate_blob(&p.remove_wire_data); | ||
423 | |||
424 | mutate_string(p.pin); | ||
425 | mutate_string(p.name); | ||
426 | |||
427 | blob_len = pack(blob, sizeof(blob), &p); | ||
428 | |||
429 | if (blob_len == 0 || blob_len > maxsize) | ||
430 | return (0); | ||
431 | |||
432 | memcpy(data, blob, blob_len); | ||
433 | |||
434 | return (blob_len); | ||
435 | } | 450 | } |
diff --git a/fuzz/fuzz_cred.c b/fuzz/fuzz_cred.c index cc37903..87a877a 100644 --- a/fuzz/fuzz_cred.c +++ b/fuzz/fuzz_cred.c | |||
@@ -18,43 +18,25 @@ | |||
18 | 18 | ||
19 | #include "../openbsd-compat/openbsd-compat.h" | 19 | #include "../openbsd-compat/openbsd-compat.h" |
20 | 20 | ||
21 | #define TAG_U2F 0x01 | ||
22 | #define TAG_TYPE 0x02 | ||
23 | #define TAG_CDH 0x03 | ||
24 | #define TAG_RP_ID 0x04 | ||
25 | #define TAG_RP_NAME 0x05 | ||
26 | #define TAG_USER_ID 0x06 | ||
27 | #define TAG_USER_NAME 0x07 | ||
28 | #define TAG_USER_NICK 0x08 | ||
29 | #define TAG_USER_ICON 0x09 | ||
30 | #define TAG_EXT 0x0a | ||
31 | #define TAG_SEED 0x0b | ||
32 | #define TAG_RK 0x0c | ||
33 | #define TAG_UV 0x0d | ||
34 | #define TAG_PIN 0x0e | ||
35 | #define TAG_WIRE_DATA 0x0f | ||
36 | #define TAG_EXCL_COUNT 0x10 | ||
37 | #define TAG_EXCL_CRED 0x11 | ||
38 | |||
39 | /* Parameter set defining a FIDO2 make credential operation. */ | 21 | /* Parameter set defining a FIDO2 make credential operation. */ |
40 | struct param { | 22 | struct param { |
41 | char pin[MAXSTR]; | 23 | char pin[MAXSTR]; |
42 | char rp_id[MAXSTR]; | 24 | char rp_id[MAXSTR]; |
43 | char rp_name[MAXSTR]; | 25 | char rp_name[MAXSTR]; |
44 | char user_icon[MAXSTR]; | 26 | char user_icon[MAXSTR]; |
45 | char user_name[MAXSTR]; | 27 | char user_name[MAXSTR]; |
46 | char user_nick[MAXSTR]; | 28 | char user_nick[MAXSTR]; |
47 | int ext; | 29 | int ext; |
48 | int seed; | 30 | int seed; |
49 | struct blob cdh; | 31 | struct blob cdh; |
50 | struct blob excl_cred; | 32 | struct blob excl_cred; |
51 | struct blob user_id; | 33 | struct blob user_id; |
52 | struct blob wire_data; | 34 | struct blob wire_data; |
53 | uint8_t excl_count; | 35 | uint8_t excl_count; |
54 | uint8_t rk; | 36 | uint8_t rk; |
55 | uint8_t type; | 37 | uint8_t type; |
56 | uint8_t u2f; | 38 | uint8_t u2f; |
57 | uint8_t uv; | 39 | uint8_t uv; |
58 | }; | 40 | }; |
59 | 41 | ||
60 | /* | 42 | /* |
@@ -86,79 +68,157 @@ static const uint8_t dummy_wire_data_u2f[] = { | |||
86 | WIREDATA_CTAP_U2F_REGISTER, | 68 | WIREDATA_CTAP_U2F_REGISTER, |
87 | }; | 69 | }; |
88 | 70 | ||
89 | int LLVMFuzzerTestOneInput(const uint8_t *, size_t); | 71 | struct param * |
90 | size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int); | 72 | unpack(const uint8_t *ptr, size_t len) |
91 | |||
92 | static int | ||
93 | unpack(const uint8_t *ptr, size_t len, struct param *p) NO_MSAN | ||
94 | { | 73 | { |
95 | uint8_t **pp = (void *)&ptr; | 74 | cbor_item_t *item = NULL, **v; |
96 | 75 | struct cbor_load_result cbor; | |
97 | if (unpack_byte(TAG_RK, pp, &len, &p->rk) < 0 || | 76 | struct param *p; |
98 | unpack_byte(TAG_TYPE, pp, &len, &p->type) < 0 || | 77 | int ok = -1; |
99 | unpack_byte(TAG_U2F, pp, &len, &p->u2f) < 0 || | 78 | |
100 | unpack_byte(TAG_UV, pp, &len, &p->uv) < 0 || | 79 | if ((p = calloc(1, sizeof(*p))) == NULL || |
101 | unpack_byte(TAG_EXCL_COUNT, pp, &len, &p->excl_count) < 0 || | 80 | (item = cbor_load(ptr, len, &cbor)) == NULL || |
102 | unpack_string(TAG_PIN, pp, &len, p->pin) < 0 || | 81 | cbor.read != len || |
103 | unpack_string(TAG_RP_ID, pp, &len, p->rp_id) < 0 || | 82 | cbor_isa_array(item) == false || |
104 | unpack_string(TAG_RP_NAME, pp, &len, p->rp_name) < 0 || | 83 | cbor_array_is_definite(item) == false || |
105 | unpack_string(TAG_USER_ICON, pp, &len, p->user_icon) < 0 || | 84 | cbor_array_size(item) != 17 || |
106 | unpack_string(TAG_USER_NAME, pp, &len, p->user_name) < 0 || | 85 | (v = cbor_array_handle(item)) == NULL) |
107 | unpack_string(TAG_USER_NICK, pp, &len, p->user_nick) < 0 || | 86 | goto fail; |
108 | unpack_int(TAG_EXT, pp, &len, &p->ext) < 0 || | 87 | |
109 | unpack_int(TAG_SEED, pp, &len, &p->seed) < 0 || | 88 | if (unpack_byte(v[0], &p->rk) < 0 || |
110 | unpack_blob(TAG_CDH, pp, &len, &p->cdh) < 0 || | 89 | unpack_byte(v[1], &p->type) < 0 || |
111 | unpack_blob(TAG_USER_ID, pp, &len, &p->user_id) < 0 || | 90 | unpack_byte(v[2], &p->u2f) < 0 || |
112 | unpack_blob(TAG_WIRE_DATA, pp, &len, &p->wire_data) < 0 || | 91 | unpack_byte(v[3], &p->uv) < 0 || |
113 | unpack_blob(TAG_EXCL_CRED, pp, &len, &p->excl_cred) < 0) | 92 | unpack_byte(v[4], &p->excl_count) < 0 || |
114 | return (-1); | 93 | unpack_int(v[5], &p->ext) < 0 || |
115 | 94 | unpack_int(v[6], &p->seed) < 0 || | |
116 | return (0); | 95 | unpack_string(v[7], p->pin) < 0 || |
96 | unpack_string(v[8], p->rp_id) < 0 || | ||
97 | unpack_string(v[9], p->rp_name) < 0 || | ||
98 | unpack_string(v[10], p->user_icon) < 0 || | ||
99 | unpack_string(v[11], p->user_name) < 0 || | ||
100 | unpack_string(v[12], p->user_nick) < 0 || | ||
101 | unpack_blob(v[13], &p->cdh) < 0 || | ||
102 | unpack_blob(v[14], &p->user_id) < 0 || | ||
103 | unpack_blob(v[15], &p->wire_data) < 0 || | ||
104 | unpack_blob(v[16], &p->excl_cred) < 0) | ||
105 | goto fail; | ||
106 | |||
107 | ok = 0; | ||
108 | fail: | ||
109 | if (ok < 0) { | ||
110 | free(p); | ||
111 | p = NULL; | ||
112 | } | ||
113 | |||
114 | if (item) | ||
115 | cbor_decref(&item); | ||
116 | |||
117 | return p; | ||
117 | } | 118 | } |
118 | 119 | ||
119 | static size_t | 120 | size_t |
120 | pack(uint8_t *ptr, size_t len, const struct param *p) | 121 | pack(uint8_t *ptr, size_t len, const struct param *p) |
121 | { | 122 | { |
122 | const size_t max = len; | 123 | cbor_item_t *argv[17], *array = NULL; |
123 | 124 | size_t cbor_alloc_len, cbor_len = 0; | |
124 | if (pack_byte(TAG_RK, &ptr, &len, p->rk) < 0 || | 125 | unsigned char *cbor = NULL; |
125 | pack_byte(TAG_TYPE, &ptr, &len, p->type) < 0 || | 126 | |
126 | pack_byte(TAG_U2F, &ptr, &len, p->u2f) < 0 || | 127 | memset(argv, 0, sizeof(argv)); |
127 | pack_byte(TAG_UV, &ptr, &len, p->uv) < 0 || | 128 | |
128 | pack_byte(TAG_EXCL_COUNT, &ptr, &len, p->excl_count) < 0 || | 129 | if ((array = cbor_new_definite_array(17)) == NULL || |
129 | pack_string(TAG_PIN, &ptr, &len, p->pin) < 0 || | 130 | (argv[0] = pack_byte(p->rk)) == NULL || |
130 | pack_string(TAG_RP_ID, &ptr, &len, p->rp_id) < 0 || | 131 | (argv[1] = pack_byte(p->type)) == NULL || |
131 | pack_string(TAG_RP_NAME, &ptr, &len, p->rp_name) < 0 || | 132 | (argv[2] = pack_byte(p->u2f)) == NULL || |
132 | pack_string(TAG_USER_ICON, &ptr, &len, p->user_icon) < 0 || | 133 | (argv[3] = pack_byte(p->uv)) == NULL || |
133 | pack_string(TAG_USER_NAME, &ptr, &len, p->user_name) < 0 || | 134 | (argv[4] = pack_byte(p->excl_count)) == NULL || |
134 | pack_string(TAG_USER_NICK, &ptr, &len, p->user_nick) < 0 || | 135 | (argv[5] = pack_int(p->ext)) == NULL || |
135 | pack_int(TAG_EXT, &ptr, &len, p->ext) < 0 || | 136 | (argv[6] = pack_int(p->seed)) == NULL || |
136 | pack_int(TAG_SEED, &ptr, &len, p->seed) < 0 || | 137 | (argv[7] = pack_string(p->pin)) == NULL || |
137 | pack_blob(TAG_CDH, &ptr, &len, &p->cdh) < 0 || | 138 | (argv[8] = pack_string(p->rp_id)) == NULL || |
138 | pack_blob(TAG_USER_ID, &ptr, &len, &p->user_id) < 0 || | 139 | (argv[9] = pack_string(p->rp_name)) == NULL || |
139 | pack_blob(TAG_WIRE_DATA, &ptr, &len, &p->wire_data) < 0 || | 140 | (argv[10] = pack_string(p->user_icon)) == NULL || |
140 | pack_blob(TAG_EXCL_CRED, &ptr, &len, &p->excl_cred) < 0) | 141 | (argv[11] = pack_string(p->user_name)) == NULL || |
141 | return (0); | 142 | (argv[12] = pack_string(p->user_nick)) == NULL || |
142 | 143 | (argv[13] = pack_blob(&p->cdh)) == NULL || | |
143 | return (max - len); | 144 | (argv[14] = pack_blob(&p->user_id)) == NULL || |
145 | (argv[15] = pack_blob(&p->wire_data)) == NULL || | ||
146 | (argv[16] = pack_blob(&p->excl_cred)) == NULL) | ||
147 | goto fail; | ||
148 | |||
149 | for (size_t i = 0; i < 17; i++) | ||
150 | if (cbor_array_push(array, argv[i]) == false) | ||
151 | goto fail; | ||
152 | |||
153 | if ((cbor_len = cbor_serialize_alloc(array, &cbor, | ||
154 | &cbor_alloc_len)) > len) { | ||
155 | cbor_len = 0; | ||
156 | goto fail; | ||
157 | } | ||
158 | |||
159 | memcpy(ptr, cbor, cbor_len); | ||
160 | fail: | ||
161 | for (size_t i = 0; i < 17; i++) | ||
162 | if (argv[i]) | ||
163 | cbor_decref(&argv[i]); | ||
164 | |||
165 | if (array) | ||
166 | cbor_decref(&array); | ||
167 | |||
168 | free(cbor); | ||
169 | |||
170 | return cbor_len; | ||
144 | } | 171 | } |
145 | 172 | ||
146 | static size_t | 173 | size_t |
147 | input_len(int max) | 174 | pack_dummy(uint8_t *ptr, size_t len) |
148 | { | 175 | { |
149 | return (5 * len_byte() + 6 * len_string(max) + 2 * len_int() + | 176 | struct param dummy; |
150 | 4 * len_blob(max)); | 177 | uint8_t blob[4096]; |
178 | size_t blob_len; | ||
179 | |||
180 | memset(&dummy, 0, sizeof(dummy)); | ||
181 | |||
182 | dummy.type = 1; | ||
183 | dummy.ext = FIDO_EXT_HMAC_SECRET; | ||
184 | |||
185 | strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); | ||
186 | strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id)); | ||
187 | strlcpy(dummy.rp_name, dummy_rp_name, sizeof(dummy.rp_name)); | ||
188 | strlcpy(dummy.user_icon, dummy_user_icon, sizeof(dummy.user_icon)); | ||
189 | strlcpy(dummy.user_name, dummy_user_name, sizeof(dummy.user_name)); | ||
190 | strlcpy(dummy.user_nick, dummy_user_nick, sizeof(dummy.user_nick)); | ||
191 | |||
192 | dummy.cdh.len = sizeof(dummy_cdh); | ||
193 | dummy.user_id.len = sizeof(dummy_user_id); | ||
194 | dummy.wire_data.len = sizeof(dummy_wire_data_fido); | ||
195 | |||
196 | memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len); | ||
197 | memcpy(&dummy.user_id.body, &dummy_user_id, dummy.user_id.len); | ||
198 | memcpy(&dummy.wire_data.body, &dummy_wire_data_fido, | ||
199 | dummy.wire_data.len); | ||
200 | |||
201 | assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); | ||
202 | |||
203 | if (blob_len > len) { | ||
204 | memcpy(ptr, blob, len); | ||
205 | return len; | ||
206 | } | ||
207 | |||
208 | memcpy(ptr, blob, blob_len); | ||
209 | |||
210 | return blob_len; | ||
151 | } | 211 | } |
152 | 212 | ||
153 | static void | 213 | static void |
154 | make_cred(fido_cred_t *cred, uint8_t u2f, int type, const struct blob *cdh, | 214 | make_cred(fido_cred_t *cred, uint8_t u2f, int type, const struct blob *cdh, |
155 | const char *rp_id, const char *rp_name, struct blob *user_id, | 215 | const char *rp_id, const char *rp_name, const struct blob *user_id, |
156 | const char *user_name, const char *user_nick, const char *user_icon, | 216 | const char *user_name, const char *user_nick, const char *user_icon, |
157 | int ext, uint8_t rk, uint8_t uv, const char *pin, uint8_t excl_count, | 217 | int ext, uint8_t rk, uint8_t uv, const char *pin, uint8_t excl_count, |
158 | struct blob *excl_cred) | 218 | const struct blob *excl_cred) |
159 | { | 219 | { |
160 | fido_dev_t *dev; | 220 | fido_dev_t *dev; |
161 | fido_dev_io_t io; | 221 | fido_dev_io_t io; |
162 | 222 | ||
163 | memset(&io, 0, sizeof(io)); | 223 | memset(&io, 0, sizeof(io)); |
164 | 224 | ||
@@ -185,6 +245,7 @@ make_cred(fido_cred_t *cred, uint8_t u2f, int type, const struct blob *cdh, | |||
185 | fido_cred_set_user(cred, user_id->body, user_id->len, user_name, | 245 | fido_cred_set_user(cred, user_id->body, user_id->len, user_name, |
186 | user_nick, user_icon); | 246 | user_nick, user_icon); |
187 | fido_cred_set_extensions(cred, ext); | 247 | fido_cred_set_extensions(cred, ext); |
248 | |||
188 | if (rk & 1) | 249 | if (rk & 1) |
189 | fido_cred_set_rk(cred, FIDO_OPT_TRUE); | 250 | fido_cred_set_rk(cred, FIDO_OPT_TRUE); |
190 | if (uv & 1) | 251 | if (uv & 1) |
@@ -192,6 +253,16 @@ make_cred(fido_cred_t *cred, uint8_t u2f, int type, const struct blob *cdh, | |||
192 | if (user_id->len) | 253 | if (user_id->len) |
193 | fido_cred_set_prot(cred, user_id->body[0] & 0x03); | 254 | fido_cred_set_prot(cred, user_id->body[0] & 0x03); |
194 | 255 | ||
256 | /* repeat memory operations to trigger reallocation paths */ | ||
257 | fido_cred_set_type(cred, type); | ||
258 | fido_cred_set_clientdata_hash(cred, cdh->body, cdh->len); | ||
259 | fido_cred_set_rp(cred, rp_id, rp_name); | ||
260 | fido_cred_set_user(cred, user_id->body, user_id->len, user_name, | ||
261 | user_nick, user_icon); | ||
262 | |||
263 | if (strlen(pin) == 0) | ||
264 | pin = NULL; | ||
265 | |||
195 | fido_dev_make_cred(dev, cred, u2f & 1 ? NULL : pin); | 266 | fido_dev_make_cred(dev, cred, u2f & 1 ? NULL : pin); |
196 | 267 | ||
197 | fido_dev_cancel(dev); | 268 | fido_dev_cancel(dev); |
@@ -206,8 +277,8 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len, | |||
206 | const unsigned char *x5c_ptr, size_t x5c_len, const unsigned char *sig_ptr, | 277 | const unsigned char *x5c_ptr, size_t x5c_len, const unsigned char *sig_ptr, |
207 | size_t sig_len, const char *fmt, int prot) | 278 | size_t sig_len, const char *fmt, int prot) |
208 | { | 279 | { |
209 | fido_cred_t *cred; | 280 | fido_cred_t *cred; |
210 | uint8_t flags; | 281 | uint8_t flags; |
211 | 282 | ||
212 | if ((cred = fido_cred_new()) == NULL) | 283 | if ((cred = fido_cred_new()) == NULL) |
213 | return; | 284 | return; |
@@ -229,11 +300,18 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len, | |||
229 | if (fmt) | 300 | if (fmt) |
230 | fido_cred_set_fmt(cred, fmt); | 301 | fido_cred_set_fmt(cred, fmt); |
231 | 302 | ||
232 | fido_cred_verify(cred); | 303 | /* repeat memory operations to trigger reallocation paths */ |
233 | fido_cred_verify_self(cred); | 304 | if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK) |
305 | fido_cred_set_authdata_raw(cred, authdata_ptr, authdata_len); | ||
306 | fido_cred_set_x509(cred, x5c_ptr, x5c_len); | ||
307 | fido_cred_set_sig(cred, sig_ptr, sig_len); | ||
308 | |||
309 | assert(fido_cred_verify(cred) != FIDO_OK); | ||
310 | assert(fido_cred_verify_self(cred) != FIDO_OK); | ||
234 | 311 | ||
235 | consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred)); | 312 | consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred)); |
236 | consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred)); | 313 | consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred)); |
314 | consume(fido_cred_aaguid_ptr(cred), fido_cred_aaguid_len(cred)); | ||
237 | consume(fido_cred_user_id_ptr(cred), fido_cred_user_id_len(cred)); | 315 | consume(fido_cred_user_id_ptr(cred), fido_cred_user_id_len(cred)); |
238 | consume(fido_cred_user_name(cred), xstrlen(fido_cred_user_name(cred))); | 316 | consume(fido_cred_user_name(cred), xstrlen(fido_cred_user_name(cred))); |
239 | consume(fido_cred_display_name(cred), | 317 | consume(fido_cred_display_name(cred), |
@@ -247,30 +325,16 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len, | |||
247 | fido_cred_free(&cred); | 325 | fido_cred_free(&cred); |
248 | } | 326 | } |
249 | 327 | ||
250 | int | 328 | static void |
251 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | 329 | test_cred(const struct param *p) |
252 | { | 330 | { |
253 | struct param p; | 331 | fido_cred_t *cred = NULL; |
254 | fido_cred_t *cred = NULL; | 332 | int cose_alg = 0; |
255 | int cose_alg = 0; | ||
256 | |||
257 | memset(&p, 0, sizeof(p)); | ||
258 | |||
259 | if (size < input_len(GETLEN_MIN) || size > input_len(GETLEN_MAX) || | ||
260 | unpack(data, size, &p) < 0) | ||
261 | return (0); | ||
262 | |||
263 | prng_init((unsigned int)p.seed); | ||
264 | |||
265 | fido_init(FIDO_DEBUG); | ||
266 | fido_set_log_handler(consume_str); | ||
267 | 333 | ||
268 | if ((cred = fido_cred_new()) == NULL) | 334 | if ((cred = fido_cred_new()) == NULL) |
269 | return (0); | 335 | return; |
270 | |||
271 | set_wire_data(p.wire_data.body, p.wire_data.len); | ||
272 | 336 | ||
273 | switch (p.type & 3) { | 337 | switch (p->type & 3) { |
274 | case 0: | 338 | case 0: |
275 | cose_alg = COSE_ES256; | 339 | cose_alg = COSE_ES256; |
276 | break; | 340 | break; |
@@ -282,116 +346,106 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | |||
282 | break; | 346 | break; |
283 | } | 347 | } |
284 | 348 | ||
285 | make_cred(cred, p.u2f, cose_alg, &p.cdh, p.rp_id, p.rp_name, | 349 | set_wire_data(p->wire_data.body, p->wire_data.len); |
286 | &p.user_id, p.user_name, p.user_nick, p.user_icon, p.ext, p.rk, | 350 | |
287 | p.uv, p.pin, p.excl_count, &p.excl_cred); | 351 | make_cred(cred, p->u2f, cose_alg, &p->cdh, p->rp_id, p->rp_name, |
352 | &p->user_id, p->user_name, p->user_nick, p->user_icon, p->ext, | ||
353 | p->rk, p->uv, p->pin, p->excl_count, &p->excl_cred); | ||
288 | 354 | ||
289 | verify_cred(cose_alg, | 355 | verify_cred(cose_alg, |
290 | fido_cred_clientdata_hash_ptr(cred), | 356 | fido_cred_clientdata_hash_ptr(cred), |
291 | fido_cred_clientdata_hash_len(cred), fido_cred_rp_id(cred), | 357 | fido_cred_clientdata_hash_len(cred), fido_cred_rp_id(cred), |
292 | fido_cred_rp_name(cred), fido_cred_authdata_ptr(cred), | 358 | fido_cred_rp_name(cred), fido_cred_authdata_ptr(cred), |
293 | fido_cred_authdata_len(cred), p.ext, p.rk, p.uv, | 359 | fido_cred_authdata_len(cred), p->ext, p->rk, p->uv, |
294 | fido_cred_x5c_ptr(cred), fido_cred_x5c_len(cred), | 360 | fido_cred_x5c_ptr(cred), fido_cred_x5c_len(cred), |
295 | fido_cred_sig_ptr(cred), fido_cred_sig_len(cred), | 361 | fido_cred_sig_ptr(cred), fido_cred_sig_len(cred), |
296 | fido_cred_fmt(cred), fido_cred_prot(cred)); | 362 | fido_cred_fmt(cred), fido_cred_prot(cred)); |
297 | 363 | ||
298 | fido_cred_free(&cred); | 364 | fido_cred_free(&cred); |
299 | |||
300 | return (0); | ||
301 | } | 365 | } |
302 | 366 | ||
303 | static size_t | 367 | static void |
304 | pack_dummy(uint8_t *ptr, size_t len) | 368 | test_touch(const struct param *p) |
305 | { | 369 | { |
306 | struct param dummy; | 370 | fido_dev_t *dev; |
307 | uint8_t blob[16384]; | 371 | fido_dev_io_t io; |
308 | size_t blob_len; | 372 | int r; |
373 | int touched; | ||
309 | 374 | ||
310 | memset(&dummy, 0, sizeof(dummy)); | 375 | memset(&io, 0, sizeof(io)); |
311 | 376 | ||
312 | dummy.type = 1; | 377 | io.open = dev_open; |
313 | dummy.ext = FIDO_EXT_HMAC_SECRET; | 378 | io.close = dev_close; |
379 | io.read = dev_read; | ||
380 | io.write = dev_write; | ||
314 | 381 | ||
315 | strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); | 382 | set_wire_data(p->wire_data.body, p->wire_data.len); |
316 | strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id)); | ||
317 | strlcpy(dummy.rp_name, dummy_rp_name, sizeof(dummy.rp_name)); | ||
318 | strlcpy(dummy.user_icon, dummy_user_icon, sizeof(dummy.user_icon)); | ||
319 | strlcpy(dummy.user_name, dummy_user_name, sizeof(dummy.user_name)); | ||
320 | strlcpy(dummy.user_nick, dummy_user_nick, sizeof(dummy.user_nick)); | ||
321 | 383 | ||
322 | dummy.cdh.len = sizeof(dummy_cdh); | 384 | if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev, |
323 | dummy.user_id.len = sizeof(dummy_user_id); | 385 | &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) { |
324 | dummy.wire_data.len = sizeof(dummy_wire_data_fido); | 386 | fido_dev_free(&dev); |
387 | return; | ||
388 | } | ||
325 | 389 | ||
326 | memcpy(&dummy.cdh.body, &dummy_cdh, dummy.cdh.len); | 390 | if (p->u2f & 1) |
327 | memcpy(&dummy.user_id.body, &dummy_user_id, dummy.user_id.len); | 391 | fido_dev_force_u2f(dev); |
328 | memcpy(&dummy.wire_data.body, &dummy_wire_data_fido, | ||
329 | dummy.wire_data.len); | ||
330 | 392 | ||
331 | blob_len = pack(blob, sizeof(blob), &dummy); | 393 | r = fido_dev_get_touch_begin(dev); |
332 | assert(blob_len != 0); | 394 | consume_str(fido_strerr(r)); |
395 | r = fido_dev_get_touch_status(dev, &touched, -1); | ||
396 | consume_str(fido_strerr(r)); | ||
397 | consume(&touched, sizeof(touched)); | ||
333 | 398 | ||
334 | if (blob_len > len) { | 399 | fido_dev_cancel(dev); |
335 | memcpy(ptr, blob, len); | 400 | fido_dev_close(dev); |
336 | return (len); | 401 | fido_dev_free(&dev); |
337 | } | 402 | } |
338 | 403 | ||
339 | memcpy(ptr, blob, blob_len); | 404 | void |
405 | test(const struct param *p) | ||
406 | { | ||
407 | prng_init((unsigned int)p->seed); | ||
408 | fido_init(FIDO_DEBUG); | ||
409 | fido_set_log_handler(consume_str); | ||
340 | 410 | ||
341 | return (blob_len); | 411 | test_cred(p); |
412 | test_touch(p); | ||
342 | } | 413 | } |
343 | 414 | ||
344 | size_t | 415 | void |
345 | LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize, | 416 | mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN |
346 | unsigned int seed) NO_MSAN | ||
347 | { | 417 | { |
348 | struct param p; | 418 | if (flags & MUTATE_SEED) |
349 | uint8_t blob[16384]; | 419 | p->seed = (int)seed; |
350 | size_t blob_len; | 420 | |
351 | 421 | if (flags & MUTATE_PARAM) { | |
352 | memset(&p, 0, sizeof(p)); | 422 | mutate_byte(&p->rk); |
353 | 423 | mutate_byte(&p->type); | |
354 | if (unpack(data, size, &p) < 0) | 424 | mutate_byte(&p->u2f); |
355 | return (pack_dummy(data, maxsize)); | 425 | mutate_byte(&p->uv); |
356 | 426 | mutate_byte(&p->excl_count); | |
357 | mutate_byte(&p.rk); | 427 | mutate_int(&p->ext); |
358 | mutate_byte(&p.type); | 428 | mutate_blob(&p->cdh); |
359 | mutate_byte(&p.u2f); | 429 | mutate_blob(&p->user_id); |
360 | mutate_byte(&p.uv); | 430 | mutate_blob(&p->excl_cred); |
361 | mutate_byte(&p.excl_count); | 431 | mutate_string(p->pin); |
362 | 432 | mutate_string(p->user_icon); | |
363 | mutate_int(&p.ext); | 433 | mutate_string(p->user_name); |
364 | p.seed = (int)seed; | 434 | mutate_string(p->user_nick); |
365 | 435 | mutate_string(p->rp_id); | |
366 | mutate_blob(&p.cdh); | 436 | mutate_string(p->rp_name); |
367 | mutate_blob(&p.user_id); | ||
368 | |||
369 | if (p.u2f & 1) { | ||
370 | p.wire_data.len = sizeof(dummy_wire_data_u2f); | ||
371 | memcpy(&p.wire_data.body, &dummy_wire_data_u2f, | ||
372 | p.wire_data.len); | ||
373 | } else { | ||
374 | p.wire_data.len = sizeof(dummy_wire_data_fido); | ||
375 | memcpy(&p.wire_data.body, &dummy_wire_data_fido, | ||
376 | p.wire_data.len); | ||
377 | } | 437 | } |
378 | 438 | ||
379 | mutate_blob(&p.wire_data); | 439 | if (flags & MUTATE_WIREDATA) { |
380 | mutate_blob(&p.excl_cred); | 440 | if (p->u2f & 1) { |
381 | 441 | p->wire_data.len = sizeof(dummy_wire_data_u2f); | |
382 | mutate_string(p.pin); | 442 | memcpy(&p->wire_data.body, &dummy_wire_data_u2f, |
383 | mutate_string(p.user_icon); | 443 | p->wire_data.len); |
384 | mutate_string(p.user_name); | 444 | } else { |
385 | mutate_string(p.user_nick); | 445 | p->wire_data.len = sizeof(dummy_wire_data_fido); |
386 | mutate_string(p.rp_id); | 446 | memcpy(&p->wire_data.body, &dummy_wire_data_fido, |
387 | mutate_string(p.rp_name); | 447 | p->wire_data.len); |
388 | 448 | } | |
389 | blob_len = pack(blob, sizeof(blob), &p); | 449 | mutate_blob(&p->wire_data); |
390 | 450 | } | |
391 | if (blob_len == 0 || blob_len > maxsize) | ||
392 | return (0); | ||
393 | |||
394 | memcpy(data, blob, blob_len); | ||
395 | |||
396 | return (blob_len); | ||
397 | } | 451 | } |
diff --git a/fuzz/fuzz_credman.c b/fuzz/fuzz_credman.c index 323d0a9..db0dfb8 100644 --- a/fuzz/fuzz_credman.c +++ b/fuzz/fuzz_credman.c | |||
@@ -19,25 +19,16 @@ | |||
19 | 19 | ||
20 | #include "../openbsd-compat/openbsd-compat.h" | 20 | #include "../openbsd-compat/openbsd-compat.h" |
21 | 21 | ||
22 | #define TAG_META_WIRE_DATA 0x01 | ||
23 | #define TAG_RP_WIRE_DATA 0x02 | ||
24 | #define TAG_RK_WIRE_DATA 0x03 | ||
25 | #define TAG_DEL_WIRE_DATA 0x04 | ||
26 | #define TAG_CRED_ID 0x05 | ||
27 | #define TAG_PIN 0x06 | ||
28 | #define TAG_RP_ID 0x07 | ||
29 | #define TAG_SEED 0x08 | ||
30 | |||
31 | /* Parameter set defining a FIDO2 credential management operation. */ | 22 | /* Parameter set defining a FIDO2 credential management operation. */ |
32 | struct param { | 23 | struct param { |
33 | char pin[MAXSTR]; | 24 | char pin[MAXSTR]; |
34 | char rp_id[MAXSTR]; | 25 | char rp_id[MAXSTR]; |
35 | int seed; | 26 | int seed; |
36 | struct blob cred_id; | 27 | struct blob cred_id; |
37 | struct blob del_wire_data; | 28 | struct blob del_wire_data; |
38 | struct blob meta_wire_data; | 29 | struct blob meta_wire_data; |
39 | struct blob rk_wire_data; | 30 | struct blob rk_wire_data; |
40 | struct blob rp_wire_data; | 31 | struct blob rp_wire_data; |
41 | }; | 32 | }; |
42 | 33 | ||
43 | /* | 34 | /* |
@@ -88,56 +79,136 @@ static const uint8_t dummy_del_wire_data[] = { | |||
88 | WIREDATA_CTAP_CBOR_STATUS, | 79 | WIREDATA_CTAP_CBOR_STATUS, |
89 | }; | 80 | }; |
90 | 81 | ||
91 | int LLVMFuzzerTestOneInput(const uint8_t *, size_t); | 82 | struct param * |
92 | size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int); | 83 | unpack(const uint8_t *ptr, size_t len) |
93 | |||
94 | static int | ||
95 | unpack(const uint8_t *ptr, size_t len, struct param *p) NO_MSAN | ||
96 | { | 84 | { |
97 | uint8_t **pp = (void *)&ptr; | 85 | cbor_item_t *item = NULL, **v; |
98 | 86 | struct cbor_load_result cbor; | |
99 | if (unpack_string(TAG_PIN, pp, &len, p->pin) < 0 || | 87 | struct param *p; |
100 | unpack_string(TAG_RP_ID, pp, &len, p->rp_id) < 0 || | 88 | int ok = -1; |
101 | unpack_blob(TAG_CRED_ID, pp, &len, &p->cred_id) < 0 || | 89 | |
102 | unpack_blob(TAG_META_WIRE_DATA, pp, &len, &p->meta_wire_data) < 0 || | 90 | if ((p = calloc(1, sizeof(*p))) == NULL || |
103 | unpack_blob(TAG_RP_WIRE_DATA, pp, &len, &p->rp_wire_data) < 0 || | 91 | (item = cbor_load(ptr, len, &cbor)) == NULL || |
104 | unpack_blob(TAG_RK_WIRE_DATA, pp, &len, &p->rk_wire_data) < 0 || | 92 | cbor.read != len || |
105 | unpack_blob(TAG_DEL_WIRE_DATA, pp, &len, &p->del_wire_data) < 0 || | 93 | cbor_isa_array(item) == false || |
106 | unpack_int(TAG_SEED, pp, &len, &p->seed) < 0) | 94 | cbor_array_is_definite(item) == false || |
107 | return (-1); | 95 | cbor_array_size(item) != 8 || |
108 | 96 | (v = cbor_array_handle(item)) == NULL) | |
109 | return (0); | 97 | goto fail; |
98 | |||
99 | if (unpack_int(v[0], &p->seed) < 0 || | ||
100 | unpack_string(v[1], p->pin) < 0 || | ||
101 | unpack_string(v[2], p->rp_id) < 0 || | ||
102 | unpack_blob(v[3], &p->cred_id) < 0 || | ||
103 | unpack_blob(v[4], &p->meta_wire_data) < 0 || | ||
104 | unpack_blob(v[5], &p->rp_wire_data) < 0 || | ||
105 | unpack_blob(v[6], &p->rk_wire_data) < 0 || | ||
106 | unpack_blob(v[7], &p->del_wire_data) < 0) | ||
107 | goto fail; | ||
108 | |||
109 | ok = 0; | ||
110 | fail: | ||
111 | if (ok < 0) { | ||
112 | free(p); | ||
113 | p = NULL; | ||
114 | } | ||
115 | |||
116 | if (item) | ||
117 | cbor_decref(&item); | ||
118 | |||
119 | return p; | ||
110 | } | 120 | } |
111 | 121 | ||
112 | static size_t | 122 | size_t |
113 | pack(uint8_t *ptr, size_t len, const struct param *p) | 123 | pack(uint8_t *ptr, size_t len, const struct param *p) |
114 | { | 124 | { |
115 | const size_t max = len; | 125 | cbor_item_t *argv[8], *array = NULL; |
116 | 126 | size_t cbor_alloc_len, cbor_len = 0; | |
117 | if (pack_string(TAG_PIN, &ptr, &len, p->pin) < 0 || | 127 | unsigned char *cbor = NULL; |
118 | pack_string(TAG_RP_ID, &ptr, &len, p->rp_id) < 0 || | 128 | |
119 | pack_blob(TAG_CRED_ID, &ptr, &len, &p->cred_id) < 0 || | 129 | memset(argv, 0, sizeof(argv)); |
120 | pack_blob(TAG_META_WIRE_DATA, &ptr, &len, &p->meta_wire_data) < 0 || | 130 | |
121 | pack_blob(TAG_RP_WIRE_DATA, &ptr, &len, &p->rp_wire_data) < 0 || | 131 | if ((array = cbor_new_definite_array(8)) == NULL || |
122 | pack_blob(TAG_RK_WIRE_DATA, &ptr, &len, &p->rk_wire_data) < 0 || | 132 | (argv[0] = pack_int(p->seed)) == NULL || |
123 | pack_blob(TAG_DEL_WIRE_DATA, &ptr, &len, &p->del_wire_data) < 0 || | 133 | (argv[1] = pack_string(p->pin)) == NULL || |
124 | pack_int(TAG_SEED, &ptr, &len, p->seed) < 0) | 134 | (argv[2] = pack_string(p->rp_id)) == NULL || |
125 | return (0); | 135 | (argv[3] = pack_blob(&p->cred_id)) == NULL || |
126 | 136 | (argv[4] = pack_blob(&p->meta_wire_data)) == NULL || | |
127 | return (max - len); | 137 | (argv[5] = pack_blob(&p->rp_wire_data)) == NULL || |
138 | (argv[6] = pack_blob(&p->rk_wire_data)) == NULL || | ||
139 | (argv[7] = pack_blob(&p->del_wire_data)) == NULL) | ||
140 | goto fail; | ||
141 | |||
142 | for (size_t i = 0; i < 8; i++) | ||
143 | if (cbor_array_push(array, argv[i]) == false) | ||
144 | goto fail; | ||
145 | |||
146 | if ((cbor_len = cbor_serialize_alloc(array, &cbor, | ||
147 | &cbor_alloc_len)) > len) { | ||
148 | cbor_len = 0; | ||
149 | goto fail; | ||
150 | } | ||
151 | |||
152 | memcpy(ptr, cbor, cbor_len); | ||
153 | fail: | ||
154 | for (size_t i = 0; i < 8; i++) | ||
155 | if (argv[i]) | ||
156 | cbor_decref(&argv[i]); | ||
157 | |||
158 | if (array) | ||
159 | cbor_decref(&array); | ||
160 | |||
161 | free(cbor); | ||
162 | |||
163 | return cbor_len; | ||
128 | } | 164 | } |
129 | 165 | ||
130 | static size_t | 166 | size_t |
131 | input_len(int max) | 167 | pack_dummy(uint8_t *ptr, size_t len) |
132 | { | 168 | { |
133 | return (2 * len_string(max) + 5 * len_blob(max) + len_int()); | 169 | struct param dummy; |
170 | uint8_t blob[4096]; | ||
171 | size_t blob_len; | ||
172 | |||
173 | memset(&dummy, 0, sizeof(dummy)); | ||
174 | |||
175 | strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); | ||
176 | strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id)); | ||
177 | |||
178 | dummy.meta_wire_data.len = sizeof(dummy_meta_wire_data); | ||
179 | dummy.rp_wire_data.len = sizeof(dummy_rp_wire_data); | ||
180 | dummy.rk_wire_data.len = sizeof(dummy_rk_wire_data); | ||
181 | dummy.del_wire_data.len = sizeof(dummy_del_wire_data); | ||
182 | dummy.cred_id.len = sizeof(dummy_cred_id); | ||
183 | |||
184 | memcpy(&dummy.meta_wire_data.body, &dummy_meta_wire_data, | ||
185 | dummy.meta_wire_data.len); | ||
186 | memcpy(&dummy.rp_wire_data.body, &dummy_rp_wire_data, | ||
187 | dummy.rp_wire_data.len); | ||
188 | memcpy(&dummy.rk_wire_data.body, &dummy_rk_wire_data, | ||
189 | dummy.rk_wire_data.len); | ||
190 | memcpy(&dummy.del_wire_data.body, &dummy_del_wire_data, | ||
191 | dummy.del_wire_data.len); | ||
192 | memcpy(&dummy.cred_id.body, &dummy_cred_id, dummy.cred_id.len); | ||
193 | |||
194 | assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); | ||
195 | |||
196 | if (blob_len > len) { | ||
197 | memcpy(ptr, blob, len); | ||
198 | return len; | ||
199 | } | ||
200 | |||
201 | memcpy(ptr, blob, blob_len); | ||
202 | |||
203 | return blob_len; | ||
134 | } | 204 | } |
135 | 205 | ||
136 | static fido_dev_t * | 206 | static fido_dev_t * |
137 | prepare_dev() | 207 | prepare_dev(void) |
138 | { | 208 | { |
139 | fido_dev_t *dev; | 209 | fido_dev_t *dev; |
140 | fido_dev_io_t io; | 210 | fido_dev_io_t io; |
211 | bool x; | ||
141 | 212 | ||
142 | memset(&io, 0, sizeof(io)); | 213 | memset(&io, 0, sizeof(io)); |
143 | 214 | ||
@@ -149,14 +220,19 @@ prepare_dev() | |||
149 | if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev, | 220 | if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev, |
150 | &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) { | 221 | &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) { |
151 | fido_dev_free(&dev); | 222 | fido_dev_free(&dev); |
152 | return (NULL); | 223 | return NULL; |
153 | } | 224 | } |
154 | 225 | ||
155 | return (dev); | 226 | x = fido_dev_is_fido2(dev); |
227 | consume(&x, sizeof(x)); | ||
228 | x = fido_dev_supports_cred_prot(dev); | ||
229 | consume(&x, sizeof(x)); | ||
230 | |||
231 | return dev; | ||
156 | } | 232 | } |
157 | 233 | ||
158 | static void | 234 | static void |
159 | get_metadata(struct param *p) | 235 | get_metadata(const struct param *p) |
160 | { | 236 | { |
161 | fido_dev_t *dev; | 237 | fido_dev_t *dev; |
162 | fido_credman_metadata_t *metadata; | 238 | fido_credman_metadata_t *metadata; |
@@ -187,7 +263,7 @@ get_metadata(struct param *p) | |||
187 | } | 263 | } |
188 | 264 | ||
189 | static void | 265 | static void |
190 | get_rp_list(struct param *p) | 266 | get_rp_list(const struct param *p) |
191 | { | 267 | { |
192 | fido_dev_t *dev; | 268 | fido_dev_t *dev; |
193 | fido_credman_rp_t *rp; | 269 | fido_credman_rp_t *rp; |
@@ -221,12 +297,12 @@ get_rp_list(struct param *p) | |||
221 | } | 297 | } |
222 | 298 | ||
223 | static void | 299 | static void |
224 | get_rk_list(struct param *p) | 300 | get_rk_list(const struct param *p) |
225 | { | 301 | { |
226 | fido_dev_t *dev; | 302 | fido_dev_t *dev; |
227 | fido_credman_rk_t *rk; | 303 | fido_credman_rk_t *rk; |
228 | const fido_cred_t *cred; | 304 | const fido_cred_t *cred; |
229 | int type; | 305 | int val; |
230 | 306 | ||
231 | set_wire_data(p->rk_wire_data.body, p->rk_wire_data.len); | 307 | set_wire_data(p->rk_wire_data.body, p->rk_wire_data.len); |
232 | 308 | ||
@@ -247,8 +323,8 @@ get_rk_list(struct param *p) | |||
247 | assert(i >= fido_credman_rk_count(rk)); | 323 | assert(i >= fido_credman_rk_count(rk)); |
248 | continue; | 324 | continue; |
249 | } | 325 | } |
250 | type = fido_cred_type(cred); | 326 | val = fido_cred_type(cred); |
251 | consume(&type, sizeof(type)); | 327 | consume(&val, sizeof(val)); |
252 | consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred)); | 328 | consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred)); |
253 | consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred)); | 329 | consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred)); |
254 | consume(fido_cred_user_id_ptr(cred), | 330 | consume(fido_cred_user_id_ptr(cred), |
@@ -257,6 +333,8 @@ get_rk_list(struct param *p) | |||
257 | xstrlen(fido_cred_user_name(cred))); | 333 | xstrlen(fido_cred_user_name(cred))); |
258 | consume(fido_cred_display_name(cred), | 334 | consume(fido_cred_display_name(cred), |
259 | xstrlen(fido_cred_display_name(cred))); | 335 | xstrlen(fido_cred_display_name(cred))); |
336 | val = fido_cred_prot(cred); | ||
337 | consume(&val, sizeof(val)); | ||
260 | } | 338 | } |
261 | 339 | ||
262 | fido_credman_rk_free(&rk); | 340 | fido_credman_rk_free(&rk); |
@@ -265,7 +343,7 @@ get_rk_list(struct param *p) | |||
265 | } | 343 | } |
266 | 344 | ||
267 | static void | 345 | static void |
268 | del_rk(struct param *p) | 346 | del_rk(const struct param *p) |
269 | { | 347 | { |
270 | fido_dev_t *dev; | 348 | fido_dev_t *dev; |
271 | 349 | ||
@@ -279,101 +357,35 @@ del_rk(struct param *p) | |||
279 | fido_dev_free(&dev); | 357 | fido_dev_free(&dev); |
280 | } | 358 | } |
281 | 359 | ||
282 | int | 360 | void |
283 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | 361 | test(const struct param *p) |
284 | { | 362 | { |
285 | struct param p; | 363 | prng_init((unsigned int)p->seed); |
286 | |||
287 | memset(&p, 0, sizeof(p)); | ||
288 | |||
289 | if (size < input_len(GETLEN_MIN) || size > input_len(GETLEN_MAX) || | ||
290 | unpack(data, size, &p) < 0) | ||
291 | return (0); | ||
292 | |||
293 | prng_init((unsigned int)p.seed); | ||
294 | |||
295 | fido_init(FIDO_DEBUG); | 364 | fido_init(FIDO_DEBUG); |
296 | fido_set_log_handler(consume_str); | 365 | fido_set_log_handler(consume_str); |
297 | 366 | ||
298 | get_metadata(&p); | 367 | get_metadata(p); |
299 | get_rp_list(&p); | 368 | get_rp_list(p); |
300 | get_rk_list(&p); | 369 | get_rk_list(p); |
301 | del_rk(&p); | 370 | del_rk(p); |
302 | |||
303 | return (0); | ||
304 | } | 371 | } |
305 | 372 | ||
306 | static size_t | 373 | void |
307 | pack_dummy(uint8_t *ptr, size_t len) | 374 | mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN |
308 | { | 375 | { |
309 | struct param dummy; | 376 | if (flags & MUTATE_SEED) |
310 | uint8_t blob[32768]; | 377 | p->seed = (int)seed; |
311 | size_t blob_len; | ||
312 | |||
313 | memset(&dummy, 0, sizeof(dummy)); | ||
314 | |||
315 | strlcpy(dummy.pin, dummy_pin, sizeof(dummy.pin)); | ||
316 | strlcpy(dummy.rp_id, dummy_rp_id, sizeof(dummy.rp_id)); | ||
317 | 378 | ||
318 | dummy.meta_wire_data.len = sizeof(dummy_meta_wire_data); | 379 | if (flags & MUTATE_PARAM) { |
319 | dummy.rp_wire_data.len = sizeof(dummy_rp_wire_data); | 380 | mutate_blob(&p->cred_id); |
320 | dummy.rk_wire_data.len = sizeof(dummy_rk_wire_data); | 381 | mutate_string(p->pin); |
321 | dummy.del_wire_data.len = sizeof(dummy_del_wire_data); | 382 | mutate_string(p->rp_id); |
322 | dummy.cred_id.len = sizeof(dummy_cred_id); | ||
323 | |||
324 | memcpy(&dummy.meta_wire_data.body, &dummy_meta_wire_data, | ||
325 | dummy.meta_wire_data.len); | ||
326 | memcpy(&dummy.rp_wire_data.body, &dummy_rp_wire_data, | ||
327 | dummy.rp_wire_data.len); | ||
328 | memcpy(&dummy.rk_wire_data.body, &dummy_rk_wire_data, | ||
329 | dummy.rk_wire_data.len); | ||
330 | memcpy(&dummy.del_wire_data.body, &dummy_del_wire_data, | ||
331 | dummy.del_wire_data.len); | ||
332 | memcpy(&dummy.cred_id.body, &dummy_cred_id, dummy.cred_id.len); | ||
333 | |||
334 | blob_len = pack(blob, sizeof(blob), &dummy); | ||
335 | assert(blob_len != 0); | ||
336 | |||
337 | if (blob_len > len) { | ||
338 | memcpy(ptr, blob, len); | ||
339 | return (len); | ||
340 | } | 383 | } |
341 | 384 | ||
342 | memcpy(ptr, blob, blob_len); | 385 | if (flags & MUTATE_WIREDATA) { |
343 | 386 | mutate_blob(&p->meta_wire_data); | |
344 | return (blob_len); | 387 | mutate_blob(&p->rp_wire_data); |
345 | } | 388 | mutate_blob(&p->rk_wire_data); |
346 | 389 | mutate_blob(&p->del_wire_data); | |
347 | size_t | 390 | } |
348 | LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize, | ||
349 | unsigned int seed) NO_MSAN | ||
350 | { | ||
351 | struct param p; | ||
352 | uint8_t blob[16384]; | ||
353 | size_t blob_len; | ||
354 | |||
355 | memset(&p, 0, sizeof(p)); | ||
356 | |||
357 | if (unpack(data, size, &p) < 0) | ||
358 | return (pack_dummy(data, maxsize)); | ||
359 | |||
360 | p.seed = (int)seed; | ||
361 | |||
362 | mutate_blob(&p.cred_id); | ||
363 | mutate_blob(&p.meta_wire_data); | ||
364 | mutate_blob(&p.rp_wire_data); | ||
365 | mutate_blob(&p.rk_wire_data); | ||
366 | mutate_blob(&p.del_wire_data); | ||
367 | |||
368 | mutate_string(p.pin); | ||
369 | mutate_string(p.rp_id); | ||
370 | |||
371 | blob_len = pack(blob, sizeof(blob), &p); | ||
372 | |||
373 | if (blob_len == 0 || blob_len > maxsize) | ||
374 | return (0); | ||
375 | |||
376 | memcpy(data, blob, blob_len); | ||
377 | |||
378 | return (blob_len); | ||
379 | } | 391 | } |
diff --git a/fuzz/fuzz_mgmt.c b/fuzz/fuzz_mgmt.c index d46daf6..0b6cf19 100644 --- a/fuzz/fuzz_mgmt.c +++ b/fuzz/fuzz_mgmt.c | |||
@@ -17,24 +17,15 @@ | |||
17 | 17 | ||
18 | #include "../openbsd-compat/openbsd-compat.h" | 18 | #include "../openbsd-compat/openbsd-compat.h" |
19 | 19 | ||
20 | #define TAG_PIN1 0x01 | ||
21 | #define TAG_PIN2 0x02 | ||
22 | #define TAG_RESET_WIRE_DATA 0x03 | ||
23 | #define TAG_INFO_WIRE_DATA 0x04 | ||
24 | #define TAG_SET_PIN_WIRE_DATA 0x05 | ||
25 | #define TAG_CHANGE_PIN_WIRE_DATA 0x06 | ||
26 | #define TAG_RETRY_WIRE_DATA 0x07 | ||
27 | #define TAG_SEED 0x08 | ||
28 | |||
29 | struct param { | 20 | struct param { |
30 | char pin1[MAXSTR]; | 21 | char pin1[MAXSTR]; |
31 | char pin2[MAXSTR]; | 22 | char pin2[MAXSTR]; |
32 | struct blob reset_wire_data; | 23 | struct blob reset_wire_data; |
33 | struct blob info_wire_data; | 24 | struct blob info_wire_data; |
34 | struct blob set_pin_wire_data; | 25 | struct blob set_pin_wire_data; |
35 | struct blob change_pin_wire_data; | 26 | struct blob change_pin_wire_data; |
36 | struct blob retry_wire_data; | 27 | struct blob retry_wire_data; |
37 | int seed; | 28 | int seed; |
38 | }; | 29 | }; |
39 | 30 | ||
40 | static const uint8_t dummy_reset_wire_data[] = { | 31 | static const uint8_t dummy_reset_wire_data[] = { |
@@ -72,56 +63,136 @@ static const uint8_t dummy_retry_wire_data[] = { | |||
72 | WIREDATA_CTAP_CBOR_RETRIES, | 63 | WIREDATA_CTAP_CBOR_RETRIES, |
73 | }; | 64 | }; |
74 | 65 | ||
75 | int LLVMFuzzerTestOneInput(const uint8_t *, size_t); | 66 | struct param * |
76 | size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int); | 67 | unpack(const uint8_t *ptr, size_t len) |
77 | |||
78 | static int | ||
79 | unpack(const uint8_t *ptr, size_t len, struct param *p) NO_MSAN | ||
80 | { | 68 | { |
81 | uint8_t **pp = (void *)&ptr; | 69 | cbor_item_t *item = NULL, **v; |
82 | 70 | struct cbor_load_result cbor; | |
83 | if (unpack_string(TAG_PIN1, pp, &len, p->pin1) < 0 || | 71 | struct param *p; |
84 | unpack_string(TAG_PIN2, pp, &len, p->pin2) < 0 || | 72 | int ok = -1; |
85 | unpack_blob(TAG_RESET_WIRE_DATA, pp, &len, &p->reset_wire_data) < 0 || | 73 | |
86 | unpack_blob(TAG_INFO_WIRE_DATA, pp, &len, &p->info_wire_data) < 0 || | 74 | if ((p = calloc(1, sizeof(*p))) == NULL || |
87 | unpack_blob(TAG_SET_PIN_WIRE_DATA, pp, &len, &p->set_pin_wire_data) < 0 || | 75 | (item = cbor_load(ptr, len, &cbor)) == NULL || |
88 | unpack_blob(TAG_CHANGE_PIN_WIRE_DATA, pp, &len, &p->change_pin_wire_data) < 0 || | 76 | cbor.read != len || |
89 | unpack_blob(TAG_RETRY_WIRE_DATA, pp, &len, &p->retry_wire_data) < 0 || | 77 | cbor_isa_array(item) == false || |
90 | unpack_int(TAG_SEED, pp, &len, &p->seed) < 0) | 78 | cbor_array_is_definite(item) == false || |
91 | return (-1); | 79 | cbor_array_size(item) != 8 || |
92 | 80 | (v = cbor_array_handle(item)) == NULL) | |
93 | return (0); | 81 | goto fail; |
82 | |||
83 | if (unpack_int(v[0], &p->seed) < 0 || | ||
84 | unpack_string(v[1], p->pin1) < 0 || | ||
85 | unpack_string(v[2], p->pin2) < 0 || | ||
86 | unpack_blob(v[3], &p->reset_wire_data) < 0 || | ||
87 | unpack_blob(v[4], &p->info_wire_data) < 0 || | ||
88 | unpack_blob(v[5], &p->set_pin_wire_data) < 0 || | ||
89 | unpack_blob(v[6], &p->change_pin_wire_data) < 0 || | ||
90 | unpack_blob(v[7], &p->retry_wire_data) < 0) | ||
91 | goto fail; | ||
92 | |||
93 | ok = 0; | ||
94 | fail: | ||
95 | if (ok < 0) { | ||
96 | free(p); | ||
97 | p = NULL; | ||
98 | } | ||
99 | |||
100 | if (item) | ||
101 | cbor_decref(&item); | ||
102 | |||
103 | return p; | ||
94 | } | 104 | } |
95 | 105 | ||
96 | static size_t | 106 | size_t |
97 | pack(uint8_t *ptr, size_t len, const struct param *p) | 107 | pack(uint8_t *ptr, size_t len, const struct param *p) |
98 | { | 108 | { |
99 | const size_t max = len; | 109 | cbor_item_t *argv[8], *array = NULL; |
100 | 110 | size_t cbor_alloc_len, cbor_len = 0; | |
101 | if (pack_string(TAG_PIN1, &ptr, &len, p->pin1) < 0 || | 111 | unsigned char *cbor = NULL; |
102 | pack_string(TAG_PIN2, &ptr, &len, p->pin2) < 0 || | 112 | |
103 | pack_blob(TAG_RESET_WIRE_DATA, &ptr, &len, &p->reset_wire_data) < 0 || | 113 | memset(argv, 0, sizeof(argv)); |
104 | pack_blob(TAG_INFO_WIRE_DATA, &ptr, &len, &p->info_wire_data) < 0 || | 114 | |
105 | pack_blob(TAG_SET_PIN_WIRE_DATA, &ptr, &len, &p->set_pin_wire_data) < 0 || | 115 | if ((array = cbor_new_definite_array(8)) == NULL || |
106 | pack_blob(TAG_CHANGE_PIN_WIRE_DATA, &ptr, &len, &p->change_pin_wire_data) < 0 || | 116 | (argv[0] = pack_int(p->seed)) == NULL || |
107 | pack_blob(TAG_RETRY_WIRE_DATA, &ptr, &len, &p->retry_wire_data) < 0 || | 117 | (argv[1] = pack_string(p->pin1)) == NULL || |
108 | pack_int(TAG_SEED, &ptr, &len, p->seed) < 0) | 118 | (argv[2] = pack_string(p->pin2)) == NULL || |
109 | return (0); | 119 | (argv[3] = pack_blob(&p->reset_wire_data)) == NULL || |
110 | 120 | (argv[4] = pack_blob(&p->info_wire_data)) == NULL || | |
111 | return (max - len); | 121 | (argv[5] = pack_blob(&p->set_pin_wire_data)) == NULL || |
122 | (argv[6] = pack_blob(&p->change_pin_wire_data)) == NULL || | ||
123 | (argv[7] = pack_blob(&p->retry_wire_data)) == NULL) | ||
124 | goto fail; | ||
125 | |||
126 | for (size_t i = 0; i < 8; i++) | ||
127 | if (cbor_array_push(array, argv[i]) == false) | ||
128 | goto fail; | ||
129 | |||
130 | if ((cbor_len = cbor_serialize_alloc(array, &cbor, | ||
131 | &cbor_alloc_len)) > len) { | ||
132 | cbor_len = 0; | ||
133 | goto fail; | ||
134 | } | ||
135 | |||
136 | memcpy(ptr, cbor, cbor_len); | ||
137 | fail: | ||
138 | for (size_t i = 0; i < 8; i++) | ||
139 | if (argv[i]) | ||
140 | cbor_decref(&argv[i]); | ||
141 | |||
142 | if (array) | ||
143 | cbor_decref(&array); | ||
144 | |||
145 | free(cbor); | ||
146 | |||
147 | return cbor_len; | ||
112 | } | 148 | } |
113 | 149 | ||
114 | static size_t | 150 | size_t |
115 | input_len(int max) | 151 | pack_dummy(uint8_t *ptr, size_t len) |
116 | { | 152 | { |
117 | return (2 * len_string(max) + 5 * len_blob(max) + len_int()); | 153 | struct param dummy; |
154 | uint8_t blob[4096]; | ||
155 | size_t blob_len; | ||
156 | |||
157 | memset(&dummy, 0, sizeof(dummy)); | ||
158 | |||
159 | strlcpy(dummy.pin1, dummy_pin1, sizeof(dummy.pin1)); | ||
160 | strlcpy(dummy.pin2, dummy_pin2, sizeof(dummy.pin2)); | ||
161 | |||
162 | dummy.reset_wire_data.len = sizeof(dummy_reset_wire_data); | ||
163 | dummy.info_wire_data.len = sizeof(dummy_info_wire_data); | ||
164 | dummy.set_pin_wire_data.len = sizeof(dummy_set_pin_wire_data); | ||
165 | dummy.change_pin_wire_data.len = sizeof(dummy_change_pin_wire_data); | ||
166 | dummy.retry_wire_data.len = sizeof(dummy_retry_wire_data); | ||
167 | |||
168 | memcpy(&dummy.reset_wire_data.body, &dummy_reset_wire_data, | ||
169 | dummy.reset_wire_data.len); | ||
170 | memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data, | ||
171 | dummy.info_wire_data.len); | ||
172 | memcpy(&dummy.set_pin_wire_data.body, &dummy_set_pin_wire_data, | ||
173 | dummy.set_pin_wire_data.len); | ||
174 | memcpy(&dummy.change_pin_wire_data.body, &dummy_change_pin_wire_data, | ||
175 | dummy.change_pin_wire_data.len); | ||
176 | memcpy(&dummy.retry_wire_data.body, &dummy_retry_wire_data, | ||
177 | dummy.retry_wire_data.len); | ||
178 | |||
179 | assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0); | ||
180 | |||
181 | if (blob_len > len) { | ||
182 | memcpy(ptr, blob, len); | ||
183 | return len; | ||
184 | } | ||
185 | |||
186 | memcpy(ptr, blob, blob_len); | ||
187 | |||
188 | return blob_len; | ||
118 | } | 189 | } |
119 | 190 | ||
120 | static fido_dev_t * | 191 | static fido_dev_t * |
121 | prepare_dev() | 192 | prepare_dev(void) |
122 | { | 193 | { |
123 | fido_dev_t *dev; | 194 | fido_dev_t *dev; |
124 | fido_dev_io_t io; | 195 | fido_dev_io_t io; |
125 | 196 | ||
126 | memset(&io, 0, sizeof(io)); | 197 | memset(&io, 0, sizeof(io)); |
127 | 198 | ||
@@ -133,14 +204,14 @@ prepare_dev() | |||
133 | if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev, | 204 | if ((dev = fido_dev_new()) == NULL || fido_dev_set_io_functions(dev, |
134 | &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) { | 205 | &io) != FIDO_OK || fido_dev_open(dev, "nodev") != FIDO_OK) { |
135 | fido_dev_free(&dev); | 206 | fido_dev_free(&dev); |
136 | return (NULL); | 207 | return NULL; |
137 | } | 208 | } |
138 | 209 | ||
139 | return (dev); | 210 | return dev; |
140 | } | 211 | } |
141 | 212 | ||
142 | static void | 213 | static void |
143 | dev_reset(struct param *p) | 214 | dev_reset(const struct param *p) |
144 | { | 215 | { |
145 | fido_dev_t *dev; | 216 | fido_dev_t *dev; |
146 | 217 | ||
@@ -155,16 +226,12 @@ dev_reset(struct param *p) | |||
155 | } | 226 | } |
156 | 227 | ||
157 | static void | 228 | static void |
158 | dev_get_cbor_info(struct param *p) | 229 | dev_get_cbor_info(const struct param *p) |
159 | { | 230 | { |
160 | fido_dev_t *dev; | 231 | fido_dev_t *dev; |
161 | fido_cbor_info_t *ci; | 232 | fido_cbor_info_t *ci; |
162 | uint64_t n; | 233 | uint64_t n; |
163 | uint8_t proto; | 234 | uint8_t proto, major, minor, build, flags; |
164 | uint8_t major; | ||
165 | uint8_t minor; | ||
166 | uint8_t build; | ||
167 | uint8_t flags; | ||
168 | 235 | ||
169 | set_wire_data(p->info_wire_data.body, p->info_wire_data.len); | 236 | set_wire_data(p->info_wire_data.body, p->info_wire_data.len); |
170 | 237 | ||
@@ -192,6 +259,7 @@ dev_get_cbor_info(struct param *p) | |||
192 | char * const *sa = fido_cbor_info_versions_ptr(ci); | 259 | char * const *sa = fido_cbor_info_versions_ptr(ci); |
193 | consume(sa[i], strlen(sa[i])); | 260 | consume(sa[i], strlen(sa[i])); |
194 | } | 261 | } |
262 | |||
195 | for (size_t i = 0; i < fido_cbor_info_extensions_len(ci); i++) { | 263 | for (size_t i = 0; i < fido_cbor_info_extensions_len(ci); i++) { |
196 | char * const *sa = fido_cbor_info_extensions_ptr(ci); | 264 | char * const *sa = fido_cbor_info_extensions_ptr(ci); |
197 | consume(sa[i], strlen(sa[i])); | 265 | consume(sa[i], strlen(sa[i])); |
@@ -207,6 +275,12 @@ dev_get_cbor_info(struct param *p) | |||
207 | n = fido_cbor_info_maxmsgsiz(ci); | 275 | n = fido_cbor_info_maxmsgsiz(ci); |
208 | consume(&n, sizeof(n)); | 276 | consume(&n, sizeof(n)); |
209 | 277 | ||
278 | n = fido_cbor_info_maxcredcntlst(ci); | ||
279 | consume(&n, sizeof(n)); | ||
280 | |||
281 | n = fido_cbor_info_maxcredidlen(ci); | ||
282 | consume(&n, sizeof(n)); | ||
283 | |||
210 | n = fido_cbor_info_fwversion(ci); | 284 | n = fido_cbor_info_fwversion(ci); |
211 | consume(&n, sizeof(n)); | 285 | consume(&n, sizeof(n)); |
212 | 286 | ||
@@ -222,7 +296,7 @@ out: | |||
222 | } | 296 | } |
223 | 297 | ||
224 | static void | 298 | static void |
225 | dev_set_pin(struct param *p) | 299 | dev_set_pin(const struct param *p) |
226 | { | 300 | { |
227 | fido_dev_t *dev; | 301 | fido_dev_t *dev; |
228 | 302 | ||
@@ -237,7 +311,7 @@ dev_set_pin(struct param *p) | |||
237 | } | 311 | } |
238 | 312 | ||
239 | static void | 313 | static void |
240 | dev_change_pin(struct param *p) | 314 | dev_change_pin(const struct param *p) |
241 | { | 315 | { |
242 | fido_dev_t *dev; | 316 | fido_dev_t *dev; |
243 | 317 | ||
@@ -252,10 +326,10 @@ dev_change_pin(struct param *p) | |||
252 | } | 326 | } |
253 | 327 | ||
254 | static void | 328 | static void |
255 | dev_get_retry_count(struct param *p) | 329 | dev_get_retry_count(const struct param *p) |
256 | { | 330 | { |
257 | fido_dev_t *dev; | 331 | fido_dev_t *dev; |
258 | int n; | 332 | int n = 0; |
259 | 333 | ||
260 | set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len); | 334 | set_wire_data(p->retry_wire_data.body, p->retry_wire_data.len); |
261 | 335 | ||
@@ -268,103 +342,36 @@ dev_get_retry_count(struct param *p) | |||
268 | fido_dev_free(&dev); | 342 | fido_dev_free(&dev); |
269 | } | 343 | } |
270 | 344 | ||
271 | int | 345 | void |
272 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | 346 | test(const struct param *p) |
273 | { | 347 | { |
274 | struct param p; | 348 | prng_init((unsigned int)p->seed); |
275 | |||
276 | memset(&p, 0, sizeof(p)); | ||
277 | |||
278 | if (size < input_len(GETLEN_MIN) || size > input_len(GETLEN_MAX) || | ||
279 | unpack(data, size, &p) < 0) | ||
280 | return (0); | ||
281 | |||
282 | prng_init((unsigned int)p.seed); | ||
283 | |||
284 | fido_init(FIDO_DEBUG); | 349 | fido_init(FIDO_DEBUG); |
285 | fido_set_log_handler(consume_str); | 350 | fido_set_log_handler(consume_str); |
286 | 351 | ||
287 | dev_reset(&p); | 352 | dev_reset(p); |
288 | dev_get_cbor_info(&p); | 353 | dev_get_cbor_info(p); |
289 | dev_set_pin(&p); | 354 | dev_set_pin(p); |
290 | dev_change_pin(&p); | 355 | dev_change_pin(p); |
291 | dev_get_retry_count(&p); | 356 | dev_get_retry_count(p); |
292 | |||
293 | return (0); | ||
294 | } | 357 | } |
295 | 358 | ||
296 | static size_t | 359 | void |
297 | pack_dummy(uint8_t *ptr, size_t len) | 360 | mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN |
298 | { | 361 | { |
299 | struct param dummy; | 362 | if (flags & MUTATE_SEED) |
300 | uint8_t blob[16384]; | 363 | p->seed = (int)seed; |
301 | size_t blob_len; | ||
302 | |||
303 | memset(&dummy, 0, sizeof(dummy)); | ||
304 | |||
305 | strlcpy(dummy.pin1, dummy_pin1, sizeof(dummy.pin1)); | ||
306 | strlcpy(dummy.pin2, dummy_pin2, sizeof(dummy.pin2)); | ||
307 | |||
308 | dummy.reset_wire_data.len = sizeof(dummy_reset_wire_data); | ||
309 | dummy.info_wire_data.len = sizeof(dummy_info_wire_data); | ||
310 | dummy.set_pin_wire_data.len = sizeof(dummy_set_pin_wire_data); | ||
311 | dummy.change_pin_wire_data.len = sizeof(dummy_change_pin_wire_data); | ||
312 | dummy.retry_wire_data.len = sizeof(dummy_retry_wire_data); | ||
313 | |||
314 | memcpy(&dummy.reset_wire_data.body, &dummy_reset_wire_data, | ||
315 | dummy.reset_wire_data.len); | ||
316 | memcpy(&dummy.info_wire_data.body, &dummy_info_wire_data, | ||
317 | dummy.info_wire_data.len); | ||
318 | memcpy(&dummy.set_pin_wire_data.body, &dummy_set_pin_wire_data, | ||
319 | dummy.set_pin_wire_data.len); | ||
320 | memcpy(&dummy.change_pin_wire_data.body, &dummy_change_pin_wire_data, | ||
321 | dummy.change_pin_wire_data.len); | ||
322 | memcpy(&dummy.retry_wire_data.body, &dummy_retry_wire_data, | ||
323 | dummy.retry_wire_data.len); | ||
324 | |||
325 | blob_len = pack(blob, sizeof(blob), &dummy); | ||
326 | assert(blob_len != 0); | ||
327 | 364 | ||
328 | if (blob_len > len) { | 365 | if (flags & MUTATE_PARAM) { |
329 | memcpy(ptr, blob, len); | 366 | mutate_string(p->pin1); |
330 | return (len); | 367 | mutate_string(p->pin2); |
331 | } | 368 | } |
332 | 369 | ||
333 | memcpy(ptr, blob, blob_len); | 370 | if (flags & MUTATE_WIREDATA) { |
334 | 371 | mutate_blob(&p->reset_wire_data); | |
335 | return (blob_len); | 372 | mutate_blob(&p->info_wire_data); |
336 | } | 373 | mutate_blob(&p->set_pin_wire_data); |
337 | 374 | mutate_blob(&p->change_pin_wire_data); | |
338 | size_t | 375 | mutate_blob(&p->retry_wire_data); |
339 | LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize, | 376 | } |
340 | unsigned int seed) | ||
341 | { | ||
342 | struct param p; | ||
343 | uint8_t blob[16384]; | ||
344 | size_t blob_len; | ||
345 | |||
346 | memset(&p, 0, sizeof(p)); | ||
347 | |||
348 | if (unpack(data, size, &p) < 0) | ||
349 | return (pack_dummy(data, maxsize)); | ||
350 | |||
351 | p.seed = (int)seed; | ||
352 | |||
353 | mutate_string(p.pin1); | ||
354 | mutate_string(p.pin2); | ||
355 | |||
356 | mutate_blob(&p.reset_wire_data); | ||
357 | mutate_blob(&p.info_wire_data); | ||
358 | mutate_blob(&p.set_pin_wire_data); | ||
359 | mutate_blob(&p.change_pin_wire_data); | ||
360 | mutate_blob(&p.retry_wire_data); | ||
361 | |||
362 | blob_len = pack(blob, sizeof(blob), &p); | ||
363 | |||
364 | if (blob_len == 0 || blob_len > maxsize) | ||
365 | return (0); | ||
366 | |||
367 | memcpy(data, blob, blob_len); | ||
368 | |||
369 | return (blob_len); | ||
370 | } | 377 | } |
diff --git a/fuzz/libfuzzer.c b/fuzz/libfuzzer.c new file mode 100644 index 0000000..ac9c798 --- /dev/null +++ b/fuzz/libfuzzer.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2019 Yubico AB. All rights reserved. | ||
3 | * Use of this source code is governed by a BSD-style | ||
4 | * license that can be found in the LICENSE file. | ||
5 | */ | ||
6 | |||
7 | #include <err.h> | ||
8 | #include <fcntl.h> | ||
9 | #include <stdbool.h> | ||
10 | #include <stdint.h> | ||
11 | #include <stdio.h> | ||
12 | #include <stdlib.h> | ||
13 | #include <string.h> | ||
14 | #include <unistd.h> | ||
15 | |||
16 | #include "mutator_aux.h" | ||
17 | |||
18 | static bool debug; | ||
19 | static unsigned int flags = MUTATE_ALL; | ||
20 | static unsigned long long test_fail; | ||
21 | static unsigned long long test_total; | ||
22 | static unsigned long long mutate_fail; | ||
23 | static unsigned long long mutate_total; | ||
24 | |||
25 | int LLVMFuzzerInitialize(int *, char ***); | ||
26 | int LLVMFuzzerTestOneInput(const uint8_t *, size_t); | ||
27 | size_t LLVMFuzzerCustomMutator(uint8_t *, size_t, size_t, unsigned int); | ||
28 | |||
29 | static int | ||
30 | save_seed(const char *opt) | ||
31 | { | ||
32 | const char *path; | ||
33 | int fd = -1, status = 1; | ||
34 | void *buf = NULL; | ||
35 | const size_t buflen = 4096; | ||
36 | size_t n; | ||
37 | struct param *p = NULL; | ||
38 | |||
39 | if ((path = strchr(opt, '=')) == NULL || strlen(++path) == 0) { | ||
40 | warnx("usage: --fido-save-seed=<path>"); | ||
41 | goto fail; | ||
42 | } | ||
43 | |||
44 | if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, 0644)) == -1) { | ||
45 | warn("open %s", path); | ||
46 | goto fail; | ||
47 | } | ||
48 | |||
49 | if ((buf = malloc(buflen)) == NULL) { | ||
50 | warn("malloc"); | ||
51 | goto fail; | ||
52 | } | ||
53 | |||
54 | n = pack_dummy(buf, buflen); | ||
55 | |||
56 | if ((p = unpack(buf, n)) == NULL) { | ||
57 | warnx("unpack"); | ||
58 | goto fail; | ||
59 | } | ||
60 | |||
61 | if (write(fd, buf, n) != (ssize_t)n) { | ||
62 | warn("write %s", path); | ||
63 | goto fail; | ||
64 | } | ||
65 | |||
66 | status = 0; | ||
67 | fail: | ||
68 | if (fd != -1) | ||
69 | close(fd); | ||
70 | free(buf); | ||
71 | free(p); | ||
72 | |||
73 | return status; | ||
74 | } | ||
75 | |||
76 | static void | ||
77 | parse_mutate_flags(const char *opt, unsigned int *mutate_flags) | ||
78 | { | ||
79 | const char *f; | ||
80 | |||
81 | if ((f = strchr(opt, '=')) == NULL || strlen(++f) == 0) | ||
82 | errx(1, "usage: --fido-mutate=<flag>"); | ||
83 | |||
84 | if (strcmp(f, "seed") == 0) | ||
85 | *mutate_flags |= MUTATE_SEED; | ||
86 | else if (strcmp(f, "param") == 0) | ||
87 | *mutate_flags |= MUTATE_PARAM; | ||
88 | else if (strcmp(f, "wiredata") == 0) | ||
89 | *mutate_flags |= MUTATE_WIREDATA; | ||
90 | else | ||
91 | errx(1, "--fido-mutate: unknown flag '%s'", f); | ||
92 | } | ||
93 | |||
94 | int | ||
95 | LLVMFuzzerInitialize(int *argc, char ***argv) | ||
96 | { | ||
97 | unsigned int mutate_flags = 0; | ||
98 | |||
99 | for (int i = 0; i < *argc; i++) | ||
100 | if (strcmp((*argv)[i], "--fido-debug") == 0) { | ||
101 | debug = 1; | ||
102 | } else if (strncmp((*argv)[i], "--fido-save-seed=", 17) == 0) { | ||
103 | exit(save_seed((*argv)[i])); | ||
104 | } else if (strncmp((*argv)[i], "--fido-mutate=", 14) == 0) { | ||
105 | parse_mutate_flags((*argv)[i], &mutate_flags); | ||
106 | } | ||
107 | |||
108 | if (mutate_flags) | ||
109 | flags = mutate_flags; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | int | ||
115 | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) | ||
116 | { | ||
117 | struct param *p; | ||
118 | |||
119 | if (++test_total % 100000 == 0 && debug) { | ||
120 | double r = (double)test_fail/(double)test_total * 100.0; | ||
121 | fprintf(stderr, "%s: %llu/%llu (%.2f%%)\n", __func__, | ||
122 | test_fail, test_total, r); | ||
123 | } | ||
124 | |||
125 | if (size > 4096 || (p = unpack(data, size)) == NULL) | ||
126 | test_fail++; | ||
127 | else { | ||
128 | test(p); | ||
129 | free(p); | ||
130 | } | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | size_t | ||
136 | LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t maxsize, | ||
137 | unsigned int seed) NO_MSAN | ||
138 | { | ||
139 | struct param *p; | ||
140 | uint8_t blob[4096]; | ||
141 | size_t blob_len; | ||
142 | |||
143 | memset(&p, 0, sizeof(p)); | ||
144 | |||
145 | #ifdef WITH_MSAN | ||
146 | __msan_unpoison(data, maxsize); | ||
147 | #endif | ||
148 | |||
149 | if (++mutate_total % 100000 == 0 && debug) { | ||
150 | double r = (double)mutate_fail/(double)mutate_total * 100.0; | ||
151 | fprintf(stderr, "%s: %llu/%llu (%.2f%%)\n", __func__, | ||
152 | mutate_fail, mutate_total, r); | ||
153 | } | ||
154 | |||
155 | if ((p = unpack(data, size)) == NULL) { | ||
156 | mutate_fail++; | ||
157 | return pack_dummy(data, maxsize); | ||
158 | } | ||
159 | |||
160 | mutate(p, seed, flags); | ||
161 | |||
162 | if ((blob_len = pack(blob, sizeof(blob), p)) == 0 || | ||
163 | blob_len > sizeof(blob) || blob_len > maxsize) { | ||
164 | mutate_fail++; | ||
165 | free(p); | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | free(p); | ||
170 | |||
171 | memcpy(data, blob, blob_len); | ||
172 | |||
173 | return blob_len; | ||
174 | } | ||
diff --git a/fuzz/mutator_aux.c b/fuzz/mutator_aux.c index fe09438..98815e8 100644 --- a/fuzz/mutator_aux.c +++ b/fuzz/mutator_aux.c | |||
@@ -5,26 +5,28 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <assert.h> | 7 | #include <assert.h> |
8 | #include <cbor.h> | ||
8 | #include <stddef.h> | 9 | #include <stddef.h> |
9 | #include <stdint.h> | 10 | #include <stdint.h> |
10 | #include <stdio.h> | 11 | #include <stdio.h> |
11 | #include <stdlib.h> | 12 | #include <stdlib.h> |
12 | #include <string.h> | 13 | #include <string.h> |
13 | 14 | ||
15 | #include "fido.h" | ||
14 | #include "mutator_aux.h" | 16 | #include "mutator_aux.h" |
15 | 17 | ||
16 | size_t LLVMFuzzerMutate(uint8_t *, size_t, size_t); | 18 | size_t LLVMFuzzerMutate(uint8_t *, size_t, size_t); |
17 | 19 | ||
18 | static uint8_t *wire_data_ptr = NULL; | 20 | static const uint8_t *wire_data_ptr = NULL; |
19 | static size_t wire_data_len = 0; | 21 | static size_t wire_data_len = 0; |
20 | 22 | ||
21 | size_t | 23 | size_t |
22 | xstrlen(const char *s) | 24 | xstrlen(const char *s) |
23 | { | 25 | { |
24 | if (s == NULL) | 26 | if (s == NULL) |
25 | return (0); | 27 | return 0; |
26 | 28 | ||
27 | return (strlen(s)); | 29 | return strlen(s); |
28 | } | 30 | } |
29 | 31 | ||
30 | void | 32 | void |
@@ -33,6 +35,10 @@ consume(const void *body, size_t len) | |||
33 | const volatile uint8_t *ptr = body; | 35 | const volatile uint8_t *ptr = body; |
34 | volatile uint8_t x = 0; | 36 | volatile uint8_t x = 0; |
35 | 37 | ||
38 | #ifdef WITH_MSAN | ||
39 | __msan_check_mem_is_initialized(body, len); | ||
40 | #endif | ||
41 | |||
36 | while (len--) | 42 | while (len--) |
37 | x ^= *ptr++; | 43 | x ^= *ptr++; |
38 | } | 44 | } |
@@ -44,217 +50,87 @@ consume_str(const char *str) | |||
44 | } | 50 | } |
45 | 51 | ||
46 | int | 52 | int |
47 | unpack_int(uint8_t t, uint8_t **ptr, size_t *len, int *v) NO_MSAN | 53 | unpack_int(cbor_item_t *item, int *v) |
48 | { | ||
49 | size_t l; | ||
50 | |||
51 | if (*len < sizeof(t) || **ptr != t) | ||
52 | return (-1); | ||
53 | |||
54 | *ptr += sizeof(t); | ||
55 | *len -= sizeof(t); | ||
56 | |||
57 | if (*len < sizeof(l)) | ||
58 | return (-1); | ||
59 | |||
60 | memcpy(&l, *ptr, sizeof(l)); | ||
61 | *ptr += sizeof(l); | ||
62 | *len -= sizeof(l); | ||
63 | |||
64 | if (l != sizeof(*v) || *len < l) | ||
65 | return (-1); | ||
66 | |||
67 | memcpy(v, *ptr, sizeof(*v)); | ||
68 | *ptr += sizeof(*v); | ||
69 | *len -= sizeof(*v); | ||
70 | |||
71 | return (0); | ||
72 | } | ||
73 | |||
74 | int | ||
75 | unpack_string(uint8_t t, uint8_t **ptr, size_t *len, char *v) NO_MSAN | ||
76 | { | 54 | { |
77 | size_t l; | 55 | if (cbor_is_int(item) == false || |
78 | 56 | cbor_int_get_width(item) != CBOR_INT_64) | |
79 | if (*len < sizeof(t) || **ptr != t) | 57 | return -1; |
80 | return (-1); | ||
81 | |||
82 | *ptr += sizeof(t); | ||
83 | *len -= sizeof(t); | ||
84 | |||
85 | if (*len < sizeof(l)) | ||
86 | return (-1); | ||
87 | |||
88 | memcpy(&l, *ptr, sizeof(l)); | ||
89 | *ptr += sizeof(l); | ||
90 | *len -= sizeof(l); | ||
91 | 58 | ||
92 | if (*len < l || l >= MAXSTR) | 59 | if (cbor_isa_uint(item)) |
93 | return (-1); | 60 | *v = (int)cbor_get_uint64(item); |
94 | 61 | else | |
95 | memcpy(v, *ptr, l); | 62 | *v = (int)(-cbor_get_uint64(item) - 1); |
96 | v[l] = '\0'; | ||
97 | |||
98 | *ptr += l; | ||
99 | *len -= l; | ||
100 | |||
101 | return (0); | ||
102 | } | ||
103 | |||
104 | int | ||
105 | unpack_byte(uint8_t t, uint8_t **ptr, size_t *len, uint8_t *v) NO_MSAN | ||
106 | { | ||
107 | size_t l; | ||
108 | |||
109 | if (*len < sizeof(t) || **ptr != t) | ||
110 | return (-1); | ||
111 | |||
112 | *ptr += sizeof(t); | ||
113 | *len -= sizeof(t); | ||
114 | |||
115 | if (*len < sizeof(l)) | ||
116 | return (-1); | ||
117 | |||
118 | memcpy(&l, *ptr, sizeof(l)); | ||
119 | *ptr += sizeof(l); | ||
120 | *len -= sizeof(l); | ||
121 | |||
122 | if (l != sizeof(*v) || *len < l) | ||
123 | return (-1); | ||
124 | |||
125 | memcpy(v, *ptr, sizeof(*v)); | ||
126 | *ptr += sizeof(*v); | ||
127 | *len -= sizeof(*v); | ||
128 | |||
129 | return (0); | ||
130 | } | ||
131 | |||
132 | int | ||
133 | unpack_blob(uint8_t t, uint8_t **ptr, size_t *len, struct blob *v) NO_MSAN | ||
134 | { | ||
135 | size_t l; | ||
136 | |||
137 | v->len = 0; | ||
138 | |||
139 | if (*len < sizeof(t) || **ptr != t) | ||
140 | return (-1); | ||
141 | |||
142 | *ptr += sizeof(t); | ||
143 | *len -= sizeof(t); | ||
144 | |||
145 | if (*len < sizeof(l)) | ||
146 | return (-1); | ||
147 | |||
148 | memcpy(&l, *ptr, sizeof(l)); | ||
149 | *ptr += sizeof(l); | ||
150 | *len -= sizeof(l); | ||
151 | |||
152 | if (*len < l || l > sizeof(v->body)) | ||
153 | return (-1); | ||
154 | |||
155 | memcpy(v->body, *ptr, l); | ||
156 | *ptr += l; | ||
157 | *len -= l; | ||
158 | |||
159 | v->len = l; | ||
160 | 63 | ||
161 | return (0); | 64 | return 0; |
162 | } | 65 | } |
163 | 66 | ||
164 | int | 67 | int |
165 | pack_int(uint8_t t, uint8_t **ptr, size_t *len, int v) NO_MSAN | 68 | unpack_string(cbor_item_t *item, char *v) |
166 | { | 69 | { |
167 | const size_t l = sizeof(v); | 70 | size_t len; |
168 | 71 | ||
169 | if (*len < sizeof(t) + sizeof(l) + l) | 72 | if (cbor_isa_bytestring(item) == false || |
170 | return (-1); | 73 | (len = cbor_bytestring_length(item)) >= MAXSTR) |
74 | return -1; | ||
171 | 75 | ||
172 | (*ptr)[0] = t; | 76 | memcpy(v, cbor_bytestring_handle(item), len); |
173 | memcpy(&(*ptr)[sizeof(t)], &l, sizeof(l)); | 77 | v[len] = '\0'; |
174 | memcpy(&(*ptr)[sizeof(t) + sizeof(l)], &v, l); | ||
175 | 78 | ||
176 | *ptr += sizeof(t) + sizeof(l) + l; | 79 | return 0; |
177 | *len -= sizeof(t) + sizeof(l) + l; | ||
178 | |||
179 | return (0); | ||
180 | } | 80 | } |
181 | 81 | ||
182 | int | 82 | int |
183 | pack_string(uint8_t t, uint8_t **ptr, size_t *len, const char *v) NO_MSAN | 83 | unpack_byte(cbor_item_t *item, uint8_t *v) |
184 | { | 84 | { |
185 | const size_t l = strlen(v); | 85 | if (cbor_isa_uint(item) == false || |
186 | 86 | cbor_int_get_width(item) != CBOR_INT_8) | |
187 | if (*len < sizeof(t) + sizeof(l) + l) | 87 | return -1; |
188 | return (-1); | ||
189 | |||
190 | (*ptr)[0] = t; | ||
191 | memcpy(&(*ptr)[sizeof(t)], &l, sizeof(l)); | ||
192 | memcpy(&(*ptr)[sizeof(t) + sizeof(l)], v, l); | ||
193 | 88 | ||
194 | *ptr += sizeof(t) + sizeof(l) + l; | 89 | *v = cbor_get_uint8(item); |
195 | *len -= sizeof(t) + sizeof(l) + l; | ||
196 | 90 | ||
197 | return (0); | 91 | return 0; |
198 | } | 92 | } |
199 | 93 | ||
200 | int | 94 | int |
201 | pack_byte(uint8_t t, uint8_t **ptr, size_t *len, uint8_t v) NO_MSAN | 95 | unpack_blob(cbor_item_t *item, struct blob *v) |
202 | { | 96 | { |
203 | const size_t l = sizeof(v); | 97 | if (cbor_isa_bytestring(item) == false || |
98 | (v->len = cbor_bytestring_length(item)) > sizeof(v->body)) | ||
99 | return -1; | ||
204 | 100 | ||
205 | if (*len < sizeof(t) + sizeof(l) + l) | 101 | memcpy(v->body, cbor_bytestring_handle(item), v->len); |
206 | return (-1); | ||
207 | 102 | ||
208 | (*ptr)[0] = t; | 103 | return 0; |
209 | memcpy(&(*ptr)[sizeof(t)], &l, sizeof(l)); | ||
210 | memcpy(&(*ptr)[sizeof(t) + sizeof(l)], &v, l); | ||
211 | |||
212 | *ptr += sizeof(t) + sizeof(l) + l; | ||
213 | *len -= sizeof(t) + sizeof(l) + l; | ||
214 | |||
215 | return (0); | ||
216 | } | 104 | } |
217 | 105 | ||
218 | int | 106 | cbor_item_t * |
219 | pack_blob(uint8_t t, uint8_t **ptr, size_t *len, const struct blob *v) NO_MSAN | 107 | pack_int(int v) NO_MSAN |
220 | { | 108 | { |
221 | const size_t l = v->len; | 109 | if (v < 0) |
222 | 110 | return cbor_build_negint64((uint64_t)(-(int64_t)v - 1)); | |
223 | if (*len < sizeof(t) + sizeof(l) + l) | 111 | else |
224 | return (-1); | 112 | return cbor_build_uint64((uint64_t)v); |
225 | |||
226 | (*ptr)[0] = t; | ||
227 | memcpy(&(*ptr)[sizeof(t)], &l, sizeof(l)); | ||
228 | memcpy(&(*ptr)[sizeof(t) + sizeof(l)], v->body, l); | ||
229 | |||
230 | *ptr += sizeof(t) + sizeof(l) + l; | ||
231 | *len -= sizeof(t) + sizeof(l) + l; | ||
232 | |||
233 | return (0); | ||
234 | } | 113 | } |
235 | 114 | ||
236 | size_t | 115 | cbor_item_t * |
237 | len_int(void) | 116 | pack_string(const char *v) NO_MSAN |
238 | { | 117 | { |
239 | return (sizeof(uint8_t) + sizeof(size_t) + sizeof(int)); | 118 | if (strlen(v) >= MAXSTR) |
240 | } | 119 | return NULL; |
241 | 120 | ||
242 | size_t | 121 | return cbor_build_bytestring((const unsigned char *)v, strlen(v)); |
243 | len_string(int max) | ||
244 | { | ||
245 | return ((sizeof(uint8_t) + sizeof(size_t)) + (max ? MAXSTR - 1 : 0)); | ||
246 | } | 122 | } |
247 | 123 | ||
248 | size_t | 124 | cbor_item_t * |
249 | len_byte(void) | 125 | pack_byte(uint8_t v) NO_MSAN |
250 | { | 126 | { |
251 | return (sizeof(uint8_t) + sizeof(size_t) + sizeof(uint8_t)); | 127 | return cbor_build_uint8(v); |
252 | } | 128 | } |
253 | 129 | ||
254 | size_t | 130 | cbor_item_t * |
255 | len_blob(int max) | 131 | pack_blob(const struct blob *v) NO_MSAN |
256 | { | 132 | { |
257 | return (sizeof(uint8_t) + sizeof(size_t) + (max ? MAXBLOB : 0)); | 133 | return cbor_build_bytestring(v->body, v->len); |
258 | } | 134 | } |
259 | 135 | ||
260 | void | 136 | void |
@@ -284,13 +160,13 @@ mutate_string(char *s) | |||
284 | n = LLVMFuzzerMutate((uint8_t *)s, strlen(s), MAXSTR - 1); | 160 | n = LLVMFuzzerMutate((uint8_t *)s, strlen(s), MAXSTR - 1); |
285 | s[n] = '\0'; | 161 | s[n] = '\0'; |
286 | } | 162 | } |
287 | 163 | ||
288 | void * | 164 | void * |
289 | dev_open(const char *path) | 165 | dev_open(const char *path) |
290 | { | 166 | { |
291 | (void)path; | 167 | (void)path; |
292 | 168 | ||
293 | return ((void *)0xdeadbeef); | 169 | return (void *)0xdeadbeef; |
294 | } | 170 | } |
295 | 171 | ||
296 | void | 172 | void |
@@ -307,7 +183,7 @@ dev_read(void *handle, unsigned char *ptr, size_t len, int ms) | |||
307 | (void)ms; | 183 | (void)ms; |
308 | 184 | ||
309 | assert(handle == (void *)0xdeadbeef); | 185 | assert(handle == (void *)0xdeadbeef); |
310 | assert(len == 64); | 186 | assert(len >= CTAP_MIN_REPORT_LEN && len <= CTAP_MAX_REPORT_LEN); |
311 | 187 | ||
312 | if (wire_data_len < len) | 188 | if (wire_data_len < len) |
313 | n = wire_data_len; | 189 | n = wire_data_len; |
@@ -319,25 +195,26 @@ dev_read(void *handle, unsigned char *ptr, size_t len, int ms) | |||
319 | wire_data_ptr += n; | 195 | wire_data_ptr += n; |
320 | wire_data_len -= n; | 196 | wire_data_len -= n; |
321 | 197 | ||
322 | return ((int)n); | 198 | return (int)n; |
323 | } | 199 | } |
324 | 200 | ||
325 | int | 201 | int |
326 | dev_write(void *handle, const unsigned char *ptr, size_t len) | 202 | dev_write(void *handle, const unsigned char *ptr, size_t len) |
327 | { | 203 | { |
328 | assert(handle == (void *)0xdeadbeef); | 204 | assert(handle == (void *)0xdeadbeef); |
329 | assert(len == 64 + 1); | 205 | assert(len >= CTAP_MIN_REPORT_LEN + 1 && |
206 | len <= CTAP_MAX_REPORT_LEN + 1); | ||
330 | 207 | ||
331 | consume(ptr, len); | 208 | consume(ptr, len); |
332 | 209 | ||
333 | if (uniform_random(400) < 1) | 210 | if (uniform_random(400) < 1) |
334 | return (-1); | 211 | return -1; |
335 | 212 | ||
336 | return ((int)len); | 213 | return (int)len; |
337 | } | 214 | } |
338 | 215 | ||
339 | void | 216 | void |
340 | set_wire_data(uint8_t *ptr, size_t len) | 217 | set_wire_data(const uint8_t *ptr, size_t len) |
341 | { | 218 | { |
342 | wire_data_ptr = ptr; | 219 | wire_data_ptr = ptr; |
343 | wire_data_len = len; | 220 | wire_data_len = len; |
diff --git a/fuzz/mutator_aux.h b/fuzz/mutator_aux.h index d14e177..4a7e647 100644 --- a/fuzz/mutator_aux.h +++ b/fuzz/mutator_aux.h | |||
@@ -9,9 +9,10 @@ | |||
9 | 9 | ||
10 | #include <stddef.h> | 10 | #include <stddef.h> |
11 | #include <stdint.h> | 11 | #include <stdint.h> |
12 | #include <cbor.h> | ||
12 | 13 | ||
13 | /* | 14 | /* |
14 | * As of LLVM 7.0.1, MSAN support in libFuzzer was still experimental. | 15 | * As of LLVM 10.0.0, MSAN support in libFuzzer was still experimental. |
15 | * We therefore have to be careful when using our custom mutator, or | 16 | * We therefore have to be careful when using our custom mutator, or |
16 | * MSAN will flag uninitialised reads on memory populated by libFuzzer. | 17 | * MSAN will flag uninitialised reads on memory populated by libFuzzer. |
17 | * Since there is no way to suppress MSAN without regenerating object | 18 | * Since there is no way to suppress MSAN without regenerating object |
@@ -22,6 +23,7 @@ | |||
22 | 23 | ||
23 | #if defined(__has_feature) | 24 | #if defined(__has_feature) |
24 | # if __has_feature(memory_sanitizer) | 25 | # if __has_feature(memory_sanitizer) |
26 | # include <sanitizer/msan_interface.h> | ||
25 | # define NO_MSAN __attribute__((no_sanitize("memory"))) | 27 | # define NO_MSAN __attribute__((no_sanitize("memory"))) |
26 | # define WITH_MSAN 1 | 28 | # define WITH_MSAN 1 |
27 | # endif | 29 | # endif |
@@ -31,44 +33,49 @@ | |||
31 | # define NO_MSAN | 33 | # define NO_MSAN |
32 | #endif | 34 | #endif |
33 | 35 | ||
36 | #define MUTATE_SEED 0x01 | ||
37 | #define MUTATE_PARAM 0x02 | ||
38 | #define MUTATE_WIREDATA 0x04 | ||
39 | #define MUTATE_ALL (MUTATE_SEED | MUTATE_PARAM | MUTATE_WIREDATA) | ||
40 | |||
34 | #define MAXSTR 1024 | 41 | #define MAXSTR 1024 |
35 | #define MAXBLOB 3072 | 42 | #define MAXBLOB 3072 |
36 | 43 | ||
37 | #define GETLEN_MIN 0 | ||
38 | #define GETLEN_MAX 1 | ||
39 | |||
40 | struct blob { | 44 | struct blob { |
41 | uint8_t body[MAXBLOB]; | 45 | uint8_t body[MAXBLOB]; |
42 | size_t len; | 46 | size_t len; |
43 | }; | 47 | }; |
44 | 48 | ||
49 | struct param; | ||
50 | |||
51 | struct param *unpack(const uint8_t *, size_t); | ||
52 | size_t pack(uint8_t *, size_t, const struct param *); | ||
53 | size_t pack_dummy(uint8_t *, size_t); | ||
54 | void mutate(struct param *, unsigned int, unsigned int); | ||
55 | void test(const struct param *); | ||
56 | |||
45 | size_t xstrlen(const char *); | 57 | size_t xstrlen(const char *); |
46 | void consume(const void *, size_t); | 58 | void consume(const void *, size_t); |
47 | void consume_str(const char *); | 59 | void consume_str(const char *); |
48 | 60 | ||
49 | int unpack_blob(uint8_t, uint8_t **, size_t *, struct blob *); | 61 | int unpack_blob(cbor_item_t *, struct blob *); |
50 | int unpack_byte(uint8_t, uint8_t **, size_t *, uint8_t *); | 62 | int unpack_byte(cbor_item_t *, uint8_t *); |
51 | int unpack_int(uint8_t, uint8_t **, size_t *, int *); | 63 | int unpack_int(cbor_item_t *, int *); |
52 | int unpack_string(uint8_t, uint8_t **, size_t *, char *); | 64 | int unpack_string(cbor_item_t *, char *); |
53 | |||
54 | int pack_blob(uint8_t, uint8_t **, size_t *, const struct blob *); | ||
55 | int pack_byte(uint8_t, uint8_t **, size_t *, uint8_t); | ||
56 | int pack_int(uint8_t, uint8_t **, size_t *, int); | ||
57 | int pack_string(uint8_t, uint8_t **, size_t *, const char *); | ||
58 | 65 | ||
59 | size_t len_int(void); | 66 | cbor_item_t *pack_blob(const struct blob *); |
60 | size_t len_string(int); | 67 | cbor_item_t *pack_byte(uint8_t); |
61 | size_t len_byte(void); | 68 | cbor_item_t *pack_int(int); |
62 | size_t len_blob(int); | 69 | cbor_item_t *pack_string(const char *); |
63 | 70 | ||
64 | void mutate_byte(uint8_t *); | 71 | void mutate_byte(uint8_t *); |
65 | void mutate_int(int *); | 72 | void mutate_int(int *); |
66 | void mutate_blob(struct blob *); | 73 | void mutate_blob(struct blob *); |
67 | void mutate_string(char *); | 74 | void mutate_string(char *); |
68 | 75 | ||
69 | void * dev_open(const char *); | 76 | void *dev_open(const char *); |
70 | void dev_close(void *); | 77 | void dev_close(void *); |
71 | void set_wire_data(uint8_t *, size_t); | 78 | void set_wire_data(const uint8_t *, size_t); |
72 | int dev_read(void *, unsigned char *, size_t, int); | 79 | int dev_read(void *, unsigned char *, size_t, int); |
73 | int dev_write(void *, const unsigned char *, size_t); | 80 | int dev_write(void *, const unsigned char *, size_t); |
74 | 81 | ||
diff --git a/fuzz/prng.c b/fuzz/prng.c index fa6d4e4..61114ac 100755..100644 --- a/fuzz/prng.c +++ b/fuzz/prng.c | |||
@@ -63,7 +63,8 @@ void init_genrand(unsigned long s) | |||
63 | mt[0]= s & 0xffffffffUL; | 63 | mt[0]= s & 0xffffffffUL; |
64 | for (mti=1; mti<N; mti++) { | 64 | for (mti=1; mti<N; mti++) { |
65 | mt[mti] = | 65 | mt[mti] = |
66 | (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); | 66 | (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + |
67 | (unsigned long)mti); | ||
67 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ | 68 | /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ |
68 | /* In the previous versions, MSBs of the seed affect */ | 69 | /* In the previous versions, MSBs of the seed affect */ |
69 | /* only MSBs of the array mt[]. */ | 70 | /* only MSBs of the array mt[]. */ |
diff --git a/fuzz/report.tgz b/fuzz/report.tgz index 8a002f0..6f02fc5 100644 --- a/fuzz/report.tgz +++ b/fuzz/report.tgz | |||
Binary files differ | |||
diff --git a/fuzz/summary.txt b/fuzz/summary.txt index da9d165..3a1ac21 100644 --- a/fuzz/summary.txt +++ b/fuzz/summary.txt | |||
@@ -1,6 +1,6 @@ | |||
1 | Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover | 1 | Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover |
2 | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 2 | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3 | fuzz/prng.c 31 0 100.00% 2 0 100.00% 48 0 100.00% | 3 | fuzz/prng.c 31 0 100.00% 2 0 100.00% 49 0 100.00% |
4 | fuzz/uniform_random.c 7 1 85.71% 1 0 100.00% 23 1 95.65% | 4 | fuzz/uniform_random.c 7 1 85.71% 1 0 100.00% 23 1 95.65% |
5 | fuzz/wrap.c 6 0 100.00% 1 0 100.00% 7 0 100.00% | 5 | fuzz/wrap.c 6 0 100.00% 1 0 100.00% 7 0 100.00% |
6 | openbsd-compat/explicit_bzero.c 4 0 100.00% 1 0 100.00% 12 0 100.00% | 6 | openbsd-compat/explicit_bzero.c 4 0 100.00% 1 0 100.00% 12 0 100.00% |
@@ -8,34 +8,35 @@ openbsd-compat/recallocarray.c 41 7 82.93% | |||
8 | openbsd-compat/strlcat.c 12 1 91.67% 1 0 100.00% 25 1 96.00% | 8 | openbsd-compat/strlcat.c 12 1 91.67% 1 0 100.00% 25 1 96.00% |
9 | openbsd-compat/timingsafe_bcmp.c 4 0 100.00% 1 0 100.00% 8 0 100.00% | 9 | openbsd-compat/timingsafe_bcmp.c 4 0 100.00% 1 0 100.00% 8 0 100.00% |
10 | src/aes256.c 56 0 100.00% 2 0 100.00% 82 0 100.00% | 10 | src/aes256.c 56 0 100.00% 2 0 100.00% 82 0 100.00% |
11 | src/assert.c 566 43 92.40% 53 1 98.11% 900 87 90.33% | 11 | src/assert.c 566 24 95.76% 53 1 98.11% 900 50 94.44% |
12 | src/authkey.c 44 0 100.00% 5 0 100.00% 75 0 100.00% | 12 | src/authkey.c 44 0 100.00% 5 0 100.00% 75 0 100.00% |
13 | src/bio.c 418 20 95.22% 49 2 95.92% 661 22 96.67% | 13 | src/bio.c 418 20 95.22% 49 2 95.92% 661 22 96.67% |
14 | src/blob.c 39 1 97.44% 7 0 100.00% 73 4 94.52% | 14 | src/blob.c 39 0 100.00% 7 0 100.00% 73 0 100.00% |
15 | src/buf.c 8 1 87.50% 2 0 100.00% 20 1 95.00% | 15 | src/buf.c 8 1 87.50% 2 0 100.00% 20 1 95.00% |
16 | src/cbor.c 884 70 92.08% 52 2 96.15% 1371 106 92.27% | 16 | src/cbor.c 883 6 99.32% 52 0 100.00% 1364 17 98.75% |
17 | src/cred.c 534 51 90.45% 55 1 98.18% 830 78 90.60% | 17 | src/cred.c 536 23 95.71% 57 1 98.25% 836 29 96.53% |
18 | src/credman.c 376 18 95.21% 38 0 100.00% 589 15 97.45% | 18 | src/credman.c 385 18 95.32% 38 0 100.00% 595 16 97.31% |
19 | src/dev.c 201 85 57.71% 26 8 69.23% 294 128 56.46% | 19 | src/dev.c 334 90 73.05% 33 8 75.76% 466 140 69.96% |
20 | src/ecdh.c 68 0 100.00% 2 0 100.00% 104 0 100.00% | 20 | src/ecdh.c 68 0 100.00% 2 0 100.00% 104 0 100.00% |
21 | src/eddsa.c 54 0 100.00% 8 0 100.00% 79 0 100.00% | 21 | src/eddsa.c 54 0 100.00% 8 0 100.00% 79 0 100.00% |
22 | src/err.c 108 108 0.00% 1 1 0.00% 112 112 0.00% | 22 | src/err.c 112 8 92.86% 1 0 100.00% 116 8 93.10% |
23 | src/es256.c 278 0 100.00% 16 0 100.00% 377 0 100.00% | 23 | src/es256.c 280 0 100.00% 16 0 100.00% 398 0 100.00% |
24 | src/hid.c 16 16 0.00% 8 8 0.00% 38 38 0.00% | 24 | src/hid.c 16 16 0.00% 8 8 0.00% 38 38 0.00% |
25 | src/hid_linux.c 166 166 0.00% 12 12 0.00% 292 292 0.00% | 25 | src/hid_linux.c 235 235 0.00% 19 19 0.00% 416 416 0.00% |
26 | src/info.c 146 0 100.00% 31 0 100.00% 304 0 100.00% | 26 | src/info.c 152 0 100.00% 34 0 100.00% 319 0 100.00% |
27 | src/io.c 123 5 95.93% 10 0 100.00% 218 11 94.95% | 27 | src/io.c 156 9 94.23% 10 0 100.00% 236 11 95.34% |
28 | src/iso7816.c 18 1 94.44% 5 0 100.00% 47 0 100.00% | 28 | src/iso7816.c 18 1 94.44% 5 0 100.00% 47 0 100.00% |
29 | src/log.c 34 2 94.12% 5 1 80.00% 50 3 94.00% | 29 | src/log.c 34 2 94.12% 5 1 80.00% 50 3 94.00% |
30 | src/pin.c 248 0 100.00% 16 0 100.00% 365 0 100.00% | 30 | src/pin.c 248 0 100.00% 16 0 100.00% 365 0 100.00% |
31 | src/reset.c 19 0 100.00% 3 0 100.00% 22 0 100.00% | 31 | src/reset.c 19 0 100.00% 3 0 100.00% 22 0 100.00% |
32 | src/rs256.c 102 29 71.57% 8 3 62.50% 140 44 68.57% | 32 | src/rs256.c 102 6 94.12% 8 0 100.00% 140 13 90.71% |
33 | src/u2f.c 443 28 93.68% 13 0 100.00% 699 52 92.56% | 33 | src/u2f.c 491 9 98.17% 15 0 100.00% 774 18 97.67% |
34 | 34 | ||
35 | Files which contain no functions: | 35 | Files which contain no functions: |
36 | openbsd-compat/time.h 0 0 - 0 0 - 0 0 - | ||
36 | src/extern.h 0 0 - 0 0 - 0 0 - | 37 | src/extern.h 0 0 - 0 0 - 0 0 - |
37 | src/fido.h 0 0 - 0 0 - 0 0 - | 38 | src/fido.h 0 0 - 0 0 - 0 0 - |
38 | src/fido/err.h 0 0 - 0 0 - 0 0 - | 39 | src/fido/err.h 0 0 - 0 0 - 0 0 - |
39 | src/fido/param.h 0 0 - 0 0 - 0 0 - | 40 | src/fido/param.h 0 0 - 0 0 - 0 0 - |
40 | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 41 | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41 | TOTAL 5054 653 87.08% 435 39 91.03% 7914 1002 87.34% | 42 | TOTAL 5359 477 91.10% 456 40 91.23% 8349 791 90.53% |
diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt index 44e4a96..f0d9cb3 100644 --- a/man/CMakeLists.txt +++ b/man/CMakeLists.txt | |||
@@ -3,12 +3,10 @@ | |||
3 | # license that can be found in the LICENSE file. | 3 | # license that can be found in the LICENSE file. |
4 | 4 | ||
5 | find_program(MANDOC_PATH mandoc) | 5 | find_program(MANDOC_PATH mandoc) |
6 | message(STATUS "MANDOC_PATH: ${MANDOC_PATH}") | 6 | find_program(GZIP_PATH gzip) |
7 | 7 | ||
8 | if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "Linux") | 8 | message(STATUS "MANDOC_PATH: ${MANDOC_PATH}") |
9 | find_program(GZIP_PATH gzip) | 9 | message(STATUS "GZIP_PATH: ${GZIP_PATH}") |
10 | message(STATUS "GZIP_PATH: ${GZIP_PATH}") | ||
11 | endif() | ||
12 | 10 | ||
13 | list(APPEND MAN_SOURCES | 11 | list(APPEND MAN_SOURCES |
14 | eddsa_pk_new.3 | 12 | eddsa_pk_new.3 |
@@ -32,6 +30,7 @@ list(APPEND MAN_SOURCES | |||
32 | fido_cred_set_authdata.3 | 30 | fido_cred_set_authdata.3 |
33 | fido_cred_verify.3 | 31 | fido_cred_verify.3 |
34 | fido_dev_get_assert.3 | 32 | fido_dev_get_assert.3 |
33 | fido_dev_get_touch_begin.3 | ||
35 | fido_dev_info_manifest.3 | 34 | fido_dev_info_manifest.3 |
36 | fido_dev_make_cred.3 | 35 | fido_dev_make_cred.3 |
37 | fido_dev_open.3 | 36 | fido_dev_open.3 |
@@ -54,9 +53,13 @@ list(APPEND MAN_ALIAS | |||
54 | fido_assert_new fido_assert_clientdata_hash_len | 53 | fido_assert_new fido_assert_clientdata_hash_len |
55 | fido_assert_new fido_assert_clientdata_hash_ptr | 54 | fido_assert_new fido_assert_clientdata_hash_ptr |
56 | fido_assert_new fido_assert_count | 55 | fido_assert_new fido_assert_count |
56 | fido_assert_new fido_assert_flags | ||
57 | fido_assert_new fido_assert_free | 57 | fido_assert_new fido_assert_free |
58 | fido_assert_new fido_assert_hmac_secret_len | 58 | fido_assert_new fido_assert_hmac_secret_len |
59 | fido_assert_new fido_assert_hmac_secret_ptr | 59 | fido_assert_new fido_assert_hmac_secret_ptr |
60 | fido_assert_new fido_assert_id_len | ||
61 | fido_assert_new fido_assert_id_ptr | ||
62 | fido_assert_new fido_assert_rp_id | ||
60 | fido_assert_new fido_assert_sigcount | 63 | fido_assert_new fido_assert_sigcount |
61 | fido_assert_new fido_assert_sig_len | 64 | fido_assert_new fido_assert_sig_len |
62 | fido_assert_new fido_assert_sig_ptr | 65 | fido_assert_new fido_assert_sig_ptr |
@@ -95,34 +98,46 @@ list(APPEND MAN_ALIAS | |||
95 | fido_bio_template fido_bio_template_new | 98 | fido_bio_template fido_bio_template_new |
96 | fido_bio_template fido_bio_template_set_id | 99 | fido_bio_template fido_bio_template_set_id |
97 | fido_bio_template fido_bio_template_set_name | 100 | fido_bio_template fido_bio_template_set_name |
98 | fido_cbor_info_new fido_cbor_info_aaguid_len | 101 | fido_cbor_info_new fido_cbor_info_aaguid_len |
99 | fido_cbor_info_new fido_cbor_info_aaguid_ptr | 102 | fido_cbor_info_new fido_cbor_info_aaguid_ptr |
100 | fido_cbor_info_new fido_cbor_info_extensions_len | 103 | fido_cbor_info_new fido_cbor_info_extensions_len |
101 | fido_cbor_info_new fido_cbor_info_extensions_ptr | 104 | fido_cbor_info_new fido_cbor_info_extensions_ptr |
102 | fido_cbor_info_new fido_cbor_info_free | 105 | fido_cbor_info_new fido_cbor_info_free |
103 | fido_cbor_info_new fido_cbor_info_maxmsgsiz | 106 | fido_cbor_info_new fido_cbor_info_maxmsgsiz |
107 | fido_cbor_info_new fido_cbor_info_maxcredcntlst; | ||
108 | fido_cbor_info_new fido_cbor_info_maxcredidlen; | ||
104 | fido_cbor_info_new fido_cbor_info_fwversion | 109 | fido_cbor_info_new fido_cbor_info_fwversion |
105 | fido_cbor_info_new fido_cbor_info_options_len | 110 | fido_cbor_info_new fido_cbor_info_options_len |
106 | fido_cbor_info_new fido_cbor_info_options_name_ptr | 111 | fido_cbor_info_new fido_cbor_info_options_name_ptr |
107 | fido_cbor_info_new fido_cbor_info_options_value_ptr | 112 | fido_cbor_info_new fido_cbor_info_options_value_ptr |
108 | fido_cbor_info_new fido_cbor_info_protocols_len | 113 | fido_cbor_info_new fido_cbor_info_protocols_len |
109 | fido_cbor_info_new fido_cbor_info_protocols_ptr | 114 | fido_cbor_info_new fido_cbor_info_protocols_ptr |
110 | fido_cbor_info_new fido_cbor_info_versions_len | 115 | fido_cbor_info_new fido_cbor_info_versions_len |
111 | fido_cbor_info_new fido_cbor_info_versions_ptr | 116 | fido_cbor_info_new fido_cbor_info_versions_ptr |
112 | fido_cbor_info_new fido_dev_get_cbor_info | 117 | fido_cbor_info_new fido_dev_get_cbor_info |
113 | fido_cred_new fido_cred_authdata_len | 118 | fido_cred_new fido_cred_authdata_len |
114 | fido_cred_new fido_cred_authdata_ptr | 119 | fido_cred_new fido_cred_authdata_ptr |
115 | fido_cred_new fido_cred_clientdata_hash_len | 120 | fido_cred_new fido_cred_clientdata_hash_len |
116 | fido_cred_new fido_cred_clientdata_hash_ptr | 121 | fido_cred_new fido_cred_clientdata_hash_ptr |
122 | fido_cred_new fido_cred_display_name | ||
123 | fido_cred_new fido_cred_flags | ||
117 | fido_cred_new fido_cred_fmt | 124 | fido_cred_new fido_cred_fmt |
118 | fido_cred_new fido_cred_free | 125 | fido_cred_new fido_cred_free |
119 | fido_cred_new fido_cred_id_len | 126 | fido_cred_new fido_cred_id_len |
120 | fido_cred_new fido_cred_id_ptr | 127 | fido_cred_new fido_cred_id_ptr |
128 | fido_cred_new fido_cred_aaguid_len | ||
129 | fido_cred_new fido_cred_aaguid_ptr | ||
121 | fido_cred_new fido_cred_prot | 130 | fido_cred_new fido_cred_prot |
122 | fido_cred_new fido_cred_pubkey_len | 131 | fido_cred_new fido_cred_pubkey_len |
123 | fido_cred_new fido_cred_pubkey_ptr | 132 | fido_cred_new fido_cred_pubkey_ptr |
133 | fido_cred_new fido_cred_rp_id | ||
134 | fido_cred_new fido_cred_rp_name | ||
124 | fido_cred_new fido_cred_sig_len | 135 | fido_cred_new fido_cred_sig_len |
125 | fido_cred_new fido_cred_sig_ptr | 136 | fido_cred_new fido_cred_sig_ptr |
137 | fido_cred_new fido_cred_type | ||
138 | fido_cred_new fido_cred_user_name | ||
139 | fido_cred_new fido_cred_user_id_len | ||
140 | fido_cred_new fido_cred_user_id_ptr | ||
126 | fido_cred_new fido_cred_x5c_len | 141 | fido_cred_new fido_cred_x5c_len |
127 | fido_cred_new fido_cred_x5c_ptr | 142 | fido_cred_new fido_cred_x5c_ptr |
128 | fido_credman_metadata_new fido_credman_del_dev_rk | 143 | fido_credman_metadata_new fido_credman_del_dev_rk |
@@ -171,6 +186,8 @@ list(APPEND MAN_ALIAS | |||
171 | fido_dev_open fido_dev_force_u2f | 186 | fido_dev_open fido_dev_force_u2f |
172 | fido_dev_open fido_dev_free | 187 | fido_dev_open fido_dev_free |
173 | fido_dev_open fido_dev_is_fido2 | 188 | fido_dev_open fido_dev_is_fido2 |
189 | fido_dev_open fido_dev_supports_cred_prot | ||
190 | fido_dev_open fido_dev_supports_pin | ||
174 | fido_dev_open fido_dev_major | 191 | fido_dev_open fido_dev_major |
175 | fido_dev_open fido_dev_minor | 192 | fido_dev_open fido_dev_minor |
176 | fido_dev_open fido_dev_new | 193 | fido_dev_open fido_dev_new |
@@ -224,7 +241,7 @@ endforeach() | |||
224 | # man_gzip | 241 | # man_gzip |
225 | foreach(f ${MAN_SOURCES}) | 242 | foreach(f ${MAN_SOURCES}) |
226 | add_custom_command(OUTPUT ${f}.gz | 243 | add_custom_command(OUTPUT ${f}.gz |
227 | COMMAND gzip -c ${f} > ${f}.gz | 244 | COMMAND gzip -cn ${f} > ${f}.gz |
228 | DEPENDS ${f}) | 245 | DEPENDS ${f}) |
229 | list(APPEND GZ_FILES ${f}.gz) | 246 | list(APPEND GZ_FILES ${f}.gz) |
230 | endforeach() | 247 | endforeach() |
@@ -2,3 +2,6 @@ To generate .partial files for https://developers.yubico.com/: | |||
2 | 2 | ||
3 | $ make -C build man_symlink_html_partial | 3 | $ make -C build man_symlink_html_partial |
4 | $ (cd build/man && pax -p p -r -w *.partial /tmp/partial) | 4 | $ (cd build/man && pax -p p -r -w *.partial /tmp/partial) |
5 | |||
6 | Use mandoc 1.14.4. Otherwise, adjust dyc.css to mandoc's HTML | ||
7 | output. | ||
diff --git a/man/fido2-assert.1 b/man/fido2-assert.1 index 67883e2..e77e771 100644 --- a/man/fido2-assert.1 +++ b/man/fido2-assert.1 | |||
@@ -12,6 +12,7 @@ | |||
12 | .Nm | 12 | .Nm |
13 | .Fl G | 13 | .Fl G |
14 | .Op Fl dhpruv | 14 | .Op Fl dhpruv |
15 | .Op Fl t Ar option | ||
15 | .Op Fl i Ar input_file | 16 | .Op Fl i Ar input_file |
16 | .Op Fl o Ar output_file | 17 | .Op Fl o Ar output_file |
17 | .Ar device | 18 | .Ar device |
@@ -110,6 +111,29 @@ is specified, | |||
110 | .Nm | 111 | .Nm |
111 | will not expect a credential id in its input, and may output | 112 | will not expect a credential id in its input, and may output |
112 | multiple assertions. | 113 | multiple assertions. |
114 | .It Fl t Ar option | ||
115 | Toggles a key/value | ||
116 | .Ar option , | ||
117 | where | ||
118 | .Ar option | ||
119 | is a string of the form | ||
120 | .Dq key=value . | ||
121 | The options supported at present are: | ||
122 | .Bl -tag -width Ds | ||
123 | .It Cm up Ns = Ns Ar true|false | ||
124 | Asks the authenticator for user presence to be enabled or disabled. | ||
125 | .It Cm uv Ns = Ns Ar true|false | ||
126 | Asks the authenticator for user verification to be enabled or | ||
127 | disabled. | ||
128 | .It Cm pin Ns = Ns Ar true|false | ||
129 | Tells | ||
130 | .Nm | ||
131 | whether to prompt for a PIN and request user verification. | ||
132 | .El | ||
133 | .Pp | ||
134 | The | ||
135 | .Fl t | ||
136 | option may be specified multiple times. | ||
113 | .It Fl u | 137 | .It Fl u |
114 | Obtain an assertion using U2F. | 138 | Obtain an assertion using U2F. |
115 | By default, | 139 | By default, |
@@ -119,6 +143,10 @@ U2F otherwise. | |||
119 | .It Fl v | 143 | .It Fl v |
120 | If obtaining an assertion, prompt the user for a PIN and request | 144 | If obtaining an assertion, prompt the user for a PIN and request |
121 | user verification from the authenticator. | 145 | user verification from the authenticator. |
146 | If verifying an assertion, check whether the user verification bit | ||
147 | was signed by the authenticator. | ||
148 | .El | ||
149 | .Pp | ||
122 | If a | 150 | If a |
123 | .Em tty | 151 | .Em tty |
124 | is available, | 152 | is available, |
@@ -127,9 +155,6 @@ will use it to obtain the PIN. | |||
127 | Otherwise, | 155 | Otherwise, |
128 | .Em stdin | 156 | .Em stdin |
129 | is used. | 157 | is used. |
130 | If verifying an assertion, check whether the user verification bit | ||
131 | was signed by the authenticator. | ||
132 | .El | ||
133 | .Sh INPUT FORMAT | 158 | .Sh INPUT FORMAT |
134 | The input of | 159 | The input of |
135 | .Nm | 160 | .Nm |
@@ -140,7 +165,7 @@ When obtaining an assertion, | |||
140 | .Nm | 165 | .Nm |
141 | expects its input to consist of: | 166 | expects its input to consist of: |
142 | .Pp | 167 | .Pp |
143 | .Bl -enum -offset indent -compact | 168 | .Bl -enum -offset indent -compact |
144 | .It | 169 | .It |
145 | client data hash (base64 blob); | 170 | client data hash (base64 blob); |
146 | .It | 171 | .It |
diff --git a/man/fido2-cred.1 b/man/fido2-cred.1 index d9bf7d2..4132d26 100644 --- a/man/fido2-cred.1 +++ b/man/fido2-cred.1 | |||
@@ -12,6 +12,7 @@ | |||
12 | .Nm | 12 | .Nm |
13 | .Fl M | 13 | .Fl M |
14 | .Op Fl dhqruv | 14 | .Op Fl dhqruv |
15 | .Op Fl c Ar cred_protect | ||
15 | .Op Fl i Ar input_file | 16 | .Op Fl i Ar input_file |
16 | .Op Fl o Ar output_file | 17 | .Op Fl o Ar output_file |
17 | .Ar device | 18 | .Ar device |
@@ -19,6 +20,7 @@ | |||
19 | .Nm | 20 | .Nm |
20 | .Fl V | 21 | .Fl V |
21 | .Op Fl dhv | 22 | .Op Fl dhv |
23 | .Op Fl c Ar cred_protect | ||
22 | .Op Fl i Ar input_file | 24 | .Op Fl i Ar input_file |
23 | .Op Fl o Ar output_file | 25 | .Op Fl o Ar output_file |
24 | .Op Ar type | 26 | .Op Ar type |
@@ -89,6 +91,12 @@ to make a new credential on | |||
89 | Tells | 91 | Tells |
90 | .Nm | 92 | .Nm |
91 | to verify a credential. | 93 | to verify a credential. |
94 | .It Fl c Ar cred_protect | ||
95 | If making a credential, set the credential's protection level to | ||
96 | .Ar cred_protect . | ||
97 | If verifying a credential, check whether the credential's protection | ||
98 | level was signed by the authenticator as | ||
99 | .Ar cred_protect . | ||
92 | .It Fl d | 100 | .It Fl d |
93 | Causes | 101 | Causes |
94 | .Nm | 102 | .Nm |
diff --git a/man/fido_assert_new.3 b/man/fido_assert_new.3 index 0c2f92f..b1b1f2f 100644 --- a/man/fido_assert_new.3 +++ b/man/fido_assert_new.3 | |||
@@ -9,6 +9,7 @@ | |||
9 | .Nm fido_assert_new , | 9 | .Nm fido_assert_new , |
10 | .Nm fido_assert_free , | 10 | .Nm fido_assert_free , |
11 | .Nm fido_assert_count , | 11 | .Nm fido_assert_count , |
12 | .Nm fido_assert_rp_id , | ||
12 | .Nm fido_assert_user_display_name , | 13 | .Nm fido_assert_user_display_name , |
13 | .Nm fido_assert_user_icon , | 14 | .Nm fido_assert_user_icon , |
14 | .Nm fido_assert_user_name , | 15 | .Nm fido_assert_user_name , |
@@ -17,12 +18,15 @@ | |||
17 | .Nm fido_assert_hmac_secret_ptr , | 18 | .Nm fido_assert_hmac_secret_ptr , |
18 | .Nm fido_assert_user_id_ptr , | 19 | .Nm fido_assert_user_id_ptr , |
19 | .Nm fido_assert_sig_ptr , | 20 | .Nm fido_assert_sig_ptr , |
21 | .Nm fido_assert_id_ptr , | ||
20 | .Nm fido_assert_authdata_len , | 22 | .Nm fido_assert_authdata_len , |
21 | .Nm fido_assert_clientdata_hash_len , | 23 | .Nm fido_assert_clientdata_hash_len , |
22 | .Nm fido_assert_hmac_secret_len , | 24 | .Nm fido_assert_hmac_secret_len , |
23 | .Nm fido_assert_user_id_len , | 25 | .Nm fido_assert_user_id_len , |
24 | .Nm fido_assert_sig_len , | 26 | .Nm fido_assert_sig_len , |
25 | .Nm fido_assert_sigcount | 27 | .Nm fido_assert_id_len , |
28 | .Nm fido_assert_sigcount , | ||
29 | .Nm fido_assert_flags | ||
26 | .Nd FIDO 2 assertion API | 30 | .Nd FIDO 2 assertion API |
27 | .Sh SYNOPSIS | 31 | .Sh SYNOPSIS |
28 | .In fido.h | 32 | .In fido.h |
@@ -33,6 +37,8 @@ | |||
33 | .Ft size_t | 37 | .Ft size_t |
34 | .Fn fido_assert_count "const fido_assert_t *assert" | 38 | .Fn fido_assert_count "const fido_assert_t *assert" |
35 | .Ft const char * | 39 | .Ft const char * |
40 | .Fn fido_assert_rp_id "const fido_assert_t *assert" | ||
41 | .Ft const char * | ||
36 | .Fn fido_assert_user_display_name "const fido_assert_t *assert" "size_t idx" | 42 | .Fn fido_assert_user_display_name "const fido_assert_t *assert" "size_t idx" |
37 | .Ft const char * | 43 | .Ft const char * |
38 | .Fn fido_assert_user_icon "const fido_assert_t *assert" "size_t idx" | 44 | .Fn fido_assert_user_icon "const fido_assert_t *assert" "size_t idx" |
@@ -48,6 +54,8 @@ | |||
48 | .Fn fido_assert_user_id_ptr "const fido_assert_t *assert" "size_t idx" | 54 | .Fn fido_assert_user_id_ptr "const fido_assert_t *assert" "size_t idx" |
49 | .Ft const unsigned char * | 55 | .Ft const unsigned char * |
50 | .Fn fido_assert_sig_ptr "const fido_assert_t *assert" "size_t idx" | 56 | .Fn fido_assert_sig_ptr "const fido_assert_t *assert" "size_t idx" |
57 | .Ft const unsigned char * | ||
58 | .Fn fido_assert_id_ptr "const fido_assert_t *assert" "size_t idx" | ||
51 | .Ft size_t | 59 | .Ft size_t |
52 | .Fn fido_assert_authdata_len "const fido_assert_t *assert" "size_t idx" | 60 | .Fn fido_assert_authdata_len "const fido_assert_t *assert" "size_t idx" |
53 | .Ft size_t | 61 | .Ft size_t |
@@ -58,8 +66,12 @@ | |||
58 | .Fn fido_assert_user_id_len "const fido_assert_t *assert" "size_t idx" | 66 | .Fn fido_assert_user_id_len "const fido_assert_t *assert" "size_t idx" |
59 | .Ft size_t | 67 | .Ft size_t |
60 | .Fn fido_assert_sig_len "const fido_assert_t *assert" "size_t idx" | 68 | .Fn fido_assert_sig_len "const fido_assert_t *assert" "size_t idx" |
69 | .Ft size_t | ||
70 | .Fn fido_assert_id_len "const fido_assert_t *assert" "size_t idx" | ||
61 | .Ft uint32_t | 71 | .Ft uint32_t |
62 | .Fn fido_assert_sigcount "const fido_assert_t *assert" "size_t idx" | 72 | .Fn fido_assert_sigcount "const fido_assert_t *assert" "size_t idx" |
73 | .Ft uint8_t | ||
74 | .Fn fido_assert_flags "const fido_assert_t *assert" "size_t idx" | ||
63 | .Sh DESCRIPTION | 75 | .Sh DESCRIPTION |
64 | FIDO 2 assertions are abstracted in | 76 | FIDO 2 assertions are abstracted in |
65 | .Em libfido2 | 77 | .Em libfido2 |
@@ -110,6 +122,12 @@ function returns the number of statements in | |||
110 | .Fa assert . | 122 | .Fa assert . |
111 | .Pp | 123 | .Pp |
112 | The | 124 | The |
125 | .Fn fido_assert_rp_id | ||
126 | function returns a pointer to a NUL-terminated string holding the | ||
127 | relying party ID of | ||
128 | .Fa assert . | ||
129 | .Pp | ||
130 | The | ||
113 | .Fn fido_assert_user_display_name , | 131 | .Fn fido_assert_user_display_name , |
114 | .Fn fido_assert_user_icon , | 132 | .Fn fido_assert_user_icon , |
115 | and | 133 | and |
@@ -126,10 +144,11 @@ The | |||
126 | .Fn fido_assert_user_id_ptr , | 144 | .Fn fido_assert_user_id_ptr , |
127 | .Fn fido_assert_authdata_ptr , | 145 | .Fn fido_assert_authdata_ptr , |
128 | .Fn fido_assert_hmac_secret_ptr , | 146 | .Fn fido_assert_hmac_secret_ptr , |
147 | .Fn fido_assert_sig_ptr , | ||
129 | and | 148 | and |
130 | .Fn fido_assert_sig_ptr | 149 | .Fn fido_assert_id_ptr |
131 | functions return pointers to the user ID, authenticator data, | 150 | functions return pointers to the user ID, authenticator data, |
132 | hmac-secret, and signature attributes of statement | 151 | hmac-secret, signature, and credential ID attributes of statement |
133 | .Fa idx | 152 | .Fa idx |
134 | in | 153 | in |
135 | .Fa assert . | 154 | .Fa assert . |
@@ -137,8 +156,9 @@ The | |||
137 | .Fn fido_assert_user_id_len , | 156 | .Fn fido_assert_user_id_len , |
138 | .Fn fido_assert_authdata_len , | 157 | .Fn fido_assert_authdata_len , |
139 | .Fn fido_assert_hmac_secret_len , | 158 | .Fn fido_assert_hmac_secret_len , |
159 | .Fn fido_assert_sig_len , | ||
140 | and | 160 | and |
141 | .Fn fido_assert_sig_len | 161 | .Fn fido_assert_id_len |
142 | functions can be used to retrieve the corresponding length of a | 162 | functions can be used to retrieve the corresponding length of a |
143 | specific attribute. | 163 | specific attribute. |
144 | .Pp | 164 | .Pp |
@@ -149,6 +169,13 @@ function can be used to obtain the signature counter of statement | |||
149 | in | 169 | in |
150 | .Fa assert . | 170 | .Fa assert . |
151 | .Pp | 171 | .Pp |
172 | The | ||
173 | .Fn fido_assert_flags | ||
174 | function returns the authenticator data flags of statement | ||
175 | .Fa idx | ||
176 | in | ||
177 | .Fa assert . | ||
178 | .Pp | ||
152 | Please note that the first statement in | 179 | Please note that the first statement in |
153 | .Fa assert | 180 | .Fa assert |
154 | has an | 181 | has an |
diff --git a/man/fido_cbor_info_new.3 b/man/fido_cbor_info_new.3 index 3e7de1f..ee942e6 100644 --- a/man/fido_cbor_info_new.3 +++ b/man/fido_cbor_info_new.3 | |||
@@ -21,6 +21,8 @@ | |||
21 | .Nm fido_cbor_info_versions_len , | 21 | .Nm fido_cbor_info_versions_len , |
22 | .Nm fido_cbor_info_options_len , | 22 | .Nm fido_cbor_info_options_len , |
23 | .Nm fido_cbor_info_maxmsgsiz , | 23 | .Nm fido_cbor_info_maxmsgsiz , |
24 | .Nm fido_cbor_info_maxcredcntlst , | ||
25 | .Nm fido_cbor_info_maxcredidlen , | ||
24 | .Nm fido_cbor_info_fwversion | 26 | .Nm fido_cbor_info_fwversion |
25 | .Nd FIDO 2 CBOR Info API | 27 | .Nd FIDO 2 CBOR Info API |
26 | .Sh SYNOPSIS | 28 | .Sh SYNOPSIS |
@@ -56,6 +58,10 @@ | |||
56 | .Ft uint64_t | 58 | .Ft uint64_t |
57 | .Fn fido_cbor_info_maxmsgsiz "const fido_cbor_info_t *ci" | 59 | .Fn fido_cbor_info_maxmsgsiz "const fido_cbor_info_t *ci" |
58 | .Ft uint64_t | 60 | .Ft uint64_t |
61 | .Fn fido_cbor_info_maxcredcntlst "const fido_cbor_info_t *ci" | ||
62 | .Ft uint64_t | ||
63 | .Fn fido_cbor_info_maxcredidlen "const fido_cbor_info_t *ci" | ||
64 | .Ft uint64_t | ||
59 | .Fn fido_cbor_info_fwversion "const fido_cbor_info_t *ci" | 65 | .Fn fido_cbor_info_fwversion "const fido_cbor_info_t *ci" |
60 | .Sh DESCRIPTION | 66 | .Sh DESCRIPTION |
61 | The | 67 | The |
@@ -103,8 +109,8 @@ The | |||
103 | .Fn fido_cbor_info_protocols_ptr , | 109 | .Fn fido_cbor_info_protocols_ptr , |
104 | and | 110 | and |
105 | .Fn fido_cbor_info_versions_ptr | 111 | .Fn fido_cbor_info_versions_ptr |
106 | functions return pointers to the AAGUID, supported extensions, | 112 | functions return pointers to the authenticator attestation GUID, |
107 | PIN protocol and CTAP version strings of | 113 | supported extensions, PIN protocol and CTAP version strings of |
108 | .Fa ci . | 114 | .Fa ci . |
109 | The corresponding length of a given attribute can be | 115 | The corresponding length of a given attribute can be |
110 | obtained by | 116 | obtained by |
@@ -131,6 +137,18 @@ function returns the maximum message size attribute of | |||
131 | .Fa ci . | 137 | .Fa ci . |
132 | .Pp | 138 | .Pp |
133 | The | 139 | The |
140 | .Fn fido_cbor_info_maxcredcntlst | ||
141 | function returns the maximum supported number of credentials in | ||
142 | a single credential ID list as reported in | ||
143 | .Fa ci . | ||
144 | .Pp | ||
145 | The | ||
146 | .Fn fido_cbor_info_maxcredidlen | ||
147 | function returns the maximum supported length of a credential ID | ||
148 | as reported in | ||
149 | .Fa ci . | ||
150 | .Pp | ||
151 | The | ||
134 | .Fn fido_cbor_info_fwversion | 152 | .Fn fido_cbor_info_fwversion |
135 | function returns the firmware version attribute of | 153 | function returns the firmware version attribute of |
136 | .Fa ci . | 154 | .Fa ci . |
diff --git a/man/fido_cred_new.3 b/man/fido_cred_new.3 index 22af60c..d2023eb 100644 --- a/man/fido_cred_new.3 +++ b/man/fido_cred_new.3 | |||
@@ -10,18 +10,28 @@ | |||
10 | .Nm fido_cred_free , | 10 | .Nm fido_cred_free , |
11 | .Nm fido_cred_prot , | 11 | .Nm fido_cred_prot , |
12 | .Nm fido_cred_fmt , | 12 | .Nm fido_cred_fmt , |
13 | .Nm fido_cred_rp_id , | ||
14 | .Nm fido_cred_rp_name , | ||
15 | .Nm fido_cred_user_name , | ||
16 | .Nm fido_cred_display_name , | ||
13 | .Nm fido_cred_authdata_ptr , | 17 | .Nm fido_cred_authdata_ptr , |
14 | .Nm fido_cred_clientdata_hash_ptr , | 18 | .Nm fido_cred_clientdata_hash_ptr , |
15 | .Nm fido_cred_id_ptr , | 19 | .Nm fido_cred_id_ptr , |
20 | .Nm fido_cred_aaguid_ptr , | ||
16 | .Nm fido_cred_pubkey_ptr , | 21 | .Nm fido_cred_pubkey_ptr , |
17 | .Nm fido_cred_sig_ptr , | 22 | .Nm fido_cred_sig_ptr , |
23 | .Nm fido_cred_user_id_ptr , | ||
18 | .Nm fido_cred_x5c_ptr , | 24 | .Nm fido_cred_x5c_ptr , |
19 | .Nm fido_cred_authdata_len , | 25 | .Nm fido_cred_authdata_len , |
20 | .Nm fido_cred_clientdata_hash_len , | 26 | .Nm fido_cred_clientdata_hash_len , |
21 | .Nm fido_cred_id_len , | 27 | .Nm fido_cred_id_len , |
28 | .Nm fido_cred_aaguid_len , | ||
22 | .Nm fido_cred_pubkey_len , | 29 | .Nm fido_cred_pubkey_len , |
23 | .Nm fido_cred_sig_len , | 30 | .Nm fido_cred_sig_len , |
24 | .Nm fido_cred_x5c_len | 31 | .Nm fido_cred_user_id_len , |
32 | .Nm fido_cred_x5c_len , | ||
33 | .Nm fido_cred_type , | ||
34 | .Nm fido_cred_flags | ||
25 | .Nd FIDO 2 credential API | 35 | .Nd FIDO 2 credential API |
26 | .Sh SYNOPSIS | 36 | .Sh SYNOPSIS |
27 | .In fido.h | 37 | .In fido.h |
@@ -33,6 +43,14 @@ | |||
33 | .Fn fido_cred_prot "fido_cred_t *cred" | 43 | .Fn fido_cred_prot "fido_cred_t *cred" |
34 | .Ft const char * | 44 | .Ft const char * |
35 | .Fn fido_cred_fmt "const fido_cred_t *cred" | 45 | .Fn fido_cred_fmt "const fido_cred_t *cred" |
46 | .Ft const char * | ||
47 | .Fn fido_cred_rp_id "const fido_cred_t *cred" | ||
48 | .Ft const char * | ||
49 | .Fn fido_cred_rp_name "const fido_cred_t *cred" | ||
50 | .Ft const char * | ||
51 | .Fn fido_cred_user_name "const fido_cred_t *cred" | ||
52 | .Ft const char * | ||
53 | .Fn fido_cred_display_name "const fido_cred_t *cred" | ||
36 | .Ft const unsigned char * | 54 | .Ft const unsigned char * |
37 | .Fn fido_cred_authdata_ptr "const fido_cred_t *cred" | 55 | .Fn fido_cred_authdata_ptr "const fido_cred_t *cred" |
38 | .Ft const unsigned char * | 56 | .Ft const unsigned char * |
@@ -40,10 +58,14 @@ | |||
40 | .Ft const unsigned char * | 58 | .Ft const unsigned char * |
41 | .Fn fido_cred_id_ptr "const fido_cred_t *cred" | 59 | .Fn fido_cred_id_ptr "const fido_cred_t *cred" |
42 | .Ft const unsigned char * | 60 | .Ft const unsigned char * |
61 | .Fn fido_cred_aaguid_ptr "const fido_cred_t *cred" | ||
62 | .Ft const unsigned char * | ||
43 | .Fn fido_cred_pubkey_ptr "const fido_cred_t *cred" | 63 | .Fn fido_cred_pubkey_ptr "const fido_cred_t *cred" |
44 | .Ft const unsigned char * | 64 | .Ft const unsigned char * |
45 | .Fn fido_cred_sig_ptr "const fido_cred_t *cred" | 65 | .Fn fido_cred_sig_ptr "const fido_cred_t *cred" |
46 | .Ft const unsigned char * | 66 | .Ft const unsigned char * |
67 | .Fn fido_cred_user_id_ptr "const fido_cred_t *cred" | ||
68 | .Ft const unsigned char * | ||
47 | .Fn fido_cred_x5c_ptr "const fido_cred_t *cred" | 69 | .Fn fido_cred_x5c_ptr "const fido_cred_t *cred" |
48 | .Ft size_t | 70 | .Ft size_t |
49 | .Fn fido_cred_authdata_len "const fido_cred_t *cred" | 71 | .Fn fido_cred_authdata_len "const fido_cred_t *cred" |
@@ -52,11 +74,19 @@ | |||
52 | .Ft size_t | 74 | .Ft size_t |
53 | .Fn fido_cred_id_len "const fido_cred_t *cred" | 75 | .Fn fido_cred_id_len "const fido_cred_t *cred" |
54 | .Ft size_t | 76 | .Ft size_t |
77 | .Fn fido_cred_aaguid_len "const fido_cred_t *cred" | ||
78 | .Ft size_t | ||
55 | .Fn fido_cred_pubkey_len "const fido_cred_t *cred" | 79 | .Fn fido_cred_pubkey_len "const fido_cred_t *cred" |
56 | .Ft size_t | 80 | .Ft size_t |
57 | .Fn fido_cred_sig_len "const fido_cred_t *cred" | 81 | .Fn fido_cred_sig_len "const fido_cred_t *cred" |
58 | .Ft size_t | 82 | .Ft size_t |
83 | .Fn fido_cred_user_id_len "const fido_cred_t *cred" | ||
84 | .Ft size_t | ||
59 | .Fn fido_cred_x5c_len "const fido_cred_t *cred" | 85 | .Fn fido_cred_x5c_len "const fido_cred_t *cred" |
86 | .Ft int | ||
87 | .Fn fido_cred_type "const fido_cred_t *cred" | ||
88 | .Ft uint8_t | ||
89 | .Fn fido_cred_flags "const fido_cred_t *cred" | ||
60 | .Sh DESCRIPTION | 90 | .Sh DESCRIPTION |
61 | FIDO 2 credentials are abstracted in | 91 | FIDO 2 credentials are abstracted in |
62 | .Em libfido2 | 92 | .Em libfido2 |
@@ -120,15 +150,30 @@ or NULL if | |||
120 | does not have a format set. | 150 | does not have a format set. |
121 | .Pp | 151 | .Pp |
122 | The | 152 | The |
153 | .Fn fido_cred_rp_id , | ||
154 | .Fn fido_cred_rp_name , | ||
155 | .Fn fido_cred_user_name , | ||
156 | and | ||
157 | .Fn fido_cred_display_name | ||
158 | functions return pointers to NUL-terminated strings holding the | ||
159 | relying party ID, relying party name, user name, and user display | ||
160 | name attributes of | ||
161 | .Fa cred , | ||
162 | or NULL if the respective entry is not set. | ||
163 | .Pp | ||
164 | The | ||
123 | .Fn fido_cred_authdata_ptr , | 165 | .Fn fido_cred_authdata_ptr , |
124 | .Fn fido_cred_clientdata_hash_ptr , | 166 | .Fn fido_cred_clientdata_hash_ptr , |
125 | .Fn fido_cred_id_ptr , | 167 | .Fn fido_cred_id_ptr , |
168 | .Fn fido_cred_aaguid_ptr , | ||
126 | .Fn fido_cred_pubkey_ptr , | 169 | .Fn fido_cred_pubkey_ptr , |
127 | .Fn fido_cred_sig_ptr , | 170 | .Fn fido_cred_sig_ptr , |
171 | .Fn fido_cred_user_id_ptr , | ||
128 | and | 172 | and |
129 | .Fn fido_cred_x5c_ptr | 173 | .Fn fido_cred_x5c_ptr |
130 | functions return pointers to the authenticator data, client data | 174 | functions return pointers to the authenticator data, client data |
131 | hash, ID, public key, signature and x509 certificate parts of | 175 | hash, ID, authenticator attestation GUID, public key, signature, |
176 | user ID, and x509 certificate parts of | ||
132 | .Fa cred , | 177 | .Fa cred , |
133 | or NULL if the respective entry is not set. | 178 | or NULL if the respective entry is not set. |
134 | .Pp | 179 | .Pp |
@@ -136,12 +181,25 @@ The corresponding length can be obtained by | |||
136 | .Fn fido_cred_authdata_len , | 181 | .Fn fido_cred_authdata_len , |
137 | .Fn fido_cred_clientdata_hash_len , | 182 | .Fn fido_cred_clientdata_hash_len , |
138 | .Fn fido_cred_id_len , | 183 | .Fn fido_cred_id_len , |
184 | .Fn fido_cred_aaguid_len , | ||
139 | .Fn fido_cred_pubkey_len , | 185 | .Fn fido_cred_pubkey_len , |
186 | .Fn fido_cred_sig_len , | ||
187 | .Fn fido_cred_user_id_len , | ||
140 | and | 188 | and |
141 | .Fn fido_cred_sig_len . | 189 | .Fn fido_cred_x5c_len . |
142 | .Pp | 190 | .Pp |
143 | The authenticator data, x509 certificate, and signature parts of a | 191 | The authenticator data, x509 certificate, and signature parts of a |
144 | credential are typically passed to a FIDO 2 server for verification. | 192 | credential are typically passed to a FIDO 2 server for verification. |
193 | .Pp | ||
194 | The | ||
195 | .Fn fido_cred_type | ||
196 | function returns the COSE algorithm of | ||
197 | .Fa cred . | ||
198 | .Pp | ||
199 | The | ||
200 | .Fn fido_cred_flags | ||
201 | function returns the authenticator data flags of | ||
202 | .Fa cred . | ||
145 | .Sh RETURN VALUES | 203 | .Sh RETURN VALUES |
146 | The authenticator data returned by | 204 | The authenticator data returned by |
147 | .Fn fido_cred_authdata_ptr | 205 | .Fn fido_cred_authdata_ptr |
@@ -152,6 +210,7 @@ If not NULL, pointers returned by | |||
152 | .Fn fido_cred_authdata_ptr , | 210 | .Fn fido_cred_authdata_ptr , |
153 | .Fn fido_cred_clientdata_hash_ptr , | 211 | .Fn fido_cred_clientdata_hash_ptr , |
154 | .Fn fido_cred_id_ptr , | 212 | .Fn fido_cred_id_ptr , |
213 | .Fn fido_cred_aaguid_ptr , | ||
155 | .Fn fido_cred_pubkey_ptr , | 214 | .Fn fido_cred_pubkey_ptr , |
156 | .Fn fido_cred_sig_ptr , | 215 | .Fn fido_cred_sig_ptr , |
157 | and | 216 | and |
diff --git a/man/fido_dev_get_touch_begin.3 b/man/fido_dev_get_touch_begin.3 new file mode 100644 index 0000000..8372c6f --- /dev/null +++ b/man/fido_dev_get_touch_begin.3 | |||
@@ -0,0 +1,73 @@ | |||
1 | .\" Copyright (c) 2020 Yubico AB. All rights reserved. | ||
2 | .\" Use of this source code is governed by a BSD-style | ||
3 | .\" license that can be found in the LICENSE file. | ||
4 | .\" | ||
5 | .Dd $Mdocdate: August 5 2020 $ | ||
6 | .Dt FIDO_DEV_GET_TOUCH_BEGIN 3 | ||
7 | .Os | ||
8 | .Sh NAME | ||
9 | .Nm fido_dev_get_touch_begin , | ||
10 | .Nm fido_dev_get_touch_status | ||
11 | .Nd asynchronously wait for touch on a FIDO 2 authenticator | ||
12 | .Sh SYNOPSIS | ||
13 | .In fido.h | ||
14 | .Ft int | ||
15 | .Fn fido_dev_get_touch_begin "fido_dev_t *dev" | ||
16 | .Ft int | ||
17 | .Fn fido_dev_get_touch_status "fido_dev_t *dev" "int *touched" "int ms" | ||
18 | .Sh DESCRIPTION | ||
19 | The functions described in this page allow an application to | ||
20 | asynchronously wait for touch on a FIDO authenticator. | ||
21 | This is useful when multiple authenticators are present and | ||
22 | the application needs to know which one to use. | ||
23 | .Pp | ||
24 | The | ||
25 | .Fn fido_dev_get_touch_begin | ||
26 | function initiates a touch request on | ||
27 | .Fa dev . | ||
28 | .Pp | ||
29 | The | ||
30 | .Fn fido_dev_get_touch_status | ||
31 | function continues an ongoing touch request on | ||
32 | .Fa dev , | ||
33 | blocking up to | ||
34 | .Fa ms | ||
35 | milliseconds. | ||
36 | On success, | ||
37 | .Fa touched | ||
38 | will be updated to reflect the touch request status. | ||
39 | If | ||
40 | .Fa touched | ||
41 | is 1, the device was touched, and the touch request is | ||
42 | terminated. | ||
43 | If | ||
44 | .Fa touched | ||
45 | is 0, the application may call | ||
46 | .Fn fido_dev_get_touch_status | ||
47 | to continue the touch request, or | ||
48 | .Fn fido_dev_cancel | ||
49 | to terminate it. | ||
50 | .Sh RETURN VALUES | ||
51 | The error codes returned by | ||
52 | .Fn fido_dev_get_touch_begin | ||
53 | and | ||
54 | .Fn fido_dev_get_touch_status | ||
55 | are defined in | ||
56 | .In fido/err.h . | ||
57 | On success, | ||
58 | .Dv FIDO_OK | ||
59 | is returned. | ||
60 | .Sh EXAMPLES | ||
61 | Please refer to | ||
62 | .Em examples/select.c | ||
63 | in | ||
64 | .Em libfido2's | ||
65 | source tree. | ||
66 | .Sh SEE ALSO | ||
67 | .Xr fido_dev_cancel 3 | ||
68 | .Sh CAVEATS | ||
69 | The | ||
70 | .Fn fido_dev_get_touch_status | ||
71 | function will cause a command to be transmitted to U2F | ||
72 | authenticators. | ||
73 | These transmissions should not exceed a frequency of 5Hz. | ||
diff --git a/man/fido_dev_open.3 b/man/fido_dev_open.3 index 53e3a12..6c7489d 100644 --- a/man/fido_dev_open.3 +++ b/man/fido_dev_open.3 | |||
@@ -14,6 +14,9 @@ | |||
14 | .Nm fido_dev_force_fido2 , | 14 | .Nm fido_dev_force_fido2 , |
15 | .Nm fido_dev_force_u2f , | 15 | .Nm fido_dev_force_u2f , |
16 | .Nm fido_dev_is_fido2 , | 16 | .Nm fido_dev_is_fido2 , |
17 | .Nm fido_dev_supports_cred_prot , | ||
18 | .Nm fido_dev_supports_pin , | ||
19 | .Nm fido_dev_has_pin , | ||
17 | .Nm fido_dev_protocol , | 20 | .Nm fido_dev_protocol , |
18 | .Nm fido_dev_build , | 21 | .Nm fido_dev_build , |
19 | .Nm fido_dev_flags , | 22 | .Nm fido_dev_flags , |
@@ -38,6 +41,12 @@ | |||
38 | .Fn fido_dev_force_u2f "fido_dev_t *dev" | 41 | .Fn fido_dev_force_u2f "fido_dev_t *dev" |
39 | .Ft bool | 42 | .Ft bool |
40 | .Fn fido_dev_is_fido2 "const fido_dev_t *dev" | 43 | .Fn fido_dev_is_fido2 "const fido_dev_t *dev" |
44 | .Ft bool | ||
45 | .Fn fido_dev_supports_cred_prot "const fido_dev_t *dev" | ||
46 | .Ft bool | ||
47 | .Fn fido_dev_supports_pin "const fido_dev_t *dev" | ||
48 | .Ft bool | ||
49 | .Fn fido_dev_has_pin "const fido_dev_t *dev" | ||
41 | .Ft uint8_t | 50 | .Ft uint8_t |
42 | .Fn fido_dev_protocol "const fido_dev_t *dev" | 51 | .Fn fido_dev_protocol "const fido_dev_t *dev" |
43 | .Ft uint8_t | 52 | .Ft uint8_t |
@@ -117,6 +126,30 @@ if | |||
117 | is a FIDO 2 device. | 126 | is a FIDO 2 device. |
118 | .Pp | 127 | .Pp |
119 | The | 128 | The |
129 | .Fn fido_dev_supports_cred_prot | ||
130 | function returns | ||
131 | .Dv true | ||
132 | if | ||
133 | .Fa dev | ||
134 | supports FIDO 2.1 Credential Protection. | ||
135 | .Pp | ||
136 | The | ||
137 | .Fn fido_dev_supports_pin | ||
138 | function returns | ||
139 | .Dv true | ||
140 | if | ||
141 | .Fa dev | ||
142 | supports FIDO 2.0 Client PINs. | ||
143 | .Pp | ||
144 | The | ||
145 | .Fn fido_dev_has_pin | ||
146 | function returns | ||
147 | .Dv true | ||
148 | if | ||
149 | .Fa dev | ||
150 | has a FIDO 2.0 Client PIN set. | ||
151 | .Pp | ||
152 | The | ||
120 | .Fn fido_dev_protocol | 153 | .Fn fido_dev_protocol |
121 | function returns the CTAPHID protocol version identifier of | 154 | function returns the CTAPHID protocol version identifier of |
122 | .Fa dev . | 155 | .Fa dev . |
diff --git a/openbsd-compat/clock_gettime.c b/openbsd-compat/clock_gettime.c new file mode 100644 index 0000000..ca261a6 --- /dev/null +++ b/openbsd-compat/clock_gettime.c | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2020 Yubico AB. All rights reserved. | ||
3 | * Use of this source code is governed by a BSD-style | ||
4 | * license that can be found in the LICENSE file. | ||
5 | */ | ||
6 | |||
7 | #include "openbsd-compat.h" | ||
8 | |||
9 | #if !defined(HAVE_CLOCK_GETTIME) | ||
10 | |||
11 | #if _WIN32 | ||
12 | int | ||
13 | clock_gettime(clockid_t clock_id, struct timespec *tp) | ||
14 | { | ||
15 | ULONGLONG ms; | ||
16 | |||
17 | if (clock_id != CLOCK_MONOTONIC) { | ||
18 | errno = EINVAL; | ||
19 | return (-1); | ||
20 | } | ||
21 | |||
22 | ms = GetTickCount64(); | ||
23 | tp->tv_sec = ms / 1000L; | ||
24 | tp->tv_nsec = (ms % 1000L) * 1000000L; | ||
25 | |||
26 | return (0); | ||
27 | } | ||
28 | #else | ||
29 | #error "please provide an implementation of clock_gettime() for your platform" | ||
30 | #endif /* _WIN32 */ | ||
31 | |||
32 | #endif /* !defined(HAVE_CLOCK_GETTIME) */ | ||
diff --git a/openbsd-compat/diff.sh b/openbsd-compat/diff.sh deleted file mode 100755 index f21e7d8..0000000 --- a/openbsd-compat/diff.sh +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | #!/bin/bash -u | ||
2 | |||
3 | # Copyright (c) 2019 Yubico AB. All rights reserved. | ||
4 | # Use of this source code is governed by a BSD-style | ||
5 | # license that can be found in the LICENSE file. | ||
6 | |||
7 | OPENSSH=$(realpath ../../openssh) | ||
8 | LIBRESSL=$(realpath ../../libressl-2.8.3) | ||
9 | [[ ! -d "${OPENSSH}" || ! -d "${LIBRESSL}" ]] && exit 1 | ||
10 | |||
11 | diff -pu bsd-getpagesize.c ${OPENSSH}/openbsd-compat/bsd-getpagesize.c | ||
12 | diff -pu err.h ${LIBRESSL}/include/compat/err.h | ||
13 | diff -pu explicit_bzero.c ${OPENSSH}/openbsd-compat/explicit_bzero.c | ||
14 | diff -pu explicit_bzero_win32.c ${LIBRESSL}/crypto/compat/explicit_bzero_win.c | ||
15 | diff -pu getopt.h ${OPENSSH}/openbsd-compat/getopt.h | ||
16 | diff -pu getopt_long.c ${OPENSSH}/openbsd-compat/getopt_long.c | ||
17 | diff -pu posix_win.c ${LIBRESSL}/crypto/compat/posix_win.c | ||
18 | diff -pu readpassphrase.c ${OPENSSH}/openbsd-compat/readpassphrase.c | ||
19 | diff -pu readpassphrase.h ${OPENSSH}/openbsd-compat/readpassphrase.h | ||
20 | diff -pu recallocarray.c ${OPENSSH}/openbsd-compat/recallocarray.c | ||
21 | diff -pu strlcat.c ${OPENSSH}/openbsd-compat/strlcat.c | ||
22 | diff -pu strlcpy.c ${OPENSSH}/openbsd-compat/strlcpy.c | ||
23 | diff -pu timingsafe_bcmp.c ${OPENSSH}/openbsd-compat/timingsafe_bcmp.c | ||
24 | diff -pu types.h ${LIBRESSL}/include/compat/sys/types.h | ||
diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index 30d80b3..4f847a5 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h | |||
@@ -90,4 +90,6 @@ int timingsafe_bcmp(const void *, const void *, size_t); | |||
90 | ssize_t getline(char **, size_t *, FILE *); | 90 | ssize_t getline(char **, size_t *, FILE *); |
91 | #endif | 91 | #endif |
92 | 92 | ||
93 | #include "time.h" | ||
94 | |||
93 | #endif /* !_OPENBSD_COMPAT_H */ | 95 | #endif /* !_OPENBSD_COMPAT_H */ |
diff --git a/openbsd-compat/time.h b/openbsd-compat/time.h new file mode 100644 index 0000000..23ac0fe --- /dev/null +++ b/openbsd-compat/time.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * Public domain | ||
3 | * sys/time.h compatibility shim | ||
4 | */ | ||
5 | |||
6 | #if defined(_MSC_VER) && (_MSC_VER >= 1900) | ||
7 | #include <../ucrt/time.h> | ||
8 | #elif defined(_MSC_VER) && (_MSC_VER < 1900) | ||
9 | #include <../include/time.h> | ||
10 | #else | ||
11 | #include <time.h> | ||
12 | #endif | ||
13 | |||
14 | #ifndef _COMPAT_TIME_H | ||
15 | #define _COMPAT_TIME_H | ||
16 | |||
17 | #ifndef CLOCK_MONOTONIC | ||
18 | #define CLOCK_MONOTONIC CLOCK_REALTIME | ||
19 | #endif | ||
20 | |||
21 | #ifndef CLOCK_REALTIME | ||
22 | #define CLOCK_REALTIME 0 | ||
23 | #endif | ||
24 | |||
25 | #ifndef HAVE_CLOCK_GETTIME | ||
26 | typedef int clockid_t; | ||
27 | int clock_gettime(clockid_t, struct timespec *); | ||
28 | #endif | ||
29 | |||
30 | #ifdef HAVE_TIMESPECSUB | ||
31 | #include <sys/time.h> | ||
32 | #endif | ||
33 | |||
34 | #ifndef HAVE_TIMESPECSUB | ||
35 | #define timespecsub(tsp, usp, vsp) \ | ||
36 | do { \ | ||
37 | (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \ | ||
38 | (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \ | ||
39 | if ((vsp)->tv_nsec < 0) { \ | ||
40 | (vsp)->tv_sec--; \ | ||
41 | (vsp)->tv_nsec += 1000000000L; \ | ||
42 | } \ | ||
43 | } while (0) | ||
44 | #endif | ||
45 | |||
46 | #endif /* _COMPAT_TIME_H */ | ||
diff --git a/openbsd-compat/types.h b/openbsd-compat/types.h index cc1da66..e3aa6b5 100644 --- a/openbsd-compat/types.h +++ b/openbsd-compat/types.h | |||
@@ -23,13 +23,6 @@ typedef uint32_t uid_t; | |||
23 | #endif | 23 | #endif |
24 | 24 | ||
25 | #ifdef _MSC_VER | 25 | #ifdef _MSC_VER |
26 | typedef unsigned char u_char; | ||
27 | typedef unsigned short u_short; | ||
28 | typedef unsigned int u_int; | ||
29 | typedef uint32_t in_addr_t; | ||
30 | typedef uint32_t mode_t; | ||
31 | typedef uint32_t uid_t; | ||
32 | |||
33 | #include <basetsd.h> | 26 | #include <basetsd.h> |
34 | typedef SSIZE_T ssize_t; | 27 | typedef SSIZE_T ssize_t; |
35 | 28 | ||
diff --git a/regress/assert.c b/regress/assert.c index caa5725..3b75839 100644 --- a/regress/assert.c +++ b/regress/assert.c | |||
@@ -160,7 +160,7 @@ free_rs256_pk(rs256_pk_t *pk) | |||
160 | } | 160 | } |
161 | 161 | ||
162 | static void | 162 | static void |
163 | empty_assert(fido_dev_t *d, fido_assert_t *a, int idx) | 163 | empty_assert(fido_dev_t *d, fido_assert_t *a, size_t idx) |
164 | { | 164 | { |
165 | es256_pk_t *es256; | 165 | es256_pk_t *es256; |
166 | rs256_pk_t *rs256; | 166 | rs256_pk_t *rs256; |
@@ -187,21 +187,21 @@ empty_assert(fido_dev_t *d, fido_assert_t *a, int idx) | |||
187 | fido_dev_force_u2f(d); | 187 | fido_dev_force_u2f(d); |
188 | assert(fido_dev_get_assert(d, a, NULL) == FIDO_ERR_INVALID_ARGUMENT); | 188 | assert(fido_dev_get_assert(d, a, NULL) == FIDO_ERR_INVALID_ARGUMENT); |
189 | assert(fido_dev_get_assert(d, a, "") == FIDO_ERR_INVALID_ARGUMENT); | 189 | assert(fido_dev_get_assert(d, a, "") == FIDO_ERR_INVALID_ARGUMENT); |
190 | assert(fido_assert_verify(a, COSE_ES256, idx, | 190 | assert(fido_assert_verify(a, idx, COSE_ES256, |
191 | NULL) == FIDO_ERR_INVALID_ARGUMENT); | 191 | NULL) == FIDO_ERR_INVALID_ARGUMENT); |
192 | assert(fido_assert_verify(a, COSE_ES256, idx, | 192 | assert(fido_assert_verify(a, idx, COSE_ES256, |
193 | es256) == FIDO_ERR_INVALID_ARGUMENT); | 193 | es256) == FIDO_ERR_INVALID_ARGUMENT); |
194 | assert(fido_assert_verify(a, COSE_RS256, idx, | 194 | assert(fido_assert_verify(a, idx, COSE_RS256, |
195 | rs256) == FIDO_ERR_INVALID_ARGUMENT); | 195 | rs256) == FIDO_ERR_INVALID_ARGUMENT); |
196 | 196 | ||
197 | fido_dev_force_fido2(d); | 197 | fido_dev_force_fido2(d); |
198 | assert(fido_dev_get_assert(d, a, NULL) == FIDO_ERR_INVALID_ARGUMENT); | 198 | assert(fido_dev_get_assert(d, a, NULL) == FIDO_ERR_INVALID_ARGUMENT); |
199 | assert(fido_dev_get_assert(d, a, "") == FIDO_ERR_INVALID_ARGUMENT); | 199 | assert(fido_dev_get_assert(d, a, "") == FIDO_ERR_INVALID_ARGUMENT); |
200 | assert(fido_assert_verify(a, COSE_ES256, idx, | 200 | assert(fido_assert_verify(a, idx, COSE_ES256, |
201 | NULL) == FIDO_ERR_INVALID_ARGUMENT); | 201 | NULL) == FIDO_ERR_INVALID_ARGUMENT); |
202 | assert(fido_assert_verify(a, COSE_ES256, idx, | 202 | assert(fido_assert_verify(a, idx, COSE_ES256, |
203 | es256) == FIDO_ERR_INVALID_ARGUMENT); | 203 | es256) == FIDO_ERR_INVALID_ARGUMENT); |
204 | assert(fido_assert_verify(a, COSE_RS256, idx, | 204 | assert(fido_assert_verify(a, idx, COSE_RS256, |
205 | rs256) == FIDO_ERR_INVALID_ARGUMENT); | 205 | rs256) == FIDO_ERR_INVALID_ARGUMENT); |
206 | 206 | ||
207 | free_es256_pk(es256); | 207 | free_es256_pk(es256); |
@@ -214,7 +214,7 @@ empty_assert_tests(void) | |||
214 | fido_assert_t *a; | 214 | fido_assert_t *a; |
215 | fido_dev_t *d; | 215 | fido_dev_t *d; |
216 | fido_dev_io_t io_f; | 216 | fido_dev_io_t io_f; |
217 | int i; | 217 | size_t i; |
218 | 218 | ||
219 | memset(&io_f, 0, sizeof(io_f)); | 219 | memset(&io_f, 0, sizeof(io_f)); |
220 | 220 | ||
diff --git a/regress/cred.c b/regress/cred.c index f8c08a4..74236e3 100644 --- a/regress/cred.c +++ b/regress/cred.c | |||
@@ -231,6 +231,16 @@ const unsigned char id[64] = { | |||
231 | 0x34, 0xe3, 0x83, 0xe7, 0xd1, 0xbd, 0x9f, 0x25, | 231 | 0x34, 0xe3, 0x83, 0xe7, 0xd1, 0xbd, 0x9f, 0x25, |
232 | }; | 232 | }; |
233 | 233 | ||
234 | /* | ||
235 | * Security Key By Yubico | ||
236 | * 5.1.X | ||
237 | * f8a011f3-8c0a-4d15-8006-17111f9edc7d | ||
238 | */ | ||
239 | const unsigned char aaguid[16] = { | ||
240 | 0xf8, 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15, | ||
241 | 0x80, 0x06, 0x17, 0x11, 0x1f, 0x9e, 0xdc, 0x7d, | ||
242 | }; | ||
243 | |||
234 | const char rp_id[] = "localhost"; | 244 | const char rp_id[] = "localhost"; |
235 | const char rp_name[] = "sweet home localhost"; | 245 | const char rp_name[] = "sweet home localhost"; |
236 | 246 | ||
@@ -323,6 +333,7 @@ empty_cred(void) | |||
323 | assert(fido_cred_fmt(c) == NULL); | 333 | assert(fido_cred_fmt(c) == NULL); |
324 | assert(fido_cred_id_len(c) == 0); | 334 | assert(fido_cred_id_len(c) == 0); |
325 | assert(fido_cred_id_ptr(c) == NULL); | 335 | assert(fido_cred_id_ptr(c) == NULL); |
336 | assert(fido_cred_prot(c) == 0); | ||
326 | assert(fido_cred_pubkey_len(c) == 0); | 337 | assert(fido_cred_pubkey_len(c) == 0); |
327 | assert(fido_cred_pubkey_ptr(c) == NULL); | 338 | assert(fido_cred_pubkey_ptr(c) == NULL); |
328 | assert(fido_cred_rp_id(c) == NULL); | 339 | assert(fido_cred_rp_id(c) == NULL); |
@@ -374,10 +385,13 @@ valid_cred(void) | |||
374 | assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); | 385 | assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); |
375 | assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); | 386 | assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); |
376 | assert(fido_cred_verify(c) == FIDO_OK); | 387 | assert(fido_cred_verify(c) == FIDO_OK); |
388 | assert(fido_cred_prot(c) == 0); | ||
377 | assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); | 389 | assert(fido_cred_pubkey_len(c) == sizeof(pubkey)); |
378 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 390 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
379 | assert(fido_cred_id_len(c) == sizeof(id)); | 391 | assert(fido_cred_id_len(c) == sizeof(id)); |
380 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 392 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
393 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
394 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
381 | free_cred(c); | 395 | free_cred(c); |
382 | } | 396 | } |
383 | 397 | ||
@@ -400,6 +414,8 @@ no_cdh(void) | |||
400 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 414 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
401 | assert(fido_cred_id_len(c) == sizeof(id)); | 415 | assert(fido_cred_id_len(c) == sizeof(id)); |
402 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 416 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
417 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
418 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
403 | free_cred(c); | 419 | free_cred(c); |
404 | } | 420 | } |
405 | 421 | ||
@@ -422,6 +438,8 @@ no_rp_id(void) | |||
422 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 438 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
423 | assert(fido_cred_id_len(c) == sizeof(id)); | 439 | assert(fido_cred_id_len(c) == sizeof(id)); |
424 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 440 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
441 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
442 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
425 | free_cred(c); | 443 | free_cred(c); |
426 | } | 444 | } |
427 | 445 | ||
@@ -445,6 +463,8 @@ no_rp_name(void) | |||
445 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 463 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
446 | assert(fido_cred_id_len(c) == sizeof(id)); | 464 | assert(fido_cred_id_len(c) == sizeof(id)); |
447 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 465 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
466 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
467 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
448 | free_cred(c); | 468 | free_cred(c); |
449 | } | 469 | } |
450 | 470 | ||
@@ -452,6 +472,10 @@ static void | |||
452 | no_authdata(void) | 472 | no_authdata(void) |
453 | { | 473 | { |
454 | fido_cred_t *c; | 474 | fido_cred_t *c; |
475 | unsigned char *unset; | ||
476 | |||
477 | unset = calloc(1, sizeof(aaguid)); | ||
478 | assert(unset != NULL); | ||
455 | 479 | ||
456 | c = alloc_cred(); | 480 | c = alloc_cred(); |
457 | assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); | 481 | assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); |
@@ -467,7 +491,10 @@ no_authdata(void) | |||
467 | assert(fido_cred_pubkey_ptr(c) == NULL); | 491 | assert(fido_cred_pubkey_ptr(c) == NULL); |
468 | assert(fido_cred_id_len(c) == 0); | 492 | assert(fido_cred_id_len(c) == 0); |
469 | assert(fido_cred_id_ptr(c) == NULL); | 493 | assert(fido_cred_id_ptr(c) == NULL); |
494 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
495 | assert(memcmp(fido_cred_aaguid_ptr(c), unset, sizeof(aaguid)) == 0); | ||
470 | free_cred(c); | 496 | free_cred(c); |
497 | free(unset); | ||
471 | } | 498 | } |
472 | 499 | ||
473 | static void | 500 | static void |
@@ -489,6 +516,8 @@ no_x509(void) | |||
489 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 516 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
490 | assert(fido_cred_id_len(c) == sizeof(id)); | 517 | assert(fido_cred_id_len(c) == sizeof(id)); |
491 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 518 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
519 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
520 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
492 | free_cred(c); | 521 | free_cred(c); |
493 | } | 522 | } |
494 | 523 | ||
@@ -511,6 +540,8 @@ no_sig(void) | |||
511 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 540 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
512 | assert(fido_cred_id_len(c) == sizeof(id)); | 541 | assert(fido_cred_id_len(c) == sizeof(id)); |
513 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 542 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
543 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
544 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
514 | free_cred(c); | 545 | free_cred(c); |
515 | } | 546 | } |
516 | 547 | ||
@@ -533,6 +564,8 @@ no_fmt(void) | |||
533 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 564 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
534 | assert(fido_cred_id_len(c) == sizeof(id)); | 565 | assert(fido_cred_id_len(c) == sizeof(id)); |
535 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 566 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
567 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
568 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
536 | free_cred(c); | 569 | free_cred(c); |
537 | } | 570 | } |
538 | 571 | ||
@@ -556,6 +589,8 @@ wrong_options(void) | |||
556 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 589 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
557 | assert(fido_cred_id_len(c) == sizeof(id)); | 590 | assert(fido_cred_id_len(c) == sizeof(id)); |
558 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 591 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
592 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
593 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
559 | free_cred(c); | 594 | free_cred(c); |
560 | } | 595 | } |
561 | 596 | ||
@@ -585,6 +620,8 @@ junk_cdh(void) | |||
585 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 620 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
586 | assert(fido_cred_id_len(c) == sizeof(id)); | 621 | assert(fido_cred_id_len(c) == sizeof(id)); |
587 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 622 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
623 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
624 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
588 | free_cred(c); | 625 | free_cred(c); |
589 | free(junk); | 626 | free(junk); |
590 | } | 627 | } |
@@ -609,6 +646,8 @@ junk_rp_id(void) | |||
609 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 646 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
610 | assert(fido_cred_id_len(c) == sizeof(id)); | 647 | assert(fido_cred_id_len(c) == sizeof(id)); |
611 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 648 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
649 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
650 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
612 | free_cred(c); | 651 | free_cred(c); |
613 | } | 652 | } |
614 | 653 | ||
@@ -632,6 +671,8 @@ junk_rp_name(void) | |||
632 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 671 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
633 | assert(fido_cred_id_len(c) == sizeof(id)); | 672 | assert(fido_cred_id_len(c) == sizeof(id)); |
634 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 673 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
674 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
675 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
635 | free_cred(c); | 676 | free_cred(c); |
636 | } | 677 | } |
637 | 678 | ||
@@ -640,12 +681,16 @@ junk_authdata(void) | |||
640 | { | 681 | { |
641 | fido_cred_t *c; | 682 | fido_cred_t *c; |
642 | unsigned char *junk; | 683 | unsigned char *junk; |
684 | unsigned char *unset; | ||
643 | 685 | ||
644 | junk = malloc(sizeof(authdata)); | 686 | junk = malloc(sizeof(authdata)); |
645 | assert(junk != NULL); | 687 | assert(junk != NULL); |
646 | memcpy(junk, authdata, sizeof(authdata)); | 688 | memcpy(junk, authdata, sizeof(authdata)); |
647 | junk[0] = ~junk[0]; | 689 | junk[0] = ~junk[0]; |
648 | 690 | ||
691 | unset = calloc(1, sizeof(aaguid)); | ||
692 | assert(unset != NULL); | ||
693 | |||
649 | c = alloc_cred(); | 694 | c = alloc_cred(); |
650 | assert(fido_cred_set_authdata(c, junk, | 695 | assert(fido_cred_set_authdata(c, junk, |
651 | sizeof(authdata)) == FIDO_ERR_INVALID_ARGUMENT); | 696 | sizeof(authdata)) == FIDO_ERR_INVALID_ARGUMENT); |
@@ -663,9 +708,12 @@ junk_authdata(void) | |||
663 | assert(fido_cred_sig_ptr(c) == NULL); | 708 | assert(fido_cred_sig_ptr(c) == NULL); |
664 | assert(fido_cred_x5c_len(c) == 0); | 709 | assert(fido_cred_x5c_len(c) == 0); |
665 | assert(fido_cred_x5c_ptr(c) == NULL); | 710 | assert(fido_cred_x5c_ptr(c) == NULL); |
711 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
712 | assert(memcmp(fido_cred_aaguid_ptr(c), unset, sizeof(aaguid)) == 0); | ||
666 | assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); | 713 | assert(fido_cred_verify(c) == FIDO_ERR_INVALID_ARGUMENT); |
667 | free_cred(c); | 714 | free_cred(c); |
668 | free(junk); | 715 | free(junk); |
716 | free(unset); | ||
669 | } | 717 | } |
670 | 718 | ||
671 | static void | 719 | static void |
@@ -694,6 +742,8 @@ junk_sig(void) | |||
694 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 742 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
695 | assert(fido_cred_id_len(c) == sizeof(id)); | 743 | assert(fido_cred_id_len(c) == sizeof(id)); |
696 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 744 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
745 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
746 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
697 | free_cred(c); | 747 | free_cred(c); |
698 | free(junk); | 748 | free(junk); |
699 | } | 749 | } |
@@ -724,6 +774,8 @@ junk_x509(void) | |||
724 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); | 774 | assert(memcmp(fido_cred_pubkey_ptr(c), pubkey, sizeof(pubkey)) == 0); |
725 | assert(fido_cred_id_len(c) == sizeof(id)); | 775 | assert(fido_cred_id_len(c) == sizeof(id)); |
726 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); | 776 | assert(memcmp(fido_cred_id_ptr(c), id, sizeof(id)) == 0); |
777 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
778 | assert(memcmp(fido_cred_aaguid_ptr(c), aaguid, sizeof(aaguid)) == 0); | ||
727 | free_cred(c); | 779 | free_cred(c); |
728 | free(junk); | 780 | free(junk); |
729 | } | 781 | } |
@@ -733,6 +785,10 @@ static void | |||
733 | invalid_type(void) | 785 | invalid_type(void) |
734 | { | 786 | { |
735 | fido_cred_t *c; | 787 | fido_cred_t *c; |
788 | unsigned char *unset; | ||
789 | |||
790 | unset = calloc(1, sizeof(aaguid)); | ||
791 | assert(unset != NULL); | ||
736 | 792 | ||
737 | c = alloc_cred(); | 793 | c = alloc_cred(); |
738 | assert(fido_cred_set_type(c, COSE_RS256) == FIDO_OK); | 794 | assert(fido_cred_set_type(c, COSE_RS256) == FIDO_OK); |
@@ -749,7 +805,10 @@ invalid_type(void) | |||
749 | assert(fido_cred_pubkey_ptr(c) == NULL); | 805 | assert(fido_cred_pubkey_ptr(c) == NULL); |
750 | assert(fido_cred_id_len(c) == 0); | 806 | assert(fido_cred_id_len(c) == 0); |
751 | assert(fido_cred_id_ptr(c) == NULL); | 807 | assert(fido_cred_id_ptr(c) == NULL); |
808 | assert(fido_cred_aaguid_len(c) == sizeof(aaguid)); | ||
809 | assert(memcmp(fido_cred_aaguid_ptr(c), unset, sizeof(aaguid)) == 0); | ||
752 | free_cred(c); | 810 | free_cred(c); |
811 | free(unset); | ||
753 | } | 812 | } |
754 | 813 | ||
755 | /* cbor_serialize_alloc misuse */ | 814 | /* cbor_serialize_alloc misuse */ |
@@ -789,6 +848,24 @@ unsorted_keys(void) | |||
789 | free_cred(c); | 848 | free_cred(c); |
790 | } | 849 | } |
791 | 850 | ||
851 | static void | ||
852 | wrong_credprot(void) | ||
853 | { | ||
854 | fido_cred_t *c; | ||
855 | |||
856 | c = alloc_cred(); | ||
857 | assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK); | ||
858 | assert(fido_cred_set_clientdata_hash(c, cdh, sizeof(cdh)) == FIDO_OK); | ||
859 | assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK); | ||
860 | assert(fido_cred_set_x509(c, x509, sizeof(x509)) == FIDO_OK); | ||
861 | assert(fido_cred_set_sig(c, sig, sizeof(sig)) == FIDO_OK); | ||
862 | assert(fido_cred_set_fmt(c, "packed") == FIDO_OK); | ||
863 | assert(fido_cred_set_prot(c, FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID) == FIDO_OK); | ||
864 | assert(fido_cred_set_authdata(c, authdata, sizeof(authdata)) == FIDO_OK); | ||
865 | assert(fido_cred_verify(c) == FIDO_ERR_INVALID_PARAM); | ||
866 | free_cred(c); | ||
867 | } | ||
868 | |||
792 | int | 869 | int |
793 | main(void) | 870 | main(void) |
794 | { | 871 | { |
@@ -814,6 +891,7 @@ main(void) | |||
814 | bad_cbor_serialize(); | 891 | bad_cbor_serialize(); |
815 | duplicate_keys(); | 892 | duplicate_keys(); |
816 | unsorted_keys(); | 893 | unsorted_keys(); |
894 | wrong_credprot(); | ||
817 | 895 | ||
818 | exit(0); | 896 | exit(0); |
819 | } | 897 | } |
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3cf62e8..ad02524 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt | |||
@@ -37,19 +37,24 @@ if(FUZZ) | |||
37 | endif() | 37 | endif() |
38 | 38 | ||
39 | if(USE_HIDAPI) | 39 | if(USE_HIDAPI) |
40 | list(APPEND COMPAT_SOURCES hid_hidapi.c) | 40 | list(APPEND FIDO_SOURCES hid_hidapi.c) |
41 | elseif(WIN32) | 41 | elseif(WIN32) |
42 | list(APPEND COMPAT_SOURCES hid_win.c) | 42 | list(APPEND FIDO_SOURCES hid_win.c) |
43 | elseif(APPLE) | 43 | elseif(APPLE) |
44 | list(APPEND COMPAT_SOURCES hid_osx.c) | 44 | list(APPEND FIDO_SOURCES hid_osx.c) |
45 | elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") | 45 | elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") |
46 | list(APPEND COMPAT_SOURCES hid_linux.c) | 46 | list(APPEND FIDO_SOURCES hid_linux.c) |
47 | elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") | 47 | elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") |
48 | list(APPEND COMPAT_SOURCES hid_openbsd.c) | 48 | list(APPEND FIDO_SOURCES hid_openbsd.c) |
49 | else() | 49 | else() |
50 | message(FATAL_ERROR "please define a hid backend for your platform") | 50 | message(FATAL_ERROR "please define a hid backend for your platform") |
51 | endif() | 51 | endif() |
52 | 52 | ||
53 | if(NOT MSVC) | ||
54 | set_source_files_properties(${FIDO_SOURCES} PROPERTIES COMPILE_FLAGS | ||
55 | "-Wconversion -Wsign-conversion") | ||
56 | endif() | ||
57 | |||
53 | list(APPEND COMPAT_SOURCES | 58 | list(APPEND COMPAT_SOURCES |
54 | ../openbsd-compat/bsd-getpagesize.c | 59 | ../openbsd-compat/bsd-getpagesize.c |
55 | ../openbsd-compat/explicit_bzero.c | 60 | ../openbsd-compat/explicit_bzero.c |
@@ -94,7 +99,7 @@ elseif(APPLE) | |||
94 | "-framework IOKit") | 99 | "-framework IOKit") |
95 | endif() | 100 | endif() |
96 | set_target_properties(fido2_shared PROPERTIES OUTPUT_NAME fido2 | 101 | set_target_properties(fido2_shared PROPERTIES OUTPUT_NAME fido2 |
97 | VERSION ${LIB_VERSION} SOVERSION ${LIB_SOVERSION}) | 102 | VERSION ${FIDO_VERSION} SOVERSION ${FIDO_MAJOR}) |
98 | install(TARGETS fido2_shared | 103 | install(TARGETS fido2_shared |
99 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} | 104 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} |
100 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} | 105 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} |
diff --git a/src/assert.c b/src/assert.c index b71d00e..1746387 100644 --- a/src/assert.c +++ b/src/assert.c | |||
@@ -313,7 +313,7 @@ fido_dev_get_assert(fido_dev_t *dev, fido_assert_t *assert, const char *pin) | |||
313 | goto fail; | 313 | goto fail; |
314 | } | 314 | } |
315 | } | 315 | } |
316 | 316 | ||
317 | r = fido_dev_get_assert_wait(dev, assert, pk, ecdh, pin, -1); | 317 | r = fido_dev_get_assert_wait(dev, assert, pk, ecdh, pin, -1); |
318 | if (r == FIDO_OK && assert->ext & FIDO_EXT_HMAC_SECRET) | 318 | if (r == FIDO_OK && assert->ext & FIDO_EXT_HMAC_SECRET) |
319 | if (decrypt_hmac_secrets(assert, ecdh) < 0) { | 319 | if (decrypt_hmac_secrets(assert, ecdh) < 0) { |
@@ -386,7 +386,7 @@ cbor_flatten_vector(cbor_item_t *argv[], size_t argc) | |||
386 | return (NULL); | 386 | return (NULL); |
387 | 387 | ||
388 | for (i = 0; i < argc; i++) | 388 | for (i = 0; i < argc; i++) |
389 | if (cbor_add_arg(map, i + 1, argv[i]) < 0) | 389 | if (cbor_add_arg(map, (uint8_t)(i + 1), argv[i]) < 0) |
390 | break; | 390 | break; |
391 | 391 | ||
392 | if (i != argc) { | 392 | if (i != argc) { |
@@ -583,7 +583,9 @@ cbor_encode_extensions(const fido_cred_ext_t *ext) | |||
583 | } | 583 | } |
584 | } | 584 | } |
585 | if (ext->mask & FIDO_EXT_CRED_PROTECT) { | 585 | if (ext->mask & FIDO_EXT_CRED_PROTECT) { |
586 | if (cbor_add_uint8(item, "credProtect", ext->prot) < 0) { | 586 | if (ext->prot < 0 || ext->prot > UINT8_MAX || |
587 | cbor_add_uint8(item, "credProtect", | ||
588 | (uint8_t)ext->prot) < 0) { | ||
587 | cbor_decref(&item); | 589 | cbor_decref(&item); |
588 | return (NULL); | 590 | return (NULL); |
589 | } | 591 | } |
@@ -634,7 +636,7 @@ cbor_encode_pin_auth(const fido_blob_t *hmac_key, const fido_blob_t *data) | |||
634 | unsigned int dgst_len; | 636 | unsigned int dgst_len; |
635 | 637 | ||
636 | if ((md = EVP_sha256()) == NULL || HMAC(md, hmac_key->ptr, | 638 | if ((md = EVP_sha256()) == NULL || HMAC(md, hmac_key->ptr, |
637 | (int)hmac_key->len, data->ptr, (int)data->len, dgst, | 639 | (int)hmac_key->len, data->ptr, data->len, dgst, |
638 | &dgst_len) == NULL || dgst_len != SHA256_DIGEST_LENGTH) | 640 | &dgst_len) == NULL || dgst_len != SHA256_DIGEST_LENGTH) |
639 | return (NULL); | 641 | return (NULL); |
640 | 642 | ||
@@ -696,7 +698,6 @@ cbor_encode_change_pin_auth(const fido_blob_t *key, const fido_blob_t *new_pin, | |||
696 | fido_blob_t *npe = NULL; /* new pin, encrypted */ | 698 | fido_blob_t *npe = NULL; /* new pin, encrypted */ |
697 | fido_blob_t *ph = NULL; /* pin hash */ | 699 | fido_blob_t *ph = NULL; /* pin hash */ |
698 | fido_blob_t *phe = NULL; /* pin hash, encrypted */ | 700 | fido_blob_t *phe = NULL; /* pin hash, encrypted */ |
699 | int ok = -1; | ||
700 | 701 | ||
701 | if ((npe = fido_blob_new()) == NULL || | 702 | if ((npe = fido_blob_new()) == NULL || |
702 | (ph = fido_blob_new()) == NULL || | 703 | (ph = fido_blob_new()) == NULL || |
@@ -735,8 +736,8 @@ cbor_encode_change_pin_auth(const fido_blob_t *key, const fido_blob_t *new_pin, | |||
735 | if ((ctx = HMAC_CTX_new()) == NULL || | 736 | if ((ctx = HMAC_CTX_new()) == NULL || |
736 | (md = EVP_sha256()) == NULL || | 737 | (md = EVP_sha256()) == NULL || |
737 | HMAC_Init_ex(ctx, key->ptr, (int)key->len, md, NULL) == 0 || | 738 | HMAC_Init_ex(ctx, key->ptr, (int)key->len, md, NULL) == 0 || |
738 | HMAC_Update(ctx, npe->ptr, (int)npe->len) == 0 || | 739 | HMAC_Update(ctx, npe->ptr, npe->len) == 0 || |
739 | HMAC_Update(ctx, phe->ptr, (int)phe->len) == 0 || | 740 | HMAC_Update(ctx, phe->ptr, phe->len) == 0 || |
740 | HMAC_Final(ctx, dgst, &dgst_len) == 0 || dgst_len != 32) { | 741 | HMAC_Final(ctx, dgst, &dgst_len) == 0 || dgst_len != 32) { |
741 | fido_log_debug("%s: HMAC", __func__); | 742 | fido_log_debug("%s: HMAC", __func__); |
742 | goto fail; | 743 | goto fail; |
@@ -748,7 +749,6 @@ cbor_encode_change_pin_auth(const fido_blob_t *key, const fido_blob_t *new_pin, | |||
748 | goto fail; | 749 | goto fail; |
749 | } | 750 | } |
750 | 751 | ||
751 | ok = 0; | ||
752 | fail: | 752 | fail: |
753 | fido_blob_free(&npe); | 753 | fido_blob_free(&npe); |
754 | fido_blob_free(&ph); | 754 | fido_blob_free(&ph); |
@@ -759,13 +759,6 @@ fail: | |||
759 | HMAC_CTX_free(ctx); | 759 | HMAC_CTX_free(ctx); |
760 | #endif | 760 | #endif |
761 | 761 | ||
762 | if (ok < 0) { | ||
763 | if (item != NULL) { | ||
764 | cbor_decref(&item); | ||
765 | item = NULL; | ||
766 | } | ||
767 | } | ||
768 | |||
769 | return (item); | 762 | return (item); |
770 | } | 763 | } |
771 | 764 | ||
@@ -787,7 +780,7 @@ cbor_encode_set_pin_auth(const fido_blob_t *key, const fido_blob_t *pin) | |||
787 | } | 780 | } |
788 | 781 | ||
789 | if ((md = EVP_sha256()) == NULL || key->len != 32 || HMAC(md, key->ptr, | 782 | if ((md = EVP_sha256()) == NULL || key->len != 32 || HMAC(md, key->ptr, |
790 | (int)key->len, pe->ptr, (int)pe->len, dgst, &dgst_len) == NULL || | 783 | (int)key->len, pe->ptr, pe->len, dgst, &dgst_len) == NULL || |
791 | dgst_len != SHA256_DIGEST_LENGTH) { | 784 | dgst_len != SHA256_DIGEST_LENGTH) { |
792 | fido_log_debug("%s: HMAC", __func__); | 785 | fido_log_debug("%s: HMAC", __func__); |
793 | goto fail; | 786 | goto fail; |
@@ -1292,7 +1285,7 @@ cbor_decode_cred_authdata(const cbor_item_t *item, int cose_alg, | |||
1292 | } | 1285 | } |
1293 | 1286 | ||
1294 | if (authdata_ext != NULL) { | 1287 | if (authdata_ext != NULL) { |
1295 | if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0 && | 1288 | if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0 && |
1296 | decode_extensions(&buf, &len, authdata_ext) < 0) | 1289 | decode_extensions(&buf, &len, authdata_ext) < 0) |
1297 | return (-1); | 1290 | return (-1); |
1298 | } | 1291 | } |
@@ -967,6 +967,18 @@ fido_cred_id_len(const fido_cred_t *cred) | |||
967 | return (cred->attcred.id.len); | 967 | return (cred->attcred.id.len); |
968 | } | 968 | } |
969 | 969 | ||
970 | const unsigned char * | ||
971 | fido_cred_aaguid_ptr(const fido_cred_t *cred) | ||
972 | { | ||
973 | return (cred->attcred.aaguid); | ||
974 | } | ||
975 | |||
976 | size_t | ||
977 | fido_cred_aaguid_len(const fido_cred_t *cred) | ||
978 | { | ||
979 | return (sizeof(cred->attcred.aaguid)); | ||
980 | } | ||
981 | |||
970 | int | 982 | int |
971 | fido_cred_prot(const fido_cred_t *cred) | 983 | fido_cred_prot(const fido_cred_t *cred) |
972 | { | 984 | { |
diff --git a/src/credman.c b/src/credman.c index a382185..4219807 100644 --- a/src/credman.c +++ b/src/credman.c | |||
@@ -230,7 +230,8 @@ fido_credman_get_dev_metadata(fido_dev_t *dev, fido_credman_metadata_t *metadata | |||
230 | static int | 230 | static int |
231 | credman_parse_rk(const cbor_item_t *key, const cbor_item_t *val, void *arg) | 231 | credman_parse_rk(const cbor_item_t *key, const cbor_item_t *val, void *arg) |
232 | { | 232 | { |
233 | fido_cred_t *cred = arg; | 233 | fido_cred_t *cred = arg; |
234 | uint64_t prot; | ||
234 | 235 | ||
235 | if (cbor_isa_uint(key) == false || | 236 | if (cbor_isa_uint(key) == false || |
236 | cbor_int_get_width(key) != CBOR_INT_8) { | 237 | cbor_int_get_width(key) != CBOR_INT_8) { |
@@ -249,6 +250,11 @@ credman_parse_rk(const cbor_item_t *key, const cbor_item_t *val, void *arg) | |||
249 | return (-1); | 250 | return (-1); |
250 | cred->type = cred->attcred.type; /* XXX */ | 251 | cred->type = cred->attcred.type; /* XXX */ |
251 | return (0); | 252 | return (0); |
253 | case 10: | ||
254 | if (cbor_decode_uint64(val, &prot) < 0 || prot > INT_MAX || | ||
255 | fido_cred_set_prot(cred, (int)prot) != FIDO_OK) | ||
256 | return (-1); | ||
257 | return (0); | ||
252 | default: | 258 | default: |
253 | fido_log_debug("%s: cbor type", __func__); | 259 | fido_log_debug("%s: cbor type", __func__); |
254 | return (0); /* ignore */ | 260 | return (0); /* ignore */ |
@@ -10,6 +10,8 @@ | |||
10 | #include <sys/random.h> | 10 | #include <sys/random.h> |
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | #include <openssl/sha.h> | ||
14 | |||
13 | #include <fcntl.h> | 15 | #include <fcntl.h> |
14 | #include <stdint.h> | 16 | #include <stdint.h> |
15 | #include <stdlib.h> | 17 | #include <stdlib.h> |
@@ -106,10 +108,49 @@ find_manifest_func_node(dev_manifest_func_t f, dev_manifest_func_node_t **curr, | |||
106 | } | 108 | } |
107 | } | 109 | } |
108 | 110 | ||
111 | #ifdef FIDO_FUZZ | ||
112 | static void | ||
113 | set_random_report_len(fido_dev_t *dev) | ||
114 | { | ||
115 | dev->rx_len = CTAP_MIN_REPORT_LEN + | ||
116 | uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1); | ||
117 | dev->tx_len = CTAP_MIN_REPORT_LEN + | ||
118 | uniform_random(CTAP_MAX_REPORT_LEN - CTAP_MIN_REPORT_LEN + 1); | ||
119 | } | ||
120 | #endif | ||
121 | |||
122 | static void | ||
123 | fido_dev_set_flags(fido_dev_t *dev, const fido_cbor_info_t *info) | ||
124 | { | ||
125 | char * const *ptr; | ||
126 | const bool *val; | ||
127 | size_t len; | ||
128 | |||
129 | ptr = fido_cbor_info_extensions_ptr(info); | ||
130 | len = fido_cbor_info_extensions_len(info); | ||
131 | |||
132 | for (size_t i = 0; i < len; i++) | ||
133 | if (strcmp(ptr[i], "credProtect") == 0) | ||
134 | dev->flags |= FIDO_DEV_CRED_PROT; | ||
135 | |||
136 | ptr = fido_cbor_info_options_name_ptr(info); | ||
137 | val = fido_cbor_info_options_value_ptr(info); | ||
138 | len = fido_cbor_info_options_len(info); | ||
139 | |||
140 | for (size_t i = 0; i < len; i++) | ||
141 | if (strcmp(ptr[i], "clientPin") == 0) { | ||
142 | if (val[i] == true) | ||
143 | dev->flags |= FIDO_DEV_PIN_SET; | ||
144 | else | ||
145 | dev->flags |= FIDO_DEV_PIN_UNSET; | ||
146 | } | ||
147 | } | ||
148 | |||
109 | static int | 149 | static int |
110 | fido_dev_open_tx(fido_dev_t *dev, const char *path) | 150 | fido_dev_open_tx(fido_dev_t *dev, const char *path) |
111 | { | 151 | { |
112 | const uint8_t cmd = CTAP_CMD_INIT; | 152 | const uint8_t cmd = CTAP_CMD_INIT; |
153 | int r; | ||
113 | 154 | ||
114 | if (dev->io_handle != NULL) { | 155 | if (dev->io_handle != NULL) { |
115 | fido_log_debug("%s: handle=%p", __func__, dev->io_handle); | 156 | fido_log_debug("%s: handle=%p", __func__, dev->io_handle); |
@@ -131,14 +172,44 @@ fido_dev_open_tx(fido_dev_t *dev, const char *path) | |||
131 | return (FIDO_ERR_INTERNAL); | 172 | return (FIDO_ERR_INTERNAL); |
132 | } | 173 | } |
133 | 174 | ||
175 | if (dev->io_own) { | ||
176 | dev->rx_len = CTAP_MAX_REPORT_LEN; | ||
177 | dev->tx_len = CTAP_MAX_REPORT_LEN; | ||
178 | } else { | ||
179 | dev->rx_len = fido_hid_report_in_len(dev->io_handle); | ||
180 | dev->tx_len = fido_hid_report_out_len(dev->io_handle); | ||
181 | } | ||
182 | |||
183 | #ifdef FIDO_FUZZ | ||
184 | set_random_report_len(dev); | ||
185 | #endif | ||
186 | |||
187 | if (dev->rx_len < CTAP_MIN_REPORT_LEN || | ||
188 | dev->rx_len > CTAP_MAX_REPORT_LEN) { | ||
189 | fido_log_debug("%s: invalid rx_len %zu", __func__, dev->rx_len); | ||
190 | r = FIDO_ERR_RX; | ||
191 | goto fail; | ||
192 | } | ||
193 | |||
194 | if (dev->tx_len < CTAP_MIN_REPORT_LEN || | ||
195 | dev->tx_len > CTAP_MAX_REPORT_LEN) { | ||
196 | fido_log_debug("%s: invalid tx_len %zu", __func__, dev->tx_len); | ||
197 | r = FIDO_ERR_TX; | ||
198 | goto fail; | ||
199 | } | ||
200 | |||
134 | if (fido_tx(dev, cmd, &dev->nonce, sizeof(dev->nonce)) < 0) { | 201 | if (fido_tx(dev, cmd, &dev->nonce, sizeof(dev->nonce)) < 0) { |
135 | fido_log_debug("%s: fido_tx", __func__); | 202 | fido_log_debug("%s: fido_tx", __func__); |
136 | dev->io.close(dev->io_handle); | 203 | r = FIDO_ERR_TX; |
137 | dev->io_handle = NULL; | 204 | goto fail; |
138 | return (FIDO_ERR_TX); | ||
139 | } | 205 | } |
140 | 206 | ||
141 | return (FIDO_OK); | 207 | return (FIDO_OK); |
208 | fail: | ||
209 | dev->io.close(dev->io_handle); | ||
210 | dev->io_handle = NULL; | ||
211 | |||
212 | return (r); | ||
142 | } | 213 | } |
143 | 214 | ||
144 | static int | 215 | static int |
@@ -166,6 +237,7 @@ fido_dev_open_rx(fido_dev_t *dev, int ms) | |||
166 | goto fail; | 237 | goto fail; |
167 | } | 238 | } |
168 | 239 | ||
240 | dev->flags = 0; | ||
169 | dev->cid = dev->attr.cid; | 241 | dev->cid = dev->attr.cid; |
170 | 242 | ||
171 | if (fido_dev_is_fido2(dev)) { | 243 | if (fido_dev_is_fido2(dev)) { |
@@ -177,6 +249,8 @@ fido_dev_open_rx(fido_dev_t *dev, int ms) | |||
177 | if (fido_dev_get_cbor_info_wait(dev, info, ms) != FIDO_OK) { | 249 | if (fido_dev_get_cbor_info_wait(dev, info, ms) != FIDO_OK) { |
178 | fido_log_debug("%s: falling back to u2f", __func__); | 250 | fido_log_debug("%s: falling back to u2f", __func__); |
179 | fido_dev_force_u2f(dev); | 251 | fido_dev_force_u2f(dev); |
252 | } else { | ||
253 | fido_dev_set_flags(dev, info); | ||
180 | } | 254 | } |
181 | } | 255 | } |
182 | 256 | ||
@@ -303,6 +377,9 @@ fido_dev_close(fido_dev_t *dev) | |||
303 | int | 377 | int |
304 | fido_dev_cancel(fido_dev_t *dev) | 378 | fido_dev_cancel(fido_dev_t *dev) |
305 | { | 379 | { |
380 | if (fido_dev_is_fido2(dev) == false) | ||
381 | return (FIDO_ERR_INVALID_ARGUMENT); | ||
382 | |||
306 | if (fido_tx(dev, CTAP_CMD_CANCEL, NULL, 0) < 0) | 383 | if (fido_tx(dev, CTAP_CMD_CANCEL, NULL, 0) < 0) |
307 | return (FIDO_ERR_TX); | 384 | return (FIDO_ERR_TX); |
308 | 385 | ||
@@ -310,6 +387,105 @@ fido_dev_cancel(fido_dev_t *dev) | |||
310 | } | 387 | } |
311 | 388 | ||
312 | int | 389 | int |
390 | fido_dev_get_touch_begin(fido_dev_t *dev) | ||
391 | { | ||
392 | fido_blob_t f; | ||
393 | cbor_item_t *argv[9]; | ||
394 | const char *clientdata = FIDO_DUMMY_CLIENTDATA; | ||
395 | const uint8_t user_id = FIDO_DUMMY_USER_ID; | ||
396 | unsigned char cdh[SHA256_DIGEST_LENGTH]; | ||
397 | fido_rp_t rp; | ||
398 | fido_user_t user; | ||
399 | int r = FIDO_ERR_INTERNAL; | ||
400 | |||
401 | memset(&f, 0, sizeof(f)); | ||
402 | memset(argv, 0, sizeof(argv)); | ||
403 | memset(cdh, 0, sizeof(cdh)); | ||
404 | memset(&rp, 0, sizeof(rp)); | ||
405 | memset(&user, 0, sizeof(user)); | ||
406 | |||
407 | if (fido_dev_is_fido2(dev) == false) | ||
408 | return (u2f_get_touch_begin(dev)); | ||
409 | |||
410 | if (SHA256((const void *)clientdata, strlen(clientdata), cdh) != cdh) { | ||
411 | fido_log_debug("%s: sha256", __func__); | ||
412 | return (FIDO_ERR_INTERNAL); | ||
413 | } | ||
414 | |||
415 | if ((rp.id = strdup(FIDO_DUMMY_RP_ID)) == NULL || | ||
416 | (user.name = strdup(FIDO_DUMMY_USER_NAME)) == NULL) { | ||
417 | fido_log_debug("%s: strdup", __func__); | ||
418 | goto fail; | ||
419 | } | ||
420 | |||
421 | if (fido_blob_set(&user.id, &user_id, sizeof(user_id)) < 0) { | ||
422 | fido_log_debug("%s: fido_blob_set", __func__); | ||
423 | goto fail; | ||
424 | } | ||
425 | |||
426 | if ((argv[0] = cbor_build_bytestring(cdh, sizeof(cdh))) == NULL || | ||
427 | (argv[1] = cbor_encode_rp_entity(&rp)) == NULL || | ||
428 | (argv[2] = cbor_encode_user_entity(&user)) == NULL || | ||
429 | (argv[3] = cbor_encode_pubkey_param(COSE_ES256)) == NULL) { | ||
430 | fido_log_debug("%s: cbor encode", __func__); | ||
431 | goto fail; | ||
432 | } | ||
433 | |||
434 | if (fido_dev_supports_pin(dev)) { | ||
435 | if ((argv[7] = cbor_new_definite_bytestring()) == NULL || | ||
436 | (argv[8] = cbor_encode_pin_opt()) == NULL) { | ||
437 | fido_log_debug("%s: cbor encode", __func__); | ||
438 | goto fail; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 || | ||
443 | fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) { | ||
444 | fido_log_debug("%s: fido_tx", __func__); | ||
445 | r = FIDO_ERR_TX; | ||
446 | goto fail; | ||
447 | } | ||
448 | |||
449 | r = FIDO_OK; | ||
450 | fail: | ||
451 | cbor_vector_free(argv, nitems(argv)); | ||
452 | free(f.ptr); | ||
453 | free(rp.id); | ||
454 | free(user.name); | ||
455 | free(user.id.ptr); | ||
456 | |||
457 | return (r); | ||
458 | } | ||
459 | |||
460 | int | ||
461 | fido_dev_get_touch_status(fido_dev_t *dev, int *touched, int ms) | ||
462 | { | ||
463 | int r; | ||
464 | |||
465 | *touched = 0; | ||
466 | |||
467 | if (fido_dev_is_fido2(dev) == false) | ||
468 | return (u2f_get_touch_status(dev, touched, ms)); | ||
469 | |||
470 | switch ((r = fido_rx_cbor_status(dev, ms))) { | ||
471 | case FIDO_ERR_PIN_AUTH_INVALID: | ||
472 | case FIDO_ERR_PIN_INVALID: | ||
473 | case FIDO_ERR_PIN_NOT_SET: | ||
474 | case FIDO_ERR_SUCCESS: | ||
475 | *touched = 1; | ||
476 | break; | ||
477 | case FIDO_ERR_RX: | ||
478 | /* ignore */ | ||
479 | break; | ||
480 | default: | ||
481 | fido_log_debug("%s: fido_rx_cbor_status", __func__); | ||
482 | return (r); | ||
483 | } | ||
484 | |||
485 | return (FIDO_OK); | ||
486 | } | ||
487 | |||
488 | int | ||
313 | fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io) | 489 | fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io) |
314 | { | 490 | { |
315 | if (dev->io_handle != NULL) { | 491 | if (dev->io_handle != NULL) { |
@@ -324,6 +500,7 @@ fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io) | |||
324 | } | 500 | } |
325 | 501 | ||
326 | dev->io = *io; | 502 | dev->io = *io; |
503 | dev->io_own = true; | ||
327 | 504 | ||
328 | return (FIDO_OK); | 505 | return (FIDO_OK); |
329 | } | 506 | } |
@@ -337,6 +514,7 @@ fido_dev_set_transport_functions(fido_dev_t *dev, const fido_dev_transport_t *t) | |||
337 | } | 514 | } |
338 | 515 | ||
339 | dev->transport = *t; | 516 | dev->transport = *t; |
517 | dev->io_own = true; | ||
340 | 518 | ||
341 | return (FIDO_OK); | 519 | return (FIDO_OK); |
342 | } | 520 | } |
@@ -446,10 +624,29 @@ fido_dev_is_fido2(const fido_dev_t *dev) | |||
446 | return (dev->attr.flags & FIDO_CAP_CBOR); | 624 | return (dev->attr.flags & FIDO_CAP_CBOR); |
447 | } | 625 | } |
448 | 626 | ||
627 | bool | ||
628 | fido_dev_supports_pin(const fido_dev_t *dev) | ||
629 | { | ||
630 | return (dev->flags & (FIDO_DEV_PIN_SET|FIDO_DEV_PIN_UNSET)); | ||
631 | } | ||
632 | |||
633 | bool | ||
634 | fido_dev_has_pin(const fido_dev_t *dev) | ||
635 | { | ||
636 | return (dev->flags & FIDO_DEV_PIN_SET); | ||
637 | } | ||
638 | |||
639 | bool | ||
640 | fido_dev_supports_cred_prot(const fido_dev_t *dev) | ||
641 | { | ||
642 | return (dev->flags & FIDO_DEV_CRED_PROT); | ||
643 | } | ||
644 | |||
449 | void | 645 | void |
450 | fido_dev_force_u2f(fido_dev_t *dev) | 646 | fido_dev_force_u2f(fido_dev_t *dev) |
451 | { | 647 | { |
452 | dev->attr.flags &= ~FIDO_CAP_CBOR; | 648 | dev->attr.flags &= (uint8_t)~FIDO_CAP_CBOR; |
649 | dev->flags = 0; | ||
453 | } | 650 | } |
454 | 651 | ||
455 | void | 652 | void |
diff --git a/src/diff_exports.sh b/src/diff_exports.sh index 7920f47..9cff009 100755 --- a/src/diff_exports.sh +++ b/src/diff_exports.sh | |||
@@ -1,23 +1,26 @@ | |||
1 | #!/bin/bash -u | 1 | #!/bin/sh -u |
2 | 2 | ||
3 | # Copyright (c) 2018 Yubico AB. All rights reserved. | 3 | # Copyright (c) 2018 Yubico AB. All rights reserved. |
4 | # Use of this source code is governed by a BSD-style | 4 | # Use of this source code is governed by a BSD-style |
5 | # license that can be found in the LICENSE file. | 5 | # license that can be found in the LICENSE file. |
6 | 6 | ||
7 | [[ ! -f export.gnu || ! -f export.llvm || ! -f export.msvc ]] && exit 1 | 7 | for f in export.gnu export.llvm export.msvc; do |
8 | if [ ! -f "${f}" ]; then | ||
9 | exit 1 | ||
10 | fi | ||
11 | done | ||
8 | 12 | ||
9 | TMPDIR=$(mktemp -d) | 13 | TMPDIR="$(mktemp -d)" |
10 | GNU=${TMPDIR}/gnu | 14 | GNU="${TMPDIR}/gnu" |
11 | LLVM=${TMPDIR}/llvm | 15 | LLVM="${TMPDIR}/llvm" |
12 | MSVC=${TMPDIR}/msvc | 16 | MSVC="${TMPDIR}/msvc" |
13 | 17 | ||
14 | egrep -o $'([^*{}\t]+);$' export.gnu | tr -d ';' | sort > ${GNU} | 18 | awk '/^[^*{}]+;$/' export.gnu | tr -d '\t;' | sort > "${GNU}" |
15 | sed 's/^_//g' export.llvm | sort > ${LLVM} | 19 | sed 's/^_//' export.llvm | sort > "${LLVM}" |
16 | egrep -v "^EXPORTS$" export.msvc | sort > ${MSVC} | 20 | grep -v '^EXPORTS$' export.msvc | sort > "${MSVC}" |
17 | diff -u ${GNU} ${LLVM} && diff -u ${MSVC} ${LLVM} | 21 | diff -u "${GNU}" "${LLVM}" && diff -u "${MSVC}" "${LLVM}" |
18 | ERROR=$? | 22 | ERROR=$? |
19 | 23 | rm "${GNU}" "${LLVM}" "${MSVC}" | |
20 | rm ${GNU} ${LLVM} ${MSVC} | 24 | rmdir "${TMPDIR}" |
21 | rmdir ${TMPDIR} | ||
22 | 25 | ||
23 | exit ${ERROR} | 26 | exit ${ERROR} |
@@ -38,6 +38,8 @@ fido_strerr(int n) | |||
38 | return "FIDO_ERR_LIMIT_EXCEEDED"; | 38 | return "FIDO_ERR_LIMIT_EXCEEDED"; |
39 | case FIDO_ERR_UNSUPPORTED_EXTENSION: | 39 | case FIDO_ERR_UNSUPPORTED_EXTENSION: |
40 | return "FIDO_ERR_UNSUPPORTED_EXTENSION"; | 40 | return "FIDO_ERR_UNSUPPORTED_EXTENSION"; |
41 | case FIDO_ERR_FP_DATABASE_FULL: | ||
42 | return "FIDO_ERR_FP_DATABASE_FULL"; | ||
41 | case FIDO_ERR_CREDENTIAL_EXCLUDED: | 43 | case FIDO_ERR_CREDENTIAL_EXCLUDED: |
42 | return "FIDO_ERR_CREDENTIAL_EXCLUDED"; | 44 | return "FIDO_ERR_CREDENTIAL_EXCLUDED"; |
43 | case FIDO_ERR_PROCESSING: | 45 | case FIDO_ERR_PROCESSING: |
@@ -94,6 +96,8 @@ fido_strerr(int n) | |||
94 | return "FIDO_ERR_ACTION_TIMEOUT"; | 96 | return "FIDO_ERR_ACTION_TIMEOUT"; |
95 | case FIDO_ERR_UP_REQUIRED: | 97 | case FIDO_ERR_UP_REQUIRED: |
96 | return "FIDO_ERR_UP_REQUIRED"; | 98 | return "FIDO_ERR_UP_REQUIRED"; |
99 | case FIDO_ERR_UV_BLOCKED: | ||
100 | return "FIDO_ERR_UV_BLOCKED"; | ||
97 | case FIDO_ERR_ERR_OTHER: | 101 | case FIDO_ERR_ERR_OTHER: |
98 | return "FIDO_ERR_ERR_OTHER"; | 102 | return "FIDO_ERR_ERR_OTHER"; |
99 | case FIDO_ERR_SPEC_LAST: | 103 | case FIDO_ERR_SPEC_LAST: |
diff --git a/src/es256.c b/src/es256.c index 020ecaa..5b4e6d6 100644 --- a/src/es256.c +++ b/src/es256.c | |||
@@ -92,7 +92,7 @@ es256_pk_encode(const es256_pk_t *pk, int ecdh) | |||
92 | 92 | ||
93 | /* alg */ | 93 | /* alg */ |
94 | if ((argv[1].key = cbor_build_uint8(3)) == NULL || | 94 | if ((argv[1].key = cbor_build_uint8(3)) == NULL || |
95 | (argv[1].value = cbor_build_negint8(-alg - 1)) == NULL || | 95 | (argv[1].value = cbor_build_negint8((uint8_t)(-alg - 1))) == NULL || |
96 | !cbor_map_add(item, argv[1])) | 96 | !cbor_map_add(item, argv[1])) |
97 | goto fail; | 97 | goto fail; |
98 | 98 | ||
diff --git a/src/export.gnu b/src/export.gnu index cbfa69f..007b5b9 100644 --- a/src/export.gnu +++ b/src/export.gnu | |||
@@ -76,6 +76,8 @@ | |||
76 | fido_cbor_info_extensions_ptr; | 76 | fido_cbor_info_extensions_ptr; |
77 | fido_cbor_info_free; | 77 | fido_cbor_info_free; |
78 | fido_cbor_info_maxmsgsiz; | 78 | fido_cbor_info_maxmsgsiz; |
79 | fido_cbor_info_maxcredcntlst; | ||
80 | fido_cbor_info_maxcredidlen; | ||
79 | fido_cbor_info_fwversion; | 81 | fido_cbor_info_fwversion; |
80 | fido_cbor_info_new; | 82 | fido_cbor_info_new; |
81 | fido_cbor_info_options_len; | 83 | fido_cbor_info_options_len; |
@@ -96,6 +98,8 @@ | |||
96 | fido_cred_free; | 98 | fido_cred_free; |
97 | fido_cred_id_len; | 99 | fido_cred_id_len; |
98 | fido_cred_id_ptr; | 100 | fido_cred_id_ptr; |
101 | fido_cred_aaguid_len; | ||
102 | fido_cred_aaguid_ptr; | ||
99 | fido_credman_del_dev_rk; | 103 | fido_credman_del_dev_rk; |
100 | fido_credman_get_dev_metadata; | 104 | fido_credman_get_dev_metadata; |
101 | fido_credman_get_dev_rk; | 105 | fido_credman_get_dev_rk; |
@@ -155,6 +159,9 @@ | |||
155 | fido_dev_get_assert; | 159 | fido_dev_get_assert; |
156 | fido_dev_get_cbor_info; | 160 | fido_dev_get_cbor_info; |
157 | fido_dev_get_retry_count; | 161 | fido_dev_get_retry_count; |
162 | fido_dev_get_touch_begin; | ||
163 | fido_dev_get_touch_status; | ||
164 | fido_dev_has_pin; | ||
158 | fido_dev_info_free; | 165 | fido_dev_info_free; |
159 | fido_dev_info_manifest; | 166 | fido_dev_info_manifest; |
160 | fido_dev_info_manufacturer_string; | 167 | fido_dev_info_manufacturer_string; |
@@ -175,6 +182,8 @@ | |||
175 | fido_dev_set_io_functions; | 182 | fido_dev_set_io_functions; |
176 | fido_dev_set_pin; | 183 | fido_dev_set_pin; |
177 | fido_dev_set_transport_functions; | 184 | fido_dev_set_transport_functions; |
185 | fido_dev_supports_cred_prot; | ||
186 | fido_dev_supports_pin; | ||
178 | fido_init; | 187 | fido_init; |
179 | fido_set_log_handler; | 188 | fido_set_log_handler; |
180 | fido_strerr; | 189 | fido_strerr; |
diff --git a/src/export.llvm b/src/export.llvm index abde2e9..ffbc157 100644 --- a/src/export.llvm +++ b/src/export.llvm | |||
@@ -74,6 +74,8 @@ _fido_cbor_info_extensions_len | |||
74 | _fido_cbor_info_extensions_ptr | 74 | _fido_cbor_info_extensions_ptr |
75 | _fido_cbor_info_free | 75 | _fido_cbor_info_free |
76 | _fido_cbor_info_maxmsgsiz | 76 | _fido_cbor_info_maxmsgsiz |
77 | _fido_cbor_info_maxcredcntlst | ||
78 | _fido_cbor_info_maxcredidlen | ||
77 | _fido_cbor_info_fwversion | 79 | _fido_cbor_info_fwversion |
78 | _fido_cbor_info_new | 80 | _fido_cbor_info_new |
79 | _fido_cbor_info_options_len | 81 | _fido_cbor_info_options_len |
@@ -94,6 +96,8 @@ _fido_cred_fmt | |||
94 | _fido_cred_free | 96 | _fido_cred_free |
95 | _fido_cred_id_len | 97 | _fido_cred_id_len |
96 | _fido_cred_id_ptr | 98 | _fido_cred_id_ptr |
99 | _fido_cred_aaguid_len | ||
100 | _fido_cred_aaguid_ptr | ||
97 | _fido_credman_del_dev_rk | 101 | _fido_credman_del_dev_rk |
98 | _fido_credman_get_dev_metadata | 102 | _fido_credman_get_dev_metadata |
99 | _fido_credman_get_dev_rk | 103 | _fido_credman_get_dev_rk |
@@ -153,6 +157,9 @@ _fido_dev_free | |||
153 | _fido_dev_get_assert | 157 | _fido_dev_get_assert |
154 | _fido_dev_get_cbor_info | 158 | _fido_dev_get_cbor_info |
155 | _fido_dev_get_retry_count | 159 | _fido_dev_get_retry_count |
160 | _fido_dev_get_touch_begin | ||
161 | _fido_dev_get_touch_status | ||
162 | _fido_dev_has_pin | ||
156 | _fido_dev_info_free | 163 | _fido_dev_info_free |
157 | _fido_dev_info_manifest | 164 | _fido_dev_info_manifest |
158 | _fido_dev_info_manufacturer_string | 165 | _fido_dev_info_manufacturer_string |
@@ -173,6 +180,8 @@ _fido_dev_reset | |||
173 | _fido_dev_set_io_functions | 180 | _fido_dev_set_io_functions |
174 | _fido_dev_set_pin | 181 | _fido_dev_set_pin |
175 | _fido_dev_set_transport_functions | 182 | _fido_dev_set_transport_functions |
183 | _fido_dev_supports_cred_prot | ||
184 | _fido_dev_supports_pin | ||
176 | _fido_init | 185 | _fido_init |
177 | _fido_set_log_handler | 186 | _fido_set_log_handler |
178 | _fido_strerr | 187 | _fido_strerr |
diff --git a/src/export.msvc b/src/export.msvc index 06ec69a..1a2a0b7 100644 --- a/src/export.msvc +++ b/src/export.msvc | |||
@@ -75,6 +75,8 @@ fido_cbor_info_extensions_len | |||
75 | fido_cbor_info_extensions_ptr | 75 | fido_cbor_info_extensions_ptr |
76 | fido_cbor_info_free | 76 | fido_cbor_info_free |
77 | fido_cbor_info_maxmsgsiz | 77 | fido_cbor_info_maxmsgsiz |
78 | fido_cbor_info_maxcredcntlst | ||
79 | fido_cbor_info_maxcredidlen | ||
78 | fido_cbor_info_fwversion | 80 | fido_cbor_info_fwversion |
79 | fido_cbor_info_new | 81 | fido_cbor_info_new |
80 | fido_cbor_info_options_len | 82 | fido_cbor_info_options_len |
@@ -95,6 +97,8 @@ fido_cred_fmt | |||
95 | fido_cred_free | 97 | fido_cred_free |
96 | fido_cred_id_len | 98 | fido_cred_id_len |
97 | fido_cred_id_ptr | 99 | fido_cred_id_ptr |
100 | fido_cred_aaguid_len | ||
101 | fido_cred_aaguid_ptr | ||
98 | fido_credman_del_dev_rk | 102 | fido_credman_del_dev_rk |
99 | fido_credman_get_dev_metadata | 103 | fido_credman_get_dev_metadata |
100 | fido_credman_get_dev_rk | 104 | fido_credman_get_dev_rk |
@@ -154,6 +158,9 @@ fido_dev_free | |||
154 | fido_dev_get_assert | 158 | fido_dev_get_assert |
155 | fido_dev_get_cbor_info | 159 | fido_dev_get_cbor_info |
156 | fido_dev_get_retry_count | 160 | fido_dev_get_retry_count |
161 | fido_dev_get_touch_begin | ||
162 | fido_dev_get_touch_status | ||
163 | fido_dev_has_pin | ||
157 | fido_dev_info_free | 164 | fido_dev_info_free |
158 | fido_dev_info_manifest | 165 | fido_dev_info_manifest |
159 | fido_dev_info_manufacturer_string | 166 | fido_dev_info_manufacturer_string |
@@ -174,6 +181,8 @@ fido_dev_reset | |||
174 | fido_dev_set_io_functions | 181 | fido_dev_set_io_functions |
175 | fido_dev_set_pin | 182 | fido_dev_set_pin |
176 | fido_dev_set_transport_functions | 183 | fido_dev_set_transport_functions |
184 | fido_dev_supports_cred_prot | ||
185 | fido_dev_supports_pin | ||
177 | fido_init | 186 | fido_init |
178 | fido_set_log_handler | 187 | fido_set_log_handler |
179 | fido_strerr | 188 | fido_strerr |
diff --git a/src/extern.h b/src/extern.h index fc0a49d..4c036cb 100644 --- a/src/extern.h +++ b/src/extern.h | |||
@@ -88,6 +88,8 @@ void *fido_hid_open(const char *); | |||
88 | void fido_hid_close(void *); | 88 | void fido_hid_close(void *); |
89 | int fido_hid_read(void *, unsigned char *, size_t, int); | 89 | int fido_hid_read(void *, unsigned char *, size_t, int); |
90 | int fido_hid_write(void *, const unsigned char *, size_t); | 90 | int fido_hid_write(void *, const unsigned char *, size_t); |
91 | size_t fido_hid_report_in_len(void *); | ||
92 | size_t fido_hid_report_out_len(void *); | ||
91 | 93 | ||
92 | /* generic i/o */ | 94 | /* generic i/o */ |
93 | int fido_rx_cbor_status(fido_dev_t *, int); | 95 | int fido_rx_cbor_status(fido_dev_t *, int); |
@@ -115,6 +117,8 @@ void fido_log_xxd(const void *, size_t); | |||
115 | /* u2f */ | 117 | /* u2f */ |
116 | int u2f_register(fido_dev_t *, fido_cred_t *, int); | 118 | int u2f_register(fido_dev_t *, fido_cred_t *, int); |
117 | int u2f_authenticate(fido_dev_t *, fido_assert_t *, int); | 119 | int u2f_authenticate(fido_dev_t *, fido_assert_t *, int); |
120 | int u2f_get_touch_begin(fido_dev_t *); | ||
121 | int u2f_get_touch_status(fido_dev_t *, int *, int); | ||
118 | 122 | ||
119 | /* unexposed fido ops */ | 123 | /* unexposed fido ops */ |
120 | int fido_dev_authkey(fido_dev_t *, es256_pk_t *); | 124 | int fido_dev_authkey(fido_dev_t *, es256_pk_t *); |
@@ -149,6 +153,22 @@ typedef int (*dev_manifest_func_t)(fido_dev_info_t *, size_t, size_t *); | |||
149 | int fido_dev_register_manifest_func(const dev_manifest_func_t); | 153 | int fido_dev_register_manifest_func(const dev_manifest_func_t); |
150 | void fido_dev_unregister_manifest_func(const dev_manifest_func_t); | 154 | void fido_dev_unregister_manifest_func(const dev_manifest_func_t); |
151 | 155 | ||
156 | /* fuzzing instrumentation */ | ||
157 | #ifdef FIDO_FUZZ | ||
158 | uint32_t uniform_random(uint32_t); | ||
159 | #endif | ||
160 | |||
161 | /* internal device capability flags */ | ||
162 | #define FIDO_DEV_PIN_SET 0x01 | ||
163 | #define FIDO_DEV_PIN_UNSET 0x02 | ||
164 | #define FIDO_DEV_CRED_PROT 0x04 | ||
165 | |||
166 | /* miscellanea */ | ||
167 | #define FIDO_DUMMY_CLIENTDATA "" | ||
168 | #define FIDO_DUMMY_RP_ID "localhost" | ||
169 | #define FIDO_DUMMY_USER_NAME "dummy" | ||
170 | #define FIDO_DUMMY_USER_ID 1 | ||
171 | |||
152 | #ifdef __cplusplus | 172 | #ifdef __cplusplus |
153 | } /* extern "C" */ | 173 | } /* extern "C" */ |
154 | #endif /* __cplusplus */ | 174 | #endif /* __cplusplus */ |
@@ -32,6 +32,12 @@ | |||
32 | extern "C" { | 32 | extern "C" { |
33 | #endif /* __cplusplus */ | 33 | #endif /* __cplusplus */ |
34 | 34 | ||
35 | #ifdef _MSC_VER | ||
36 | #define FIDO_DEPRECATED(reason) __declspec(deprecated(reason)) | ||
37 | #else | ||
38 | #define FIDO_DEPRECATED(reason) __attribute__((__deprecated__(reason))) | ||
39 | #endif | ||
40 | |||
35 | fido_assert_t *fido_assert_new(void); | 41 | fido_assert_t *fido_assert_new(void); |
36 | fido_cred_t *fido_cred_new(void); | 42 | fido_cred_t *fido_cred_new(void); |
37 | fido_dev_t *fido_dev_new(void); | 43 | fido_dev_t *fido_dev_new(void); |
@@ -82,6 +88,7 @@ const unsigned char *fido_cbor_info_aaguid_ptr(const fido_cbor_info_t *); | |||
82 | const unsigned char *fido_cred_authdata_ptr(const fido_cred_t *); | 88 | const unsigned char *fido_cred_authdata_ptr(const fido_cred_t *); |
83 | const unsigned char *fido_cred_clientdata_hash_ptr(const fido_cred_t *); | 89 | const unsigned char *fido_cred_clientdata_hash_ptr(const fido_cred_t *); |
84 | const unsigned char *fido_cred_id_ptr(const fido_cred_t *); | 90 | const unsigned char *fido_cred_id_ptr(const fido_cred_t *); |
91 | const unsigned char *fido_cred_aaguid_ptr(const fido_cred_t *); | ||
85 | const unsigned char *fido_cred_user_id_ptr(const fido_cred_t *); | 92 | const unsigned char *fido_cred_user_id_ptr(const fido_cred_t *); |
86 | const unsigned char *fido_cred_pubkey_ptr(const fido_cred_t *); | 93 | const unsigned char *fido_cred_pubkey_ptr(const fido_cred_t *); |
87 | const unsigned char *fido_cred_sig_ptr(const fido_cred_t *); | 94 | const unsigned char *fido_cred_sig_ptr(const fido_cred_t *); |
@@ -97,8 +104,8 @@ int fido_assert_set_clientdata_hash(fido_assert_t *, const unsigned char *, | |||
97 | int fido_assert_set_count(fido_assert_t *, size_t); | 104 | int fido_assert_set_count(fido_assert_t *, size_t); |
98 | int fido_assert_set_extensions(fido_assert_t *, int); | 105 | int fido_assert_set_extensions(fido_assert_t *, int); |
99 | int fido_assert_set_hmac_salt(fido_assert_t *, const unsigned char *, size_t); | 106 | int fido_assert_set_hmac_salt(fido_assert_t *, const unsigned char *, size_t); |
100 | int fido_assert_set_options(fido_assert_t *, bool, bool) | 107 | FIDO_DEPRECATED("use fido_assert_set_up/fido_assert_set_uv") |
101 | __attribute__((__deprecated__("use fido_assert_set_up/fido_assert_set_uv"))); | 108 | int fido_assert_set_options(fido_assert_t *, bool, bool); |
102 | int fido_assert_set_rp(fido_assert_t *, const char *); | 109 | int fido_assert_set_rp(fido_assert_t *, const char *); |
103 | int fido_assert_set_up(fido_assert_t *, fido_opt_t); | 110 | int fido_assert_set_up(fido_assert_t *, fido_opt_t); |
104 | int fido_assert_set_uv(fido_assert_t *, fido_opt_t); | 111 | int fido_assert_set_uv(fido_assert_t *, fido_opt_t); |
@@ -111,8 +118,8 @@ int fido_cred_set_authdata_raw(fido_cred_t *, const unsigned char *, size_t); | |||
111 | int fido_cred_set_clientdata_hash(fido_cred_t *, const unsigned char *, size_t); | 118 | int fido_cred_set_clientdata_hash(fido_cred_t *, const unsigned char *, size_t); |
112 | int fido_cred_set_extensions(fido_cred_t *, int); | 119 | int fido_cred_set_extensions(fido_cred_t *, int); |
113 | int fido_cred_set_fmt(fido_cred_t *, const char *); | 120 | int fido_cred_set_fmt(fido_cred_t *, const char *); |
114 | int fido_cred_set_options(fido_cred_t *, bool, bool) | 121 | FIDO_DEPRECATED("use fido_cred_set_rk/fido_cred_set_uv") |
115 | __attribute__((__deprecated__("use fido_cred_set_rk/fido_cred_set_uv"))); | 122 | int fido_cred_set_options(fido_cred_t *, bool, bool); |
116 | int fido_cred_set_prot(fido_cred_t *, int); | 123 | int fido_cred_set_prot(fido_cred_t *, int); |
117 | int fido_cred_set_rk(fido_cred_t *, fido_opt_t); | 124 | int fido_cred_set_rk(fido_cred_t *, fido_opt_t); |
118 | int fido_cred_set_rp(fido_cred_t *, const char *, const char *); | 125 | int fido_cred_set_rp(fido_cred_t *, const char *, const char *); |
@@ -130,6 +137,8 @@ int fido_dev_close(fido_dev_t *); | |||
130 | int fido_dev_get_assert(fido_dev_t *, fido_assert_t *, const char *); | 137 | int fido_dev_get_assert(fido_dev_t *, fido_assert_t *, const char *); |
131 | int fido_dev_get_cbor_info(fido_dev_t *, fido_cbor_info_t *); | 138 | int fido_dev_get_cbor_info(fido_dev_t *, fido_cbor_info_t *); |
132 | int fido_dev_get_retry_count(fido_dev_t *, int *); | 139 | int fido_dev_get_retry_count(fido_dev_t *, int *); |
140 | int fido_dev_get_touch_begin(fido_dev_t *); | ||
141 | int fido_dev_get_touch_status(fido_dev_t *, int *, int); | ||
133 | int fido_dev_info_manifest(fido_dev_info_t *, size_t, size_t *); | 142 | int fido_dev_info_manifest(fido_dev_info_t *, size_t, size_t *); |
134 | int fido_dev_make_cred(fido_dev_t *, fido_cred_t *, const char *); | 143 | int fido_dev_make_cred(fido_dev_t *, fido_cred_t *, const char *); |
135 | int fido_dev_open_with_info(fido_dev_t *); | 144 | int fido_dev_open_with_info(fido_dev_t *); |
@@ -154,6 +163,7 @@ size_t fido_cbor_info_versions_len(const fido_cbor_info_t *); | |||
154 | size_t fido_cred_authdata_len(const fido_cred_t *); | 163 | size_t fido_cred_authdata_len(const fido_cred_t *); |
155 | size_t fido_cred_clientdata_hash_len(const fido_cred_t *); | 164 | size_t fido_cred_clientdata_hash_len(const fido_cred_t *); |
156 | size_t fido_cred_id_len(const fido_cred_t *); | 165 | size_t fido_cred_id_len(const fido_cred_t *); |
166 | size_t fido_cred_aaguid_len(const fido_cred_t *); | ||
157 | size_t fido_cred_user_id_len(const fido_cred_t *); | 167 | size_t fido_cred_user_id_len(const fido_cred_t *); |
158 | size_t fido_cred_pubkey_len(const fido_cred_t *); | 168 | size_t fido_cred_pubkey_len(const fido_cred_t *); |
159 | size_t fido_cred_sig_len(const fido_cred_t *); | 169 | size_t fido_cred_sig_len(const fido_cred_t *); |
@@ -170,9 +180,14 @@ uint8_t fido_dev_flags(const fido_dev_t *); | |||
170 | int16_t fido_dev_info_vendor(const fido_dev_info_t *); | 180 | int16_t fido_dev_info_vendor(const fido_dev_info_t *); |
171 | int16_t fido_dev_info_product(const fido_dev_info_t *); | 181 | int16_t fido_dev_info_product(const fido_dev_info_t *); |
172 | uint64_t fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *); | 182 | uint64_t fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *); |
183 | uint64_t fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *); | ||
184 | uint64_t fido_cbor_info_maxcredidlen(const fido_cbor_info_t *); | ||
173 | uint64_t fido_cbor_info_fwversion(const fido_cbor_info_t *); | 185 | uint64_t fido_cbor_info_fwversion(const fido_cbor_info_t *); |
174 | 186 | ||
187 | bool fido_dev_has_pin(const fido_dev_t *); | ||
175 | bool fido_dev_is_fido2(const fido_dev_t *); | 188 | bool fido_dev_is_fido2(const fido_dev_t *); |
189 | bool fido_dev_supports_pin(const fido_dev_t *); | ||
190 | bool fido_dev_supports_cred_prot(const fido_dev_t *); | ||
176 | 191 | ||
177 | #ifdef __cplusplus | 192 | #ifdef __cplusplus |
178 | } /* extern "C" */ | 193 | } /* extern "C" */ |
diff --git a/src/fido/err.h b/src/fido/err.h index d7453fc..253914f 100644 --- a/src/fido/err.h +++ b/src/fido/err.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define FIDO_ERR_MISSING_PARAMETER 0x14 | 21 | #define FIDO_ERR_MISSING_PARAMETER 0x14 |
22 | #define FIDO_ERR_LIMIT_EXCEEDED 0x15 | 22 | #define FIDO_ERR_LIMIT_EXCEEDED 0x15 |
23 | #define FIDO_ERR_UNSUPPORTED_EXTENSION 0x16 | 23 | #define FIDO_ERR_UNSUPPORTED_EXTENSION 0x16 |
24 | #define FIDO_ERR_FP_DATABASE_FULL 0x17 | ||
24 | #define FIDO_ERR_CREDENTIAL_EXCLUDED 0x19 | 25 | #define FIDO_ERR_CREDENTIAL_EXCLUDED 0x19 |
25 | #define FIDO_ERR_PROCESSING 0x21 | 26 | #define FIDO_ERR_PROCESSING 0x21 |
26 | #define FIDO_ERR_INVALID_CREDENTIAL 0x22 | 27 | #define FIDO_ERR_INVALID_CREDENTIAL 0x22 |
@@ -49,6 +50,7 @@ | |||
49 | #define FIDO_ERR_REQUEST_TOO_LARGE 0x39 | 50 | #define FIDO_ERR_REQUEST_TOO_LARGE 0x39 |
50 | #define FIDO_ERR_ACTION_TIMEOUT 0x3a | 51 | #define FIDO_ERR_ACTION_TIMEOUT 0x3a |
51 | #define FIDO_ERR_UP_REQUIRED 0x3b | 52 | #define FIDO_ERR_UP_REQUIRED 0x3b |
53 | #define FIDO_ERR_UV_BLOCKED 0x3c | ||
52 | #define FIDO_ERR_ERR_OTHER 0x7f | 54 | #define FIDO_ERR_ERR_OTHER 0x7f |
53 | #define FIDO_ERR_SPEC_LAST 0xdf | 55 | #define FIDO_ERR_SPEC_LAST 0xdf |
54 | 56 | ||
diff --git a/src/fido/param.h b/src/fido/param.h index 7d3c0cc..14ee74e 100644 --- a/src/fido/param.h +++ b/src/fido/param.h | |||
@@ -50,8 +50,14 @@ | |||
50 | /* HID Broadcast channel ID. */ | 50 | /* HID Broadcast channel ID. */ |
51 | #define CTAP_CID_BROADCAST 0xffffffff | 51 | #define CTAP_CID_BROADCAST 0xffffffff |
52 | 52 | ||
53 | /* Expected size of a HID report in bytes. */ | 53 | #define CTAP_INIT_HEADER_LEN 7 |
54 | #define CTAP_RPT_SIZE 64 | 54 | #define CTAP_CONT_HEADER_LEN 5 |
55 | |||
56 | /* Maximum length of a CTAP HID report in bytes. */ | ||
57 | #define CTAP_MAX_REPORT_LEN 64 | ||
58 | |||
59 | /* Minimum length of a CTAP HID report in bytes. */ | ||
60 | #define CTAP_MIN_REPORT_LEN (CTAP_INIT_HEADER_LEN + 1) | ||
55 | 61 | ||
56 | /* Randomness device on UNIX-like platforms. */ | 62 | /* Randomness device on UNIX-like platforms. */ |
57 | #ifndef FIDO_RANDOM_DEV | 63 | #ifndef FIDO_RANDOM_DEV |
@@ -60,7 +66,7 @@ | |||
60 | 66 | ||
61 | /* Maximum message size in bytes. */ | 67 | /* Maximum message size in bytes. */ |
62 | #ifndef FIDO_MAXMSG | 68 | #ifndef FIDO_MAXMSG |
63 | #define FIDO_MAXMSG 1200 | 69 | #define FIDO_MAXMSG 2048 |
64 | #endif | 70 | #endif |
65 | 71 | ||
66 | /* CTAP capability bits. */ | 72 | /* CTAP capability bits. */ |
diff --git a/src/fido/types.h b/src/fido/types.h index 5df5e36..cce1a44 100644 --- a/src/fido/types.h +++ b/src/fido/types.h | |||
@@ -175,13 +175,15 @@ typedef struct fido_byte_array { | |||
175 | } fido_byte_array_t; | 175 | } fido_byte_array_t; |
176 | 176 | ||
177 | typedef struct fido_cbor_info { | 177 | typedef struct fido_cbor_info { |
178 | fido_str_array_t versions; /* supported versions: fido2|u2f */ | 178 | fido_str_array_t versions; /* supported versions: fido2|u2f */ |
179 | fido_str_array_t extensions; /* list of supported extensions */ | 179 | fido_str_array_t extensions; /* list of supported extensions */ |
180 | unsigned char aaguid[16]; /* aaguid */ | 180 | unsigned char aaguid[16]; /* aaguid */ |
181 | fido_opt_array_t options; /* list of supported options */ | 181 | fido_opt_array_t options; /* list of supported options */ |
182 | uint64_t maxmsgsiz; /* maximum message size */ | 182 | uint64_t maxmsgsiz; /* maximum message size */ |
183 | fido_byte_array_t protocols; /* supported pin protocols */ | 183 | fido_byte_array_t protocols; /* supported pin protocols */ |
184 | uint64_t fwversion; /* firmware version */ | 184 | uint64_t maxcredcntlst; /* max number of credentials in list */ |
185 | uint64_t maxcredidlen; /* max credential ID length */ | ||
186 | uint64_t fwversion; /* firmware version */ | ||
185 | } fido_cbor_info_t; | 187 | } fido_cbor_info_t; |
186 | 188 | ||
187 | typedef struct fido_dev_info { | 189 | typedef struct fido_dev_info { |
@@ -213,6 +215,10 @@ typedef struct fido_dev { | |||
213 | char *path; /* device path */ | 215 | char *path; /* device path */ |
214 | void *io_handle; /* abstract i/o handle */ | 216 | void *io_handle; /* abstract i/o handle */ |
215 | fido_dev_io_t io; /* i/o functions */ | 217 | fido_dev_io_t io; /* i/o functions */ |
218 | bool io_own; /* device has own io/transport */ | ||
219 | size_t rx_len; /* length of HID input reports */ | ||
220 | size_t tx_len; /* length of HID output reports */ | ||
221 | int flags; /* internal flags; see FIDO_DEV_* */ | ||
216 | fido_dev_transport_t transport; /* transport functions */ | 222 | fido_dev_transport_t transport; /* transport functions */ |
217 | } fido_dev_t; | 223 | } fido_dev_t; |
218 | 224 | ||
diff --git a/src/hid_hidapi.c b/src/hid_hidapi.c index 915621f..898fd9e 100644 --- a/src/hid_hidapi.c +++ b/src/hid_hidapi.c | |||
@@ -4,14 +4,26 @@ | |||
4 | * license that can be found in the LICENSE file. | 4 | * license that can be found in the LICENSE file. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <hidapi/hidapi.h> | 7 | #ifdef __linux__ |
8 | #include <sys/ioctl.h> | ||
9 | #include <linux/hidraw.h> | ||
10 | #include <linux/input.h> | ||
11 | #include <fcntl.h> | ||
12 | #endif | ||
8 | 13 | ||
14 | #include <hidapi.h> | ||
9 | #include <stdlib.h> | 15 | #include <stdlib.h> |
10 | #include <string.h> | 16 | #include <string.h> |
11 | #include <wchar.h> | 17 | #include <wchar.h> |
12 | 18 | ||
13 | #include "fido.h" | 19 | #include "fido.h" |
14 | 20 | ||
21 | struct hid_hidapi { | ||
22 | void *handle; | ||
23 | size_t report_in_len; | ||
24 | size_t report_out_len; | ||
25 | }; | ||
26 | |||
15 | static size_t | 27 | static size_t |
16 | fido_wcslen(const wchar_t *wcs) | 28 | fido_wcslen(const wchar_t *wcs) |
17 | { | 29 | { |
@@ -27,7 +39,7 @@ wcs_to_cs(const wchar_t *wcs) | |||
27 | char *cs; | 39 | char *cs; |
28 | size_t i; | 40 | size_t i; |
29 | 41 | ||
30 | if (wcs == NULL || (cs = calloc(fido_wcslen(wcs) + 1, 1)) == NULL) | 42 | if (wcs == NULL || (cs = calloc(fido_wcslen(wcs) + 1, 1)) == NULL) |
31 | return NULL; | 43 | return NULL; |
32 | 44 | ||
33 | for (i = 0; i < fido_wcslen(wcs); i++) { | 45 | for (i = 0; i < fido_wcslen(wcs); i++) { |
@@ -68,11 +80,12 @@ copy_info(fido_dev_info_t *di, const struct hid_device_info *d) | |||
68 | free(di->path); | 80 | free(di->path); |
69 | free(di->manufacturer); | 81 | free(di->manufacturer); |
70 | free(di->product); | 82 | free(di->product); |
83 | explicit_bzero(di, sizeof(*di)); | ||
71 | return -1; | 84 | return -1; |
72 | } | 85 | } |
73 | 86 | ||
74 | di->product_id = d->product_id; | 87 | di->product_id = (int16_t)d->product_id; |
75 | di->vendor_id = d->vendor_id; | 88 | di->vendor_id = (int16_t)d->vendor_id; |
76 | di->io = (fido_dev_io_t) { | 89 | di->io = (fido_dev_io_t) { |
77 | &fido_hid_open, | 90 | &fido_hid_open, |
78 | &fido_hid_close, | 91 | &fido_hid_close, |
@@ -83,28 +96,199 @@ copy_info(fido_dev_info_t *di, const struct hid_device_info *d) | |||
83 | return 0; | 96 | return 0; |
84 | } | 97 | } |
85 | 98 | ||
99 | #ifdef __linux__ | ||
100 | static int | ||
101 | get_key_len(uint8_t tag, uint8_t *key, size_t *key_len) | ||
102 | { | ||
103 | *key = tag & 0xfc; | ||
104 | if ((*key & 0xf0) == 0xf0) { | ||
105 | fido_log_debug("%s: *key=0x%02x", __func__, *key); | ||
106 | return -1; | ||
107 | } | ||
108 | |||
109 | *key_len = tag & 0x3; | ||
110 | if (*key_len == 3) { | ||
111 | *key_len = 4; | ||
112 | } | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int | ||
118 | get_key_val(const void *body, size_t key_len, uint32_t *val) | ||
119 | { | ||
120 | const uint8_t *ptr = body; | ||
121 | |||
122 | switch (key_len) { | ||
123 | case 0: | ||
124 | *val = 0; | ||
125 | break; | ||
126 | case 1: | ||
127 | *val = ptr[0]; | ||
128 | break; | ||
129 | case 2: | ||
130 | *val = (uint32_t)((ptr[1] << 8) | ptr[0]); | ||
131 | break; | ||
132 | default: | ||
133 | fido_log_debug("%s: key_len=%zu", __func__, key_len); | ||
134 | return -1; | ||
135 | } | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static int | ||
141 | get_usage_info(const struct hidraw_report_descriptor *hrd, uint32_t *usage_page, | ||
142 | uint32_t *usage) | ||
143 | { | ||
144 | const uint8_t *ptr = hrd->value; | ||
145 | size_t len = hrd->size; | ||
146 | |||
147 | while (len > 0) { | ||
148 | const uint8_t tag = ptr[0]; | ||
149 | |||
150 | ptr++; | ||
151 | len--; | ||
152 | |||
153 | uint8_t key; | ||
154 | size_t key_len; | ||
155 | uint32_t key_val; | ||
156 | |||
157 | if (get_key_len(tag, &key, &key_len) < 0 || key_len > len || | ||
158 | get_key_val(ptr, key_len, &key_val) < 0) { | ||
159 | return -1; | ||
160 | } | ||
161 | |||
162 | if (key == 0x4) { | ||
163 | *usage_page = key_val; | ||
164 | } else if (key == 0x8) { | ||
165 | *usage = key_val; | ||
166 | } | ||
167 | |||
168 | ptr += key_len; | ||
169 | len -= key_len; | ||
170 | } | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int | ||
176 | get_report_descriptor(const char *path, struct hidraw_report_descriptor *hrd) | ||
177 | { | ||
178 | int fd; | ||
179 | int s = -1; | ||
180 | int ok = -1; | ||
181 | |||
182 | if ((fd = open(path, O_RDONLY)) < 0) { | ||
183 | fido_log_debug("%s: open", __func__); | ||
184 | return -1; | ||
185 | } | ||
186 | |||
187 | if (ioctl(fd, HIDIOCGRDESCSIZE, &s) < 0 || s < 0 || | ||
188 | (unsigned)s > HID_MAX_DESCRIPTOR_SIZE) { | ||
189 | fido_log_debug("%s: ioctl HIDIOCGRDESCSIZE", __func__); | ||
190 | goto fail; | ||
191 | } | ||
192 | |||
193 | hrd->size = (unsigned)s; | ||
194 | |||
195 | if (ioctl(fd, HIDIOCGRDESC, hrd) < 0) { | ||
196 | fido_log_debug("%s: ioctl HIDIOCGRDESC", __func__); | ||
197 | goto fail; | ||
198 | } | ||
199 | |||
200 | ok = 0; | ||
201 | fail: | ||
202 | if (fd != -1) | ||
203 | close(fd); | ||
204 | |||
205 | return ok; | ||
206 | } | ||
207 | |||
208 | static bool | ||
209 | is_fido(const struct hid_device_info *hdi) | ||
210 | { | ||
211 | uint32_t usage = 0; | ||
212 | uint32_t usage_page = 0; | ||
213 | struct hidraw_report_descriptor hrd; | ||
214 | |||
215 | memset(&hrd, 0, sizeof(hrd)); | ||
216 | |||
217 | if (get_report_descriptor(hdi->path, &hrd) < 0 || | ||
218 | get_usage_info(&hrd, &usage_page, &usage) < 0) { | ||
219 | return false; | ||
220 | } | ||
221 | |||
222 | return usage_page == 0xf1d0; | ||
223 | } | ||
224 | #elif defined(_WIN32) || defined(__APPLE__) | ||
225 | static bool | ||
226 | is_fido(const struct hid_device_info *hdi) | ||
227 | { | ||
228 | return hdi->usage_page == 0xf1d0; | ||
229 | } | ||
230 | #else | ||
231 | static bool | ||
232 | is_fido(const struct hid_device_info *hdi) | ||
233 | { | ||
234 | (void)hdi; | ||
235 | fido_log_debug("%s: assuming FIDO HID", __func__); | ||
236 | return true; | ||
237 | } | ||
238 | #endif | ||
239 | |||
86 | void * | 240 | void * |
87 | fido_hid_open(const char *path) | 241 | fido_hid_open(const char *path) |
88 | { | 242 | { |
89 | return hid_open_path(path); | 243 | struct hid_hidapi *ctx; |
244 | |||
245 | if ((ctx = calloc(1, sizeof(*ctx))) == NULL) { | ||
246 | return (NULL); | ||
247 | } | ||
248 | |||
249 | if ((ctx->handle = hid_open_path(path)) == NULL) { | ||
250 | free(ctx); | ||
251 | return (NULL); | ||
252 | } | ||
253 | |||
254 | ctx->report_in_len = ctx->report_out_len = CTAP_MAX_REPORT_LEN; | ||
255 | |||
256 | return ctx; | ||
90 | } | 257 | } |
91 | 258 | ||
92 | void | 259 | void |
93 | fido_hid_close(void *hid_dev_handle) | 260 | fido_hid_close(void *handle) |
94 | { | 261 | { |
95 | hid_close(hid_dev_handle); | 262 | struct hid_hidapi *ctx = handle; |
263 | |||
264 | hid_close(ctx->handle); | ||
265 | free(ctx); | ||
96 | } | 266 | } |
97 | 267 | ||
98 | int | 268 | int |
99 | fido_hid_read(void *hid_dev_handle, unsigned char *buf, size_t len, int ms) | 269 | fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms) |
100 | { | 270 | { |
101 | return hid_read_timeout(hid_dev_handle, buf, len, ms); | 271 | struct hid_hidapi *ctx = handle; |
272 | |||
273 | if (len != ctx->report_in_len) { | ||
274 | fido_log_debug("%s: len %zu", __func__, len); | ||
275 | return -1; | ||
276 | } | ||
277 | |||
278 | return hid_read_timeout(ctx->handle, buf, len, ms); | ||
102 | } | 279 | } |
103 | 280 | ||
104 | int | 281 | int |
105 | fido_hid_write(void *hid_dev_handle, const unsigned char *buf, size_t len) | 282 | fido_hid_write(void *handle, const unsigned char *buf, size_t len) |
106 | { | 283 | { |
107 | return hid_write(hid_dev_handle, buf, len); | 284 | struct hid_hidapi *ctx = handle; |
285 | |||
286 | if (len != ctx->report_out_len + 1) { | ||
287 | fido_log_debug("%s: len %zu", __func__, len); | ||
288 | return -1; | ||
289 | } | ||
290 | |||
291 | return hid_write(ctx->handle, buf, len); | ||
108 | } | 292 | } |
109 | 293 | ||
110 | int | 294 | int |
@@ -122,10 +306,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
122 | return FIDO_OK; /* nothing to do */ | 306 | return FIDO_OK; /* nothing to do */ |
123 | 307 | ||
124 | for (struct hid_device_info *d = hdi; d != NULL; d = d->next) { | 308 | for (struct hid_device_info *d = hdi; d != NULL; d = d->next) { |
125 | #if defined(_WIN32) || defined(__APPLE__) | 309 | if (is_fido(d) == false) |
126 | if (d->usage_page != 0xf1d0) | ||
127 | continue; | 310 | continue; |
128 | #endif | ||
129 | if (copy_info(&devlist[*olen], d) == 0) { | 311 | if (copy_info(&devlist[*olen], d) == 0) { |
130 | if (++(*olen) == ilen) | 312 | if (++(*olen) == ilen) |
131 | break; | 313 | break; |
@@ -136,3 +318,19 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
136 | 318 | ||
137 | return FIDO_OK; | 319 | return FIDO_OK; |
138 | } | 320 | } |
321 | |||
322 | size_t | ||
323 | fido_hid_report_in_len(void *handle) | ||
324 | { | ||
325 | struct hid_hidapi *ctx = handle; | ||
326 | |||
327 | return (ctx->report_in_len); | ||
328 | } | ||
329 | |||
330 | size_t | ||
331 | fido_hid_report_out_len(void *handle) | ||
332 | { | ||
333 | struct hid_hidapi *ctx = handle; | ||
334 | |||
335 | return (ctx->report_out_len); | ||
336 | } | ||
diff --git a/src/hid_linux.c b/src/hid_linux.c index 99c5afb..9788012 100644 --- a/src/hid_linux.c +++ b/src/hid_linux.c | |||
@@ -8,16 +8,22 @@ | |||
8 | 8 | ||
9 | #include <sys/ioctl.h> | 9 | #include <sys/ioctl.h> |
10 | #include <linux/hidraw.h> | 10 | #include <linux/hidraw.h> |
11 | #include <linux/input.h> | ||
11 | 12 | ||
13 | #include <errno.h> | ||
12 | #include <fcntl.h> | 14 | #include <fcntl.h> |
13 | #include <libudev.h> | 15 | #include <libudev.h> |
16 | #include <poll.h> | ||
14 | #include <string.h> | 17 | #include <string.h> |
15 | #include <unistd.h> | 18 | #include <unistd.h> |
16 | #include <errno.h> | ||
17 | 19 | ||
18 | #include "fido.h" | 20 | #include "fido.h" |
19 | 21 | ||
20 | #define REPORT_LEN 65 | 22 | struct hid_linux { |
23 | int fd; | ||
24 | size_t report_in_len; | ||
25 | size_t report_out_len; | ||
26 | }; | ||
21 | 27 | ||
22 | static int | 28 | static int |
23 | get_key_len(uint8_t tag, uint8_t *key, size_t *key_len) | 29 | get_key_len(uint8_t tag, uint8_t *key, size_t *key_len) |
@@ -63,11 +69,8 @@ static int | |||
63 | get_usage_info(const struct hidraw_report_descriptor *hrd, uint32_t *usage_page, | 69 | get_usage_info(const struct hidraw_report_descriptor *hrd, uint32_t *usage_page, |
64 | uint32_t *usage) | 70 | uint32_t *usage) |
65 | { | 71 | { |
66 | const uint8_t *ptr; | 72 | const uint8_t *ptr = hrd->value; |
67 | size_t len; | 73 | size_t len = hrd->size; |
68 | |||
69 | ptr = hrd->value; | ||
70 | len = hrd->size; | ||
71 | 74 | ||
72 | while (len > 0) { | 75 | while (len > 0) { |
73 | const uint8_t tag = ptr[0]; | 76 | const uint8_t tag = ptr[0]; |
@@ -97,80 +100,113 @@ get_usage_info(const struct hidraw_report_descriptor *hrd, uint32_t *usage_page, | |||
97 | } | 100 | } |
98 | 101 | ||
99 | static int | 102 | static int |
100 | get_report_descriptor(const char *path, struct hidraw_report_descriptor *hrd) | 103 | get_report_sizes(const struct hidraw_report_descriptor *hrd, |
104 | size_t *report_in_len, size_t *report_out_len) | ||
101 | { | 105 | { |
102 | int s = -1; | 106 | const uint8_t *ptr = hrd->value; |
103 | int fd; | 107 | size_t len = hrd->size; |
104 | int ok = -1; | 108 | uint32_t report_size = 0; |
105 | 109 | ||
106 | if ((fd = open(path, O_RDONLY)) < 0) { | 110 | while (len > 0) { |
107 | fido_log_debug("%s: open", __func__); | 111 | const uint8_t tag = ptr[0]; |
108 | return (-1); | 112 | ptr++; |
113 | len--; | ||
114 | |||
115 | uint8_t key; | ||
116 | size_t key_len; | ||
117 | uint32_t key_val; | ||
118 | |||
119 | if (get_key_len(tag, &key, &key_len) < 0 || key_len > len || | ||
120 | get_key_val(ptr, key_len, &key_val) < 0) { | ||
121 | return (-1); | ||
122 | } | ||
123 | |||
124 | if (key == 0x94) { | ||
125 | report_size = key_val; | ||
126 | } else if (key == 0x80) { | ||
127 | *report_in_len = (size_t)report_size; | ||
128 | } else if (key == 0x90) { | ||
129 | *report_out_len = (size_t)report_size; | ||
130 | } | ||
131 | |||
132 | ptr += key_len; | ||
133 | len -= key_len; | ||
109 | } | 134 | } |
110 | 135 | ||
136 | return (0); | ||
137 | } | ||
138 | |||
139 | static int | ||
140 | get_report_descriptor(int fd, struct hidraw_report_descriptor *hrd) | ||
141 | { | ||
142 | int s = -1; | ||
143 | |||
111 | if (ioctl(fd, HIDIOCGRDESCSIZE, &s) < 0 || s < 0 || | 144 | if (ioctl(fd, HIDIOCGRDESCSIZE, &s) < 0 || s < 0 || |
112 | (unsigned)s > HID_MAX_DESCRIPTOR_SIZE) { | 145 | (unsigned)s > HID_MAX_DESCRIPTOR_SIZE) { |
113 | fido_log_debug("%s: ioctl HIDIOCGRDESCSIZE", __func__); | 146 | fido_log_debug("%s: ioctl HIDIOCGRDESCSIZE", __func__); |
114 | goto fail; | 147 | return (-1); |
115 | } | 148 | } |
116 | 149 | ||
117 | hrd->size = s; | 150 | hrd->size = (unsigned)s; |
118 | 151 | ||
119 | if (ioctl(fd, HIDIOCGRDESC, hrd) < 0) { | 152 | if (ioctl(fd, HIDIOCGRDESC, hrd) < 0) { |
120 | fido_log_debug("%s: ioctl HIDIOCGRDESC", __func__); | 153 | fido_log_debug("%s: ioctl HIDIOCGRDESC", __func__); |
121 | goto fail; | 154 | return (-1); |
122 | } | 155 | } |
123 | 156 | ||
124 | ok = 0; | 157 | return (0); |
125 | fail: | ||
126 | if (fd != -1) | ||
127 | close(fd); | ||
128 | |||
129 | return (ok); | ||
130 | } | 158 | } |
131 | 159 | ||
132 | static bool | 160 | static bool |
133 | is_fido(const char *path) | 161 | is_fido(const char *path) |
134 | { | 162 | { |
163 | int fd; | ||
135 | uint32_t usage = 0; | 164 | uint32_t usage = 0; |
136 | uint32_t usage_page = 0; | 165 | uint32_t usage_page = 0; |
137 | struct hidraw_report_descriptor hrd; | 166 | struct hidraw_report_descriptor hrd; |
138 | 167 | ||
139 | memset(&hrd, 0, sizeof(hrd)); | 168 | memset(&hrd, 0, sizeof(hrd)); |
140 | 169 | ||
141 | if (get_report_descriptor(path, &hrd) < 0 || | 170 | if ((fd = open(path, O_RDONLY)) == -1) { |
171 | fido_log_debug("%s: open", __func__); | ||
172 | return (false); | ||
173 | } | ||
174 | |||
175 | if (get_report_descriptor(fd, &hrd) < 0 || | ||
142 | get_usage_info(&hrd, &usage_page, &usage) < 0) { | 176 | get_usage_info(&hrd, &usage_page, &usage) < 0) { |
177 | close(fd); | ||
143 | return (false); | 178 | return (false); |
144 | } | 179 | } |
145 | 180 | ||
181 | close(fd); | ||
182 | |||
146 | return (usage_page == 0xf1d0); | 183 | return (usage_page == 0xf1d0); |
147 | } | 184 | } |
148 | 185 | ||
149 | static int | 186 | static int |
150 | parse_uevent(struct udev_device *dev, int16_t *vendor_id, int16_t *product_id) | 187 | parse_uevent(const char *uevent, int *bus, int16_t *vendor_id, |
188 | int16_t *product_id) | ||
151 | { | 189 | { |
152 | const char *uevent; | ||
153 | char *cp; | 190 | char *cp; |
154 | char *p; | 191 | char *p; |
155 | char *s; | 192 | char *s; |
156 | int ok = -1; | 193 | int ok = -1; |
157 | short unsigned int x; | 194 | short unsigned int x; |
158 | short unsigned int y; | 195 | short unsigned int y; |
159 | 196 | short unsigned int z; | |
160 | if ((uevent = udev_device_get_sysattr_value(dev, "uevent")) == NULL) | ||
161 | return (-1); | ||
162 | 197 | ||
163 | if ((s = cp = strdup(uevent)) == NULL) | 198 | if ((s = cp = strdup(uevent)) == NULL) |
164 | return (-1); | 199 | return (-1); |
165 | 200 | ||
166 | for ((p = strsep(&cp, "\n")); p && *p != '\0'; (p = strsep(&cp, "\n"))) { | 201 | while ((p = strsep(&cp, "\n")) != NULL && *p != '\0') { |
167 | if (strncmp(p, "HID_ID=", 7) == 0) { | 202 | if (strncmp(p, "HID_ID=", 7) == 0) { |
168 | if (sscanf(p + 7, "%*x:%hx:%hx", &x, &y) == 2) { | 203 | if (sscanf(p + 7, "%hx:%hx:%hx", &x, &y, &z) == 3) { |
169 | *vendor_id = (int16_t)x; | 204 | *bus = (int)x; |
170 | *product_id = (int16_t)y; | 205 | *vendor_id = (int16_t)y; |
206 | *product_id = (int16_t)z; | ||
171 | ok = 0; | 207 | ok = 0; |
208 | break; | ||
172 | } | 209 | } |
173 | break; | ||
174 | } | 210 | } |
175 | } | 211 | } |
176 | 212 | ||
@@ -179,17 +215,36 @@ parse_uevent(struct udev_device *dev, int16_t *vendor_id, int16_t *product_id) | |||
179 | return (ok); | 215 | return (ok); |
180 | } | 216 | } |
181 | 217 | ||
218 | static char * | ||
219 | get_parent_attr(struct udev_device *dev, const char *subsystem, | ||
220 | const char *devtype, const char *attr) | ||
221 | { | ||
222 | struct udev_device *parent; | ||
223 | const char *value; | ||
224 | |||
225 | if ((parent = udev_device_get_parent_with_subsystem_devtype(dev, | ||
226 | subsystem, devtype)) == NULL || (value = | ||
227 | udev_device_get_sysattr_value(parent, attr)) == NULL) | ||
228 | return (NULL); | ||
229 | |||
230 | return (strdup(value)); | ||
231 | } | ||
232 | |||
233 | static char * | ||
234 | get_usb_attr(struct udev_device *dev, const char *attr) | ||
235 | { | ||
236 | return (get_parent_attr(dev, "usb", "usb_device", attr)); | ||
237 | } | ||
238 | |||
182 | static int | 239 | static int |
183 | copy_info(fido_dev_info_t *di, struct udev *udev, | 240 | copy_info(fido_dev_info_t *di, struct udev *udev, |
184 | struct udev_list_entry *udev_entry) | 241 | struct udev_list_entry *udev_entry) |
185 | { | 242 | { |
186 | const char *name; | 243 | const char *name; |
187 | const char *path; | 244 | const char *path; |
188 | const char *manufacturer; | 245 | char *uevent = NULL; |
189 | const char *product; | ||
190 | struct udev_device *dev = NULL; | 246 | struct udev_device *dev = NULL; |
191 | struct udev_device *hid_parent; | 247 | int bus = 0; |
192 | struct udev_device *usb_parent; | ||
193 | int ok = -1; | 248 | int ok = -1; |
194 | 249 | ||
195 | memset(di, 0, sizeof(*di)); | 250 | memset(di, 0, sizeof(*di)); |
@@ -200,28 +255,24 @@ copy_info(fido_dev_info_t *di, struct udev *udev, | |||
200 | is_fido(path) == 0) | 255 | is_fido(path) == 0) |
201 | goto fail; | 256 | goto fail; |
202 | 257 | ||
203 | if ((hid_parent = udev_device_get_parent_with_subsystem_devtype(dev, | 258 | if ((uevent = get_parent_attr(dev, "hid", NULL, "uevent")) == NULL || |
204 | "hid", NULL)) == NULL) | 259 | parse_uevent(uevent, &bus, &di->vendor_id, &di->product_id) < 0) { |
205 | goto fail; | 260 | fido_log_debug("%s: uevent", __func__); |
206 | |||
207 | if ((usb_parent = udev_device_get_parent_with_subsystem_devtype(dev, | ||
208 | "usb", "usb_device")) == NULL) | ||
209 | goto fail; | 261 | goto fail; |
262 | } | ||
210 | 263 | ||
211 | if (parse_uevent(hid_parent, &di->vendor_id, &di->product_id) < 0 || | 264 | #ifndef FIDO_HID_ANY |
212 | (manufacturer = udev_device_get_sysattr_value(usb_parent, | 265 | if (bus != BUS_USB) { |
213 | "manufacturer")) == NULL || | 266 | fido_log_debug("%s: bus", __func__); |
214 | (product = udev_device_get_sysattr_value(usb_parent, | ||
215 | "product")) == NULL) | ||
216 | goto fail; | 267 | goto fail; |
268 | } | ||
269 | #endif | ||
217 | 270 | ||
218 | di->path = strdup(path); | 271 | di->path = strdup(path); |
219 | di->manufacturer = strdup(manufacturer); | 272 | di->manufacturer = get_usb_attr(dev, "manufacturer"); |
220 | di->product = strdup(product); | 273 | di->product = get_usb_attr(dev, "product"); |
221 | 274 | ||
222 | if (di->path == NULL || | 275 | if (di->path == NULL || di->manufacturer == NULL || di->product == NULL) |
223 | di->manufacturer == NULL || | ||
224 | di->product == NULL) | ||
225 | goto fail; | 276 | goto fail; |
226 | 277 | ||
227 | ok = 0; | 278 | ok = 0; |
@@ -229,6 +280,8 @@ fail: | |||
229 | if (dev != NULL) | 280 | if (dev != NULL) |
230 | udev_device_unref(dev); | 281 | udev_device_unref(dev); |
231 | 282 | ||
283 | free(uevent); | ||
284 | |||
232 | if (ok < 0) { | 285 | if (ok < 0) { |
233 | free(di->path); | 286 | free(di->path); |
234 | free(di->manufacturer); | 287 | free(di->manufacturer); |
@@ -261,9 +314,13 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
261 | goto fail; | 314 | goto fail; |
262 | 315 | ||
263 | if (udev_enumerate_add_match_subsystem(udev_enum, "hidraw") < 0 || | 316 | if (udev_enumerate_add_match_subsystem(udev_enum, "hidraw") < 0 || |
264 | udev_enumerate_scan_devices(udev_enum) < 0 || | 317 | udev_enumerate_scan_devices(udev_enum) < 0) |
265 | (udev_list = udev_enumerate_get_list_entry(udev_enum)) == NULL) | 318 | goto fail; |
319 | |||
320 | if ((udev_list = udev_enumerate_get_list_entry(udev_enum)) == NULL) { | ||
321 | r = FIDO_OK; /* zero hidraw devices */ | ||
266 | goto fail; | 322 | goto fail; |
323 | } | ||
267 | 324 | ||
268 | udev_list_entry_foreach(udev_entry, udev_list) { | 325 | udev_list_entry_foreach(udev_entry, udev_list) { |
269 | if (copy_info(&devlist[*olen], udev, udev_entry) == 0) { | 326 | if (copy_info(&devlist[*olen], udev, udev_entry) == 0) { |
@@ -291,60 +348,157 @@ fail: | |||
291 | void * | 348 | void * |
292 | fido_hid_open(const char *path) | 349 | fido_hid_open(const char *path) |
293 | { | 350 | { |
294 | int *fd; | 351 | struct hid_linux *ctx; |
352 | struct hidraw_report_descriptor hrd; | ||
353 | |||
354 | if ((ctx = calloc(1, sizeof(*ctx))) == NULL) | ||
355 | return (NULL); | ||
295 | 356 | ||
296 | if ((fd = malloc(sizeof(*fd))) == NULL || | 357 | if ((ctx->fd = open(path, O_RDWR)) < 0) { |
297 | (*fd = open(path, O_RDWR)) < 0) { | 358 | free(ctx); |
298 | free(fd); | ||
299 | return (NULL); | 359 | return (NULL); |
300 | } | 360 | } |
301 | 361 | ||
302 | return (fd); | 362 | if (get_report_descriptor(ctx->fd, &hrd) < 0 || get_report_sizes(&hrd, |
363 | &ctx->report_in_len, &ctx->report_out_len) < 0 || | ||
364 | ctx->report_in_len == 0 || ctx->report_out_len == 0) { | ||
365 | fido_log_debug("%s: using default report sizes", __func__); | ||
366 | ctx->report_in_len = CTAP_MAX_REPORT_LEN; | ||
367 | ctx->report_out_len = CTAP_MAX_REPORT_LEN; | ||
368 | } | ||
369 | |||
370 | return (ctx); | ||
303 | } | 371 | } |
304 | 372 | ||
305 | void | 373 | void |
306 | fido_hid_close(void *handle) | 374 | fido_hid_close(void *handle) |
307 | { | 375 | { |
308 | int *fd = handle; | 376 | struct hid_linux *ctx = handle; |
377 | |||
378 | close(ctx->fd); | ||
379 | free(ctx); | ||
380 | } | ||
381 | |||
382 | static int | ||
383 | timespec_to_ms(const struct timespec *ts, int upper_bound) | ||
384 | { | ||
385 | int64_t x; | ||
386 | int64_t y; | ||
387 | |||
388 | if (ts->tv_sec < 0 || ts->tv_sec > INT64_MAX / 1000LL || | ||
389 | ts->tv_nsec < 0 || ts->tv_nsec / 1000000LL > INT64_MAX) | ||
390 | return (upper_bound); | ||
391 | |||
392 | x = ts->tv_sec * 1000LL; | ||
393 | y = ts->tv_nsec / 1000000LL; | ||
394 | |||
395 | if (INT64_MAX - x < y || x + y > upper_bound) | ||
396 | return (upper_bound); | ||
397 | |||
398 | return (int)(x + y); | ||
399 | } | ||
400 | |||
401 | static int | ||
402 | waitfd(int fd, int ms) | ||
403 | { | ||
404 | struct timespec ts_start; | ||
405 | struct timespec ts_now; | ||
406 | struct timespec ts_delta; | ||
407 | struct pollfd pfd; | ||
408 | int ms_remain; | ||
409 | int r; | ||
410 | |||
411 | if (ms < 0) | ||
412 | return (0); | ||
413 | |||
414 | memset(&pfd, 0, sizeof(pfd)); | ||
415 | pfd.events = POLLIN; | ||
416 | pfd.fd = fd; | ||
417 | |||
418 | if (clock_gettime(CLOCK_MONOTONIC, &ts_start) != 0) { | ||
419 | fido_log_debug("%s: clock_gettime: %s", __func__, | ||
420 | strerror(errno)); | ||
421 | return (-1); | ||
422 | } | ||
423 | |||
424 | for (ms_remain = ms; ms_remain > 0;) { | ||
425 | if ((r = poll(&pfd, 1, ms_remain)) > 0) | ||
426 | return (0); | ||
427 | else if (r == 0) | ||
428 | break; | ||
429 | else if (errno != EINTR) { | ||
430 | fido_log_debug("%s: poll: %s", __func__, | ||
431 | strerror(errno)); | ||
432 | return (-1); | ||
433 | } | ||
434 | /* poll interrupted - subtract time already waited */ | ||
435 | if (clock_gettime(CLOCK_MONOTONIC, &ts_now) != 0) { | ||
436 | fido_log_debug("%s: clock_gettime: %s", __func__, | ||
437 | strerror(errno)); | ||
438 | return (-1); | ||
439 | } | ||
440 | timespecsub(&ts_now, &ts_start, &ts_delta); | ||
441 | ms_remain = ms - timespec_to_ms(&ts_delta, ms); | ||
442 | } | ||
309 | 443 | ||
310 | close(*fd); | 444 | return (-1); |
311 | free(fd); | ||
312 | } | 445 | } |
313 | 446 | ||
314 | int | 447 | int |
315 | fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms) | 448 | fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms) |
316 | { | 449 | { |
317 | int *fd = handle; | 450 | struct hid_linux *ctx = handle; |
318 | ssize_t r; | 451 | ssize_t r; |
319 | 452 | ||
320 | (void)ms; /* XXX */ | 453 | if (len != ctx->report_in_len) { |
454 | fido_log_debug("%s: len %zu", __func__, len); | ||
455 | return (-1); | ||
456 | } | ||
321 | 457 | ||
322 | if (len != REPORT_LEN - 1) { | 458 | if (waitfd(ctx->fd, ms) < 0) { |
323 | fido_log_debug("%s: invalid len", __func__); | 459 | fido_log_debug("%s: fd not ready", __func__); |
324 | return (-1); | 460 | return (-1); |
325 | } | 461 | } |
326 | 462 | ||
327 | if ((r = read(*fd, buf, len)) < 0 || r != REPORT_LEN - 1) | 463 | if ((r = read(ctx->fd, buf, len)) < 0 || (size_t)r != len) { |
464 | fido_log_debug("%s: read", __func__); | ||
328 | return (-1); | 465 | return (-1); |
466 | } | ||
329 | 467 | ||
330 | return (REPORT_LEN - 1); | 468 | return ((int)r); |
331 | } | 469 | } |
332 | 470 | ||
333 | int | 471 | int |
334 | fido_hid_write(void *handle, const unsigned char *buf, size_t len) | 472 | fido_hid_write(void *handle, const unsigned char *buf, size_t len) |
335 | { | 473 | { |
336 | int *fd = handle; | 474 | struct hid_linux *ctx = handle; |
337 | ssize_t r; | 475 | ssize_t r; |
338 | 476 | ||
339 | if (len != REPORT_LEN) { | 477 | if (len != ctx->report_out_len + 1) { |
340 | fido_log_debug("%s: invalid len", __func__); | 478 | fido_log_debug("%s: len %zu", __func__, len); |
341 | return (-1); | 479 | return (-1); |
342 | } | 480 | } |
343 | 481 | ||
344 | if ((r = write(*fd, buf, len)) < 0 || r != REPORT_LEN) { | 482 | if ((r = write(ctx->fd, buf, len)) < 0 || (size_t)r != len) { |
345 | fido_log_debug("%s: write", __func__); | 483 | fido_log_debug("%s: write", __func__); |
346 | return (-1); | 484 | return (-1); |
347 | } | 485 | } |
348 | 486 | ||
349 | return (REPORT_LEN); | 487 | return ((int)r); |
488 | } | ||
489 | |||
490 | size_t | ||
491 | fido_hid_report_in_len(void *handle) | ||
492 | { | ||
493 | struct hid_linux *ctx = handle; | ||
494 | |||
495 | return (ctx->report_in_len); | ||
496 | } | ||
497 | |||
498 | size_t | ||
499 | fido_hid_report_out_len(void *handle) | ||
500 | { | ||
501 | struct hid_linux *ctx = handle; | ||
502 | |||
503 | return (ctx->report_out_len); | ||
350 | } | 504 | } |
diff --git a/src/hid_openbsd.c b/src/hid_openbsd.c index 2b31dba..319f7b8 100644 --- a/src/hid_openbsd.c +++ b/src/hid_openbsd.c | |||
@@ -8,19 +8,16 @@ | |||
8 | 8 | ||
9 | #include <sys/ioctl.h> | 9 | #include <sys/ioctl.h> |
10 | #include <dev/usb/usb.h> | 10 | #include <dev/usb/usb.h> |
11 | #include <dev/usb/usbhid.h> | ||
12 | 11 | ||
13 | #include <errno.h> | 12 | #include <errno.h> |
14 | #include <fcntl.h> | 13 | #include <fcntl.h> |
15 | #include <string.h> | 14 | #include <string.h> |
16 | #include <unistd.h> | 15 | #include <unistd.h> |
17 | #include <usbhid.h> | ||
18 | #include <poll.h> | 16 | #include <poll.h> |
19 | 17 | ||
20 | #include "fido.h" | 18 | #include "fido.h" |
21 | 19 | ||
22 | #define MAX_UHID 64 | 20 | #define MAX_UHID 64 |
23 | #define MAX_REPORT_LEN (sizeof(((struct usb_ctl_report *)(NULL))->ucr_data)) | ||
24 | 21 | ||
25 | struct hid_openbsd { | 22 | struct hid_openbsd { |
26 | int fd; | 23 | int fd; |
@@ -33,11 +30,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
33 | { | 30 | { |
34 | size_t i; | 31 | size_t i; |
35 | char path[64]; | 32 | char path[64]; |
36 | int is_fido, fd; | 33 | int fd; |
37 | struct usb_device_info udi; | 34 | struct usb_device_info udi; |
38 | report_desc_t rdesc = NULL; | ||
39 | hid_data_t hdata = NULL; | ||
40 | hid_item_t hitem; | ||
41 | fido_dev_info_t *di; | 35 | fido_dev_info_t *di; |
42 | 36 | ||
43 | if (ilen == 0) | 37 | if (ilen == 0) |
@@ -47,7 +41,7 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
47 | return (FIDO_ERR_INVALID_ARGUMENT); | 41 | return (FIDO_ERR_INVALID_ARGUMENT); |
48 | 42 | ||
49 | for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) { | 43 | for (i = *olen = 0; i < MAX_UHID && *olen < ilen; i++) { |
50 | snprintf(path, sizeof(path), "/dev/uhid%zu", i); | 44 | snprintf(path, sizeof(path), "/dev/fido/%zu", i); |
51 | if ((fd = open(path, O_RDWR)) == -1) { | 45 | if ((fd = open(path, O_RDWR)) == -1) { |
52 | if (errno != ENOENT && errno != ENXIO) { | 46 | if (errno != ENOENT && errno != ENXIO) { |
53 | fido_log_debug("%s: open %s: %s", __func__, | 47 | fido_log_debug("%s: open %s: %s", __func__, |
@@ -55,6 +49,7 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
55 | } | 49 | } |
56 | continue; | 50 | continue; |
57 | } | 51 | } |
52 | |||
58 | memset(&udi, 0, sizeof(udi)); | 53 | memset(&udi, 0, sizeof(udi)); |
59 | if (ioctl(fd, USB_GET_DEVICEINFO, &udi) != 0) { | 54 | if (ioctl(fd, USB_GET_DEVICEINFO, &udi) != 0) { |
60 | fido_log_debug("%s: get device info %s: %s", __func__, | 55 | fido_log_debug("%s: get device info %s: %s", __func__, |
@@ -62,35 +57,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
62 | close(fd); | 57 | close(fd); |
63 | continue; | 58 | continue; |
64 | } | 59 | } |
65 | if ((rdesc = hid_get_report_desc(fd)) == NULL) { | ||
66 | fido_log_debug("%s: failed to get report descriptor: %s", | ||
67 | __func__, path); | ||
68 | close(fd); | ||
69 | continue; | ||
70 | } | ||
71 | if ((hdata = hid_start_parse(rdesc, | ||
72 | 1<<hid_collection, -1)) == NULL) { | ||
73 | fido_log_debug("%s: failed to parse report descriptor: %s", | ||
74 | __func__, path); | ||
75 | hid_dispose_report_desc(rdesc); | ||
76 | close(fd); | ||
77 | continue; | ||
78 | } | ||
79 | is_fido = 0; | ||
80 | for (is_fido = 0; !is_fido;) { | ||
81 | memset(&hitem, 0, sizeof(hitem)); | ||
82 | if (hid_get_item(hdata, &hitem) <= 0) | ||
83 | break; | ||
84 | if ((hitem._usage_page & 0xFFFF0000) == 0xf1d00000) | ||
85 | is_fido = 1; | ||
86 | } | ||
87 | hid_end_parse(hdata); | ||
88 | hid_dispose_report_desc(rdesc); | ||
89 | close(fd); | 60 | close(fd); |
90 | 61 | ||
91 | if (!is_fido) | ||
92 | continue; | ||
93 | |||
94 | fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x", | 62 | fido_log_debug("%s: %s: bus = 0x%02x, addr = 0x%02x", |
95 | __func__, path, udi.udi_bus, udi.udi_addr); | 63 | __func__, path, udi.udi_bus, udi.udi_addr); |
96 | fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"", | 64 | fido_log_debug("%s: %s: vendor = \"%s\", product = \"%s\"", |
@@ -116,8 +84,8 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
116 | explicit_bzero(di, sizeof(*di)); | 84 | explicit_bzero(di, sizeof(*di)); |
117 | return FIDO_ERR_INTERNAL; | 85 | return FIDO_ERR_INTERNAL; |
118 | } | 86 | } |
119 | di->vendor_id = udi.udi_vendorNo; | 87 | di->vendor_id = (int16_t)udi.udi_vendorNo; |
120 | di->product_id = udi.udi_productNo; | 88 | di->product_id = (int16_t)udi.udi_productNo; |
121 | (*olen)++; | 89 | (*olen)++; |
122 | } | 90 | } |
123 | 91 | ||
@@ -184,42 +152,15 @@ void * | |||
184 | fido_hid_open(const char *path) | 152 | fido_hid_open(const char *path) |
185 | { | 153 | { |
186 | struct hid_openbsd *ret = NULL; | 154 | struct hid_openbsd *ret = NULL; |
187 | report_desc_t rdesc = NULL; | ||
188 | int len, usb_report_id = 0; | ||
189 | 155 | ||
190 | if ((ret = calloc(1, sizeof(*ret))) == NULL || | 156 | if ((ret = calloc(1, sizeof(*ret))) == NULL || |
191 | (ret->fd = open(path, O_RDWR)) < 0) { | 157 | (ret->fd = open(path, O_RDWR)) < 0) { |
192 | free(ret); | 158 | free(ret); |
193 | return (NULL); | 159 | return (NULL); |
194 | } | 160 | } |
195 | if (ioctl(ret->fd, USB_GET_REPORT_ID, &usb_report_id) != 0) { | 161 | ret->report_in_len = ret->report_out_len = CTAP_MAX_REPORT_LEN; |
196 | fido_log_debug("%s: failed to get report ID: %s", __func__, | 162 | fido_log_debug("%s: inlen = %zu outlen = %zu", __func__, |
197 | strerror(errno)); | 163 | ret->report_in_len, ret->report_out_len); |
198 | goto fail; | ||
199 | } | ||
200 | if ((rdesc = hid_get_report_desc(ret->fd)) == NULL) { | ||
201 | fido_log_debug("%s: failed to get report descriptor", __func__); | ||
202 | goto fail; | ||
203 | } | ||
204 | if ((len = hid_report_size(rdesc, hid_input, usb_report_id)) <= 0 || | ||
205 | (size_t)len > MAX_REPORT_LEN) { | ||
206 | fido_log_debug("%s: bad input report size %d", __func__, len); | ||
207 | goto fail; | ||
208 | } | ||
209 | ret->report_in_len = (size_t)len; | ||
210 | if ((len = hid_report_size(rdesc, hid_output, usb_report_id)) <= 0 || | ||
211 | (size_t)len > MAX_REPORT_LEN) { | ||
212 | fido_log_debug("%s: bad output report size %d", __func__, len); | ||
213 | fail: | ||
214 | hid_dispose_report_desc(rdesc); | ||
215 | close(ret->fd); | ||
216 | free(ret); | ||
217 | return NULL; | ||
218 | } | ||
219 | ret->report_out_len = (size_t)len; | ||
220 | hid_dispose_report_desc(rdesc); | ||
221 | fido_log_debug("%s: USB report ID %d, inlen = %zu outlen = %zu", | ||
222 | __func__, usb_report_id, ret->report_in_len, ret->report_out_len); | ||
223 | 164 | ||
224 | /* | 165 | /* |
225 | * OpenBSD (as of 201910) has a bug that causes it to lose | 166 | * OpenBSD (as of 201910) has a bug that causes it to lose |
@@ -281,3 +222,19 @@ fido_hid_write(void *handle, const unsigned char *buf, size_t len) | |||
281 | } | 222 | } |
282 | return ((int)len); | 223 | return ((int)len); |
283 | } | 224 | } |
225 | |||
226 | size_t | ||
227 | fido_hid_report_in_len(void *handle) | ||
228 | { | ||
229 | struct hid_openbsd *ctx = handle; | ||
230 | |||
231 | return (ctx->report_in_len); | ||
232 | } | ||
233 | |||
234 | size_t | ||
235 | fido_hid_report_out_len(void *handle) | ||
236 | { | ||
237 | struct hid_openbsd *ctx = handle; | ||
238 | |||
239 | return (ctx->report_out_len); | ||
240 | } | ||
diff --git a/src/hid_osx.c b/src/hid_osx.c index 5c40747..6be5cd7 100644 --- a/src/hid_osx.c +++ b/src/hid_osx.c | |||
@@ -19,11 +19,13 @@ | |||
19 | 19 | ||
20 | #include "fido.h" | 20 | #include "fido.h" |
21 | 21 | ||
22 | #define REPORT_LEN 65 | 22 | struct hid_osx { |
23 | |||
24 | struct dev { | ||
25 | IOHIDDeviceRef ref; | 23 | IOHIDDeviceRef ref; |
26 | CFStringRef loop_id; | 24 | CFStringRef loop_id; |
25 | int report_pipe[2]; | ||
26 | size_t report_in_len; | ||
27 | size_t report_out_len; | ||
28 | unsigned char report[CTAP_MAX_REPORT_LEN]; | ||
27 | }; | 29 | }; |
28 | 30 | ||
29 | static int | 31 | static int |
@@ -64,7 +66,8 @@ get_utf8(IOHIDDeviceRef dev, CFStringRef key, void *buf, size_t len) | |||
64 | return (-1); | 66 | return (-1); |
65 | } | 67 | } |
66 | 68 | ||
67 | if (CFStringGetCString(ref, buf, len, kCFStringEncodingUTF8) == false) { | 69 | if (CFStringGetCString(ref, buf, (long)len, |
70 | kCFStringEncodingUTF8) == false) { | ||
68 | fido_log_debug("%s: CFStringGetCString", __func__); | 71 | fido_log_debug("%s: CFStringGetCString", __func__); |
69 | return (-1); | 72 | return (-1); |
70 | } | 73 | } |
@@ -72,30 +75,35 @@ get_utf8(IOHIDDeviceRef dev, CFStringRef key, void *buf, size_t len) | |||
72 | return (0); | 75 | return (0); |
73 | } | 76 | } |
74 | 77 | ||
75 | static bool | 78 | static int |
76 | is_fido(IOHIDDeviceRef dev) | 79 | get_report_len(IOHIDDeviceRef dev, int dir, size_t *report_len) |
77 | { | 80 | { |
78 | uint32_t usage_page; | 81 | CFStringRef key; |
79 | int32_t report_len; | 82 | int32_t v; |
80 | 83 | ||
81 | if (get_int32(dev, CFSTR(kIOHIDPrimaryUsagePageKey), | 84 | if (dir == 0) |
82 | (int32_t *)&usage_page) != 0 || usage_page != 0xf1d0) | 85 | key = CFSTR(kIOHIDMaxInputReportSizeKey); |
83 | return (false); | 86 | else |
87 | key = CFSTR(kIOHIDMaxOutputReportSizeKey); | ||
84 | 88 | ||
85 | if (get_int32(dev, CFSTR(kIOHIDMaxInputReportSizeKey), | 89 | if (get_int32(dev, key, &v) < 0) { |
86 | &report_len) < 0 || report_len != REPORT_LEN - 1) { | 90 | fido_log_debug("%s: get_int32/%d", __func__, dir); |
87 | fido_log_debug("%s: unsupported report len", __func__); | 91 | return (-1); |
88 | return (false); | ||
89 | } | 92 | } |
90 | 93 | ||
91 | return (true); | 94 | if ((*report_len = (size_t)v) > CTAP_MAX_REPORT_LEN) { |
95 | fido_log_debug("%s: report_len=%zu", __func__, *report_len); | ||
96 | return (-1); | ||
97 | } | ||
98 | |||
99 | return (0); | ||
92 | } | 100 | } |
93 | 101 | ||
94 | static int | 102 | static int |
95 | get_id(IOHIDDeviceRef dev, int16_t *vendor_id, int16_t *product_id) | 103 | get_id(IOHIDDeviceRef dev, int16_t *vendor_id, int16_t *product_id) |
96 | { | 104 | { |
97 | int32_t vendor; | 105 | int32_t vendor; |
98 | int32_t product; | 106 | int32_t product; |
99 | 107 | ||
100 | if (get_int32(dev, CFSTR(kIOHIDVendorIDKey), &vendor) < 0 || | 108 | if (get_int32(dev, CFSTR(kIOHIDVendorIDKey), &vendor) < 0 || |
101 | vendor > UINT16_MAX) { | 109 | vendor > UINT16_MAX) { |
@@ -175,6 +183,31 @@ get_path(IOHIDDeviceRef dev) | |||
175 | return (strdup(path)); | 183 | return (strdup(path)); |
176 | } | 184 | } |
177 | 185 | ||
186 | static bool | ||
187 | is_fido(IOHIDDeviceRef dev) | ||
188 | { | ||
189 | char buf[32]; | ||
190 | uint32_t usage_page; | ||
191 | |||
192 | if (get_int32(dev, CFSTR(kIOHIDPrimaryUsagePageKey), | ||
193 | (int32_t *)&usage_page) < 0 || usage_page != 0xf1d0) | ||
194 | return (false); | ||
195 | |||
196 | if (get_utf8(dev, CFSTR(kIOHIDTransportKey), buf, sizeof(buf)) < 0) { | ||
197 | fido_log_debug("%s: get_utf8 transport", __func__); | ||
198 | return (false); | ||
199 | } | ||
200 | |||
201 | #ifndef FIDO_HID_ANY | ||
202 | if (strcasecmp(buf, "usb") != 0) { | ||
203 | fido_log_debug("%s: transport", __func__); | ||
204 | return (false); | ||
205 | } | ||
206 | #endif | ||
207 | |||
208 | return (true); | ||
209 | } | ||
210 | |||
178 | static int | 211 | static int |
179 | copy_info(fido_dev_info_t *di, IOHIDDeviceRef dev) | 212 | copy_info(fido_dev_info_t *di, IOHIDDeviceRef dev) |
180 | { | 213 | { |
@@ -199,11 +232,12 @@ copy_info(fido_dev_info_t *di, IOHIDDeviceRef dev) | |||
199 | int | 232 | int |
200 | fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | 233 | fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) |
201 | { | 234 | { |
202 | IOHIDManagerRef manager = NULL; | 235 | IOHIDManagerRef manager = NULL; |
203 | CFSetRef devset = NULL; | 236 | CFSetRef devset = NULL; |
204 | CFIndex devcnt; | 237 | size_t devcnt; |
205 | IOHIDDeviceRef *devs = NULL; | 238 | CFIndex n; |
206 | int r = FIDO_ERR_INTERNAL; | 239 | IOHIDDeviceRef *devs = NULL; |
240 | int r = FIDO_ERR_INTERNAL; | ||
207 | 241 | ||
208 | *olen = 0; | 242 | *olen = 0; |
209 | 243 | ||
@@ -226,11 +260,13 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
226 | goto fail; | 260 | goto fail; |
227 | } | 261 | } |
228 | 262 | ||
229 | if ((devcnt = CFSetGetCount(devset)) < 0) { | 263 | if ((n = CFSetGetCount(devset)) < 0) { |
230 | fido_log_debug("%s: CFSetGetCount", __func__); | 264 | fido_log_debug("%s: CFSetGetCount", __func__); |
231 | goto fail; | 265 | goto fail; |
232 | } | 266 | } |
233 | 267 | ||
268 | devcnt = (size_t)n; | ||
269 | |||
234 | if ((devs = calloc(devcnt, sizeof(*devs))) == NULL) { | 270 | if ((devs = calloc(devcnt, sizeof(*devs))) == NULL) { |
235 | fido_log_debug("%s: calloc", __func__); | 271 | fido_log_debug("%s: calloc", __func__); |
236 | goto fail; | 272 | goto fail; |
@@ -238,7 +274,7 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
238 | 274 | ||
239 | CFSetGetValues(devset, (void *)devs); | 275 | CFSetGetValues(devset, (void *)devs); |
240 | 276 | ||
241 | for (CFIndex i = 0; i < devcnt; i++) { | 277 | for (size_t i = 0; i < devcnt; i++) { |
242 | if (copy_info(&devlist[*olen], devs[i]) == 0) { | 278 | if (copy_info(&devlist[*olen], devs[i]) == 0) { |
243 | devlist[*olen].io = (fido_dev_io_t) { | 279 | devlist[*olen].io = (fido_dev_io_t) { |
244 | fido_hid_open, | 280 | fido_hid_open, |
@@ -263,157 +299,258 @@ fail: | |||
263 | return (r); | 299 | return (r); |
264 | } | 300 | } |
265 | 301 | ||
302 | static void | ||
303 | report_callback(void *context, IOReturn result, void *dev, IOHIDReportType type, | ||
304 | uint32_t id, uint8_t *ptr, CFIndex len) | ||
305 | { | ||
306 | struct hid_osx *ctx = context; | ||
307 | ssize_t r; | ||
308 | |||
309 | (void)dev; | ||
310 | |||
311 | if (result != kIOReturnSuccess || type != kIOHIDReportTypeInput || | ||
312 | id != 0 || len < 0 || (size_t)len != ctx->report_in_len) { | ||
313 | fido_log_debug("%s: io error", __func__); | ||
314 | return; | ||
315 | } | ||
316 | |||
317 | if ((r = write(ctx->report_pipe[1], ptr, (size_t)len)) < 0 || | ||
318 | (size_t)r != (size_t)len) { | ||
319 | fido_log_debug("%s: write", __func__); | ||
320 | return; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | static void | ||
325 | removal_callback(void *context, IOReturn result, void *sender) | ||
326 | { | ||
327 | (void)context; | ||
328 | (void)result; | ||
329 | (void)sender; | ||
330 | |||
331 | CFRunLoopStop(CFRunLoopGetMain()); | ||
332 | } | ||
333 | |||
334 | static int | ||
335 | set_nonblock(int fd) | ||
336 | { | ||
337 | int flags; | ||
338 | |||
339 | if ((flags = fcntl(fd, F_GETFL)) == -1) { | ||
340 | fido_log_debug("%s: fcntl F_GETFL", __func__); | ||
341 | return (-1); | ||
342 | } | ||
343 | |||
344 | if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { | ||
345 | fido_log_debug("%s: fcntl, F_SETFL", __func__); | ||
346 | return (-1); | ||
347 | } | ||
348 | |||
349 | return (0); | ||
350 | } | ||
351 | |||
352 | static int | ||
353 | disable_sigpipe(int fd) | ||
354 | { | ||
355 | int disabled = 1; | ||
356 | |||
357 | if (fcntl(fd, F_SETNOSIGPIPE, &disabled) == -1) { | ||
358 | fido_log_debug("%s: fcntl F_SETNOSIGPIPE", __func__); | ||
359 | return (-1); | ||
360 | } | ||
361 | |||
362 | return (0); | ||
363 | } | ||
364 | |||
266 | void * | 365 | void * |
267 | fido_hid_open(const char *path) | 366 | fido_hid_open(const char *path) |
268 | { | 367 | { |
368 | struct hid_osx *ctx; | ||
269 | io_registry_entry_t entry = MACH_PORT_NULL; | 369 | io_registry_entry_t entry = MACH_PORT_NULL; |
270 | struct dev *dev = NULL; | 370 | char loop_id[32]; |
271 | int ok = -1; | 371 | int ok = -1; |
272 | int r; | 372 | int r; |
273 | char loop_id[32]; | ||
274 | 373 | ||
275 | if ((dev = calloc(1, sizeof(*dev))) == NULL) { | 374 | if ((ctx = calloc(1, sizeof(*ctx))) == NULL) { |
276 | fido_log_debug("%s: calloc", __func__); | 375 | fido_log_debug("%s: calloc", __func__); |
277 | goto fail; | 376 | goto fail; |
278 | } | 377 | } |
279 | 378 | ||
379 | ctx->report_pipe[0] = -1; | ||
380 | ctx->report_pipe[1] = -1; | ||
381 | |||
382 | if (pipe(ctx->report_pipe) == -1) { | ||
383 | fido_log_debug("%s: pipe", __func__); | ||
384 | goto fail; | ||
385 | } | ||
386 | |||
387 | if (set_nonblock(ctx->report_pipe[0]) < 0 || | ||
388 | set_nonblock(ctx->report_pipe[1]) < 0) { | ||
389 | fido_log_debug("%s: set_nonblock", __func__); | ||
390 | goto fail; | ||
391 | } | ||
392 | |||
393 | if (disable_sigpipe(ctx->report_pipe[1]) < 0) { | ||
394 | fido_log_debug("%s: disable_sigpipe", __func__); | ||
395 | goto fail; | ||
396 | } | ||
397 | |||
280 | if ((entry = IORegistryEntryFromPath(kIOMasterPortDefault, | 398 | if ((entry = IORegistryEntryFromPath(kIOMasterPortDefault, |
281 | path)) == MACH_PORT_NULL) { | 399 | path)) == MACH_PORT_NULL) { |
282 | fido_log_debug("%s: IORegistryEntryFromPath", __func__); | 400 | fido_log_debug("%s: IORegistryEntryFromPath", __func__); |
283 | goto fail; | 401 | goto fail; |
284 | } | 402 | } |
285 | 403 | ||
286 | if ((dev->ref = IOHIDDeviceCreate(kCFAllocatorDefault, | 404 | if ((ctx->ref = IOHIDDeviceCreate(kCFAllocatorDefault, |
287 | entry)) == NULL) { | 405 | entry)) == NULL) { |
288 | fido_log_debug("%s: IOHIDDeviceCreate", __func__); | 406 | fido_log_debug("%s: IOHIDDeviceCreate", __func__); |
289 | goto fail; | 407 | goto fail; |
290 | } | 408 | } |
291 | 409 | ||
292 | if (IOHIDDeviceOpen(dev->ref, | 410 | if (get_report_len(ctx->ref, 0, &ctx->report_in_len) < 0 || |
411 | get_report_len(ctx->ref, 1, &ctx->report_out_len) < 0) { | ||
412 | fido_log_debug("%s: get_report_len", __func__); | ||
413 | goto fail; | ||
414 | } | ||
415 | |||
416 | if (ctx->report_in_len > sizeof(ctx->report)) { | ||
417 | fido_log_debug("%s: report_in_len=%zu", __func__, | ||
418 | ctx->report_in_len); | ||
419 | goto fail; | ||
420 | } | ||
421 | |||
422 | if (IOHIDDeviceOpen(ctx->ref, | ||
293 | kIOHIDOptionsTypeSeizeDevice) != kIOReturnSuccess) { | 423 | kIOHIDOptionsTypeSeizeDevice) != kIOReturnSuccess) { |
294 | fido_log_debug("%s: IOHIDDeviceOpen", __func__); | 424 | fido_log_debug("%s: IOHIDDeviceOpen", __func__); |
295 | goto fail; | 425 | goto fail; |
296 | } | 426 | } |
297 | 427 | ||
298 | if ((r = snprintf(loop_id, sizeof(loop_id), "fido2-%p", | 428 | if ((r = snprintf(loop_id, sizeof(loop_id), "fido2-%p", |
299 | (void *)dev->ref)) < 0 || (size_t)r >= sizeof(loop_id)) { | 429 | (void *)ctx->ref)) < 0 || (size_t)r >= sizeof(loop_id)) { |
300 | fido_log_debug("%s: snprintf", __func__); | 430 | fido_log_debug("%s: snprintf", __func__); |
301 | goto fail; | 431 | goto fail; |
302 | } | 432 | } |
303 | 433 | ||
304 | if ((dev->loop_id = CFStringCreateWithCString(NULL, loop_id, | 434 | if ((ctx->loop_id = CFStringCreateWithCString(NULL, loop_id, |
305 | kCFStringEncodingASCII)) == NULL) { | 435 | kCFStringEncodingASCII)) == NULL) { |
306 | fido_log_debug("%s: CFStringCreateWithCString", __func__); | 436 | fido_log_debug("%s: CFStringCreateWithCString", __func__); |
307 | goto fail; | 437 | goto fail; |
308 | } | 438 | } |
309 | 439 | ||
440 | IOHIDDeviceRegisterInputReportCallback(ctx->ref, ctx->report, | ||
441 | (long)ctx->report_in_len, &report_callback, ctx); | ||
442 | IOHIDDeviceRegisterRemovalCallback(ctx->ref, &removal_callback, ctx); | ||
443 | IOHIDDeviceScheduleWithRunLoop(ctx->ref, CFRunLoopGetMain(), | ||
444 | ctx->loop_id); | ||
445 | |||
310 | ok = 0; | 446 | ok = 0; |
311 | fail: | 447 | fail: |
312 | if (entry != MACH_PORT_NULL) | 448 | if (entry != MACH_PORT_NULL) |
313 | IOObjectRelease(entry); | 449 | IOObjectRelease(entry); |
314 | 450 | ||
315 | if (ok < 0 && dev != NULL) { | 451 | if (ok < 0 && ctx != NULL) { |
316 | if (dev->ref != NULL) | 452 | if (ctx->ref != NULL) |
317 | CFRelease(dev->ref); | 453 | CFRelease(ctx->ref); |
318 | if (dev->loop_id != NULL) | 454 | if (ctx->loop_id != NULL) |
319 | CFRelease(dev->loop_id); | 455 | CFRelease(ctx->loop_id); |
320 | free(dev); | 456 | if (ctx->report_pipe[0] != -1) |
321 | dev = NULL; | 457 | close(ctx->report_pipe[0]); |
458 | if (ctx->report_pipe[1] != -1) | ||
459 | close(ctx->report_pipe[1]); | ||
460 | free(ctx); | ||
461 | ctx = NULL; | ||
322 | } | 462 | } |
323 | 463 | ||
324 | return (dev); | 464 | return (ctx); |
325 | } | 465 | } |
326 | 466 | ||
327 | void | 467 | void |
328 | fido_hid_close(void *handle) | 468 | fido_hid_close(void *handle) |
329 | { | 469 | { |
330 | struct dev *dev = handle; | 470 | struct hid_osx *ctx = handle; |
471 | |||
472 | IOHIDDeviceRegisterInputReportCallback(ctx->ref, ctx->report, | ||
473 | (long)ctx->report_in_len, NULL, ctx); | ||
474 | IOHIDDeviceRegisterRemovalCallback(ctx->ref, NULL, NULL); | ||
475 | IOHIDDeviceUnscheduleFromRunLoop(ctx->ref, CFRunLoopGetMain(), | ||
476 | ctx->loop_id); | ||
331 | 477 | ||
332 | if (IOHIDDeviceClose(dev->ref, | 478 | if (IOHIDDeviceClose(ctx->ref, |
333 | kIOHIDOptionsTypeSeizeDevice) != kIOReturnSuccess) | 479 | kIOHIDOptionsTypeSeizeDevice) != kIOReturnSuccess) |
334 | fido_log_debug("%s: IOHIDDeviceClose", __func__); | 480 | fido_log_debug("%s: IOHIDDeviceClose", __func__); |
335 | 481 | ||
336 | CFRelease(dev->ref); | 482 | CFRelease(ctx->ref); |
337 | CFRelease(dev->loop_id); | 483 | CFRelease(ctx->loop_id); |
338 | |||
339 | free(dev); | ||
340 | } | ||
341 | 484 | ||
342 | static void | 485 | explicit_bzero(ctx->report, sizeof(ctx->report)); |
343 | read_callback(void *context, IOReturn result, void *dev, IOHIDReportType type, | 486 | close(ctx->report_pipe[0]); |
344 | uint32_t report_id, uint8_t *report, CFIndex report_len) | 487 | close(ctx->report_pipe[1]); |
345 | { | ||
346 | (void)context; | ||
347 | (void)dev; | ||
348 | (void)report; | ||
349 | 488 | ||
350 | if (result != kIOReturnSuccess || type != kIOHIDReportTypeInput || | 489 | free(ctx); |
351 | report_id != 0 || report_len != REPORT_LEN - 1) { | ||
352 | fido_log_debug("%s: io error", __func__); | ||
353 | } | ||
354 | } | ||
355 | |||
356 | static void | ||
357 | removal_callback(void *context, IOReturn result, void *sender) | ||
358 | { | ||
359 | (void)context; | ||
360 | (void)result; | ||
361 | (void)sender; | ||
362 | |||
363 | CFRunLoopStop(CFRunLoopGetCurrent()); | ||
364 | } | 490 | } |
365 | 491 | ||
366 | int | 492 | int |
367 | fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms) | 493 | fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms) |
368 | { | 494 | { |
369 | struct dev *dev = handle; | 495 | struct hid_osx *ctx = handle; |
370 | CFRunLoopRunResult r; | 496 | ssize_t r; |
371 | 497 | ||
372 | (void)ms; /* XXX */ | 498 | explicit_bzero(buf, len); |
499 | explicit_bzero(ctx->report, sizeof(ctx->report)); | ||
373 | 500 | ||
374 | if (len != REPORT_LEN - 1) { | 501 | if (len != ctx->report_in_len || len > sizeof(ctx->report)) { |
375 | fido_log_debug("%s: invalid len", __func__); | 502 | fido_log_debug("%s: len %zu", __func__, len); |
376 | return (-1); | 503 | return (-1); |
377 | } | 504 | } |
378 | 505 | ||
379 | explicit_bzero(buf, len); | 506 | if (ms == -1) |
380 | 507 | ms = 5000; /* wait 5 seconds by default */ | |
381 | IOHIDDeviceRegisterInputReportCallback(dev->ref, buf, len, | ||
382 | &read_callback, NULL); | ||
383 | IOHIDDeviceRegisterRemovalCallback(dev->ref, &removal_callback, dev); | ||
384 | IOHIDDeviceScheduleWithRunLoop(dev->ref, CFRunLoopGetCurrent(), | ||
385 | dev->loop_id); | ||
386 | 508 | ||
387 | r = CFRunLoopRunInMode(dev->loop_id, 0.3, true); | 509 | if (CFRunLoopGetCurrent() != CFRunLoopGetMain()) |
510 | fido_log_debug("%s: CFRunLoopGetCurrent != CFRunLoopGetMain", | ||
511 | __func__); | ||
388 | 512 | ||
389 | IOHIDDeviceRegisterInputReportCallback(dev->ref, buf, len, NULL, NULL); | 513 | CFRunLoopRunInMode(ctx->loop_id, (double)ms/1000.0, true); |
390 | IOHIDDeviceRegisterRemovalCallback(dev->ref, NULL, NULL); | ||
391 | IOHIDDeviceUnscheduleFromRunLoop(dev->ref, CFRunLoopGetCurrent(), | ||
392 | dev->loop_id); | ||
393 | 514 | ||
394 | if (r != kCFRunLoopRunHandledSource) { | 515 | if ((r = read(ctx->report_pipe[0], buf, len)) < 0 || (size_t)r != len) { |
395 | fido_log_debug("%s: CFRunLoopRunInMode=%d", __func__, (int)r); | 516 | fido_log_debug("%s: read", __func__); |
396 | return (-1); | 517 | return (-1); |
397 | } | 518 | } |
398 | 519 | ||
399 | return (REPORT_LEN - 1); | 520 | return ((int)len); |
400 | } | 521 | } |
401 | 522 | ||
402 | int | 523 | int |
403 | fido_hid_write(void *handle, const unsigned char *buf, size_t len) | 524 | fido_hid_write(void *handle, const unsigned char *buf, size_t len) |
404 | { | 525 | { |
405 | struct dev *dev = handle; | 526 | struct hid_osx *ctx = handle; |
406 | 527 | ||
407 | if (len != REPORT_LEN) { | 528 | if (len != ctx->report_out_len + 1 || len > LONG_MAX) { |
408 | fido_log_debug("%s: invalid len", __func__); | 529 | fido_log_debug("%s: len %zu", __func__, len); |
409 | return (-1); | 530 | return (-1); |
410 | } | 531 | } |
411 | 532 | ||
412 | if (IOHIDDeviceSetReport(dev->ref, kIOHIDReportTypeOutput, 0, buf + 1, | 533 | if (IOHIDDeviceSetReport(ctx->ref, kIOHIDReportTypeOutput, 0, buf + 1, |
413 | len - 1) != kIOReturnSuccess) { | 534 | (long)(len - 1)) != kIOReturnSuccess) { |
414 | fido_log_debug("%s: IOHIDDeviceSetReport", __func__); | 535 | fido_log_debug("%s: IOHIDDeviceSetReport", __func__); |
415 | return (-1); | 536 | return (-1); |
416 | } | 537 | } |
417 | 538 | ||
418 | return (REPORT_LEN); | 539 | return ((int)len); |
540 | } | ||
541 | |||
542 | size_t | ||
543 | fido_hid_report_in_len(void *handle) | ||
544 | { | ||
545 | struct hid_osx *ctx = handle; | ||
546 | |||
547 | return (ctx->report_in_len); | ||
548 | } | ||
549 | |||
550 | size_t | ||
551 | fido_hid_report_out_len(void *handle) | ||
552 | { | ||
553 | struct hid_osx *ctx = handle; | ||
554 | |||
555 | return (ctx->report_out_len); | ||
419 | } | 556 | } |
diff --git a/src/hid_win.c b/src/hid_win.c index f970589..018b4d9 100644 --- a/src/hid_win.c +++ b/src/hid_win.c | |||
@@ -14,19 +14,39 @@ | |||
14 | #include <windows.h> | 14 | #include <windows.h> |
15 | #include <setupapi.h> | 15 | #include <setupapi.h> |
16 | #include <initguid.h> | 16 | #include <initguid.h> |
17 | #include <devpkey.h> | ||
18 | #include <devpropdef.h> | ||
17 | #include <hidclass.h> | 19 | #include <hidclass.h> |
18 | #include <hidsdi.h> | 20 | #include <hidsdi.h> |
19 | 21 | ||
20 | #include "fido.h" | 22 | #include "fido.h" |
21 | 23 | ||
22 | #define REPORT_LEN 65 | 24 | #if defined(__MINGW32__) && __MINGW64_VERSION_MAJOR < 6 |
25 | WINSETUPAPI WINBOOL WINAPI SetupDiGetDevicePropertyW(HDEVINFO, | ||
26 | PSP_DEVINFO_DATA, const DEVPROPKEY *, DEVPROPTYPE *, PBYTE, | ||
27 | DWORD, PDWORD, DWORD); | ||
28 | #endif | ||
29 | |||
30 | #if defined(__MINGW32__) | ||
31 | DEFINE_DEVPROPKEY(DEVPKEY_Device_Parent, 0x4340a6c5, 0x93fa, 0x4706, 0x97, | ||
32 | 0x2c, 0x7b, 0x64, 0x80, 0x08, 0xa5, 0xa7, 8); | ||
33 | #endif | ||
34 | |||
35 | struct hid_win { | ||
36 | HANDLE dev; | ||
37 | OVERLAPPED overlap; | ||
38 | int report_pending; | ||
39 | size_t report_in_len; | ||
40 | size_t report_out_len; | ||
41 | unsigned char report[1 + CTAP_MAX_REPORT_LEN]; | ||
42 | }; | ||
23 | 43 | ||
24 | static bool | 44 | static bool |
25 | is_fido(HANDLE dev) | 45 | is_fido(HANDLE dev) |
26 | { | 46 | { |
27 | PHIDP_PREPARSED_DATA data = NULL; | 47 | PHIDP_PREPARSED_DATA data = NULL; |
28 | HIDP_CAPS caps; | 48 | HIDP_CAPS caps; |
29 | uint16_t usage_page = 0; | 49 | int fido = 0; |
30 | 50 | ||
31 | if (HidD_GetPreparsedData(dev, &data) == false) { | 51 | if (HidD_GetPreparsedData(dev, &data) == false) { |
32 | fido_log_debug("%s: HidD_GetPreparsedData", __func__); | 52 | fido_log_debug("%s: HidD_GetPreparsedData", __func__); |
@@ -38,18 +58,48 @@ is_fido(HANDLE dev) | |||
38 | goto fail; | 58 | goto fail; |
39 | } | 59 | } |
40 | 60 | ||
41 | if (caps.OutputReportByteLength != REPORT_LEN || | 61 | fido = (uint16_t)caps.UsagePage == 0xf1d0; |
42 | caps.InputReportByteLength != REPORT_LEN) { | 62 | fail: |
43 | fido_log_debug("%s: unsupported report len", __func__); | 63 | if (data != NULL) |
64 | HidD_FreePreparsedData(data); | ||
65 | |||
66 | return (fido); | ||
67 | } | ||
68 | |||
69 | static int | ||
70 | get_report_len(HANDLE dev, int dir, size_t *report_len) | ||
71 | { | ||
72 | PHIDP_PREPARSED_DATA data = NULL; | ||
73 | HIDP_CAPS caps; | ||
74 | USHORT v; | ||
75 | int ok = -1; | ||
76 | |||
77 | if (HidD_GetPreparsedData(dev, &data) == false) { | ||
78 | fido_log_debug("%s: HidD_GetPreparsedData/%d", __func__, dir); | ||
44 | goto fail; | 79 | goto fail; |
45 | } | 80 | } |
46 | 81 | ||
47 | usage_page = caps.UsagePage; | 82 | if (HidP_GetCaps(data, &caps) != HIDP_STATUS_SUCCESS) { |
83 | fido_log_debug("%s: HidP_GetCaps/%d", __func__, dir); | ||
84 | goto fail; | ||
85 | } | ||
86 | |||
87 | if (dir == 0) | ||
88 | v = caps.InputReportByteLength; | ||
89 | else | ||
90 | v = caps.OutputReportByteLength; | ||
91 | |||
92 | if ((*report_len = (size_t)v) == 0) { | ||
93 | fido_log_debug("%s: report_len == 0", __func__); | ||
94 | goto fail; | ||
95 | } | ||
96 | |||
97 | ok = 0; | ||
48 | fail: | 98 | fail: |
49 | if (data != NULL) | 99 | if (data != NULL) |
50 | HidD_FreePreparsedData(data); | 100 | HidD_FreePreparsedData(data); |
51 | 101 | ||
52 | return (usage_page == 0xf1d0); | 102 | return (ok); |
53 | } | 103 | } |
54 | 104 | ||
55 | static int | 105 | static int |
@@ -59,13 +109,14 @@ get_int(HANDLE dev, int16_t *vendor_id, int16_t *product_id) | |||
59 | 109 | ||
60 | attr.Size = sizeof(attr); | 110 | attr.Size = sizeof(attr); |
61 | 111 | ||
62 | if (HidD_GetAttributes(dev, &attr) == false) { | 112 | if (HidD_GetAttributes(dev, &attr) == false || |
113 | attr.VendorID > INT16_MAX || attr.ProductID > INT16_MAX) { | ||
63 | fido_log_debug("%s: HidD_GetAttributes", __func__); | 114 | fido_log_debug("%s: HidD_GetAttributes", __func__); |
64 | return (-1); | 115 | return (-1); |
65 | } | 116 | } |
66 | 117 | ||
67 | *vendor_id = attr.VendorID; | 118 | *vendor_id = (int16_t)attr.VendorID; |
68 | *product_id = attr.ProductID; | 119 | *product_id = (int16_t)attr.ProductID; |
69 | 120 | ||
70 | return (0); | 121 | return (0); |
71 | } | 122 | } |
@@ -91,7 +142,7 @@ get_str(HANDLE dev, char **manufacturer, char **product) | |||
91 | goto fail; | 142 | goto fail; |
92 | } | 143 | } |
93 | 144 | ||
94 | if ((*manufacturer = malloc(utf8_len)) == NULL) { | 145 | if ((*manufacturer = malloc((size_t)utf8_len)) == NULL) { |
95 | fido_log_debug("%s: malloc", __func__); | 146 | fido_log_debug("%s: malloc", __func__); |
96 | goto fail; | 147 | goto fail; |
97 | } | 148 | } |
@@ -113,7 +164,7 @@ get_str(HANDLE dev, char **manufacturer, char **product) | |||
113 | goto fail; | 164 | goto fail; |
114 | } | 165 | } |
115 | 166 | ||
116 | if ((*product = malloc(utf8_len)) == NULL) { | 167 | if ((*product = malloc((size_t)utf8_len)) == NULL) { |
117 | fido_log_debug("%s: malloc", __func__); | 168 | fido_log_debug("%s: malloc", __func__); |
118 | goto fail; | 169 | goto fail; |
119 | } | 170 | } |
@@ -136,25 +187,138 @@ fail: | |||
136 | return (ok); | 187 | return (ok); |
137 | } | 188 | } |
138 | 189 | ||
190 | static char * | ||
191 | get_path(HDEVINFO devinfo, SP_DEVICE_INTERFACE_DATA *ifdata) | ||
192 | { | ||
193 | SP_DEVICE_INTERFACE_DETAIL_DATA_A *ifdetail = NULL; | ||
194 | char *path = NULL; | ||
195 | DWORD len = 0; | ||
196 | |||
197 | /* | ||
198 | * "Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail | ||
199 | * with a NULL DeviceInterfaceDetailData pointer, a | ||
200 | * DeviceInterfaceDetailDataSize of zero, and a valid RequiredSize | ||
201 | * variable. In response to such a call, this function returns the | ||
202 | * required buffer size at RequiredSize and fails with GetLastError | ||
203 | * returning ERROR_INSUFFICIENT_BUFFER." | ||
204 | */ | ||
205 | if (SetupDiGetDeviceInterfaceDetailA(devinfo, ifdata, NULL, 0, &len, | ||
206 | NULL) != false || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { | ||
207 | fido_log_debug("%s: SetupDiGetDeviceInterfaceDetailA 1", | ||
208 | __func__); | ||
209 | goto fail; | ||
210 | } | ||
211 | |||
212 | if ((ifdetail = malloc(len)) == NULL) { | ||
213 | fido_log_debug("%s: malloc", __func__); | ||
214 | goto fail; | ||
215 | } | ||
216 | |||
217 | ifdetail->cbSize = sizeof(*ifdetail); | ||
218 | |||
219 | if (SetupDiGetDeviceInterfaceDetailA(devinfo, ifdata, ifdetail, len, | ||
220 | NULL, NULL) == false) { | ||
221 | fido_log_debug("%s: SetupDiGetDeviceInterfaceDetailA 2", | ||
222 | __func__); | ||
223 | goto fail; | ||
224 | } | ||
225 | |||
226 | if ((path = strdup(ifdetail->DevicePath)) == NULL) { | ||
227 | fido_log_debug("%s: strdup", __func__); | ||
228 | goto fail; | ||
229 | } | ||
230 | |||
231 | fail: | ||
232 | free(ifdetail); | ||
233 | |||
234 | return (path); | ||
235 | } | ||
236 | |||
237 | #ifndef FIDO_HID_ANY | ||
238 | static bool | ||
239 | hid_ok(HDEVINFO devinfo, DWORD idx) | ||
240 | { | ||
241 | SP_DEVINFO_DATA devinfo_data; | ||
242 | wchar_t *parent = NULL; | ||
243 | DWORD parent_type = DEVPROP_TYPE_STRING; | ||
244 | DWORD len = 0; | ||
245 | bool ok = false; | ||
246 | |||
247 | memset(&devinfo_data, 0, sizeof(devinfo_data)); | ||
248 | devinfo_data.cbSize = sizeof(devinfo_data); | ||
249 | |||
250 | if (SetupDiEnumDeviceInfo(devinfo, idx, &devinfo_data) == false) { | ||
251 | fido_log_debug("%s: SetupDiEnumDeviceInfo", __func__); | ||
252 | goto fail; | ||
253 | } | ||
254 | |||
255 | if (SetupDiGetDevicePropertyW(devinfo, &devinfo_data, | ||
256 | &DEVPKEY_Device_Parent, &parent_type, NULL, 0, &len, 0) != false || | ||
257 | GetLastError() != ERROR_INSUFFICIENT_BUFFER) { | ||
258 | fido_log_debug("%s: SetupDiGetDevicePropertyW 1", __func__); | ||
259 | goto fail; | ||
260 | } | ||
261 | |||
262 | if ((parent = malloc(len)) == NULL) { | ||
263 | fido_log_debug("%s: malloc", __func__); | ||
264 | goto fail; | ||
265 | } | ||
266 | |||
267 | if (SetupDiGetDevicePropertyW(devinfo, &devinfo_data, | ||
268 | &DEVPKEY_Device_Parent, &parent_type, (PBYTE)parent, len, NULL, | ||
269 | 0) == false) { | ||
270 | fido_log_debug("%s: SetupDiGetDevicePropertyW 2", __func__); | ||
271 | goto fail; | ||
272 | } | ||
273 | |||
274 | ok = wcsncmp(parent, L"USB\\", 4) == 0; | ||
275 | fail: | ||
276 | free(parent); | ||
277 | |||
278 | return (ok); | ||
279 | } | ||
280 | #endif | ||
281 | |||
139 | static int | 282 | static int |
140 | copy_info(fido_dev_info_t *di, const char *path) | 283 | copy_info(fido_dev_info_t *di, HDEVINFO devinfo, DWORD idx, |
284 | SP_DEVICE_INTERFACE_DATA *ifdata) | ||
141 | { | 285 | { |
142 | HANDLE dev = INVALID_HANDLE_VALUE; | 286 | HANDLE dev = INVALID_HANDLE_VALUE; |
143 | int ok = -1; | 287 | int ok = -1; |
144 | 288 | ||
145 | memset(di, 0, sizeof(*di)); | 289 | memset(di, 0, sizeof(*di)); |
146 | 290 | ||
147 | dev = CreateFileA(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | 291 | if ((di->path = get_path(devinfo, ifdata)) == NULL) { |
148 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | 292 | fido_log_debug("%s: get_path", __func__); |
149 | if (dev == INVALID_HANDLE_VALUE || is_fido(dev) == 0) | ||
150 | goto fail; | 293 | goto fail; |
294 | } | ||
151 | 295 | ||
152 | if (get_int(dev, &di->vendor_id, &di->product_id) < 0 || | 296 | fido_log_debug("%s: path=%s", __func__, di->path); |
153 | get_str(dev, &di->manufacturer, &di->product) < 0) | 297 | |
298 | #ifndef FIDO_HID_ANY | ||
299 | if (hid_ok(devinfo, idx) == false) { | ||
300 | fido_log_debug("%s: hid_ok", __func__); | ||
154 | goto fail; | 301 | goto fail; |
302 | } | ||
303 | #endif | ||
155 | 304 | ||
156 | if ((di->path = strdup(path)) == NULL) | 305 | dev = CreateFileA(di->path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, |
306 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | ||
307 | if (dev == INVALID_HANDLE_VALUE) { | ||
308 | fido_log_debug("%s: CreateFileA", __func__); | ||
157 | goto fail; | 309 | goto fail; |
310 | } | ||
311 | |||
312 | if (is_fido(dev) == false) { | ||
313 | fido_log_debug("%s: is_fido", __func__); | ||
314 | goto fail; | ||
315 | } | ||
316 | |||
317 | if (get_int(dev, &di->vendor_id, &di->product_id) < 0 || | ||
318 | get_str(dev, &di->manufacturer, &di->product) < 0) { | ||
319 | fido_log_debug("%s: get_int/get_str", __func__); | ||
320 | goto fail; | ||
321 | } | ||
158 | 322 | ||
159 | ok = 0; | 323 | ok = 0; |
160 | fail: | 324 | fail: |
@@ -174,66 +338,30 @@ fail: | |||
174 | int | 338 | int |
175 | fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | 339 | fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) |
176 | { | 340 | { |
177 | GUID hid_guid = GUID_DEVINTERFACE_HID; | 341 | GUID hid_guid = GUID_DEVINTERFACE_HID; |
178 | HDEVINFO devinfo = INVALID_HANDLE_VALUE; | 342 | HDEVINFO devinfo = INVALID_HANDLE_VALUE; |
179 | SP_DEVICE_INTERFACE_DATA ifdata; | 343 | SP_DEVICE_INTERFACE_DATA ifdata; |
180 | SP_DEVICE_INTERFACE_DETAIL_DATA_A *ifdetail = NULL; | 344 | DWORD idx; |
181 | DWORD len = 0; | 345 | int r = FIDO_ERR_INTERNAL; |
182 | DWORD idx = 0; | ||
183 | int r = FIDO_ERR_INTERNAL; | ||
184 | 346 | ||
185 | *olen = 0; | 347 | *olen = 0; |
186 | 348 | ||
187 | if (ilen == 0) | 349 | if (ilen == 0) |
188 | return (FIDO_OK); /* nothing to do */ | 350 | return (FIDO_OK); /* nothing to do */ |
189 | |||
190 | if (devlist == NULL) | 351 | if (devlist == NULL) |
191 | return (FIDO_ERR_INVALID_ARGUMENT); | 352 | return (FIDO_ERR_INVALID_ARGUMENT); |
192 | 353 | ||
193 | devinfo = SetupDiGetClassDevsA(&hid_guid, NULL, NULL, | 354 | if ((devinfo = SetupDiGetClassDevsA(&hid_guid, NULL, NULL, |
194 | DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); | 355 | DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)) == INVALID_HANDLE_VALUE) { |
195 | if (devinfo == INVALID_HANDLE_VALUE) { | ||
196 | fido_log_debug("%s: SetupDiGetClassDevsA", __func__); | 356 | fido_log_debug("%s: SetupDiGetClassDevsA", __func__); |
197 | goto fail; | 357 | goto fail; |
198 | } | 358 | } |
199 | 359 | ||
200 | ifdata.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); | 360 | ifdata.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); |
201 | 361 | ||
202 | while (SetupDiEnumDeviceInterfaces(devinfo, NULL, &hid_guid, idx++, | 362 | for (idx = 0; SetupDiEnumDeviceInterfaces(devinfo, NULL, &hid_guid, |
203 | &ifdata) == true) { | 363 | idx, &ifdata) == true; idx++) { |
204 | /* | 364 | if (copy_info(&devlist[*olen], devinfo, idx, &ifdata) == 0) { |
205 | * "Get the required buffer size. Call | ||
206 | * SetupDiGetDeviceInterfaceDetail with a NULL | ||
207 | * DeviceInterfaceDetailData pointer, a | ||
208 | * DeviceInterfaceDetailDataSize of zero, and a valid | ||
209 | * RequiredSize variable. In response to such a call, this | ||
210 | * function returns the required buffer size at RequiredSize | ||
211 | * and fails with GetLastError returning | ||
212 | * ERROR_INSUFFICIENT_BUFFER." | ||
213 | */ | ||
214 | if (SetupDiGetDeviceInterfaceDetailA(devinfo, &ifdata, NULL, 0, | ||
215 | &len, NULL) != false || | ||
216 | GetLastError() != ERROR_INSUFFICIENT_BUFFER) { | ||
217 | fido_log_debug("%s: SetupDiGetDeviceInterfaceDetailA 1", | ||
218 | __func__); | ||
219 | goto fail; | ||
220 | } | ||
221 | |||
222 | if ((ifdetail = malloc(len)) == NULL) { | ||
223 | fido_log_debug("%s: malloc", __func__); | ||
224 | goto fail; | ||
225 | } | ||
226 | |||
227 | ifdetail->cbSize = sizeof(*ifdetail); | ||
228 | |||
229 | if (SetupDiGetDeviceInterfaceDetailA(devinfo, &ifdata, ifdetail, | ||
230 | len, NULL, NULL) == false) { | ||
231 | fido_log_debug("%s: SetupDiGetDeviceInterfaceDetailA 2", | ||
232 | __func__); | ||
233 | goto fail; | ||
234 | } | ||
235 | |||
236 | if (copy_info(&devlist[*olen], ifdetail->DevicePath) == 0) { | ||
237 | devlist[*olen].io = (fido_dev_io_t) { | 365 | devlist[*olen].io = (fido_dev_io_t) { |
238 | fido_hid_open, | 366 | fido_hid_open, |
239 | fido_hid_close, | 367 | fido_hid_close, |
@@ -243,9 +371,6 @@ fido_hid_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) | |||
243 | if (++(*olen) == ilen) | 371 | if (++(*olen) == ilen) |
244 | break; | 372 | break; |
245 | } | 373 | } |
246 | |||
247 | free(ifdetail); | ||
248 | ifdetail = NULL; | ||
249 | } | 374 | } |
250 | 375 | ||
251 | r = FIDO_OK; | 376 | r = FIDO_OK; |
@@ -253,78 +378,153 @@ fail: | |||
253 | if (devinfo != INVALID_HANDLE_VALUE) | 378 | if (devinfo != INVALID_HANDLE_VALUE) |
254 | SetupDiDestroyDeviceInfoList(devinfo); | 379 | SetupDiDestroyDeviceInfoList(devinfo); |
255 | 380 | ||
256 | free(ifdetail); | ||
257 | |||
258 | return (r); | 381 | return (r); |
259 | } | 382 | } |
260 | 383 | ||
261 | void * | 384 | void * |
262 | fido_hid_open(const char *path) | 385 | fido_hid_open(const char *path) |
263 | { | 386 | { |
264 | HANDLE dev; | 387 | struct hid_win *ctx; |
388 | |||
389 | if ((ctx = calloc(1, sizeof(*ctx))) == NULL) | ||
390 | return (NULL); | ||
265 | 391 | ||
266 | dev = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, | 392 | ctx->dev = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, |
267 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, | 393 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, |
268 | FILE_ATTRIBUTE_NORMAL, NULL); | 394 | FILE_FLAG_OVERLAPPED, NULL); |
395 | |||
396 | if (ctx->dev == INVALID_HANDLE_VALUE) { | ||
397 | free(ctx); | ||
398 | return (NULL); | ||
399 | } | ||
269 | 400 | ||
270 | if (dev == INVALID_HANDLE_VALUE) | 401 | if ((ctx->overlap.hEvent = CreateEventA(NULL, FALSE, FALSE, |
402 | NULL)) == NULL) { | ||
403 | fido_log_debug("%s: CreateEventA", __func__); | ||
404 | fido_hid_close(ctx); | ||
271 | return (NULL); | 405 | return (NULL); |
406 | } | ||
272 | 407 | ||
273 | return (dev); | 408 | if (get_report_len(ctx->dev, 0, &ctx->report_in_len) < 0 || |
409 | get_report_len(ctx->dev, 1, &ctx->report_out_len) < 0) { | ||
410 | fido_log_debug("%s: get_report_len", __func__); | ||
411 | fido_hid_close(ctx); | ||
412 | return (NULL); | ||
413 | } | ||
414 | |||
415 | return (ctx); | ||
274 | } | 416 | } |
275 | 417 | ||
276 | void | 418 | void |
277 | fido_hid_close(void *handle) | 419 | fido_hid_close(void *handle) |
278 | { | 420 | { |
279 | CloseHandle(handle); | 421 | struct hid_win *ctx = handle; |
422 | |||
423 | if (ctx->overlap.hEvent != NULL) { | ||
424 | if (ctx->report_pending) { | ||
425 | fido_log_debug("%s: report_pending", __func__); | ||
426 | CancelIo(ctx->dev); | ||
427 | } | ||
428 | CloseHandle(ctx->overlap.hEvent); | ||
429 | } | ||
430 | |||
431 | explicit_bzero(ctx->report, sizeof(ctx->report)); | ||
432 | CloseHandle(ctx->dev); | ||
433 | free(ctx); | ||
280 | } | 434 | } |
281 | 435 | ||
282 | int | 436 | int |
283 | fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms) | 437 | fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms) |
284 | { | 438 | { |
285 | DWORD n; | 439 | struct hid_win *ctx = handle; |
286 | int r = -1; | 440 | DWORD n; |
287 | uint8_t report[REPORT_LEN]; | ||
288 | 441 | ||
289 | (void)ms; /* XXX */ | 442 | if (len != ctx->report_in_len - 1 || len > sizeof(ctx->report) - 1) { |
443 | fido_log_debug("%s: len %zu", __func__, len); | ||
444 | return (-1); | ||
445 | } | ||
446 | |||
447 | if (ctx->report_pending == 0) { | ||
448 | memset(&ctx->report, 0, sizeof(ctx->report)); | ||
449 | ResetEvent(ctx->overlap.hEvent); | ||
450 | if (ReadFile(ctx->dev, ctx->report, (DWORD)(len + 1), &n, | ||
451 | &ctx->overlap) == 0 && GetLastError() != ERROR_IO_PENDING) { | ||
452 | CancelIo(ctx->dev); | ||
453 | fido_log_debug("%s: ReadFile", __func__); | ||
454 | return (-1); | ||
455 | } | ||
456 | ctx->report_pending = 1; | ||
457 | } | ||
290 | 458 | ||
291 | memset(report, 0, sizeof(report)); | 459 | if (ms > -1 && WaitForSingleObject(ctx->overlap.hEvent, |
460 | (DWORD)ms) != WAIT_OBJECT_0) | ||
461 | return (0); | ||
292 | 462 | ||
293 | if (len != sizeof(report) - 1) { | 463 | ctx->report_pending = 0; |
294 | fido_log_debug("%s: invalid len", __func__); | 464 | |
465 | if (GetOverlappedResult(ctx->dev, &ctx->overlap, &n, TRUE) == 0) { | ||
466 | fido_log_debug("%s: GetOverlappedResult", __func__); | ||
295 | return (-1); | 467 | return (-1); |
296 | } | 468 | } |
297 | 469 | ||
298 | if (ReadFile(handle, report, sizeof(report), &n, NULL) == false || | 470 | if (n != len + 1) { |
299 | n != sizeof(report)) { | 471 | fido_log_debug("%s: expected %zu, got %zu", __func__, |
300 | fido_log_debug("%s: ReadFile", __func__); | 472 | len + 1, (size_t)n); |
301 | goto fail; | 473 | return (-1); |
302 | } | 474 | } |
303 | 475 | ||
304 | r = sizeof(report) - 1; | 476 | memcpy(buf, ctx->report + 1, len); |
305 | memcpy(buf, report + 1, len); | 477 | explicit_bzero(ctx->report, sizeof(ctx->report)); |
306 | |||
307 | fail: | ||
308 | explicit_bzero(report, sizeof(report)); | ||
309 | 478 | ||
310 | return (r); | 479 | return ((int)len); |
311 | } | 480 | } |
312 | 481 | ||
313 | int | 482 | int |
314 | fido_hid_write(void *handle, const unsigned char *buf, size_t len) | 483 | fido_hid_write(void *handle, const unsigned char *buf, size_t len) |
315 | { | 484 | { |
316 | DWORD n; | 485 | struct hid_win *ctx = handle; |
486 | OVERLAPPED overlap; | ||
487 | DWORD n; | ||
488 | |||
489 | memset(&overlap, 0, sizeof(overlap)); | ||
317 | 490 | ||
318 | if (len != REPORT_LEN) { | 491 | if (len != ctx->report_out_len) { |
319 | fido_log_debug("%s: invalid len", __func__); | 492 | fido_log_debug("%s: len %zu", __func__, len); |
320 | return (-1); | 493 | return (-1); |
321 | } | 494 | } |
322 | 495 | ||
323 | if (WriteFile(handle, buf, (DWORD)len, &n, NULL) == false || | 496 | if (WriteFile(ctx->dev, buf, (DWORD)len, NULL, &overlap) == 0 && |
324 | n != REPORT_LEN) { | 497 | GetLastError() != ERROR_IO_PENDING) { |
325 | fido_log_debug("%s: WriteFile", __func__); | 498 | fido_log_debug("%s: WriteFile", __func__); |
326 | return (-1); | 499 | return (-1); |
327 | } | 500 | } |
328 | 501 | ||
329 | return (REPORT_LEN); | 502 | if (GetOverlappedResult(ctx->dev, &overlap, &n, TRUE) == 0) { |
503 | fido_log_debug("%s: GetOverlappedResult", __func__); | ||
504 | return (-1); | ||
505 | } | ||
506 | |||
507 | if (n != len) { | ||
508 | fido_log_debug("%s: expected %zu, got %zu", __func__, len, | ||
509 | (size_t)n); | ||
510 | return (-1); | ||
511 | } | ||
512 | |||
513 | return ((int)len); | ||
514 | } | ||
515 | |||
516 | size_t | ||
517 | fido_hid_report_in_len(void *handle) | ||
518 | { | ||
519 | struct hid_win *ctx = handle; | ||
520 | |||
521 | return (ctx->report_in_len - 1); | ||
522 | } | ||
523 | |||
524 | size_t | ||
525 | fido_hid_report_out_len(void *handle) | ||
526 | { | ||
527 | struct hid_win *ctx = handle; | ||
528 | |||
529 | return (ctx->report_out_len - 1); | ||
330 | } | 530 | } |
@@ -217,6 +217,10 @@ parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg) | |||
217 | return (cbor_decode_uint64(val, &ci->maxmsgsiz)); | 217 | return (cbor_decode_uint64(val, &ci->maxmsgsiz)); |
218 | case 6: /* pinProtocols */ | 218 | case 6: /* pinProtocols */ |
219 | return (decode_protocols(val, &ci->protocols)); | 219 | return (decode_protocols(val, &ci->protocols)); |
220 | case 7: /* maxCredentialCountInList */ | ||
221 | return (cbor_decode_uint64(val, &ci->maxcredcntlst)); | ||
222 | case 8: /* maxCredentialIdLength */ | ||
223 | return (cbor_decode_uint64(val, &ci->maxcredidlen)); | ||
220 | case 14: /* fwVersion */ | 224 | case 14: /* fwVersion */ |
221 | return (cbor_decode_uint64(val, &ci->fwversion)); | 225 | return (cbor_decode_uint64(val, &ci->fwversion)); |
222 | default: /* ignore */ | 226 | default: /* ignore */ |
@@ -399,6 +403,18 @@ fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *ci) | |||
399 | } | 403 | } |
400 | 404 | ||
401 | uint64_t | 405 | uint64_t |
406 | fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *ci) | ||
407 | { | ||
408 | return (ci->maxcredcntlst); | ||
409 | } | ||
410 | |||
411 | uint64_t | ||
412 | fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci) | ||
413 | { | ||
414 | return (ci->maxcredidlen); | ||
415 | } | ||
416 | |||
417 | uint64_t | ||
402 | fido_cbor_info_fwversion(const fido_cbor_info_t *ci) | 418 | fido_cbor_info_fwversion(const fido_cbor_info_t *ci) |
403 | { | 419 | { |
404 | return (ci->fwversion); | 420 | return (ci->fwversion); |
@@ -20,11 +20,11 @@ struct frame { | |||
20 | uint8_t cmd; | 20 | uint8_t cmd; |
21 | uint8_t bcnth; | 21 | uint8_t bcnth; |
22 | uint8_t bcntl; | 22 | uint8_t bcntl; |
23 | uint8_t data[CTAP_RPT_SIZE - 7]; | 23 | uint8_t data[CTAP_MAX_REPORT_LEN - CTAP_INIT_HEADER_LEN]; |
24 | } init; | 24 | } init; |
25 | struct { | 25 | struct { |
26 | uint8_t seq; | 26 | uint8_t seq; |
27 | uint8_t data[CTAP_RPT_SIZE - 5]; | 27 | uint8_t data[CTAP_MAX_REPORT_LEN - CTAP_CONT_HEADER_LEN]; |
28 | } cont; | 28 | } cont; |
29 | } body; | 29 | } body; |
30 | }) | 30 | }) |
@@ -38,6 +38,7 @@ tx_empty(fido_dev_t *d, uint8_t cmd) | |||
38 | { | 38 | { |
39 | struct frame *fp; | 39 | struct frame *fp; |
40 | unsigned char pkt[sizeof(*fp) + 1]; | 40 | unsigned char pkt[sizeof(*fp) + 1]; |
41 | const size_t len = d->tx_len + 1; | ||
41 | int n; | 42 | int n; |
42 | 43 | ||
43 | memset(&pkt, 0, sizeof(pkt)); | 44 | memset(&pkt, 0, sizeof(pkt)); |
@@ -45,8 +46,8 @@ tx_empty(fido_dev_t *d, uint8_t cmd) | |||
45 | fp->cid = d->cid; | 46 | fp->cid = d->cid; |
46 | fp->body.init.cmd = CTAP_FRAME_INIT | cmd; | 47 | fp->body.init.cmd = CTAP_FRAME_INIT | cmd; |
47 | 48 | ||
48 | n = d->io.write(d->io_handle, pkt, sizeof(pkt)); | 49 | if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt, |
49 | if (n < 0 || (size_t)n != sizeof(pkt)) | 50 | len)) < 0 || (size_t)n != len) |
50 | return (-1); | 51 | return (-1); |
51 | 52 | ||
52 | return (0); | 53 | return (0); |
@@ -57,19 +58,23 @@ tx_preamble(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) | |||
57 | { | 58 | { |
58 | struct frame *fp; | 59 | struct frame *fp; |
59 | unsigned char pkt[sizeof(*fp) + 1]; | 60 | unsigned char pkt[sizeof(*fp) + 1]; |
61 | const size_t len = d->tx_len + 1; | ||
60 | int n; | 62 | int n; |
61 | 63 | ||
64 | if (d->tx_len - CTAP_INIT_HEADER_LEN > sizeof(fp->body.init.data)) | ||
65 | return (0); | ||
66 | |||
62 | memset(&pkt, 0, sizeof(pkt)); | 67 | memset(&pkt, 0, sizeof(pkt)); |
63 | fp = (struct frame *)(pkt + 1); | 68 | fp = (struct frame *)(pkt + 1); |
64 | fp->cid = d->cid; | 69 | fp->cid = d->cid; |
65 | fp->body.init.cmd = CTAP_FRAME_INIT | cmd; | 70 | fp->body.init.cmd = CTAP_FRAME_INIT | cmd; |
66 | fp->body.init.bcnth = (count >> 8) & 0xff; | 71 | fp->body.init.bcnth = (count >> 8) & 0xff; |
67 | fp->body.init.bcntl = count & 0xff; | 72 | fp->body.init.bcntl = count & 0xff; |
68 | count = MIN(count, sizeof(fp->body.init.data)); | 73 | count = MIN(count, d->tx_len - CTAP_INIT_HEADER_LEN); |
69 | memcpy(&fp->body.init.data, buf, count); | 74 | memcpy(&fp->body.init.data, buf, count); |
70 | 75 | ||
71 | n = d->io.write(d->io_handle, pkt, sizeof(pkt)); | 76 | if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt, |
72 | if (n < 0 || (size_t)n != sizeof(pkt)) | 77 | len)) < 0 || (size_t)n != len) |
73 | return (0); | 78 | return (0); |
74 | 79 | ||
75 | return (count); | 80 | return (count); |
@@ -80,17 +85,21 @@ tx_frame(fido_dev_t *d, uint8_t seq, const void *buf, size_t count) | |||
80 | { | 85 | { |
81 | struct frame *fp; | 86 | struct frame *fp; |
82 | unsigned char pkt[sizeof(*fp) + 1]; | 87 | unsigned char pkt[sizeof(*fp) + 1]; |
88 | const size_t len = d->tx_len + 1; | ||
83 | int n; | 89 | int n; |
84 | 90 | ||
91 | if (d->tx_len - CTAP_CONT_HEADER_LEN > sizeof(fp->body.cont.data)) | ||
92 | return (0); | ||
93 | |||
85 | memset(&pkt, 0, sizeof(pkt)); | 94 | memset(&pkt, 0, sizeof(pkt)); |
86 | fp = (struct frame *)(pkt + 1); | 95 | fp = (struct frame *)(pkt + 1); |
87 | fp->cid = d->cid; | 96 | fp->cid = d->cid; |
88 | fp->body.cont.seq = seq; | 97 | fp->body.cont.seq = seq; |
89 | count = MIN(count, sizeof(fp->body.cont.data)); | 98 | count = MIN(count, d->tx_len - CTAP_CONT_HEADER_LEN); |
90 | memcpy(&fp->body.cont.data, buf, count); | 99 | memcpy(&fp->body.cont.data, buf, count); |
91 | 100 | ||
92 | n = d->io.write(d->io_handle, pkt, sizeof(pkt)); | 101 | if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt, |
93 | if (n < 0 || (size_t)n != sizeof(pkt)) | 102 | len)) < 0 || (size_t)n != len) |
94 | return (0); | 103 | return (0); |
95 | 104 | ||
96 | return (count); | 105 | return (count); |
@@ -129,16 +138,12 @@ fido_tx(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) | |||
129 | 138 | ||
130 | if (d->transport.tx != NULL) | 139 | if (d->transport.tx != NULL) |
131 | return (d->transport.tx(d, cmd, buf, count)); | 140 | return (d->transport.tx(d, cmd, buf, count)); |
132 | |||
133 | if (d->io_handle == NULL || d->io.write == NULL || count > UINT16_MAX) { | 141 | if (d->io_handle == NULL || d->io.write == NULL || count > UINT16_MAX) { |
134 | fido_log_debug("%s: invalid argument", __func__); | 142 | fido_log_debug("%s: invalid argument", __func__); |
135 | return (-1); | 143 | return (-1); |
136 | } | 144 | } |
137 | 145 | ||
138 | if (count == 0) | 146 | return (count == 0 ? tx_empty(d, cmd) : tx(d, cmd, buf, count)); |
139 | return (tx_empty(d, cmd)); | ||
140 | |||
141 | return (tx(d, cmd, buf, count)); | ||
142 | } | 147 | } |
143 | 148 | ||
144 | static int | 149 | static int |
@@ -146,8 +151,10 @@ rx_frame(fido_dev_t *d, struct frame *fp, int ms) | |||
146 | { | 151 | { |
147 | int n; | 152 | int n; |
148 | 153 | ||
149 | n = d->io.read(d->io_handle, (unsigned char *)fp, sizeof(*fp), ms); | 154 | memset(fp, 0, sizeof(*fp)); |
150 | if (n < 0 || (size_t)n != sizeof(*fp)) | 155 | |
156 | if (d->rx_len > sizeof(*fp) || (n = d->io.read(d->io_handle, | ||
157 | (unsigned char *)fp, d->rx_len, ms)) < 0 || (size_t)n != d->rx_len) | ||
151 | return (-1); | 158 | return (-1); |
152 | 159 | ||
153 | return (0); | 160 | return (0); |
@@ -165,8 +172,11 @@ rx_preamble(fido_dev_t *d, uint8_t cmd, struct frame *fp, int ms) | |||
165 | } while (fp->cid == d->cid && | 172 | } while (fp->cid == d->cid && |
166 | fp->body.init.cmd == (CTAP_FRAME_INIT | CTAP_KEEPALIVE)); | 173 | fp->body.init.cmd == (CTAP_FRAME_INIT | CTAP_KEEPALIVE)); |
167 | 174 | ||
175 | if (d->rx_len > sizeof(*fp)) | ||
176 | return (-1); | ||
177 | |||
168 | fido_log_debug("%s: initiation frame at %p", __func__, (void *)fp); | 178 | fido_log_debug("%s: initiation frame at %p", __func__, (void *)fp); |
169 | fido_log_xxd(fp, sizeof(*fp)); | 179 | fido_log_xxd(fp, d->rx_len); |
170 | 180 | ||
171 | #ifdef FIDO_FUZZ | 181 | #ifdef FIDO_FUZZ |
172 | fp->body.init.cmd = (CTAP_FRAME_INIT | cmd); | 182 | fp->body.init.cmd = (CTAP_FRAME_INIT | cmd); |
@@ -185,30 +195,41 @@ static int | |||
185 | rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) | 195 | rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) |
186 | { | 196 | { |
187 | struct frame f; | 197 | struct frame f; |
188 | uint16_t r, payload_len; | 198 | size_t r, payload_len, init_data_len, cont_data_len; |
199 | |||
200 | if (d->rx_len <= CTAP_INIT_HEADER_LEN || | ||
201 | d->rx_len <= CTAP_CONT_HEADER_LEN) | ||
202 | return (-1); | ||
203 | |||
204 | init_data_len = d->rx_len - CTAP_INIT_HEADER_LEN; | ||
205 | cont_data_len = d->rx_len - CTAP_CONT_HEADER_LEN; | ||
206 | |||
207 | if (init_data_len > sizeof(f.body.init.data) || | ||
208 | cont_data_len > sizeof(f.body.cont.data)) | ||
209 | return (-1); | ||
189 | 210 | ||
190 | if (rx_preamble(d, cmd, &f, ms) < 0) { | 211 | if (rx_preamble(d, cmd, &f, ms) < 0) { |
191 | fido_log_debug("%s: rx_preamble", __func__); | 212 | fido_log_debug("%s: rx_preamble", __func__); |
192 | return (-1); | 213 | return (-1); |
193 | } | 214 | } |
194 | 215 | ||
195 | payload_len = (f.body.init.bcnth << 8) | f.body.init.bcntl; | 216 | payload_len = (size_t)((f.body.init.bcnth << 8) | f.body.init.bcntl); |
196 | fido_log_debug("%s: payload_len=%zu", __func__, (size_t)payload_len); | 217 | fido_log_debug("%s: payload_len=%zu", __func__, payload_len); |
197 | 218 | ||
198 | if (count < (size_t)payload_len) { | 219 | if (count < payload_len) { |
199 | fido_log_debug("%s: count < payload_len", __func__); | 220 | fido_log_debug("%s: count < payload_len", __func__); |
200 | return (-1); | 221 | return (-1); |
201 | } | 222 | } |
202 | 223 | ||
203 | if (payload_len < sizeof(f.body.init.data)) { | 224 | if (payload_len < init_data_len) { |
204 | memcpy(buf, f.body.init.data, payload_len); | 225 | memcpy(buf, f.body.init.data, payload_len); |
205 | return (payload_len); | 226 | return ((int)payload_len); |
206 | } | 227 | } |
207 | 228 | ||
208 | memcpy(buf, f.body.init.data, sizeof(f.body.init.data)); | 229 | memcpy(buf, f.body.init.data, init_data_len); |
209 | r = sizeof(f.body.init.data); | 230 | r = init_data_len; |
210 | 231 | ||
211 | for (int seq = 0; (size_t)r < payload_len; seq++) { | 232 | for (int seq = 0; r < payload_len; seq++) { |
212 | if (rx_frame(d, &f, ms) < 0) { | 233 | if (rx_frame(d, &f, ms) < 0) { |
213 | fido_log_debug("%s: rx_frame", __func__); | 234 | fido_log_debug("%s: rx_frame", __func__); |
214 | return (-1); | 235 | return (-1); |
@@ -216,11 +237,11 @@ rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) | |||
216 | 237 | ||
217 | fido_log_debug("%s: continuation frame at %p", __func__, | 238 | fido_log_debug("%s: continuation frame at %p", __func__, |
218 | (void *)&f); | 239 | (void *)&f); |
219 | fido_log_xxd(&f, sizeof(f)); | 240 | fido_log_xxd(&f, d->rx_len); |
220 | 241 | ||
221 | #ifdef FIDO_FUZZ | 242 | #ifdef FIDO_FUZZ |
222 | f.cid = d->cid; | 243 | f.cid = d->cid; |
223 | f.body.cont.seq = seq; | 244 | f.body.cont.seq = (uint8_t)seq; |
224 | #endif | 245 | #endif |
225 | 246 | ||
226 | if (f.cid != d->cid || f.body.cont.seq != seq) { | 247 | if (f.cid != d->cid || f.body.cont.seq != seq) { |
@@ -229,17 +250,16 @@ rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) | |||
229 | return (-1); | 250 | return (-1); |
230 | } | 251 | } |
231 | 252 | ||
232 | if ((size_t)(payload_len - r) > sizeof(f.body.cont.data)) { | 253 | if (payload_len - r > cont_data_len) { |
233 | memcpy(buf + r, f.body.cont.data, | 254 | memcpy(buf + r, f.body.cont.data, cont_data_len); |
234 | sizeof(f.body.cont.data)); | 255 | r += cont_data_len; |
235 | r += sizeof(f.body.cont.data); | ||
236 | } else { | 256 | } else { |
237 | memcpy(buf + r, f.body.cont.data, payload_len - r); | 257 | memcpy(buf + r, f.body.cont.data, payload_len - r); |
238 | r += (payload_len - r); /* break */ | 258 | r += payload_len - r; /* break */ |
239 | } | 259 | } |
240 | } | 260 | } |
241 | 261 | ||
242 | return (r); | 262 | return ((int)r); |
243 | } | 263 | } |
244 | 264 | ||
245 | int | 265 | int |
@@ -252,15 +272,13 @@ fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms) | |||
252 | 272 | ||
253 | if (d->transport.rx != NULL) | 273 | if (d->transport.rx != NULL) |
254 | return (d->transport.rx(d, cmd, buf, count, ms)); | 274 | return (d->transport.rx(d, cmd, buf, count, ms)); |
255 | |||
256 | if (d->io_handle == NULL || d->io.read == NULL || count > UINT16_MAX) { | 275 | if (d->io_handle == NULL || d->io.read == NULL || count > UINT16_MAX) { |
257 | fido_log_debug("%s: invalid argument", __func__); | 276 | fido_log_debug("%s: invalid argument", __func__); |
258 | return (-1); | 277 | return (-1); |
259 | } | 278 | } |
260 | |||
261 | if ((n = rx(d, cmd, buf, count, ms)) >= 0) { | 279 | if ((n = rx(d, cmd, buf, count, ms)) >= 0) { |
262 | fido_log_debug("%s: buf=%p, len=%d", __func__, (void *)buf, n); | 280 | fido_log_debug("%s: buf=%p, len=%d", __func__, (void *)buf, n); |
263 | fido_log_xxd(buf, n); | 281 | fido_log_xxd(buf, (size_t)n); |
264 | } | 282 | } |
265 | 283 | ||
266 | return (n); | 284 | return (n); |
diff --git a/src/iso7816.c b/src/iso7816.c index a3fd280..4fe6329 100644 --- a/src/iso7816.c +++ b/src/iso7816.c | |||
@@ -23,8 +23,8 @@ iso7816_new(uint8_t ins, uint8_t p1, uint16_t payload_len) | |||
23 | apdu->payload_ptr = apdu->payload; | 23 | apdu->payload_ptr = apdu->payload; |
24 | apdu->header.ins = ins; | 24 | apdu->header.ins = ins; |
25 | apdu->header.p1 = p1; | 25 | apdu->header.p1 = p1; |
26 | apdu->header.lc2 = (payload_len >> 8) & 0xff; | 26 | apdu->header.lc2 = (uint8_t)((payload_len >> 8) & 0xff); |
27 | apdu->header.lc3 = payload_len & 0xff; | 27 | apdu->header.lc3 = (uint8_t)(payload_len & 0xff); |
28 | 28 | ||
29 | return (apdu); | 29 | return (apdu); |
30 | } | 30 | } |
@@ -51,7 +51,7 @@ iso7816_add(iso7816_apdu_t *apdu, const void *buf, size_t cnt) | |||
51 | 51 | ||
52 | memcpy(apdu->payload_ptr, buf, cnt); | 52 | memcpy(apdu->payload_ptr, buf, cnt); |
53 | apdu->payload_ptr += cnt; | 53 | apdu->payload_ptr += cnt; |
54 | apdu->payload_len -= (uint16_t)cnt; | 54 | apdu->payload_len = (uint16_t)(apdu->payload_len - cnt); |
55 | 55 | ||
56 | return (0); | 56 | return (0); |
57 | } | 57 | } |
@@ -53,7 +53,7 @@ fido_dev_get_pin_token_tx(fido_dev_t *dev, const char *pin, | |||
53 | 53 | ||
54 | if ((argv[0] = cbor_build_uint8(1)) == NULL || | 54 | if ((argv[0] = cbor_build_uint8(1)) == NULL || |
55 | (argv[1] = cbor_build_uint8(5)) == NULL || | 55 | (argv[1] = cbor_build_uint8(5)) == NULL || |
56 | (argv[2] = es256_pk_encode(pk, 0)) == NULL || | 56 | (argv[2] = es256_pk_encode(pk, 1)) == NULL || |
57 | (argv[5] = cbor_encode_pin_hash_enc(ecdh, p)) == NULL) { | 57 | (argv[5] = cbor_encode_pin_hash_enc(ecdh, p)) == NULL) { |
58 | fido_log_debug("%s: cbor encode", __func__); | 58 | fido_log_debug("%s: cbor encode", __func__); |
59 | r = FIDO_ERR_INTERNAL; | 59 | r = FIDO_ERR_INTERNAL; |
@@ -89,7 +89,7 @@ fido_dev_get_uv_token_tx(fido_dev_t *dev, const es256_pk_t *pk) | |||
89 | 89 | ||
90 | if ((argv[0] = cbor_build_uint8(1)) == NULL || | 90 | if ((argv[0] = cbor_build_uint8(1)) == NULL || |
91 | (argv[1] = cbor_build_uint8(6)) == NULL || | 91 | (argv[1] = cbor_build_uint8(6)) == NULL || |
92 | (argv[2] = es256_pk_encode(pk, 0)) == NULL) { | 92 | (argv[2] = es256_pk_encode(pk, 1)) == NULL) { |
93 | fido_log_debug("%s: cbor encode", __func__); | 93 | fido_log_debug("%s: cbor encode", __func__); |
94 | r = FIDO_ERR_INTERNAL; | 94 | r = FIDO_ERR_INTERNAL; |
95 | goto fail; | 95 | goto fail; |
@@ -240,7 +240,7 @@ pad64(const char *pin, fido_blob_t **ppin) | |||
240 | if ((*ppin = fido_blob_new()) == NULL) | 240 | if ((*ppin = fido_blob_new()) == NULL) |
241 | return (FIDO_ERR_INTERNAL); | 241 | return (FIDO_ERR_INTERNAL); |
242 | 242 | ||
243 | ppin_len = (pin_len + 63) & ~63; | 243 | ppin_len = (pin_len + 63U) & ~63U; |
244 | if (ppin_len < pin_len || ((*ppin)->ptr = calloc(1, ppin_len)) == NULL) { | 244 | if (ppin_len < pin_len || ((*ppin)->ptr = calloc(1, ppin_len)) == NULL) { |
245 | fido_blob_free(ppin); | 245 | fido_blob_free(ppin); |
246 | return (FIDO_ERR_INTERNAL); | 246 | return (FIDO_ERR_INTERNAL); |
@@ -285,7 +285,7 @@ fido_dev_change_pin_tx(fido_dev_t *dev, const char *pin, const char *oldpin) | |||
285 | 285 | ||
286 | if ((argv[0] = cbor_build_uint8(1)) == NULL || | 286 | if ((argv[0] = cbor_build_uint8(1)) == NULL || |
287 | (argv[1] = cbor_build_uint8(4)) == NULL || | 287 | (argv[1] = cbor_build_uint8(4)) == NULL || |
288 | (argv[2] = es256_pk_encode(pk, 0)) == NULL || | 288 | (argv[2] = es256_pk_encode(pk, 1)) == NULL || |
289 | (argv[3] = cbor_encode_change_pin_auth(ecdh, ppin, opin)) == NULL || | 289 | (argv[3] = cbor_encode_change_pin_auth(ecdh, ppin, opin)) == NULL || |
290 | (argv[4] = cbor_encode_pin_enc(ecdh, ppin)) == NULL || | 290 | (argv[4] = cbor_encode_pin_enc(ecdh, ppin)) == NULL || |
291 | (argv[5] = cbor_encode_pin_hash_enc(ecdh, opin)) == NULL) { | 291 | (argv[5] = cbor_encode_pin_hash_enc(ecdh, opin)) == NULL) { |
@@ -339,7 +339,7 @@ fido_dev_set_pin_tx(fido_dev_t *dev, const char *pin) | |||
339 | 339 | ||
340 | if ((argv[0] = cbor_build_uint8(1)) == NULL || | 340 | if ((argv[0] = cbor_build_uint8(1)) == NULL || |
341 | (argv[1] = cbor_build_uint8(3)) == NULL || | 341 | (argv[1] = cbor_build_uint8(3)) == NULL || |
342 | (argv[2] = es256_pk_encode(pk, 0)) == NULL || | 342 | (argv[2] = es256_pk_encode(pk, 1)) == NULL || |
343 | (argv[3] = cbor_encode_set_pin_auth(ecdh, ppin)) == NULL || | 343 | (argv[3] = cbor_encode_set_pin_auth(ecdh, ppin)) == NULL || |
344 | (argv[4] = cbor_encode_pin_enc(ecdh, ppin)) == NULL) { | 344 | (argv[4] = cbor_encode_pin_enc(ecdh, ppin)) == NULL) { |
345 | fido_log_debug("%s: cbor encode", __func__); | 345 | fido_log_debug("%s: cbor encode", __func__); |
@@ -122,6 +122,7 @@ authdata_fake(const char *rp_id, uint8_t flags, uint32_t sigcount, | |||
122 | return (0); | 122 | return (0); |
123 | } | 123 | } |
124 | 124 | ||
125 | /* TODO: use u2f_get_touch_begin & u2f_get_touch_status instead */ | ||
125 | static int | 126 | static int |
126 | send_dummy_register(fido_dev_t *dev, int ms) | 127 | send_dummy_register(fido_dev_t *dev, int ms) |
127 | { | 128 | { |
@@ -160,7 +161,7 @@ send_dummy_register(fido_dev_t *dev, int ms) | |||
160 | r = FIDO_ERR_RX; | 161 | r = FIDO_ERR_RX; |
161 | goto fail; | 162 | goto fail; |
162 | } | 163 | } |
163 | if (usleep((ms == -1 ? 100 : ms) * 1000) < 0) { | 164 | if (usleep((unsigned)(ms == -1 ? 100 : ms) * 1000) < 0) { |
164 | fido_log_debug("%s: usleep", __func__); | 165 | fido_log_debug("%s: usleep", __func__); |
165 | r = FIDO_ERR_RX; | 166 | r = FIDO_ERR_RX; |
166 | goto fail; | 167 | goto fail; |
@@ -204,8 +205,8 @@ key_lookup(fido_dev_t *dev, const char *rp_id, const fido_blob_t *key_id, | |||
204 | 205 | ||
205 | key_id_len = (uint8_t)key_id->len; | 206 | key_id_len = (uint8_t)key_id->len; |
206 | 207 | ||
207 | if ((apdu = iso7816_new(U2F_CMD_AUTH, U2F_AUTH_CHECK, 2 * | 208 | if ((apdu = iso7816_new(U2F_CMD_AUTH, U2F_AUTH_CHECK, (uint16_t)(2 * |
208 | SHA256_DIGEST_LENGTH + sizeof(key_id_len) + key_id_len)) == NULL || | 209 | SHA256_DIGEST_LENGTH + sizeof(key_id_len) + key_id_len))) == NULL || |
209 | iso7816_add(apdu, &challenge, sizeof(challenge)) < 0 || | 210 | iso7816_add(apdu, &challenge, sizeof(challenge)) < 0 || |
210 | iso7816_add(apdu, &rp_id_hash, sizeof(rp_id_hash)) < 0 || | 211 | iso7816_add(apdu, &rp_id_hash, sizeof(rp_id_hash)) < 0 || |
211 | iso7816_add(apdu, &key_id_len, sizeof(key_id_len)) < 0 || | 212 | iso7816_add(apdu, &key_id_len, sizeof(key_id_len)) < 0 || |
@@ -312,8 +313,8 @@ do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id, | |||
312 | 313 | ||
313 | key_id_len = (uint8_t)key_id->len; | 314 | key_id_len = (uint8_t)key_id->len; |
314 | 315 | ||
315 | if ((apdu = iso7816_new(U2F_CMD_AUTH, U2F_AUTH_SIGN, 2 * | 316 | if ((apdu = iso7816_new(U2F_CMD_AUTH, U2F_AUTH_SIGN, (uint16_t)(2 * |
316 | SHA256_DIGEST_LENGTH + sizeof(key_id_len) + key_id_len)) == NULL || | 317 | SHA256_DIGEST_LENGTH + sizeof(key_id_len) + key_id_len))) == NULL || |
317 | iso7816_add(apdu, cdh->ptr, cdh->len) < 0 || | 318 | iso7816_add(apdu, cdh->ptr, cdh->len) < 0 || |
318 | iso7816_add(apdu, &rp_id_hash, sizeof(rp_id_hash)) < 0 || | 319 | iso7816_add(apdu, &rp_id_hash, sizeof(rp_id_hash)) < 0 || |
319 | iso7816_add(apdu, &key_id_len, sizeof(key_id_len)) < 0 || | 320 | iso7816_add(apdu, &key_id_len, sizeof(key_id_len)) < 0 || |
@@ -336,7 +337,7 @@ do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id, | |||
336 | r = FIDO_ERR_RX; | 337 | r = FIDO_ERR_RX; |
337 | goto fail; | 338 | goto fail; |
338 | } | 339 | } |
339 | if (usleep((ms == -1 ? 100 : ms) * 1000) < 0) { | 340 | if (usleep((unsigned)(ms == -1 ? 100 : ms) * 1000) < 0) { |
340 | fido_log_debug("%s: usleep", __func__); | 341 | fido_log_debug("%s: usleep", __func__); |
341 | r = FIDO_ERR_RX; | 342 | r = FIDO_ERR_RX; |
342 | goto fail; | 343 | goto fail; |
@@ -643,7 +644,7 @@ u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms) | |||
643 | r = FIDO_ERR_RX; | 644 | r = FIDO_ERR_RX; |
644 | goto fail; | 645 | goto fail; |
645 | } | 646 | } |
646 | if (usleep((ms == -1 ? 100 : ms) * 1000) < 0) { | 647 | if (usleep((unsigned)(ms == -1 ? 100 : ms) * 1000) < 0) { |
647 | fido_log_debug("%s: usleep", __func__); | 648 | fido_log_debug("%s: usleep", __func__); |
648 | r = FIDO_ERR_RX; | 649 | r = FIDO_ERR_RX; |
649 | goto fail; | 650 | goto fail; |
@@ -726,8 +727,8 @@ fail: | |||
726 | int | 727 | int |
727 | u2f_authenticate(fido_dev_t *dev, fido_assert_t *fa, int ms) | 728 | u2f_authenticate(fido_dev_t *dev, fido_assert_t *fa, int ms) |
728 | { | 729 | { |
729 | int nfound = 0; | 730 | size_t nfound = 0; |
730 | int nauth_ok = 0; | 731 | size_t nauth_ok = 0; |
731 | int r; | 732 | int r; |
732 | 733 | ||
733 | if (fa->uv == FIDO_OPT_TRUE || fa->allow_list.ptr == NULL) { | 734 | if (fa->uv == FIDO_OPT_TRUE || fa->allow_list.ptr == NULL) { |
@@ -769,3 +770,84 @@ u2f_authenticate(fido_dev_t *dev, fido_assert_t *fa, int ms) | |||
769 | 770 | ||
770 | return (FIDO_OK); | 771 | return (FIDO_OK); |
771 | } | 772 | } |
773 | |||
774 | int | ||
775 | u2f_get_touch_begin(fido_dev_t *dev) | ||
776 | { | ||
777 | iso7816_apdu_t *apdu = NULL; | ||
778 | const char *clientdata = FIDO_DUMMY_CLIENTDATA; | ||
779 | const char *rp_id = FIDO_DUMMY_RP_ID; | ||
780 | unsigned char clientdata_hash[SHA256_DIGEST_LENGTH]; | ||
781 | unsigned char rp_id_hash[SHA256_DIGEST_LENGTH]; | ||
782 | unsigned char reply[FIDO_MAXMSG]; | ||
783 | int r; | ||
784 | |||
785 | memset(&clientdata_hash, 0, sizeof(clientdata_hash)); | ||
786 | memset(&rp_id_hash, 0, sizeof(rp_id_hash)); | ||
787 | |||
788 | if (SHA256((const void *)clientdata, strlen(clientdata), | ||
789 | clientdata_hash) != clientdata_hash || SHA256((const void *)rp_id, | ||
790 | strlen(rp_id), rp_id_hash) != rp_id_hash) { | ||
791 | fido_log_debug("%s: sha256", __func__); | ||
792 | return (FIDO_ERR_INTERNAL); | ||
793 | } | ||
794 | |||
795 | if ((apdu = iso7816_new(U2F_CMD_REGISTER, 0, 2 * | ||
796 | SHA256_DIGEST_LENGTH)) == NULL || | ||
797 | iso7816_add(apdu, clientdata_hash, sizeof(clientdata_hash)) < 0 || | ||
798 | iso7816_add(apdu, rp_id_hash, sizeof(rp_id_hash)) < 0) { | ||
799 | fido_log_debug("%s: iso7816", __func__); | ||
800 | r = FIDO_ERR_INTERNAL; | ||
801 | goto fail; | ||
802 | } | ||
803 | |||
804 | if (dev->attr.flags & FIDO_CAP_WINK) { | ||
805 | fido_tx(dev, CTAP_CMD_WINK, NULL, 0); | ||
806 | fido_rx(dev, CTAP_CMD_WINK, &reply, sizeof(reply), 200); | ||
807 | } | ||
808 | |||
809 | if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu), | ||
810 | iso7816_len(apdu)) < 0) { | ||
811 | fido_log_debug("%s: fido_tx", __func__); | ||
812 | r = FIDO_ERR_TX; | ||
813 | goto fail; | ||
814 | } | ||
815 | |||
816 | r = FIDO_OK; | ||
817 | fail: | ||
818 | iso7816_free(&apdu); | ||
819 | |||
820 | return (r); | ||
821 | } | ||
822 | |||
823 | int | ||
824 | u2f_get_touch_status(fido_dev_t *dev, int *touched, int ms) | ||
825 | { | ||
826 | unsigned char reply[FIDO_MAXMSG]; | ||
827 | int reply_len; | ||
828 | int r; | ||
829 | |||
830 | if ((reply_len = fido_rx(dev, CTAP_CMD_MSG, &reply, sizeof(reply), | ||
831 | ms)) < 2) { | ||
832 | fido_log_debug("%s: fido_rx", __func__); | ||
833 | return (FIDO_OK); /* ignore */ | ||
834 | } | ||
835 | |||
836 | switch ((reply[reply_len - 2] << 8) | reply[reply_len - 1]) { | ||
837 | case SW_CONDITIONS_NOT_SATISFIED: | ||
838 | if ((r = u2f_get_touch_begin(dev)) != FIDO_OK) { | ||
839 | fido_log_debug("%s: u2f_get_touch_begin", __func__); | ||
840 | return (r); | ||
841 | } | ||
842 | *touched = 0; | ||
843 | break; | ||
844 | case SW_NO_ERROR: | ||
845 | *touched = 1; | ||
846 | break; | ||
847 | default: | ||
848 | fido_log_debug("%s: unexpected sw", __func__); | ||
849 | return (FIDO_ERR_RX); | ||
850 | } | ||
851 | |||
852 | return (FIDO_OK); | ||
853 | } | ||
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 274a799..4d08be9 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt | |||
@@ -20,6 +20,13 @@ else() | |||
20 | list(APPEND COMPAT_SOURCES ../openbsd-compat/readpassphrase.c) | 20 | list(APPEND COMPAT_SOURCES ../openbsd-compat/readpassphrase.c) |
21 | endif() | 21 | endif() |
22 | 22 | ||
23 | if(NOT MSVC) | ||
24 | set_source_files_properties(assert_get.c assert_verify.c base64.c bio.c | ||
25 | cred_make.c cred_verify.c credman.c fido2-assert.c fido2-cred.c | ||
26 | fido2-token.c pin.c token.c util.c PROPERTIES COMPILE_FLAGS | ||
27 | "-Wconversion -Wsign-conversion") | ||
28 | endif() | ||
29 | |||
23 | add_executable(fido2-cred | 30 | add_executable(fido2-cred |
24 | fido2-cred.c | 31 | fido2-cred.c |
25 | cred_make.c | 32 | cred_make.c |
diff --git a/tools/assert_get.c b/tools/assert_get.c index 5e209cd..d52cd06 100644 --- a/tools/assert_get.c +++ b/tools/assert_get.c | |||
@@ -15,8 +15,67 @@ | |||
15 | #include "../openbsd-compat/openbsd-compat.h" | 15 | #include "../openbsd-compat/openbsd-compat.h" |
16 | #include "extern.h" | 16 | #include "extern.h" |
17 | 17 | ||
18 | struct toggle { | ||
19 | fido_opt_t up; | ||
20 | fido_opt_t uv; | ||
21 | fido_opt_t pin; | ||
22 | }; | ||
23 | |||
24 | static const char * | ||
25 | opt2str(fido_opt_t v) | ||
26 | { | ||
27 | switch (v) { | ||
28 | case FIDO_OPT_OMIT: | ||
29 | return "omit"; | ||
30 | case FIDO_OPT_TRUE: | ||
31 | return "true"; | ||
32 | case FIDO_OPT_FALSE: | ||
33 | return "false"; | ||
34 | default: | ||
35 | return "unknown"; | ||
36 | } | ||
37 | } | ||
38 | |||
39 | static void | ||
40 | parse_toggle(const char *str, struct toggle *opt) | ||
41 | { | ||
42 | fido_opt_t *k; | ||
43 | fido_opt_t v; | ||
44 | char *assignment; | ||
45 | char *key; | ||
46 | char *val; | ||
47 | |||
48 | if ((assignment = strdup(str)) == NULL) | ||
49 | err(1, "strdup"); | ||
50 | if ((val = strchr(assignment, '=')) == NULL) | ||
51 | errx(1, "invalid assignment '%s'", assignment); | ||
52 | |||
53 | key = assignment; | ||
54 | *val++ = '\0'; | ||
55 | |||
56 | if (!strcmp(val, "true")) | ||
57 | v = FIDO_OPT_TRUE; | ||
58 | else if (!strcmp(val, "false")) | ||
59 | v = FIDO_OPT_FALSE; | ||
60 | else | ||
61 | errx(1, "unknown value '%s'", val); | ||
62 | |||
63 | if (!strcmp(key, "up")) | ||
64 | k = &opt->up; | ||
65 | else if (!strcmp(key, "uv")) | ||
66 | k = &opt->uv; | ||
67 | else if (!strcmp(key, "pin")) | ||
68 | k = &opt->pin; | ||
69 | else | ||
70 | errx(1, "unknown key '%s'", key); | ||
71 | |||
72 | free(assignment); | ||
73 | |||
74 | *k = v; | ||
75 | } | ||
76 | |||
18 | static fido_assert_t * | 77 | static fido_assert_t * |
19 | prepare_assert(FILE *in_f, int flags) | 78 | prepare_assert(FILE *in_f, int flags, const struct toggle *opt) |
20 | { | 79 | { |
21 | fido_assert_t *assert = NULL; | 80 | fido_assert_t *assert = NULL; |
22 | struct blob cdh; | 81 | struct blob cdh; |
@@ -46,6 +105,9 @@ prepare_assert(FILE *in_f, int flags) | |||
46 | fprintf(stderr, "credential id:\n"); | 105 | fprintf(stderr, "credential id:\n"); |
47 | xxd(id.ptr, id.len); | 106 | xxd(id.ptr, id.len); |
48 | } | 107 | } |
108 | fprintf(stderr, "up=%s\n", opt2str(opt->up)); | ||
109 | fprintf(stderr, "uv=%s\n", opt2str(opt->uv)); | ||
110 | fprintf(stderr, "pin=%s\n", opt2str(opt->pin)); | ||
49 | } | 111 | } |
50 | 112 | ||
51 | if ((assert = fido_assert_new()) == NULL) | 113 | if ((assert = fido_assert_new()) == NULL) |
@@ -55,15 +117,11 @@ prepare_assert(FILE *in_f, int flags) | |||
55 | cdh.len)) != FIDO_OK || | 117 | cdh.len)) != FIDO_OK || |
56 | (r = fido_assert_set_rp(assert, rpid)) != FIDO_OK) | 118 | (r = fido_assert_set_rp(assert, rpid)) != FIDO_OK) |
57 | errx(1, "fido_assert_set: %s", fido_strerr(r)); | 119 | errx(1, "fido_assert_set: %s", fido_strerr(r)); |
120 | if ((r = fido_assert_set_up(assert, opt->up)) != FIDO_OK) | ||
121 | errx(1, "fido_assert_set_up: %s", fido_strerr(r)); | ||
122 | if ((r = fido_assert_set_uv(assert, opt->uv)) != FIDO_OK) | ||
123 | errx(1, "fido_assert_set_uv: %s", fido_strerr(r)); | ||
58 | 124 | ||
59 | if (flags & FLAG_UP) { | ||
60 | if ((r = fido_assert_set_up(assert, FIDO_OPT_TRUE)) != FIDO_OK) | ||
61 | errx(1, "fido_assert_set_up: %s", fido_strerr(r)); | ||
62 | } | ||
63 | if (flags & FLAG_UV) { | ||
64 | if ((r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) | ||
65 | errx(1, "fido_assert_set_uv: %s", fido_strerr(r)); | ||
66 | } | ||
67 | if (flags & FLAG_HMAC) { | 125 | if (flags & FLAG_HMAC) { |
68 | if ((r = fido_assert_set_extensions(assert, | 126 | if ((r = fido_assert_set_extensions(assert, |
69 | FIDO_EXT_HMAC_SECRET)) != FIDO_OK) | 127 | FIDO_EXT_HMAC_SECRET)) != FIDO_OK) |
@@ -136,6 +194,7 @@ assert_get(int argc, char **argv) | |||
136 | { | 194 | { |
137 | fido_dev_t *dev = NULL; | 195 | fido_dev_t *dev = NULL; |
138 | fido_assert_t *assert = NULL; | 196 | fido_assert_t *assert = NULL; |
197 | struct toggle opt; | ||
139 | char pin[1024]; | 198 | char pin[1024]; |
140 | char prompt[1024]; | 199 | char prompt[1024]; |
141 | char *in_path = NULL; | 200 | char *in_path = NULL; |
@@ -146,7 +205,9 @@ assert_get(int argc, char **argv) | |||
146 | int ch; | 205 | int ch; |
147 | int r; | 206 | int r; |
148 | 207 | ||
149 | while ((ch = getopt(argc, argv, "dhi:o:pruv")) != -1) { | 208 | opt.up = opt.uv = opt.pin = FIDO_OPT_OMIT; |
209 | |||
210 | while ((ch = getopt(argc, argv, "dhi:o:prt:uv")) != -1) { | ||
150 | switch (ch) { | 211 | switch (ch) { |
151 | case 'd': | 212 | case 'd': |
152 | flags |= FLAG_DEBUG; | 213 | flags |= FLAG_DEBUG; |
@@ -161,16 +222,21 @@ assert_get(int argc, char **argv) | |||
161 | out_path = optarg; | 222 | out_path = optarg; |
162 | break; | 223 | break; |
163 | case 'p': | 224 | case 'p': |
164 | flags |= FLAG_UP; | 225 | opt.up = FIDO_OPT_TRUE; |
165 | break; | 226 | break; |
166 | case 'r': | 227 | case 'r': |
167 | flags |= FLAG_RK; | 228 | flags |= FLAG_RK; |
168 | break; | 229 | break; |
230 | case 't' : | ||
231 | parse_toggle(optarg, &opt); | ||
232 | break; | ||
169 | case 'u': | 233 | case 'u': |
170 | flags |= FLAG_U2F; | 234 | flags |= FLAG_U2F; |
171 | break; | 235 | break; |
172 | case 'v': | 236 | case 'v': |
173 | flags |= FLAG_UV; | 237 | /* -v implies both pin and uv for historical reasons */ |
238 | opt.pin = FIDO_OPT_TRUE; | ||
239 | opt.uv = FIDO_OPT_TRUE; | ||
174 | break; | 240 | break; |
175 | default: | 241 | default: |
176 | usage(); | 242 | usage(); |
@@ -188,13 +254,13 @@ assert_get(int argc, char **argv) | |||
188 | 254 | ||
189 | fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); | 255 | fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); |
190 | 256 | ||
191 | assert = prepare_assert(in_f, flags); | 257 | assert = prepare_assert(in_f, flags, &opt); |
192 | 258 | ||
193 | dev = open_dev(argv[0]); | 259 | dev = open_dev(argv[0]); |
194 | if (flags & FLAG_U2F) | 260 | if (flags & FLAG_U2F) |
195 | fido_dev_force_u2f(dev); | 261 | fido_dev_force_u2f(dev); |
196 | 262 | ||
197 | if (flags & FLAG_UV) { | 263 | if (opt.pin == FIDO_OPT_TRUE) { |
198 | r = snprintf(prompt, sizeof(prompt), "Enter PIN for %s: ", | 264 | r = snprintf(prompt, sizeof(prompt), "Enter PIN for %s: ", |
199 | argv[0]); | 265 | argv[0]); |
200 | if (r < 0 || (size_t)r >= sizeof(prompt)) | 266 | if (r < 0 || (size_t)r >= sizeof(prompt)) |
diff --git a/tools/assert_verify.c b/tools/assert_verify.c index ccff57a..fb96b65 100644 --- a/tools/assert_verify.c +++ b/tools/assert_verify.c | |||
@@ -175,16 +175,8 @@ assert_verify(int argc, char **argv) | |||
175 | 175 | ||
176 | in_f = open_read(in_path); | 176 | in_f = open_read(in_path); |
177 | 177 | ||
178 | if (argc > 1) { | 178 | if (argc > 1 && cose_type(argv[1], &type) < 0) |
179 | if (strcmp(argv[1], "es256") == 0) | 179 | errx(1, "unknown type %s", argv[1]); |
180 | type = COSE_ES256; | ||
181 | else if (strcmp(argv[1], "rs256") == 0) | ||
182 | type = COSE_RS256; | ||
183 | else if (strcmp(argv[1], "eddsa") == 0) | ||
184 | type = COSE_EDDSA; | ||
185 | else | ||
186 | errx(1, "unknown type %s", argv[1]); | ||
187 | } | ||
188 | 180 | ||
189 | fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); | 181 | fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); |
190 | 182 | ||
diff --git a/tools/base64.c b/tools/base64.c index 9f31def..e131198 100644 --- a/tools/base64.c +++ b/tools/base64.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <openssl/bio.h> | 7 | #include <openssl/bio.h> |
8 | #include <openssl/evp.h> | 8 | #include <openssl/evp.h> |
9 | 9 | ||
10 | #include <fido.h> | ||
11 | #include <limits.h> | 10 | #include <limits.h> |
12 | #include <stdint.h> | 11 | #include <stdint.h> |
13 | #include <string.h> | 12 | #include <string.h> |
@@ -62,7 +61,7 @@ fail: | |||
62 | } | 61 | } |
63 | 62 | ||
64 | int | 63 | int |
65 | base64_decode(char *in, void **ptr, size_t *len) | 64 | base64_decode(const char *in, void **ptr, size_t *len) |
66 | { | 65 | { |
67 | BIO *bio_mem = NULL; | 66 | BIO *bio_mem = NULL; |
68 | BIO *bio_b64 = NULL; | 67 | BIO *bio_b64 = NULL; |
@@ -78,7 +77,7 @@ base64_decode(char *in, void **ptr, size_t *len) | |||
78 | 77 | ||
79 | if ((bio_b64 = BIO_new(BIO_f_base64())) == NULL) | 78 | if ((bio_b64 = BIO_new(BIO_f_base64())) == NULL) |
80 | goto fail; | 79 | goto fail; |
81 | if ((bio_mem = BIO_new_mem_buf((void *)in, -1)) == NULL) | 80 | if ((bio_mem = BIO_new_mem_buf((const void *)in, -1)) == NULL) |
82 | goto fail; | 81 | goto fail; |
83 | 82 | ||
84 | BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL); | 83 | BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL); |
diff --git a/tools/cred_make.c b/tools/cred_make.c index 380c67a..255a488 100644 --- a/tools/cred_make.c +++ b/tools/cred_make.c | |||
@@ -130,11 +130,16 @@ cred_make(int argc, char **argv) | |||
130 | FILE *out_f = NULL; | 130 | FILE *out_f = NULL; |
131 | int type = COSE_ES256; | 131 | int type = COSE_ES256; |
132 | int flags = 0; | 132 | int flags = 0; |
133 | int cred_protect = -1; | ||
133 | int ch; | 134 | int ch; |
134 | int r; | 135 | int r; |
135 | 136 | ||
136 | while ((ch = getopt(argc, argv, "dhi:o:qruv")) != -1) { | 137 | while ((ch = getopt(argc, argv, "c:dhi:o:qruv")) != -1) { |
137 | switch (ch) { | 138 | switch (ch) { |
139 | case 'c': | ||
140 | if ((cred_protect = base10(optarg)) < 0) | ||
141 | errx(1, "-c: invalid argument '%s'", optarg); | ||
142 | break; | ||
138 | case 'd': | 143 | case 'd': |
139 | flags |= FLAG_DEBUG; | 144 | flags |= FLAG_DEBUG; |
140 | break; | 145 | break; |
@@ -173,16 +178,8 @@ cred_make(int argc, char **argv) | |||
173 | in_f = open_read(in_path); | 178 | in_f = open_read(in_path); |
174 | out_f = open_write(out_path); | 179 | out_f = open_write(out_path); |
175 | 180 | ||
176 | if (argc > 1) { | 181 | if (argc > 1 && cose_type(argv[1], &type) < 0) |
177 | if (strcmp(argv[1], "es256") == 0) | 182 | errx(1, "unknown type %s", argv[1]); |
178 | type = COSE_ES256; | ||
179 | else if (strcmp(argv[1], "rs256") == 0) | ||
180 | type = COSE_RS256; | ||
181 | else if (strcmp(argv[1], "eddsa") == 0) | ||
182 | type = COSE_EDDSA; | ||
183 | else | ||
184 | errx(1, "unknown type %s", argv[1]); | ||
185 | } | ||
186 | 183 | ||
187 | fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); | 184 | fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); |
188 | 185 | ||
@@ -192,6 +189,13 @@ cred_make(int argc, char **argv) | |||
192 | if (flags & FLAG_U2F) | 189 | if (flags & FLAG_U2F) |
193 | fido_dev_force_u2f(dev); | 190 | fido_dev_force_u2f(dev); |
194 | 191 | ||
192 | if (cred_protect > 0) { | ||
193 | r = fido_cred_set_prot(cred, cred_protect); | ||
194 | if (r != FIDO_OK) { | ||
195 | errx(1, "fido_cred_set_prot: %s", fido_strerr(r)); | ||
196 | } | ||
197 | } | ||
198 | |||
195 | r = fido_dev_make_cred(dev, cred, NULL); | 199 | r = fido_dev_make_cred(dev, cred, NULL); |
196 | if (r == FIDO_ERR_PIN_REQUIRED && !(flags & FLAG_QUIET)) { | 200 | if (r == FIDO_ERR_PIN_REQUIRED && !(flags & FLAG_QUIET)) { |
197 | r = snprintf(prompt, sizeof(prompt), "Enter PIN for %s: ", | 201 | r = snprintf(prompt, sizeof(prompt), "Enter PIN for %s: ", |
diff --git a/tools/cred_verify.c b/tools/cred_verify.c index 3f7a400..d622ed7 100644 --- a/tools/cred_verify.c +++ b/tools/cred_verify.c | |||
@@ -109,11 +109,16 @@ cred_verify(int argc, char **argv) | |||
109 | FILE *out_f = NULL; | 109 | FILE *out_f = NULL; |
110 | int type = COSE_ES256; | 110 | int type = COSE_ES256; |
111 | int flags = 0; | 111 | int flags = 0; |
112 | int cred_prot = -1; | ||
112 | int ch; | 113 | int ch; |
113 | int r; | 114 | int r; |
114 | 115 | ||
115 | while ((ch = getopt(argc, argv, "dhi:o:v")) != -1) { | 116 | while ((ch = getopt(argc, argv, "c:dhi:o:v")) != -1) { |
116 | switch (ch) { | 117 | switch (ch) { |
118 | case 'c': | ||
119 | if ((cred_prot = base10(optarg)) < 0) | ||
120 | errx(1, "-c: invalid argument '%s'", optarg); | ||
121 | break; | ||
117 | case 'd': | 122 | case 'd': |
118 | flags |= FLAG_DEBUG; | 123 | flags |= FLAG_DEBUG; |
119 | break; | 124 | break; |
@@ -143,20 +148,19 @@ cred_verify(int argc, char **argv) | |||
143 | in_f = open_read(in_path); | 148 | in_f = open_read(in_path); |
144 | out_f = open_write(out_path); | 149 | out_f = open_write(out_path); |
145 | 150 | ||
146 | if (argc > 0) { | 151 | if (argc > 0 && cose_type(argv[0], &type) < 0) |
147 | if (strcmp(argv[0], "es256") == 0) | 152 | errx(1, "unknown type %s", argv[0]); |
148 | type = COSE_ES256; | ||
149 | else if (strcmp(argv[0], "rs256") == 0) | ||
150 | type = COSE_RS256; | ||
151 | else if (strcmp(argv[0], "eddsa") == 0) | ||
152 | type = COSE_EDDSA; | ||
153 | else | ||
154 | errx(1, "unknown type %s", argv[0]); | ||
155 | } | ||
156 | 153 | ||
157 | fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); | 154 | fido_init((flags & FLAG_DEBUG) ? FIDO_DEBUG : 0); |
158 | cred = prepare_cred(in_f, type, flags); | 155 | cred = prepare_cred(in_f, type, flags); |
159 | 156 | ||
157 | if (cred_prot > 0) { | ||
158 | r = fido_cred_set_prot(cred, cred_prot); | ||
159 | if (r != FIDO_OK) { | ||
160 | errx(1, "fido_cred_set_prot: %s", fido_strerr(r)); | ||
161 | } | ||
162 | } | ||
163 | |||
160 | if (fido_cred_x5c_ptr(cred) == NULL) { | 164 | if (fido_cred_x5c_ptr(cred) == NULL) { |
161 | if ((r = fido_cred_verify_self(cred)) != FIDO_OK) | 165 | if ((r = fido_cred_verify_self(cred)) != FIDO_OK) |
162 | errx(1, "fido_cred_verify_self: %s", fido_strerr(r)); | 166 | errx(1, "fido_cred_verify_self: %s", fido_strerr(r)); |
diff --git a/tools/credman.c b/tools/credman.c index 6eda245..ea913bb 100644 --- a/tools/credman.c +++ b/tools/credman.c | |||
@@ -101,6 +101,7 @@ print_rk(const fido_credman_rk_t *rk, size_t idx) | |||
101 | char *id = NULL; | 101 | char *id = NULL; |
102 | char *user_id = NULL; | 102 | char *user_id = NULL; |
103 | const char *type; | 103 | const char *type; |
104 | const char *prot; | ||
104 | 105 | ||
105 | if ((cred = fido_credman_rk(rk, idx)) == NULL) | 106 | if ((cred = fido_credman_rk(rk, idx)) == NULL) |
106 | errx(1, "fido_credman_rk"); | 107 | errx(1, "fido_credman_rk"); |
@@ -109,23 +110,11 @@ print_rk(const fido_credman_rk_t *rk, size_t idx) | |||
109 | fido_cred_user_id_len(cred), &user_id) < 0) | 110 | fido_cred_user_id_len(cred), &user_id) < 0) |
110 | errx(1, "output error"); | 111 | errx(1, "output error"); |
111 | 112 | ||
112 | switch (fido_cred_type(cred)) { | 113 | type = cose_string(fido_cred_type(cred)); |
113 | case COSE_EDDSA: | 114 | prot = prot_string(fido_cred_prot(cred)); |
114 | type = "eddsa"; | ||
115 | break; | ||
116 | case COSE_ES256: | ||
117 | type = "es256"; | ||
118 | break; | ||
119 | case COSE_RS256: | ||
120 | type = "rs256"; | ||
121 | break; | ||
122 | default: | ||
123 | type = "unknown"; | ||
124 | break; | ||
125 | } | ||
126 | 115 | ||
127 | printf("%02u: %s %s (%s) %s\n", (unsigned)idx, id, | 116 | printf("%02u: %s %s %s %s %s\n", (unsigned)idx, id, |
128 | fido_cred_display_name(cred), user_id, type); | 117 | fido_cred_display_name(cred), user_id, type, prot); |
129 | 118 | ||
130 | free(user_id); | 119 | free(user_id); |
131 | free(id); | 120 | free(id); |
diff --git a/tools/extern.h b/tools/extern.h index be01046..df5fcd8 100644 --- a/tools/extern.h +++ b/tools/extern.h | |||
@@ -32,9 +32,11 @@ EC_KEY *read_ec_pubkey(const char *); | |||
32 | fido_dev_t *open_dev(const char *); | 32 | fido_dev_t *open_dev(const char *); |
33 | FILE *open_read(const char *); | 33 | FILE *open_read(const char *); |
34 | FILE *open_write(const char *); | 34 | FILE *open_write(const char *); |
35 | const char *cose_string(int); | ||
36 | const char *prot_string(int); | ||
35 | int assert_get(int, char **); | 37 | int assert_get(int, char **); |
36 | int assert_verify(int, char **); | 38 | int assert_verify(int, char **); |
37 | int base64_decode(char *, void **, size_t *); | 39 | int base64_decode(const char *, void **, size_t *); |
38 | int base64_encode(const void *, size_t, char **); | 40 | int base64_encode(const void *, size_t, char **); |
39 | int base64_read(FILE *, struct blob *); | 41 | int base64_read(FILE *, struct blob *); |
40 | int bio_delete(fido_dev_t *, char *, char *); | 42 | int bio_delete(fido_dev_t *, char *, char *); |
@@ -42,6 +44,7 @@ int bio_enroll(char *); | |||
42 | void bio_info(fido_dev_t *); | 44 | void bio_info(fido_dev_t *); |
43 | int bio_list(char *); | 45 | int bio_list(char *); |
44 | int bio_set_name(char *, char *, char *); | 46 | int bio_set_name(char *, char *, char *); |
47 | int cose_type(const char *, int *); | ||
45 | int cred_make(int, char **); | 48 | int cred_make(int, char **); |
46 | int cred_verify(int, char **); | 49 | int cred_verify(int, char **); |
47 | int credman_delete_rk(fido_dev_t *, const char *, char *); | 50 | int credman_delete_rk(fido_dev_t *, const char *, char *); |
@@ -66,5 +69,6 @@ void print_cred(FILE *, int, const fido_cred_t *); | |||
66 | void read_pin(const char *, char *, size_t); | 69 | void read_pin(const char *, char *, size_t); |
67 | void usage(void); | 70 | void usage(void); |
68 | void xxd(const void *, size_t); | 71 | void xxd(const void *, size_t); |
72 | int base10(const char *); | ||
69 | 73 | ||
70 | #endif /* _EXTERN_H_ */ | 74 | #endif /* _EXTERN_H_ */ |
diff --git a/tools/fido2-assert.c b/tools/fido2-assert.c index 9ce537a..7fd7632 100644 --- a/tools/fido2-assert.c +++ b/tools/fido2-assert.c | |||
@@ -11,10 +11,10 @@ | |||
11 | * $ echo relying party >> assert_param | 11 | * $ echo relying party >> assert_param |
12 | * $ head -1 cred >> assert_param # credential id | 12 | * $ head -1 cred >> assert_param # credential id |
13 | * $ tail -n +2 cred > pubkey # credential pubkey | 13 | * $ tail -n +2 cred > pubkey # credential pubkey |
14 | * $ fido2-assert -G -i assert_param /dev/hidraw5 | fido2-assert -V pubkey rs256 | 14 | * $ fido2-assert -G -i assert_param /dev/hidraw5 | fido2-assert -V pubkey rs256 |
15 | * | 15 | * |
16 | * See blurb in fido2-cred.c on how to obtain cred. | 16 | * See blurb in fido2-cred.c on how to obtain cred. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <fido.h> | 19 | #include <fido.h> |
20 | #include <stdio.h> | 20 | #include <stdio.h> |
@@ -28,7 +28,7 @@ void | |||
28 | usage(void) | 28 | usage(void) |
29 | { | 29 | { |
30 | fprintf(stderr, | 30 | fprintf(stderr, |
31 | "usage: fido2-assert -G [-dhpruv] [-i input_file] [-o output_file] device\n" | 31 | "usage: fido2-assert -G [-dhpruv] [-t option] [-i input_file] [-o output_file] device\n" |
32 | " fido2-assert -V [-dhpv] [-i input_file] key_file [type]\n" | 32 | " fido2-assert -V [-dhpv] [-i input_file] key_file [type]\n" |
33 | ); | 33 | ); |
34 | 34 | ||
diff --git a/tools/fido2-attach.sh b/tools/fido2-attach.sh new file mode 100755 index 0000000..d4bc449 --- /dev/null +++ b/tools/fido2-attach.sh | |||
@@ -0,0 +1,14 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # Copyright (c) 2020 Yubico AB. All rights reserved. | ||
4 | # Use of this source code is governed by a BSD-style | ||
5 | # license that can be found in the LICENSE file. | ||
6 | |||
7 | DEV="" | ||
8 | |||
9 | while [ -z "${DEV}" ]; do | ||
10 | sleep .5 | ||
11 | DEV="$(fido2-token -L | sed 's/^\(.*\): .*$/\1/;q')" | ||
12 | done | ||
13 | |||
14 | printf '%s\n' "${DEV}" | ||
diff --git a/tools/fido2-cred.c b/tools/fido2-cred.c index 45efca0..ce277f5 100644 --- a/tools/fido2-cred.c +++ b/tools/fido2-cred.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * $ echo user name >> cred_param | 12 | * $ echo user name >> cred_param |
13 | * $ dd if=/dev/urandom bs=1 count=32 | base64 >> cred_param | 13 | * $ dd if=/dev/urandom bs=1 count=32 | base64 >> cred_param |
14 | * $ fido2-cred -M -i cred_param /dev/hidraw5 | fido2-cred -V -o cred | 14 | * $ fido2-cred -M -i cred_param /dev/hidraw5 | fido2-cred -V -o cred |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <fido.h> | 17 | #include <fido.h> |
18 | #include <stdio.h> | 18 | #include <stdio.h> |
@@ -26,8 +26,8 @@ void | |||
26 | usage(void) | 26 | usage(void) |
27 | { | 27 | { |
28 | fprintf(stderr, | 28 | fprintf(stderr, |
29 | "usage: fido2-cred -M [-dhqruv] [-i input_file] [-o output_file] device [type]\n" | 29 | "usage: fido2-cred -M [-dhqruv] [-c cred_protect] [-i input_file] [-o output_file] device [type]\n" |
30 | " fido2-cred -V [-dhv] [-i input_file] [-o output_file] [type]\n" | 30 | " fido2-cred -V [-dhv] [-c cred_protect] [-i input_file] [-o output_file] [type]\n" |
31 | ); | 31 | ); |
32 | 32 | ||
33 | exit(1); | 33 | exit(1); |
diff --git a/tools/fido2-detach.sh b/tools/fido2-detach.sh new file mode 100755 index 0000000..9cd2e64 --- /dev/null +++ b/tools/fido2-detach.sh | |||
@@ -0,0 +1,12 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # Copyright (c) 2020 Yubico AB. All rights reserved. | ||
4 | # Use of this source code is governed by a BSD-style | ||
5 | # license that can be found in the LICENSE file. | ||
6 | |||
7 | DEV="$(fido2-token -L | sed 's/^\(.*\): .*$/\1/;q')" | ||
8 | |||
9 | while [ -n "${DEV}" ]; do | ||
10 | sleep .5 | ||
11 | DEV="$(fido2-token -L | sed 's/^\(.*\): .*$/\1/;q')" | ||
12 | done | ||
diff --git a/tools/fido2-token.c b/tools/fido2-token.c index 0b02fea..a1e6594 100644 --- a/tools/fido2-token.c +++ b/tools/fido2-token.c | |||
@@ -19,11 +19,11 @@ usage(void) | |||
19 | { | 19 | { |
20 | fprintf(stderr, | 20 | fprintf(stderr, |
21 | "usage: fido2-token [-CR] [-d] device\n" | 21 | "usage: fido2-token [-CR] [-d] device\n" |
22 | " fido2-token -D [-de] -i id device\n" | 22 | " fido2-token -D [-de] -i id device\n" |
23 | " fido2-token -I [-cd] [-k rp_id -i cred_id] device\n" | 23 | " fido2-token -I [-cd] [-k rp_id -i cred_id] device\n" |
24 | " fido2-token -L [-der] [-k rp_id] [device]\n" | 24 | " fido2-token -L [-der] [-k rp_id] [device]\n" |
25 | " fido2-token -S [-de] [-i template_id -n template_name] device\n" | 25 | " fido2-token -S [-de] [-i template_id -n template_name] device\n" |
26 | " fido2-token -V\n" | 26 | " fido2-token -V\n" |
27 | ); | 27 | ); |
28 | 28 | ||
29 | exit(1); | 29 | exit(1); |
diff --git a/tools/fido2-unprot.sh b/tools/fido2-unprot.sh new file mode 100755 index 0000000..44b28b8 --- /dev/null +++ b/tools/fido2-unprot.sh | |||
@@ -0,0 +1,75 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # Copyright (c) 2020 Fabian Henneke. | ||
4 | # Use of this source code is governed by a BSD-style | ||
5 | # license that can be found in the LICENSE file. | ||
6 | |||
7 | |||
8 | if [ $(uname) != "Linux" ] ; then | ||
9 | echo "Can only run on Linux" | ||
10 | exit 1 | ||
11 | fi | ||
12 | |||
13 | TOKEN_VERSION=$(${FIDO_TOOLS_PREFIX}fido2-token -V 2>&1) | ||
14 | if [ $? -ne 0 ] ; then | ||
15 | echo "Please install libfido2 1.5.0 or higher" | ||
16 | exit | ||
17 | fi | ||
18 | |||
19 | TOKEN_VERSION_MAJOR=$(echo "$TOKEN_VERSION" | cut -d. -f1) | ||
20 | TOKEN_VERSION_MINOR=$(echo "$TOKEN_VERSION" | cut -d. -f2) | ||
21 | if [ $TOKEN_VERSION_MAJOR -eq 0 -o $TOKEN_VERSION_MAJOR -eq 1 -a $TOKEN_VERSION_MINOR -lt 5 ] ; then | ||
22 | echo "Please install libfido2 1.5.0 or higher (current version: $TOKEN_VERSION)" | ||
23 | exit 1 | ||
24 | fi | ||
25 | |||
26 | set -e | ||
27 | |||
28 | TOKEN_OUTPUT=$(${FIDO_TOOLS_PREFIX}fido2-token -L) | ||
29 | DEV_PATH_NAMES=$(echo "$TOKEN_OUTPUT" | sed -r 's/^(.*): .*\((.*)\)$/\1 \2/g') | ||
30 | DEV_COUNT=$(echo "$DEV_PATH_NAMES" | wc -l) | ||
31 | |||
32 | for i in $(seq 1 $DEV_COUNT) | ||
33 | do | ||
34 | DEV_PATH_NAME=$(echo "$DEV_PATH_NAMES" | sed "${i}q;d") | ||
35 | DEV_PATH=$(echo "$DEV_PATH_NAME" | cut -d' ' -f1) | ||
36 | DEV_NAME=$(echo "$DEV_PATH_NAME" | cut -d' ' -f1 --complement) | ||
37 | DEV_PRETTY=$(echo "$DEV_NAME (at '$DEV_PATH')") | ||
38 | if expr match "$(${FIDO_TOOLS_PREFIX}fido2-token -I $DEV_PATH)" ".* credMgmt.* clientPin.*\|.* clientPin.* credMgmt.*" > /dev/null ; then | ||
39 | printf "Enter PIN for $DEV_PRETTY once (ignore further prompts): " | ||
40 | stty -echo | ||
41 | read PIN | ||
42 | stty echo | ||
43 | printf "\n" | ||
44 | RESIDENT_RPS=$(echo "${PIN}\n" | setsid -w ${FIDO_TOOLS_PREFIX}fido2-token -L -r $DEV_PATH | cut -d' ' -f3) | ||
45 | printf "\n" | ||
46 | RESIDENT_RPS_COUNT=$(echo "$RESIDENT_RPS" | wc -l) | ||
47 | FOUND=0 | ||
48 | for j in $(seq 1 $DEV_RESIDENT_RPS_COUNT) | ||
49 | do | ||
50 | RESIDENT_RP=$(echo "$RESIDENT_RPS" | sed "${j}q;d") | ||
51 | 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) | ||
52 | printf "\n" | ||
53 | UNPROT_CREDS_COUNT=$(echo "$UNPROT_CREDS" | wc -l) | ||
54 | if [ $UNPROT_CREDS_COUNT -gt 0 ] ; then | ||
55 | FOUND=1 | ||
56 | echo "Unprotected credentials on $DEV_PRETTY for '$RESIDENT_RP':" | ||
57 | echo "$UNPROT_CREDS" | ||
58 | fi | ||
59 | done | ||
60 | if [ $FOUND -eq 0 ] ; then | ||
61 | echo "No unprotected credentials on $DEV_PRETTY" | ||
62 | fi | ||
63 | else | ||
64 | echo "$DEV_PRETTY cannot enumerate credentials" | ||
65 | echo "Discovering unprotected SSH credentials only..." | ||
66 | STUB_HASH=$(echo -n "" | openssl sha256 -binary | base64) | ||
67 | printf "$STUB_HASH\nssh:\n" | ${FIDO_TOOLS_PREFIX}fido2-assert -G -r -t up=false $DEV_PATH 2> /dev/null || ASSERT_EXIT_CODE=$? | ||
68 | if [ $ASSERT_EXIT_CODE -eq 0 ] ; then | ||
69 | echo "Found an unprotected SSH credential on $DEV_PRETTY!" | ||
70 | else | ||
71 | echo "No unprotected SSH credentials (default settings) on $DEV_PRETTY" | ||
72 | fi | ||
73 | fi | ||
74 | printf "\n" | ||
75 | done | ||
diff --git a/tools/include_check.sh b/tools/include_check.sh index 9958c9a..e684d0b 100755 --- a/tools/include_check.sh +++ b/tools/include_check.sh | |||
@@ -1,5 +1,5 @@ | |||
1 | #!/bin/bash | 1 | #!/bin/sh |
2 | # | 2 | |
3 | # Copyright (c) 2019 Yubico AB. All rights reserved. | 3 | # Copyright (c) 2019 Yubico AB. All rights reserved. |
4 | # Use of this source code is governed by a BSD-style | 4 | # Use of this source code is governed by a BSD-style |
5 | # license that can be found in the LICENSE file. | 5 | # license that can be found in the LICENSE file. |
@@ -8,14 +8,14 @@ check() { | |||
8 | for f in $(find $1 -maxdepth 1 -name '*.h'); do | 8 | for f in $(find $1 -maxdepth 1 -name '*.h'); do |
9 | echo "#include \"$f\"" | \ | 9 | echo "#include \"$f\"" | \ |
10 | cc $CFLAGS -Isrc -xc -c - -o /dev/null 2>&1 | 10 | cc $CFLAGS -Isrc -xc -c - -o /dev/null 2>&1 |
11 | echo $f $CFLAGS $? | 11 | echo "$f $CFLAGS $?" |
12 | done | 12 | done |
13 | } | 13 | } |
14 | 14 | ||
15 | check examples | 15 | check examples |
16 | check fuzz | 16 | check fuzz |
17 | check openbsd-compat | 17 | check openbsd-compat |
18 | CFLAGS=-D_FIDO_INTERNAL check src | 18 | CFLAGS="${CFLAGS} -D_FIDO_INTERNAL" check src |
19 | check src/fido.h | 19 | check src/fido.h |
20 | check src/fido | 20 | check src/fido |
21 | check tools | 21 | check tools |
diff --git a/tools/macos_pkg.sh b/tools/macos_pkg.sh deleted file mode 100755 index 4313c27..0000000 --- a/tools/macos_pkg.sh +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | #!/bin/bash -e | ||
2 | # Copyright (c) 2019 Yubico AB. All rights reserved. | ||
3 | # Use of this source code is governed by a BSD-style | ||
4 | # license that can be found in the LICENSE file. | ||
5 | |||
6 | if [[ "$#" -ne 2 ]]; then | ||
7 | echo usage: $0 version directory 1>&2 | ||
8 | exit 1 | ||
9 | fi | ||
10 | |||
11 | V=$1 | ||
12 | D=$2 | ||
13 | |||
14 | FIDO_PATH=$(realpath ${D}/lib/libfido2.${V}.dylib) | ||
15 | CBOR_PATH=$(otool -L "${FIDO_PATH}" | grep cbor | awk '{ print $1 }') | ||
16 | CRYPTO_PATH=$(otool -L "${FIDO_PATH}" | grep crypto | awk '{ print $1 }') | ||
17 | |||
18 | cp -p "${CBOR_PATH}" "${CRYPTO_PATH}" "${D}/lib" | ||
19 | chmod 755 "${D}/lib/"*dylib | ||
20 | rm "${D}/lib/pkgconfig/libfido2.pc" | ||
21 | rmdir "${D}/lib/pkgconfig" | ||
22 | |||
23 | CBOR_NAME=$(echo "${CBOR_PATH}" | grep -o 'libcbor.*dylib') | ||
24 | CRYPTO_NAME=$(echo "${CRYPTO_PATH}" | grep -o 'libcrypto.*dylib') | ||
25 | FIDO_NAME="libfido2.${V}.dylib" | ||
26 | |||
27 | install_name_tool -id "@loader_path/${CBOR_NAME}" "${D}/lib/${CBOR_NAME}" | ||
28 | install_name_tool -id "@loader_path/${CRYPTO_NAME}" "${D}/lib/${CRYPTO_NAME}" | ||
29 | install_name_tool -id "@loader_path/libfido2.${V}.dylib" "${FIDO_PATH}" | ||
30 | |||
31 | install_name_tool -change "${CBOR_PATH}" "@loader_path/${CBOR_NAME}" \ | ||
32 | "${FIDO_PATH}" | ||
33 | install_name_tool -change "${CRYPTO_PATH}" "@loader_path/${CRYPTO_NAME}" \ | ||
34 | "${FIDO_PATH}" | ||
35 | |||
36 | for f in $(find "${D}/bin" -type f); do | ||
37 | FIDO_PATH=$(otool -L "${f}" | grep libfido2 | awk '{ print $1 }') | ||
38 | install_name_tool -change "${CBOR_PATH}" \ | ||
39 | "@executable_path/../lib/${CBOR_NAME}" "${f}" | ||
40 | install_name_tool -change "${CRYPTO_PATH}" \ | ||
41 | "@executable_path/../lib/${CRYPTO_NAME}" "${f}" | ||
42 | install_name_tool -change "${FIDO_PATH}" \ | ||
43 | "@executable_path/../lib/${FIDO_NAME}" "${f}" | ||
44 | done | ||
diff --git a/tools/token.c b/tools/token.c index e65f09f..28e4512 100644 --- a/tools/token.c +++ b/tools/token.c | |||
@@ -112,6 +112,18 @@ print_maxmsgsiz(uint64_t maxmsgsiz) | |||
112 | } | 112 | } |
113 | 113 | ||
114 | static void | 114 | static void |
115 | print_maxcredcntlst(uint64_t maxcredcntlst) | ||
116 | { | ||
117 | printf("maxcredcntlst: %d\n", (int)maxcredcntlst); | ||
118 | } | ||
119 | |||
120 | static void | ||
121 | print_maxcredidlen(uint64_t maxcredidlen) | ||
122 | { | ||
123 | printf("maxcredlen: %d\n", (int)maxcredidlen); | ||
124 | } | ||
125 | |||
126 | static void | ||
115 | print_fwversion(uint64_t fwversion) | 127 | print_fwversion(uint64_t fwversion) |
116 | { | 128 | { |
117 | printf("fwversion: 0x%x\n", (int)fwversion); | 129 | printf("fwversion: 0x%x\n", (int)fwversion); |
@@ -202,6 +214,12 @@ token_info(int argc, char **argv, char *path) | |||
202 | /* print maximum message size */ | 214 | /* print maximum message size */ |
203 | print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci)); | 215 | print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci)); |
204 | 216 | ||
217 | /* print maximum number of credentials allowed in credential lists */ | ||
218 | print_maxcredcntlst(fido_cbor_info_maxcredcntlst(ci)); | ||
219 | |||
220 | /* print maximum length of a credential ID */ | ||
221 | print_maxcredidlen(fido_cbor_info_maxcredidlen(ci)); | ||
222 | |||
205 | /* print firmware version */ | 223 | /* print firmware version */ |
206 | print_fwversion(fido_cbor_info_fwversion(ci)); | 224 | print_fwversion(fido_cbor_info_fwversion(ci)); |
207 | 225 | ||
diff --git a/tools/util.c b/tools/util.c index de70388..7ed59e4 100644 --- a/tools/util.c +++ b/tools/util.c | |||
@@ -16,7 +16,9 @@ | |||
16 | #include <fido/rs256.h> | 16 | #include <fido/rs256.h> |
17 | #include <fido/eddsa.h> | 17 | #include <fido/eddsa.h> |
18 | 18 | ||
19 | #include <errno.h> | ||
19 | #include <fcntl.h> | 20 | #include <fcntl.h> |
21 | #include <limits.h> | ||
20 | #include <stdint.h> | 22 | #include <stdint.h> |
21 | #include <stdio.h> | 23 | #include <stdio.h> |
22 | #include <stdlib.h> | 24 | #include <stdlib.h> |
@@ -78,6 +80,25 @@ open_read(const char *file) | |||
78 | return (f); | 80 | return (f); |
79 | } | 81 | } |
80 | 82 | ||
83 | int | ||
84 | base10(const char *str) | ||
85 | { | ||
86 | char *ep; | ||
87 | long long ll; | ||
88 | |||
89 | ll = strtoll(str, &ep, 10); | ||
90 | if (str == ep || *ep != '\0') | ||
91 | return (-1); | ||
92 | else if (ll == LLONG_MIN && errno == ERANGE) | ||
93 | return (-1); | ||
94 | else if (ll == LLONG_MAX && errno == ERANGE) | ||
95 | return (-1); | ||
96 | else if (ll < 0 || ll > INT_MAX) | ||
97 | return (-1); | ||
98 | |||
99 | return ((int)ll); | ||
100 | } | ||
101 | |||
81 | void | 102 | void |
82 | xxd(const void *buf, size_t count) | 103 | xxd(const void *buf, size_t count) |
83 | { | 104 | { |
@@ -362,3 +383,50 @@ print_cred(FILE *out_f, int type, const fido_cred_t *cred) | |||
362 | 383 | ||
363 | free(id); | 384 | free(id); |
364 | } | 385 | } |
386 | |||
387 | int | ||
388 | cose_type(const char *str, int *type) | ||
389 | { | ||
390 | if (strcmp(str, "es256") == 0) | ||
391 | *type = COSE_ES256; | ||
392 | else if (strcmp(str, "rs256") == 0) | ||
393 | *type = COSE_RS256; | ||
394 | else if (strcmp(str, "eddsa") == 0) | ||
395 | *type = COSE_EDDSA; | ||
396 | else { | ||
397 | *type = 0; | ||
398 | return (-1); | ||
399 | } | ||
400 | |||
401 | return (0); | ||
402 | } | ||
403 | |||
404 | const char * | ||
405 | cose_string(int type) | ||
406 | { | ||
407 | switch (type) { | ||
408 | case COSE_EDDSA: | ||
409 | return ("eddsa"); | ||
410 | case COSE_ES256: | ||
411 | return ("es256"); | ||
412 | case COSE_RS256: | ||
413 | return ("rs256"); | ||
414 | default: | ||
415 | return ("unknown"); | ||
416 | } | ||
417 | } | ||
418 | |||
419 | const char * | ||
420 | prot_string(int prot) | ||
421 | { | ||
422 | switch (prot) { | ||
423 | case FIDO_CRED_PROT_UV_OPTIONAL: | ||
424 | return ("uvopt"); | ||
425 | case FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID: | ||
426 | return ("uvopt+id"); | ||
427 | case FIDO_CRED_PROT_UV_REQUIRED: | ||
428 | return ("uvreq"); | ||
429 | default: | ||
430 | return ("unknown"); | ||
431 | } | ||
432 | } | ||
diff --git a/udev/70-u2f.rules b/udev/70-u2f.rules index 22b47c9..be02043 100644 --- a/udev/70-u2f.rules +++ b/udev/70-u2f.rules | |||
@@ -1,75 +1,175 @@ | |||
1 | # Copyright (c) 2018 Yubico AB. All rights reserved. | 1 | # Copyright (c) 2020 Yubico AB. All rights reserved. |
2 | # Use of this source code is governed by a BSD-style | 2 | # Use of this source code is governed by a BSD-style |
3 | # license that can be found in the LICENSE file. | 3 | # license that can be found in the LICENSE file. |
4 | 4 | ||
5 | # this udev file should be used with udev 188 and newer | 5 | # This file is automatically generated, and should |
6 | ACTION!="add|change", GOTO="u2f_end" | 6 | # be used with udev 188 or newer. |
7 | 7 | ||
8 | # Yubico YubiKey | 8 | ACTION!="add|change", GOTO="fido_end" |
9 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0113|0114|0115|0116|0120|0121|0200|0402|0403|0406|0407|0410", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
10 | 9 | ||
11 | # Happlink (formerly Plug-Up) Security KEY | 10 | # ellipticSecure MIRKey by STMicroelectronics |
12 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2581", ATTRS{idProduct}=="f1d0", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 11 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ac", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
12 | |||
13 | # Unknown product by STMicroelectronics | ||
14 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
15 | |||
16 | # Unknown product by STMicroelectronics | ||
17 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="cdab", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
18 | |||
19 | # Infineon FIDO by Infineon Technologies | ||
20 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="058b", ATTRS{idProduct}=="022d", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
21 | |||
22 | # Kensington VeriMark by Synaptics Inc. | ||
23 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="06cb", ATTRS{idProduct}=="0088", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
24 | |||
25 | # FS ePass FIDO by Feitian Technologies Co., Ltd. | ||
26 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="0850", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
27 | |||
28 | # Unknown product by Feitian Technologies Co., Ltd. | ||
29 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="0852", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
30 | |||
31 | # Unknown product by Feitian Technologies Co., Ltd. | ||
32 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="0853", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
33 | |||
34 | # Unknown product by Feitian Technologies Co., Ltd. | ||
35 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="0854", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
36 | |||
37 | # Unknown product by Feitian Technologies Co., Ltd. | ||
38 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="0856", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
39 | |||
40 | # Unknown product by Feitian Technologies Co., Ltd. | ||
41 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="0858", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
42 | |||
43 | # FS MultiPass FIDO U2F by Feitian Technologies Co., Ltd. | ||
44 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="085a", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
13 | 45 | ||
14 | # Neowave Keydo and Keydo AES | 46 | # Unknown product by Feitian Technologies Co., Ltd. |
15 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1e0d", ATTRS{idProduct}=="f1d0|f1ae", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 47 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="085b", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
16 | 48 | ||
17 | # HyperSecu HyperFIDO | 49 | # Unknown product by Feitian Technologies Co., Ltd. |
18 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e|2ccf", ATTRS{idProduct}=="0880", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 50 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="085d", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
19 | 51 | ||
20 | # Feitian ePass FIDO, BioPass FIDO2 | 52 | # Hypersecu HyperFIDO by Feitian Technologies Co., Ltd. |
21 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="0850|0852|0853|0854|0856|0858|085a|085b|085d", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 53 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="096e", ATTRS{idProduct}=="0880", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
22 | 54 | ||
23 | # JaCarta U2F | 55 | # YubiKey NEO FIDO by Yubico AB |
24 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="24dc", ATTRS{idProduct}=="0101|0501", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 56 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0113", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
25 | 57 | ||
26 | # U2F Zero | 58 | # YubiKey NEO OTP+FIDO by Yubico AB |
59 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0114", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
60 | |||
61 | # YubiKey NEO FIDO+CCID by Yubico AB | ||
62 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0115", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
63 | |||
64 | # YubiKey NEO OTP+FIDO+CCID by Yubico AB | ||
65 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0116", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
66 | |||
67 | # Security Key by Yubico by Yubico AB | ||
68 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0120", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
69 | |||
70 | # Unknown product by Yubico AB | ||
71 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0121", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
72 | |||
73 | # Gnubby U2F by Yubico AB | ||
74 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0200", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
75 | |||
76 | # YubiKey 4 FIDO by Yubico AB | ||
77 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0402", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
78 | |||
79 | # YubiKey 4 OTP+FIDO by Yubico AB | ||
80 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0403", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
81 | |||
82 | # YubiKey 4 FIDO+CCID by Yubico AB | ||
83 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0406", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
84 | |||
85 | # YubiKey 4 OTP+FIDO+CCID by Yubico AB | ||
86 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0407", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
87 | |||
88 | # YubiKey Plus by Yubico AB | ||
89 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0410", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
90 | |||
91 | # U2F Zero by Silicon Laboratories, Inc. | ||
27 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 92 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
28 | 93 | ||
29 | # VASCO SecureClick | 94 | # SoloKeys SoloHacker by pid.codes |
95 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="5070", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
96 | |||
97 | # SoloKeys SoloBoot by pid.codes | ||
98 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="50b0", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
99 | |||
100 | # SatoshiLabs TREZOR by pid.codes | ||
101 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="53c1", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
102 | |||
103 | # Google Titan U2F by Google Inc. | ||
104 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="5026", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
105 | |||
106 | # VASCO SecureClick by VASCO Data Security NV | ||
30 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1a44", ATTRS{idProduct}=="00bb", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 107 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1a44", ATTRS{idProduct}=="00bb", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
31 | 108 | ||
32 | # Bluink Key | 109 | # OnlyKey (FIDO2/U2F) by OpenMoko, Inc. |
33 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2abe", ATTRS{idProduct}=="1002", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 110 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="60fc", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
111 | |||
112 | # Neowave Keydo AES by NEOWAVE | ||
113 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1e0d", ATTRS{idProduct}=="f1ae", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
34 | 114 | ||
35 | # Thetis Key | 115 | # Neowave Keydo by NEOWAVE |
116 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1e0d", ATTRS{idProduct}=="f1d0", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
117 | |||
118 | # Thethis Key by Shenzhen Excelsecu Data Technology Co., Ltd. | ||
36 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1ea8", ATTRS{idProduct}=="f025", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 119 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1ea8", ATTRS{idProduct}=="f025", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
37 | 120 | ||
38 | # Nitrokey FIDO U2F, Nitrokey FIDO2, Safetech SafeKey | 121 | # ExcelSecu FIDO2 Security Key by Shenzhen Excelsecu Data Technology Co., Ltd. |
39 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="4287|42b1|42b3", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 122 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1ea8", ATTRS{idProduct}=="fc25", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
40 | 123 | ||
41 | # Google Titan U2F | 124 | # GoTrust Idem Key by NXP Semiconductors |
42 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="5026", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 125 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1fc9", ATTRS{idProduct}=="f143", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
43 | 126 | ||
44 | # Tomu board + chopstx U2F + SoloKeys | 127 | # Nitrokey FIDO U2F by Flirc |
45 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="cdab|a2ca", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 128 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="4287", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
46 | 129 | ||
47 | # SoloKeys | 130 | # Nitrokey FIDO2 by Flirc |
48 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="5070|50b0", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 131 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="42b1", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
49 | 132 | ||
50 | # Trezor | 133 | # Safetech SafeKey by Flirc |
51 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="534c", ATTRS{idProduct}=="0001", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 134 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="20a0", ATTRS{idProduct}=="42b3", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
52 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="53c1", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
53 | 135 | ||
54 | # Infineon FIDO | 136 | # JaCarta U2F by Aladdin Software Security R.D. |
55 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="058b", ATTRS{idProduct}=="022d", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 137 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="24dc", ATTRS{idProduct}=="0101", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
56 | 138 | ||
57 | # Ledger Nano S and Nano X | 139 | # JaCarta U2F by Aladdin Software Security R.D. |
58 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0001|0004", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 140 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="24dc", ATTRS{idProduct}=="0501", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
59 | 141 | ||
60 | # Kensington VeriMark | 142 | # Happlink Security Key by Plugāup |
61 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="06cb", ATTRS{idProduct}=="0088", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 143 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2581", ATTRS{idProduct}=="f1d0", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
62 | 144 | ||
63 | # Longmai mFIDO | 145 | # Bluink Key by Bluink Ltd |
64 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="4c4d", ATTRS{idProduct}=="f703", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 146 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2abe", ATTRS{idProduct}=="1002", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
65 | 147 | ||
66 | # eWBM FIDO2 - Goldengate 310, 320, 500, 450 | 148 | # Ledger Nano S by LEDGER |
67 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="311f", ATTRS{idProduct}=="4a1a|4c2a|5c2f|f47c", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 149 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0001", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
68 | 150 | ||
69 | # OnlyKey (FIDO2 / U2F) | 151 | # Ledger Nano X by LEDGER |
70 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="60fc", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 152 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2c97", ATTRS{idProduct}=="0004", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
71 | 153 | ||
72 | # GoTrust Idem Key | 154 | # Hypersecu HyperFIDO by Hypersecu Information Systems, Inc. |
73 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1fc9", ATTRS{idProduct}=="f143", TAG+="uaccess", GROUP="plugdev", MODE="0660" | 155 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2ccf", ATTRS{idProduct}=="0880", TAG+="uaccess", GROUP="plugdev", MODE="0660" |
156 | |||
157 | # eWBM FIDO2 Goldengate 310 by eWBM Co., Ltd. | ||
158 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="311f", ATTRS{idProduct}=="4a1a", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
159 | |||
160 | # eWBM FIDO2 Goldengate 320 by eWBM Co., Ltd. | ||
161 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="311f", ATTRS{idProduct}=="4c2a", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
162 | |||
163 | # eWBM FIDO2 Goldengate 500 by eWBM Co., Ltd. | ||
164 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="311f", ATTRS{idProduct}=="5c2f", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
165 | |||
166 | # eWBM FIDO2 Goldengate 450 by eWBM Co., Ltd. | ||
167 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="311f", ATTRS{idProduct}=="f47c", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
168 | |||
169 | # Longmai mFIDO by Unknown vendor | ||
170 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="4c4d", ATTRS{idProduct}=="f703", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
171 | |||
172 | # SatoshiLabs TREZOR by SatoshiLabs | ||
173 | KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="534c", ATTRS{idProduct}=="0001", TAG+="uaccess", GROUP="plugdev", MODE="0660" | ||
74 | 174 | ||
75 | LABEL="u2f_end" | 175 | LABEL="fido_end" |
diff --git a/udev/check.sh b/udev/check.sh new file mode 100755 index 0000000..97bbb97 --- /dev/null +++ b/udev/check.sh | |||
@@ -0,0 +1,31 @@ | |||
1 | #!/bin/sh -u | ||
2 | |||
3 | # Copyright (c) 2020 Yubico AB. All rights reserved. | ||
4 | # Use of this source code is governed by a BSD-style | ||
5 | # license that can be found in the LICENSE file. | ||
6 | |||
7 | sort_by_id() { | ||
8 | awk '{ printf "%d\n", $3 }' | sort -Cnu | ||
9 | } | ||
10 | |||
11 | if ! grep '^vendor' "$1" | sort_by_id; then | ||
12 | echo unsorted vendor section 1>&2 | ||
13 | exit 1 | ||
14 | fi | ||
15 | |||
16 | VENDORS=$(grep '^vendor' "$1" | awk '{ print $2 }') | ||
17 | PRODUCTS=$(grep '^product' "$1" | awk '{ print $2 }' | uniq) | ||
18 | |||
19 | if [ "${VENDORS}" != "${PRODUCTS}" ]; then | ||
20 | echo vendors: "$(echo "${VENDORS}" | tr '\n' ',')" 1>&2 | ||
21 | echo products: "$(echo "${PRODUCTS}" | tr '\n' ',')" 1>&2 | ||
22 | echo vendors and products in different order 1>&2 | ||
23 | exit 2 | ||
24 | fi | ||
25 | |||
26 | for v in ${VENDORS}; do | ||
27 | if ! grep "^product ${v}" "$1" | sort_by_id; then | ||
28 | echo "${v}": unsorted product section 1>&2 | ||
29 | exit 3 | ||
30 | fi | ||
31 | done | ||
diff --git a/udev/fidodevs b/udev/fidodevs new file mode 100644 index 0000000..e149964 --- /dev/null +++ b/udev/fidodevs | |||
@@ -0,0 +1,110 @@ | |||
1 | # Copyright (c) 2020 Yubico AB. All rights reserved. | ||
2 | # Use of this source code is governed by a BSD-style | ||
3 | # license that can be found in the LICENSE file. | ||
4 | |||
5 | # After modifying this file, regenerate 70-u2f.rules: | ||
6 | # ./genrules.awk fidodevs > 70-u2f.rules | ||
7 | |||
8 | # List of known vendors. Sorted by vendor ID. | ||
9 | |||
10 | vendor STMICRO 0x0483 STMicroelectronics | ||
11 | vendor INFINEON 0x058b Infineon Technologies | ||
12 | vendor SYNAPTICS 0x06cb Synaptics Inc. | ||
13 | vendor FEITIAN 0x096e Feitian Technologies Co., Ltd. | ||
14 | vendor YUBICO 0x1050 Yubico AB | ||
15 | vendor SILICON 0x10c4 Silicon Laboratories, Inc. | ||
16 | vendor PIDCODES 0x1209 pid.codes | ||
17 | vendor GOOGLE 0x18d1 Google Inc. | ||
18 | vendor VASCO 0x1a44 VASCO Data Security NV | ||
19 | vendor OPENMOKO 0x1d50 OpenMoko, Inc. | ||
20 | vendor NEOWAVE 0x1e0d NEOWAVE | ||
21 | vendor EXCELSECU 0x1ea8 Shenzhen Excelsecu Data Technology Co., Ltd. | ||
22 | vendor NXP 0x1fc9 NXP Semiconductors | ||
23 | vendor FLIRC 0x20a0 Flirc | ||
24 | vendor ALLADIN 0x24dc Aladdin Software Security R.D. | ||
25 | vendor PLUGUP 0x2581 Plugāup | ||
26 | vendor BLUINK 0x2abe Bluink Ltd | ||
27 | vendor LEDGER 0x2c97 LEDGER | ||
28 | vendor HYPERSECU 0x2ccf Hypersecu Information Systems, Inc. | ||
29 | vendor EWBM 0x311f eWBM Co., Ltd. | ||
30 | vendor UNKNOWN1 0x4c4d Unknown vendor | ||
31 | vendor SATOSHI 0x534c SatoshiLabs | ||
32 | |||
33 | # List of known products. Grouped by vendor; sorted by product ID. | ||
34 | |||
35 | product STMICRO 0xa2ac ellipticSecure MIRKey | ||
36 | product STMICRO 0xa2ca Unknown product | ||
37 | product STMICRO 0xcdab Unknown product | ||
38 | |||
39 | product INFINEON 0x022d Infineon FIDO | ||
40 | |||
41 | product SYNAPTICS 0x0088 Kensington VeriMark | ||
42 | |||
43 | product FEITIAN 0x0850 FS ePass FIDO | ||
44 | product FEITIAN 0x0852 Unknown product | ||
45 | product FEITIAN 0x0853 Unknown product | ||
46 | product FEITIAN 0x0854 Unknown product | ||
47 | product FEITIAN 0x0856 Unknown product | ||
48 | product FEITIAN 0x0858 Unknown product | ||
49 | product FEITIAN 0x085a FS MultiPass FIDO U2F | ||
50 | product FEITIAN 0x085b Unknown product | ||
51 | product FEITIAN 0x085d Unknown product | ||
52 | product FEITIAN 0x0880 Hypersecu HyperFIDO | ||
53 | |||
54 | product YUBICO 0x0113 YubiKey NEO FIDO | ||
55 | product YUBICO 0x0114 YubiKey NEO OTP+FIDO | ||
56 | product YUBICO 0x0115 YubiKey NEO FIDO+CCID | ||
57 | product YUBICO 0x0116 YubiKey NEO OTP+FIDO+CCID | ||
58 | product YUBICO 0x0120 Security Key by Yubico | ||
59 | product YUBICO 0x0121 Unknown product | ||
60 | product YUBICO 0x0200 Gnubby U2F | ||
61 | product YUBICO 0x0402 YubiKey 4 FIDO | ||
62 | product YUBICO 0x0403 YubiKey 4 OTP+FIDO | ||
63 | product YUBICO 0x0406 YubiKey 4 FIDO+CCID | ||
64 | product YUBICO 0x0407 YubiKey 4 OTP+FIDO+CCID | ||
65 | product YUBICO 0x0410 YubiKey Plus | ||
66 | |||
67 | product SILICON 0x8acf U2F Zero | ||
68 | |||
69 | product PIDCODES 0x5070 SoloKeys SoloHacker | ||
70 | product PIDCODES 0x50b0 SoloKeys SoloBoot | ||
71 | product PIDCODES 0x53c1 SatoshiLabs TREZOR | ||
72 | |||
73 | product GOOGLE 0x5026 Google Titan U2F | ||
74 | |||
75 | product VASCO 0x00bb VASCO SecureClick | ||
76 | |||
77 | product OPENMOKO 0x60fc OnlyKey (FIDO2/U2F) | ||
78 | |||
79 | product NEOWAVE 0xf1ae Neowave Keydo AES | ||
80 | product NEOWAVE 0xf1d0 Neowave Keydo | ||
81 | |||
82 | product EXCELSECU 0xf025 Thethis Key | ||
83 | product EXCELSECU 0xfc25 ExcelSecu FIDO2 Security Key | ||
84 | |||
85 | product NXP 0xf143 GoTrust Idem Key | ||
86 | |||
87 | product FLIRC 0x4287 Nitrokey FIDO U2F | ||
88 | product FLIRC 0x42b1 Nitrokey FIDO2 | ||
89 | product FLIRC 0x42b3 Safetech SafeKey | ||
90 | |||
91 | product ALLADIN 0x0101 JaCarta U2F | ||
92 | product ALLADIN 0x0501 JaCarta U2F | ||
93 | |||
94 | product PLUGUP 0xf1d0 Happlink Security Key | ||
95 | |||
96 | product BLUINK 0x1002 Bluink Key | ||
97 | |||
98 | product LEDGER 0x0001 Ledger Nano S | ||
99 | product LEDGER 0x0004 Ledger Nano X | ||
100 | |||
101 | product HYPERSECU 0x0880 Hypersecu HyperFIDO | ||
102 | |||
103 | product EWBM 0x4a1a eWBM FIDO2 Goldengate 310 | ||
104 | product EWBM 0x4c2a eWBM FIDO2 Goldengate 320 | ||
105 | product EWBM 0x5c2f eWBM FIDO2 Goldengate 500 | ||
106 | product EWBM 0xf47c eWBM FIDO2 Goldengate 450 | ||
107 | |||
108 | product UNKNOWN1 0xf703 Longmai mFIDO | ||
109 | |||
110 | product SATOSHI 0x0001 SatoshiLabs TREZOR | ||
diff --git a/udev/genrules.awk b/udev/genrules.awk new file mode 100755 index 0000000..2a85c7c --- /dev/null +++ b/udev/genrules.awk | |||
@@ -0,0 +1,55 @@ | |||
1 | #!/usr/bin/awk -f | ||
2 | |||
3 | # Copyright (c) 2020 Yubico AB. All rights reserved. | ||
4 | # Use of this source code is governed by a BSD-style | ||
5 | # license that can be found in the LICENSE file. | ||
6 | |||
7 | NR == 1 { | ||
8 | print "# Copyright (c) 2020 Yubico AB. All rights reserved." | ||
9 | print "# Use of this source code is governed by a BSD-style" | ||
10 | print "# license that can be found in the LICENSE file." | ||
11 | print "" | ||
12 | print "# This file is automatically generated, and should" | ||
13 | print "# be used with udev 188 or newer." | ||
14 | print "" | ||
15 | print "ACTION!=\"add|change\", GOTO=\"fido_end\"" | ||
16 | |||
17 | next | ||
18 | } | ||
19 | |||
20 | $1 == "vendor" { | ||
21 | sub("0x", "", $3) | ||
22 | vendors[$2, "id"] = $3 | ||
23 | |||
24 | f = 4 | ||
25 | while (f <= NF) { | ||
26 | vendors[$2, "name"] = vendors[$2, "name"] " " $f | ||
27 | f++ | ||
28 | } | ||
29 | } | ||
30 | |||
31 | $1 == "product" { | ||
32 | sub("0x", "", $3) | ||
33 | name = "" | ||
34 | |||
35 | f = 4 | ||
36 | while (f <= NF) { | ||
37 | name = name " " $f | ||
38 | f++ | ||
39 | } | ||
40 | |||
41 | line = "\n#" name " by" vendors[$2, "name"]"\n" | ||
42 | line = line"KERNEL==\"hidraw*\"" | ||
43 | line = line", SUBSYSTEM==\"hidraw\"" | ||
44 | line = line", ATTRS{idVendor}==\""vendors[$2, "id"]"\"" | ||
45 | line = line", ATTRS{idProduct}==\""$3"\"" | ||
46 | line = line", TAG+=\"uaccess\"" | ||
47 | line = line", GROUP=\"plugdev\"" | ||
48 | line = line", MODE=\"0660\"" | ||
49 | |||
50 | print line | ||
51 | } | ||
52 | |||
53 | END { | ||
54 | print "\nLABEL=\"fido_end\"" | ||
55 | } | ||
diff --git a/windows/build.ps1 b/windows/build.ps1 index aaa848d..a65fdd9 100644 --- a/windows/build.ps1 +++ b/windows/build.ps1 | |||
@@ -12,11 +12,11 @@ $ErrorActionPreference = "Continue" | |||
12 | # LibreSSL coordinates. | 12 | # LibreSSL coordinates. |
13 | New-Variable -Name 'LIBRESSL_URL' ` | 13 | New-Variable -Name 'LIBRESSL_URL' ` |
14 | -Value 'https://ftp.openbsd.org/pub/OpenBSD/LibreSSL' -Option Constant | 14 | -Value 'https://ftp.openbsd.org/pub/OpenBSD/LibreSSL' -Option Constant |
15 | New-Variable -Name 'LIBRESSL' -Value 'libressl-3.0.2' -Option Constant | 15 | New-Variable -Name 'LIBRESSL' -Value 'libressl-3.1.4' -Option Constant |
16 | 16 | ||
17 | # libcbor coordinates. | 17 | # libcbor coordinates. |
18 | New-Variable -Name 'LIBCBOR' -Value 'libcbor-0.5.0' -Option Constant | 18 | New-Variable -Name 'LIBCBOR' -Value 'libcbor-0.7.0' -Option Constant |
19 | New-Variable -Name 'LIBCBOR_BRANCH' -Value 'v0.5.0' -Option Constant | 19 | New-Variable -Name 'LIBCBOR_BRANCH' -Value 'v0.7.0' -Option Constant |
20 | New-Variable -Name 'LIBCBOR_GIT' -Value 'https://github.com/pjk/libcbor' ` | 20 | New-Variable -Name 'LIBCBOR_GIT' -Value 'https://github.com/pjk/libcbor' ` |
21 | -Option Constant | 21 | -Option Constant |
22 | 22 | ||
@@ -149,7 +149,7 @@ Function Build(${OUTPUT}, ${GENERATOR}, ${ARCH}) { | |||
149 | -DCMAKE_INSTALL_PREFIX="${OUTPUT}" | 149 | -DCMAKE_INSTALL_PREFIX="${OUTPUT}" |
150 | & $CMake --build . --config Release | 150 | & $CMake --build . --config Release |
151 | & $CMake --build . --config Release --target install | 151 | & $CMake --build . --config Release --target install |
152 | "cbor.dll", "crypto-45.dll" | %{ Copy-Item "${OUTPUT}\bin\$_" ` | 152 | "cbor.dll", "crypto-46.dll" | %{ Copy-Item "${OUTPUT}\bin\$_" ` |
153 | -Destination "examples\Release" } | 153 | -Destination "examples\Release" } |
154 | } | 154 | } |
155 | 155 | ||
@@ -161,15 +161,15 @@ Function Package-Headers() { | |||
161 | Function Package-Libraries(${SRC}, ${DEST}) { | 161 | Function Package-Libraries(${SRC}, ${DEST}) { |
162 | Copy-Item "${SRC}\bin\cbor.dll" "${DEST}" -ErrorAction Stop | 162 | Copy-Item "${SRC}\bin\cbor.dll" "${DEST}" -ErrorAction Stop |
163 | Copy-Item "${SRC}\lib\cbor.lib" "${DEST}" -ErrorAction Stop | 163 | Copy-Item "${SRC}\lib\cbor.lib" "${DEST}" -ErrorAction Stop |
164 | Copy-Item "${SRC}\bin\crypto-45.dll" "${DEST}" -ErrorAction Stop | 164 | Copy-Item "${SRC}\bin\crypto-46.dll" "${DEST}" -ErrorAction Stop |
165 | Copy-Item "${SRC}\lib\crypto-45.lib" "${DEST}" -ErrorAction Stop | 165 | Copy-Item "${SRC}\lib\crypto-46.lib" "${DEST}" -ErrorAction Stop |
166 | Copy-Item "${SRC}\lib\fido2.dll" "${DEST}" -ErrorAction Stop | 166 | Copy-Item "${SRC}\lib\fido2.dll" "${DEST}" -ErrorAction Stop |
167 | Copy-Item "${SRC}\lib\fido2.lib" "${DEST}" -ErrorAction Stop | 167 | Copy-Item "${SRC}\lib\fido2.lib" "${DEST}" -ErrorAction Stop |
168 | } | 168 | } |
169 | 169 | ||
170 | Function Package-PDBs(${SRC}, ${DEST}) { | 170 | Function Package-PDBs(${SRC}, ${DEST}) { |
171 | Copy-Item "${SRC}\${LIBRESSL}\crypto\crypto.dir\Release\vc142.pdb" ` | 171 | Copy-Item "${SRC}\${LIBRESSL}\crypto\crypto.dir\Release\vc142.pdb" ` |
172 | "${DEST}\crypto-45.pdb" -ErrorAction Stop | 172 | "${DEST}\crypto-46.pdb" -ErrorAction Stop |
173 | Copy-Item "${SRC}\${LIBCBOR}\src\cbor_shared.dir\Release\vc142.pdb" ` | 173 | Copy-Item "${SRC}\${LIBCBOR}\src\cbor_shared.dir\Release\vc142.pdb" ` |
174 | "${DEST}\cbor.pdb" -ErrorAction Stop | 174 | "${DEST}\cbor.pdb" -ErrorAction Stop |
175 | Copy-Item "${SRC}\src\fido2_shared.dir\Release\vc142.pdb" ` | 175 | Copy-Item "${SRC}\src\fido2_shared.dir\Release\vc142.pdb" ` |