Vendor import of libfido2 1.9.0
This commit is contained in:
parent
a58dee945a
commit
7248ec417c
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
# Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
@ -28,7 +28,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(CMAKE_COLOR_MAKEFILE OFF)
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(FIDO_MAJOR "1")
|
||||
set(FIDO_MINOR "8")
|
||||
set(FIDO_MINOR "9")
|
||||
set(FIDO_PATCH "0")
|
||||
set(FIDO_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}.${FIDO_PATCH})
|
||||
|
||||
@ -68,10 +68,11 @@ if(NOT MSVC)
|
||||
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_DARWIN_C_SOURCE")
|
||||
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D__STDC_WANT_LIB_EXT1__=1")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set(NFC_LINUX OFF)
|
||||
set(NFC_LINUX ON)
|
||||
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_GNU_SOURCE")
|
||||
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D_DEFAULT_SOURCE")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "MidnightBSD")
|
||||
set(FIDO_CFLAGS "${FIDO_CFLAGS} -D__BSD_VISIBLE=1")
|
||||
endif()
|
||||
set(FIDO_CFLAGS "${FIDO_CFLAGS} -std=c99")
|
||||
@ -79,7 +80,7 @@ if(NOT MSVC)
|
||||
endif()
|
||||
|
||||
check_c_compiler_flag("-Wshorten-64-to-32" HAVE_SHORTEN_64_TO_32)
|
||||
check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL)
|
||||
check_c_compiler_flag("-Werror -fstack-protector-all" HAVE_STACK_PROTECTOR_ALL)
|
||||
|
||||
check_include_files(cbor.h HAVE_CBOR_H)
|
||||
check_include_files(endian.h HAVE_ENDIAN_H)
|
||||
@ -88,7 +89,6 @@ check_include_files(openssl/opensslv.h HAVE_OPENSSLV_H)
|
||||
check_include_files(signal.h HAVE_SIGNAL_H)
|
||||
check_include_files(sys/random.h HAVE_SYS_RANDOM_H)
|
||||
check_include_files(unistd.h HAVE_UNISTD_H)
|
||||
check_include_files("windows.h;webauthn.h" HAVE_WEBAUTHN_H)
|
||||
|
||||
check_symbol_exists(arc4random_buf stdlib.h HAVE_ARC4RANDOM_BUF)
|
||||
check_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME)
|
||||
@ -101,17 +101,13 @@ check_symbol_exists(getrandom sys/random.h HAVE_GETRANDOM)
|
||||
check_symbol_exists(memset_s string.h HAVE_MEMSET_S)
|
||||
check_symbol_exists(readpassphrase readpassphrase.h HAVE_READPASSPHRASE)
|
||||
check_symbol_exists(recallocarray stdlib.h HAVE_RECALLOCARRAY)
|
||||
check_symbol_exists(sigaction signal.h HAVE_SIGACTION)
|
||||
check_symbol_exists(strlcat string.h HAVE_STRLCAT)
|
||||
check_symbol_exists(strlcpy string.h HAVE_STRLCPY)
|
||||
check_symbol_exists(strsep string.h HAVE_STRSEP)
|
||||
check_symbol_exists(sysconf unistd.h HAVE_SYSCONF)
|
||||
check_symbol_exists(timespecsub sys/time.h HAVE_TIMESPECSUB)
|
||||
check_symbol_exists(timingsafe_bcmp string.h HAVE_TIMINGSAFE_BCMP)
|
||||
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES signal.h)
|
||||
check_type_size("sig_atomic_t" HAVE_SIG_ATOMIC_T)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
try_compile(HAVE_POSIX_IOCTL
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/posix_ioctl_check.o"
|
||||
@ -134,16 +130,15 @@ list(APPEND CHECK_VARIABLES
|
||||
HAVE_POSIX_IOCTL
|
||||
HAVE_READPASSPHRASE
|
||||
HAVE_RECALLOCARRAY
|
||||
HAVE_SIGACTION
|
||||
HAVE_SIGNAL_H
|
||||
HAVE_STRLCAT
|
||||
HAVE_STRLCPY
|
||||
HAVE_STRSEP
|
||||
HAVE_SYSCONF
|
||||
HAVE_SYS_RANDOM_H
|
||||
HAVE_TIMESPECSUB
|
||||
HAVE_TIMINGSAFE_BCMP
|
||||
HAVE_UNISTD_H
|
||||
HAVE_WEBAUTHN_H
|
||||
)
|
||||
|
||||
foreach(v ${CHECK_VARIABLES})
|
||||
@ -156,26 +151,26 @@ if(HAVE_EXPLICIT_BZERO AND NOT LIBFUZZER)
|
||||
add_definitions(-DHAVE_EXPLICIT_BZERO)
|
||||
endif()
|
||||
|
||||
if(HAVE_SIGACTION AND (NOT HAVE_SIG_ATOMIC_T STREQUAL ""))
|
||||
add_definitions(-DSIGNAL_EXAMPLE)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
add_definitions(-DHAVE_DEV_URANDOM)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if((NOT CBOR_INCLUDE_DIRS) OR (NOT CBOR_LIBRARY_DIRS) OR
|
||||
(NOT CRYPTO_INCLUDE_DIRS) OR (NOT CRYPTO_LIBRARY_DIRS) OR
|
||||
(NOT ZLIB_INCLUDE_DIRS) OR (NOT ZLIB_LIBRARY_DIRS))
|
||||
message(FATAL_ERROR "please provide definitions for "
|
||||
"{CBOR,CRYPTO,ZLIB}_{INCLUDE,LIBRARY}_DIRS when building "
|
||||
"under msvc")
|
||||
(NOT CBOR_BIN_DIRS) OR (NOT CRYPTO_INCLUDE_DIRS) OR
|
||||
(NOT CRYPTO_LIBRARY_DIRS) OR (NOT CRYPTO_BIN_DIRS) OR
|
||||
(NOT ZLIB_INCLUDE_DIRS) OR (NOT ZLIB_LIBRARY_DIRS) OR
|
||||
(NOT ZLIB_BIN_DIRS))
|
||||
message(FATAL_ERROR "please define "
|
||||
"{CBOR,CRYPTO,ZLIB}_{INCLUDE,LIBRARY,BIN}_DIRS when "
|
||||
"building under msvc")
|
||||
endif()
|
||||
set(CBOR_LIBRARIES cbor)
|
||||
set(ZLIB_LIBRARIES zlib)
|
||||
set(CRYPTO_LIBRARIES crypto-46)
|
||||
set(MSVC_DISABLED_WARNINGS_LIST
|
||||
"C4152" # nonstandard extension used: function/data pointer
|
||||
# conversion in expression;
|
||||
"C4200" # nonstandard extension used: zero-sized array in
|
||||
# struct/union;
|
||||
"C4204" # nonstandard extension used: non-constant aggregate
|
||||
@ -191,12 +186,10 @@ if(MSVC)
|
||||
${MSVC_DISABLED_WARNINGS_LIST})
|
||||
string(REGEX REPLACE "[/-]W[1234][ ]?" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP -W4 -WX ${MSVC_DISABLED_WARNINGS_STR}")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7 /guard:cf /sdl /RTCcsu")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od /Z7 /guard:cf /sdl /RTCcsu")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi /guard:cf /sdl")
|
||||
if (HAVE_WEBAUTHN_H)
|
||||
add_definitions(-DUSE_WINHELLO)
|
||||
set(USE_WINHELLO ON)
|
||||
endif()
|
||||
add_definitions(-DUSE_WINHELLO)
|
||||
set(USE_WINHELLO ON)
|
||||
else()
|
||||
include(FindPkgConfig)
|
||||
pkg_search_module(CBOR libcbor)
|
||||
@ -275,9 +268,14 @@ else()
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2")
|
||||
|
||||
if(CRYPTO_VERSION VERSION_GREATER_EQUAL 3.0)
|
||||
add_definitions(-DOPENSSL_API_COMPAT=0x10100000L)
|
||||
endif()
|
||||
|
||||
if(FUZZ)
|
||||
add_definitions(-DFIDO_FUZZ)
|
||||
endif()
|
||||
|
||||
if(LIBFUZZER)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link")
|
||||
endif()
|
||||
@ -404,10 +402,9 @@ if(BUILD_MANPAGES)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
if(NOT LIBFUZZER AND NOT FUZZ)
|
||||
subdirs(regress)
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT FUZZ)
|
||||
enable_testing()
|
||||
subdirs(regress)
|
||||
endif()
|
||||
if(FUZZ)
|
||||
subdirs(fuzz)
|
||||
|
22
NEWS
22
NEWS
@ -1,3 +1,25 @@
|
||||
* Version 1.9.0 (2021-10-27)
|
||||
** Enabled NFC support on Linux.
|
||||
** Added OpenSSL 3.0 compatibility.
|
||||
** Removed OpenSSL 1.0 compatibility.
|
||||
** Support for FIDO 2.1 "minPinLength" extension.
|
||||
** Support for COSE_EDDSA, COSE_ES256, and COSE_RS1 attestation.
|
||||
** Support for TPM 2.0 attestation.
|
||||
** Support for device timeouts; see fido_dev_set_timeout().
|
||||
** New API calls:
|
||||
- es256_pk_from_EVP_PKEY;
|
||||
- fido_cred_attstmt_len;
|
||||
- fido_cred_attstmt_ptr;
|
||||
- fido_cred_pin_minlen;
|
||||
- fido_cred_set_attstmt;
|
||||
- fido_cred_set_pin_minlen;
|
||||
- fido_dev_set_pin_minlen_rpid;
|
||||
- fido_dev_set_timeout;
|
||||
- rs256_pk_from_EVP_PKEY.
|
||||
** Reliability and portability fixes.
|
||||
** Better handling of HID devices without identification strings; gh#381.
|
||||
** Fixed detection of Windows's native webauthn API; gh#382.
|
||||
|
||||
* Version 1.8.0 (2021-07-22)
|
||||
** Dropped 'Requires.private' entry from pkg-config file.
|
||||
** Better support for FIDO 2.1 authenticators.
|
||||
|
@ -23,6 +23,8 @@ file for the full license text.
|
||||
|
||||
*libfido2* is known to work on Linux, macOS, Windows, OpenBSD, and FreeBSD.
|
||||
|
||||
NFC support is available on Linux and Windows.
|
||||
|
||||
=== Documentation
|
||||
|
||||
Documentation is available in troff and HTML formats. An
|
||||
@ -40,7 +42,7 @@ is also available.
|
||||
|
||||
==== Releases
|
||||
|
||||
The current release of *libfido2* is 1.8.0. Please consult Yubico's
|
||||
The current release of *libfido2* is 1.9.0. Please consult Yubico's
|
||||
https://developers.yubico.com/libfido2/Releases[release page] for source
|
||||
and binary releases.
|
||||
|
||||
@ -66,7 +68,7 @@ Follow the instructions for Ubuntu 18.04 (Bionic) below.
|
||||
|
||||
Or from source, on UNIX-like systems:
|
||||
|
||||
$ (rm -rf build && mkdir build && cd build && cmake ..)
|
||||
$ cmake -B build
|
||||
$ make -C build
|
||||
$ sudo make -C build install
|
||||
|
||||
@ -75,7 +77,8 @@ https://www.freedesktop.org/wiki/Software/pkg-config/[pkg-config] may need to
|
||||
be installed, or the PKG_CONFIG_PATH environment variable set.
|
||||
|
||||
*libfido2* depends on https://github.com/pjk/libcbor[libcbor],
|
||||
https://www.openssl.org[OpenSSL], and https://zlib.net[zlib]. On Linux, libudev
|
||||
https://www.openssl.org[OpenSSL] 1.1 or newer, and https://zlib.net[zlib].
|
||||
On Linux, libudev
|
||||
(part of https://www.freedesktop.org/wiki/Software/systemd[systemd]) is also
|
||||
required.
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -20,7 +20,7 @@
|
||||
#include "../openbsd-compat/openbsd-compat.h"
|
||||
#include "extern.h"
|
||||
|
||||
static const unsigned char cdh[32] = {
|
||||
static const unsigned char cd[32] = {
|
||||
0xec, 0x8d, 0x8f, 0x78, 0x42, 0x4a, 0x2b, 0xb7,
|
||||
0x82, 0x34, 0xaa, 0xca, 0x07, 0xa1, 0xf6, 0x56,
|
||||
0x42, 0x1c, 0xb6, 0xf6, 0xb3, 0x00, 0x86, 0x52,
|
||||
@ -106,10 +106,9 @@ verify_assert(int type, const unsigned char *authdata_ptr, size_t authdata_len,
|
||||
errx(1, "fido_assert_new");
|
||||
|
||||
/* client data hash */
|
||||
r = fido_assert_set_clientdata_hash(assert, cdh, sizeof(cdh));
|
||||
r = fido_assert_set_clientdata(assert, cd, sizeof(cd));
|
||||
if (r != FIDO_OK)
|
||||
errx(1, "fido_assert_set_clientdata_hash: %s (0x%x)",
|
||||
fido_strerr(r), r);
|
||||
errx(1, "fido_assert_set_clientdata: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
/* relying party */
|
||||
r = fido_assert_set_rp(assert, "localhost");
|
||||
@ -166,7 +165,7 @@ main(int argc, char **argv)
|
||||
const char *blobkey_out = NULL;
|
||||
const char *hmac_out = NULL;
|
||||
unsigned char *body = NULL;
|
||||
long long seconds = 0;
|
||||
long long ms = 0;
|
||||
size_t len;
|
||||
int type = COSE_ES256;
|
||||
int ext = 0;
|
||||
@ -182,16 +181,12 @@ main(int argc, char **argv)
|
||||
pin = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
#ifndef SIGNAL_EXAMPLE
|
||||
(void)seconds;
|
||||
errx(1, "-T not supported");
|
||||
#else
|
||||
if (base10(optarg, &seconds) < 0)
|
||||
if (base10(optarg, &ms) < 0)
|
||||
errx(1, "base10: %s", optarg);
|
||||
if (seconds <= 0 || seconds > 30)
|
||||
if (ms <= 0 || ms > 30)
|
||||
errx(1, "-T: %s must be in (0,30]", optarg);
|
||||
ms *= 1000; /* seconds to milliseconds */
|
||||
break;
|
||||
#endif
|
||||
case 'a':
|
||||
if (read_blob(optarg, &body, &len) < 0)
|
||||
errx(1, "read_blob: %s", optarg);
|
||||
@ -262,10 +257,9 @@ main(int argc, char **argv)
|
||||
fido_dev_force_u2f(dev);
|
||||
|
||||
/* client data hash */
|
||||
r = fido_assert_set_clientdata_hash(assert, cdh, sizeof(cdh));
|
||||
r = fido_assert_set_clientdata(assert, cd, sizeof(cd));
|
||||
if (r != FIDO_OK)
|
||||
errx(1, "fido_assert_set_clientdata_hash: %s (0x%x)",
|
||||
fido_strerr(r), r);
|
||||
errx(1, "fido_assert_set_clientdata: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
/* relying party */
|
||||
r = fido_assert_set_rp(assert, "localhost");
|
||||
@ -286,20 +280,12 @@ main(int argc, char **argv)
|
||||
if (uv && (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK)
|
||||
errx(1, "fido_assert_set_uv: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
#ifdef SIGNAL_EXAMPLE
|
||||
prepare_signal_handler(SIGINT);
|
||||
if (seconds) {
|
||||
prepare_signal_handler(SIGALRM);
|
||||
alarm((unsigned)seconds);
|
||||
}
|
||||
#endif
|
||||
/* timeout */
|
||||
if (ms != 0 && (r = fido_dev_set_timeout(dev, (int)ms)) != FIDO_OK)
|
||||
errx(1, "fido_dev_set_timeout: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
r = fido_dev_get_assert(dev, assert, pin);
|
||||
if (r != FIDO_OK) {
|
||||
#ifdef SIGNAL_EXAMPLE
|
||||
if (got_signal)
|
||||
fido_dev_cancel(dev);
|
||||
#endif
|
||||
if ((r = fido_dev_get_assert(dev, assert, pin)) != FIDO_OK) {
|
||||
fido_dev_cancel(dev);
|
||||
errx(1, "fido_dev_get_assert: %s (0x%x)", fido_strerr(r), r);
|
||||
}
|
||||
|
||||
|
110
examples/cred.c
110
examples/cred.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -17,7 +17,7 @@
|
||||
#include "../openbsd-compat/openbsd-compat.h"
|
||||
#include "extern.h"
|
||||
|
||||
static const unsigned char cdh[32] = {
|
||||
static const unsigned char cd[32] = {
|
||||
0xf9, 0x64, 0x57, 0xe7, 0x2d, 0x97, 0xf6, 0xbb,
|
||||
0xdd, 0xd7, 0xfb, 0x06, 0x37, 0x62, 0xea, 0x26,
|
||||
0x20, 0x44, 0x8e, 0x69, 0x7c, 0x03, 0xf2, 0x31,
|
||||
@ -42,9 +42,8 @@ usage(void)
|
||||
|
||||
static void
|
||||
verify_cred(int type, const char *fmt, const unsigned char *authdata_ptr,
|
||||
size_t authdata_len, const unsigned char *x509_ptr, size_t x509_len,
|
||||
const unsigned char *sig_ptr, size_t sig_len, bool rk, bool uv, int ext,
|
||||
const char *key_out, const char *id_out)
|
||||
size_t authdata_len, const unsigned char *attstmt_ptr, size_t attstmt_len,
|
||||
bool rk, bool uv, int ext, const char *key_out, const char *id_out)
|
||||
{
|
||||
fido_cred_t *cred;
|
||||
int r;
|
||||
@ -57,11 +56,10 @@ verify_cred(int type, const char *fmt, const unsigned char *authdata_ptr,
|
||||
if (r != FIDO_OK)
|
||||
errx(1, "fido_cred_set_type: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
/* client data hash */
|
||||
r = fido_cred_set_clientdata_hash(cred, cdh, sizeof(cdh));
|
||||
/* client data */
|
||||
r = fido_cred_set_clientdata(cred, cd, sizeof(cd));
|
||||
if (r != FIDO_OK)
|
||||
errx(1, "fido_cred_set_clientdata_hash: %s (0x%x)",
|
||||
fido_strerr(r), r);
|
||||
errx(1, "fido_cred_set_clientdata: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
/* relying party */
|
||||
r = fido_cred_set_rp(cred, "localhost", "sweet home localhost");
|
||||
@ -96,15 +94,10 @@ verify_cred(int type, const char *fmt, const unsigned char *authdata_ptr,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* x509 */
|
||||
r = fido_cred_set_x509(cred, x509_ptr, x509_len);
|
||||
/* attestation statement */
|
||||
r = fido_cred_set_attstmt(cred, attstmt_ptr, attstmt_len);
|
||||
if (r != FIDO_OK)
|
||||
errx(1, "fido_cred_set_x509: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
/* sig */
|
||||
r = fido_cred_set_sig(cred, sig_ptr, sig_len);
|
||||
if (r != FIDO_OK)
|
||||
errx(1, "fido_cred_set_sig: %s (0x%x)", fido_strerr(r), r);
|
||||
errx(1, "fido_cred_set_attstmt: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
r = fido_cred_verify(cred);
|
||||
if (r != FIDO_OK)
|
||||
@ -138,27 +131,6 @@ verify_cred(int type, const char *fmt, const unsigned char *authdata_ptr,
|
||||
fido_cred_free(&cred);
|
||||
}
|
||||
|
||||
static fido_dev_t *
|
||||
open_from_manifest(const fido_dev_info_t *dev_infos, size_t len,
|
||||
const char *path)
|
||||
{
|
||||
size_t i;
|
||||
fido_dev_t *dev;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
const fido_dev_info_t *curr = fido_dev_info_ptr(dev_infos, i);
|
||||
if (path == NULL ||
|
||||
strcmp(path, fido_dev_info_path(curr)) == 0) {
|
||||
dev = fido_dev_new_with_info(curr);
|
||||
if (fido_dev_open_with_info(dev) == FIDO_OK)
|
||||
return (dev);
|
||||
fido_dev_free(&dev);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -171,16 +143,13 @@ main(int argc, char **argv)
|
||||
const char *blobkey_out = NULL;
|
||||
const char *key_out = NULL;
|
||||
const char *id_out = NULL;
|
||||
const char *path = NULL;
|
||||
unsigned char *body = NULL;
|
||||
long long seconds = 0;
|
||||
long long ms = 0;
|
||||
size_t len;
|
||||
int type = COSE_ES256;
|
||||
int ext = 0;
|
||||
int ch;
|
||||
int r;
|
||||
fido_dev_info_t *dev_infos = NULL;
|
||||
size_t dev_infos_len = 0;
|
||||
|
||||
if ((cred = fido_cred_new()) == NULL)
|
||||
errx(1, "fido_cred_new");
|
||||
@ -191,16 +160,12 @@ main(int argc, char **argv)
|
||||
pin = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
#ifndef SIGNAL_EXAMPLE
|
||||
(void)seconds;
|
||||
errx(1, "-T not supported");
|
||||
#else
|
||||
if (base10(optarg, &seconds) < 0)
|
||||
if (base10(optarg, &ms) < 0)
|
||||
errx(1, "base10: %s", optarg);
|
||||
if (seconds <= 0 || seconds > 30)
|
||||
if (ms <= 0 || ms > 30)
|
||||
errx(1, "-T: %s must be in (0,30]", optarg);
|
||||
ms *= 1000; /* seconds to milliseconds */
|
||||
break;
|
||||
#endif
|
||||
case 'b':
|
||||
ext |= FIDO_EXT_LARGEBLOB_KEY;
|
||||
blobkey_out = optarg;
|
||||
@ -248,21 +213,20 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
fido_init(0);
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc > 1)
|
||||
if (argc != 1)
|
||||
usage();
|
||||
dev_infos = fido_dev_info_new(16);
|
||||
fido_dev_info_manifest(dev_infos, 16, &dev_infos_len);
|
||||
if (argc == 1)
|
||||
path = argv[0];
|
||||
|
||||
if ((dev = open_from_manifest(dev_infos, dev_infos_len, path)) == NULL)
|
||||
errx(1, "open_from_manifest");
|
||||
fido_init(0);
|
||||
|
||||
if ((dev = fido_dev_new()) == NULL)
|
||||
errx(1, "fido_dev_new");
|
||||
|
||||
r = fido_dev_open(dev, argv[0]);
|
||||
if (r != FIDO_OK)
|
||||
errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
|
||||
if (u2f)
|
||||
fido_dev_force_u2f(dev);
|
||||
|
||||
@ -271,11 +235,10 @@ main(int argc, char **argv)
|
||||
if (r != FIDO_OK)
|
||||
errx(1, "fido_cred_set_type: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
/* client data hash */
|
||||
r = fido_cred_set_clientdata_hash(cred, cdh, sizeof(cdh));
|
||||
/* client data */
|
||||
r = fido_cred_set_clientdata(cred, cd, sizeof(cd));
|
||||
if (r != FIDO_OK)
|
||||
errx(1, "fido_cred_set_clientdata_hash: %s (0x%x)",
|
||||
fido_strerr(r), r);
|
||||
errx(1, "fido_cred_set_clientdata: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
/* relying party */
|
||||
r = fido_cred_set_rp(cred, "localhost", "sweet home localhost");
|
||||
@ -301,20 +264,12 @@ main(int argc, char **argv)
|
||||
if (uv && (r = fido_cred_set_uv(cred, FIDO_OPT_TRUE)) != FIDO_OK)
|
||||
errx(1, "fido_cred_set_uv: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
#ifdef SIGNAL_EXAMPLE
|
||||
prepare_signal_handler(SIGINT);
|
||||
if (seconds) {
|
||||
prepare_signal_handler(SIGALRM);
|
||||
alarm((unsigned)seconds);
|
||||
}
|
||||
#endif
|
||||
/* timeout */
|
||||
if (ms != 0 && (r = fido_dev_set_timeout(dev, (int)ms)) != FIDO_OK)
|
||||
errx(1, "fido_dev_set_timeout: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
r = fido_dev_make_cred(dev, cred, pin);
|
||||
if (r != FIDO_OK) {
|
||||
#ifdef SIGNAL_EXAMPLE
|
||||
if (got_signal)
|
||||
fido_dev_cancel(dev);
|
||||
#endif
|
||||
if ((r = fido_dev_make_cred(dev, cred, pin)) != FIDO_OK) {
|
||||
fido_dev_cancel(dev);
|
||||
errx(1, "fido_makecred: %s (0x%x)", fido_strerr(r), r);
|
||||
}
|
||||
|
||||
@ -329,9 +284,8 @@ main(int argc, char **argv)
|
||||
uv = true;
|
||||
|
||||
verify_cred(type, fido_cred_fmt(cred), fido_cred_authdata_ptr(cred),
|
||||
fido_cred_authdata_len(cred), fido_cred_x5c_ptr(cred),
|
||||
fido_cred_x5c_len(cred), fido_cred_sig_ptr(cred),
|
||||
fido_cred_sig_len(cred), rk, uv, ext, key_out, id_out);
|
||||
fido_cred_authdata_len(cred), fido_cred_attstmt_ptr(cred),
|
||||
fido_cred_attstmt_len(cred), rk, uv, ext, key_out, id_out);
|
||||
|
||||
if (blobkey_out != NULL) {
|
||||
/* extract the "largeBlob" key */
|
||||
|
@ -11,10 +11,6 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
/* util.c */
|
||||
EC_KEY *read_ec_pubkey(const char *);
|
||||
RSA *read_rsa_pubkey(const char *);
|
||||
@ -25,9 +21,5 @@ int write_blob(const char *, const unsigned char *, size_t);
|
||||
int write_ec_pubkey(const char *, const void *, size_t);
|
||||
int write_rsa_pubkey(const char *, const void *, size_t);
|
||||
int write_eddsa_pubkey(const char *, const void *, size_t);
|
||||
#ifdef SIGNAL_EXAMPLE
|
||||
void prepare_signal_handler(int);
|
||||
extern volatile sig_atomic_t got_signal;
|
||||
#endif
|
||||
|
||||
#endif /* _EXTERN_H_ */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -34,16 +34,9 @@ main(int argc, char **argv)
|
||||
if ((r = fido_dev_open(dev, argv[1])) != FIDO_OK)
|
||||
errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
|
||||
|
||||
#ifdef SIGNAL_EXAMPLE
|
||||
prepare_signal_handler(SIGINT);
|
||||
#endif
|
||||
|
||||
if ((r = fido_dev_reset(dev)) != FIDO_OK) {
|
||||
#ifdef SIGNAL_EXAMPLE
|
||||
if (got_signal)
|
||||
fido_dev_cancel(dev);
|
||||
#endif
|
||||
errx(1, "fido_reset: %s (0x%x)", fido_strerr(r), r);
|
||||
fido_dev_cancel(dev);
|
||||
errx(1, "fido_dev_reset: %s (0x%x)", fido_strerr(r), r);
|
||||
}
|
||||
|
||||
if ((r = fido_dev_close(dev)) != FIDO_OK)
|
||||
|
@ -21,9 +21,6 @@
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@ -33,31 +30,6 @@
|
||||
#include "../openbsd-compat/openbsd-compat.h"
|
||||
#include "extern.h"
|
||||
|
||||
#ifdef SIGNAL_EXAMPLE
|
||||
volatile sig_atomic_t got_signal = 0;
|
||||
|
||||
static void
|
||||
signal_handler(int signo)
|
||||
{
|
||||
(void)signo;
|
||||
got_signal = 1;
|
||||
}
|
||||
|
||||
void
|
||||
prepare_signal_handler(int signo)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_handler = signal_handler;
|
||||
|
||||
if (sigaction(signo, &sa, NULL) < 0)
|
||||
err(1, "sigaction");
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
base10(const char *str, long long *ll)
|
||||
{
|
||||
|
@ -1,12 +1,12 @@
|
||||
# Copyright (c) 2019 Yubico AB. All rights reserved.
|
||||
# Copyright (c) 2019-2021 Yubico AB. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
FROM ubuntu:focal
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y clang-11 cmake git libssl-dev libudev-dev make pkg-config
|
||||
RUN apt-get install -y clang-12 cmake git libssl-dev libudev-dev make pkg-config
|
||||
RUN apt-get install -y zlib1g-dev
|
||||
RUN git clone --branch v0.8.0 https://github.com/PJK/libcbor
|
||||
RUN git clone https://github.com/yubico/libfido2
|
||||
RUN CC=clang-11 CXX=clang++-11 /libfido2/fuzz/build-coverage /libcbor /libfido2
|
||||
RUN CC=clang-12 CXX=clang++-12 /libfido2/fuzz/build-coverage /libcbor /libfido2
|
||||
|
@ -1,11 +1,11 @@
|
||||
# Copyright (c) 2019 Yubico AB. All rights reserved.
|
||||
# Copyright (c) 2019-2021 Yubico AB. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
IMAGE := libfido2-coverage:1.8.0
|
||||
IMAGE := libfido2-coverage:1.9.1
|
||||
RUNNER := libfido2-runner
|
||||
PROFDATA := llvm-profdata-11
|
||||
COV := llvm-cov-11
|
||||
PROFDATA := llvm-profdata-12
|
||||
COV := llvm-cov-12
|
||||
TARGETS := fuzz_assert fuzz_bio fuzz_cred fuzz_credman fuzz_hid \
|
||||
fuzz_largeblob fuzz_netlink fuzz_mgmt
|
||||
CORPORA := $(foreach f,${TARGETS},${f}/corpus)
|
||||
@ -50,16 +50,18 @@ profdata: run
|
||||
report.tgz: profdata
|
||||
docker exec ${RUNNER} /bin/sh -c 'rm -rf /report && mkdir /report && \
|
||||
${COV} show -format=html -tab-size=8 -instr-profile=/$< \
|
||||
-output-dir=/report /libfido2/build/src/libfido2.so'
|
||||
--show-branch-summary=false -output-dir=/report \
|
||||
/libfido2/build/src/libfido2.so'
|
||||
docker exec -i ${RUNNER} tar Czcf / - report > $@
|
||||
|
||||
summary.txt: profdata
|
||||
docker exec ${RUNNER} ${COV} report -use-color=false \
|
||||
/libfido2/build/src/libfido2.so -instr-profile=/$< > $@
|
||||
--show-branch-summary=false /libfido2/build/src/libfido2.so \
|
||||
-instr-profile=/$< > $@
|
||||
|
||||
functions.txt: profdata
|
||||
docker exec ${RUNNER} /bin/sh -c '${COV} report -use-color=false \
|
||||
-show-functions -instr-profile=/$< \
|
||||
-show-functions --show-branch-summary=false -instr-profile=/$< \
|
||||
/libfido2/build/src/libfido2.so /libfido2/src/*.[ch]' > $@
|
||||
|
||||
clean: run
|
||||
|
79
fuzz/clock.c
Normal file
79
fuzz/clock.c
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "mutator_aux.h"
|
||||
|
||||
/*
|
||||
* A pseudo-random monotonic clock with a probabilistic discontinuity to
|
||||
* the end of time (as measured by struct timespec).
|
||||
*/
|
||||
|
||||
extern int prng_up;
|
||||
extern int __wrap_clock_gettime(clockid_t, struct timespec *);
|
||||
extern int __real_clock_gettime(clockid_t, struct timespec *);
|
||||
extern int __wrap_usleep(unsigned int);
|
||||
static TLS struct timespec fuzz_clock;
|
||||
|
||||
static void
|
||||
tick(unsigned int usec)
|
||||
{
|
||||
long long drift;
|
||||
|
||||
/*
|
||||
* Simulate a jump to the end of time with 0.125% probability.
|
||||
* This condition should be gracefully handled by callers of
|
||||
* clock_gettime().
|
||||
*/
|
||||
if (uniform_random(800) < 1) {
|
||||
fuzz_clock.tv_sec = LLONG_MAX;
|
||||
fuzz_clock.tv_nsec = LONG_MAX;
|
||||
return;
|
||||
}
|
||||
|
||||
drift = usec * 1000LL + (long long)uniform_random(10000000); /* 10ms */
|
||||
if (LLONG_MAX - drift < (long long)fuzz_clock.tv_nsec) {
|
||||
fuzz_clock_reset(); /* Not much we can do here. */
|
||||
} else if (drift + (long long)fuzz_clock.tv_nsec < 1000000000) {
|
||||
fuzz_clock.tv_nsec += (long)(drift);
|
||||
} else {
|
||||
fuzz_clock.tv_sec += (long)(drift / 1000000000);
|
||||
fuzz_clock.tv_nsec += (long)(drift % 1000000000);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
__wrap_clock_gettime(clockid_t clk_id, struct timespec *tp)
|
||||
{
|
||||
if (!prng_up || clk_id != CLOCK_MONOTONIC)
|
||||
return __real_clock_gettime(clk_id, tp);
|
||||
if (uniform_random(400) < 1)
|
||||
return -1;
|
||||
|
||||
tick(0);
|
||||
*tp = fuzz_clock;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__wrap_usleep(unsigned int usec)
|
||||
{
|
||||
if (uniform_random(400) < 1)
|
||||
return -1;
|
||||
|
||||
tick(usec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
fuzz_clock_reset(void)
|
||||
{
|
||||
memset(&fuzz_clock, 0, sizeof(fuzz_clock));
|
||||
}
|
83
fuzz/dummy.h
83
fuzz/dummy.h
@ -93,4 +93,87 @@ const uint8_t dummy_eddsa[] = {
|
||||
0xe2, 0x39, 0xdf, 0x2f, 0x87, 0x19, 0xb3, 0x02,
|
||||
};
|
||||
|
||||
const uint8_t dummy_netlink_wiredata[] = {
|
||||
0xd8, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x9d, 0x2e, 0x00, 0x00,
|
||||
0x01, 0x02, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x6e, 0x66, 0x63, 0x00, 0x06, 0x00, 0x01, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00,
|
||||
0x1f, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x00,
|
||||
0x14, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x06, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x09, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0c, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0e, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x1a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x10, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x11, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x1c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x13, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x07, 0x00,
|
||||
0x18, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x05, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00,
|
||||
0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x00,
|
||||
0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x9d, 0x2e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x9d, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x09, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x9d, 0x2e, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00,
|
||||
0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x05, 0x00, 0x44, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x06, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||
0x93, 0xb9, 0x25, 0x00
|
||||
};
|
||||
|
||||
#endif /* !_DUMMY_H */
|
||||
|
@ -7,6 +7,7 @@
|
||||
eddsa_pk_to_EVP_PKEY;
|
||||
es256_pk_free;
|
||||
es256_pk_from_EC_KEY;
|
||||
es256_pk_from_EVP_PKEY;
|
||||
es256_pk_from_ptr;
|
||||
es256_pk_new;
|
||||
es256_pk_to_EVP_PKEY;
|
||||
@ -30,6 +31,7 @@
|
||||
fido_assert_rp_id;
|
||||
fido_assert_set_authdata;
|
||||
fido_assert_set_authdata_raw;
|
||||
fido_assert_set_clientdata;
|
||||
fido_assert_set_clientdata_hash;
|
||||
fido_assert_set_count;
|
||||
fido_assert_set_extensions;
|
||||
@ -98,6 +100,8 @@
|
||||
fido_cbor_info_transports_ptr;
|
||||
fido_cbor_info_versions_len;
|
||||
fido_cbor_info_versions_ptr;
|
||||
fido_cred_attstmt_len;
|
||||
fido_cred_attstmt_ptr;
|
||||
fido_cred_authdata_len;
|
||||
fido_cred_authdata_ptr;
|
||||
fido_cred_authdata_raw_len;
|
||||
@ -137,19 +141,23 @@
|
||||
fido_credman_rp_new;
|
||||
fido_credman_set_dev_rk;
|
||||
fido_cred_new;
|
||||
fido_cred_pin_minlen;
|
||||
fido_cred_prot;
|
||||
fido_cred_pubkey_len;
|
||||
fido_cred_pubkey_ptr;
|
||||
fido_cred_rp_id;
|
||||
fido_cred_rp_name;
|
||||
fido_cred_set_attstmt;
|
||||
fido_cred_set_authdata;
|
||||
fido_cred_set_authdata_raw;
|
||||
fido_cred_set_blob;
|
||||
fido_cred_set_clientdata;
|
||||
fido_cred_set_clientdata_hash;
|
||||
fido_cred_set_extensions;
|
||||
fido_cred_set_fmt;
|
||||
fido_cred_set_id;
|
||||
fido_cred_set_options;
|
||||
fido_cred_set_pin_minlen;
|
||||
fido_cred_set_prot;
|
||||
fido_cred_set_rk;
|
||||
fido_cred_set_rp;
|
||||
@ -205,6 +213,8 @@
|
||||
fido_dev_set_io_functions;
|
||||
fido_dev_set_pin;
|
||||
fido_dev_set_pin_minlen;
|
||||
fido_dev_set_pin_minlen_rpid;
|
||||
fido_dev_set_timeout;
|
||||
fido_dev_set_transport_functions;
|
||||
fido_dev_supports_cred_prot;
|
||||
fido_dev_supports_credman;
|
||||
@ -230,10 +240,12 @@
|
||||
fido_strerr;
|
||||
rs256_pk_free;
|
||||
rs256_pk_from_ptr;
|
||||
rs256_pk_from_EVP_PKEY;
|
||||
rs256_pk_from_RSA;
|
||||
rs256_pk_new;
|
||||
rs256_pk_to_EVP_PKEY;
|
||||
prng_init;
|
||||
fuzz_clock_reset;
|
||||
set_netlink_io_functions;
|
||||
set_udev_parameters;
|
||||
uniform_random;
|
||||
|
1165
fuzz/functions.txt
1165
fuzz/functions.txt
File diff suppressed because it is too large
Load Diff
@ -255,6 +255,7 @@ verify_assert(int type, const unsigned char *cdh_ptr, size_t cdh_len,
|
||||
int ext, void *pk)
|
||||
{
|
||||
fido_assert_t *assert = NULL;
|
||||
int r;
|
||||
|
||||
if ((assert = fido_assert_new()) == NULL)
|
||||
return;
|
||||
@ -285,33 +286,52 @@ verify_assert(int type, const unsigned char *cdh_ptr, size_t cdh_len,
|
||||
}
|
||||
fido_assert_set_sig(assert, 0, sig_ptr, sig_len);
|
||||
|
||||
assert(fido_assert_verify(assert, 0, type, pk) != FIDO_OK);
|
||||
r = fido_assert_verify(assert, 0, type, pk);
|
||||
consume(&r, sizeof(r));
|
||||
|
||||
fido_assert_free(&assert);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a dummy conversion to exercise rs256_pk_from_RSA().
|
||||
* Do a dummy conversion to exercise es256_pk_from_EVP_PKEY().
|
||||
*/
|
||||
static void
|
||||
es256_convert(const es256_pk_t *k)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
es256_pk_t *pk = NULL;
|
||||
int r;
|
||||
|
||||
if ((pkey = es256_pk_to_EVP_PKEY(k)) == NULL ||
|
||||
(pk = es256_pk_new()) == NULL)
|
||||
goto out;
|
||||
|
||||
r = es256_pk_from_EVP_PKEY(pk, pkey);
|
||||
consume(&r, sizeof(r));
|
||||
out:
|
||||
es256_pk_free(&pk);
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a dummy conversion to exercise rs256_pk_from_EVP_PKEY().
|
||||
*/
|
||||
static void
|
||||
rs256_convert(const rs256_pk_t *k)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
rs256_pk_t *pk = NULL;
|
||||
RSA *rsa = NULL;
|
||||
volatile int r;
|
||||
int r;
|
||||
|
||||
if ((pkey = rs256_pk_to_EVP_PKEY(k)) == NULL ||
|
||||
(pk = rs256_pk_new()) == NULL ||
|
||||
(rsa = EVP_PKEY_get0_RSA(pkey)) == NULL)
|
||||
(pk = rs256_pk_new()) == NULL)
|
||||
goto out;
|
||||
|
||||
r = rs256_pk_from_RSA(pk, rsa);
|
||||
r = rs256_pk_from_EVP_PKEY(pk, pkey);
|
||||
consume(&r, sizeof(r));
|
||||
out:
|
||||
if (pk)
|
||||
rs256_pk_free(&pk);
|
||||
if (pkey)
|
||||
EVP_PKEY_free(pkey);
|
||||
rs256_pk_free(&pk);
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -322,13 +342,14 @@ eddsa_convert(const eddsa_pk_t *k)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
eddsa_pk_t *pk = NULL;
|
||||
volatile int r;
|
||||
int r;
|
||||
|
||||
if ((pkey = eddsa_pk_to_EVP_PKEY(k)) == NULL ||
|
||||
(pk = eddsa_pk_new()) == NULL)
|
||||
goto out;
|
||||
|
||||
r = eddsa_pk_from_EVP_PKEY(pk, pkey);
|
||||
consume(&r, sizeof(r));
|
||||
out:
|
||||
if (pk)
|
||||
eddsa_pk_free(&pk);
|
||||
@ -349,6 +370,7 @@ test(const struct param *p)
|
||||
void *pk;
|
||||
|
||||
prng_init((unsigned int)p->seed);
|
||||
fuzz_clock_reset();
|
||||
fido_init(FIDO_DEBUG);
|
||||
fido_set_log_handler(consume_str);
|
||||
|
||||
@ -362,6 +384,8 @@ test(const struct param *p)
|
||||
es256_pk_from_ptr(es256_pk, p->es256.body, p->es256.len);
|
||||
pk = es256_pk;
|
||||
|
||||
es256_convert(pk);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
cose_alg = COSE_RS256;
|
||||
|
@ -408,6 +408,7 @@ void
|
||||
test(const struct param *p)
|
||||
{
|
||||
prng_init((unsigned int)p->seed);
|
||||
fuzz_clock_reset();
|
||||
fido_init(FIDO_DEBUG);
|
||||
fido_set_log_handler(consume_str);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2019-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -231,12 +231,15 @@ make_cred(fido_cred_t *cred, uint8_t opt, int type, const struct blob *cdh,
|
||||
fido_cred_set_rp(cred, rp_id, rp_name);
|
||||
fido_cred_set_user(cred, user_id->body, user_id->len, user_name,
|
||||
user_nick, user_icon);
|
||||
|
||||
if (ext & FIDO_EXT_HMAC_SECRET)
|
||||
fido_cred_set_extensions(cred, FIDO_EXT_HMAC_SECRET);
|
||||
if (ext & FIDO_EXT_CRED_BLOB)
|
||||
fido_cred_set_blob(cred, user_id->body, user_id->len);
|
||||
if (ext & FIDO_EXT_LARGEBLOB_KEY)
|
||||
fido_cred_set_extensions(cred, FIDO_EXT_LARGEBLOB_KEY);
|
||||
if (ext & FIDO_EXT_MINPINLEN)
|
||||
fido_cred_set_pin_minlen(cred, strlen(pin));
|
||||
|
||||
if (rk & 1)
|
||||
fido_cred_set_rk(cred, FIDO_OPT_TRUE);
|
||||
@ -268,11 +271,13 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
|
||||
size_t authdata_len, const unsigned char *authdata_raw_ptr,
|
||||
size_t authdata_raw_len, int ext, uint8_t rk, uint8_t uv,
|
||||
const unsigned char *x5c_ptr, size_t x5c_len, const unsigned char *sig_ptr,
|
||||
size_t sig_len, const char *fmt, int prot)
|
||||
size_t sig_len, const unsigned char *attstmt_ptr, size_t attstmt_len,
|
||||
const char *fmt, int prot, size_t minpinlen)
|
||||
{
|
||||
fido_cred_t *cred;
|
||||
uint8_t flags;
|
||||
uint32_t sigcount;
|
||||
int r;
|
||||
|
||||
if ((cred = fido_cred_new()) == NULL)
|
||||
return;
|
||||
@ -282,13 +287,19 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
|
||||
fido_cred_set_rp(cred, rp_id, rp_name);
|
||||
consume(authdata_ptr, authdata_len);
|
||||
consume(authdata_raw_ptr, authdata_raw_len);
|
||||
consume(x5c_ptr, x5c_len);
|
||||
consume(sig_ptr, sig_len);
|
||||
consume(attstmt_ptr, attstmt_len);
|
||||
if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK)
|
||||
fido_cred_set_authdata_raw(cred, authdata_raw_ptr,
|
||||
authdata_raw_len);
|
||||
fido_cred_set_extensions(cred, ext);
|
||||
fido_cred_set_x509(cred, x5c_ptr, x5c_len);
|
||||
fido_cred_set_sig(cred, sig_ptr, sig_len);
|
||||
if (fido_cred_set_attstmt(cred, attstmt_ptr, attstmt_len) != FIDO_OK) {
|
||||
fido_cred_set_x509(cred, x5c_ptr, x5c_len);
|
||||
fido_cred_set_sig(cred, sig_ptr, sig_len);
|
||||
}
|
||||
fido_cred_set_prot(cred, prot);
|
||||
fido_cred_set_pin_minlen(cred, minpinlen);
|
||||
|
||||
if (rk & 1)
|
||||
fido_cred_set_rk(cred, FIDO_OPT_TRUE);
|
||||
@ -299,12 +310,19 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
|
||||
|
||||
/* repeat memory operations to trigger reallocation paths */
|
||||
if (fido_cred_set_authdata(cred, authdata_ptr, authdata_len) != FIDO_OK)
|
||||
fido_cred_set_authdata_raw(cred, authdata_ptr, authdata_len);
|
||||
fido_cred_set_authdata_raw(cred, authdata_raw_ptr,
|
||||
authdata_raw_len);
|
||||
if (fido_cred_set_attstmt(cred, attstmt_ptr, attstmt_len) != FIDO_OK) {
|
||||
fido_cred_set_x509(cred, x5c_ptr, x5c_len);
|
||||
fido_cred_set_sig(cred, sig_ptr, sig_len);
|
||||
}
|
||||
fido_cred_set_x509(cred, x5c_ptr, x5c_len);
|
||||
fido_cred_set_sig(cred, sig_ptr, sig_len);
|
||||
|
||||
assert(fido_cred_verify(cred) != FIDO_OK);
|
||||
assert(fido_cred_verify_self(cred) != FIDO_OK);
|
||||
r = fido_cred_verify(cred);
|
||||
consume(&r, sizeof(r));
|
||||
r = fido_cred_verify_self(cred);
|
||||
consume(&r, sizeof(r));
|
||||
|
||||
consume(fido_cred_pubkey_ptr(cred), fido_cred_pubkey_len(cred));
|
||||
consume(fido_cred_id_ptr(cred), fido_cred_id_len(cred));
|
||||
@ -321,6 +339,8 @@ verify_cred(int type, const unsigned char *cdh_ptr, size_t cdh_len,
|
||||
consume(&sigcount, sizeof(sigcount));
|
||||
type = fido_cred_type(cred);
|
||||
consume(&type, sizeof(type));
|
||||
minpinlen = fido_cred_pin_minlen(cred);
|
||||
consume(&minpinlen, sizeof(minpinlen));
|
||||
|
||||
fido_cred_free(&cred);
|
||||
}
|
||||
@ -360,7 +380,9 @@ test_cred(const struct param *p)
|
||||
fido_cred_authdata_raw_len(cred), p->ext, p->rk, p->uv,
|
||||
fido_cred_x5c_ptr(cred), fido_cred_x5c_len(cred),
|
||||
fido_cred_sig_ptr(cred), fido_cred_sig_len(cred),
|
||||
fido_cred_fmt(cred), fido_cred_prot(cred));
|
||||
fido_cred_attstmt_ptr(cred), fido_cred_attstmt_len(cred),
|
||||
fido_cred_fmt(cred), fido_cred_prot(cred),
|
||||
fido_cred_pin_minlen(cred));
|
||||
|
||||
fido_cred_free(&cred);
|
||||
}
|
||||
@ -408,6 +430,7 @@ void
|
||||
test(const struct param *p)
|
||||
{
|
||||
prng_init((unsigned int)p->seed);
|
||||
fuzz_clock_reset();
|
||||
fido_init(FIDO_DEBUG);
|
||||
fido_set_log_handler(consume_str);
|
||||
|
||||
|
@ -374,6 +374,7 @@ void
|
||||
test(const struct param *p)
|
||||
{
|
||||
prng_init((unsigned int)p->seed);
|
||||
fuzz_clock_reset();
|
||||
fido_init(FIDO_DEBUG);
|
||||
fido_set_log_handler(consume_str);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2020-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include "../openbsd-compat/openbsd-compat.h"
|
||||
#include "mutator_aux.h"
|
||||
#include "dummy.h"
|
||||
|
||||
extern int fido_hid_get_usage(const uint8_t *, size_t, uint32_t *);
|
||||
extern int fido_hid_get_report_len(const uint8_t *, size_t, size_t *, size_t *);
|
||||
@ -21,6 +22,7 @@ struct param {
|
||||
int seed;
|
||||
char uevent[MAXSTR];
|
||||
struct blob report_descriptor;
|
||||
struct blob netlink_wiredata;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -58,13 +60,14 @@ unpack(const uint8_t *ptr, size_t len)
|
||||
cbor.read != len ||
|
||||
cbor_isa_array(item) == false ||
|
||||
cbor_array_is_definite(item) == false ||
|
||||
cbor_array_size(item) != 3 ||
|
||||
cbor_array_size(item) != 4 ||
|
||||
(v = cbor_array_handle(item)) == NULL)
|
||||
goto fail;
|
||||
|
||||
if (unpack_int(v[0], &p->seed) < 0 ||
|
||||
unpack_string(v[1], p->uevent) < 0 ||
|
||||
unpack_blob(v[2], &p->report_descriptor) < 0)
|
||||
unpack_blob(v[2], &p->report_descriptor) < 0 ||
|
||||
unpack_blob(v[3], &p->netlink_wiredata) < 0)
|
||||
goto fail;
|
||||
|
||||
ok = 0;
|
||||
@ -83,19 +86,20 @@ unpack(const uint8_t *ptr, size_t len)
|
||||
size_t
|
||||
pack(uint8_t *ptr, size_t len, const struct param *p)
|
||||
{
|
||||
cbor_item_t *argv[3], *array = NULL;
|
||||
cbor_item_t *argv[4], *array = NULL;
|
||||
size_t cbor_alloc_len, cbor_len = 0;
|
||||
unsigned char *cbor = NULL;
|
||||
|
||||
memset(argv, 0, sizeof(argv));
|
||||
|
||||
if ((array = cbor_new_definite_array(3)) == NULL ||
|
||||
if ((array = cbor_new_definite_array(4)) == NULL ||
|
||||
(argv[0] = pack_int(p->seed)) == NULL ||
|
||||
(argv[1] = pack_string(p->uevent)) == NULL ||
|
||||
(argv[2] = pack_blob(&p->report_descriptor)) == NULL)
|
||||
(argv[2] = pack_blob(&p->report_descriptor)) == NULL ||
|
||||
(argv[3] = pack_blob(&p->netlink_wiredata)) == NULL)
|
||||
goto fail;
|
||||
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
if (cbor_array_push(array, argv[i]) == false)
|
||||
goto fail;
|
||||
|
||||
@ -107,7 +111,7 @@ pack(uint8_t *ptr, size_t len, const struct param *p)
|
||||
|
||||
memcpy(ptr, cbor, cbor_len);
|
||||
fail:
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
if (argv[i])
|
||||
cbor_decref(&argv[i]);
|
||||
|
||||
@ -132,6 +136,9 @@ pack_dummy(uint8_t *ptr, size_t len)
|
||||
strlcpy(dummy.uevent, dummy_uevent, sizeof(dummy.uevent));
|
||||
memcpy(&dummy.report_descriptor.body, &dummy_report_descriptor,
|
||||
dummy.report_descriptor.len);
|
||||
dummy.netlink_wiredata.len = sizeof(dummy_netlink_wiredata);
|
||||
memcpy(&dummy.netlink_wiredata.body, &dummy_netlink_wiredata,
|
||||
dummy.netlink_wiredata.len);
|
||||
|
||||
assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
|
||||
if (blob_len > len)
|
||||
@ -171,7 +178,10 @@ manifest(const struct param *p)
|
||||
fido_dev_info_t *devlist;
|
||||
int16_t vendor_id, product_id;
|
||||
|
||||
set_netlink_io_functions(fd_read, fd_write);
|
||||
set_wire_data(p->netlink_wiredata.body, p->netlink_wiredata.len);
|
||||
set_udev_parameters(p->uevent, &p->report_descriptor);
|
||||
|
||||
ndevs = uniform_random(64);
|
||||
if ((devlist = fido_dev_info_new(ndevs)) == NULL ||
|
||||
fido_dev_info_manifest(devlist, ndevs, &nfound) != FIDO_OK)
|
||||
@ -194,6 +204,7 @@ void
|
||||
test(const struct param *p)
|
||||
{
|
||||
prng_init((unsigned int)p->seed);
|
||||
fuzz_clock_reset();
|
||||
fido_init(FIDO_DEBUG);
|
||||
fido_set_log_handler(consume_str);
|
||||
|
||||
@ -212,4 +223,7 @@ mutate(struct param *p, unsigned int seed, unsigned int flags) NO_MSAN
|
||||
mutate_blob(&p->report_descriptor);
|
||||
mutate_string(p->uevent);
|
||||
}
|
||||
|
||||
if (flags & MUTATE_WIREDATA)
|
||||
mutate_blob(&p->netlink_wiredata);
|
||||
}
|
||||
|
@ -242,6 +242,7 @@ void
|
||||
test(const struct param *p)
|
||||
{
|
||||
prng_init((unsigned int)p->seed);
|
||||
fuzz_clock_reset();
|
||||
fido_init(FIDO_DEBUG);
|
||||
fido_set_log_handler(consume_str);
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#include "../openbsd-compat/openbsd-compat.h"
|
||||
|
||||
#define MAXRPID 64
|
||||
|
||||
struct param {
|
||||
char pin1[MAXSTR];
|
||||
char pin2[MAXSTR];
|
||||
@ -440,10 +442,35 @@ dev_set_pin_minlen(const struct param *p)
|
||||
fido_dev_free(&dev);
|
||||
}
|
||||
|
||||
static void
|
||||
dev_set_pin_minlen_rpid(const struct param *p)
|
||||
{
|
||||
fido_dev_t *dev;
|
||||
const char *rpid[MAXRPID];
|
||||
const char *pin;
|
||||
size_t n;
|
||||
int r;
|
||||
|
||||
set_wire_data(p->config_wire_data.body, p->config_wire_data.len);
|
||||
if ((dev = open_dev(0)) == NULL)
|
||||
return;
|
||||
n = uniform_random(MAXRPID);
|
||||
for (size_t i = 0; i < n; i++)
|
||||
rpid[i] = dummy_rp_id;
|
||||
pin = p->pin1;
|
||||
if (strlen(pin) == 0)
|
||||
pin = NULL;
|
||||
r = fido_dev_set_pin_minlen_rpid(dev, rpid, n, pin);
|
||||
consume_str(fido_strerr(r));
|
||||
fido_dev_close(dev);
|
||||
fido_dev_free(&dev);
|
||||
}
|
||||
|
||||
void
|
||||
test(const struct param *p)
|
||||
{
|
||||
prng_init((unsigned int)p->seed);
|
||||
fuzz_clock_reset();
|
||||
fido_init(FIDO_DEBUG);
|
||||
fido_set_log_handler(consume_str);
|
||||
|
||||
@ -457,6 +484,7 @@ test(const struct param *p)
|
||||
dev_toggle_always_uv(p);
|
||||
dev_force_pin_change(p);
|
||||
dev_set_pin_minlen(p);
|
||||
dev_set_pin_minlen_rpid(p);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "../openbsd-compat/openbsd-compat.h"
|
||||
#include "mutator_aux.h"
|
||||
#include "dummy.h"
|
||||
|
||||
struct param {
|
||||
int seed;
|
||||
@ -19,94 +20,6 @@ struct param {
|
||||
struct blob wiredata;
|
||||
};
|
||||
|
||||
/*
|
||||
* Sample netlink messages. These are unlikely to get the harness very far in
|
||||
* terms of coverage, but serve to give libFuzzer a sense of the underlying
|
||||
* structure.
|
||||
*/
|
||||
static const uint8_t sample_netlink_wiredata[] = {
|
||||
0xd8, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x9d, 0x2e, 0x00, 0x00,
|
||||
0x01, 0x02, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x6e, 0x66, 0x63, 0x00, 0x06, 0x00, 0x01, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x03, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x05, 0x00,
|
||||
0x1f, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x00,
|
||||
0x14, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x03, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x04, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x05, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x06, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x07, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x08, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x09, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0a, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x0b, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0c, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x11, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0e, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x1a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x10, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x1b, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x11, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x1c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00,
|
||||
0x08, 0x00, 0x01, 0x00, 0x1d, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x13, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x07, 0x00,
|
||||
0x18, 0x00, 0x01, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||
0x05, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00,
|
||||
0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x00, 0x00,
|
||||
0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x9d, 0x2e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x9d, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x09, 0x01, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x9d, 0x2e, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00,
|
||||
0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x05, 0x00, 0x44, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x06, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x00, 0x07, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||
0x93, 0xb9, 0x25, 0x00
|
||||
};
|
||||
|
||||
struct param *
|
||||
unpack(const uint8_t *ptr, size_t len)
|
||||
{
|
||||
@ -190,8 +103,8 @@ pack_dummy(uint8_t *ptr, size_t len)
|
||||
|
||||
memset(&dummy, 0, sizeof(dummy));
|
||||
|
||||
dummy.wiredata.len = sizeof(sample_netlink_wiredata);
|
||||
memcpy(&dummy.wiredata.body, &sample_netlink_wiredata,
|
||||
dummy.wiredata.len = sizeof(dummy_netlink_wiredata);
|
||||
memcpy(&dummy.wiredata.body, &dummy_netlink_wiredata,
|
||||
dummy.wiredata.len);
|
||||
|
||||
assert((blob_len = pack(blob, sizeof(blob), &dummy)) != 0);
|
||||
@ -213,6 +126,7 @@ test(const struct param *p)
|
||||
uint32_t target;
|
||||
|
||||
prng_init((unsigned int)p->seed);
|
||||
fuzz_clock_reset();
|
||||
fido_init(FIDO_DEBUG);
|
||||
fido_set_log_handler(consume_str);
|
||||
|
||||
|
@ -37,6 +37,8 @@ consume(const void *body, size_t len)
|
||||
|
||||
while (len--)
|
||||
x ^= *ptr++;
|
||||
|
||||
(void)x;
|
||||
}
|
||||
|
||||
void
|
||||
@ -308,7 +310,8 @@ open_dev(int nfc)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fido_dev_open(dev, "nodev") != FIDO_OK)
|
||||
if (fido_dev_set_timeout(dev, 300) != FIDO_OK ||
|
||||
fido_dev_open(dev, "nodev") != FIDO_OK)
|
||||
goto fail;
|
||||
|
||||
return dev;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2019-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -49,7 +49,7 @@
|
||||
#define MUTATE_ALL (MUTATE_SEED | MUTATE_PARAM | MUTATE_WIREDATA)
|
||||
|
||||
#define MAXSTR 1024
|
||||
#define MAXBLOB 3072
|
||||
#define MAXBLOB 3600
|
||||
|
||||
struct blob {
|
||||
uint8_t body[MAXBLOB];
|
||||
@ -88,6 +88,7 @@ ssize_t fd_write(int, const void *, size_t);
|
||||
fido_dev_t *open_dev(int);
|
||||
void set_wire_data(const uint8_t *, size_t);
|
||||
|
||||
void fuzz_clock_reset(void);
|
||||
void prng_init(unsigned long);
|
||||
unsigned long prng_uint32(void);
|
||||
|
||||
|
BIN
fuzz/report.tgz
BIN
fuzz/report.tgz
Binary file not shown.
@ -1,51 +1,57 @@
|
||||
Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
fuzz/prng.c 31 0 100.00% 2 0 100.00% 49 0 100.00%
|
||||
fuzz/udev.c 103 5 95.15% 17 1 94.12% 141 7 95.04%
|
||||
fuzz/uniform_random.c 7 1 85.71% 1 0 100.00% 23 1 95.65%
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
fuzz/clock.c 24 1 95.83% 4 0 100.00% 35 0 100.00%
|
||||
fuzz/prng.c 31 0 100.00% 2 0 100.00% 35 0 100.00%
|
||||
fuzz/udev.c 103 1 99.03% 17 0 100.00% 126 3 97.62%
|
||||
fuzz/uniform_random.c 7 1 85.71% 1 0 100.00% 12 1 91.67%
|
||||
fuzz/wrap.c 6 0 100.00% 1 0 100.00% 7 0 100.00%
|
||||
openbsd-compat/explicit_bzero.c 4 0 100.00% 1 0 100.00% 13 0 100.00%
|
||||
openbsd-compat/explicit_bzero.c 4 0 100.00% 1 0 100.00% 7 0 100.00%
|
||||
openbsd-compat/freezero.c 4 0 100.00% 1 0 100.00% 6 0 100.00%
|
||||
openbsd-compat/recallocarray.c 41 7 82.93% 1 0 100.00% 49 7 85.71%
|
||||
openbsd-compat/strlcat.c 12 1 91.67% 1 0 100.00% 25 1 96.00%
|
||||
openbsd-compat/timingsafe_bcmp.c 4 0 100.00% 1 0 100.00% 8 0 100.00%
|
||||
src/aes256.c 115 4 96.52% 8 0 100.00% 175 14 92.00%
|
||||
src/assert.c 616 46 92.53% 59 3 94.92% 924 64 93.07%
|
||||
src/authkey.c 44 0 100.00% 5 0 100.00% 75 0 100.00%
|
||||
src/bio.c 419 20 95.23% 49 2 95.92% 660 22 96.67%
|
||||
src/blob.c 53 3 94.34% 10 0 100.00% 96 7 92.71%
|
||||
src/buf.c 8 1 87.50% 2 0 100.00% 20 1 95.00%
|
||||
src/cbor.c 986 17 98.28% 53 0 100.00% 1426 37 97.41%
|
||||
src/compress.c 34 4 88.24% 3 0 100.00% 30 3 90.00%
|
||||
src/config.c 94 1 98.94% 10 0 100.00% 146 3 97.95%
|
||||
src/cred.c 581 38 93.46% 63 2 96.83% 872 48 94.50%
|
||||
src/credman.c 382 10 97.38% 40 0 100.00% 614 15 97.56%
|
||||
src/dev.c 414 74 82.13% 43 6 86.05% 556 106 80.94%
|
||||
src/ecdh.c 117 2 98.29% 4 0 100.00% 161 5 96.89%
|
||||
src/eddsa.c 54 0 100.00% 8 0 100.00% 77 0 100.00%
|
||||
openbsd-compat/recallocarray.c 41 7 82.93% 1 0 100.00% 36 7 80.56%
|
||||
openbsd-compat/strlcat.c 12 1 91.67% 1 0 100.00% 21 1 95.24%
|
||||
openbsd-compat/timingsafe_bcmp.c 4 0 100.00% 1 0 100.00% 7 0 100.00%
|
||||
src/aes256.c 115 4 96.52% 8 0 100.00% 157 14 91.08%
|
||||
src/assert.c 563 40 92.90% 56 3 94.64% 694 40 94.24%
|
||||
src/authkey.c 44 0 100.00% 5 0 100.00% 59 0 100.00%
|
||||
src/bio.c 419 20 95.23% 49 2 95.92% 559 21 96.24%
|
||||
src/blob.c 53 2 96.23% 10 0 100.00% 83 4 95.18%
|
||||
src/buf.c 8 1 87.50% 2 0 100.00% 16 1 93.75%
|
||||
src/cbor.c 1047 28 97.33% 54 0 100.00% 1237 54 95.63%
|
||||
src/compress.c 34 4 88.24% 3 0 100.00% 28 3 89.29%
|
||||
src/config.c 108 0 100.00% 11 0 100.00% 151 0 100.00%
|
||||
src/cred.c 632 34 94.62% 69 2 97.10% 830 36 95.66%
|
||||
src/credman.c 382 10 97.38% 40 0 100.00% 518 15 97.10%
|
||||
src/dev.c 420 78 81.43% 44 6 86.36% 488 102 79.10%
|
||||
src/ecdh.c 117 2 98.29% 4 0 100.00% 146 5 96.58%
|
||||
src/eddsa.c 80 3 96.25% 10 0 100.00% 106 8 92.45%
|
||||
src/err.c 122 10 91.80% 1 0 100.00% 126 10 92.06%
|
||||
src/es256.c 280 0 100.00% 16 0 100.00% 394 0 100.00%
|
||||
src/hid.c 60 0 100.00% 12 0 100.00% 134 0 100.00%
|
||||
src/hid_linux.c 173 68 60.69% 14 7 50.00% 303 123 59.41%
|
||||
src/hid_unix.c 30 20 33.33% 2 0 100.00% 52 28 46.15%
|
||||
src/info.c 198 0 100.00% 44 0 100.00% 405 0 100.00%
|
||||
src/io.c 158 7 95.57% 10 0 100.00% 228 11 95.18%
|
||||
src/iso7816.c 18 1 94.44% 5 0 100.00% 42 0 100.00%
|
||||
src/largeblob.c 513 19 96.30% 30 0 100.00% 759 43 94.33%
|
||||
src/log.c 39 5 87.18% 7 1 85.71% 73 4 94.52%
|
||||
src/netlink.c 327 15 95.41% 40 0 100.00% 565 35 93.81%
|
||||
src/nfc_linux.c 304 123 59.54% 23 10 56.52% 520 199 61.73%
|
||||
src/pin.c 403 3 99.26% 26 0 100.00% 583 3 99.49%
|
||||
src/random.c 6 1 83.33% 1 0 100.00% 8 1 87.50%
|
||||
src/reset.c 24 0 100.00% 3 0 100.00% 27 0 100.00%
|
||||
src/rs256.c 102 4 96.08% 8 0 100.00% 138 6 95.65%
|
||||
src/u2f.c 473 6 98.73% 15 0 100.00% 742 9 98.79%
|
||||
src/es256.c 306 5 98.37% 19 0 100.00% 358 7 98.04%
|
||||
src/hid.c 60 0 100.00% 12 0 100.00% 114 0 100.00%
|
||||
src/hid_linux.c 173 68 60.69% 14 7 50.00% 250 104 58.40%
|
||||
src/hid_unix.c 28 20 28.57% 2 0 100.00% 43 24 44.19%
|
||||
src/info.c 184 0 100.00% 39 0 100.00% 316 0 100.00%
|
||||
src/io.c 182 7 96.15% 13 0 100.00% 221 11 95.02%
|
||||
src/iso7816.c 18 1 94.44% 5 0 100.00% 38 0 100.00%
|
||||
src/largeblob.c 513 21 95.91% 30 0 100.00% 684 47 93.13%
|
||||
src/log.c 39 5 87.18% 7 1 85.71% 63 4 93.65%
|
||||
src/netlink.c 328 14 95.73% 40 0 100.00% 498 32 93.57%
|
||||
src/nfc_linux.c 327 73 77.68% 23 5 78.26% 458 124 72.93%
|
||||
src/pin.c 403 3 99.26% 26 0 100.00% 495 3 99.39%
|
||||
src/random.c 6 1 83.33% 1 0 100.00% 6 1 83.33%
|
||||
src/reset.c 24 0 100.00% 3 0 100.00% 23 0 100.00%
|
||||
src/rs1.c 25 1 96.00% 3 0 100.00% 39 3 92.31%
|
||||
src/rs256.c 141 8 94.33% 13 0 100.00% 172 10 94.19%
|
||||
src/time.c 43 3 93.02% 3 0 100.00% 43 1 97.67%
|
||||
src/tpm.c 76 0 100.00% 7 0 100.00% 138 0 100.00%
|
||||
src/types.c 25 0 100.00% 6 0 100.00% 46 0 100.00%
|
||||
src/u2f.c 528 4 99.24% 17 0 100.00% 685 12 98.25%
|
||||
|
||||
Files which contain no functions:
|
||||
openbsd-compat/openbsd-compat.h 0 0 - 0 0 - 0 0 -
|
||||
openbsd-compat/time.h 0 0 - 0 0 - 0 0 -
|
||||
src/extern.h 0 0 - 0 0 - 0 0 -
|
||||
src/fido.h 0 0 - 0 0 - 0 0 -
|
||||
src/fido/err.h 0 0 - 0 0 - 0 0 -
|
||||
src/fido/param.h 0 0 - 0 0 - 0 0 -
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
TOTAL 7359 516 92.99% 640 32 95.00% 11252 813 92.77%
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
TOTAL 7809 481 93.84% 679 26 96.17% 10180 708 93.05%
|
||||
|
201
fuzz/wrap.c
201
fuzz/wrap.c
@ -4,6 +4,9 @@
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
@ -50,6 +53,14 @@ WRAP(void *,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(void *,
|
||||
realloc,
|
||||
(void *ptr, size_t size),
|
||||
NULL,
|
||||
(ptr, size),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(char *,
|
||||
strdup,
|
||||
(const char *s),
|
||||
@ -83,32 +94,6 @@ WRAP(EVP_CIPHER_CTX *,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_EncryptInit_ex,
|
||||
(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl,
|
||||
const unsigned char *key, const unsigned char *iv),
|
||||
0,
|
||||
(ctx, type, impl, key, iv),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_CIPHER_CTX_set_padding,
|
||||
(EVP_CIPHER_CTX *x, int padding),
|
||||
0,
|
||||
(x, padding),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_EncryptUpdate,
|
||||
(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
const unsigned char *in, int inl),
|
||||
0,
|
||||
(ctx, out, outl, in, inl),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_CipherInit,
|
||||
(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
|
||||
@ -118,48 +103,6 @@ WRAP(int,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_DecryptInit_ex,
|
||||
(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl,
|
||||
const unsigned char *key, const unsigned char *iv),
|
||||
0,
|
||||
(ctx, type, impl, key, iv),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_DecryptUpdate,
|
||||
(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
const unsigned char *in, int inl),
|
||||
0,
|
||||
(ctx, out, outl, in, inl),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
SHA256_Init,
|
||||
(SHA256_CTX *c),
|
||||
0,
|
||||
(c),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
SHA256_Update,
|
||||
(SHA256_CTX *c, const void *data, size_t len),
|
||||
0,
|
||||
(c, data, len),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
SHA256_Final,
|
||||
(unsigned char *md, SHA256_CTX *c),
|
||||
0,
|
||||
(md, c),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(RSA *,
|
||||
EVP_PKEY_get0_RSA,
|
||||
(EVP_PKEY *pkey),
|
||||
@ -201,6 +144,30 @@ WRAP(int,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_DigestInit_ex,
|
||||
(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl),
|
||||
0,
|
||||
(ctx, type, impl),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_DigestUpdate,
|
||||
(EVP_MD_CTX *ctx, const void *data, size_t count),
|
||||
0,
|
||||
(ctx, data, count),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_DigestFinal_ex,
|
||||
(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize),
|
||||
0,
|
||||
(ctx, md, isize),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(BIGNUM *,
|
||||
BN_bin2bn,
|
||||
(const unsigned char *s, int len, BIGNUM *ret),
|
||||
@ -241,6 +208,14 @@ WRAP(BIGNUM *,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(RSA *,
|
||||
RSA_new,
|
||||
(void),
|
||||
NULL,
|
||||
(),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
RSA_set0_key,
|
||||
(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d),
|
||||
@ -249,6 +224,14 @@ WRAP(int,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
RSA_pkey_ctx_ctrl,
|
||||
(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2),
|
||||
-1,
|
||||
(ctx, optype, cmd, p1, p2),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(EC_KEY *,
|
||||
EC_KEY_new_by_curve_name,
|
||||
(int nid),
|
||||
@ -385,6 +368,30 @@ WRAP(int,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_PKEY_verify_init,
|
||||
(EVP_PKEY_CTX *ctx),
|
||||
0,
|
||||
(ctx),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
EVP_PKEY_CTX_ctrl,
|
||||
(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, int p1, void *p2),
|
||||
-1,
|
||||
(ctx, keytype, optype, cmd, p1, p2),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(const EVP_MD *,
|
||||
EVP_sha1,
|
||||
(void),
|
||||
NULL,
|
||||
(),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(const EVP_MD *,
|
||||
EVP_sha256,
|
||||
(void),
|
||||
@ -393,6 +400,22 @@ WRAP(const EVP_MD *,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(const EVP_CIPHER *,
|
||||
EVP_aes_256_cbc,
|
||||
(void),
|
||||
NULL,
|
||||
(),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(const EVP_CIPHER *,
|
||||
EVP_aes_256_gcm,
|
||||
(void),
|
||||
NULL,
|
||||
(),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(unsigned char *,
|
||||
HMAC,
|
||||
(const EVP_MD *evp_md, const void *key, int key_len,
|
||||
@ -436,6 +459,14 @@ WRAP(int,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(unsigned char *,
|
||||
SHA1,
|
||||
(const unsigned char *d, size_t n, unsigned char *md),
|
||||
NULL,
|
||||
(d, n, md),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(unsigned char *,
|
||||
SHA256,
|
||||
(const unsigned char *d, size_t n, unsigned char *md),
|
||||
@ -500,6 +531,14 @@ WRAP(cbor_item_t *,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(cbor_item_t *,
|
||||
cbor_build_uint16,
|
||||
(uint16_t value),
|
||||
NULL,
|
||||
(value),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(cbor_item_t *,
|
||||
cbor_build_uint32,
|
||||
(uint32_t value),
|
||||
@ -508,6 +547,14 @@ WRAP(cbor_item_t *,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(cbor_item_t *,
|
||||
cbor_build_uint64,
|
||||
(uint64_t value),
|
||||
NULL,
|
||||
(value),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(struct cbor_pair *,
|
||||
cbor_map_handle,
|
||||
(const cbor_item_t *item),
|
||||
@ -556,6 +603,14 @@ WRAP(cbor_item_t *,
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(cbor_item_t *,
|
||||
cbor_new_definite_bytestring,
|
||||
(void),
|
||||
NULL,
|
||||
(),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(size_t,
|
||||
cbor_serialize_alloc,
|
||||
(const cbor_item_t *item, cbor_mutable_data *buffer,
|
||||
@ -567,16 +622,16 @@ WRAP(size_t,
|
||||
|
||||
WRAP(int,
|
||||
fido_tx,
|
||||
(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count),
|
||||
(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count, int *ms),
|
||||
-1,
|
||||
(d, cmd, buf, count),
|
||||
(d, cmd, buf, count, ms),
|
||||
1
|
||||
)
|
||||
|
||||
WRAP(int,
|
||||
usleep,
|
||||
(unsigned int usec),
|
||||
bind,
|
||||
(int sockfd, const struct sockaddr *addr, socklen_t addrlen),
|
||||
-1,
|
||||
(usec),
|
||||
(sockfd, addr, addrlen),
|
||||
1
|
||||
)
|
||||
|
@ -1,3 +1,4 @@
|
||||
bind
|
||||
BN_bin2bn
|
||||
BN_bn2bin
|
||||
BN_CTX_get
|
||||
@ -11,31 +12,36 @@ cbor_build_bytestring
|
||||
cbor_build_negint16
|
||||
cbor_build_negint8
|
||||
cbor_build_string
|
||||
cbor_build_uint16
|
||||
cbor_build_uint32
|
||||
cbor_build_uint64
|
||||
cbor_build_uint8
|
||||
cbor_load
|
||||
cbor_map_add
|
||||
cbor_map_handle
|
||||
cbor_new_definite_array
|
||||
cbor_new_definite_bytestring
|
||||
cbor_new_definite_map
|
||||
cbor_serialize_alloc
|
||||
clock_gettime
|
||||
EC_KEY_get0_group
|
||||
EC_KEY_get0_private_key
|
||||
EC_KEY_new_by_curve_name
|
||||
EC_POINT_get_affine_coordinates_GFp
|
||||
EC_POINT_new
|
||||
EVP_aes_256_cbc
|
||||
EVP_aes_256_gcm
|
||||
EVP_Cipher
|
||||
EVP_CIPHER_CTX_ctrl
|
||||
EVP_CIPHER_CTX_new
|
||||
EVP_CIPHER_CTX_set_padding
|
||||
EVP_CipherInit
|
||||
EVP_DecryptInit_ex
|
||||
EVP_DecryptUpdate
|
||||
EVP_DigestFinal_ex
|
||||
EVP_DigestInit_ex
|
||||
EVP_DigestUpdate
|
||||
EVP_DigestVerifyInit
|
||||
EVP_EncryptInit_ex
|
||||
EVP_EncryptUpdate
|
||||
EVP_MD_CTX_new
|
||||
EVP_PKEY_assign
|
||||
EVP_PKEY_CTX_ctrl
|
||||
EVP_PKEY_CTX_new
|
||||
EVP_PKEY_CTX_new_id
|
||||
EVP_PKEY_derive
|
||||
@ -50,6 +56,8 @@ EVP_PKEY_new
|
||||
EVP_PKEY_new_raw_public_key
|
||||
EVP_PKEY_paramgen
|
||||
EVP_PKEY_paramgen_init
|
||||
EVP_PKEY_verify_init
|
||||
EVP_sha1
|
||||
EVP_sha256
|
||||
fido_tx
|
||||
HMAC
|
||||
@ -59,11 +67,12 @@ HMAC_Init_ex
|
||||
HMAC_Update
|
||||
ioctl
|
||||
malloc
|
||||
realloc
|
||||
RSA_new
|
||||
RSA_pkey_ctx_ctrl
|
||||
RSA_set0_key
|
||||
SHA1
|
||||
SHA256
|
||||
SHA256_Final
|
||||
SHA256_Init
|
||||
SHA256_Update
|
||||
strdup
|
||||
udev_device_get_devnode
|
||||
udev_device_get_parent_with_subsystem_devtype
|
||||
|
@ -48,6 +48,7 @@ list(APPEND MAN_ALIAS
|
||||
eddsa_pk_new eddsa_pk_to_EVP_PKEY
|
||||
es256_pk_new es256_pk_free
|
||||
es256_pk_new es256_pk_from_EC_KEY
|
||||
es256_pk_new es256_pk_from_EVP_PKEY
|
||||
es256_pk_new es256_pk_from_ptr
|
||||
es256_pk_new es256_pk_to_EVP_PKEY
|
||||
fido_assert_new fido_assert_authdata_len
|
||||
@ -129,6 +130,10 @@ list(APPEND MAN_ALIAS
|
||||
fido_cbor_info_new fido_cbor_info_versions_len
|
||||
fido_cbor_info_new fido_cbor_info_versions_ptr
|
||||
fido_cbor_info_new fido_dev_get_cbor_info
|
||||
fido_cred_new fido_cred_aaguid_len
|
||||
fido_cred_new fido_cred_aaguid_ptr
|
||||
fido_cred_new fido_cred_attstmt_len
|
||||
fido_cred_new fido_cred_attstmt_ptr
|
||||
fido_cred_new fido_cred_authdata_len
|
||||
fido_cred_new fido_cred_authdata_ptr
|
||||
fido_cred_new fido_cred_authdata_raw_len
|
||||
@ -137,26 +142,25 @@ list(APPEND MAN_ALIAS
|
||||
fido_cred_new fido_cred_clientdata_hash_ptr
|
||||
fido_cred_new fido_cred_display_name
|
||||
fido_cred_new fido_cred_flags
|
||||
fido_cred_new fido_cred_sigcount
|
||||
fido_cred_new fido_cred_fmt
|
||||
fido_cred_new fido_cred_free
|
||||
fido_cred_new fido_cred_id_len
|
||||
fido_cred_new fido_cred_id_ptr
|
||||
fido_cred_new fido_cred_aaguid_len
|
||||
fido_cred_new fido_cred_aaguid_ptr
|
||||
fido_cred_new fido_cred_largeblob_key_len
|
||||
fido_cred_new fido_cred_largeblob_key_ptr
|
||||
fido_cred_new fido_cred_pin_minlen
|
||||
fido_cred_new fido_cred_prot
|
||||
fido_cred_new fido_cred_pubkey_len
|
||||
fido_cred_new fido_cred_pubkey_ptr
|
||||
fido_cred_new fido_cred_rp_id
|
||||
fido_cred_new fido_cred_rp_name
|
||||
fido_cred_new fido_cred_sigcount
|
||||
fido_cred_new fido_cred_sig_len
|
||||
fido_cred_new fido_cred_sig_ptr
|
||||
fido_cred_new fido_cred_type
|
||||
fido_cred_new fido_cred_user_name
|
||||
fido_cred_new fido_cred_user_id_len
|
||||
fido_cred_new fido_cred_user_id_ptr
|
||||
fido_cred_new fido_cred_user_name
|
||||
fido_cred_new fido_cred_x5c_len
|
||||
fido_cred_new fido_cred_x5c_ptr
|
||||
fido_credman_metadata_new fido_credman_del_dev_rk
|
||||
@ -178,6 +182,7 @@ list(APPEND MAN_ALIAS
|
||||
fido_credman_metadata_new fido_credman_rp_name
|
||||
fido_credman_metadata_new fido_credman_rp_new
|
||||
fido_credman_metadata_new fido_credman_set_dev_rk
|
||||
fido_cred_set_authdata fido_cred_set_attstmt
|
||||
fido_cred_set_authdata fido_cred_set_authdata_raw
|
||||
fido_cred_set_authdata fido_cred_set_blob
|
||||
fido_cred_set_authdata fido_cred_set_clientdata
|
||||
@ -185,6 +190,7 @@ list(APPEND MAN_ALIAS
|
||||
fido_cred_set_authdata fido_cred_set_extensions
|
||||
fido_cred_set_authdata fido_cred_set_fmt
|
||||
fido_cred_set_authdata fido_cred_set_id
|
||||
fido_cred_set_authdata fido_cred_set_pin_minlen
|
||||
fido_cred_set_authdata fido_cred_set_prot
|
||||
fido_cred_set_authdata fido_cred_set_rk
|
||||
fido_cred_set_authdata fido_cred_set_rp
|
||||
@ -196,6 +202,7 @@ list(APPEND MAN_ALIAS
|
||||
fido_dev_enable_entattest fido_dev_toggle_always_uv
|
||||
fido_dev_enable_entattest fido_dev_force_pin_change
|
||||
fido_dev_enable_entattest fido_dev_set_pin_minlen
|
||||
fido_dev_enable_entattest fido_dev_set_pin_minlen_rpid
|
||||
fido_dev_get_touch_begin fido_dev_get_touch_status
|
||||
fido_dev_info_manifest fido_dev_info_free
|
||||
fido_dev_info_manifest fido_dev_info_manufacturer_string
|
||||
@ -227,12 +234,14 @@ list(APPEND MAN_ALIAS
|
||||
fido_dev_set_pin fido_dev_get_uv_retry_count
|
||||
fido_dev_set_pin fido_dev_reset
|
||||
fido_dev_set_io_functions fido_dev_set_sigmask
|
||||
fido_dev_set_io_functions fido_dev_set_timeout
|
||||
fido_dev_largeblob_get fido_dev_largeblob_set
|
||||
fido_dev_largeblob_get fido_dev_largeblob_remove
|
||||
fido_dev_largeblob_get fido_dev_largeblob_get_array
|
||||
fido_dev_largeblob_get fido_dev_largeblob_set_array
|
||||
rs256_pk_new rs256_pk_free
|
||||
rs256_pk_new rs256_pk_from_ptr
|
||||
rs256_pk_new rs256_pk_from_EVP_PKEY
|
||||
rs256_pk_new rs256_pk_from_RSA
|
||||
rs256_pk_new rs256_pk_to_EVP_PKEY
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
.\" Use of this source code is governed by a BSD-style
|
||||
.\" license that can be found in the LICENSE file.
|
||||
.\"
|
||||
@ -9,6 +9,7 @@
|
||||
.Nm es256_pk_new ,
|
||||
.Nm es256_pk_free ,
|
||||
.Nm es256_pk_from_EC_KEY ,
|
||||
.Nm es256_pk_from_EVP_KEY ,
|
||||
.Nm es256_pk_from_ptr ,
|
||||
.Nm es256_pk_to_EVP_PKEY
|
||||
.Nd FIDO 2 COSE ES256 API
|
||||
@ -22,6 +23,8 @@
|
||||
.Ft int
|
||||
.Fn es256_pk_from_EC_KEY "es256_pk_t *pk" "const EC_KEY *ec"
|
||||
.Ft int
|
||||
.Fn es256_pk_from_EVP_PKEY "es256_pk_t *pk" "const EVP_PKEY *pkey"
|
||||
.Ft int
|
||||
.Fn es256_pk_from_ptr "es256_pk_t *pk" "const void *ptr" "size_t len"
|
||||
.Ft EVP_PKEY *
|
||||
.Fn es256_pk_to_EVP_PKEY "const es256_pk_t *pk"
|
||||
@ -79,6 +82,16 @@ No references to
|
||||
are kept.
|
||||
.Pp
|
||||
The
|
||||
.Fn es256_pk_from_EVP_KEY
|
||||
function fills
|
||||
.Fa pk
|
||||
with the contents of
|
||||
.Fa pkey .
|
||||
No references to
|
||||
.Fa pkey
|
||||
are kept.
|
||||
.Pp
|
||||
The
|
||||
.Fn es256_pk_from_ptr
|
||||
function fills
|
||||
.Fa pk
|
||||
@ -110,7 +123,8 @@ If an error occurs,
|
||||
returns NULL.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn es256_pk_from_EC_KEY
|
||||
.Fn es256_pk_from_EC_KEY ,
|
||||
.Fn es256_pk_from_EVP_KEY ,
|
||||
and
|
||||
.Fn es256_pk_from_ptr
|
||||
functions return
|
||||
|
@ -82,6 +82,7 @@
|
||||
.Op Fl d
|
||||
.Fl i Ar template_id
|
||||
.Fl n Ar template_name
|
||||
.Ar device
|
||||
.Nm
|
||||
.Fl S
|
||||
.Op Fl d
|
||||
@ -112,6 +113,11 @@
|
||||
.Fl p Ar display_name
|
||||
.Ar device
|
||||
.Nm
|
||||
.Fl S
|
||||
.Fl m
|
||||
.Ar rp_id
|
||||
.Ar device
|
||||
.Nm
|
||||
.Fl V
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
@ -340,6 +346,12 @@ Sets the minimum PIN length of
|
||||
to
|
||||
.Ar pin_length .
|
||||
The user will be prompted for the PIN.
|
||||
.It Fl S Fl m Ar rp_id Ar device
|
||||
Sets the list of relying party IDs that are allowed to retrieve
|
||||
the minimum PIN length of
|
||||
.Ar device .
|
||||
Multiple IDs may be specified, separated by commas.
|
||||
The user will be prompted for the PIN.
|
||||
.It Fl S Fl u Ar device
|
||||
Enables the FIDO 2.1
|
||||
.Dq user verification always
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
.\" Use of this source code is governed by a BSD-style
|
||||
.\" license that can be found in the LICENSE file.
|
||||
.\"
|
||||
@ -8,6 +8,7 @@
|
||||
.Sh NAME
|
||||
.Nm fido_cred_new ,
|
||||
.Nm fido_cred_free ,
|
||||
.Nm fido_cred_pin_minlen ,
|
||||
.Nm fido_cred_prot ,
|
||||
.Nm fido_cred_fmt ,
|
||||
.Nm fido_cred_rp_id ,
|
||||
@ -24,6 +25,7 @@
|
||||
.Nm fido_cred_sig_ptr ,
|
||||
.Nm fido_cred_user_id_ptr ,
|
||||
.Nm fido_cred_x5c_ptr ,
|
||||
.Nm fido_cred_attstmt_ptr ,
|
||||
.Nm fido_cred_authdata_len ,
|
||||
.Nm fido_cred_authdata_raw_len ,
|
||||
.Nm fido_cred_clientdata_hash_len ,
|
||||
@ -34,6 +36,7 @@
|
||||
.Nm fido_cred_sig_len ,
|
||||
.Nm fido_cred_user_id_len ,
|
||||
.Nm fido_cred_x5c_len ,
|
||||
.Nm fido_cred_attstmt_len ,
|
||||
.Nm fido_cred_type ,
|
||||
.Nm fido_cred_flags ,
|
||||
.Nm fido_cred_sigcount
|
||||
@ -44,8 +47,10 @@
|
||||
.Fn fido_cred_new "void"
|
||||
.Ft void
|
||||
.Fn fido_cred_free "fido_cred_t **cred_p"
|
||||
.Ft size_t
|
||||
.Fn fido_cred_pin_minlen "const fido_cred_t *cred"
|
||||
.Ft int
|
||||
.Fn fido_cred_prot "fido_cred_t *cred"
|
||||
.Fn fido_cred_prot "const fido_cred_t *cred"
|
||||
.Ft const char *
|
||||
.Fn fido_cred_fmt "const fido_cred_t *cred"
|
||||
.Ft const char *
|
||||
@ -76,6 +81,8 @@
|
||||
.Fn fido_cred_user_id_ptr "const fido_cred_t *cred"
|
||||
.Ft const unsigned char *
|
||||
.Fn fido_cred_x5c_ptr "const fido_cred_t *cred"
|
||||
.Ft const unsigned char *
|
||||
.Fn fido_cred_attstmt_ptr "const fido_cred_t *cred"
|
||||
.Ft size_t
|
||||
.Fn fido_cred_authdata_len "const fido_cred_t *cred"
|
||||
.Ft size_t
|
||||
@ -96,6 +103,8 @@
|
||||
.Fn fido_cred_user_id_len "const fido_cred_t *cred"
|
||||
.Ft size_t
|
||||
.Fn fido_cred_x5c_len "const fido_cred_t *cred"
|
||||
.Ft size_t
|
||||
.Fn fido_cred_attstmt_len "const fido_cred_t *cred"
|
||||
.Ft int
|
||||
.Fn fido_cred_type "const fido_cred_t *cred"
|
||||
.Ft uint8_t
|
||||
@ -146,13 +155,35 @@ may be NULL, in which case
|
||||
.Fn fido_cred_free
|
||||
is a NOP.
|
||||
.Pp
|
||||
The
|
||||
If the FIDO 2.1
|
||||
.Dv FIDO_EXT_MINPINLEN
|
||||
extension is enabled on
|
||||
.Fa cred ,
|
||||
then the
|
||||
.Fn fido_cred_pin_minlen
|
||||
function returns the minimum PIN length of
|
||||
.Fa cred .
|
||||
Otherwise,
|
||||
.Fn fido_cred_pin_minlen
|
||||
returns zero.
|
||||
See
|
||||
.Xr fido_cred_set_pin_minlen 3
|
||||
on how to enable this extension.
|
||||
.Pp
|
||||
If the FIDO 2.1
|
||||
.Dv FIDO_EXT_CRED_PROTECT
|
||||
extension is enabled on
|
||||
.Fa cred ,
|
||||
then the
|
||||
.Fn fido_cred_prot
|
||||
function returns the protection of
|
||||
.Fa cred .
|
||||
Otherwise,
|
||||
.Fn fido_cred_prot
|
||||
returns zero.
|
||||
See
|
||||
.Xr fido_cred_set_prot 3
|
||||
for the values understood by
|
||||
for the protection policies understood by
|
||||
.Em libfido2 .
|
||||
.Pp
|
||||
The
|
||||
@ -186,12 +217,14 @@ The
|
||||
.Fn fido_cred_pubkey_ptr ,
|
||||
.Fn fido_cred_sig_ptr ,
|
||||
.Fn fido_cred_user_id_ptr ,
|
||||
.Fn fido_cred_x5c_ptr ,
|
||||
and
|
||||
.Fn fido_cred_x5c_ptr
|
||||
.Fn fido_cred_attstmt_ptr
|
||||
functions return pointers to the CBOR-encoded and raw authenticator
|
||||
data, client data hash, ID, authenticator attestation GUID,
|
||||
.Dq largeBlobKey ,
|
||||
public key, signature, user ID, and x509 certificate parts of
|
||||
public key, signature, user ID, x509 certificate, and attestation
|
||||
statement parts of
|
||||
.Fa cred ,
|
||||
or NULL if the respective entry is not set.
|
||||
.Pp
|
||||
@ -205,8 +238,9 @@ The corresponding length can be obtained by
|
||||
.Fn fido_cred_pubkey_len ,
|
||||
.Fn fido_cred_sig_len ,
|
||||
.Fn fido_cred_user_id_len ,
|
||||
.Fn fido_cred_x5c_len ,
|
||||
and
|
||||
.Fn fido_cred_x5c_len .
|
||||
.Fn fido_cred_attstmt_len .
|
||||
.Pp
|
||||
The authenticator data, x509 certificate, and signature parts of a
|
||||
credential are typically passed to a FIDO 2 server for verification.
|
||||
@ -251,6 +285,8 @@ qualifier is invoked.
|
||||
.Sh SEE ALSO
|
||||
.Xr fido_cred_exclude 3 ,
|
||||
.Xr fido_cred_set_authdata 3 ,
|
||||
.Xr fido_cred_set_pin_minlen 3 ,
|
||||
.Xr fido_cred_set_prot 3 ,
|
||||
.Xr fido_cred_verify 3 ,
|
||||
.Xr fido_credman_metadata_new 3 ,
|
||||
.Xr fido_dev_largeblob_get 3 ,
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
.\" Use of this source code is governed by a BSD-style
|
||||
.\" license that can be found in the LICENSE file.
|
||||
.\"
|
||||
@ -8,6 +8,7 @@
|
||||
.Sh NAME
|
||||
.Nm fido_cred_set_authdata ,
|
||||
.Nm fido_cred_set_authdata_raw ,
|
||||
.Nm fido_cred_set_attstmt ,
|
||||
.Nm fido_cred_set_x509 ,
|
||||
.Nm fido_cred_set_sig ,
|
||||
.Nm fido_cred_set_id ,
|
||||
@ -17,6 +18,7 @@
|
||||
.Nm fido_cred_set_user ,
|
||||
.Nm fido_cred_set_extensions ,
|
||||
.Nm fido_cred_set_blob ,
|
||||
.Nm fido_cred_set_pin_minlen ,
|
||||
.Nm fido_cred_set_prot ,
|
||||
.Nm fido_cred_set_rk ,
|
||||
.Nm fido_cred_set_uv ,
|
||||
@ -37,6 +39,8 @@ typedef enum {
|
||||
.Ft int
|
||||
.Fn fido_cred_set_authdata_raw "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
|
||||
.Ft int
|
||||
.Fn fido_cred_set_attstmt "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
|
||||
.Ft int
|
||||
.Fn fido_cred_set_x509 "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
|
||||
.Ft int
|
||||
.Fn fido_cred_set_sig "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
|
||||
@ -55,6 +59,8 @@ typedef enum {
|
||||
.Ft int
|
||||
.Fn fido_cred_set_blob "fido_cred_t *cred" "const unsigned char *ptr" "size_t len"
|
||||
.Ft int
|
||||
.Fn fido_cred_set_pin_minlen "fido_cred_t *cred" "size_t len"
|
||||
.Ft int
|
||||
.Fn fido_cred_set_prot "fido_cred_t *cred" "int prot"
|
||||
.Ft int
|
||||
.Fn fido_cred_set_rk "fido_cred_t *cred" "fido_opt_t rk"
|
||||
@ -80,13 +86,15 @@ of its constituent parts, please refer to the Web Authentication
|
||||
.Pp
|
||||
The
|
||||
.Fn fido_cred_set_authdata ,
|
||||
.Fn fido_cred_set_attstmt ,
|
||||
.Fn fido_cred_set_x509 ,
|
||||
.Fn fido_cred_set_sig ,
|
||||
.Fn fido_cred_set_id ,
|
||||
and
|
||||
.Fn fido_cred_set_clientdata_hash
|
||||
functions set the authenticator data, attestation certificate,
|
||||
signature, id, and client data hash parts of
|
||||
functions set the authenticator data, attestation statement,
|
||||
attestation certificate, attestation signature, id, and client
|
||||
data hash parts of
|
||||
.Fa cred
|
||||
to
|
||||
.Fa ptr ,
|
||||
@ -98,13 +106,13 @@ bytes.
|
||||
A copy of
|
||||
.Fa ptr
|
||||
is made, and no references to the passed pointer are kept.
|
||||
.Pp
|
||||
The authenticator data passed to
|
||||
.Fn fido_cred_set_authdata
|
||||
must be a CBOR-encoded byte string, as obtained from
|
||||
.Fn fido_cred_authdata_ptr .
|
||||
Alternatively, a raw binary blob may be passed to
|
||||
.Fn fido_cred_set_authdata_raw .
|
||||
.Pp
|
||||
An application calling
|
||||
.Fn fido_cred_set_authdata
|
||||
does not need to call
|
||||
@ -112,6 +120,20 @@ does not need to call
|
||||
The latter is meant to be used in contexts where the
|
||||
credential's authenticator data is not available.
|
||||
.Pp
|
||||
The attestation statement passed to
|
||||
.Fn fido_cred_set_attstmt
|
||||
must be a CBOR-encoded map, as obtained from
|
||||
.Fn fido_cred_attstmt_ptr .
|
||||
An application calling
|
||||
.Fn fido_cred_set_attstmt
|
||||
does not need to call
|
||||
.Fn fido_cred_set_x509
|
||||
or
|
||||
.Fn fido_cred_set_sig .
|
||||
The latter two are meant to be used in contexts where the
|
||||
credential's complete attestation statement is not available or
|
||||
required.
|
||||
.Pp
|
||||
The
|
||||
.Fn fido_cred_set_clientdata
|
||||
function allows an application to set the client data hash of
|
||||
@ -183,6 +205,7 @@ At the moment, only the
|
||||
.Dv FIDO_EXT_CRED_BLOB ,
|
||||
.Dv FIDO_EXT_CRED_PROTECT ,
|
||||
.Dv FIDO_EXT_HMAC_SECRET ,
|
||||
.Dv FIDO_EXT_MINPINLEN ,
|
||||
and
|
||||
.Dv FIDO_EXT_LARGEBLOB_KEY
|
||||
extensions are supported.
|
||||
@ -205,8 +228,32 @@ which must be
|
||||
bytes long.
|
||||
.Pp
|
||||
The
|
||||
.Fn fido_cred_set_pin_minlen
|
||||
function enables the FIDO 2.1
|
||||
.Dv FIDO_EXT_MINPINLEN
|
||||
extension on
|
||||
.Fa cred
|
||||
and sets the expected minimum PIN length of
|
||||
.Fa cred
|
||||
to
|
||||
.Fa len ,
|
||||
where
|
||||
.Fa len
|
||||
is greater than zero.
|
||||
If
|
||||
.Fa len
|
||||
is zero, the
|
||||
.Dv FIDO_EXT_MINPINLEN
|
||||
extension is disabled on
|
||||
.Fa cred .
|
||||
.Pp
|
||||
The
|
||||
.Fn fido_cred_set_prot
|
||||
function sets the protection of
|
||||
function enables the FIDO 2.1
|
||||
.Dv FIDO_EXT_CRED_PROTECT
|
||||
extension on
|
||||
.Fa cred
|
||||
and sets the protection of
|
||||
.Fa cred
|
||||
to the scalar
|
||||
.Fa prot .
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
.\" Use of this source code is governed by a BSD-style
|
||||
.\" license that can be found in the LICENSE file.
|
||||
.\"
|
||||
@ -29,8 +29,8 @@ A brief description follows:
|
||||
The
|
||||
.Fn fido_cred_verify
|
||||
function verifies whether the client data hash, relying party ID,
|
||||
credential ID, type, and resident/discoverable key and user verification
|
||||
attributes of
|
||||
credential ID, type, protection policy, minimum PIN length, and
|
||||
resident/discoverable key and user verification attributes of
|
||||
.Fa cred
|
||||
have been attested by the holder of the private counterpart of
|
||||
the public key contained in the credential's x509 certificate.
|
||||
@ -40,14 +40,14 @@ Please note that the x509 certificate itself is not verified.
|
||||
The attestation statement formats supported by
|
||||
.Fn fido_cred_verify
|
||||
are
|
||||
.Em packed
|
||||
.Em packed ,
|
||||
.Em fido-u2f ,
|
||||
and
|
||||
.Em fido-u2f .
|
||||
.Em tpm .
|
||||
The attestation type implemented by
|
||||
.Fn fido_cred_verify
|
||||
is
|
||||
.Em Basic Attestation .
|
||||
The attestation key pair is assumed to be of the type ES256.
|
||||
Other attestation formats and types are not supported.
|
||||
.Sh RETURN VALUES
|
||||
The error codes returned by
|
||||
|
@ -9,7 +9,8 @@
|
||||
.Nm fido_dev_enable_entattest ,
|
||||
.Nm fido_dev_toggle_always_uv ,
|
||||
.Nm fido_dev_force_pin_change ,
|
||||
.Nm fido_dev_set_pin_minlen
|
||||
.Nm fido_dev_set_pin_minlen ,
|
||||
.Nm fido_dev_set_pin_minlen_rpid
|
||||
.Nd FIDO 2.1 configuration authenticator API
|
||||
.Sh SYNOPSIS
|
||||
.In fido.h
|
||||
@ -22,6 +23,8 @@
|
||||
.Fn fido_dev_force_pin_change "fido_dev_t *dev" "const char *pin"
|
||||
.Ft int
|
||||
.Fn fido_dev_set_pin_minlen "fido_dev_t *dev" "size_t len" "const char *pin"
|
||||
.Ft int
|
||||
.Fn fido_dev_set_pin_minlen_rpid "fido_dev_t *dev" "const char * const *rpid" "size_t n" "const char *pin"
|
||||
.Sh DESCRIPTION
|
||||
The functions described in this page allow configuration of a
|
||||
FIDO 2.1 authenticator.
|
||||
@ -77,6 +80,24 @@ to
|
||||
.Fa len .
|
||||
Minimum PIN lengths may only be increased.
|
||||
.Pp
|
||||
The
|
||||
.Fn fido_dev_set_pin_minlen_rpid
|
||||
function sets the list of relying party identifiers
|
||||
.Pq RP IDs
|
||||
that are allowed to obtain the minimum PIN length of
|
||||
.Fa dev
|
||||
through the FIDO 2.1
|
||||
.Dv FIDO_EXT_MINPINLEN
|
||||
extension.
|
||||
The list of RP identifiers is denoted by
|
||||
.Fa rpid ,
|
||||
a vector of
|
||||
.Fa n
|
||||
NUL-terminated UTF-8 strings.
|
||||
A copy of
|
||||
.Fa rpid
|
||||
is made, and no reference to it or its contents is kept.
|
||||
.Pp
|
||||
Configuration settings are reflected in the payload returned by the
|
||||
authenticator in response to a
|
||||
.Xr fido_dev_get_cbor_info 3
|
||||
@ -86,13 +107,15 @@ The error codes returned by
|
||||
.Fn fido_dev_enable_entattest ,
|
||||
.Fn fido_dev_toggle_always_uv ,
|
||||
.Fn fido_dev_force_pin_change ,
|
||||
.Fn fido_dev_set_pin_minlen ,
|
||||
and
|
||||
.Fn fido_dev_set_pin_minlen
|
||||
.Fn fido_dev_set_pin_minlen_rpid
|
||||
are defined in
|
||||
.In fido/err.h .
|
||||
On success,
|
||||
.Dv FIDO_OK
|
||||
is returned.
|
||||
.Sh SEE ALSO
|
||||
.Xr fido_cred_pin_minlen 3 ,
|
||||
.Xr fido_dev_get_cbor_info 3 ,
|
||||
.Xr fido_dev_reset 3
|
||||
|
@ -112,11 +112,21 @@ The
|
||||
.Fn fido_dev_info_manufacturer_string
|
||||
function returns the manufacturer string of
|
||||
.Fa di .
|
||||
If
|
||||
.Fa di
|
||||
does not have an associated manufacturer string,
|
||||
.Fn fido_dev_info_manufacturer_string
|
||||
returns an empty string.
|
||||
.Pp
|
||||
The
|
||||
.Fn fido_dev_info_product_string
|
||||
function returns the product string of
|
||||
.Fa di .
|
||||
If
|
||||
.Fa di
|
||||
does not have an associated product string,
|
||||
.Fn fido_dev_info_product_string
|
||||
returns an empty string.
|
||||
.Pp
|
||||
An example of how to use the functions described in this document
|
||||
can be found in the
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
.\" Use of this source code is governed by a BSD-style
|
||||
.\" license that can be found in the LICENSE file.
|
||||
.\"
|
||||
@ -7,7 +7,8 @@
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm fido_dev_set_io_functions ,
|
||||
.Nm fido_dev_set_sigmask
|
||||
.Nm fido_dev_set_sigmask ,
|
||||
.Nm fido_dev_set_timeout
|
||||
.Nd FIDO 2 device I/O interface
|
||||
.Sh SYNOPSIS
|
||||
.In fido.h
|
||||
@ -34,6 +35,8 @@ typedef sigset_t fido_sigset_t;
|
||||
.Fn fido_dev_set_io_functions "fido_dev_t *dev" "const fido_dev_io_t *io"
|
||||
.Ft int
|
||||
.Fn fido_dev_set_sigmask "fido_dev_t *dev" "const fido_sigset_t *sigmask"
|
||||
.Ft int
|
||||
.Fn fido_dev_set_timeout "fido_dev_t *dev" "int ms"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn fido_dev_set_io_functions
|
||||
@ -122,11 +125,35 @@ No references to
|
||||
.Fa sigmask
|
||||
are held by
|
||||
.Fn fido_dev_set_sigmask .
|
||||
.Pp
|
||||
The
|
||||
.Fn fido_dev_set_timeout
|
||||
function informs
|
||||
.Em libfido2
|
||||
not to block for more than
|
||||
.Fa ms
|
||||
milliseconds while communicating with
|
||||
.Fa dev .
|
||||
If a timeout occurs, the corresponding
|
||||
.Em fido_dev_*
|
||||
function will fail with
|
||||
.Dv FIDO_ERR_RX .
|
||||
If
|
||||
.Fa ms
|
||||
is -1,
|
||||
then
|
||||
.Em libfido2
|
||||
may block indefinitely.
|
||||
This is the default behaviour.
|
||||
When using the Windows Hello backend,
|
||||
.Fa ms
|
||||
is used as a guidance and may be overwritten by the platform.
|
||||
.Sh RETURN VALUES
|
||||
On success,
|
||||
.Fn fido_dev_set_io_functions
|
||||
.Fn fido_dev_set_io_functions ,
|
||||
.Fn fido_dev_set_sigmask ,
|
||||
and
|
||||
.Fn fido_dev_set_sigmask
|
||||
.Fn fido_dev_set_timeout
|
||||
return
|
||||
.Dv FIDO_OK .
|
||||
On error, a different error code defined in
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
.\" Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
.\" Use of this source code is governed by a BSD-style
|
||||
.\" license that can be found in the LICENSE file.
|
||||
.\"
|
||||
@ -8,6 +8,7 @@
|
||||
.Sh NAME
|
||||
.Nm rs256_pk_new ,
|
||||
.Nm rs256_pk_free ,
|
||||
.Nm rs256_pk_from_EVP_PKEY ,
|
||||
.Nm rs256_pk_from_RSA ,
|
||||
.Nm rs256_pk_from_ptr ,
|
||||
.Nm rs256_pk_to_EVP_PKEY
|
||||
@ -20,6 +21,8 @@
|
||||
.Ft void
|
||||
.Fn rs256_pk_free "rs256_pk_t **pkp"
|
||||
.Ft int
|
||||
.Fn rs256_pk_from_EVP_PKEY "rs256_pk_t *pk" "const EVP_PKEY *pkey"
|
||||
.Ft int
|
||||
.Fn rs256_pk_from_RSA "rs256_pk_t *pk" "const RSA *rsa"
|
||||
.Ft int
|
||||
.Fn rs256_pk_from_ptr "rs256_pk_t *pk" "const void *ptr" "size_t len"
|
||||
@ -69,6 +72,16 @@ may be NULL, in which case
|
||||
is a NOP.
|
||||
.Pp
|
||||
The
|
||||
.Fn rs256_pk_from_EVP_PKEY
|
||||
function fills
|
||||
.Fa pk
|
||||
with the contents of
|
||||
.Fa pkey .
|
||||
No references to
|
||||
.Fa pkey
|
||||
are kept.
|
||||
.Pp
|
||||
The
|
||||
.Fn rs256_pk_from_RSA
|
||||
function fills
|
||||
.Fa pk
|
||||
@ -106,7 +119,8 @@ If an error occurs,
|
||||
returns NULL.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn rs256_pk_from_RSA
|
||||
.Fn rs256_pk_from_EVP_PKEY ,
|
||||
.Fn rs256_pk_from_RSA ,
|
||||
and
|
||||
.Fn rs256_pk_from_ptr
|
||||
functions return
|
||||
|
@ -1,124 +0,0 @@
|
||||
/* $OpenBSD: hkdf.c,v 1.4 2019/11/21 20:02:20 tim Exp $ */
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "openbsd-compat.h"
|
||||
#include "fido.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
#define CRYPTOerror(r) CRYPTOerr(ERR_LIB_CRYPTO, (r))
|
||||
|
||||
/* https://tools.ietf.org/html/rfc5869#section-2 */
|
||||
int
|
||||
HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest,
|
||||
const uint8_t *secret, size_t secret_len, const uint8_t *salt,
|
||||
size_t salt_len, const uint8_t *info, size_t info_len)
|
||||
{
|
||||
uint8_t prk[EVP_MAX_MD_SIZE];
|
||||
size_t prk_len;
|
||||
|
||||
if (!HKDF_extract(prk, &prk_len, digest, secret, secret_len, salt,
|
||||
salt_len))
|
||||
return 0;
|
||||
if (!HKDF_expand(out_key, out_len, digest, prk, prk_len, info,
|
||||
info_len))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* https://tools.ietf.org/html/rfc5869#section-2.2 */
|
||||
int
|
||||
HKDF_extract(uint8_t *out_key, size_t *out_len,
|
||||
const EVP_MD *digest, const uint8_t *secret, size_t secret_len,
|
||||
const uint8_t *salt, size_t salt_len)
|
||||
{
|
||||
unsigned int len;
|
||||
|
||||
/*
|
||||
* If salt is not given, HashLength zeros are used. However, HMAC does
|
||||
* that internally already so we can ignore it.
|
||||
*/
|
||||
if (salt_len > INT_MAX || HMAC(digest, salt, (int)salt_len, secret,
|
||||
secret_len, out_key, &len) == NULL) {
|
||||
CRYPTOerror(ERR_R_CRYPTO_LIB);
|
||||
return 0;
|
||||
}
|
||||
*out_len = len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* https://tools.ietf.org/html/rfc5869#section-2.3 */
|
||||
int
|
||||
HKDF_expand(uint8_t *out_key, size_t out_len,
|
||||
const EVP_MD *digest, const uint8_t *prk, size_t prk_len,
|
||||
const uint8_t *info, size_t info_len)
|
||||
{
|
||||
const size_t digest_len = EVP_MD_size(digest);
|
||||
uint8_t previous[EVP_MAX_MD_SIZE];
|
||||
size_t n, done = 0;
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
HMAC_CTX hmac;
|
||||
|
||||
/* Expand key material to desired length. */
|
||||
n = (out_len + digest_len - 1) / digest_len;
|
||||
if (out_len + digest_len < out_len || n > 255 || prk_len > INT_MAX) {
|
||||
CRYPTOerror(EVP_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HMAC_CTX_init(&hmac);
|
||||
if (!HMAC_Init_ex(&hmac, prk, (int)prk_len, digest, NULL))
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
uint8_t ctr = i + 1;
|
||||
size_t todo;
|
||||
|
||||
if (i != 0 && (!HMAC_Init_ex(&hmac, NULL, 0, NULL, NULL) ||
|
||||
!HMAC_Update(&hmac, previous, digest_len)))
|
||||
goto out;
|
||||
|
||||
if (!HMAC_Update(&hmac, info, info_len) ||
|
||||
!HMAC_Update(&hmac, &ctr, 1) ||
|
||||
!HMAC_Final(&hmac, previous, NULL))
|
||||
goto out;
|
||||
|
||||
todo = digest_len;
|
||||
if (done + todo > out_len)
|
||||
todo = out_len - done;
|
||||
|
||||
memcpy(out_key + done, previous, todo);
|
||||
done += todo;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
out:
|
||||
HMAC_CTX_cleanup(&hmac);
|
||||
explicit_bzero(previous, sizeof(previous));
|
||||
if (ret != 1)
|
||||
CRYPTOerror(ERR_R_CRYPTO_LIB);
|
||||
return ret;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
@ -1,65 +0,0 @@
|
||||
/* $OpenBSD: hkdf.h,v 1.2 2018/04/03 13:33:53 tb Exp $ */
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#ifndef OPENSSL_HEADER_HKDF_H
|
||||
#define OPENSSL_HEADER_HKDF_H
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* HKDF computes HKDF (as specified by RFC 5869) of initial keying
|
||||
* material |secret| with |salt| and |info| using |digest|, and
|
||||
* outputs |out_len| bytes to |out_key|. It returns one on success and
|
||||
* zero on error.
|
||||
*
|
||||
* HKDF is an Extract-and-Expand algorithm. It does not do any key
|
||||
* stretching, and as such, is not suited to be used alone to generate
|
||||
* a key from a password.
|
||||
*/
|
||||
|
||||
int HKDF(uint8_t *out_key, size_t out_len, const struct env_md_st *digest,
|
||||
const uint8_t *secret, size_t secret_len, const uint8_t *salt,
|
||||
size_t salt_len, const uint8_t *info, size_t info_len);
|
||||
|
||||
/*
|
||||
* HKDF_extract computes a HKDF PRK (as specified by RFC 5869) from
|
||||
* initial keying material |secret| and salt |salt| using |digest|,
|
||||
* and outputs |out_len| bytes to |out_key|. The maximum output size
|
||||
* is |EVP_MAX_MD_SIZE|. It returns one on success and zero on error.
|
||||
*/
|
||||
int HKDF_extract(uint8_t *out_key, size_t *out_len,
|
||||
const struct env_md_st *digest, const uint8_t *secret,
|
||||
size_t secret_len, const uint8_t *salt, size_t salt_len);
|
||||
|
||||
/*
|
||||
* HKDF_expand computes a HKDF OKM (as specified by RFC 5869) of
|
||||
* length |out_len| from the PRK |prk| and info |info| using |digest|,
|
||||
* and outputs the result to |out_key|. It returns one on success and
|
||||
* zero on error.
|
||||
*/
|
||||
int HKDF_expand(uint8_t *out_key, size_t out_len,
|
||||
const EVP_MD *digest, const uint8_t *prk, size_t prk_len,
|
||||
const uint8_t *info, size_t info_len);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_HKDF_H */
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -20,6 +20,7 @@
|
||||
#define be16toh(x) OSSwapBigToHostInt16((x))
|
||||
#define htobe16(x) OSSwapHostToBigInt16((x))
|
||||
#define be32toh(x) OSSwapBigToHostInt32((x))
|
||||
#define htobe32(x) OSSwapHostToBigInt32((x))
|
||||
#define htole32(x) OSSwapHostToLittleInt32((x))
|
||||
#define htole64(x) OSSwapHostToLittleInt64((x))
|
||||
#endif /* __APPLE__ && !HAVE_ENDIAN_H */
|
||||
@ -33,11 +34,12 @@
|
||||
#define be16toh(x) ntohs((x))
|
||||
#define htobe16(x) htons((x))
|
||||
#define be32toh(x) ntohl((x))
|
||||
#define htobe32(x) htonl((x))
|
||||
uint32_t htole32(uint32_t);
|
||||
uint64_t htole64(uint64_t);
|
||||
#endif /* _WIN32 && !HAVE_ENDIAN_H */
|
||||
|
||||
#if defined(__FreeBSD__) && !defined(HAVE_ENDIAN_H)
|
||||
#if (defined(__FreeBSD__) || defined(__MidnightBSD__)) && !defined(HAVE_ENDIAN_H)
|
||||
#include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
@ -52,6 +54,10 @@ size_t strlcat(char *, const char *, size_t);
|
||||
size_t strlcpy(char *, const char *, size_t);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_STRSEP)
|
||||
char *strsep(char **, const char *);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_RECALLOCARRAY)
|
||||
void *recallocarray(void *, size_t, size_t, size_t);
|
||||
#endif
|
||||
@ -80,13 +86,6 @@ int timingsafe_bcmp(const void *, const void *, size_t);
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
#include <stdint.h>
|
||||
#include "hkdf.h"
|
||||
#define EVP_PKEY_get0_EC_KEY(x) ((x)->pkey.ec)
|
||||
#define EVP_PKEY_get0_RSA(x) ((x)->pkey.rsa)
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_ERR_H)
|
||||
#include "err.h"
|
||||
#else
|
||||
|
79
openbsd-compat/strsep.c
Normal file
79
openbsd-compat/strsep.c
Normal file
@ -0,0 +1,79 @@
|
||||
/* $OpenBSD: strsep.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* OPENBSD ORIGINAL: lib/libc/string/strsep.c */
|
||||
|
||||
#include "openbsd-compat.h"
|
||||
|
||||
#if !defined(HAVE_STRSEP)
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Get next token from string *stringp, where tokens are possibly-empty
|
||||
* strings separated by characters from delim.
|
||||
*
|
||||
* Writes NULs into the string at *stringp to end tokens.
|
||||
* delim need not remain constant from call to call.
|
||||
* On return, *stringp points past the last NUL written (if there might
|
||||
* be further tokens), or is NULL (if there are definitely no more tokens).
|
||||
*
|
||||
* If *stringp is NULL, strsep returns NULL.
|
||||
*/
|
||||
char *
|
||||
strsep(char **stringp, const char *delim)
|
||||
{
|
||||
char *s;
|
||||
const char *spanp;
|
||||
int c, sc;
|
||||
char *tok;
|
||||
|
||||
if ((s = *stringp) == NULL)
|
||||
return (NULL);
|
||||
for (tok = s;;) {
|
||||
c = *s++;
|
||||
spanp = delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = 0;
|
||||
*stringp = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#endif /* !defined(HAVE_STRSEP) */
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
# Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
@ -7,10 +7,14 @@ add_custom_target(regress ALL)
|
||||
macro(add_regress_test NAME SOURCES)
|
||||
add_executable(${NAME} ${SOURCES})
|
||||
target_link_libraries(${NAME} fido2_shared)
|
||||
add_custom_command(TARGET regress POST_BUILD COMMAND ${NAME}
|
||||
DEPENDS ${NAME})
|
||||
add_test(${NAME} ${NAME})
|
||||
add_dependencies(regress ${NAME})
|
||||
endmacro()
|
||||
|
||||
add_custom_command(TARGET regress POST_BUILD
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
add_regress_test(regress_cred cred.c)
|
||||
add_regress_test(regress_assert assert.c)
|
||||
add_regress_test(regress_dev dev.c)
|
||||
|
@ -1,9 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#define _FIDO_INTERNAL
|
||||
|
||||
#include <assert.h>
|
||||
#include <fido.h>
|
||||
#include <fido/es256.h>
|
||||
@ -24,6 +26,42 @@ static const unsigned char es256_pk[64] = {
|
||||
0x64, 0x1a, 0x1d, 0xf8, 0xbe, 0x14, 0x90, 0x8a,
|
||||
};
|
||||
|
||||
static const unsigned char rs256_pk[259] = {
|
||||
0x9e, 0x54, 0x78, 0xb2, 0x51, 0xbe, 0x19, 0x7c,
|
||||
0xcb, 0x1a, 0x9a, 0xc3, 0x49, 0x2a, 0x2f, 0xfd,
|
||||
0x99, 0x64, 0x76, 0xc6, 0xdb, 0xca, 0x38, 0x3f,
|
||||
0xb0, 0x6a, 0xc9, 0xc0, 0x07, 0x9f, 0x5c, 0x4d,
|
||||
0xfc, 0xd1, 0x01, 0x7f, 0x69, 0x65, 0xab, 0x9c,
|
||||
0x2a, 0xc2, 0x95, 0xd9, 0x44, 0xf3, 0xea, 0x94,
|
||||
0x6b, 0x25, 0x66, 0x54, 0x81, 0xee, 0x24, 0x1d,
|
||||
0xe1, 0x7d, 0x7f, 0xbe, 0xea, 0x76, 0x90, 0x5c,
|
||||
0xbf, 0x59, 0x22, 0xd3, 0xa0, 0x68, 0x1a, 0x65,
|
||||
0x8b, 0x2f, 0xb6, 0xa8, 0x30, 0x2d, 0x26, 0x81,
|
||||
0xfa, 0x9e, 0x59, 0xec, 0x2f, 0xee, 0x59, 0x39,
|
||||
0xe2, 0x79, 0x19, 0x54, 0x54, 0xdf, 0x24, 0x83,
|
||||
0xee, 0x61, 0x5a, 0x66, 0x24, 0x2b, 0x7b, 0xfb,
|
||||
0x82, 0x66, 0xe4, 0x85, 0x18, 0x20, 0x76, 0xe5,
|
||||
0x4a, 0xb6, 0xcb, 0xec, 0x43, 0xbe, 0xfd, 0xb0,
|
||||
0x8f, 0xfd, 0x2f, 0x69, 0xda, 0x06, 0x9c, 0x09,
|
||||
0x68, 0x7a, 0x94, 0x6c, 0xb7, 0x51, 0x6d, 0x4c,
|
||||
0xf7, 0x13, 0xe8, 0xd5, 0x22, 0x6b, 0x1e, 0xba,
|
||||
0xb9, 0x85, 0xe8, 0x5f, 0xa1, 0x66, 0xe3, 0x20,
|
||||
0x75, 0x30, 0x11, 0xb5, 0xa3, 0xc3, 0xb0, 0x72,
|
||||
0x08, 0xff, 0xa3, 0xbb, 0xf1, 0x32, 0x0b, 0x06,
|
||||
0xc4, 0x12, 0xa3, 0x49, 0x30, 0x19, 0xb9, 0xfe,
|
||||
0x69, 0x0c, 0xd6, 0xe1, 0x58, 0x36, 0xe6, 0x41,
|
||||
0x22, 0x41, 0xbf, 0x96, 0x50, 0x35, 0x56, 0x0d,
|
||||
0x92, 0x8c, 0x34, 0xea, 0x28, 0x91, 0x88, 0x9e,
|
||||
0x8a, 0xaa, 0x36, 0xd0, 0x0f, 0xbe, 0x16, 0xde,
|
||||
0x9d, 0x5f, 0x7b, 0xda, 0x52, 0xf7, 0xf1, 0xb6,
|
||||
0x28, 0x10, 0x05, 0x8f, 0xb9, 0x19, 0x7a, 0xcf,
|
||||
0x18, 0x9b, 0x40, 0xcd, 0xff, 0x78, 0xea, 0x61,
|
||||
0x24, 0x3b, 0x80, 0x68, 0x04, 0x9b, 0x40, 0x07,
|
||||
0x98, 0xd4, 0x94, 0xd1, 0x18, 0x44, 0xa5, 0xed,
|
||||
0xee, 0x18, 0xc2, 0x25, 0x52, 0x66, 0x42, 0xdf,
|
||||
0x01, 0x00, 0x01,
|
||||
};
|
||||
|
||||
static const unsigned char cdh[32] = {
|
||||
0xec, 0x8d, 0x8f, 0x78, 0x42, 0x4a, 0x2b, 0xb7,
|
||||
0x82, 0x34, 0xaa, 0xca, 0x07, 0xa1, 0xf6, 0x56,
|
||||
@ -397,7 +435,7 @@ junk_cdh(void)
|
||||
junk = malloc(sizeof(cdh));
|
||||
assert(junk != NULL);
|
||||
memcpy(junk, cdh, sizeof(cdh));
|
||||
junk[0] = ~junk[0];
|
||||
junk[0] = (unsigned char)~junk[0];
|
||||
|
||||
a = alloc_assert();
|
||||
pk = alloc_es256_pk();
|
||||
@ -448,7 +486,7 @@ junk_authdata(void)
|
||||
junk = malloc(sizeof(authdata));
|
||||
assert(junk != NULL);
|
||||
memcpy(junk, authdata, sizeof(authdata));
|
||||
junk[0] = ~junk[0];
|
||||
junk[0] = (unsigned char)~junk[0];
|
||||
|
||||
a = alloc_assert();
|
||||
assert(fido_assert_set_count(a, 1) == FIDO_OK);
|
||||
@ -468,7 +506,7 @@ junk_sig(void)
|
||||
junk = malloc(sizeof(sig));
|
||||
assert(junk != NULL);
|
||||
memcpy(junk, sig, sizeof(sig));
|
||||
junk[0] = ~junk[0];
|
||||
junk[0] = (unsigned char)~junk[0];
|
||||
|
||||
a = alloc_assert();
|
||||
pk = alloc_es256_pk();
|
||||
@ -531,6 +569,46 @@ bad_cbor_serialize(void)
|
||||
free_assert(a);
|
||||
}
|
||||
|
||||
/* rs256 <-> EVP_PKEY transformations */
|
||||
static void
|
||||
rs256_PKEY(void)
|
||||
{
|
||||
rs256_pk_t *pk1, *pk2;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
pk1 = alloc_rs256_pk();
|
||||
pk2 = alloc_rs256_pk();
|
||||
|
||||
assert(rs256_pk_from_ptr(pk1, rs256_pk, sizeof(rs256_pk)) == FIDO_OK);
|
||||
assert((pkey = rs256_pk_to_EVP_PKEY(pk1)) != NULL);
|
||||
assert(rs256_pk_from_EVP_PKEY(pk2, pkey) == FIDO_OK);
|
||||
assert(memcmp(pk1, pk2, sizeof(*pk1)) == 0);
|
||||
|
||||
free_rs256_pk(pk1);
|
||||
free_rs256_pk(pk2);
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
|
||||
/* es256 <-> EVP_PKEY transformations */
|
||||
static void
|
||||
es256_PKEY(void)
|
||||
{
|
||||
es256_pk_t *pk1, *pk2;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
pk1 = alloc_es256_pk();
|
||||
pk2 = alloc_es256_pk();
|
||||
|
||||
assert(es256_pk_from_ptr(pk1, es256_pk, sizeof(es256_pk)) == FIDO_OK);
|
||||
assert((pkey = es256_pk_to_EVP_PKEY(pk1)) != NULL);
|
||||
assert(es256_pk_from_EVP_PKEY(pk2, pkey) == FIDO_OK);
|
||||
assert(memcmp(pk1, pk2, sizeof(*pk1)) == 0);
|
||||
|
||||
free_es256_pk(pk1);
|
||||
free_es256_pk(pk2);
|
||||
EVP_PKEY_free(pkey);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@ -548,6 +626,8 @@ main(void)
|
||||
junk_sig();
|
||||
wrong_options();
|
||||
bad_cbor_serialize();
|
||||
rs256_PKEY();
|
||||
es256_PKEY();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
646
regress/cred.c
646
regress/cred.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -102,6 +102,55 @@ static const unsigned char authdata_unsorted_keys[198] = {
|
||||
0xe1, 0x30, 0xfc, 0x2b, 0x1e, 0xd2,
|
||||
};
|
||||
|
||||
const unsigned char authdata_tpm[362] = {
|
||||
0x59, 0x01, 0x67, 0x49, 0x96, 0x0d, 0xe5, 0x88,
|
||||
0x0e, 0x8c, 0x68, 0x74, 0x34, 0x17, 0x0f, 0x64,
|
||||
0x76, 0x60, 0x5b, 0x8f, 0xe4, 0xae, 0xb9, 0xa2,
|
||||
0x86, 0x32, 0xc7, 0x99, 0x5c, 0xf3, 0xba, 0x83,
|
||||
0x1d, 0x97, 0x63, 0x45, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x98, 0x70, 0x58, 0xca, 0xdc, 0x4b, 0x81,
|
||||
0xb6, 0xe1, 0x30, 0xde, 0x50, 0xdc, 0xbe, 0x96,
|
||||
0x00, 0x20, 0x89, 0x99, 0x6d, 0x5a, 0x00, 0x29,
|
||||
0xe5, 0x3e, 0x6a, 0x1c, 0x72, 0x6d, 0x71, 0x4a,
|
||||
0x4f, 0x03, 0x9b, 0x68, 0x17, 0xdb, 0x29, 0x1a,
|
||||
0x6b, 0x02, 0x6c, 0x26, 0xf9, 0xbd, 0xc3, 0x0e,
|
||||
0x38, 0x1a, 0xa4, 0x01, 0x03, 0x03, 0x39, 0x01,
|
||||
0x00, 0x20, 0x59, 0x01, 0x00, 0xc5, 0xb6, 0x9c,
|
||||
0x06, 0x1d, 0xcf, 0xb9, 0xf2, 0x5e, 0x99, 0x7d,
|
||||
0x6d, 0x73, 0xd8, 0x36, 0xc1, 0x4a, 0x90, 0x05,
|
||||
0x4d, 0x82, 0x57, 0xc1, 0xb6, 0x6a, 0xd1, 0x43,
|
||||
0x03, 0x85, 0xf8, 0x52, 0x4f, 0xd2, 0x27, 0x91,
|
||||
0x0b, 0xb5, 0x93, 0xa0, 0x68, 0xf8, 0x80, 0x1b,
|
||||
0xaa, 0x65, 0x97, 0x45, 0x11, 0x86, 0x34, 0xd6,
|
||||
0x67, 0xf8, 0xd5, 0x12, 0x79, 0x84, 0xee, 0x70,
|
||||
0x99, 0x00, 0x63, 0xa8, 0xb4, 0x43, 0x0b, 0x4c,
|
||||
0x57, 0x4a, 0xd6, 0x9b, 0x75, 0x63, 0x8a, 0x46,
|
||||
0x57, 0xdb, 0x14, 0xc8, 0x71, 0xd1, 0xb3, 0x07,
|
||||
0x68, 0x58, 0xbc, 0x55, 0x84, 0x80, 0x2a, 0xd2,
|
||||
0x36, 0x9f, 0xc1, 0x64, 0xa0, 0x11, 0x4b, 0xc9,
|
||||
0x32, 0x31, 0x3a, 0xd6, 0x87, 0x26, 0x1a, 0x3a,
|
||||
0x78, 0x3d, 0x89, 0xdb, 0x00, 0x28, 0x3b, 0xae,
|
||||
0x2b, 0x1b, 0x56, 0xe2, 0x8c, 0x4c, 0x63, 0xac,
|
||||
0x6e, 0x6c, 0xf7, 0xb5, 0x7d, 0x4d, 0x0b, 0x9f,
|
||||
0x06, 0xa0, 0x10, 0x35, 0x38, 0x20, 0x4d, 0xcc,
|
||||
0x07, 0xd7, 0x00, 0x4e, 0x86, 0xba, 0xfe, 0x8b,
|
||||
0xe4, 0x3f, 0x4a, 0xd6, 0xca, 0xbf, 0x67, 0x40,
|
||||
0x1a, 0xa4, 0xda, 0x82, 0x52, 0x15, 0xb8, 0x14,
|
||||
0x3a, 0x7c, 0xa9, 0x02, 0xc1, 0x01, 0x69, 0xc6,
|
||||
0x51, 0xd4, 0xbc, 0x1f, 0x95, 0xb2, 0xee, 0x1f,
|
||||
0xdd, 0xb5, 0x73, 0x16, 0x5e, 0x29, 0x3f, 0x47,
|
||||
0xac, 0x65, 0xfb, 0x63, 0x5c, 0xb9, 0xc8, 0x13,
|
||||
0x2d, 0xec, 0x85, 0xde, 0x71, 0x0d, 0x84, 0x93,
|
||||
0x74, 0x76, 0x91, 0xdd, 0x1d, 0x6d, 0x3d, 0xc7,
|
||||
0x36, 0x19, 0x19, 0x86, 0xde, 0x7c, 0xca, 0xd6,
|
||||
0xc6, 0x65, 0x7e, 0x4b, 0x24, 0x9c, 0xce, 0x92,
|
||||
0x6b, 0x1c, 0xe0, 0xa0, 0xa9, 0x6c, 0xc3, 0xed,
|
||||
0x4f, 0x2a, 0x54, 0x07, 0x00, 0x32, 0x5e, 0x1b,
|
||||
0x94, 0x37, 0xcd, 0xe2, 0x32, 0xa8, 0xd5, 0x2c,
|
||||
0xfb, 0x03, 0x9d, 0x79, 0xdf, 0x21, 0x43, 0x01,
|
||||
0x00, 0x01
|
||||
};
|
||||
|
||||
static const unsigned char x509[742] = {
|
||||
0x30, 0x82, 0x02, 0xe2, 0x30, 0x81, 0xcb, 0x02,
|
||||
0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
|
||||
@ -221,6 +270,42 @@ const unsigned char pubkey[64] = {
|
||||
0xfe, 0x5d, 0xe1, 0x30, 0xfc, 0x2b, 0x1e, 0xd2,
|
||||
};
|
||||
|
||||
const unsigned char pubkey_tpm[259] = {
|
||||
0xc5, 0xb6, 0x9c, 0x06, 0x1d, 0xcf, 0xb9, 0xf2,
|
||||
0x5e, 0x99, 0x7d, 0x6d, 0x73, 0xd8, 0x36, 0xc1,
|
||||
0x4a, 0x90, 0x05, 0x4d, 0x82, 0x57, 0xc1, 0xb6,
|
||||
0x6a, 0xd1, 0x43, 0x03, 0x85, 0xf8, 0x52, 0x4f,
|
||||
0xd2, 0x27, 0x91, 0x0b, 0xb5, 0x93, 0xa0, 0x68,
|
||||
0xf8, 0x80, 0x1b, 0xaa, 0x65, 0x97, 0x45, 0x11,
|
||||
0x86, 0x34, 0xd6, 0x67, 0xf8, 0xd5, 0x12, 0x79,
|
||||
0x84, 0xee, 0x70, 0x99, 0x00, 0x63, 0xa8, 0xb4,
|
||||
0x43, 0x0b, 0x4c, 0x57, 0x4a, 0xd6, 0x9b, 0x75,
|
||||
0x63, 0x8a, 0x46, 0x57, 0xdb, 0x14, 0xc8, 0x71,
|
||||
0xd1, 0xb3, 0x07, 0x68, 0x58, 0xbc, 0x55, 0x84,
|
||||
0x80, 0x2a, 0xd2, 0x36, 0x9f, 0xc1, 0x64, 0xa0,
|
||||
0x11, 0x4b, 0xc9, 0x32, 0x31, 0x3a, 0xd6, 0x87,
|
||||
0x26, 0x1a, 0x3a, 0x78, 0x3d, 0x89, 0xdb, 0x00,
|
||||
0x28, 0x3b, 0xae, 0x2b, 0x1b, 0x56, 0xe2, 0x8c,
|
||||
0x4c, 0x63, 0xac, 0x6e, 0x6c, 0xf7, 0xb5, 0x7d,
|
||||
0x4d, 0x0b, 0x9f, 0x06, 0xa0, 0x10, 0x35, 0x38,
|
||||
0x20, 0x4d, 0xcc, 0x07, 0xd7, 0x00, 0x4e, 0x86,
|
||||
0xba, 0xfe, 0x8b, 0xe4, 0x3f, 0x4a, 0xd6, 0xca,
|
||||
0xbf, 0x67, 0x40, 0x1a, 0xa4, 0xda, 0x82, 0x52,
|
||||
0x15, 0xb8, 0x14, 0x3a, 0x7c, 0xa9, 0x02, 0xc1,
|
||||
0x01, 0x69, 0xc6, 0x51, 0xd4, 0xbc, 0x1f, 0x95,
|
||||
0xb2, 0xee, 0x1f, 0xdd, 0xb5, 0x73, 0x16, 0x5e,
|
||||
0x29, 0x3f, 0x47, 0xac, 0x65, 0xfb, 0x63, 0x5c,
|
||||
0xb9, 0xc8, 0x13, 0x2d, 0xec, 0x85, 0xde, 0x71,
|
||||
0x0d, 0x84, 0x93, 0x74, 0x76, 0x91, 0xdd, 0x1d,
|
||||
0x6d, 0x3d, 0xc7, 0x36, 0x19, 0x19, 0x86, 0xde,
|
||||
0x7c, 0xca, 0xd6, 0xc6, 0x65, 0x7e, 0x4b, 0x24,
|
||||
0x9c, 0xce, 0x92, 0x6b, 0x1c, 0xe0, 0xa0, 0xa9,
|
||||
0x6c, 0xc3, 0xed, 0x4f, 0x2a, 0x54, 0x07, 0x00,
|
||||
0x32, 0x5e, 0x1b, 0x94, 0x37, 0xcd, 0xe2, 0x32,
|
||||
0xa8, 0xd5, 0x2c, 0xfb, 0x03, 0x9d, 0x79, 0xdf,
|
||||
0x01, 0x00, 0x01,
|
||||
};
|
||||
|
||||
const unsigned char id[64] = {
|
||||
0x53, 0xfb, 0xdf, 0xaa, 0xce, 0x63, 0xde, 0xc5,
|
||||
0xfe, 0x47, 0xe6, 0x52, 0xeb, 0xf3, 0x5d, 0x53,
|
||||
@ -232,16 +317,539 @@ const unsigned char id[64] = {
|
||||
0x34, 0xe3, 0x83, 0xe7, 0xd1, 0xbd, 0x9f, 0x25,
|
||||
};
|
||||
|
||||
const unsigned char id_tpm[32] = {
|
||||
0x89, 0x99, 0x6d, 0x5a, 0x00, 0x29, 0xe5, 0x3e,
|
||||
0x6a, 0x1c, 0x72, 0x6d, 0x71, 0x4a, 0x4f, 0x03,
|
||||
0x9b, 0x68, 0x17, 0xdb, 0x29, 0x1a, 0x6b, 0x02,
|
||||
0x6c, 0x26, 0xf9, 0xbd, 0xc3, 0x0e, 0x38, 0x1a
|
||||
};
|
||||
|
||||
const unsigned char attstmt_tpm[4034] = {
|
||||
0xa6, 0x63, 0x61, 0x6c, 0x67, 0x39, 0xff, 0xfe,
|
||||
0x63, 0x73, 0x69, 0x67, 0x59, 0x01, 0x00, 0x1c,
|
||||
0x09, 0x0d, 0x35, 0x97, 0x22, 0xfc, 0xfe, 0xc0,
|
||||
0x58, 0x49, 0x9e, 0xd4, 0x7e, 0x6a, 0x7d, 0xdb,
|
||||
0x6d, 0x20, 0x95, 0x5c, 0x0b, 0xd0, 0xd5, 0x72,
|
||||
0x4f, 0x15, 0x22, 0x38, 0x97, 0xb2, 0x4b, 0xd0,
|
||||
0xef, 0x31, 0x7c, 0xf2, 0x42, 0x19, 0x41, 0xa1,
|
||||
0xe2, 0xc5, 0xca, 0xc6, 0x74, 0x95, 0xcf, 0xf9,
|
||||
0x41, 0x75, 0x0b, 0x56, 0x39, 0x82, 0x78, 0xf6,
|
||||
0x59, 0xf1, 0x09, 0x96, 0x9e, 0x38, 0x7f, 0x14,
|
||||
0x9b, 0xf5, 0x36, 0xbb, 0x92, 0x32, 0xc4, 0x64,
|
||||
0xe8, 0xff, 0xb4, 0xc7, 0xcf, 0xcd, 0x17, 0x48,
|
||||
0x0f, 0x83, 0xd9, 0x44, 0x03, 0x35, 0x26, 0xad,
|
||||
0x01, 0xb7, 0x57, 0x06, 0xb3, 0x9c, 0xa0, 0x6e,
|
||||
0x2f, 0x58, 0xcb, 0x5c, 0xaa, 0x7c, 0xea, 0x7e,
|
||||
0x3f, 0xbc, 0x76, 0xc9, 0x0e, 0x52, 0x39, 0x81,
|
||||
0xa9, 0x9e, 0x37, 0x14, 0x1f, 0x50, 0x6a, 0x4f,
|
||||
0xd7, 0xfc, 0xd4, 0xfa, 0xf2, 0x18, 0x60, 0xd5,
|
||||
0xc3, 0x57, 0x7d, 0x6d, 0x05, 0x28, 0x25, 0xc3,
|
||||
0xde, 0x86, 0x85, 0x06, 0x71, 0xfb, 0x84, 0xa2,
|
||||
0x07, 0xb6, 0x77, 0xc9, 0x68, 0x41, 0x53, 0x32,
|
||||
0x4c, 0xa8, 0x4b, 0xf7, 0x08, 0x84, 0x62, 0x6c,
|
||||
0x8a, 0xb6, 0xcf, 0xc1, 0xde, 0x6b, 0x61, 0xc8,
|
||||
0xdd, 0xc0, 0x13, 0x70, 0x22, 0x28, 0xe1, 0x0f,
|
||||
0x46, 0x02, 0xc6, 0xb1, 0xfa, 0x30, 0xcb, 0xec,
|
||||
0xd1, 0x82, 0xfa, 0x51, 0xcb, 0x71, 0x5e, 0x1f,
|
||||
0x1b, 0x5f, 0xe0, 0xb0, 0x02, 0x8a, 0x7c, 0x78,
|
||||
0xd1, 0xb7, 0x4d, 0x56, 0xb0, 0x92, 0x3e, 0xda,
|
||||
0xc7, 0xb1, 0x74, 0xcf, 0x6a, 0x40, 0xeb, 0x98,
|
||||
0x1c, 0x2e, 0xf2, 0x86, 0x76, 0xf8, 0x2e, 0x6a,
|
||||
0x9f, 0x77, 0x51, 0x64, 0xce, 0xdc, 0x12, 0x85,
|
||||
0x84, 0x6b, 0x01, 0xc8, 0xeb, 0xbc, 0x57, 0x6c,
|
||||
0x32, 0x26, 0xcb, 0xb2, 0x84, 0x02, 0x2a, 0x33,
|
||||
0x15, 0xd9, 0xe3, 0x15, 0xfc, 0x3a, 0x24, 0x63,
|
||||
0x76, 0x65, 0x72, 0x63, 0x32, 0x2e, 0x30, 0x63,
|
||||
0x78, 0x35, 0x63, 0x82, 0x59, 0x05, 0xc4, 0x30,
|
||||
0x82, 0x05, 0xc0, 0x30, 0x82, 0x03, 0xa8, 0xa0,
|
||||
0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x78, 0xd9,
|
||||
0xa8, 0xb2, 0x64, 0xf9, 0x4d, 0x28, 0x82, 0xc0,
|
||||
0xd3, 0x1b, 0x40, 0x3c, 0xc8, 0xd9, 0x30, 0x0d,
|
||||
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x41, 0x31,
|
||||
0x3f, 0x30, 0x3d, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x13, 0x36, 0x45, 0x55, 0x53, 0x2d, 0x53, 0x54,
|
||||
0x4d, 0x2d, 0x4b, 0x45, 0x59, 0x49, 0x44, 0x2d,
|
||||
0x31, 0x41, 0x44, 0x42, 0x39, 0x39, 0x34, 0x41,
|
||||
0x42, 0x35, 0x38, 0x42, 0x45, 0x35, 0x37, 0x41,
|
||||
0x30, 0x43, 0x43, 0x39, 0x42, 0x39, 0x30, 0x30,
|
||||
0x45, 0x37, 0x38, 0x35, 0x31, 0x45, 0x31, 0x41,
|
||||
0x34, 0x33, 0x43, 0x30, 0x38, 0x36, 0x36, 0x30,
|
||||
0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x37,
|
||||
0x31, 0x35, 0x31, 0x31, 0x31, 0x32, 0x31, 0x33,
|
||||
0x5a, 0x17, 0x0d, 0x32, 0x35, 0x30, 0x33, 0x32,
|
||||
0x31, 0x32, 0x30, 0x32, 0x39, 0x31, 0x35, 0x5a,
|
||||
0x30, 0x00, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
|
||||
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
|
||||
0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
|
||||
0x01, 0x01, 0x00, 0xca, 0xbe, 0x77, 0x9f, 0x45,
|
||||
0x97, 0x17, 0x8d, 0x01, 0xe1, 0x18, 0xcc, 0xf0,
|
||||
0xb5, 0xed, 0x9a, 0xb7, 0x36, 0xac, 0x05, 0x26,
|
||||
0xbe, 0x35, 0xd9, 0x5c, 0x00, 0x5c, 0x5d, 0x8b,
|
||||
0x6f, 0x2a, 0xb8, 0xf6, 0x02, 0x4f, 0x33, 0xfe,
|
||||
0x84, 0x45, 0x4c, 0x4f, 0x7a, 0xdb, 0xa9, 0x6a,
|
||||
0x62, 0x0f, 0x19, 0x35, 0x5d, 0xd2, 0x34, 0x1a,
|
||||
0x9d, 0x73, 0x55, 0xe5, 0x3e, 0x04, 0xa2, 0xd6,
|
||||
0xbe, 0xe7, 0x5a, 0xb9, 0x16, 0x6c, 0x55, 0x18,
|
||||
0xa8, 0x4b, 0xb2, 0x37, 0xb9, 0xa3, 0x87, 0xfc,
|
||||
0x76, 0xa8, 0x55, 0xc9, 0xe7, 0x30, 0xe5, 0x0e,
|
||||
0x3c, 0x7b, 0x74, 0xd2, 0x1e, 0xa8, 0x05, 0xd5,
|
||||
0xe2, 0xe3, 0xcb, 0xaf, 0x63, 0x33, 0x12, 0xaa,
|
||||
0xfd, 0x31, 0x32, 0x71, 0x4f, 0x41, 0x96, 0x05,
|
||||
0xb5, 0x69, 0x73, 0x45, 0xbe, 0x6f, 0x90, 0xd9,
|
||||
0x10, 0x36, 0xaf, 0x7a, 0x1c, 0xf1, 0x6d, 0x14,
|
||||
0xb0, 0x1e, 0xbb, 0xae, 0x1c, 0x35, 0xec, 0x1c,
|
||||
0xb5, 0x0e, 0xf6, 0x33, 0x98, 0x13, 0x4e, 0x44,
|
||||
0x7b, 0x5c, 0x97, 0x47, 0xed, 0x4f, 0xfe, 0xbd,
|
||||
0x08, 0xd2, 0xa9, 0xc6, 0xbe, 0x8c, 0x04, 0x9e,
|
||||
0xdc, 0x3d, 0xbe, 0x98, 0xe9, 0x2a, 0xb1, 0xf4,
|
||||
0xfa, 0x45, 0xf9, 0xc8, 0x9a, 0x55, 0x85, 0x26,
|
||||
0xfc, 0x5f, 0xad, 0x00, 0x8b, 0xc8, 0x41, 0xf2,
|
||||
0x86, 0x4e, 0xba, 0x55, 0x1c, 0xb2, 0x89, 0xe8,
|
||||
0x85, 0x6e, 0x1e, 0x02, 0x9f, 0x55, 0x70, 0xbe,
|
||||
0xfd, 0xe7, 0x9f, 0xba, 0x59, 0xa0, 0x2e, 0x9a,
|
||||
0x74, 0x11, 0xe7, 0xad, 0xa9, 0xc7, 0x7b, 0x58,
|
||||
0xc4, 0x16, 0xd3, 0x35, 0xcb, 0x61, 0x00, 0xec,
|
||||
0x36, 0x4a, 0xa3, 0x51, 0xa3, 0xdd, 0x61, 0xb6,
|
||||
0xd6, 0x29, 0xcb, 0x76, 0xe1, 0xab, 0x51, 0x3a,
|
||||
0xe8, 0xbf, 0xdb, 0x09, 0x4a, 0x39, 0x96, 0xd9,
|
||||
0xac, 0x8f, 0x6c, 0x62, 0xe0, 0x03, 0x23, 0x24,
|
||||
0xbe, 0xd4, 0x83, 0x02, 0x03, 0x01, 0x00, 0x01,
|
||||
0xa3, 0x82, 0x01, 0xf3, 0x30, 0x82, 0x01, 0xef,
|
||||
0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01,
|
||||
0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80,
|
||||
0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
|
||||
0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x6d,
|
||||
0x06, 0x03, 0x55, 0x1d, 0x20, 0x01, 0x01, 0xff,
|
||||
0x04, 0x63, 0x30, 0x61, 0x30, 0x5f, 0x06, 0x09,
|
||||
0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15,
|
||||
0x1f, 0x30, 0x52, 0x30, 0x50, 0x06, 0x08, 0x2b,
|
||||
0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30,
|
||||
0x44, 0x1e, 0x42, 0x00, 0x54, 0x00, 0x43, 0x00,
|
||||
0x50, 0x00, 0x41, 0x00, 0x20, 0x00, 0x20, 0x00,
|
||||
0x54, 0x00, 0x72, 0x00, 0x75, 0x00, 0x73, 0x00,
|
||||
0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00,
|
||||
0x20, 0x00, 0x50, 0x00, 0x6c, 0x00, 0x61, 0x00,
|
||||
0x74, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00,
|
||||
0x6d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x49, 0x00,
|
||||
0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00,
|
||||
0x69, 0x00, 0x74, 0x00, 0x79, 0x30, 0x10, 0x06,
|
||||
0x03, 0x55, 0x1d, 0x25, 0x04, 0x09, 0x30, 0x07,
|
||||
0x06, 0x05, 0x67, 0x81, 0x05, 0x08, 0x03, 0x30,
|
||||
0x59, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x01, 0x01,
|
||||
0xff, 0x04, 0x4f, 0x30, 0x4d, 0xa4, 0x4b, 0x30,
|
||||
0x49, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05, 0x67,
|
||||
0x81, 0x05, 0x02, 0x01, 0x0c, 0x0b, 0x69, 0x64,
|
||||
0x3a, 0x35, 0x33, 0x35, 0x34, 0x34, 0x44, 0x32,
|
||||
0x30, 0x31, 0x17, 0x30, 0x15, 0x06, 0x05, 0x67,
|
||||
0x81, 0x05, 0x02, 0x02, 0x0c, 0x0c, 0x53, 0x54,
|
||||
0x33, 0x33, 0x48, 0x54, 0x50, 0x48, 0x41, 0x48,
|
||||
0x42, 0x34, 0x31, 0x16, 0x30, 0x14, 0x06, 0x05,
|
||||
0x67, 0x81, 0x05, 0x02, 0x03, 0x0c, 0x0b, 0x69,
|
||||
0x64, 0x3a, 0x30, 0x30, 0x34, 0x39, 0x30, 0x30,
|
||||
0x30, 0x34, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d,
|
||||
0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb8,
|
||||
0x5f, 0xd5, 0x67, 0xca, 0x92, 0xc4, 0x0e, 0xcf,
|
||||
0x0c, 0xd8, 0x1f, 0x6d, 0x3f, 0x03, 0x55, 0x6f,
|
||||
0x38, 0xa6, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55,
|
||||
0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd4, 0x04,
|
||||
0x64, 0xfc, 0x6e, 0x50, 0x0a, 0x56, 0x48, 0x0f,
|
||||
0x05, 0xa9, 0x00, 0xb7, 0x1d, 0x5e, 0x57, 0x08,
|
||||
0xd5, 0xdc, 0x30, 0x81, 0xb2, 0x06, 0x08, 0x2b,
|
||||
0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
|
||||
0x81, 0xa5, 0x30, 0x81, 0xa2, 0x30, 0x81, 0x9f,
|
||||
0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
|
||||
0x30, 0x02, 0x86, 0x81, 0x92, 0x68, 0x74, 0x74,
|
||||
0x70, 0x3a, 0x2f, 0x2f, 0x61, 0x7a, 0x63, 0x73,
|
||||
0x70, 0x72, 0x6f, 0x64, 0x65, 0x75, 0x73, 0x61,
|
||||
0x69, 0x6b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73,
|
||||
0x68, 0x2e, 0x62, 0x6c, 0x6f, 0x62, 0x2e, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64,
|
||||
0x6f, 0x77, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x2f,
|
||||
0x65, 0x75, 0x73, 0x2d, 0x73, 0x74, 0x6d, 0x2d,
|
||||
0x6b, 0x65, 0x79, 0x69, 0x64, 0x2d, 0x31, 0x61,
|
||||
0x64, 0x62, 0x39, 0x39, 0x34, 0x61, 0x62, 0x35,
|
||||
0x38, 0x62, 0x65, 0x35, 0x37, 0x61, 0x30, 0x63,
|
||||
0x63, 0x39, 0x62, 0x39, 0x30, 0x30, 0x65, 0x37,
|
||||
0x38, 0x35, 0x31, 0x65, 0x31, 0x61, 0x34, 0x33,
|
||||
0x63, 0x30, 0x38, 0x36, 0x36, 0x30, 0x2f, 0x61,
|
||||
0x62, 0x64, 0x36, 0x31, 0x35, 0x66, 0x32, 0x2d,
|
||||
0x31, 0x35, 0x38, 0x61, 0x2d, 0x34, 0x35, 0x38,
|
||||
0x65, 0x2d, 0x61, 0x31, 0x35, 0x35, 0x2d, 0x37,
|
||||
0x63, 0x34, 0x63, 0x38, 0x63, 0x62, 0x31, 0x33,
|
||||
0x63, 0x36, 0x35, 0x2e, 0x63, 0x65, 0x72, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82,
|
||||
0x02, 0x01, 0x00, 0xa2, 0x10, 0xc5, 0xbf, 0x41,
|
||||
0xa6, 0xba, 0x8c, 0x72, 0xca, 0x0f, 0x3e, 0x5e,
|
||||
0x7f, 0xe2, 0xcb, 0x60, 0xb8, 0x3f, 0xfb, 0xde,
|
||||
0x03, 0xe2, 0xfe, 0x20, 0x29, 0xdf, 0x11, 0xf5,
|
||||
0xb0, 0x50, 0x6d, 0x32, 0xe8, 0x1b, 0x05, 0xad,
|
||||
0x6b, 0x60, 0xb5, 0xed, 0xf3, 0xa4, 0x4a, 0xea,
|
||||
0x09, 0xe5, 0x65, 0x7e, 0xe0, 0xd5, 0x3a, 0x6a,
|
||||
0xdb, 0x64, 0xb7, 0x07, 0x8f, 0xa1, 0x63, 0xb3,
|
||||
0x89, 0x8a, 0xac, 0x49, 0x97, 0xa0, 0x9a, 0xa3,
|
||||
0xd3, 0x3a, 0xc2, 0x13, 0xb2, 0xbb, 0xab, 0x0d,
|
||||
0xf2, 0x35, 0xc5, 0x03, 0xde, 0x1c, 0xad, 0x6a,
|
||||
0x03, 0x0a, 0x4c, 0xe1, 0x37, 0x8f, 0xbc, 0x13,
|
||||
0xc0, 0x9a, 0x17, 0xd4, 0x2e, 0x36, 0x17, 0x51,
|
||||
0x12, 0xb0, 0x79, 0xbf, 0x9b, 0xb3, 0xb0, 0x74,
|
||||
0x25, 0x81, 0x7e, 0x21, 0x31, 0xb7, 0xc2, 0x5e,
|
||||
0xfb, 0x36, 0xab, 0xf3, 0x7a, 0x5f, 0xa4, 0x5e,
|
||||
0x8f, 0x0c, 0xbd, 0xcf, 0xf5, 0x50, 0xe7, 0x0c,
|
||||
0x51, 0x55, 0x48, 0xe6, 0x15, 0xb6, 0xd4, 0xaf,
|
||||
0x95, 0x72, 0x56, 0x94, 0xf7, 0x0e, 0xd6, 0x90,
|
||||
0xe3, 0xd3, 0x5d, 0xbd, 0x93, 0xa1, 0xbd, 0x6c,
|
||||
0xe4, 0xf2, 0x39, 0x4d, 0x54, 0x74, 0xcf, 0xf5,
|
||||
0xeb, 0x70, 0xdb, 0x4f, 0x52, 0xcd, 0x39, 0x8f,
|
||||
0x11, 0x54, 0x28, 0x06, 0x29, 0x8f, 0x23, 0xde,
|
||||
0x9e, 0x2f, 0x7b, 0xb6, 0x5f, 0xa3, 0x89, 0x04,
|
||||
0x99, 0x0a, 0xf1, 0x2d, 0xf9, 0x66, 0xd3, 0x13,
|
||||
0x45, 0xbd, 0x6c, 0x22, 0x57, 0xf5, 0xb1, 0xb9,
|
||||
0xdf, 0x5b, 0x7b, 0x1a, 0x3a, 0xdd, 0x6b, 0xc7,
|
||||
0x35, 0x88, 0xed, 0xc4, 0x09, 0x70, 0x4e, 0x5f,
|
||||
0xb5, 0x3e, 0xd1, 0x0b, 0xd0, 0xca, 0xef, 0x0b,
|
||||
0xe9, 0x8b, 0x6f, 0xc3, 0x16, 0xc3, 0x3d, 0x79,
|
||||
0x06, 0xef, 0x81, 0xf0, 0x60, 0x0b, 0x32, 0xe3,
|
||||
0x86, 0x6b, 0x92, 0x38, 0x90, 0x62, 0xed, 0x84,
|
||||
0x3a, 0xb7, 0x45, 0x43, 0x2e, 0xd0, 0x3a, 0x71,
|
||||
0x9e, 0x80, 0xcc, 0x9c, 0xac, 0x27, 0x10, 0x91,
|
||||
0xb7, 0xb2, 0xbd, 0x41, 0x40, 0xa7, 0xb7, 0xcf,
|
||||
0xe7, 0x38, 0xca, 0x68, 0xdd, 0x62, 0x09, 0xff,
|
||||
0x68, 0xce, 0xba, 0xe2, 0x07, 0x49, 0x09, 0xe7,
|
||||
0x1f, 0xdf, 0xe6, 0x26, 0xe5, 0x0f, 0xa9, 0xbf,
|
||||
0x2a, 0x5b, 0x67, 0x92, 0xa1, 0x10, 0x53, 0xb2,
|
||||
0x7a, 0x07, 0x29, 0x9d, 0xfd, 0x6d, 0xb6, 0x3b,
|
||||
0x45, 0xc1, 0x94, 0xcb, 0x1c, 0xc3, 0xce, 0xf6,
|
||||
0x8a, 0x1a, 0x81, 0x66, 0xb0, 0xa5, 0x14, 0xc7,
|
||||
0x9e, 0x1f, 0x6e, 0xb6, 0xff, 0x8b, 0x90, 0x87,
|
||||
0x3a, 0x3f, 0xa8, 0xc2, 0x2d, 0x8f, 0x6f, 0xdb,
|
||||
0xb4, 0xc4, 0x14, 0x3c, 0x1d, 0x12, 0x1d, 0x6d,
|
||||
0xcf, 0xa6, 0x04, 0x6a, 0xa8, 0x13, 0x5e, 0xf2,
|
||||
0x5e, 0x77, 0x80, 0x6b, 0x85, 0x83, 0xfe, 0xbb,
|
||||
0xeb, 0x70, 0xcb, 0x5f, 0xe4, 0x95, 0xaa, 0x0f,
|
||||
0x61, 0x36, 0x7c, 0xbb, 0x22, 0x1e, 0xba, 0x98,
|
||||
0x43, 0x52, 0x33, 0xae, 0xed, 0x5d, 0x10, 0x2c,
|
||||
0xb3, 0xa9, 0x31, 0x8e, 0x60, 0x54, 0xaf, 0x40,
|
||||
0x6d, 0x2e, 0x18, 0xc2, 0x6a, 0xf4, 0x7b, 0x9a,
|
||||
0x73, 0x0f, 0x58, 0x69, 0x23, 0xbb, 0xc4, 0x84,
|
||||
0x53, 0x30, 0xe2, 0xd6, 0x1e, 0x10, 0xc1, 0xec,
|
||||
0x82, 0x13, 0xab, 0x53, 0x86, 0xa2, 0xb9, 0xda,
|
||||
0xbb, 0x3a, 0xa2, 0xbe, 0xb0, 0x10, 0x99, 0x0e,
|
||||
0xe5, 0x9c, 0xc9, 0xf1, 0xce, 0x76, 0x46, 0xea,
|
||||
0x86, 0xaa, 0x36, 0x83, 0x99, 0x09, 0x9b, 0x30,
|
||||
0xd3, 0x26, 0xc7, 0xdf, 0x66, 0xc7, 0xf0, 0xdd,
|
||||
0x08, 0x09, 0x15, 0x15, 0x21, 0x49, 0x46, 0xd8,
|
||||
0x8a, 0x66, 0xca, 0x62, 0x9c, 0x79, 0x1d, 0x81,
|
||||
0xea, 0x5d, 0x82, 0xb0, 0xa6, 0x6b, 0x5c, 0xf5,
|
||||
0xb8, 0x8c, 0xf6, 0x16, 0x01, 0x2c, 0xf8, 0x27,
|
||||
0xf8, 0xcf, 0x88, 0xfe, 0xf3, 0xa4, 0xfc, 0x17,
|
||||
0x97, 0xe7, 0x07, 0x59, 0x06, 0xef, 0x30, 0x82,
|
||||
0x06, 0xeb, 0x30, 0x82, 0x04, 0xd3, 0xa0, 0x03,
|
||||
0x02, 0x01, 0x02, 0x02, 0x13, 0x33, 0x00, 0x00,
|
||||
0x02, 0x39, 0xf9, 0xbb, 0x6a, 0x1d, 0x49, 0x64,
|
||||
0x47, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39,
|
||||
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
||||
0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30,
|
||||
0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
|
||||
0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
|
||||
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
|
||||
0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e,
|
||||
0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e,
|
||||
0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52,
|
||||
0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e,
|
||||
0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
|
||||
0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f,
|
||||
0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x36,
|
||||
0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
||||
0x2d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f,
|
||||
0x66, 0x74, 0x20, 0x54, 0x50, 0x4d, 0x20, 0x52,
|
||||
0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74,
|
||||
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20,
|
||||
0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74,
|
||||
0x79, 0x20, 0x32, 0x30, 0x31, 0x34, 0x30, 0x1e,
|
||||
0x17, 0x0d, 0x31, 0x39, 0x30, 0x33, 0x32, 0x31,
|
||||
0x32, 0x30, 0x32, 0x39, 0x31, 0x35, 0x5a, 0x17,
|
||||
0x0d, 0x32, 0x35, 0x30, 0x33, 0x32, 0x31, 0x32,
|
||||
0x30, 0x32, 0x39, 0x31, 0x35, 0x5a, 0x30, 0x41,
|
||||
0x31, 0x3f, 0x30, 0x3d, 0x06, 0x03, 0x55, 0x04,
|
||||
0x03, 0x13, 0x36, 0x45, 0x55, 0x53, 0x2d, 0x53,
|
||||
0x54, 0x4d, 0x2d, 0x4b, 0x45, 0x59, 0x49, 0x44,
|
||||
0x2d, 0x31, 0x41, 0x44, 0x42, 0x39, 0x39, 0x34,
|
||||
0x41, 0x42, 0x35, 0x38, 0x42, 0x45, 0x35, 0x37,
|
||||
0x41, 0x30, 0x43, 0x43, 0x39, 0x42, 0x39, 0x30,
|
||||
0x30, 0x45, 0x37, 0x38, 0x35, 0x31, 0x45, 0x31,
|
||||
0x41, 0x34, 0x33, 0x43, 0x30, 0x38, 0x36, 0x36,
|
||||
0x30, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06,
|
||||
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
|
||||
0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f,
|
||||
0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02,
|
||||
0x01, 0x00, 0xdb, 0xe2, 0x23, 0xf9, 0x86, 0x8f,
|
||||
0xa9, 0x71, 0x9f, 0x8b, 0xf9, 0x7c, 0xe9, 0x45,
|
||||
0x2d, 0x59, 0x56, 0x5e, 0x96, 0xf4, 0xdd, 0x9a,
|
||||
0x12, 0xcd, 0x90, 0x1a, 0x0c, 0xb5, 0x03, 0xbf,
|
||||
0x09, 0xbe, 0xbf, 0xf7, 0x55, 0x52, 0xe8, 0x39,
|
||||
0x4c, 0xbe, 0x2a, 0x28, 0x88, 0x78, 0x39, 0xa7,
|
||||
0xcb, 0xf9, 0x4c, 0x55, 0xd2, 0x31, 0x96, 0x3b,
|
||||
0x48, 0xa2, 0xf3, 0xf6, 0xd3, 0x1a, 0x81, 0x7f,
|
||||
0x90, 0x62, 0xab, 0xec, 0x5a, 0xc7, 0xa0, 0x7f,
|
||||
0x81, 0x32, 0x27, 0x9b, 0x29, 0x75, 0x7d, 0x1e,
|
||||
0x96, 0xc5, 0xfa, 0x0e, 0x7c, 0xe0, 0x60, 0x96,
|
||||
0x7a, 0xca, 0x94, 0xba, 0xe6, 0xb2, 0x69, 0xdd,
|
||||
0xc4, 0x7d, 0xbb, 0xd3, 0xc4, 0xb4, 0x6e, 0x00,
|
||||
0x86, 0x1f, 0x9d, 0x25, 0xe8, 0xae, 0xc7, 0x10,
|
||||
0x84, 0xdc, 0xc0, 0x34, 0x24, 0x6e, 0xf7, 0xfc,
|
||||
0xdd, 0x3d, 0x32, 0x7a, 0x43, 0x96, 0xd6, 0xc8,
|
||||
0x7b, 0xf4, 0x9b, 0x3d, 0xa7, 0x1e, 0xba, 0x4d,
|
||||
0xd0, 0x3b, 0x3d, 0x84, 0x9a, 0xd1, 0x25, 0x22,
|
||||
0x5d, 0x00, 0x44, 0xb0, 0x59, 0xb7, 0x40, 0xc5,
|
||||
0xa3, 0x53, 0x53, 0xaf, 0x8f, 0x9e, 0xfd, 0x8f,
|
||||
0x1e, 0x02, 0xd3, 0x4f, 0xf7, 0x09, 0xce, 0xc5,
|
||||
0xc6, 0x71, 0x5c, 0xe9, 0xe8, 0x7a, 0xb5, 0x6b,
|
||||
0xa4, 0xbf, 0x0b, 0xd9, 0xb6, 0xfa, 0x24, 0xb0,
|
||||
0xcd, 0x52, 0x22, 0x1d, 0x7e, 0xe8, 0x15, 0x2f,
|
||||
0x1e, 0x5e, 0xa2, 0xec, 0xd3, 0xa8, 0x02, 0x77,
|
||||
0xb9, 0x55, 0x9a, 0xcf, 0xcc, 0xd7, 0x08, 0x20,
|
||||
0xa5, 0xda, 0x39, 0x9a, 0x30, 0x76, 0x90, 0x37,
|
||||
0xa7, 0x60, 0xdf, 0x18, 0x12, 0x65, 0x17, 0xaa,
|
||||
0xdd, 0x48, 0xd5, 0x12, 0x1d, 0x4c, 0x83, 0x5d,
|
||||
0x81, 0x07, 0x1d, 0x18, 0x81, 0x40, 0x55, 0x60,
|
||||
0x8f, 0xa3, 0x6b, 0x34, 0x1e, 0xd5, 0xe6, 0xcf,
|
||||
0x52, 0x73, 0x77, 0x4a, 0x50, 0x4f, 0x1b, 0x0f,
|
||||
0x39, 0xc3, 0x0d, 0x16, 0xf9, 0xbb, 0x4c, 0x77,
|
||||
0xf6, 0x4e, 0xac, 0x9c, 0xfe, 0xe8, 0xbb, 0x52,
|
||||
0xa5, 0x0a, 0x0e, 0x9b, 0xf0, 0x0d, 0xef, 0xfb,
|
||||
0x6f, 0x89, 0x34, 0x7d, 0x47, 0xec, 0x14, 0x6a,
|
||||
0xf4, 0x0a, 0xe1, 0x60, 0x44, 0x73, 0x7b, 0xa0,
|
||||
0xab, 0x5b, 0x8c, 0x43, 0xa6, 0x05, 0x42, 0x61,
|
||||
0x46, 0xaa, 0x1c, 0xf5, 0xec, 0x2c, 0x86, 0x85,
|
||||
0x21, 0x99, 0xdf, 0x45, 0x8e, 0xf4, 0xd1, 0x1e,
|
||||
0xfb, 0xcd, 0x9b, 0x94, 0x32, 0xe0, 0xa0, 0xcc,
|
||||
0x4f, 0xad, 0xae, 0x44, 0x8b, 0x86, 0x27, 0x91,
|
||||
0xfe, 0x60, 0x9f, 0xf2, 0x63, 0x30, 0x6c, 0x5d,
|
||||
0x8d, 0xbc, 0xab, 0xd4, 0xf5, 0xa2, 0xb2, 0x74,
|
||||
0xe8, 0xd4, 0x95, 0xf2, 0xd6, 0x03, 0x8b, 0xc9,
|
||||
0xa3, 0x52, 0xe7, 0x63, 0x05, 0x64, 0x50, 0xe5,
|
||||
0x0a, 0x6a, 0xa0, 0x6c, 0x50, 0xcd, 0x37, 0x98,
|
||||
0xa8, 0x87, 0x02, 0x38, 0x5b, 0x6c, 0x02, 0x69,
|
||||
0x3d, 0x1f, 0x95, 0x74, 0x4d, 0x46, 0x76, 0x2a,
|
||||
0x9d, 0x62, 0xd4, 0xc7, 0x1b, 0xf9, 0x31, 0xa6,
|
||||
0x51, 0xee, 0x7b, 0xc8, 0xe4, 0x6e, 0x3a, 0xcf,
|
||||
0x4f, 0x4f, 0x49, 0x8a, 0xf5, 0x4f, 0x25, 0x93,
|
||||
0x23, 0x02, 0xef, 0x79, 0xa6, 0x27, 0xbe, 0x5a,
|
||||
0xe7, 0x74, 0xb7, 0xd7, 0xa8, 0xc1, 0xae, 0x55,
|
||||
0x88, 0xa4, 0xc7, 0x4d, 0xb7, 0x62, 0xf0, 0xf9,
|
||||
0x5b, 0xbf, 0x47, 0x5b, 0xfe, 0xcc, 0x0b, 0x89,
|
||||
0x19, 0x65, 0x4b, 0x6f, 0xdf, 0x4f, 0x7d, 0x4d,
|
||||
0x96, 0x42, 0x0d, 0x2a, 0xa1, 0xbd, 0x3e, 0x70,
|
||||
0x92, 0xba, 0xc8, 0x59, 0xd5, 0x1d, 0x3a, 0x98,
|
||||
0x53, 0x75, 0xa6, 0x32, 0xc8, 0x72, 0x03, 0x46,
|
||||
0x5f, 0x5c, 0x13, 0xa4, 0xdb, 0xc7, 0x55, 0x35,
|
||||
0x22, 0x0d, 0xc6, 0x17, 0x85, 0xbd, 0x46, 0x4b,
|
||||
0xfa, 0x1e, 0x49, 0xc2, 0xfe, 0x1e, 0xf9, 0x62,
|
||||
0x89, 0x56, 0x84, 0xdf, 0xa0, 0xfb, 0xfd, 0x93,
|
||||
0xa4, 0x25, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,
|
||||
0x82, 0x01, 0x8e, 0x30, 0x82, 0x01, 0x8a, 0x30,
|
||||
0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
|
||||
0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x84, 0x30,
|
||||
0x1b, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x14,
|
||||
0x30, 0x12, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04,
|
||||
0x01, 0x82, 0x37, 0x15, 0x24, 0x06, 0x05, 0x67,
|
||||
0x81, 0x05, 0x08, 0x03, 0x30, 0x16, 0x06, 0x03,
|
||||
0x55, 0x1d, 0x20, 0x04, 0x0f, 0x30, 0x0d, 0x30,
|
||||
0x0b, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01,
|
||||
0x82, 0x37, 0x15, 0x1f, 0x30, 0x12, 0x06, 0x03,
|
||||
0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08,
|
||||
0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00,
|
||||
0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
|
||||
0x16, 0x04, 0x14, 0xb8, 0x5f, 0xd5, 0x67, 0xca,
|
||||
0x92, 0xc4, 0x0e, 0xcf, 0x0c, 0xd8, 0x1f, 0x6d,
|
||||
0x3f, 0x03, 0x55, 0x6f, 0x38, 0xa6, 0x51, 0x30,
|
||||
0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
|
||||
0x30, 0x16, 0x80, 0x14, 0x7a, 0x8c, 0x0a, 0xce,
|
||||
0x2f, 0x48, 0x62, 0x17, 0xe2, 0x94, 0xd1, 0xae,
|
||||
0x55, 0xc1, 0x52, 0xec, 0x71, 0x74, 0xa4, 0x56,
|
||||
0x30, 0x70, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04,
|
||||
0x69, 0x30, 0x67, 0x30, 0x65, 0xa0, 0x63, 0xa0,
|
||||
0x61, 0x86, 0x5f, 0x68, 0x74, 0x74, 0x70, 0x3a,
|
||||
0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69,
|
||||
0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x6f,
|
||||
0x70, 0x73, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x4d,
|
||||
0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
|
||||
0x25, 0x32, 0x30, 0x54, 0x50, 0x4d, 0x25, 0x32,
|
||||
0x30, 0x52, 0x6f, 0x6f, 0x74, 0x25, 0x32, 0x30,
|
||||
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
||||
0x61, 0x74, 0x65, 0x25, 0x32, 0x30, 0x41, 0x75,
|
||||
0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x25,
|
||||
0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2e, 0x63,
|
||||
0x72, 0x6c, 0x30, 0x7d, 0x06, 0x08, 0x2b, 0x06,
|
||||
0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x71,
|
||||
0x30, 0x6f, 0x30, 0x6d, 0x06, 0x08, 0x2b, 0x06,
|
||||
0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x61,
|
||||
0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
|
||||
0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f,
|
||||
0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x70, 0x6b, 0x69, 0x6f, 0x70, 0x73, 0x2f,
|
||||
0x63, 0x65, 0x72, 0x74, 0x73, 0x2f, 0x4d, 0x69,
|
||||
0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x25,
|
||||
0x32, 0x30, 0x54, 0x50, 0x4d, 0x25, 0x32, 0x30,
|
||||
0x52, 0x6f, 0x6f, 0x74, 0x25, 0x32, 0x30, 0x43,
|
||||
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x25, 0x32, 0x30, 0x41, 0x75, 0x74,
|
||||
0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x25, 0x32,
|
||||
0x30, 0x32, 0x30, 0x31, 0x34, 0x2e, 0x63, 0x72,
|
||||
0x74, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
||||
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
|
||||
0x03, 0x82, 0x02, 0x01, 0x00, 0x41, 0xaa, 0xfe,
|
||||
0x28, 0x6c, 0xf7, 0x6b, 0x53, 0xde, 0x77, 0xc0,
|
||||
0x80, 0x50, 0x94, 0xd9, 0xdb, 0x46, 0x8e, 0x6a,
|
||||
0x93, 0xa9, 0x10, 0x37, 0x27, 0x1f, 0xf5, 0x70,
|
||||
0xf1, 0xa8, 0xcf, 0xa1, 0x45, 0x86, 0x2a, 0xdd,
|
||||
0x8f, 0xb8, 0xb5, 0xc1, 0xe6, 0xcf, 0x8a, 0xfa,
|
||||
0x32, 0xa1, 0x4b, 0xb7, 0xa4, 0xbf, 0x0a, 0x48,
|
||||
0xcb, 0x42, 0x63, 0x71, 0xc1, 0x96, 0xb9, 0x3a,
|
||||
0x37, 0x84, 0x0e, 0x24, 0x39, 0xeb, 0x58, 0xce,
|
||||
0x3d, 0xb7, 0xa9, 0x44, 0x92, 0x59, 0xb9, 0xff,
|
||||
0xdb, 0x18, 0xbe, 0x6a, 0x5e, 0xe7, 0xce, 0xef,
|
||||
0xb8, 0x40, 0x53, 0xaf, 0xc1, 0x9b, 0xfb, 0x42,
|
||||
0x99, 0x7e, 0x9d, 0x05, 0x2b, 0x71, 0x0a, 0x7a,
|
||||
0x7a, 0x44, 0xd1, 0x31, 0xca, 0xf0, 0x5f, 0x74,
|
||||
0x85, 0xa9, 0xe2, 0xbc, 0xc8, 0x0c, 0xad, 0x57,
|
||||
0xd1, 0xe9, 0x48, 0x90, 0x88, 0x57, 0x86, 0xd7,
|
||||
0xc5, 0xc9, 0xe6, 0xb2, 0x5e, 0x5f, 0x13, 0xdc,
|
||||
0x10, 0x7f, 0xdf, 0x63, 0x8a, 0xd5, 0x9e, 0x90,
|
||||
0xc2, 0x75, 0x53, 0x1e, 0x68, 0x17, 0x2b, 0x03,
|
||||
0x29, 0x15, 0x03, 0xc5, 0x8c, 0x66, 0x3e, 0xae,
|
||||
0xbd, 0x4a, 0x32, 0x7e, 0x59, 0x89, 0x0b, 0x84,
|
||||
0xc2, 0xd9, 0x90, 0xfa, 0x02, 0x22, 0x90, 0x8d,
|
||||
0x9c, 0xb6, 0x0c, 0x4d, 0xe1, 0x28, 0x76, 0xd7,
|
||||
0x82, 0xc3, 0x36, 0xc2, 0xa3, 0x2a, 0x52, 0xe5,
|
||||
0xfe, 0x3c, 0x8f, 0xe3, 0x4b, 0xda, 0x6a, 0xdb,
|
||||
0xc0, 0x7a, 0x3c, 0x57, 0xfa, 0x85, 0x8f, 0xfb,
|
||||
0x62, 0xc3, 0xa1, 0x38, 0xce, 0x84, 0xf2, 0xba,
|
||||
0x12, 0xf4, 0x30, 0x2a, 0x4a, 0x94, 0xa9, 0x35,
|
||||
0x2c, 0x7d, 0x11, 0xc7, 0x68, 0x1f, 0x47, 0xaa,
|
||||
0x57, 0x43, 0x06, 0x70, 0x79, 0x8c, 0xb6, 0x3b,
|
||||
0x5d, 0x57, 0xf3, 0xf3, 0xc0, 0x2c, 0xc5, 0xde,
|
||||
0x41, 0x99, 0xf6, 0xdd, 0x55, 0x8a, 0xe4, 0x13,
|
||||
0xca, 0xc9, 0xec, 0x69, 0x93, 0x13, 0x48, 0xf0,
|
||||
0x5f, 0xda, 0x2e, 0xfd, 0xfb, 0xa9, 0x1b, 0x92,
|
||||
0xde, 0x49, 0x71, 0x37, 0x8c, 0x3f, 0xc2, 0x08,
|
||||
0x0a, 0x83, 0x25, 0xf1, 0x6e, 0x0a, 0xe3, 0x55,
|
||||
0x85, 0x96, 0x9a, 0x2d, 0xa2, 0xc0, 0xa1, 0xee,
|
||||
0xfe, 0x23, 0x3b, 0x69, 0x22, 0x03, 0xfd, 0xcc,
|
||||
0x8a, 0xdd, 0xb4, 0x53, 0x8d, 0x84, 0xa6, 0xac,
|
||||
0xe0, 0x1e, 0x07, 0xe5, 0xd7, 0xf9, 0xcb, 0xb9,
|
||||
0xe3, 0x9a, 0xb7, 0x84, 0x70, 0xa1, 0x93, 0xd6,
|
||||
0x02, 0x1e, 0xfe, 0xdb, 0x28, 0x7c, 0xf7, 0xd4,
|
||||
0x62, 0x6f, 0x80, 0x75, 0xc8, 0xd8, 0x35, 0x26,
|
||||
0x0c, 0xcb, 0x84, 0xed, 0xbb, 0x95, 0xdf, 0x7f,
|
||||
0xd5, 0xbb, 0x00, 0x96, 0x97, 0x32, 0xe7, 0xba,
|
||||
0xe8, 0x29, 0xb5, 0x1a, 0x51, 0x81, 0xbb, 0x04,
|
||||
0xd1, 0x21, 0x76, 0x34, 0x6d, 0x1e, 0x93, 0x96,
|
||||
0x1f, 0x96, 0x53, 0x5f, 0x5c, 0x9e, 0xf3, 0x9d,
|
||||
0x82, 0x1c, 0x39, 0x36, 0x59, 0xae, 0xc9, 0x3c,
|
||||
0x53, 0x4a, 0x67, 0x65, 0x6e, 0xbf, 0xa6, 0xac,
|
||||
0x3e, 0xda, 0xb2, 0xa7, 0x63, 0x07, 0x17, 0xe1,
|
||||
0x5b, 0xda, 0x6a, 0x31, 0x9f, 0xfb, 0xb4, 0xea,
|
||||
0xa1, 0x97, 0x08, 0x6e, 0xb2, 0x68, 0xf3, 0x72,
|
||||
0x76, 0x99, 0xe8, 0x00, 0x46, 0x88, 0x26, 0xe1,
|
||||
0x3c, 0x07, 0x2b, 0x78, 0x49, 0xda, 0x79, 0x3a,
|
||||
0xbd, 0x6f, 0xca, 0x5c, 0xa0, 0xa8, 0xed, 0x34,
|
||||
0xcc, 0xdb, 0x13, 0xe2, 0x51, 0x9b, 0x3d, 0x03,
|
||||
0xac, 0xc7, 0xf6, 0x32, 0xe1, 0x11, 0x5d, 0xe1,
|
||||
0xc5, 0xfd, 0x9e, 0x7a, 0xcd, 0x06, 0xb9, 0xe6,
|
||||
0xfc, 0xe0, 0x03, 0x31, 0xf4, 0x4a, 0xa9, 0x3b,
|
||||
0x79, 0x01, 0xb0, 0x64, 0x68, 0x9f, 0x6e, 0x76,
|
||||
0xa1, 0xcc, 0xec, 0x17, 0x41, 0x9d, 0xd4, 0x5b,
|
||||
0x4e, 0x9d, 0xe5, 0x46, 0xd4, 0x6b, 0x60, 0x2a,
|
||||
0x23, 0xb5, 0x7a, 0x89, 0x7c, 0x27, 0x96, 0x65,
|
||||
0x97, 0x56, 0xec, 0x98, 0xe3, 0x67, 0x70, 0x75,
|
||||
0x62, 0x41, 0x72, 0x65, 0x61, 0x59, 0x01, 0x36,
|
||||
0x00, 0x01, 0x00, 0x0b, 0x00, 0x06, 0x04, 0x72,
|
||||
0x00, 0x20, 0x9d, 0xff, 0xcb, 0xf3, 0x6c, 0x38,
|
||||
0x3a, 0xe6, 0x99, 0xfb, 0x98, 0x68, 0xdc, 0x6d,
|
||||
0xcb, 0x89, 0xd7, 0x15, 0x38, 0x84, 0xbe, 0x28,
|
||||
0x03, 0x92, 0x2c, 0x12, 0x41, 0x58, 0xbf, 0xad,
|
||||
0x22, 0xae, 0x00, 0x10, 0x00, 0x10, 0x08, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc5, 0xb6,
|
||||
0x9c, 0x06, 0x1d, 0xcf, 0xb9, 0xf2, 0x5e, 0x99,
|
||||
0x7d, 0x6d, 0x73, 0xd8, 0x36, 0xc1, 0x4a, 0x90,
|
||||
0x05, 0x4d, 0x82, 0x57, 0xc1, 0xb6, 0x6a, 0xd1,
|
||||
0x43, 0x03, 0x85, 0xf8, 0x52, 0x4f, 0xd2, 0x27,
|
||||
0x91, 0x0b, 0xb5, 0x93, 0xa0, 0x68, 0xf8, 0x80,
|
||||
0x1b, 0xaa, 0x65, 0x97, 0x45, 0x11, 0x86, 0x34,
|
||||
0xd6, 0x67, 0xf8, 0xd5, 0x12, 0x79, 0x84, 0xee,
|
||||
0x70, 0x99, 0x00, 0x63, 0xa8, 0xb4, 0x43, 0x0b,
|
||||
0x4c, 0x57, 0x4a, 0xd6, 0x9b, 0x75, 0x63, 0x8a,
|
||||
0x46, 0x57, 0xdb, 0x14, 0xc8, 0x71, 0xd1, 0xb3,
|
||||
0x07, 0x68, 0x58, 0xbc, 0x55, 0x84, 0x80, 0x2a,
|
||||
0xd2, 0x36, 0x9f, 0xc1, 0x64, 0xa0, 0x11, 0x4b,
|
||||
0xc9, 0x32, 0x31, 0x3a, 0xd6, 0x87, 0x26, 0x1a,
|
||||
0x3a, 0x78, 0x3d, 0x89, 0xdb, 0x00, 0x28, 0x3b,
|
||||
0xae, 0x2b, 0x1b, 0x56, 0xe2, 0x8c, 0x4c, 0x63,
|
||||
0xac, 0x6e, 0x6c, 0xf7, 0xb5, 0x7d, 0x4d, 0x0b,
|
||||
0x9f, 0x06, 0xa0, 0x10, 0x35, 0x38, 0x20, 0x4d,
|
||||
0xcc, 0x07, 0xd7, 0x00, 0x4e, 0x86, 0xba, 0xfe,
|
||||
0x8b, 0xe4, 0x3f, 0x4a, 0xd6, 0xca, 0xbf, 0x67,
|
||||
0x40, 0x1a, 0xa4, 0xda, 0x82, 0x52, 0x15, 0xb8,
|
||||
0x14, 0x3a, 0x7c, 0xa9, 0x02, 0xc1, 0x01, 0x69,
|
||||
0xc6, 0x51, 0xd4, 0xbc, 0x1f, 0x95, 0xb2, 0xee,
|
||||
0x1f, 0xdd, 0xb5, 0x73, 0x16, 0x5e, 0x29, 0x3f,
|
||||
0x47, 0xac, 0x65, 0xfb, 0x63, 0x5c, 0xb9, 0xc8,
|
||||
0x13, 0x2d, 0xec, 0x85, 0xde, 0x71, 0x0d, 0x84,
|
||||
0x93, 0x74, 0x76, 0x91, 0xdd, 0x1d, 0x6d, 0x3d,
|
||||
0xc7, 0x36, 0x19, 0x19, 0x86, 0xde, 0x7c, 0xca,
|
||||
0xd6, 0xc6, 0x65, 0x7e, 0x4b, 0x24, 0x9c, 0xce,
|
||||
0x92, 0x6b, 0x1c, 0xe0, 0xa0, 0xa9, 0x6c, 0xc3,
|
||||
0xed, 0x4f, 0x2a, 0x54, 0x07, 0x00, 0x32, 0x5e,
|
||||
0x1b, 0x94, 0x37, 0xcd, 0xe2, 0x32, 0xa8, 0xd5,
|
||||
0x2c, 0xfb, 0x03, 0x9d, 0x79, 0xdf, 0x68, 0x63,
|
||||
0x65, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x58,
|
||||
0xa1, 0xff, 0x54, 0x43, 0x47, 0x80, 0x17, 0x00,
|
||||
0x22, 0x00, 0x0b, 0xdb, 0x1f, 0x74, 0x21, 0x4f,
|
||||
0xa9, 0x0d, 0x90, 0x64, 0xa2, 0x33, 0xbe, 0x3f,
|
||||
0xf1, 0x95, 0xb0, 0x4e, 0x3f, 0x02, 0xdc, 0xad,
|
||||
0xb0, 0x05, 0x13, 0xe6, 0x32, 0x5f, 0xed, 0x90,
|
||||
0x2c, 0xad, 0xc0, 0x00, 0x14, 0x58, 0x52, 0x07,
|
||||
0x5d, 0x64, 0x6c, 0x1f, 0xd1, 0x13, 0x7f, 0xc3,
|
||||
0x74, 0xf6, 0x4b, 0xe3, 0xa0, 0x2e, 0xb7, 0x71,
|
||||
0xda, 0x00, 0x00, 0x00, 0x00, 0x29, 0x3c, 0x64,
|
||||
0xdf, 0x95, 0x38, 0xba, 0x73, 0xe3, 0x57, 0x61,
|
||||
0xa0, 0x01, 0x24, 0x01, 0x08, 0xc9, 0xd6, 0xea,
|
||||
0x60, 0xe4, 0x00, 0x22, 0x00, 0x0b, 0xe1, 0x86,
|
||||
0xbb, 0x79, 0x27, 0xe5, 0x01, 0x19, 0x90, 0xb3,
|
||||
0xe9, 0x08, 0xb0, 0xee, 0xfa, 0x3a, 0x67, 0xa9,
|
||||
0xf3, 0xc8, 0x9e, 0x03, 0x41, 0x07, 0x75, 0x60,
|
||||
0xbc, 0x94, 0x0c, 0x2a, 0xb7, 0xad, 0x00, 0x22,
|
||||
0x00, 0x0b, 0x35, 0xb1, 0x72, 0xd6, 0x3c, 0xe9,
|
||||
0x85, 0xe8, 0x66, 0xed, 0x10, 0x7a, 0x5c, 0xa3,
|
||||
0xe6, 0xd9, 0x4d, 0xf0, 0x52, 0x69, 0x26, 0x14,
|
||||
0xb4, 0x36, 0x7e, 0xad, 0x76, 0x9e, 0x58, 0x68,
|
||||
0x3e, 0x91
|
||||
};
|
||||
|
||||
/*
|
||||
* Security Key By Yubico
|
||||
* 5.1.X
|
||||
* f8a011f3-8c0a-4d15-8006-17111f9edc7d
|
||||
*/
|
||||
*/
|
||||
const unsigned char aaguid[16] = {
|
||||
0xf8, 0xa0, 0x11, 0xf3, 0x8c, 0x0a, 0x4d, 0x15,
|
||||
0x80, 0x06, 0x17, 0x11, 0x1f, 0x9e, 0xdc, 0x7d,
|
||||
};
|
||||
|
||||
/*
|
||||
* Windows Hello by Microsoft
|
||||
*/
|
||||
const unsigned char aaguid_tpm[16] = {
|
||||
0x08, 0x98, 0x70, 0x58, 0xca, 0xdc, 0x4b, 0x81,
|
||||
0xb6, 0xe1, 0x30, 0xde, 0x50, 0xdc, 0xbe, 0x96,
|
||||
};
|
||||
|
||||
const char rp_id[] = "localhost";
|
||||
const char rp_name[] = "sweet home localhost";
|
||||
|
||||
@ -606,7 +1214,7 @@ junk_cdh(void)
|
||||
junk = malloc(sizeof(cdh));
|
||||
assert(junk != NULL);
|
||||
memcpy(junk, cdh, sizeof(cdh));
|
||||
junk[0] = ~junk[0];
|
||||
junk[0] = (unsigned char)~junk[0];
|
||||
|
||||
c = alloc_cred();
|
||||
assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK);
|
||||
@ -708,7 +1316,7 @@ junk_authdata(void)
|
||||
junk = malloc(sizeof(authdata));
|
||||
assert(junk != NULL);
|
||||
memcpy(junk, authdata, sizeof(authdata));
|
||||
junk[0] = ~junk[0];
|
||||
junk[0] = (unsigned char)~junk[0];
|
||||
|
||||
unset = calloc(1, sizeof(aaguid));
|
||||
assert(unset != NULL);
|
||||
@ -749,7 +1357,7 @@ junk_sig(void)
|
||||
junk = malloc(sizeof(sig));
|
||||
assert(junk != NULL);
|
||||
memcpy(junk, sig, sizeof(sig));
|
||||
junk[0] = ~junk[0];
|
||||
junk[0] = (unsigned char)~junk[0];
|
||||
|
||||
c = alloc_cred();
|
||||
assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK);
|
||||
@ -781,7 +1389,7 @@ junk_x509(void)
|
||||
junk = malloc(sizeof(x509));
|
||||
assert(junk != NULL);
|
||||
memcpy(junk, x509, sizeof(x509));
|
||||
junk[0] = ~junk[0];
|
||||
junk[0] = (unsigned char)~junk[0];
|
||||
|
||||
c = alloc_cred();
|
||||
assert(fido_cred_set_type(c, COSE_ES256) == FIDO_OK);
|
||||
@ -954,6 +1562,31 @@ fmt_none(void)
|
||||
free_cred(c);
|
||||
}
|
||||
|
||||
static void
|
||||
valid_tpm_cred(void)
|
||||
{
|
||||
fido_cred_t *c;
|
||||
|
||||
c = alloc_cred();
|
||||
assert(fido_cred_set_type(c, COSE_RS256) == FIDO_OK);
|
||||
assert(fido_cred_set_clientdata(c, cdh, sizeof(cdh)) == FIDO_OK);
|
||||
assert(fido_cred_set_rp(c, rp_id, rp_name) == FIDO_OK);
|
||||
assert(fido_cred_set_authdata(c, authdata_tpm, sizeof(authdata_tpm)) == FIDO_OK);
|
||||
assert(fido_cred_set_rk(c, FIDO_OPT_FALSE) == FIDO_OK);
|
||||
assert(fido_cred_set_uv(c, FIDO_OPT_TRUE) == FIDO_OK);
|
||||
assert(fido_cred_set_fmt(c, "tpm") == FIDO_OK);
|
||||
assert(fido_cred_set_attstmt(c, attstmt_tpm, sizeof(attstmt_tpm)) == FIDO_OK);
|
||||
assert(fido_cred_verify(c) == FIDO_OK);
|
||||
assert(fido_cred_prot(c) == 0);
|
||||
assert(fido_cred_pubkey_len(c) == sizeof(pubkey_tpm));
|
||||
assert(memcmp(fido_cred_pubkey_ptr(c), pubkey_tpm, sizeof(pubkey_tpm)) == 0);
|
||||
assert(fido_cred_id_len(c) == sizeof(id_tpm));
|
||||
assert(memcmp(fido_cred_id_ptr(c), id_tpm, sizeof(id_tpm)) == 0);
|
||||
assert(fido_cred_aaguid_len(c) == sizeof(aaguid_tpm));
|
||||
assert(memcmp(fido_cred_aaguid_ptr(c), aaguid_tpm, sizeof(aaguid_tpm)) == 0);
|
||||
free_cred(c);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@ -983,6 +1616,7 @@ main(void)
|
||||
wrong_credprot();
|
||||
raw_authdata();
|
||||
fmt_none();
|
||||
valid_tpm_cred();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
154
regress/dev.c
154
regress/dev.c
@ -1,12 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2019-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <fido.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../fuzz/wiredata_fido2.h"
|
||||
|
||||
@ -17,6 +19,7 @@ static uint8_t ctap_nonce[8];
|
||||
static uint8_t *wiredata_ptr;
|
||||
static size_t wiredata_len;
|
||||
static int initialised;
|
||||
static long interval_ms;
|
||||
|
||||
static void *
|
||||
dummy_open(const char *path)
|
||||
@ -35,9 +38,9 @@ dummy_close(void *handle)
|
||||
static int
|
||||
dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
(void)ms;
|
||||
struct timespec tv;
|
||||
size_t n;
|
||||
long d;
|
||||
|
||||
assert(handle == FAKE_DEV_HANDLE);
|
||||
assert(ptr != NULL);
|
||||
@ -52,6 +55,21 @@ dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)
|
||||
initialised = 1;
|
||||
}
|
||||
|
||||
if (ms >= 0 && ms < interval_ms)
|
||||
d = ms;
|
||||
else
|
||||
d = interval_ms;
|
||||
|
||||
if (d) {
|
||||
tv.tv_sec = d / 1000;
|
||||
tv.tv_nsec = (d % 1000) * 1000000;
|
||||
if (nanosleep(&tv, NULL) == -1)
|
||||
err(1, "nanosleep");
|
||||
}
|
||||
|
||||
if (d != interval_ms)
|
||||
return (-1); /* timeout */
|
||||
|
||||
if (wiredata_len < len)
|
||||
n = wiredata_len;
|
||||
else
|
||||
@ -67,6 +85,8 @@ dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)
|
||||
static int
|
||||
dummy_write(void *handle, const unsigned char *ptr, size_t len)
|
||||
{
|
||||
struct timespec tv;
|
||||
|
||||
assert(handle == FAKE_DEV_HANDLE);
|
||||
assert(ptr != NULL);
|
||||
assert(len == REPORT_LEN);
|
||||
@ -74,6 +94,13 @@ dummy_write(void *handle, const unsigned char *ptr, size_t len)
|
||||
if (!initialised)
|
||||
memcpy(&ctap_nonce, &ptr[8], sizeof(ctap_nonce));
|
||||
|
||||
if (interval_ms) {
|
||||
tv.tv_sec = interval_ms / 1000;
|
||||
tv.tv_nsec = (interval_ms % 1000) * 1000000;
|
||||
if (nanosleep(&tv, NULL) == -1)
|
||||
err(1, "nanosleep");
|
||||
}
|
||||
|
||||
return ((int)len);
|
||||
}
|
||||
|
||||
@ -153,6 +180,7 @@ reopen(void)
|
||||
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
|
||||
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
|
||||
assert(fido_dev_close(dev) == FIDO_OK);
|
||||
fido_dev_free(&dev);
|
||||
wiredata_clear(&wiredata);
|
||||
}
|
||||
|
||||
@ -177,6 +205,34 @@ double_open(void)
|
||||
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
|
||||
assert(fido_dev_open(dev, "dummy") == FIDO_ERR_INVALID_ARGUMENT);
|
||||
assert(fido_dev_close(dev) == FIDO_OK);
|
||||
fido_dev_free(&dev);
|
||||
wiredata_clear(&wiredata);
|
||||
}
|
||||
|
||||
static void
|
||||
double_close(void)
|
||||
{
|
||||
const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
|
||||
uint8_t *wiredata;
|
||||
fido_dev_t *dev = NULL;
|
||||
fido_dev_io_t io;
|
||||
|
||||
memset(&io, 0, sizeof(io));
|
||||
|
||||
io.open = dummy_open;
|
||||
io.close = dummy_close;
|
||||
io.read = dummy_read;
|
||||
io.write = dummy_write;
|
||||
|
||||
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
|
||||
assert((dev = fido_dev_new()) != NULL);
|
||||
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
|
||||
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
|
||||
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
|
||||
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
|
||||
assert(fido_dev_close(dev) == FIDO_OK);
|
||||
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
|
||||
fido_dev_free(&dev);
|
||||
wiredata_clear(&wiredata);
|
||||
}
|
||||
|
||||
@ -215,6 +271,7 @@ is_fido2(void)
|
||||
assert(fido_dev_is_fido2(dev) == true);
|
||||
assert(fido_dev_supports_pin(dev) == false);
|
||||
assert(fido_dev_close(dev) == FIDO_OK);
|
||||
fido_dev_free(&dev);
|
||||
wiredata_clear(&wiredata);
|
||||
}
|
||||
|
||||
@ -248,9 +305,94 @@ has_pin(void)
|
||||
assert(fido_dev_reset(dev) == FIDO_OK);
|
||||
assert(fido_dev_has_pin(dev) == false);
|
||||
assert(fido_dev_close(dev) == FIDO_OK);
|
||||
fido_dev_free(&dev);
|
||||
wiredata_clear(&wiredata);
|
||||
}
|
||||
|
||||
static void
|
||||
timeout_rx(void)
|
||||
{
|
||||
const uint8_t timeout_rx_data[] = {
|
||||
WIREDATA_CTAP_CBOR_INFO,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_CBOR_STATUS
|
||||
};
|
||||
uint8_t *wiredata;
|
||||
fido_dev_t *dev = NULL;
|
||||
fido_dev_io_t io;
|
||||
|
||||
memset(&io, 0, sizeof(io));
|
||||
|
||||
io.open = dummy_open;
|
||||
io.close = dummy_close;
|
||||
io.read = dummy_read;
|
||||
io.write = dummy_write;
|
||||
|
||||
wiredata = wiredata_setup(timeout_rx_data, sizeof(timeout_rx_data));
|
||||
assert((dev = fido_dev_new()) != NULL);
|
||||
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
|
||||
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
|
||||
assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK);
|
||||
interval_ms = 1000;
|
||||
assert(fido_dev_reset(dev) == FIDO_ERR_RX);
|
||||
assert(fido_dev_close(dev) == FIDO_OK);
|
||||
fido_dev_free(&dev);
|
||||
wiredata_clear(&wiredata);
|
||||
interval_ms = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
timeout_ok(void)
|
||||
{
|
||||
const uint8_t timeout_ok_data[] = {
|
||||
WIREDATA_CTAP_CBOR_INFO,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_KEEPALIVE,
|
||||
WIREDATA_CTAP_CBOR_STATUS
|
||||
};
|
||||
uint8_t *wiredata;
|
||||
fido_dev_t *dev = NULL;
|
||||
fido_dev_io_t io;
|
||||
|
||||
memset(&io, 0, sizeof(io));
|
||||
|
||||
io.open = dummy_open;
|
||||
io.close = dummy_close;
|
||||
io.read = dummy_read;
|
||||
io.write = dummy_write;
|
||||
|
||||
wiredata = wiredata_setup(timeout_ok_data, sizeof(timeout_ok_data));
|
||||
assert((dev = fido_dev_new()) != NULL);
|
||||
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
|
||||
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
|
||||
assert(fido_dev_set_timeout(dev, 30 * 1000) == FIDO_OK);
|
||||
interval_ms = 1000;
|
||||
assert(fido_dev_reset(dev) == FIDO_OK);
|
||||
assert(fido_dev_close(dev) == FIDO_OK);
|
||||
fido_dev_free(&dev);
|
||||
wiredata_clear(&wiredata);
|
||||
interval_ms = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
timeout_misc(void)
|
||||
{
|
||||
fido_dev_t *dev;
|
||||
|
||||
assert((dev = fido_dev_new()) != NULL);
|
||||
assert(fido_dev_set_timeout(dev, -2) == FIDO_ERR_INVALID_ARGUMENT);
|
||||
assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK);
|
||||
assert(fido_dev_set_timeout(dev, -1) == FIDO_OK);
|
||||
fido_dev_free(&dev);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@ -259,8 +401,12 @@ main(void)
|
||||
open_iff_ok();
|
||||
reopen();
|
||||
double_open();
|
||||
double_close();
|
||||
is_fido2();
|
||||
has_pin();
|
||||
timeout_rx();
|
||||
timeout_ok();
|
||||
timeout_misc();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
# Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
@ -30,11 +30,16 @@ list(APPEND FIDO_SOURCES
|
||||
pin.c
|
||||
random.c
|
||||
reset.c
|
||||
rs1.c
|
||||
rs256.c
|
||||
time.c
|
||||
tpm.c
|
||||
types.c
|
||||
u2f.c
|
||||
)
|
||||
|
||||
if(FUZZ)
|
||||
list(APPEND FIDO_SOURCES ../fuzz/clock.c)
|
||||
list(APPEND FIDO_SOURCES ../fuzz/prng.c)
|
||||
list(APPEND FIDO_SOURCES ../fuzz/uniform_random.c)
|
||||
list(APPEND FIDO_SOURCES ../fuzz/udev.c)
|
||||
@ -62,7 +67,8 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
|
||||
list(APPEND FIDO_SOURCES hid_netbsd.c hid_unix.c)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
|
||||
list(APPEND FIDO_SOURCES hid_openbsd.c hid_unix.c)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
|
||||
CMAKE_SYSTEM_NAME STREQUAL "MidnightBSD")
|
||||
list(APPEND FIDO_SOURCES hid_freebsd.c hid_unix.c)
|
||||
else()
|
||||
message(FATAL_ERROR "please define a hid backend for your platform")
|
||||
@ -75,11 +81,11 @@ endif()
|
||||
|
||||
list(APPEND COMPAT_SOURCES
|
||||
../openbsd-compat/bsd-getpagesize.c
|
||||
../openbsd-compat/clock_gettime.c
|
||||
../openbsd-compat/endian_win32.c
|
||||
../openbsd-compat/explicit_bzero.c
|
||||
../openbsd-compat/explicit_bzero_win32.c
|
||||
../openbsd-compat/freezero.c
|
||||
../openbsd-compat/hkdf.c
|
||||
../openbsd-compat/recallocarray.c
|
||||
../openbsd-compat/strlcat.c
|
||||
../openbsd-compat/timingsafe_bcmp.c
|
||||
@ -87,9 +93,6 @@ list(APPEND COMPAT_SOURCES
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND BASE_LIBRARIES wsock32 ws2_32 bcrypt setupapi hid)
|
||||
if(USE_WINHELLO)
|
||||
list(APPEND BASE_LIBRARIES webauthn)
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
list(APPEND BASE_LIBRARIES "-framework CoreFoundation" "-framework IOKit")
|
||||
endif()
|
||||
|
168
src/assert.c
168
src/assert.c
@ -4,7 +4,6 @@
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "fido.h"
|
||||
@ -79,7 +78,7 @@ parse_assert_reply(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
|
||||
static int
|
||||
fido_dev_get_assert_tx(fido_dev_t *dev, fido_assert_t *assert,
|
||||
const es256_pk_t *pk, const fido_blob_t *ecdh, const char *pin)
|
||||
const es256_pk_t *pk, const fido_blob_t *ecdh, const char *pin, int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
fido_opt_t uv = assert->uv;
|
||||
@ -127,7 +126,7 @@ fido_dev_get_assert_tx(fido_dev_t *dev, fido_assert_t *assert,
|
||||
if (pin != NULL || (uv == FIDO_OPT_TRUE &&
|
||||
fido_dev_supports_permissions(dev))) {
|
||||
if ((r = cbor_add_uv_params(dev, cmd, &assert->cdh, pk, ecdh,
|
||||
pin, assert->rp_id, &argv[5], &argv[6])) != FIDO_OK) {
|
||||
pin, assert->rp_id, &argv[5], &argv[6], ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: cbor_add_uv_params", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -144,7 +143,7 @@ fido_dev_get_assert_tx(fido_dev_t *dev, fido_assert_t *assert,
|
||||
|
||||
/* frame and transmit */
|
||||
if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -159,7 +158,7 @@ fido_dev_get_assert_tx(fido_dev_t *dev, fido_assert_t *assert,
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_get_assert_rx(fido_dev_t *dev, fido_assert_t *assert, int ms)
|
||||
fido_dev_get_assert_rx(fido_dev_t *dev, fido_assert_t *assert, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -200,11 +199,11 @@ fido_dev_get_assert_rx(fido_dev_t *dev, fido_assert_t *assert, int ms)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_get_next_assert_tx(fido_dev_t *dev)
|
||||
fido_get_next_assert_tx(fido_dev_t *dev, int *ms)
|
||||
{
|
||||
const unsigned char cbor[] = { CTAP_CBOR_NEXT_ASSERT };
|
||||
|
||||
if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor)) < 0) {
|
||||
if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor), ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
return (FIDO_ERR_TX);
|
||||
}
|
||||
@ -213,7 +212,7 @@ fido_get_next_assert_tx(fido_dev_t *dev)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_get_next_assert_rx(fido_dev_t *dev, fido_assert_t *assert, int ms)
|
||||
fido_get_next_assert_rx(fido_dev_t *dev, fido_assert_t *assert, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -243,16 +242,17 @@ fido_get_next_assert_rx(fido_dev_t *dev, fido_assert_t *assert, int ms)
|
||||
|
||||
static int
|
||||
fido_dev_get_assert_wait(fido_dev_t *dev, fido_assert_t *assert,
|
||||
const es256_pk_t *pk, const fido_blob_t *ecdh, const char *pin, int ms)
|
||||
const es256_pk_t *pk, const fido_blob_t *ecdh, const char *pin, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = fido_dev_get_assert_tx(dev, assert, pk, ecdh, pin)) != FIDO_OK ||
|
||||
if ((r = fido_dev_get_assert_tx(dev, assert, pk, ecdh, pin,
|
||||
ms)) != FIDO_OK ||
|
||||
(r = fido_dev_get_assert_rx(dev, assert, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
while (assert->stmt_len < assert->stmt_cnt) {
|
||||
if ((r = fido_get_next_assert_tx(dev)) != FIDO_OK ||
|
||||
if ((r = fido_get_next_assert_tx(dev, ms)) != FIDO_OK ||
|
||||
(r = fido_get_next_assert_rx(dev, assert, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
assert->stmt_len++;
|
||||
@ -286,11 +286,12 @@ fido_dev_get_assert(fido_dev_t *dev, fido_assert_t *assert, const char *pin)
|
||||
{
|
||||
fido_blob_t *ecdh = NULL;
|
||||
es256_pk_t *pk = NULL;
|
||||
int ms = dev->timeout_ms;
|
||||
int r;
|
||||
|
||||
#ifdef USE_WINHELLO
|
||||
if (dev->flags & FIDO_DEV_WINHELLO)
|
||||
return (fido_winhello_get_assert(dev, assert, pin));
|
||||
return (fido_winhello_get_assert(dev, assert, pin, ms));
|
||||
#endif
|
||||
|
||||
if (assert->rp_id == NULL || assert->cdh.ptr == NULL) {
|
||||
@ -302,19 +303,19 @@ fido_dev_get_assert(fido_dev_t *dev, fido_assert_t *assert, const char *pin)
|
||||
if (fido_dev_is_fido2(dev) == false) {
|
||||
if (pin != NULL || assert->ext.mask != 0)
|
||||
return (FIDO_ERR_UNSUPPORTED_OPTION);
|
||||
return (u2f_authenticate(dev, assert, -1));
|
||||
return (u2f_authenticate(dev, assert, &ms));
|
||||
}
|
||||
|
||||
if (pin != NULL || (assert->uv == FIDO_OPT_TRUE &&
|
||||
fido_dev_supports_permissions(dev)) ||
|
||||
(assert->ext.mask & FIDO_EXT_HMAC_SECRET)) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh, &ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_do_ecdh", __func__);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
r = fido_dev_get_assert_wait(dev, assert, pk, ecdh, pin, -1);
|
||||
r = fido_dev_get_assert_wait(dev, assert, pk, ecdh, pin, &ms);
|
||||
if (r == FIDO_OK && (assert->ext.mask & FIDO_EXT_HMAC_SECRET))
|
||||
if (decrypt_hmac_secrets(dev, assert, ecdh) < 0) {
|
||||
fido_log_debug("%s: decrypt_hmac_secrets", __func__);
|
||||
@ -372,7 +373,8 @@ fido_get_signed_hash(int cose_alg, fido_blob_t *dgst,
|
||||
unsigned char *authdata_ptr = NULL;
|
||||
size_t authdata_len;
|
||||
struct cbor_load_result cbor;
|
||||
SHA256_CTX ctx;
|
||||
const EVP_MD *md = NULL;
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
int ok = -1;
|
||||
|
||||
if ((item = cbor_load(authdata_cbor->ptr, authdata_cbor->len,
|
||||
@ -386,10 +388,13 @@ fido_get_signed_hash(int cose_alg, fido_blob_t *dgst,
|
||||
authdata_len = cbor_bytestring_length(item);
|
||||
|
||||
if (cose_alg != COSE_EDDSA) {
|
||||
if (dgst->len < SHA256_DIGEST_LENGTH || SHA256_Init(&ctx) == 0 ||
|
||||
SHA256_Update(&ctx, authdata_ptr, authdata_len) == 0 ||
|
||||
SHA256_Update(&ctx, clientdata->ptr, clientdata->len) == 0 ||
|
||||
SHA256_Final(dgst->ptr, &ctx) == 0) {
|
||||
if (dgst->len < SHA256_DIGEST_LENGTH ||
|
||||
(md = EVP_sha256()) == NULL ||
|
||||
(ctx = EVP_MD_CTX_new()) == NULL ||
|
||||
EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
|
||||
EVP_DigestUpdate(ctx, authdata_ptr, authdata_len) != 1 ||
|
||||
EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
|
||||
EVP_DigestFinal_ex(ctx, dgst->ptr, NULL) != 1) {
|
||||
fido_log_debug("%s: sha256", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -411,122 +416,7 @@ fido_get_signed_hash(int cose_alg, fido_blob_t *dgst,
|
||||
if (item != NULL)
|
||||
cbor_decref(&item);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int
|
||||
fido_verify_sig_es256(const fido_blob_t *dgst, const es256_pk_t *pk,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EC_KEY *ec = NULL;
|
||||
int ok = -1;
|
||||
|
||||
/* ECDSA_verify needs ints */
|
||||
if (dgst->len > INT_MAX || sig->len > INT_MAX) {
|
||||
fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__,
|
||||
dgst->len, sig->len);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL ||
|
||||
(ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) {
|
||||
fido_log_debug("%s: pk -> ec", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ECDSA_verify(0, dgst->ptr, (int)dgst->len, sig->ptr,
|
||||
(int)sig->len, ec) != 1) {
|
||||
fido_log_debug("%s: ECDSA_verify", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
if (pkey != NULL)
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int
|
||||
fido_verify_sig_rs256(const fido_blob_t *dgst, const rs256_pk_t *pk,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
RSA *rsa = NULL;
|
||||
int ok = -1;
|
||||
|
||||
/* RSA_verify needs unsigned ints */
|
||||
if (dgst->len > UINT_MAX || sig->len > UINT_MAX) {
|
||||
fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__,
|
||||
dgst->len, sig->len);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL ||
|
||||
(rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) {
|
||||
fido_log_debug("%s: pk -> ec", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (RSA_verify(NID_sha256, dgst->ptr, (unsigned int)dgst->len, sig->ptr,
|
||||
(unsigned int)sig->len, rsa) != 1) {
|
||||
fido_log_debug("%s: RSA_verify", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
if (pkey != NULL)
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int
|
||||
fido_verify_sig_eddsa(const fido_blob_t *dgst, const eddsa_pk_t *pk,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_MD_CTX *mdctx = NULL;
|
||||
int ok = -1;
|
||||
|
||||
/* EVP_DigestVerify needs ints */
|
||||
if (dgst->len > INT_MAX || sig->len > INT_MAX) {
|
||||
fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__,
|
||||
dgst->len, sig->len);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) {
|
||||
fido_log_debug("%s: pk -> pkey", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((mdctx = EVP_MD_CTX_new()) == NULL) {
|
||||
fido_log_debug("%s: EVP_MD_CTX_new", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey) != 1) {
|
||||
fido_log_debug("%s: EVP_DigestVerifyInit", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerify(mdctx, sig->ptr, sig->len, dgst->ptr,
|
||||
dgst->len) != 1) {
|
||||
fido_log_debug("%s: EVP_DigestVerify", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
if (mdctx != NULL)
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
|
||||
if (pkey != NULL)
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
@ -589,13 +479,13 @@ fido_assert_verify(const fido_assert_t *assert, size_t idx, int cose_alg,
|
||||
|
||||
switch (cose_alg) {
|
||||
case COSE_ES256:
|
||||
ok = fido_verify_sig_es256(&dgst, pk, &stmt->sig);
|
||||
ok = es256_pk_verify_sig(&dgst, pk, &stmt->sig);
|
||||
break;
|
||||
case COSE_RS256:
|
||||
ok = fido_verify_sig_rs256(&dgst, pk, &stmt->sig);
|
||||
ok = rs256_pk_verify_sig(&dgst, pk, &stmt->sig);
|
||||
break;
|
||||
case COSE_EDDSA:
|
||||
ok = fido_verify_sig_eddsa(&dgst, pk, &stmt->sig);
|
||||
ok = eddsa_pk_verify_sig(&dgst, pk, &stmt->sig);
|
||||
break;
|
||||
default:
|
||||
fido_log_debug("%s: unsupported cose_alg %d", __func__,
|
||||
|
@ -22,7 +22,7 @@ parse_authkey(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_authkey_tx(fido_dev_t *dev)
|
||||
fido_dev_authkey_tx(fido_dev_t *dev, int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
cbor_item_t *argv[2];
|
||||
@ -43,7 +43,7 @@ fido_dev_authkey_tx(fido_dev_t *dev)
|
||||
|
||||
/* frame and transmit */
|
||||
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -58,13 +58,13 @@ fido_dev_authkey_tx(fido_dev_t *dev)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_authkey_rx(fido_dev_t *dev, es256_pk_t *authkey, int ms)
|
||||
fido_dev_authkey_rx(fido_dev_t *dev, es256_pk_t *authkey, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
|
||||
fido_log_debug("%s: dev=%p, authkey=%p, ms=%d", __func__, (void *)dev,
|
||||
(void *)authkey, ms);
|
||||
(void *)authkey, *ms);
|
||||
|
||||
memset(authkey, 0, sizeof(*authkey));
|
||||
|
||||
@ -79,11 +79,11 @@ fido_dev_authkey_rx(fido_dev_t *dev, es256_pk_t *authkey, int ms)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_authkey_wait(fido_dev_t *dev, es256_pk_t *authkey, int ms)
|
||||
fido_dev_authkey_wait(fido_dev_t *dev, es256_pk_t *authkey, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = fido_dev_authkey_tx(dev)) != FIDO_OK ||
|
||||
if ((r = fido_dev_authkey_tx(dev, ms)) != FIDO_OK ||
|
||||
(r = fido_dev_authkey_rx(dev, authkey, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -91,7 +91,7 @@ fido_dev_authkey_wait(fido_dev_t *dev, es256_pk_t *authkey, int ms)
|
||||
}
|
||||
|
||||
int
|
||||
fido_dev_authkey(fido_dev_t *dev, es256_pk_t *authkey)
|
||||
fido_dev_authkey(fido_dev_t *dev, es256_pk_t *authkey, int *ms)
|
||||
{
|
||||
return (fido_dev_authkey_wait(dev, authkey, -1));
|
||||
return (fido_dev_authkey_wait(dev, authkey, ms));
|
||||
}
|
||||
|
77
src/bio.c
77
src/bio.c
@ -58,7 +58,7 @@ bio_prepare_hmac(uint8_t cmd, cbor_item_t **argv, size_t argc,
|
||||
|
||||
static int
|
||||
bio_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **sub_argv, size_t sub_argc,
|
||||
const char *pin, const fido_blob_t *token)
|
||||
const char *pin, const fido_blob_t *token, int *ms)
|
||||
{
|
||||
cbor_item_t *argv[5];
|
||||
es256_pk_t *pk = NULL;
|
||||
@ -90,12 +90,12 @@ bio_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **sub_argv, size_t sub_argc,
|
||||
|
||||
/* pinProtocol, pinAuth */
|
||||
if (pin) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_do_ecdh", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((r = cbor_add_uv_params(dev, cmd, &hmac, pk, ecdh, pin,
|
||||
NULL, &argv[4], &argv[3])) != FIDO_OK) {
|
||||
NULL, &argv[4], &argv[3], ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: cbor_add_uv_params", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -109,7 +109,7 @@ bio_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **sub_argv, size_t sub_argc,
|
||||
|
||||
/* framing and transmission */
|
||||
if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -231,7 +231,7 @@ bio_parse_template_array(const cbor_item_t *key, const cbor_item_t *val,
|
||||
}
|
||||
|
||||
static int
|
||||
bio_rx_template_array(fido_dev_t *dev, fido_bio_template_array_t *ta, int ms)
|
||||
bio_rx_template_array(fido_dev_t *dev, fido_bio_template_array_t *ta, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -256,11 +256,11 @@ bio_rx_template_array(fido_dev_t *dev, fido_bio_template_array_t *ta, int ms)
|
||||
|
||||
static int
|
||||
bio_get_template_array_wait(fido_dev_t *dev, fido_bio_template_array_t *ta,
|
||||
const char *pin, int ms)
|
||||
const char *pin, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = bio_tx(dev, CMD_ENUM, NULL, 0, pin, NULL)) != FIDO_OK ||
|
||||
if ((r = bio_tx(dev, CMD_ENUM, NULL, 0, pin, NULL, ms)) != FIDO_OK ||
|
||||
(r = bio_rx_template_array(dev, ta, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -271,15 +271,17 @@ int
|
||||
fido_bio_dev_get_template_array(fido_dev_t *dev, fido_bio_template_array_t *ta,
|
||||
const char *pin)
|
||||
{
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
if (pin == NULL)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
return (bio_get_template_array_wait(dev, ta, pin, -1));
|
||||
return (bio_get_template_array_wait(dev, ta, pin, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
bio_set_template_name_wait(fido_dev_t *dev, const fido_bio_template_t *t,
|
||||
const char *pin, int ms)
|
||||
const char *pin, int *ms)
|
||||
{
|
||||
cbor_item_t *argv[2];
|
||||
int r = FIDO_ERR_INTERNAL;
|
||||
@ -292,7 +294,8 @@ bio_set_template_name_wait(fido_dev_t *dev, const fido_bio_template_t *t,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((r = bio_tx(dev, CMD_SET_NAME, argv, 2, pin, NULL)) != FIDO_OK ||
|
||||
if ((r = bio_tx(dev, CMD_SET_NAME, argv, 2, pin, NULL,
|
||||
ms)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: tx/rx", __func__);
|
||||
goto fail;
|
||||
@ -309,10 +312,12 @@ int
|
||||
fido_bio_dev_set_template_name(fido_dev_t *dev, const fido_bio_template_t *t,
|
||||
const char *pin)
|
||||
{
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
if (pin == NULL || t->name == NULL)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
return (bio_set_template_name_wait(dev, t, pin, -1));
|
||||
return (bio_set_template_name_wait(dev, t, pin, &ms));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -378,7 +383,7 @@ bio_parse_template_id(const cbor_item_t *key, const cbor_item_t *val,
|
||||
|
||||
static int
|
||||
bio_rx_enroll_begin(fido_dev_t *dev, fido_bio_template_t *t,
|
||||
fido_bio_enroll_t *e, int ms)
|
||||
fido_bio_enroll_t *e, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -411,7 +416,7 @@ bio_rx_enroll_begin(fido_dev_t *dev, fido_bio_template_t *t,
|
||||
|
||||
static int
|
||||
bio_enroll_begin_wait(fido_dev_t *dev, fido_bio_template_t *t,
|
||||
fido_bio_enroll_t *e, uint32_t timo_ms, int ms)
|
||||
fido_bio_enroll_t *e, uint32_t timo_ms, int *ms)
|
||||
{
|
||||
cbor_item_t *argv[3];
|
||||
const uint8_t cmd = CMD_ENROLL_BEGIN;
|
||||
@ -424,7 +429,7 @@ bio_enroll_begin_wait(fido_dev_t *dev, fido_bio_template_t *t,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((r = bio_tx(dev, cmd, argv, 3, NULL, e->token)) != FIDO_OK ||
|
||||
if ((r = bio_tx(dev, cmd, argv, 3, NULL, e->token, ms)) != FIDO_OK ||
|
||||
(r = bio_rx_enroll_begin(dev, t, e, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: tx/rx", __func__);
|
||||
goto fail;
|
||||
@ -444,6 +449,7 @@ fido_bio_dev_enroll_begin(fido_dev_t *dev, fido_bio_template_t *t,
|
||||
es256_pk_t *pk = NULL;
|
||||
fido_blob_t *ecdh = NULL;
|
||||
fido_blob_t *token = NULL;
|
||||
int ms = dev->timeout_ms;
|
||||
int r;
|
||||
|
||||
if (pin == NULL || e->token != NULL)
|
||||
@ -454,13 +460,13 @@ fido_bio_dev_enroll_begin(fido_dev_t *dev, fido_bio_template_t *t,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh, &ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_do_ecdh", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((r = fido_dev_get_uv_token(dev, CTAP_CBOR_BIO_ENROLL_PRE, pin, ecdh,
|
||||
pk, NULL, token)) != FIDO_OK) {
|
||||
pk, NULL, token, &ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_dev_get_uv_token", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -475,11 +481,11 @@ fido_bio_dev_enroll_begin(fido_dev_t *dev, fido_bio_template_t *t,
|
||||
if (r != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
return (bio_enroll_begin_wait(dev, t, e, timo_ms, -1));
|
||||
return (bio_enroll_begin_wait(dev, t, e, timo_ms, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
bio_rx_enroll_continue(fido_dev_t *dev, fido_bio_enroll_t *e, int ms)
|
||||
bio_rx_enroll_continue(fido_dev_t *dev, fido_bio_enroll_t *e, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -505,7 +511,7 @@ bio_rx_enroll_continue(fido_dev_t *dev, fido_bio_enroll_t *e, int ms)
|
||||
|
||||
static int
|
||||
bio_enroll_continue_wait(fido_dev_t *dev, const fido_bio_template_t *t,
|
||||
fido_bio_enroll_t *e, uint32_t timo_ms, int ms)
|
||||
fido_bio_enroll_t *e, uint32_t timo_ms, int *ms)
|
||||
{
|
||||
cbor_item_t *argv[3];
|
||||
const uint8_t cmd = CMD_ENROLL_NEXT;
|
||||
@ -519,7 +525,7 @@ bio_enroll_continue_wait(fido_dev_t *dev, const fido_bio_template_t *t,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((r = bio_tx(dev, cmd, argv, 3, NULL, e->token)) != FIDO_OK ||
|
||||
if ((r = bio_tx(dev, cmd, argv, 3, NULL, e->token, ms)) != FIDO_OK ||
|
||||
(r = bio_rx_enroll_continue(dev, e, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: tx/rx", __func__);
|
||||
goto fail;
|
||||
@ -536,19 +542,21 @@ int
|
||||
fido_bio_dev_enroll_continue(fido_dev_t *dev, const fido_bio_template_t *t,
|
||||
fido_bio_enroll_t *e, uint32_t timo_ms)
|
||||
{
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
if (e->token == NULL)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
return (bio_enroll_continue_wait(dev, t, e, timo_ms, -1));
|
||||
return (bio_enroll_continue_wait(dev, t, e, timo_ms, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
bio_enroll_cancel_wait(fido_dev_t *dev, int ms)
|
||||
bio_enroll_cancel_wait(fido_dev_t *dev, int *ms)
|
||||
{
|
||||
const uint8_t cmd = CMD_ENROLL_CANCEL;
|
||||
int r;
|
||||
|
||||
if ((r = bio_tx(dev, cmd, NULL, 0, NULL, NULL)) != FIDO_OK ||
|
||||
if ((r = bio_tx(dev, cmd, NULL, 0, NULL, NULL, ms)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: tx/rx", __func__);
|
||||
return (r);
|
||||
@ -560,12 +568,14 @@ bio_enroll_cancel_wait(fido_dev_t *dev, int ms)
|
||||
int
|
||||
fido_bio_dev_enroll_cancel(fido_dev_t *dev)
|
||||
{
|
||||
return (bio_enroll_cancel_wait(dev, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (bio_enroll_cancel_wait(dev, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
bio_enroll_remove_wait(fido_dev_t *dev, const fido_bio_template_t *t,
|
||||
const char *pin, int ms)
|
||||
const char *pin, int *ms)
|
||||
{
|
||||
cbor_item_t *argv[1];
|
||||
const uint8_t cmd = CMD_ENROLL_REMOVE;
|
||||
@ -578,7 +588,7 @@ bio_enroll_remove_wait(fido_dev_t *dev, const fido_bio_template_t *t,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((r = bio_tx(dev, cmd, argv, 1, pin, NULL)) != FIDO_OK ||
|
||||
if ((r = bio_tx(dev, cmd, argv, 1, pin, NULL, ms)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: tx/rx", __func__);
|
||||
goto fail;
|
||||
@ -595,7 +605,9 @@ int
|
||||
fido_bio_dev_enroll_remove(fido_dev_t *dev, const fido_bio_template_t *t,
|
||||
const char *pin)
|
||||
{
|
||||
return (bio_enroll_remove_wait(dev, t, pin, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (bio_enroll_remove_wait(dev, t, pin, &ms));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -640,7 +652,7 @@ bio_parse_info(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
}
|
||||
|
||||
static int
|
||||
bio_rx_info(fido_dev_t *dev, fido_bio_info_t *i, int ms)
|
||||
bio_rx_info(fido_dev_t *dev, fido_bio_info_t *i, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -664,11 +676,12 @@ bio_rx_info(fido_dev_t *dev, fido_bio_info_t *i, int ms)
|
||||
}
|
||||
|
||||
static int
|
||||
bio_get_info_wait(fido_dev_t *dev, fido_bio_info_t *i, int ms)
|
||||
bio_get_info_wait(fido_dev_t *dev, fido_bio_info_t *i, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = bio_tx(dev, CMD_GET_INFO, NULL, 0, NULL, NULL)) != FIDO_OK ||
|
||||
if ((r = bio_tx(dev, CMD_GET_INFO, NULL, 0, NULL, NULL,
|
||||
ms)) != FIDO_OK ||
|
||||
(r = bio_rx_info(dev, i, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: tx/rx", __func__);
|
||||
return (r);
|
||||
@ -680,7 +693,9 @@ bio_get_info_wait(fido_dev_t *dev, fido_bio_info_t *i, int ms)
|
||||
int
|
||||
fido_bio_dev_get_info(fido_dev_t *dev, fido_bio_info_t *i)
|
||||
{
|
||||
return (bio_get_info_wait(dev, i, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (bio_get_info_wait(dev, i, &ms));
|
||||
}
|
||||
|
||||
const char *
|
||||
|
107
src/cbor.c
107
src/cbor.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -560,6 +560,32 @@ cbor_encode_pubkey_list(const fido_blob_array_t *list)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
cbor_item_t *
|
||||
cbor_encode_str_array(const fido_str_array_t *a)
|
||||
{
|
||||
cbor_item_t *array = NULL;
|
||||
cbor_item_t *entry = NULL;
|
||||
|
||||
if ((array = cbor_new_definite_array(a->len)) == NULL)
|
||||
goto fail;
|
||||
|
||||
for (size_t i = 0; i < a->len; i++) {
|
||||
if ((entry = cbor_build_string(a->ptr[i])) == NULL ||
|
||||
cbor_array_push(array, entry) == false)
|
||||
goto fail;
|
||||
cbor_decref(&entry);
|
||||
}
|
||||
|
||||
return (array);
|
||||
fail:
|
||||
if (entry != NULL)
|
||||
cbor_decref(&entry);
|
||||
if (array != NULL)
|
||||
cbor_decref(&array);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
cbor_encode_largeblob_key_ext(cbor_item_t *map)
|
||||
{
|
||||
@ -584,6 +610,8 @@ cbor_encode_cred_ext(const fido_cred_ext_t *ext, const fido_blob_t *blob)
|
||||
size++;
|
||||
if (ext->mask & FIDO_EXT_LARGEBLOB_KEY)
|
||||
size++;
|
||||
if (ext->mask & FIDO_EXT_MINPINLEN)
|
||||
size++;
|
||||
|
||||
if (size == 0 || (item = cbor_new_definite_map(size)) == NULL)
|
||||
return (NULL);
|
||||
@ -615,6 +643,12 @@ cbor_encode_cred_ext(const fido_cred_ext_t *ext, const fido_blob_t *blob)
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
if (ext->mask & FIDO_EXT_MINPINLEN) {
|
||||
if (cbor_add_bool(item, "minPinLength", FIDO_OPT_TRUE) < 0) {
|
||||
cbor_decref(&item);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (item);
|
||||
}
|
||||
@ -706,11 +740,7 @@ cbor_encode_change_pin_auth(const fido_dev_t *dev, const fido_blob_t *secret,
|
||||
unsigned int dgst_len;
|
||||
cbor_item_t *item = NULL;
|
||||
const EVP_MD *md = NULL;
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
HMAC_CTX ctx;
|
||||
#else
|
||||
HMAC_CTX *ctx = NULL;
|
||||
#endif
|
||||
fido_blob_t key;
|
||||
uint8_t prot;
|
||||
size_t outlen;
|
||||
@ -726,19 +756,6 @@ cbor_encode_change_pin_auth(const fido_dev_t *dev, const fido_blob_t *secret,
|
||||
if (prot == CTAP_PIN_PROTOCOL2 && key.len > 32)
|
||||
key.len = 32;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
HMAC_CTX_init(&ctx);
|
||||
|
||||
if ((md = EVP_sha256()) == NULL ||
|
||||
HMAC_Init_ex(&ctx, key.ptr, (int)key.len, md, NULL) == 0 ||
|
||||
HMAC_Update(&ctx, new_pin_enc->ptr, new_pin_enc->len) == 0 ||
|
||||
HMAC_Update(&ctx, pin_hash_enc->ptr, pin_hash_enc->len) == 0 ||
|
||||
HMAC_Final(&ctx, dgst, &dgst_len) == 0 ||
|
||||
dgst_len != SHA256_DIGEST_LENGTH) {
|
||||
fido_log_debug("%s: HMAC", __func__);
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
if ((ctx = HMAC_CTX_new()) == NULL ||
|
||||
(md = EVP_sha256()) == NULL ||
|
||||
HMAC_Init_ex(ctx, key.ptr, (int)key.len, md, NULL) == 0 ||
|
||||
@ -749,7 +766,6 @@ cbor_encode_change_pin_auth(const fido_dev_t *dev, const fido_blob_t *secret,
|
||||
fido_log_debug("%s: HMAC", __func__);
|
||||
goto fail;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
|
||||
outlen = (prot == CTAP_PIN_PROTOCOL1) ? 16 : dgst_len;
|
||||
|
||||
@ -759,10 +775,7 @@ cbor_encode_change_pin_auth(const fido_dev_t *dev, const fido_blob_t *secret,
|
||||
}
|
||||
|
||||
fail:
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
if (ctx != NULL)
|
||||
HMAC_CTX_free(ctx);
|
||||
#endif
|
||||
HMAC_CTX_free(ctx);
|
||||
|
||||
return (item);
|
||||
}
|
||||
@ -775,6 +788,7 @@ cbor_encode_hmac_secret_param(const fido_dev_t *dev, cbor_item_t *item,
|
||||
cbor_item_t *argv[4];
|
||||
struct cbor_pair pair;
|
||||
fido_blob_t *enc = NULL;
|
||||
uint8_t prot;
|
||||
int r;
|
||||
|
||||
memset(argv, 0, sizeof(argv));
|
||||
@ -801,11 +815,17 @@ cbor_encode_hmac_secret_param(const fido_dev_t *dev, cbor_item_t *item,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((prot = fido_dev_get_pin_protocol(dev)) == 0) {
|
||||
fido_log_debug("%s: fido_dev_get_pin_protocol", __func__);
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* XXX not pin, but salt */
|
||||
if ((argv[0] = es256_pk_encode(pk, 1)) == NULL ||
|
||||
(argv[1] = fido_blob_encode(enc)) == NULL ||
|
||||
(argv[2] = cbor_encode_pin_auth(dev, ecdh, enc)) == NULL ||
|
||||
(argv[3] = cbor_encode_pin_opt(dev)) == NULL) {
|
||||
(prot != 1 && (argv[3] = cbor_build_uint8(prot)) == NULL)) {
|
||||
fido_log_debug("%s: cbor encode", __func__);
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
@ -896,7 +916,7 @@ cbor_decode_fmt(const cbor_item_t *item, char **fmt)
|
||||
}
|
||||
|
||||
if (strcmp(type, "packed") && strcmp(type, "fido-u2f") &&
|
||||
strcmp(type, "none")) {
|
||||
strcmp(type, "none") && strcmp(type, "tpm")) {
|
||||
fido_log_debug("%s: type=%s", __func__, type);
|
||||
free(type);
|
||||
return (-1);
|
||||
@ -1141,6 +1161,14 @@ decode_cred_extension(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
}
|
||||
if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE)
|
||||
authdata_ext->mask |= FIDO_EXT_CRED_BLOB;
|
||||
} else if (strcmp(type, "minPinLength") == 0) {
|
||||
if (cbor_isa_uint(val) == false ||
|
||||
cbor_int_get_width(val) != CBOR_INT_8) {
|
||||
fido_log_debug("%s: cbor type", __func__);
|
||||
goto out;
|
||||
}
|
||||
authdata_ext->mask |= FIDO_EXT_MINPINLEN;
|
||||
authdata_ext->minpinlen = cbor_get_uint8(val);
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
@ -1365,7 +1393,6 @@ decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
{
|
||||
fido_attstmt_t *attstmt = arg;
|
||||
char *name = NULL;
|
||||
int cose_alg = 0;
|
||||
int ok = -1;
|
||||
|
||||
if (cbor_string_copy(key, &name) < 0) {
|
||||
@ -1380,10 +1407,11 @@ decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
fido_log_debug("%s: alg", __func__);
|
||||
goto out;
|
||||
}
|
||||
if ((cose_alg = -(int)cbor_get_int(val) - 1) != COSE_ES256 &&
|
||||
cose_alg != COSE_RS256 && cose_alg != COSE_EDDSA) {
|
||||
fido_log_debug("%s: unsupported cose_alg=%d", __func__,
|
||||
cose_alg);
|
||||
attstmt->alg = -(int)cbor_get_int(val) - 1;
|
||||
if (attstmt->alg != COSE_ES256 && attstmt->alg != COSE_RS256 &&
|
||||
attstmt->alg != COSE_EDDSA && attstmt->alg != COSE_RS1) {
|
||||
fido_log_debug("%s: unsupported attstmt->alg=%d",
|
||||
__func__, attstmt->alg);
|
||||
goto out;
|
||||
}
|
||||
} else if (!strcmp(name, "sig")) {
|
||||
@ -1398,6 +1426,16 @@ decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
fido_log_debug("%s: x5c", __func__);
|
||||
goto out;
|
||||
}
|
||||
} else if (!strcmp(name, "certInfo")) {
|
||||
if (fido_blob_decode(val, &attstmt->certinfo) < 0) {
|
||||
fido_log_debug("%s: certinfo", __func__);
|
||||
goto out;
|
||||
}
|
||||
} else if (!strcmp(name, "pubArea")) {
|
||||
if (fido_blob_decode(val, &attstmt->pubarea) < 0) {
|
||||
fido_log_debug("%s: pubarea", __func__);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
@ -1410,6 +1448,8 @@ decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
int
|
||||
cbor_decode_attstmt(const cbor_item_t *item, fido_attstmt_t *attstmt)
|
||||
{
|
||||
size_t alloc_len;
|
||||
|
||||
if (cbor_isa_map(item) == false ||
|
||||
cbor_map_is_definite(item) == false ||
|
||||
cbor_map_iter(item, attstmt, decode_attstmt_entry) < 0) {
|
||||
@ -1417,6 +1457,13 @@ cbor_decode_attstmt(const cbor_item_t *item, fido_attstmt_t *attstmt)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (attstmt->cbor.ptr != NULL ||
|
||||
(attstmt->cbor.len = cbor_serialize_alloc(item,
|
||||
&attstmt->cbor.ptr, &alloc_len)) == 0) {
|
||||
fido_log_debug("%s: cbor_serialize_alloc", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
74
src/config.c
74
src/config.c
@ -39,7 +39,7 @@ config_prepare_hmac(uint8_t subcmd, const cbor_item_t *item, fido_blob_t *hmac)
|
||||
|
||||
static int
|
||||
config_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **paramv, size_t paramc,
|
||||
const char *pin)
|
||||
const char *pin, int *ms)
|
||||
{
|
||||
cbor_item_t *argv[4];
|
||||
es256_pk_t *pk = NULL;
|
||||
@ -68,12 +68,12 @@ config_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **paramv, size_t paramc,
|
||||
fido_log_debug("%s: config_prepare_hmac", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_do_ecdh", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((r = cbor_add_uv_params(dev, cmd, &hmac, pk, ecdh, pin,
|
||||
NULL, &argv[3], &argv[2])) != FIDO_OK) {
|
||||
NULL, &argv[3], &argv[2], ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: cbor_add_uv_params", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -81,7 +81,7 @@ config_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **paramv, size_t paramc,
|
||||
|
||||
/* framing and transmission */
|
||||
if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -99,11 +99,12 @@ config_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **paramv, size_t paramc,
|
||||
}
|
||||
|
||||
static int
|
||||
config_enable_entattest_wait(fido_dev_t *dev, const char *pin, int ms)
|
||||
config_enable_entattest_wait(fido_dev_t *dev, const char *pin, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = config_tx(dev, CMD_ENABLE_ENTATTEST, NULL, 0, pin)) != FIDO_OK)
|
||||
if ((r = config_tx(dev, CMD_ENABLE_ENTATTEST, NULL, 0, pin,
|
||||
ms)) != FIDO_OK)
|
||||
return r;
|
||||
|
||||
return fido_rx_cbor_status(dev, ms);
|
||||
@ -112,15 +113,18 @@ config_enable_entattest_wait(fido_dev_t *dev, const char *pin, int ms)
|
||||
int
|
||||
fido_dev_enable_entattest(fido_dev_t *dev, const char *pin)
|
||||
{
|
||||
return (config_enable_entattest_wait(dev, pin, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (config_enable_entattest_wait(dev, pin, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
config_toggle_always_uv_wait(fido_dev_t *dev, const char *pin, int ms)
|
||||
config_toggle_always_uv_wait(fido_dev_t *dev, const char *pin, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = config_tx(dev, CMD_TOGGLE_ALWAYS_UV, NULL, 0, pin)) != FIDO_OK)
|
||||
if ((r = config_tx(dev, CMD_TOGGLE_ALWAYS_UV, NULL, 0, pin,
|
||||
ms)) != FIDO_OK)
|
||||
return r;
|
||||
|
||||
return (fido_rx_cbor_status(dev, ms));
|
||||
@ -129,18 +133,21 @@ config_toggle_always_uv_wait(fido_dev_t *dev, const char *pin, int ms)
|
||||
int
|
||||
fido_dev_toggle_always_uv(fido_dev_t *dev, const char *pin)
|
||||
{
|
||||
return config_toggle_always_uv_wait(dev, pin, -1);
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return config_toggle_always_uv_wait(dev, pin, &ms);
|
||||
}
|
||||
|
||||
static int
|
||||
config_pin_minlen_tx(fido_dev_t *dev, size_t len, bool force, const char *pin)
|
||||
config_pin_minlen_tx(fido_dev_t *dev, size_t len, bool force,
|
||||
const fido_str_array_t *rpid, const char *pin, int *ms)
|
||||
{
|
||||
cbor_item_t *argv[3];
|
||||
int r;
|
||||
|
||||
memset(argv, 0, sizeof(argv));
|
||||
|
||||
if ((!len && !force) || len > UINT8_MAX) {
|
||||
if ((rpid == NULL && len == 0 && !force) || len > UINT8_MAX) {
|
||||
r = FIDO_ERR_INVALID_ARGUMENT;
|
||||
goto fail;
|
||||
}
|
||||
@ -149,13 +156,18 @@ config_pin_minlen_tx(fido_dev_t *dev, size_t len, bool force, const char *pin)
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
}
|
||||
if (rpid != NULL && (argv[1] = cbor_encode_str_array(rpid)) == NULL) {
|
||||
fido_log_debug("%s: cbor_encode_str_array", __func__);
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
}
|
||||
if (force && (argv[2] = cbor_build_bool(true)) == NULL) {
|
||||
fido_log_debug("%s: cbor_build_bool", __func__);
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
}
|
||||
if ((r = config_tx(dev, CMD_SET_PIN_MINLEN, argv, nitems(argv),
|
||||
pin)) != FIDO_OK) {
|
||||
pin, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: config_tx", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -167,12 +179,13 @@ config_pin_minlen_tx(fido_dev_t *dev, size_t len, bool force, const char *pin)
|
||||
}
|
||||
|
||||
static int
|
||||
config_pin_minlen(fido_dev_t *dev, size_t len, bool force, const char *pin,
|
||||
int ms)
|
||||
config_pin_minlen(fido_dev_t *dev, size_t len, bool force,
|
||||
const fido_str_array_t *rpid, const char *pin, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = config_pin_minlen_tx(dev, len, force, pin)) != FIDO_OK)
|
||||
if ((r = config_pin_minlen_tx(dev, len, force, rpid, pin,
|
||||
ms)) != FIDO_OK)
|
||||
return r;
|
||||
|
||||
return fido_rx_cbor_status(dev, ms);
|
||||
@ -181,11 +194,36 @@ config_pin_minlen(fido_dev_t *dev, size_t len, bool force, const char *pin,
|
||||
int
|
||||
fido_dev_set_pin_minlen(fido_dev_t *dev, size_t len, const char *pin)
|
||||
{
|
||||
return config_pin_minlen(dev, len, false, pin, -1);
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return config_pin_minlen(dev, len, false, NULL, pin, &ms);
|
||||
}
|
||||
|
||||
int
|
||||
fido_dev_force_pin_change(fido_dev_t *dev, const char *pin)
|
||||
{
|
||||
return config_pin_minlen(dev, 0, true, pin, -1);
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return config_pin_minlen(dev, 0, true, NULL, pin, &ms);
|
||||
}
|
||||
|
||||
int
|
||||
fido_dev_set_pin_minlen_rpid(fido_dev_t *dev, const char * const *rpid,
|
||||
size_t n, const char *pin)
|
||||
{
|
||||
fido_str_array_t sa;
|
||||
int ms = dev->timeout_ms;
|
||||
int r;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
if (fido_str_array_pack(&sa, rpid, n) < 0) {
|
||||
fido_log_debug("%s: fido_str_array_pack", __func__);
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
}
|
||||
r = config_pin_minlen(dev, 0, false, &sa, pin, &ms);
|
||||
fail:
|
||||
fido_str_array_free(&sa);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
281
src/cred.c
281
src/cred.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -10,6 +10,10 @@
|
||||
#include "fido.h"
|
||||
#include "fido/es256.h"
|
||||
|
||||
#ifndef FIDO_MAXMSG_CRED
|
||||
#define FIDO_MAXMSG_CRED 4096
|
||||
#endif
|
||||
|
||||
static int
|
||||
parse_makecred_reply(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
{
|
||||
@ -43,7 +47,8 @@ parse_makecred_reply(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
|
||||
fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
|
||||
int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
fido_blob_t *ecdh = NULL;
|
||||
@ -92,12 +97,12 @@ fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
|
||||
/* user verification */
|
||||
if (pin != NULL || (uv == FIDO_OPT_TRUE &&
|
||||
fido_dev_supports_permissions(dev))) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_do_ecdh", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((r = cbor_add_uv_params(dev, cmd, &cred->cdh, pk, ecdh,
|
||||
pin, cred->rp.id, &argv[7], &argv[8])) != FIDO_OK) {
|
||||
pin, cred->rp.id, &argv[7], &argv[8], ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: cbor_add_uv_params", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -114,7 +119,7 @@ fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
|
||||
|
||||
/* framing and transmission */
|
||||
if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -131,42 +136,55 @@ fido_dev_make_cred_tx(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_make_cred_rx(fido_dev_t *dev, fido_cred_t *cred, int ms)
|
||||
fido_dev_make_cred_rx(fido_dev_t *dev, fido_cred_t *cred, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
int r;
|
||||
unsigned char *reply;
|
||||
int reply_len;
|
||||
int r;
|
||||
|
||||
fido_cred_reset_rx(cred);
|
||||
|
||||
if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
|
||||
if ((reply = malloc(FIDO_MAXMSG_CRED)) == NULL) {
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, reply, FIDO_MAXMSG_CRED,
|
||||
ms)) < 0) {
|
||||
fido_log_debug("%s: fido_rx", __func__);
|
||||
return (FIDO_ERR_RX);
|
||||
r = FIDO_ERR_RX;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((r = cbor_parse_reply(reply, (size_t)reply_len, cred,
|
||||
parse_makecred_reply)) != FIDO_OK) {
|
||||
fido_log_debug("%s: parse_makecred_reply", __func__);
|
||||
return (r);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (cred->fmt == NULL || fido_blob_is_empty(&cred->authdata_cbor) ||
|
||||
fido_blob_is_empty(&cred->attcred.id)) {
|
||||
fido_cred_reset_rx(cred);
|
||||
return (FIDO_ERR_INVALID_CBOR);
|
||||
r = FIDO_ERR_INVALID_CBOR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return (FIDO_OK);
|
||||
r = FIDO_OK;
|
||||
fail:
|
||||
free(reply);
|
||||
|
||||
if (r != FIDO_OK)
|
||||
fido_cred_reset_rx(cred);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_make_cred_wait(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
|
||||
int ms)
|
||||
int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = fido_dev_make_cred_tx(dev, cred, pin)) != FIDO_OK ||
|
||||
if ((r = fido_dev_make_cred_tx(dev, cred, pin, ms)) != FIDO_OK ||
|
||||
(r = fido_dev_make_cred_rx(dev, cred, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -176,18 +194,20 @@ fido_dev_make_cred_wait(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
|
||||
int
|
||||
fido_dev_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
|
||||
{
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
#ifdef USE_WINHELLO
|
||||
if (dev->flags & FIDO_DEV_WINHELLO)
|
||||
return (fido_winhello_make_cred(dev, cred, pin));
|
||||
return (fido_winhello_make_cred(dev, cred, pin, ms));
|
||||
#endif
|
||||
if (fido_dev_is_fido2(dev) == false) {
|
||||
if (pin != NULL || cred->rk == FIDO_OPT_TRUE ||
|
||||
cred->ext.mask != 0)
|
||||
return (FIDO_ERR_UNSUPPORTED_OPTION);
|
||||
return (u2f_register(dev, cred, -1));
|
||||
return (u2f_register(dev, cred, &ms));
|
||||
}
|
||||
|
||||
return (fido_dev_make_cred_wait(dev, cred, pin, -1));
|
||||
return (fido_dev_make_cred_wait(dev, cred, pin, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -225,66 +245,81 @@ get_signed_hash_u2f(fido_blob_t *dgst, const unsigned char *rp_id,
|
||||
size_t rp_id_len, const fido_blob_t *clientdata, const fido_blob_t *id,
|
||||
const es256_pk_t *pk)
|
||||
{
|
||||
const uint8_t zero = 0;
|
||||
const uint8_t four = 4; /* uncompressed point */
|
||||
SHA256_CTX ctx;
|
||||
|
||||
if (dgst->len != SHA256_DIGEST_LENGTH || SHA256_Init(&ctx) == 0 ||
|
||||
SHA256_Update(&ctx, &zero, sizeof(zero)) == 0 ||
|
||||
SHA256_Update(&ctx, rp_id, rp_id_len) == 0 ||
|
||||
SHA256_Update(&ctx, clientdata->ptr, clientdata->len) == 0 ||
|
||||
SHA256_Update(&ctx, id->ptr, id->len) == 0 ||
|
||||
SHA256_Update(&ctx, &four, sizeof(four)) == 0 ||
|
||||
SHA256_Update(&ctx, pk->x, sizeof(pk->x)) == 0 ||
|
||||
SHA256_Update(&ctx, pk->y, sizeof(pk->y)) == 0 ||
|
||||
SHA256_Final(dgst->ptr, &ctx) == 0) {
|
||||
fido_log_debug("%s: sha256", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
verify_sig(const fido_blob_t *dgst, const fido_blob_t *x5c,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
BIO *rawcert = NULL;
|
||||
X509 *cert = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EC_KEY *ec;
|
||||
const uint8_t zero = 0;
|
||||
const uint8_t four = 4; /* uncompressed point */
|
||||
const EVP_MD *md = NULL;
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
int ok = -1;
|
||||
|
||||
/* openssl needs ints */
|
||||
if (dgst->len > INT_MAX || x5c->len > INT_MAX || sig->len > INT_MAX) {
|
||||
fido_log_debug("%s: dgst->len=%zu, x5c->len=%zu, sig->len=%zu",
|
||||
__func__, dgst->len, x5c->len, sig->len);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* fetch key from x509 */
|
||||
if ((rawcert = BIO_new_mem_buf(x5c->ptr, (int)x5c->len)) == NULL ||
|
||||
(cert = d2i_X509_bio(rawcert, NULL)) == NULL ||
|
||||
(pkey = X509_get_pubkey(cert)) == NULL ||
|
||||
(ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) {
|
||||
fido_log_debug("%s: x509 key", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ECDSA_verify(0, dgst->ptr, (int)dgst->len, sig->ptr,
|
||||
(int)sig->len, ec) != 1) {
|
||||
fido_log_debug("%s: ECDSA_verify", __func__);
|
||||
if (dgst->len != SHA256_DIGEST_LENGTH ||
|
||||
(md = EVP_sha256()) == NULL ||
|
||||
(ctx = EVP_MD_CTX_new()) == NULL ||
|
||||
EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
|
||||
EVP_DigestUpdate(ctx, &zero, sizeof(zero)) != 1 ||
|
||||
EVP_DigestUpdate(ctx, rp_id, rp_id_len) != 1 ||
|
||||
EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
|
||||
EVP_DigestUpdate(ctx, id->ptr, id->len) != 1 ||
|
||||
EVP_DigestUpdate(ctx, &four, sizeof(four)) != 1 ||
|
||||
EVP_DigestUpdate(ctx, pk->x, sizeof(pk->x)) != 1 ||
|
||||
EVP_DigestUpdate(ctx, pk->y, sizeof(pk->y)) != 1 ||
|
||||
EVP_DigestFinal_ex(ctx, dgst->ptr, NULL) != 1) {
|
||||
fido_log_debug("%s: sha256", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
if (rawcert != NULL)
|
||||
BIO_free(rawcert);
|
||||
if (cert != NULL)
|
||||
X509_free(cert);
|
||||
if (pkey != NULL)
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
static int
|
||||
verify_attstmt(const fido_blob_t *dgst, const fido_attstmt_t *attstmt)
|
||||
{
|
||||
BIO *rawcert = NULL;
|
||||
X509 *cert = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
int ok = -1;
|
||||
|
||||
/* openssl needs ints */
|
||||
if (attstmt->x5c.len > INT_MAX) {
|
||||
fido_log_debug("%s: x5c.len=%zu", __func__, attstmt->x5c.len);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* fetch key from x509 */
|
||||
if ((rawcert = BIO_new_mem_buf(attstmt->x5c.ptr,
|
||||
(int)attstmt->x5c.len)) == NULL ||
|
||||
(cert = d2i_X509_bio(rawcert, NULL)) == NULL ||
|
||||
(pkey = X509_get_pubkey(cert)) == NULL) {
|
||||
fido_log_debug("%s: x509 key", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (attstmt->alg) {
|
||||
case COSE_UNSPEC:
|
||||
case COSE_ES256:
|
||||
ok = es256_verify_sig(dgst, pkey, &attstmt->sig);
|
||||
break;
|
||||
case COSE_RS256:
|
||||
ok = rs256_verify_sig(dgst, pkey, &attstmt->sig);
|
||||
break;
|
||||
case COSE_RS1:
|
||||
ok = rs1_verify_sig(dgst, pkey, &attstmt->sig);
|
||||
break;
|
||||
case COSE_EDDSA:
|
||||
ok = eddsa_verify_sig(dgst, pkey, &attstmt->sig);
|
||||
break;
|
||||
default:
|
||||
fido_log_debug("%s: unknown alg %d", __func__, attstmt->alg);
|
||||
break;
|
||||
}
|
||||
|
||||
fail:
|
||||
BIO_free(rawcert);
|
||||
X509_free(cert);
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
@ -348,14 +383,21 @@ fido_cred_verify(const fido_cred_t *cred)
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto out;
|
||||
}
|
||||
} else if (!strcmp(cred->fmt, "tpm")) {
|
||||
if (fido_get_signed_hash_tpm(&dgst, &cred->cdh,
|
||||
&cred->authdata_raw, &cred->attstmt, &cred->attcred) < 0) {
|
||||
fido_log_debug("%s: fido_get_signed_hash_tpm", __func__);
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
fido_log_debug("%s: unknown fmt %s", __func__, cred->fmt);
|
||||
r = FIDO_ERR_INVALID_ARGUMENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (verify_sig(&dgst, &cred->attstmt.x5c, &cred->attstmt.sig) < 0) {
|
||||
fido_log_debug("%s: verify_sig", __func__);
|
||||
if (verify_attstmt(&dgst, &cred->attstmt) < 0) {
|
||||
fido_log_debug("%s: verify_attstmt", __func__);
|
||||
r = FIDO_ERR_INVALID_SIG;
|
||||
goto out;
|
||||
}
|
||||
@ -435,15 +477,15 @@ fido_cred_verify_self(const fido_cred_t *cred)
|
||||
|
||||
switch (cred->attcred.type) {
|
||||
case COSE_ES256:
|
||||
ok = fido_verify_sig_es256(&dgst, &cred->attcred.pubkey.es256,
|
||||
ok = es256_pk_verify_sig(&dgst, &cred->attcred.pubkey.es256,
|
||||
&cred->attstmt.sig);
|
||||
break;
|
||||
case COSE_RS256:
|
||||
ok = fido_verify_sig_rs256(&dgst, &cred->attcred.pubkey.rs256,
|
||||
ok = rs256_pk_verify_sig(&dgst, &cred->attcred.pubkey.rs256,
|
||||
&cred->attstmt.sig);
|
||||
break;
|
||||
case COSE_EDDSA:
|
||||
ok = fido_verify_sig_eddsa(&dgst, &cred->attcred.pubkey.eddsa,
|
||||
ok = eddsa_pk_verify_sig(&dgst, &cred->attcred.pubkey.eddsa,
|
||||
&cred->attstmt.sig);
|
||||
break;
|
||||
default:
|
||||
@ -482,6 +524,18 @@ fido_cred_clean_authdata(fido_cred_t *cred)
|
||||
memset(&cred->attcred, 0, sizeof(cred->attcred));
|
||||
}
|
||||
|
||||
static void
|
||||
fido_cred_clean_attstmt(fido_attstmt_t *attstmt)
|
||||
{
|
||||
fido_blob_reset(&attstmt->certinfo);
|
||||
fido_blob_reset(&attstmt->pubarea);
|
||||
fido_blob_reset(&attstmt->cbor);
|
||||
fido_blob_reset(&attstmt->x5c);
|
||||
fido_blob_reset(&attstmt->sig);
|
||||
|
||||
memset(attstmt, 0, sizeof(*attstmt));
|
||||
}
|
||||
|
||||
void
|
||||
fido_cred_reset_tx(fido_cred_t *cred)
|
||||
{
|
||||
@ -513,8 +567,7 @@ fido_cred_reset_rx(fido_cred_t *cred)
|
||||
free(cred->fmt);
|
||||
cred->fmt = NULL;
|
||||
fido_cred_clean_authdata(cred);
|
||||
fido_blob_reset(&cred->attstmt.x5c);
|
||||
fido_blob_reset(&cred->attstmt.sig);
|
||||
fido_cred_clean_attstmt(&cred->attstmt);
|
||||
fido_blob_reset(&cred->largeblob_key);
|
||||
}
|
||||
|
||||
@ -568,7 +621,6 @@ fido_cred_set_authdata(fido_cred_t *cred, const unsigned char *ptr, size_t len)
|
||||
fido_cred_clean_authdata(cred);
|
||||
|
||||
return (r);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
@ -610,7 +662,6 @@ fido_cred_set_authdata_raw(fido_cred_t *cred, const unsigned char *ptr,
|
||||
fido_cred_clean_authdata(cred);
|
||||
|
||||
return (r);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
@ -640,6 +691,39 @@ fido_cred_set_sig(fido_cred_t *cred, const unsigned char *ptr, size_t len)
|
||||
return (FIDO_OK);
|
||||
}
|
||||
|
||||
int
|
||||
fido_cred_set_attstmt(fido_cred_t *cred, const unsigned char *ptr, size_t len)
|
||||
{
|
||||
cbor_item_t *item = NULL;
|
||||
struct cbor_load_result cbor;
|
||||
int r = FIDO_ERR_INVALID_ARGUMENT;
|
||||
|
||||
fido_cred_clean_attstmt(&cred->attstmt);
|
||||
|
||||
if (ptr == NULL || len == 0)
|
||||
goto fail;
|
||||
|
||||
if ((item = cbor_load(ptr, len, &cbor)) == NULL) {
|
||||
fido_log_debug("%s: cbor_load", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (cbor_decode_attstmt(item, &cred->attstmt) < 0) {
|
||||
fido_log_debug("%s: cbor_decode_attstmt", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = FIDO_OK;
|
||||
fail:
|
||||
if (item != NULL)
|
||||
cbor_decref(&item);
|
||||
|
||||
if (r != FIDO_OK)
|
||||
fido_cred_clean_attstmt(&cred->attstmt);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
int
|
||||
fido_cred_exclude(fido_cred_t *cred, const unsigned char *id_ptr, size_t id_len)
|
||||
{
|
||||
@ -833,6 +917,19 @@ fido_cred_set_prot(fido_cred_t *cred, int prot)
|
||||
return (FIDO_OK);
|
||||
}
|
||||
|
||||
int
|
||||
fido_cred_set_pin_minlen(fido_cred_t *cred, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
cred->ext.mask &= ~FIDO_EXT_MINPINLEN;
|
||||
else
|
||||
cred->ext.mask |= FIDO_EXT_MINPINLEN;
|
||||
|
||||
cred->ext.minpinlen = len;
|
||||
|
||||
return (FIDO_OK);
|
||||
}
|
||||
|
||||
int
|
||||
fido_cred_set_blob(fido_cred_t *cred, const unsigned char *ptr, size_t len)
|
||||
{
|
||||
@ -856,7 +953,7 @@ fido_cred_set_fmt(fido_cred_t *cred, const char *fmt)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
if (strcmp(fmt, "packed") && strcmp(fmt, "fido-u2f") &&
|
||||
strcmp(fmt, "none"))
|
||||
strcmp(fmt, "none") && strcmp(fmt, "tpm"))
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
if ((cred->fmt = strdup(fmt)) == NULL)
|
||||
@ -955,6 +1052,18 @@ fido_cred_authdata_raw_len(const fido_cred_t *cred)
|
||||
return (cred->authdata_raw.len);
|
||||
}
|
||||
|
||||
const unsigned char *
|
||||
fido_cred_attstmt_ptr(const fido_cred_t *cred)
|
||||
{
|
||||
return (cred->attstmt.cbor.ptr);
|
||||
}
|
||||
|
||||
size_t
|
||||
fido_cred_attstmt_len(const fido_cred_t *cred)
|
||||
{
|
||||
return (cred->attstmt.cbor.len);
|
||||
}
|
||||
|
||||
const unsigned char *
|
||||
fido_cred_pubkey_ptr(const fido_cred_t *cred)
|
||||
{
|
||||
@ -1031,6 +1140,12 @@ fido_cred_prot(const fido_cred_t *cred)
|
||||
return (cred->ext.prot);
|
||||
}
|
||||
|
||||
size_t
|
||||
fido_cred_pin_minlen(const fido_cred_t *cred)
|
||||
{
|
||||
return (cred->ext.minpinlen);
|
||||
}
|
||||
|
||||
const char *
|
||||
fido_cred_fmt(const fido_cred_t *cred)
|
||||
{
|
||||
|
@ -112,7 +112,7 @@ credman_prepare_hmac(uint8_t cmd, const void *body, cbor_item_t **param,
|
||||
|
||||
static int
|
||||
credman_tx(fido_dev_t *dev, uint8_t subcmd, const void *param, const char *pin,
|
||||
const char *rp_id, fido_opt_t uv)
|
||||
const char *rp_id, fido_opt_t uv, int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
fido_blob_t *ecdh = NULL;
|
||||
@ -144,12 +144,12 @@ credman_tx(fido_dev_t *dev, uint8_t subcmd, const void *param, const char *pin,
|
||||
fido_log_debug("%s: credman_prepare_hmac", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_do_ecdh", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((r = cbor_add_uv_params(dev, cmd, &hmac, pk, ecdh, pin,
|
||||
rp_id, &argv[3], &argv[2])) != FIDO_OK) {
|
||||
rp_id, &argv[3], &argv[2], ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: cbor_add_uv_params", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -157,7 +157,7 @@ credman_tx(fido_dev_t *dev, uint8_t subcmd, const void *param, const char *pin,
|
||||
|
||||
/* framing and transmission */
|
||||
if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -198,7 +198,7 @@ credman_parse_metadata(const cbor_item_t *key, const cbor_item_t *val,
|
||||
}
|
||||
|
||||
static int
|
||||
credman_rx_metadata(fido_dev_t *dev, fido_credman_metadata_t *metadata, int ms)
|
||||
credman_rx_metadata(fido_dev_t *dev, fido_credman_metadata_t *metadata, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -223,12 +223,12 @@ credman_rx_metadata(fido_dev_t *dev, fido_credman_metadata_t *metadata, int ms)
|
||||
|
||||
static int
|
||||
credman_get_metadata_wait(fido_dev_t *dev, fido_credman_metadata_t *metadata,
|
||||
const char *pin, int ms)
|
||||
const char *pin, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = credman_tx(dev, CMD_CRED_METADATA, NULL, pin, NULL,
|
||||
FIDO_OPT_TRUE)) != FIDO_OK ||
|
||||
FIDO_OPT_TRUE, ms)) != FIDO_OK ||
|
||||
(r = credman_rx_metadata(dev, metadata, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -239,7 +239,9 @@ int
|
||||
fido_credman_get_dev_metadata(fido_dev_t *dev, fido_credman_metadata_t *metadata,
|
||||
const char *pin)
|
||||
{
|
||||
return (credman_get_metadata_wait(dev, metadata, pin, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (credman_get_metadata_wait(dev, metadata, pin, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -321,7 +323,7 @@ credman_parse_rk_count(const cbor_item_t *key, const cbor_item_t *val,
|
||||
}
|
||||
|
||||
static int
|
||||
credman_rx_rk(fido_dev_t *dev, fido_credman_rk_t *rk, int ms)
|
||||
credman_rx_rk(fido_dev_t *dev, fido_credman_rk_t *rk, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -360,7 +362,7 @@ credman_rx_rk(fido_dev_t *dev, fido_credman_rk_t *rk, int ms)
|
||||
}
|
||||
|
||||
static int
|
||||
credman_rx_next_rk(fido_dev_t *dev, fido_credman_rk_t *rk, int ms)
|
||||
credman_rx_next_rk(fido_dev_t *dev, fido_credman_rk_t *rk, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -390,7 +392,7 @@ credman_rx_next_rk(fido_dev_t *dev, fido_credman_rk_t *rk, int ms)
|
||||
|
||||
static int
|
||||
credman_get_rk_wait(fido_dev_t *dev, const char *rp_id, fido_credman_rk_t *rk,
|
||||
const char *pin, int ms)
|
||||
const char *pin, int *ms)
|
||||
{
|
||||
fido_blob_t rp_dgst;
|
||||
uint8_t dgst[SHA256_DIGEST_LENGTH];
|
||||
@ -405,13 +407,13 @@ credman_get_rk_wait(fido_dev_t *dev, const char *rp_id, fido_credman_rk_t *rk,
|
||||
rp_dgst.len = sizeof(dgst);
|
||||
|
||||
if ((r = credman_tx(dev, CMD_RK_BEGIN, &rp_dgst, pin, rp_id,
|
||||
FIDO_OPT_TRUE)) != FIDO_OK ||
|
||||
FIDO_OPT_TRUE, ms)) != FIDO_OK ||
|
||||
(r = credman_rx_rk(dev, rk, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
while (rk->n_rx < rk->n_alloc) {
|
||||
if ((r = credman_tx(dev, CMD_RK_NEXT, NULL, NULL, NULL,
|
||||
FIDO_OPT_FALSE)) != FIDO_OK ||
|
||||
FIDO_OPT_FALSE, ms)) != FIDO_OK ||
|
||||
(r = credman_rx_next_rk(dev, rk, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
rk->n_rx++;
|
||||
@ -424,12 +426,14 @@ int
|
||||
fido_credman_get_dev_rk(fido_dev_t *dev, const char *rp_id,
|
||||
fido_credman_rk_t *rk, const char *pin)
|
||||
{
|
||||
return (credman_get_rk_wait(dev, rp_id, rk, pin, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (credman_get_rk_wait(dev, rp_id, rk, pin, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
credman_del_rk_wait(fido_dev_t *dev, const unsigned char *cred_id,
|
||||
size_t cred_id_len, const char *pin, int ms)
|
||||
size_t cred_id_len, const char *pin, int *ms)
|
||||
{
|
||||
fido_blob_t cred;
|
||||
int r;
|
||||
@ -440,7 +444,7 @@ credman_del_rk_wait(fido_dev_t *dev, const unsigned char *cred_id,
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
if ((r = credman_tx(dev, CMD_DELETE_CRED, &cred, pin, NULL,
|
||||
FIDO_OPT_TRUE)) != FIDO_OK ||
|
||||
FIDO_OPT_TRUE, ms)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK)
|
||||
goto fail;
|
||||
|
||||
@ -455,7 +459,9 @@ int
|
||||
fido_credman_del_dev_rk(fido_dev_t *dev, const unsigned char *cred_id,
|
||||
size_t cred_id_len, const char *pin)
|
||||
{
|
||||
return (credman_del_rk_wait(dev, cred_id, cred_id_len, pin, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (credman_del_rk_wait(dev, cred_id, cred_id_len, pin, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -526,7 +532,7 @@ credman_parse_rp_count(const cbor_item_t *key, const cbor_item_t *val,
|
||||
}
|
||||
|
||||
static int
|
||||
credman_rx_rp(fido_dev_t *dev, fido_credman_rp_t *rp, int ms)
|
||||
credman_rx_rp(fido_dev_t *dev, fido_credman_rp_t *rp, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -565,7 +571,7 @@ credman_rx_rp(fido_dev_t *dev, fido_credman_rp_t *rp, int ms)
|
||||
}
|
||||
|
||||
static int
|
||||
credman_rx_next_rp(fido_dev_t *dev, fido_credman_rp_t *rp, int ms)
|
||||
credman_rx_next_rp(fido_dev_t *dev, fido_credman_rp_t *rp, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -595,18 +601,18 @@ credman_rx_next_rp(fido_dev_t *dev, fido_credman_rp_t *rp, int ms)
|
||||
|
||||
static int
|
||||
credman_get_rp_wait(fido_dev_t *dev, fido_credman_rp_t *rp, const char *pin,
|
||||
int ms)
|
||||
int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = credman_tx(dev, CMD_RP_BEGIN, NULL, pin, NULL,
|
||||
FIDO_OPT_TRUE)) != FIDO_OK ||
|
||||
FIDO_OPT_TRUE, ms)) != FIDO_OK ||
|
||||
(r = credman_rx_rp(dev, rp, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
while (rp->n_rx < rp->n_alloc) {
|
||||
if ((r = credman_tx(dev, CMD_RP_NEXT, NULL, NULL, NULL,
|
||||
FIDO_OPT_FALSE)) != FIDO_OK ||
|
||||
FIDO_OPT_FALSE, ms)) != FIDO_OK ||
|
||||
(r = credman_rx_next_rp(dev, rp, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
rp->n_rx++;
|
||||
@ -618,17 +624,19 @@ credman_get_rp_wait(fido_dev_t *dev, fido_credman_rp_t *rp, const char *pin,
|
||||
int
|
||||
fido_credman_get_dev_rp(fido_dev_t *dev, fido_credman_rp_t *rp, const char *pin)
|
||||
{
|
||||
return (credman_get_rp_wait(dev, rp, pin, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (credman_get_rp_wait(dev, rp, pin, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
credman_set_dev_rk_wait(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
|
||||
int ms)
|
||||
int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = credman_tx(dev, CMD_UPDATE_CRED, cred, pin, NULL,
|
||||
FIDO_OPT_TRUE)) != FIDO_OK ||
|
||||
FIDO_OPT_TRUE, ms)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -638,7 +646,9 @@ credman_set_dev_rk_wait(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
|
||||
int
|
||||
fido_credman_set_dev_rk(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
|
||||
{
|
||||
return (credman_set_dev_rk_wait(dev, cred, pin, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (credman_set_dev_rk_wait(dev, cred, pin, &ms));
|
||||
}
|
||||
|
||||
fido_credman_rk_t *
|
||||
|
63
src/dev.c
63
src/dev.c
@ -106,7 +106,7 @@ fido_dev_set_flags(fido_dev_t *dev, const fido_cbor_info_t *info)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_open_tx(fido_dev_t *dev, const char *path)
|
||||
fido_dev_open_tx(fido_dev_t *dev, const char *path, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -161,7 +161,8 @@ fido_dev_open_tx(fido_dev_t *dev, const char *path)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fido_tx(dev, CTAP_CMD_INIT, &dev->nonce, sizeof(dev->nonce)) < 0) {
|
||||
if (fido_tx(dev, CTAP_CMD_INIT, &dev->nonce, sizeof(dev->nonce),
|
||||
ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -176,7 +177,7 @@ fido_dev_open_tx(fido_dev_t *dev, const char *path)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_open_rx(fido_dev_t *dev, int ms)
|
||||
fido_dev_open_rx(fido_dev_t *dev, int *ms)
|
||||
{
|
||||
fido_cbor_info_t *info = NULL;
|
||||
int reply_len;
|
||||
@ -241,7 +242,7 @@ fido_dev_open_rx(fido_dev_t *dev, int ms)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_open_wait(fido_dev_t *dev, const char *path, int ms)
|
||||
fido_dev_open_wait(fido_dev_t *dev, const char *path, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -249,7 +250,7 @@ fido_dev_open_wait(fido_dev_t *dev, const char *path, int ms)
|
||||
if (strcmp(path, FIDO_WINHELLO_PATH) == 0)
|
||||
return (fido_winhello_open(dev));
|
||||
#endif
|
||||
if ((r = fido_dev_open_tx(dev, path)) != FIDO_OK ||
|
||||
if ((r = fido_dev_open_tx(dev, path, ms)) != FIDO_OK ||
|
||||
(r = fido_dev_open_rx(dev, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -331,24 +332,21 @@ fido_dev_info_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
|
||||
int
|
||||
fido_dev_open_with_info(fido_dev_t *dev)
|
||||
{
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
if (dev->path == NULL)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
return (fido_dev_open_wait(dev, dev->path, -1));
|
||||
return (fido_dev_open_wait(dev, dev->path, &ms));
|
||||
}
|
||||
|
||||
int
|
||||
fido_dev_open(fido_dev_t *dev, const char *path)
|
||||
{
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
#ifdef NFC_LINUX
|
||||
/*
|
||||
* this is a hack to get existing applications up and running with nfc;
|
||||
* it will *NOT* be part of a libfido2 release. to support nfc in your
|
||||
* application, please change it to use fido_dev_open_with_info().
|
||||
*/
|
||||
if (strncmp(path, "/sys", strlen("/sys")) == 0 && strlen(path) > 4 &&
|
||||
path[strlen(path) - 4] == 'n' && path[strlen(path) - 3] == 'f' &&
|
||||
path[strlen(path) - 2] == 'c') {
|
||||
if (strncmp(path, FIDO_NFC_PREFIX, strlen(FIDO_NFC_PREFIX)) == 0) {
|
||||
dev->io_own = true;
|
||||
dev->io = (fido_dev_io_t) {
|
||||
fido_nfc_open,
|
||||
@ -363,7 +361,7 @@ fido_dev_open(fido_dev_t *dev, const char *path)
|
||||
}
|
||||
#endif
|
||||
|
||||
return (fido_dev_open_wait(dev, path, -1));
|
||||
return (fido_dev_open_wait(dev, path, &ms));
|
||||
}
|
||||
|
||||
int
|
||||
@ -386,26 +384,31 @@ fido_dev_close(fido_dev_t *dev)
|
||||
int
|
||||
fido_dev_set_sigmask(fido_dev_t *dev, const fido_sigset_t *sigmask)
|
||||
{
|
||||
if (dev->io_own || dev->io_handle == NULL || sigmask == NULL)
|
||||
if (dev->io_handle == NULL || sigmask == NULL)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
#ifdef NFC_LINUX
|
||||
if (dev->transport.rx == fido_nfc_rx)
|
||||
if (dev->transport.rx == fido_nfc_rx && dev->io.read == fido_nfc_read)
|
||||
return (fido_nfc_set_sigmask(dev->io_handle, sigmask));
|
||||
#endif
|
||||
return (fido_hid_set_sigmask(dev->io_handle, sigmask));
|
||||
if (dev->transport.rx == NULL && dev->io.read == fido_hid_read)
|
||||
return (fido_hid_set_sigmask(dev->io_handle, sigmask));
|
||||
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
}
|
||||
|
||||
int
|
||||
fido_dev_cancel(fido_dev_t *dev)
|
||||
{
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
#ifdef USE_WINHELLO
|
||||
if (dev->flags & FIDO_DEV_WINHELLO)
|
||||
return (fido_winhello_cancel(dev));
|
||||
#endif
|
||||
if (fido_dev_is_fido2(dev) == false)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
if (fido_tx(dev, CTAP_CMD_CANCEL, NULL, 0) < 0)
|
||||
if (fido_tx(dev, CTAP_CMD_CANCEL, NULL, 0, &ms) < 0)
|
||||
return (FIDO_ERR_TX);
|
||||
|
||||
return (FIDO_OK);
|
||||
@ -421,6 +424,7 @@ fido_dev_get_touch_begin(fido_dev_t *dev)
|
||||
unsigned char cdh[SHA256_DIGEST_LENGTH];
|
||||
fido_rp_t rp;
|
||||
fido_user_t user;
|
||||
int ms = dev->timeout_ms;
|
||||
int r = FIDO_ERR_INTERNAL;
|
||||
|
||||
memset(&f, 0, sizeof(f));
|
||||
@ -430,7 +434,7 @@ fido_dev_get_touch_begin(fido_dev_t *dev)
|
||||
memset(&user, 0, sizeof(user));
|
||||
|
||||
if (fido_dev_is_fido2(dev) == false)
|
||||
return (u2f_get_touch_begin(dev));
|
||||
return (u2f_get_touch_begin(dev, &ms));
|
||||
|
||||
if (SHA256((const void *)clientdata, strlen(clientdata), cdh) != cdh) {
|
||||
fido_log_debug("%s: sha256", __func__);
|
||||
@ -465,7 +469,7 @@ fido_dev_get_touch_begin(fido_dev_t *dev)
|
||||
}
|
||||
|
||||
if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 ||
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, &ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -490,9 +494,9 @@ fido_dev_get_touch_status(fido_dev_t *dev, int *touched, int ms)
|
||||
*touched = 0;
|
||||
|
||||
if (fido_dev_is_fido2(dev) == false)
|
||||
return (u2f_get_touch_status(dev, touched, ms));
|
||||
return (u2f_get_touch_status(dev, touched, &ms));
|
||||
|
||||
switch ((r = fido_rx_cbor_status(dev, ms))) {
|
||||
switch ((r = fido_rx_cbor_status(dev, &ms))) {
|
||||
case FIDO_ERR_PIN_AUTH_INVALID:
|
||||
case FIDO_ERR_PIN_INVALID:
|
||||
case FIDO_ERR_PIN_NOT_SET:
|
||||
@ -562,6 +566,7 @@ fido_dev_new(void)
|
||||
return (NULL);
|
||||
|
||||
dev->cid = CTAP_CID_BROADCAST;
|
||||
dev->timeout_ms = -1;
|
||||
dev->io = (fido_dev_io_t) {
|
||||
&fido_hid_open,
|
||||
&fido_hid_close,
|
||||
@ -593,6 +598,7 @@ fido_dev_new_with_info(const fido_dev_info_t *di)
|
||||
dev->io_own = di->transport.tx != NULL || di->transport.rx != NULL;
|
||||
dev->transport = di->transport;
|
||||
dev->cid = CTAP_CID_BROADCAST;
|
||||
dev->timeout_ms = -1;
|
||||
|
||||
if ((dev->path = strdup(di->path)) == NULL) {
|
||||
fido_log_debug("%s: strdup", __func__);
|
||||
@ -730,3 +736,14 @@ fido_dev_maxmsgsize(const fido_dev_t *dev)
|
||||
{
|
||||
return (dev->maxmsgsize);
|
||||
}
|
||||
|
||||
int
|
||||
fido_dev_set_timeout(fido_dev_t *dev, int ms)
|
||||
{
|
||||
if (ms < -1)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
dev->timeout_ms = ms;
|
||||
|
||||
return (FIDO_OK);
|
||||
}
|
||||
|
12
src/ecdh.c
12
src/ecdh.c
@ -8,14 +8,14 @@
|
||||
#include <openssl/sha.h>
|
||||
#if defined(LIBRESSL_VERSION_NUMBER)
|
||||
#include <openssl/hkdf.h>
|
||||
#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
#else
|
||||
#include <openssl/kdf.h>
|
||||
#endif
|
||||
|
||||
#include "fido.h"
|
||||
#include "fido/es256.h"
|
||||
|
||||
#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
#if defined(LIBRESSL_VERSION_NUMBER)
|
||||
static int
|
||||
hkdf_sha256(uint8_t *key, const char *info, const fido_blob_t *secret)
|
||||
{
|
||||
@ -56,7 +56,7 @@ hkdf_sha256(uint8_t *key, char *info, fido_blob_t *secret)
|
||||
EVP_PKEY_CTX_set_hkdf_md(ctx, md) < 1 ||
|
||||
EVP_PKEY_CTX_set1_hkdf_salt(ctx, salt, sizeof(salt)) < 1 ||
|
||||
EVP_PKEY_CTX_set1_hkdf_key(ctx, secret->ptr, (int)secret->len) < 1 ||
|
||||
EVP_PKEY_CTX_add1_hkdf_info(ctx, info, (int)strlen(info)) < 1) {
|
||||
EVP_PKEY_CTX_add1_hkdf_info(ctx, (void *)info, (int)strlen(info)) < 1) {
|
||||
fido_log_debug("%s: EVP_PKEY_CTX", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -74,7 +74,7 @@ hkdf_sha256(uint8_t *key, char *info, fido_blob_t *secret)
|
||||
|
||||
return ok;
|
||||
}
|
||||
#endif /* defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
#endif /* defined(LIBRESSL_VERSION_NUMBER) */
|
||||
|
||||
static int
|
||||
kdf(uint8_t prot, fido_blob_t *key, /* const */ fido_blob_t *secret)
|
||||
@ -164,7 +164,7 @@ do_ecdh(const fido_dev_t *dev, const es256_sk_t *sk, const es256_pk_t *pk,
|
||||
}
|
||||
|
||||
int
|
||||
fido_do_ecdh(fido_dev_t *dev, es256_pk_t **pk, fido_blob_t **ecdh)
|
||||
fido_do_ecdh(fido_dev_t *dev, es256_pk_t **pk, fido_blob_t **ecdh, int *ms)
|
||||
{
|
||||
es256_sk_t *sk = NULL; /* our private key */
|
||||
es256_pk_t *ak = NULL; /* authenticator's public key */
|
||||
@ -182,7 +182,7 @@ fido_do_ecdh(fido_dev_t *dev, es256_pk_t **pk, fido_blob_t **ecdh)
|
||||
goto fail;
|
||||
}
|
||||
if ((ak = es256_pk_new()) == NULL ||
|
||||
fido_dev_authkey(dev, ak) != FIDO_OK) {
|
||||
fido_dev_authkey(dev, ak, ms) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_dev_authkey", __func__);
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
|
82
src/eddsa.c
82
src/eddsa.c
@ -10,7 +10,7 @@
|
||||
#include "fido.h"
|
||||
#include "fido/eddsa.h"
|
||||
|
||||
#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10101000L
|
||||
#if defined(LIBRESSL_VERSION_NUMBER)
|
||||
EVP_PKEY *
|
||||
EVP_PKEY_new_raw_public_key(int type, ENGINE *e, const unsigned char *key,
|
||||
size_t keylen)
|
||||
@ -52,23 +52,7 @@ EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen,
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif /* LIBRESSL_VERSION_NUMBER || OPENSSL_VERSION_NUMBER < 0x10101000L */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
EVP_MD_CTX *
|
||||
EVP_MD_CTX_new(void)
|
||||
{
|
||||
fido_log_debug("%s: unimplemented", __func__);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
EVP_MD_CTX_free(EVP_MD_CTX *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
#endif /* LIBRESSL_VERSION_NUMBER */
|
||||
|
||||
static int
|
||||
decode_coord(const cbor_item_t *item, void *xy, size_t xy_len)
|
||||
@ -170,3 +154,65 @@ eddsa_pk_from_EVP_PKEY(eddsa_pk_t *pk, const EVP_PKEY *pkey)
|
||||
|
||||
return (FIDO_OK);
|
||||
}
|
||||
|
||||
int
|
||||
eddsa_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_MD_CTX *mdctx = NULL;
|
||||
int ok = -1;
|
||||
|
||||
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_ED25519) {
|
||||
fido_log_debug("%s: EVP_PKEY_base_id", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* EVP_DigestVerify needs ints */
|
||||
if (dgst->len > INT_MAX || sig->len > INT_MAX) {
|
||||
fido_log_debug("%s: dgst->len=%zu, sig->len=%zu", __func__,
|
||||
dgst->len, sig->len);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((mdctx = EVP_MD_CTX_new()) == NULL) {
|
||||
fido_log_debug("%s: EVP_MD_CTX_new", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyInit(mdctx, NULL, NULL, NULL, pkey) != 1) {
|
||||
fido_log_debug("%s: EVP_DigestVerifyInit", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerify(mdctx, sig->ptr, sig->len, dgst->ptr,
|
||||
dgst->len) != 1) {
|
||||
fido_log_debug("%s: EVP_DigestVerify", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
EVP_MD_CTX_free(mdctx);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int
|
||||
eddsa_pk_verify_sig(const fido_blob_t *dgst, const eddsa_pk_t *pk,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_PKEY *pkey;
|
||||
int ok = -1;
|
||||
|
||||
if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL ||
|
||||
eddsa_verify_sig(dgst, pkey, sig) < 0) {
|
||||
fido_log_debug("%s: eddsa_verify_sig", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
62
src/es256.c
62
src/es256.c
@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#include "fido.h"
|
||||
@ -362,6 +363,18 @@ es256_pk_from_EC_KEY(es256_pk_t *pk, const EC_KEY *ec)
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int
|
||||
es256_pk_from_EVP_PKEY(es256_pk_t *pk, const EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY *ec;
|
||||
|
||||
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC ||
|
||||
(ec = EVP_PKEY_get0(pkey)) == NULL)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
return (es256_pk_from_EC_KEY(pk, ec));
|
||||
}
|
||||
|
||||
EVP_PKEY *
|
||||
es256_sk_to_EVP_PKEY(const es256_sk_t *k)
|
||||
{
|
||||
@ -451,3 +464,50 @@ es256_derive_pk(const es256_sk_t *sk, es256_pk_t *pk)
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int
|
||||
es256_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
int ok = -1;
|
||||
|
||||
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
|
||||
fido_log_debug("%s: EVP_PKEY_base_id", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL ||
|
||||
EVP_PKEY_verify_init(pctx) != 1 ||
|
||||
EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr,
|
||||
dgst->len) != 1) {
|
||||
fido_log_debug("%s: EVP_PKEY_verify", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int
|
||||
es256_pk_verify_sig(const fido_blob_t *dgst, const es256_pk_t *pk,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_PKEY *pkey;
|
||||
int ok = -1;
|
||||
|
||||
if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL ||
|
||||
es256_verify_sig(dgst, pkey, sig) < 0) {
|
||||
fido_log_debug("%s: es256_verify_sig", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
eddsa_pk_to_EVP_PKEY;
|
||||
es256_pk_free;
|
||||
es256_pk_from_EC_KEY;
|
||||
es256_pk_from_EVP_PKEY;
|
||||
es256_pk_from_ptr;
|
||||
es256_pk_new;
|
||||
es256_pk_to_EVP_PKEY;
|
||||
@ -99,6 +100,8 @@
|
||||
fido_cbor_info_transports_ptr;
|
||||
fido_cbor_info_versions_len;
|
||||
fido_cbor_info_versions_ptr;
|
||||
fido_cred_attstmt_len;
|
||||
fido_cred_attstmt_ptr;
|
||||
fido_cred_authdata_len;
|
||||
fido_cred_authdata_ptr;
|
||||
fido_cred_authdata_raw_len;
|
||||
@ -138,11 +141,13 @@
|
||||
fido_credman_rp_new;
|
||||
fido_credman_set_dev_rk;
|
||||
fido_cred_new;
|
||||
fido_cred_pin_minlen;
|
||||
fido_cred_prot;
|
||||
fido_cred_pubkey_len;
|
||||
fido_cred_pubkey_ptr;
|
||||
fido_cred_rp_id;
|
||||
fido_cred_rp_name;
|
||||
fido_cred_set_attstmt;
|
||||
fido_cred_set_authdata;
|
||||
fido_cred_set_authdata_raw;
|
||||
fido_cred_set_blob;
|
||||
@ -152,6 +157,7 @@
|
||||
fido_cred_set_fmt;
|
||||
fido_cred_set_id;
|
||||
fido_cred_set_options;
|
||||
fido_cred_set_pin_minlen;
|
||||
fido_cred_set_prot;
|
||||
fido_cred_set_rk;
|
||||
fido_cred_set_rp;
|
||||
@ -208,7 +214,9 @@
|
||||
fido_dev_set_io_functions;
|
||||
fido_dev_set_pin;
|
||||
fido_dev_set_pin_minlen;
|
||||
fido_dev_set_pin_minlen_rpid;
|
||||
fido_dev_set_sigmask;
|
||||
fido_dev_set_timeout;
|
||||
fido_dev_set_transport_functions;
|
||||
fido_dev_supports_cred_prot;
|
||||
fido_dev_supports_credman;
|
||||
@ -226,6 +234,7 @@
|
||||
fido_strerr;
|
||||
rs256_pk_free;
|
||||
rs256_pk_from_ptr;
|
||||
rs256_pk_from_EVP_PKEY;
|
||||
rs256_pk_from_RSA;
|
||||
rs256_pk_new;
|
||||
rs256_pk_to_EVP_PKEY;
|
||||
|
@ -5,6 +5,7 @@ _eddsa_pk_new
|
||||
_eddsa_pk_to_EVP_PKEY
|
||||
_es256_pk_free
|
||||
_es256_pk_from_EC_KEY
|
||||
_es256_pk_from_EVP_PKEY
|
||||
_es256_pk_from_ptr
|
||||
_es256_pk_new
|
||||
_es256_pk_to_EVP_PKEY
|
||||
@ -97,6 +98,8 @@ _fido_cbor_info_transports_len
|
||||
_fido_cbor_info_transports_ptr
|
||||
_fido_cbor_info_versions_len
|
||||
_fido_cbor_info_versions_ptr
|
||||
_fido_cred_attstmt_len
|
||||
_fido_cred_attstmt_ptr
|
||||
_fido_cred_authdata_len
|
||||
_fido_cred_authdata_ptr
|
||||
_fido_cred_authdata_raw_len
|
||||
@ -136,11 +139,13 @@ _fido_credman_rp_name
|
||||
_fido_credman_rp_new
|
||||
_fido_credman_set_dev_rk
|
||||
_fido_cred_new
|
||||
_fido_cred_pin_minlen
|
||||
_fido_cred_prot
|
||||
_fido_cred_pubkey_len
|
||||
_fido_cred_pubkey_ptr
|
||||
_fido_cred_rp_id
|
||||
_fido_cred_rp_name
|
||||
_fido_cred_set_attstmt
|
||||
_fido_cred_set_authdata
|
||||
_fido_cred_set_authdata_raw
|
||||
_fido_cred_set_blob
|
||||
@ -150,6 +155,7 @@ _fido_cred_set_extensions
|
||||
_fido_cred_set_fmt
|
||||
_fido_cred_set_id
|
||||
_fido_cred_set_options
|
||||
_fido_cred_set_pin_minlen
|
||||
_fido_cred_set_prot
|
||||
_fido_cred_set_rk
|
||||
_fido_cred_set_rp
|
||||
@ -206,7 +212,9 @@ _fido_dev_reset
|
||||
_fido_dev_set_io_functions
|
||||
_fido_dev_set_pin
|
||||
_fido_dev_set_pin_minlen
|
||||
_fido_dev_set_pin_minlen_rpid
|
||||
_fido_dev_set_sigmask
|
||||
_fido_dev_set_timeout
|
||||
_fido_dev_set_transport_functions
|
||||
_fido_dev_supports_cred_prot
|
||||
_fido_dev_supports_credman
|
||||
@ -224,6 +232,7 @@ _fido_set_log_handler
|
||||
_fido_strerr
|
||||
_rs256_pk_free
|
||||
_rs256_pk_from_ptr
|
||||
_rs256_pk_from_EVP_PKEY
|
||||
_rs256_pk_from_RSA
|
||||
_rs256_pk_new
|
||||
_rs256_pk_to_EVP_PKEY
|
||||
|
@ -6,6 +6,7 @@ eddsa_pk_new
|
||||
eddsa_pk_to_EVP_PKEY
|
||||
es256_pk_free
|
||||
es256_pk_from_EC_KEY
|
||||
es256_pk_from_EVP_PKEY
|
||||
es256_pk_from_ptr
|
||||
es256_pk_new
|
||||
es256_pk_to_EVP_PKEY
|
||||
@ -98,6 +99,8 @@ fido_cbor_info_transports_len
|
||||
fido_cbor_info_transports_ptr
|
||||
fido_cbor_info_versions_len
|
||||
fido_cbor_info_versions_ptr
|
||||
fido_cred_attstmt_len
|
||||
fido_cred_attstmt_ptr
|
||||
fido_cred_authdata_len
|
||||
fido_cred_authdata_ptr
|
||||
fido_cred_authdata_raw_len
|
||||
@ -137,11 +140,13 @@ fido_credman_rp_name
|
||||
fido_credman_rp_new
|
||||
fido_credman_set_dev_rk
|
||||
fido_cred_new
|
||||
fido_cred_pin_minlen
|
||||
fido_cred_prot
|
||||
fido_cred_pubkey_len
|
||||
fido_cred_pubkey_ptr
|
||||
fido_cred_rp_id
|
||||
fido_cred_rp_name
|
||||
fido_cred_set_attstmt
|
||||
fido_cred_set_authdata
|
||||
fido_cred_set_authdata_raw
|
||||
fido_cred_set_blob
|
||||
@ -151,6 +156,7 @@ fido_cred_set_extensions
|
||||
fido_cred_set_fmt
|
||||
fido_cred_set_id
|
||||
fido_cred_set_options
|
||||
fido_cred_set_pin_minlen
|
||||
fido_cred_set_prot
|
||||
fido_cred_set_rk
|
||||
fido_cred_set_rp
|
||||
@ -207,7 +213,9 @@ fido_dev_reset
|
||||
fido_dev_set_io_functions
|
||||
fido_dev_set_pin
|
||||
fido_dev_set_pin_minlen
|
||||
fido_dev_set_pin_minlen_rpid
|
||||
fido_dev_set_sigmask
|
||||
fido_dev_set_timeout
|
||||
fido_dev_set_transport_functions
|
||||
fido_dev_supports_cred_prot
|
||||
fido_dev_supports_credman
|
||||
@ -225,6 +233,7 @@ fido_set_log_handler
|
||||
fido_strerr
|
||||
rs256_pk_free
|
||||
rs256_pk_from_ptr
|
||||
rs256_pk_from_EVP_PKEY
|
||||
rs256_pk_from_RSA
|
||||
rs256_pk_new
|
||||
rs256_pk_to_EVP_PKEY
|
||||
|
55
src/extern.h
55
src/extern.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -51,6 +51,7 @@ cbor_item_t *cbor_encode_pubkey(const fido_blob_t *);
|
||||
cbor_item_t *cbor_encode_pubkey_list(const fido_blob_array_t *);
|
||||
cbor_item_t *cbor_encode_pubkey_param(int);
|
||||
cbor_item_t *cbor_encode_rp_entity(const fido_rp_t *);
|
||||
cbor_item_t *cbor_encode_str_array(const fido_str_array_t *);
|
||||
cbor_item_t *cbor_encode_user_entity(const fido_user_t *);
|
||||
cbor_item_t *es256_pk_encode(const es256_pk_t *, int);
|
||||
|
||||
@ -86,7 +87,7 @@ int cbor_parse_reply(const unsigned char *, size_t, void *,
|
||||
int(*)(const cbor_item_t *, const cbor_item_t *, void *));
|
||||
int cbor_add_uv_params(fido_dev_t *, uint8_t, const fido_blob_t *,
|
||||
const es256_pk_t *, const fido_blob_t *, const char *, const char *,
|
||||
cbor_item_t **, cbor_item_t **);
|
||||
cbor_item_t **, cbor_item_t **, int *);
|
||||
void cbor_vector_free(cbor_item_t **, size_t);
|
||||
int cbor_array_append(cbor_item_t **, cbor_item_t *);
|
||||
int cbor_array_drop(cbor_item_t **, size_t);
|
||||
@ -130,14 +131,14 @@ int fido_winhello_manifest(fido_dev_info_t *, size_t, size_t *);
|
||||
int fido_winhello_open(fido_dev_t *);
|
||||
int fido_winhello_close(fido_dev_t *);
|
||||
int fido_winhello_cancel(fido_dev_t *);
|
||||
int fido_winhello_get_assert(fido_dev_t *, fido_assert_t *, const char *);
|
||||
int fido_winhello_get_assert(fido_dev_t *, fido_assert_t *, const char *, int);
|
||||
int fido_winhello_get_cbor_info(fido_dev_t *, fido_cbor_info_t *);
|
||||
int fido_winhello_make_cred(fido_dev_t *, fido_cred_t *, const char *);
|
||||
int fido_winhello_make_cred(fido_dev_t *, fido_cred_t *, const char *, int);
|
||||
|
||||
/* generic i/o */
|
||||
int fido_rx_cbor_status(fido_dev_t *, int);
|
||||
int fido_rx(fido_dev_t *, uint8_t, void *, size_t, int);
|
||||
int fido_tx(fido_dev_t *, uint8_t, const void *, size_t);
|
||||
int fido_rx_cbor_status(fido_dev_t *, int *);
|
||||
int fido_rx(fido_dev_t *, uint8_t, void *, size_t, int *);
|
||||
int fido_tx(fido_dev_t *, uint8_t, const void *, size_t, int *);
|
||||
|
||||
/* log */
|
||||
#ifdef FIDO_NO_DIAGNOSTIC
|
||||
@ -163,21 +164,30 @@ void fido_log_error(int, const char *, ...);
|
||||
#endif /* FIDO_NO_DIAGNOSTIC */
|
||||
|
||||
/* u2f */
|
||||
int u2f_register(fido_dev_t *, fido_cred_t *, int);
|
||||
int u2f_authenticate(fido_dev_t *, fido_assert_t *, int);
|
||||
int u2f_get_touch_begin(fido_dev_t *);
|
||||
int u2f_get_touch_status(fido_dev_t *, int *, int);
|
||||
int u2f_register(fido_dev_t *, fido_cred_t *, int *);
|
||||
int u2f_authenticate(fido_dev_t *, fido_assert_t *, int *);
|
||||
int u2f_get_touch_begin(fido_dev_t *, int *);
|
||||
int u2f_get_touch_status(fido_dev_t *, int *, int *);
|
||||
|
||||
/* unexposed fido ops */
|
||||
uint8_t fido_dev_get_pin_protocol(const fido_dev_t *);
|
||||
int fido_dev_authkey(fido_dev_t *, es256_pk_t *);
|
||||
int fido_dev_get_cbor_info_wait(fido_dev_t *, fido_cbor_info_t *, int);
|
||||
int fido_dev_authkey(fido_dev_t *, es256_pk_t *, int *);
|
||||
int fido_dev_get_cbor_info_wait(fido_dev_t *, fido_cbor_info_t *, int *);
|
||||
int fido_dev_get_uv_token(fido_dev_t *, uint8_t, const char *,
|
||||
const fido_blob_t *, const es256_pk_t *, const char *, fido_blob_t *);
|
||||
const fido_blob_t *, const es256_pk_t *, const char *, fido_blob_t *,
|
||||
int *);
|
||||
uint64_t fido_dev_maxmsgsize(const fido_dev_t *);
|
||||
int fido_do_ecdh(fido_dev_t *, es256_pk_t **, fido_blob_t **);
|
||||
int fido_do_ecdh(fido_dev_t *, es256_pk_t **, fido_blob_t **, int *);
|
||||
bool fido_dev_supports_permissions(const fido_dev_t *);
|
||||
|
||||
/* types */
|
||||
void fido_algo_array_free(fido_algo_array_t *);
|
||||
void fido_byte_array_free(fido_byte_array_t *);
|
||||
void fido_opt_array_free(fido_opt_array_t *);
|
||||
void fido_str_array_free(fido_str_array_t *);
|
||||
void fido_algo_free(fido_algo_t *);
|
||||
int fido_str_array_pack(fido_str_array_t *, const char * const *, size_t);
|
||||
|
||||
/* misc */
|
||||
void fido_assert_reset_rx(fido_assert_t *);
|
||||
void fido_assert_reset_tx(fido_assert_t *);
|
||||
@ -189,16 +199,24 @@ int fido_check_flags(uint8_t, fido_opt_t, fido_opt_t);
|
||||
int fido_check_rp_id(const char *, const unsigned char *);
|
||||
int fido_get_random(void *, size_t);
|
||||
int fido_sha256(fido_blob_t *, const u_char *, size_t);
|
||||
int fido_time_now(struct timespec *);
|
||||
int fido_time_delta(const struct timespec *, int *);
|
||||
|
||||
/* crypto */
|
||||
int fido_verify_sig_es256(const fido_blob_t *, const es256_pk_t *,
|
||||
int es256_verify_sig(const fido_blob_t *, EVP_PKEY *, const fido_blob_t *);
|
||||
int rs256_verify_sig(const fido_blob_t *, EVP_PKEY *, const fido_blob_t *);
|
||||
int eddsa_verify_sig(const fido_blob_t *, EVP_PKEY *, const fido_blob_t *);
|
||||
int rs1_verify_sig(const fido_blob_t *, EVP_PKEY *, const fido_blob_t *);
|
||||
int es256_pk_verify_sig(const fido_blob_t *, const es256_pk_t *,
|
||||
const fido_blob_t *);
|
||||
int fido_verify_sig_rs256(const fido_blob_t *, const rs256_pk_t *,
|
||||
int rs256_pk_verify_sig(const fido_blob_t *, const rs256_pk_t *,
|
||||
const fido_blob_t *);
|
||||
int fido_verify_sig_eddsa(const fido_blob_t *, const eddsa_pk_t *,
|
||||
int eddsa_pk_verify_sig(const fido_blob_t *, const eddsa_pk_t *,
|
||||
const fido_blob_t *);
|
||||
int fido_get_signed_hash(int, fido_blob_t *, const fido_blob_t *,
|
||||
const fido_blob_t *);
|
||||
int fido_get_signed_hash_tpm(fido_blob_t *, const fido_blob_t *,
|
||||
const fido_blob_t *, const fido_attstmt_t *, const fido_attcred_t *);
|
||||
|
||||
/* device manifest functions */
|
||||
int fido_hid_manifest(fido_dev_info_t *, size_t, size_t *);
|
||||
@ -232,6 +250,7 @@ uint32_t uniform_random(uint32_t);
|
||||
#define FIDO_DUMMY_USER_NAME "dummy"
|
||||
#define FIDO_DUMMY_USER_ID 1
|
||||
#define FIDO_WINHELLO_PATH "windows://hello"
|
||||
#define FIDO_NFC_PREFIX "nfc:"
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
18
src/fido.h
18
src/fido.h
@ -86,16 +86,17 @@ const char *fido_dev_info_product_string(const fido_dev_info_t *);
|
||||
const fido_dev_info_t *fido_dev_info_ptr(const fido_dev_info_t *, size_t);
|
||||
const uint8_t *fido_cbor_info_protocols_ptr(const fido_cbor_info_t *);
|
||||
const unsigned char *fido_cbor_info_aaguid_ptr(const fido_cbor_info_t *);
|
||||
const unsigned char *fido_cred_aaguid_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_attstmt_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_authdata_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_authdata_raw_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_clientdata_hash_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_id_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_aaguid_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_user_id_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_largeblob_key_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_pubkey_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_sig_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_user_id_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_x5c_ptr(const fido_cred_t *);
|
||||
const unsigned char *fido_cred_largeblob_key_ptr(const fido_cred_t *);
|
||||
|
||||
int fido_assert_allow_cred(fido_assert_t *, const unsigned char *, size_t);
|
||||
int fido_assert_set_authdata(fido_assert_t *, size_t, const unsigned char *,
|
||||
@ -119,6 +120,7 @@ int fido_assert_verify(const fido_assert_t *, size_t, int, const void *);
|
||||
int fido_cbor_info_algorithm_cose(const fido_cbor_info_t *, size_t);
|
||||
int fido_cred_exclude(fido_cred_t *, const unsigned char *, size_t);
|
||||
int fido_cred_prot(const fido_cred_t *);
|
||||
int fido_cred_set_attstmt(fido_cred_t *, const unsigned char *, size_t);
|
||||
int fido_cred_set_authdata(fido_cred_t *, const unsigned char *, size_t);
|
||||
int fido_cred_set_authdata_raw(fido_cred_t *, const unsigned char *, size_t);
|
||||
int fido_cred_set_blob(fido_cred_t *, const unsigned char *, size_t);
|
||||
@ -128,6 +130,7 @@ int fido_cred_set_extensions(fido_cred_t *, int);
|
||||
int fido_cred_set_fmt(fido_cred_t *, const char *);
|
||||
int fido_cred_set_id(fido_cred_t *, const unsigned char *, size_t);
|
||||
int fido_cred_set_options(fido_cred_t *, bool, bool);
|
||||
int fido_cred_set_pin_minlen(fido_cred_t *, size_t);
|
||||
int fido_cred_set_prot(fido_cred_t *, int);
|
||||
int fido_cred_set_rk(fido_cred_t *, fido_opt_t);
|
||||
int fido_cred_set_rp(fido_cred_t *, const char *, const char *);
|
||||
@ -157,6 +160,7 @@ int fido_dev_reset(fido_dev_t *);
|
||||
int fido_dev_set_io_functions(fido_dev_t *, const fido_dev_io_t *);
|
||||
int fido_dev_set_pin(fido_dev_t *, const char *, const char *);
|
||||
int fido_dev_set_transport_functions(fido_dev_t *, const fido_dev_transport_t *);
|
||||
int fido_dev_set_timeout(fido_dev_t *, int);
|
||||
|
||||
size_t fido_assert_authdata_len(const fido_assert_t *, size_t);
|
||||
size_t fido_assert_clientdata_hash_len(const fido_assert_t *);
|
||||
@ -174,16 +178,18 @@ size_t fido_cbor_info_options_len(const fido_cbor_info_t *);
|
||||
size_t fido_cbor_info_protocols_len(const fido_cbor_info_t *);
|
||||
size_t fido_cbor_info_transports_len(const fido_cbor_info_t *);
|
||||
size_t fido_cbor_info_versions_len(const fido_cbor_info_t *);
|
||||
size_t fido_cred_aaguid_len(const fido_cred_t *);
|
||||
size_t fido_cred_attstmt_len(const fido_cred_t *);
|
||||
size_t fido_cred_authdata_len(const fido_cred_t *);
|
||||
size_t fido_cred_authdata_raw_len(const fido_cred_t *);
|
||||
size_t fido_cred_clientdata_hash_len(const fido_cred_t *);
|
||||
size_t fido_cred_id_len(const fido_cred_t *);
|
||||
size_t fido_cred_aaguid_len(const fido_cred_t *);
|
||||
size_t fido_cred_user_id_len(const fido_cred_t *);
|
||||
size_t fido_cred_largeblob_key_len(const fido_cred_t *);
|
||||
size_t fido_cred_pin_minlen(const fido_cred_t *);
|
||||
size_t fido_cred_pubkey_len(const fido_cred_t *);
|
||||
size_t fido_cred_sig_len(const fido_cred_t *);
|
||||
size_t fido_cred_user_id_len(const fido_cred_t *);
|
||||
size_t fido_cred_x5c_len(const fido_cred_t *);
|
||||
size_t fido_cred_largeblob_key_len(const fido_cred_t *);
|
||||
|
||||
uint8_t fido_assert_flags(const fido_assert_t *, size_t);
|
||||
uint32_t fido_assert_sigcount(const fido_assert_t *, size_t);
|
||||
|
@ -26,6 +26,8 @@ int fido_dev_enable_entattest(fido_dev_t *, const char *);
|
||||
int fido_dev_force_pin_change(fido_dev_t *, const char *);
|
||||
int fido_dev_toggle_always_uv(fido_dev_t *, const char *);
|
||||
int fido_dev_set_pin_minlen(fido_dev_t *, size_t, const char *);
|
||||
int fido_dev_set_pin_minlen_rpid(fido_dev_t *, const char * const *, size_t,
|
||||
const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -31,19 +31,14 @@ int eddsa_pk_from_ptr(eddsa_pk_t *, const void *, size_t);
|
||||
|
||||
#ifdef _FIDO_INTERNAL
|
||||
|
||||
#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10101000L
|
||||
#if defined(LIBRESSL_VERSION_NUMBER)
|
||||
#define EVP_PKEY_ED25519 EVP_PKEY_NONE
|
||||
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *, unsigned char *, size_t *);
|
||||
EVP_PKEY *EVP_PKEY_new_raw_public_key(int, ENGINE *, const unsigned char *,
|
||||
size_t);
|
||||
int EVP_DigestVerify(EVP_MD_CTX *, const unsigned char *, size_t,
|
||||
const unsigned char *, size_t);
|
||||
#endif /* LIBRESSL_VERSION_NUMBER || OPENSSL_VERSION_NUMBER < 0x10101000L */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
EVP_MD_CTX *EVP_MD_CTX_new(void);
|
||||
void EVP_MD_CTX_free(EVP_MD_CTX *);
|
||||
#endif
|
||||
#endif /* LIBRESSL_VERSION_NUMBER */
|
||||
|
||||
#endif /* _FIDO_INTERNAL */
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -27,6 +27,7 @@ void es256_pk_free(es256_pk_t **);
|
||||
EVP_PKEY *es256_pk_to_EVP_PKEY(const es256_pk_t *);
|
||||
|
||||
int es256_pk_from_EC_KEY(es256_pk_t *, const EC_KEY *);
|
||||
int es256_pk_from_EVP_PKEY(es256_pk_t *, const EVP_PKEY *);
|
||||
int es256_pk_from_ptr(es256_pk_t *, const void *, size_t);
|
||||
|
||||
#ifdef _FIDO_INTERNAL
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -82,10 +82,12 @@
|
||||
#define FIDO_CAP_NMSG 0x08 /* if set, device doesn't support CTAP_CMD_MSG */
|
||||
|
||||
/* Supported COSE algorithms. */
|
||||
#define COSE_UNSPEC 0
|
||||
#define COSE_ES256 -7
|
||||
#define COSE_EDDSA -8
|
||||
#define COSE_ECDH_ES256 -25
|
||||
#define COSE_RS256 -257
|
||||
#define COSE_RS1 -65535
|
||||
|
||||
/* Supported COSE types. */
|
||||
#define COSE_KTY_OKP 1
|
||||
@ -101,6 +103,7 @@
|
||||
#define FIDO_EXT_CRED_PROTECT 0x02
|
||||
#define FIDO_EXT_LARGEBLOB_KEY 0x04
|
||||
#define FIDO_EXT_CRED_BLOB 0x08
|
||||
#define FIDO_EXT_MINPINLEN 0x10
|
||||
|
||||
/* Supported credential protection policies. */
|
||||
#define FIDO_CRED_PROT_UV_OPTIONAL 0x01
|
||||
@ -111,7 +114,8 @@
|
||||
#define FIDO_EXT_ASSERT_MASK (FIDO_EXT_HMAC_SECRET|FIDO_EXT_LARGEBLOB_KEY| \
|
||||
FIDO_EXT_CRED_BLOB)
|
||||
#define FIDO_EXT_CRED_MASK (FIDO_EXT_HMAC_SECRET|FIDO_EXT_CRED_PROTECT| \
|
||||
FIDO_EXT_LARGEBLOB_KEY|FIDO_EXT_CRED_BLOB)
|
||||
FIDO_EXT_LARGEBLOB_KEY|FIDO_EXT_CRED_BLOB| \
|
||||
FIDO_EXT_MINPINLEN)
|
||||
#endif /* _FIDO_INTERNAL */
|
||||
|
||||
#endif /* !_FIDO_PARAM_H */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -26,6 +26,7 @@ rs256_pk_t *rs256_pk_new(void);
|
||||
void rs256_pk_free(rs256_pk_t **);
|
||||
EVP_PKEY *rs256_pk_to_EVP_PKEY(const rs256_pk_t *);
|
||||
|
||||
int rs256_pk_from_EVP_PKEY(rs256_pk_t *, const EVP_PKEY *);
|
||||
int rs256_pk_from_RSA(rs256_pk_t *, const RSA *);
|
||||
int rs256_pk_from_ptr(rs256_pk_t *, const void *, size_t);
|
||||
|
||||
|
@ -107,8 +107,12 @@ typedef struct fido_attcred {
|
||||
} fido_attcred_t;
|
||||
|
||||
typedef struct fido_attstmt {
|
||||
fido_blob_t x5c; /* attestation certificate */
|
||||
fido_blob_t sig; /* attestation signature */
|
||||
fido_blob_t certinfo; /* tpm attestation TPMS_ATTEST structure */
|
||||
fido_blob_t pubarea; /* tpm attestation TPMT_PUBLIC structure */
|
||||
fido_blob_t cbor; /* cbor-encoded attestation statement */
|
||||
fido_blob_t x5c; /* attestation certificate */
|
||||
fido_blob_t sig; /* attestation signature */
|
||||
int alg; /* attestation algorithm (cose) */
|
||||
} fido_attstmt_t;
|
||||
|
||||
typedef struct fido_rp {
|
||||
@ -124,8 +128,9 @@ typedef struct fido_user {
|
||||
} fido_user_t;
|
||||
|
||||
typedef struct fido_cred_ext {
|
||||
int mask; /* enabled extensions */
|
||||
int prot; /* protection policy */
|
||||
int mask; /* enabled extensions */
|
||||
int prot; /* protection policy */
|
||||
size_t minpinlen; /* minimum pin length */
|
||||
} fido_cred_ext_t;
|
||||
|
||||
typedef struct fido_cred {
|
||||
@ -260,6 +265,7 @@ typedef struct fido_dev {
|
||||
int flags; /* internal flags; see FIDO_DEV_* */
|
||||
fido_dev_transport_t transport; /* transport functions */
|
||||
uint64_t maxmsgsize; /* max message size */
|
||||
int timeout_ms; /* read timeout in ms */
|
||||
} fido_dev_t;
|
||||
|
||||
#else
|
||||
|
@ -14,6 +14,12 @@
|
||||
|
||||
#include "fido.h"
|
||||
|
||||
#if defined(__MidnightBSD__)
|
||||
#define UHID_VENDOR "MidnightBSD"
|
||||
#else
|
||||
#define UHID_VENDOR "FreeBSD"
|
||||
#endif
|
||||
|
||||
#define MAX_UHID 64
|
||||
|
||||
struct hid_freebsd {
|
||||
@ -66,7 +72,7 @@ copy_info(fido_dev_info_t *di, const char *path)
|
||||
|
||||
if (ioctl(fd, IOCTL_REQ(USB_GET_DEVICEINFO), &udi) == -1) {
|
||||
fido_log_error(errno, "%s: ioctl", __func__);
|
||||
strlcpy(udi.udi_vendor, "FreeBSD", sizeof(udi.udi_vendor));
|
||||
strlcpy(udi.udi_vendor, UHID_VENDOR, sizeof(udi.udi_vendor));
|
||||
strlcpy(udi.udi_product, "uhid(4)", sizeof(udi.udi_product));
|
||||
udi.udi_vendorNo = 0x0b5d; /* stolen from PCI_VENDOR_OPENBSD */
|
||||
}
|
||||
|
@ -160,9 +160,9 @@ copy_info(fido_dev_info_t *di, struct udev *udev,
|
||||
|
||||
di->path = strdup(path);
|
||||
if ((di->manufacturer = get_usb_attr(dev, "manufacturer")) == NULL)
|
||||
di->manufacturer = strdup("unknown");
|
||||
di->manufacturer = strdup("");
|
||||
if ((di->product = get_usb_attr(dev, "product")) == NULL)
|
||||
di->product = strdup("unknown");
|
||||
di->product = strdup("");
|
||||
if (di->path == NULL || di->manufacturer == NULL || di->product == NULL)
|
||||
goto fail;
|
||||
|
||||
|
@ -23,6 +23,8 @@ struct hid_openbsd {
|
||||
int fd;
|
||||
size_t report_in_len;
|
||||
size_t report_out_len;
|
||||
sigset_t sigmask;
|
||||
const sigset_t *sigmaskp;
|
||||
};
|
||||
|
||||
int
|
||||
@ -185,10 +187,12 @@ fido_hid_close(void *handle)
|
||||
int
|
||||
fido_hid_set_sigmask(void *handle, const fido_sigset_t *sigmask)
|
||||
{
|
||||
(void)handle;
|
||||
(void)sigmask;
|
||||
struct hid_openbsd *ctx = handle;
|
||||
|
||||
return (FIDO_ERR_INTERNAL);
|
||||
ctx->sigmask = *sigmask;
|
||||
ctx->sigmaskp = &ctx->sigmask;
|
||||
|
||||
return (FIDO_OK);
|
||||
}
|
||||
|
||||
int
|
||||
@ -197,14 +201,17 @@ fido_hid_read(void *handle, unsigned char *buf, size_t len, int ms)
|
||||
struct hid_openbsd *ctx = (struct hid_openbsd *)handle;
|
||||
ssize_t r;
|
||||
|
||||
(void)ms; /* XXX */
|
||||
|
||||
if (len != ctx->report_in_len) {
|
||||
fido_log_debug("%s: invalid len: got %zu, want %zu", __func__,
|
||||
len, ctx->report_in_len);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (fido_hid_unix_wait(ctx->fd, ms, ctx->sigmaskp) < 0) {
|
||||
fido_log_debug("%s: fd not ready", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((r = read(ctx->fd, buf, len)) == -1) {
|
||||
fido_log_error(errno, "%s: read", __func__);
|
||||
return (-1);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <Availability.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/hid/IOHIDKeys.h>
|
||||
@ -18,6 +19,10 @@
|
||||
|
||||
#include "fido.h"
|
||||
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 120000
|
||||
#define kIOMainPortDefault kIOMasterPortDefault
|
||||
#endif
|
||||
|
||||
struct hid_osx {
|
||||
IOHIDDeviceRef ref;
|
||||
CFStringRef loop_id;
|
||||
@ -131,23 +136,18 @@ get_str(IOHIDDeviceRef dev, char **manufacturer, char **product)
|
||||
*manufacturer = NULL;
|
||||
*product = NULL;
|
||||
|
||||
if (get_utf8(dev, CFSTR(kIOHIDManufacturerKey), buf, sizeof(buf)) < 0) {
|
||||
fido_log_debug("%s: get_utf8 manufacturer", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if (get_utf8(dev, CFSTR(kIOHIDManufacturerKey), buf, sizeof(buf)) < 0)
|
||||
*manufacturer = strdup("");
|
||||
else
|
||||
*manufacturer = strdup(buf);
|
||||
|
||||
if ((*manufacturer = strdup(buf)) == NULL) {
|
||||
fido_log_debug("%s: strdup manufacturer", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if (get_utf8(dev, CFSTR(kIOHIDProductKey), buf, sizeof(buf)) < 0)
|
||||
*product = strdup("");
|
||||
else
|
||||
*product = strdup(buf);
|
||||
|
||||
if (get_utf8(dev, CFSTR(kIOHIDProductKey), buf, sizeof(buf)) < 0) {
|
||||
fido_log_debug("%s: get_utf8 product", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((*product = strdup(buf)) == NULL) {
|
||||
fido_log_debug("%s: strdup product", __func__);
|
||||
if (*manufacturer == NULL || *product == NULL) {
|
||||
fido_log_debug("%s: strdup", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -398,7 +398,7 @@ fido_hid_open(const char *path)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((entry = IORegistryEntryFromPath(kIOMasterPortDefault,
|
||||
if ((entry = IORegistryEntryFromPath(kIOMainPortDefault,
|
||||
path)) == MACH_PORT_NULL) {
|
||||
fido_log_debug("%s: IORegistryEntryFromPath", __func__);
|
||||
goto fail;
|
||||
|
@ -58,8 +58,7 @@ fido_hid_unix_wait(int fd, int ms, const fido_sigset_t *sigmask)
|
||||
pfd.fd = fd;
|
||||
|
||||
#ifdef FIDO_FUZZ
|
||||
if (ms < 0)
|
||||
return (0);
|
||||
return (0);
|
||||
#endif
|
||||
if (ms > -1) {
|
||||
ts.tv_sec = ms / 1000;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2019-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -103,7 +103,7 @@ get_report_len(HANDLE dev, int dir, size_t *report_len)
|
||||
}
|
||||
|
||||
static int
|
||||
get_int(HANDLE dev, int16_t *vendor_id, int16_t *product_id)
|
||||
get_id(HANDLE dev, int16_t *vendor_id, int16_t *product_id)
|
||||
{
|
||||
HIDD_ATTRIBUTES attr;
|
||||
|
||||
@ -121,14 +121,13 @@ get_int(HANDLE dev, int16_t *vendor_id, int16_t *product_id)
|
||||
}
|
||||
|
||||
static int
|
||||
get_str(HANDLE dev, char **manufacturer, char **product)
|
||||
get_manufacturer(HANDLE dev, char **manufacturer)
|
||||
{
|
||||
wchar_t buf[512];
|
||||
int utf8_len;
|
||||
int ok = -1;
|
||||
|
||||
*manufacturer = NULL;
|
||||
*product = NULL;
|
||||
|
||||
if (HidD_GetManufacturerString(dev, &buf, sizeof(buf)) == false) {
|
||||
fido_log_debug("%s: HidD_GetManufacturerString", __func__);
|
||||
@ -152,6 +151,25 @@ get_str(HANDLE dev, char **manufacturer, char **product)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
if (ok < 0) {
|
||||
free(*manufacturer);
|
||||
*manufacturer = NULL;
|
||||
}
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
static int
|
||||
get_product(HANDLE dev, char **product)
|
||||
{
|
||||
wchar_t buf[512];
|
||||
int utf8_len;
|
||||
int ok = -1;
|
||||
|
||||
*product = NULL;
|
||||
|
||||
if (HidD_GetProductString(dev, &buf, sizeof(buf)) == false) {
|
||||
fido_log_debug("%s: HidD_GetProductString", __func__);
|
||||
goto fail;
|
||||
@ -177,9 +195,7 @@ get_str(HANDLE dev, char **manufacturer, char **product)
|
||||
ok = 0;
|
||||
fail:
|
||||
if (ok < 0) {
|
||||
free(*manufacturer);
|
||||
free(*product);
|
||||
*manufacturer = NULL;
|
||||
*product = NULL;
|
||||
}
|
||||
|
||||
@ -313,9 +329,23 @@ copy_info(fido_dev_info_t *di, HDEVINFO devinfo, DWORD idx,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (get_int(dev, &di->vendor_id, &di->product_id) < 0 ||
|
||||
get_str(dev, &di->manufacturer, &di->product) < 0) {
|
||||
fido_log_debug("%s: get_int/get_str", __func__);
|
||||
if (get_id(dev, &di->vendor_id, &di->product_id) < 0) {
|
||||
fido_log_debug("%s: get_id", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (get_manufacturer(dev, &di->manufacturer) < 0) {
|
||||
fido_log_debug("%s: get_manufacturer", __func__);
|
||||
di->manufacturer = strdup("");
|
||||
}
|
||||
|
||||
if (get_product(dev, &di->product) < 0) {
|
||||
fido_log_debug("%s: get_product", __func__);
|
||||
di->product = strdup("");
|
||||
}
|
||||
|
||||
if (di->manufacturer == NULL || di->product == NULL) {
|
||||
fido_log_debug("%s: manufacturer/product", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
81
src/info.c
81
src/info.c
@ -186,14 +186,6 @@ decode_algorithm_entry(const cbor_item_t *key, const cbor_item_t *val,
|
||||
return (ok);
|
||||
}
|
||||
|
||||
static void
|
||||
free_algo(fido_algo_t *a)
|
||||
{
|
||||
free(a->type);
|
||||
a->type = NULL;
|
||||
a->cose = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_algorithm(const cbor_item_t *item, void *arg)
|
||||
{
|
||||
@ -210,7 +202,7 @@ decode_algorithm(const cbor_item_t *item, void *arg)
|
||||
|
||||
if (cbor_map_iter(item, &aa->ptr[i], decode_algorithm_entry) < 0) {
|
||||
fido_log_debug("%s: decode_algorithm_entry", __func__);
|
||||
free_algo(&aa->ptr[i]);
|
||||
fido_algo_free(&aa->ptr[i]);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -287,13 +279,13 @@ parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_get_cbor_info_tx(fido_dev_t *dev)
|
||||
fido_dev_get_cbor_info_tx(fido_dev_t *dev, int *ms)
|
||||
{
|
||||
const unsigned char cbor[] = { CTAP_CBOR_GETINFO };
|
||||
|
||||
fido_log_debug("%s: dev=%p", __func__, (void *)dev);
|
||||
|
||||
if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor)) < 0) {
|
||||
if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor), ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
return (FIDO_ERR_TX);
|
||||
}
|
||||
@ -302,13 +294,13 @@ fido_dev_get_cbor_info_tx(fido_dev_t *dev)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
|
||||
fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
|
||||
fido_log_debug("%s: dev=%p, ci=%p, ms=%d", __func__, (void *)dev,
|
||||
(void *)ci, ms);
|
||||
(void *)ci, *ms);
|
||||
|
||||
fido_cbor_info_reset(ci);
|
||||
|
||||
@ -323,7 +315,7 @@ fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
|
||||
}
|
||||
|
||||
int
|
||||
fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
|
||||
fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -331,7 +323,7 @@ fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
|
||||
if (dev->flags & FIDO_DEV_WINHELLO)
|
||||
return (fido_winhello_get_cbor_info(dev, ci));
|
||||
#endif
|
||||
if ((r = fido_dev_get_cbor_info_tx(dev)) != FIDO_OK ||
|
||||
if ((r = fido_dev_get_cbor_info_tx(dev, ms)) != FIDO_OK ||
|
||||
(r = fido_dev_get_cbor_info_rx(dev, ci, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -341,7 +333,9 @@ fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
|
||||
int
|
||||
fido_dev_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
|
||||
{
|
||||
return (fido_dev_get_cbor_info_wait(dev, ci, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (fido_dev_get_cbor_info_wait(dev, ci, &ms));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -354,58 +348,15 @@ fido_cbor_info_new(void)
|
||||
return (calloc(1, sizeof(fido_cbor_info_t)));
|
||||
}
|
||||
|
||||
static void
|
||||
free_str_array(fido_str_array_t *sa)
|
||||
{
|
||||
for (size_t i = 0; i < sa->len; i++)
|
||||
free(sa->ptr[i]);
|
||||
|
||||
free(sa->ptr);
|
||||
sa->ptr = NULL;
|
||||
sa->len = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_opt_array(fido_opt_array_t *oa)
|
||||
{
|
||||
for (size_t i = 0; i < oa->len; i++)
|
||||
free(oa->name[i]);
|
||||
|
||||
free(oa->name);
|
||||
free(oa->value);
|
||||
oa->name = NULL;
|
||||
oa->value = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
free_byte_array(fido_byte_array_t *ba)
|
||||
{
|
||||
free(ba->ptr);
|
||||
|
||||
ba->ptr = NULL;
|
||||
ba->len = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_algo_array(fido_algo_array_t *aa)
|
||||
{
|
||||
for (size_t i = 0; i < aa->len; i++)
|
||||
free_algo(&aa->ptr[i]);
|
||||
|
||||
free(aa->ptr);
|
||||
aa->ptr = NULL;
|
||||
aa->len = 0;
|
||||
}
|
||||
|
||||
void
|
||||
fido_cbor_info_reset(fido_cbor_info_t *ci)
|
||||
{
|
||||
free_str_array(&ci->versions);
|
||||
free_str_array(&ci->extensions);
|
||||
free_str_array(&ci->transports);
|
||||
free_opt_array(&ci->options);
|
||||
free_byte_array(&ci->protocols);
|
||||
free_algo_array(&ci->algorithms);
|
||||
fido_str_array_free(&ci->versions);
|
||||
fido_str_array_free(&ci->extensions);
|
||||
fido_str_array_free(&ci->transports);
|
||||
fido_opt_array_free(&ci->options);
|
||||
fido_byte_array_free(&ci->protocols);
|
||||
fido_algo_array_free(&ci->algorithms);
|
||||
}
|
||||
|
||||
void
|
||||
|
106
src/io.c
106
src/io.c
@ -30,7 +30,24 @@ struct frame {
|
||||
#endif
|
||||
|
||||
static int
|
||||
tx_empty(fido_dev_t *d, uint8_t cmd)
|
||||
tx_pkt(fido_dev_t *d, const void *pkt, size_t len, int *ms)
|
||||
{
|
||||
struct timespec ts;
|
||||
int n;
|
||||
|
||||
if (fido_time_now(&ts) != 0)
|
||||
return (-1);
|
||||
|
||||
n = d->io.write(d->io_handle, pkt, len);
|
||||
|
||||
if (fido_time_delta(&ts, ms) != 0)
|
||||
return (-1);
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
static int
|
||||
tx_empty(fido_dev_t *d, uint8_t cmd, int *ms)
|
||||
{
|
||||
struct frame *fp;
|
||||
unsigned char pkt[sizeof(*fp) + 1];
|
||||
@ -42,15 +59,15 @@ tx_empty(fido_dev_t *d, uint8_t cmd)
|
||||
fp->cid = d->cid;
|
||||
fp->body.init.cmd = CTAP_FRAME_INIT | cmd;
|
||||
|
||||
if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt,
|
||||
len)) < 0 || (size_t)n != len)
|
||||
if (len > sizeof(pkt) || (n = tx_pkt(d, pkt, len, ms)) < 0 ||
|
||||
(size_t)n != len)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static size_t
|
||||
tx_preamble(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count)
|
||||
tx_preamble(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count, int *ms)
|
||||
{
|
||||
struct frame *fp;
|
||||
unsigned char pkt[sizeof(*fp) + 1];
|
||||
@ -69,15 +86,15 @@ tx_preamble(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count)
|
||||
count = MIN(count, d->tx_len - CTAP_INIT_HEADER_LEN);
|
||||
memcpy(&fp->body.init.data, buf, count);
|
||||
|
||||
if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt,
|
||||
len)) < 0 || (size_t)n != len)
|
||||
if (len > sizeof(pkt) || (n = tx_pkt(d, pkt, len, ms)) < 0 ||
|
||||
(size_t)n != len)
|
||||
return (0);
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
static size_t
|
||||
tx_frame(fido_dev_t *d, uint8_t seq, const void *buf, size_t count)
|
||||
tx_frame(fido_dev_t *d, uint8_t seq, const void *buf, size_t count, int *ms)
|
||||
{
|
||||
struct frame *fp;
|
||||
unsigned char pkt[sizeof(*fp) + 1];
|
||||
@ -94,19 +111,19 @@ tx_frame(fido_dev_t *d, uint8_t seq, const void *buf, size_t count)
|
||||
count = MIN(count, d->tx_len - CTAP_CONT_HEADER_LEN);
|
||||
memcpy(&fp->body.cont.data, buf, count);
|
||||
|
||||
if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt,
|
||||
len)) < 0 || (size_t)n != len)
|
||||
if (len > sizeof(pkt) || (n = tx_pkt(d, pkt, len, ms)) < 0 ||
|
||||
(size_t)n != len)
|
||||
return (0);
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
static int
|
||||
tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count)
|
||||
tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count, int *ms)
|
||||
{
|
||||
size_t n, sent;
|
||||
|
||||
if ((sent = tx_preamble(d, cmd, buf, count)) == 0) {
|
||||
if ((sent = tx_preamble(d, cmd, buf, count, ms)) == 0) {
|
||||
fido_log_debug("%s: tx_preamble", __func__);
|
||||
return (-1);
|
||||
}
|
||||
@ -116,7 +133,8 @@ tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count)
|
||||
fido_log_debug("%s: seq & 0x80", __func__);
|
||||
return (-1);
|
||||
}
|
||||
if ((n = tx_frame(d, seq++, buf + sent, count - sent)) == 0) {
|
||||
if ((n = tx_frame(d, seq++, buf + sent, count - sent,
|
||||
ms)) == 0) {
|
||||
fido_log_debug("%s: tx_frame", __func__);
|
||||
return (-1);
|
||||
}
|
||||
@ -125,38 +143,59 @@ tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
transport_tx(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count, int *ms)
|
||||
{
|
||||
struct timespec ts;
|
||||
int n;
|
||||
|
||||
if (fido_time_now(&ts) != 0)
|
||||
return (-1);
|
||||
|
||||
n = d->transport.tx(d, cmd, buf, count);
|
||||
|
||||
if (fido_time_delta(&ts, ms) != 0)
|
||||
return (-1);
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
int
|
||||
fido_tx(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count)
|
||||
fido_tx(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count, int *ms)
|
||||
{
|
||||
fido_log_debug("%s: dev=%p, cmd=0x%02x", __func__, (void *)d, cmd);
|
||||
fido_log_xxd(buf, count, "%s", __func__);
|
||||
|
||||
if (d->transport.tx != NULL)
|
||||
return (d->transport.tx(d, cmd, buf, count));
|
||||
return (transport_tx(d, cmd, buf, count, ms));
|
||||
if (d->io_handle == NULL || d->io.write == NULL || count > UINT16_MAX) {
|
||||
fido_log_debug("%s: invalid argument", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (count == 0 ? tx_empty(d, cmd) : tx(d, cmd, buf, count));
|
||||
return (count == 0 ? tx_empty(d, cmd, ms) : tx(d, cmd, buf, count, ms));
|
||||
}
|
||||
|
||||
static int
|
||||
rx_frame(fido_dev_t *d, struct frame *fp, int ms)
|
||||
rx_frame(fido_dev_t *d, struct frame *fp, int *ms)
|
||||
{
|
||||
struct timespec ts;
|
||||
int n;
|
||||
|
||||
memset(fp, 0, sizeof(*fp));
|
||||
|
||||
if (d->rx_len > sizeof(*fp) || (n = d->io.read(d->io_handle,
|
||||
(unsigned char *)fp, d->rx_len, ms)) < 0 || (size_t)n != d->rx_len)
|
||||
if (fido_time_now(&ts) != 0)
|
||||
return (-1);
|
||||
|
||||
return (0);
|
||||
if (d->rx_len > sizeof(*fp) || (n = d->io.read(d->io_handle,
|
||||
(unsigned char *)fp, d->rx_len, *ms)) < 0 || (size_t)n != d->rx_len)
|
||||
return (-1);
|
||||
|
||||
return (fido_time_delta(&ts, ms));
|
||||
}
|
||||
|
||||
static int
|
||||
rx_preamble(fido_dev_t *d, uint8_t cmd, struct frame *fp, int ms)
|
||||
rx_preamble(fido_dev_t *d, uint8_t cmd, struct frame *fp, int *ms)
|
||||
{
|
||||
do {
|
||||
if (rx_frame(d, fp, ms) < 0)
|
||||
@ -185,7 +224,7 @@ rx_preamble(fido_dev_t *d, uint8_t cmd, struct frame *fp, int ms)
|
||||
}
|
||||
|
||||
static int
|
||||
rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms)
|
||||
rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int *ms)
|
||||
{
|
||||
struct frame f;
|
||||
size_t r, payload_len, init_data_len, cont_data_len;
|
||||
@ -252,16 +291,33 @@ rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms)
|
||||
return ((int)r);
|
||||
}
|
||||
|
||||
static int
|
||||
transport_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int *ms)
|
||||
{
|
||||
struct timespec ts;
|
||||
int n;
|
||||
|
||||
if (fido_time_now(&ts) != 0)
|
||||
return (-1);
|
||||
|
||||
n = d->transport.rx(d, cmd, buf, count, *ms);
|
||||
|
||||
if (fido_time_delta(&ts, ms) != 0)
|
||||
return (-1);
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
int
|
||||
fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms)
|
||||
fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int *ms)
|
||||
{
|
||||
int n;
|
||||
|
||||
fido_log_debug("%s: dev=%p, cmd=0x%02x, ms=%d", __func__, (void *)d,
|
||||
cmd, ms);
|
||||
cmd, *ms);
|
||||
|
||||
if (d->transport.rx != NULL)
|
||||
return (d->transport.rx(d, cmd, buf, count, ms));
|
||||
return (transport_rx(d, cmd, buf, count, ms));
|
||||
if (d->io_handle == NULL || d->io.read == NULL || count > UINT16_MAX) {
|
||||
fido_log_debug("%s: invalid argument", __func__);
|
||||
return (-1);
|
||||
@ -273,7 +329,7 @@ fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms)
|
||||
}
|
||||
|
||||
int
|
||||
fido_rx_cbor_status(fido_dev_t *d, int ms)
|
||||
fido_rx_cbor_status(fido_dev_t *d, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
|
@ -59,6 +59,6 @@ iso7816_ptr(const iso7816_apdu_t *apdu)
|
||||
size_t
|
||||
iso7816_len(const iso7816_apdu_t *apdu)
|
||||
{
|
||||
return apdu->alloc_len - sizeof(apdu->alloc_len) -
|
||||
sizeof(apdu->payload_len) - sizeof(apdu->payload_ptr);
|
||||
return apdu->alloc_len - offsetof(iso7816_apdu_t, header) -
|
||||
(sizeof(iso7816_apdu_t) - offsetof(iso7816_apdu_t, payload));
|
||||
}
|
||||
|
@ -27,14 +27,13 @@ struct iso7816_header {
|
||||
uint8_t lc3;
|
||||
})
|
||||
|
||||
PACKED_TYPE(iso7816_apdu_t,
|
||||
struct iso7816_apdu {
|
||||
typedef struct iso7816_apdu {
|
||||
size_t alloc_len;
|
||||
uint16_t payload_len;
|
||||
uint8_t *payload_ptr;
|
||||
iso7816_header_t header;
|
||||
uint8_t payload[];
|
||||
})
|
||||
} iso7816_apdu_t;
|
||||
|
||||
const unsigned char *iso7816_ptr(const iso7816_apdu_t *);
|
||||
int iso7816_add(iso7816_apdu_t *, const void *, size_t);
|
||||
|
@ -153,7 +153,7 @@ largeblob_seal(largeblob_t *blob, const fido_blob_t *body,
|
||||
}
|
||||
|
||||
static int
|
||||
largeblob_get_tx(fido_dev_t *dev, size_t offset, size_t count)
|
||||
largeblob_get_tx(fido_dev_t *dev, size_t offset, size_t count, int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
cbor_item_t *argv[3];
|
||||
@ -169,7 +169,7 @@ largeblob_get_tx(fido_dev_t *dev, size_t offset, size_t count)
|
||||
goto fail;
|
||||
}
|
||||
if (cbor_build_frame(CTAP_CBOR_LARGEBLOB, argv, nitems(argv), &f) < 0 ||
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -198,7 +198,7 @@ parse_largeblob_reply(const cbor_item_t *key, const cbor_item_t *val,
|
||||
}
|
||||
|
||||
static int
|
||||
largeblob_get_rx(fido_dev_t *dev, fido_blob_t **chunk, int ms)
|
||||
largeblob_get_rx(fido_dev_t *dev, fido_blob_t **chunk, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len, r;
|
||||
@ -419,7 +419,7 @@ largeblob_array_check(const fido_blob_t *array)
|
||||
}
|
||||
|
||||
static int
|
||||
largeblob_get_array(fido_dev_t *dev, cbor_item_t **item)
|
||||
largeblob_get_array(fido_dev_t *dev, cbor_item_t **item, int *ms)
|
||||
{
|
||||
fido_blob_t *array, *chunk = NULL;
|
||||
size_t n;
|
||||
@ -432,8 +432,8 @@ largeblob_get_array(fido_dev_t *dev, cbor_item_t **item)
|
||||
return FIDO_ERR_INTERNAL;
|
||||
do {
|
||||
fido_blob_free(&chunk);
|
||||
if ((r = largeblob_get_tx(dev, array->len, n)) != FIDO_OK ||
|
||||
(r = largeblob_get_rx(dev, &chunk, -1)) != FIDO_OK) {
|
||||
if ((r = largeblob_get_tx(dev, array->len, n, ms)) != FIDO_OK ||
|
||||
(r = largeblob_get_rx(dev, &chunk, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: largeblob_get_wait %zu/%zu",
|
||||
__func__, array->len, n);
|
||||
goto fail;
|
||||
@ -491,7 +491,7 @@ prepare_hmac(size_t offset, const u_char *data, size_t len, fido_blob_t *hmac)
|
||||
|
||||
static int
|
||||
largeblob_set_tx(fido_dev_t *dev, const fido_blob_t *token, const u_char *chunk,
|
||||
size_t chunk_len, size_t offset, size_t totalsiz)
|
||||
size_t chunk_len, size_t offset, size_t totalsiz, int *ms)
|
||||
{
|
||||
fido_blob_t *hmac = NULL, f;
|
||||
cbor_item_t *argv[6];
|
||||
@ -518,7 +518,7 @@ largeblob_set_tx(fido_dev_t *dev, const fido_blob_t *token, const u_char *chunk,
|
||||
}
|
||||
}
|
||||
if (cbor_build_frame(CTAP_CBOR_LARGEBLOB, argv, nitems(argv), &f) < 0 ||
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -534,7 +534,8 @@ largeblob_set_tx(fido_dev_t *dev, const fido_blob_t *token, const u_char *chunk,
|
||||
}
|
||||
|
||||
static int
|
||||
largeblob_get_uv_token(fido_dev_t *dev, const char *pin, fido_blob_t **token)
|
||||
largeblob_get_uv_token(fido_dev_t *dev, const char *pin, fido_blob_t **token,
|
||||
int *ms)
|
||||
{
|
||||
es256_pk_t *pk = NULL;
|
||||
fido_blob_t *ecdh = NULL;
|
||||
@ -542,12 +543,12 @@ largeblob_get_uv_token(fido_dev_t *dev, const char *pin, fido_blob_t **token)
|
||||
|
||||
if ((*token = fido_blob_new()) == NULL)
|
||||
return FIDO_ERR_INTERNAL;
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_do_ecdh", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((r = fido_dev_get_uv_token(dev, CTAP_CBOR_LARGEBLOB, pin, ecdh, pk,
|
||||
NULL, *token)) != FIDO_OK) {
|
||||
NULL, *token, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_dev_get_uv_token", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -564,7 +565,8 @@ largeblob_get_uv_token(fido_dev_t *dev, const char *pin, fido_blob_t **token)
|
||||
}
|
||||
|
||||
static int
|
||||
largeblob_set_array(fido_dev_t *dev, const cbor_item_t *item, const char *pin)
|
||||
largeblob_set_array(fido_dev_t *dev, const cbor_item_t *item, const char *pin,
|
||||
int *ms)
|
||||
{
|
||||
unsigned char dgst[SHA256_DIGEST_LENGTH];
|
||||
fido_blob_t cbor, *token = NULL;
|
||||
@ -600,7 +602,8 @@ largeblob_set_array(fido_dev_t *dev, const cbor_item_t *item, const char *pin)
|
||||
}
|
||||
totalsize = cbor.len + sizeof(dgst) - 16; /* the first 16 bytes only */
|
||||
if (pin != NULL || fido_dev_supports_permissions(dev)) {
|
||||
if ((r = largeblob_get_uv_token(dev, pin, &token)) != FIDO_OK) {
|
||||
if ((r = largeblob_get_uv_token(dev, pin, &token,
|
||||
ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: largeblob_get_uv_token", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -609,15 +612,15 @@ largeblob_set_array(fido_dev_t *dev, const cbor_item_t *item, const char *pin)
|
||||
if ((chunklen = cbor.len - offset) > maxchunklen)
|
||||
chunklen = maxchunklen;
|
||||
if ((r = largeblob_set_tx(dev, token, cbor.ptr + offset,
|
||||
chunklen, offset, totalsize)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, -1)) != FIDO_OK) {
|
||||
chunklen, offset, totalsize, ms)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: body", __func__);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if ((r = largeblob_set_tx(dev, token, dgst, sizeof(dgst) - 16, cbor.len,
|
||||
totalsize)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, -1)) != FIDO_OK) {
|
||||
totalsize, ms)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: dgst", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -632,13 +635,13 @@ largeblob_set_array(fido_dev_t *dev, const cbor_item_t *item, const char *pin)
|
||||
|
||||
static int
|
||||
largeblob_add(fido_dev_t *dev, const fido_blob_t *key, cbor_item_t *item,
|
||||
const char *pin)
|
||||
const char *pin, int *ms)
|
||||
{
|
||||
cbor_item_t *array = NULL;
|
||||
size_t idx;
|
||||
int r;
|
||||
|
||||
if ((r = largeblob_get_array(dev, &array)) != FIDO_OK) {
|
||||
if ((r = largeblob_get_array(dev, &array, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: largeblob_get_array", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -661,7 +664,7 @@ largeblob_add(fido_dev_t *dev, const fido_blob_t *key, cbor_item_t *item,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((r = largeblob_set_array(dev, array, pin)) != FIDO_OK) {
|
||||
if ((r = largeblob_set_array(dev, array, pin, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: largeblob_set_array", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -675,13 +678,14 @@ largeblob_add(fido_dev_t *dev, const fido_blob_t *key, cbor_item_t *item,
|
||||
}
|
||||
|
||||
static int
|
||||
largeblob_drop(fido_dev_t *dev, const fido_blob_t *key, const char *pin)
|
||||
largeblob_drop(fido_dev_t *dev, const fido_blob_t *key, const char *pin,
|
||||
int *ms)
|
||||
{
|
||||
cbor_item_t *array = NULL;
|
||||
size_t idx;
|
||||
int r;
|
||||
|
||||
if ((r = largeblob_get_array(dev, &array)) != FIDO_OK) {
|
||||
if ((r = largeblob_get_array(dev, &array, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: largeblob_get_array", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -694,7 +698,7 @@ largeblob_drop(fido_dev_t *dev, const fido_blob_t *key, const char *pin)
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
}
|
||||
if ((r = largeblob_set_array(dev, array, pin)) != FIDO_OK) {
|
||||
if ((r = largeblob_set_array(dev, array, pin, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: largeblob_set_array", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -713,6 +717,7 @@ fido_dev_largeblob_get(fido_dev_t *dev, const unsigned char *key_ptr,
|
||||
{
|
||||
cbor_item_t *item = NULL;
|
||||
fido_blob_t key, body;
|
||||
int ms = dev->timeout_ms;
|
||||
int r;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
@ -733,7 +738,7 @@ fido_dev_largeblob_get(fido_dev_t *dev, const unsigned char *key_ptr,
|
||||
fido_log_debug("%s: fido_blob_set", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
if ((r = largeblob_get_array(dev, &item)) != FIDO_OK) {
|
||||
if ((r = largeblob_get_array(dev, &item, &ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: largeblob_get_array", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -759,6 +764,7 @@ fido_dev_largeblob_set(fido_dev_t *dev, const unsigned char *key_ptr,
|
||||
{
|
||||
cbor_item_t *item = NULL;
|
||||
fido_blob_t key, body;
|
||||
int ms = dev->timeout_ms;
|
||||
int r;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
@ -784,7 +790,7 @@ fido_dev_largeblob_set(fido_dev_t *dev, const unsigned char *key_ptr,
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
}
|
||||
if ((r = largeblob_add(dev, &key, item, pin)) != FIDO_OK)
|
||||
if ((r = largeblob_add(dev, &key, item, pin, &ms)) != FIDO_OK)
|
||||
fido_log_debug("%s: largeblob_add", __func__);
|
||||
fail:
|
||||
if (item != NULL)
|
||||
@ -801,6 +807,7 @@ fido_dev_largeblob_remove(fido_dev_t *dev, const unsigned char *key_ptr,
|
||||
size_t key_len, const char *pin)
|
||||
{
|
||||
fido_blob_t key;
|
||||
int ms = dev->timeout_ms;
|
||||
int r;
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
@ -813,7 +820,7 @@ fido_dev_largeblob_remove(fido_dev_t *dev, const unsigned char *key_ptr,
|
||||
fido_log_debug("%s: fido_blob_set", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
if ((r = largeblob_drop(dev, &key, pin)) != FIDO_OK)
|
||||
if ((r = largeblob_drop(dev, &key, pin, &ms)) != FIDO_OK)
|
||||
fido_log_debug("%s: largeblob_drop", __func__);
|
||||
|
||||
fido_blob_reset(&key);
|
||||
@ -827,6 +834,7 @@ fido_dev_largeblob_get_array(fido_dev_t *dev, unsigned char **cbor_ptr,
|
||||
{
|
||||
cbor_item_t *item = NULL;
|
||||
fido_blob_t cbor;
|
||||
int ms = dev->timeout_ms;
|
||||
int r;
|
||||
|
||||
memset(&cbor, 0, sizeof(cbor));
|
||||
@ -838,7 +846,7 @@ fido_dev_largeblob_get_array(fido_dev_t *dev, unsigned char **cbor_ptr,
|
||||
}
|
||||
*cbor_ptr = NULL;
|
||||
*cbor_len = 0;
|
||||
if ((r = largeblob_get_array(dev, &item)) != FIDO_OK) {
|
||||
if ((r = largeblob_get_array(dev, &item, &ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: largeblob_get_array", __func__);
|
||||
return r;
|
||||
}
|
||||
@ -861,6 +869,7 @@ fido_dev_largeblob_set_array(fido_dev_t *dev, const unsigned char *cbor_ptr,
|
||||
{
|
||||
cbor_item_t *item = NULL;
|
||||
struct cbor_load_result cbor_result;
|
||||
int ms = dev->timeout_ms;
|
||||
int r;
|
||||
|
||||
if (cbor_ptr == NULL || cbor_len == 0) {
|
||||
@ -872,7 +881,7 @@ fido_dev_largeblob_set_array(fido_dev_t *dev, const unsigned char *cbor_ptr,
|
||||
fido_log_debug("%s: cbor_load", __func__);
|
||||
return FIDO_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
if ((r = largeblob_set_array(dev, item, pin)) != FIDO_OK)
|
||||
if ((r = largeblob_set_array(dev, item, pin, &ms)) != FIDO_OK)
|
||||
fido_log_debug("%s: largeblob_set_array", __func__);
|
||||
|
||||
cbor_decref(&item);
|
||||
|
@ -30,6 +30,8 @@ static ssize_t (*fuzz_write)(int, const void *, size_t);
|
||||
#define SOL_NETLINK 270
|
||||
#endif
|
||||
|
||||
#define NETLINK_POLL_MS 100
|
||||
|
||||
/* XXX avoid signed NLA_ALIGNTO */
|
||||
#undef NLA_HDRLEN
|
||||
#define NLA_HDRLEN NLMSG_ALIGN(sizeof(struct nlattr))
|
||||
@ -694,7 +696,7 @@ fido_nl_get_nfc_target(fido_nl_t *nl, uint32_t dev, uint32_t *target)
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
r = nlmsg_rx(nl->fd, reply, sizeof(reply), -1);
|
||||
r = nlmsg_rx(nl->fd, reply, sizeof(reply), NETLINK_POLL_MS);
|
||||
#ifndef FIDO_FUZZ
|
||||
if (setsockopt(nl->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP,
|
||||
&nl->nfc_mcastgrp, sizeof(nl->nfc_mcastgrp)) == -1) {
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <errno.h>
|
||||
#include <libudev.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fido.h"
|
||||
@ -218,16 +220,23 @@ tx_get_response(fido_dev_t *d, uint8_t count)
|
||||
}
|
||||
|
||||
static int
|
||||
rx_apdu(fido_dev_t *d, uint8_t sw[2], unsigned char **buf, size_t *count, int ms)
|
||||
rx_apdu(fido_dev_t *d, uint8_t sw[2], unsigned char **buf, size_t *count, int *ms)
|
||||
{
|
||||
uint8_t f[256 + 2];
|
||||
struct timespec ts;
|
||||
int n, ok = -1;
|
||||
|
||||
if ((n = d->io.read(d->io_handle, f, sizeof(f), ms)) < 2) {
|
||||
if (fido_time_now(&ts) != 0)
|
||||
goto fail;
|
||||
|
||||
if ((n = d->io.read(d->io_handle, f, sizeof(f), *ms)) < 2) {
|
||||
fido_log_debug("%s: read", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fido_time_delta(&ts, ms) != 0)
|
||||
goto fail;
|
||||
|
||||
if (fido_buf_write(buf, count, f, (size_t)(n - 2)) < 0) {
|
||||
fido_log_debug("%s: fido_buf_write", __func__);
|
||||
goto fail;
|
||||
@ -248,14 +257,14 @@ rx_msg(fido_dev_t *d, unsigned char *buf, size_t count, int ms)
|
||||
uint8_t sw[2];
|
||||
const size_t bufsiz = count;
|
||||
|
||||
if (rx_apdu(d, sw, &buf, &count, ms) < 0) {
|
||||
if (rx_apdu(d, sw, &buf, &count, &ms) < 0) {
|
||||
fido_log_debug("%s: preamble", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
while (sw[0] == SW1_MORE_DATA)
|
||||
if (tx_get_response(d, sw[1]) < 0 ||
|
||||
rx_apdu(d, sw, &buf, &count, ms) < 0) {
|
||||
rx_apdu(d, sw, &buf, &count, &ms) < 0) {
|
||||
fido_log_debug("%s: chain", __func__);
|
||||
return (-1);
|
||||
}
|
||||
@ -347,6 +356,7 @@ copy_info(fido_dev_info_t *di, struct udev *udev,
|
||||
const char *name;
|
||||
char *str;
|
||||
struct udev_device *dev = NULL;
|
||||
void *ctx = NULL;
|
||||
int id, ok = -1;
|
||||
|
||||
memset(di, 0, sizeof(*di));
|
||||
@ -354,27 +364,35 @@ copy_info(fido_dev_info_t *di, struct udev *udev,
|
||||
if ((name = udev_list_entry_get_name(udev_entry)) == NULL ||
|
||||
(dev = udev_device_new_from_syspath(udev, name)) == NULL)
|
||||
goto fail;
|
||||
|
||||
if ((di->path = strdup(name)) == NULL ||
|
||||
(di->manufacturer = get_usb_attr(dev, "manufacturer")) == NULL ||
|
||||
(di->product = get_usb_attr(dev, "product")) == NULL)
|
||||
if (asprintf(&di->path, "%s/%s", FIDO_NFC_PREFIX, name) == -1)
|
||||
goto fail;
|
||||
if ((di->manufacturer = get_usb_attr(dev, "manufacturer")) == NULL)
|
||||
di->manufacturer = strdup("");
|
||||
if ((di->product = get_usb_attr(dev, "product")) == NULL)
|
||||
di->product = strdup("");
|
||||
if (di->manufacturer == NULL || di->product == NULL)
|
||||
goto fail;
|
||||
|
||||
/* XXX assumes USB for vendor/product info */
|
||||
if ((str = get_usb_attr(dev, "idVendor")) != NULL &&
|
||||
(id = to_int(str, 16)) > 0 && id <= UINT16_MAX)
|
||||
di->vendor_id = (int16_t)id;
|
||||
free(str);
|
||||
|
||||
if ((str = get_usb_attr(dev, "idProduct")) != NULL &&
|
||||
(id = to_int(str, 16)) > 0 && id <= UINT16_MAX)
|
||||
di->product_id = (int16_t)id;
|
||||
free(str);
|
||||
|
||||
if ((ctx = fido_nfc_open(di->path)) == NULL) {
|
||||
fido_log_debug("%s: fido_nfc_open", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
if (dev != NULL)
|
||||
udev_device_unref(dev);
|
||||
if (ctx != NULL)
|
||||
fido_nfc_close(ctx);
|
||||
|
||||
if (ok < 0) {
|
||||
free(di->path);
|
||||
@ -532,7 +550,11 @@ fido_nfc_open(const char *path)
|
||||
struct nfc_linux *ctx = NULL;
|
||||
int idx;
|
||||
|
||||
if ((idx = sysnum_from_syspath(path)) < 0 ||
|
||||
if (strncmp(path, FIDO_NFC_PREFIX, strlen(FIDO_NFC_PREFIX)) != 0) {
|
||||
fido_log_debug("%s: bad prefix", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((idx = sysnum_from_syspath(path + strlen(FIDO_NFC_PREFIX))) < 0 ||
|
||||
(ctx = nfc_new((uint32_t)idx)) == NULL) {
|
||||
fido_log_debug("%s: nfc_new", __func__);
|
||||
goto fail;
|
||||
|
72
src/pin.c
72
src/pin.c
@ -146,7 +146,7 @@ encode_uv_permission(uint8_t cmd)
|
||||
|
||||
static int
|
||||
ctap20_uv_token_tx(fido_dev_t *dev, const char *pin, const fido_blob_t *ecdh,
|
||||
const es256_pk_t *pk)
|
||||
const es256_pk_t *pk, int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
fido_blob_t *p = NULL;
|
||||
@ -185,7 +185,7 @@ ctap20_uv_token_tx(fido_dev_t *dev, const char *pin, const fido_blob_t *ecdh,
|
||||
}
|
||||
|
||||
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -203,7 +203,7 @@ ctap20_uv_token_tx(fido_dev_t *dev, const char *pin, const fido_blob_t *ecdh,
|
||||
|
||||
static int
|
||||
ctap21_uv_token_tx(fido_dev_t *dev, const char *pin, const fido_blob_t *ecdh,
|
||||
const es256_pk_t *pk, uint8_t cmd, const char *rpid)
|
||||
const es256_pk_t *pk, uint8_t cmd, const char *rpid, int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
fido_blob_t *p = NULL;
|
||||
@ -248,7 +248,7 @@ ctap21_uv_token_tx(fido_dev_t *dev, const char *pin, const fido_blob_t *ecdh,
|
||||
}
|
||||
|
||||
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -281,7 +281,7 @@ parse_uv_token(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
|
||||
static int
|
||||
uv_token_rx(fido_dev_t *dev, const fido_blob_t *ecdh, fido_blob_t *token,
|
||||
int ms)
|
||||
int *ms)
|
||||
{
|
||||
fido_blob_t *aes_token = NULL;
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
@ -322,16 +322,16 @@ uv_token_rx(fido_dev_t *dev, const fido_blob_t *ecdh, fido_blob_t *token,
|
||||
static int
|
||||
uv_token_wait(fido_dev_t *dev, uint8_t cmd, const char *pin,
|
||||
const fido_blob_t *ecdh, const es256_pk_t *pk, const char *rpid,
|
||||
fido_blob_t *token, int ms)
|
||||
fido_blob_t *token, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (ecdh == NULL || pk == NULL)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
if (fido_dev_supports_permissions(dev))
|
||||
r = ctap21_uv_token_tx(dev, pin, ecdh, pk, cmd, rpid);
|
||||
r = ctap21_uv_token_tx(dev, pin, ecdh, pk, cmd, rpid, ms);
|
||||
else
|
||||
r = ctap20_uv_token_tx(dev, pin, ecdh, pk);
|
||||
r = ctap20_uv_token_tx(dev, pin, ecdh, pk, ms);
|
||||
if (r != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -341,13 +341,14 @@ uv_token_wait(fido_dev_t *dev, uint8_t cmd, const char *pin,
|
||||
int
|
||||
fido_dev_get_uv_token(fido_dev_t *dev, uint8_t cmd, const char *pin,
|
||||
const fido_blob_t *ecdh, const es256_pk_t *pk, const char *rpid,
|
||||
fido_blob_t *token)
|
||||
fido_blob_t *token, int *ms)
|
||||
{
|
||||
return (uv_token_wait(dev, cmd, pin, ecdh, pk, rpid, token, -1));
|
||||
return (uv_token_wait(dev, cmd, pin, ecdh, pk, rpid, token, ms));
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_change_pin_tx(fido_dev_t *dev, const char *pin, const char *oldpin)
|
||||
fido_dev_change_pin_tx(fido_dev_t *dev, const char *pin, const char *oldpin,
|
||||
int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
fido_blob_t *ppine = NULL;
|
||||
@ -368,7 +369,7 @@ fido_dev_change_pin_tx(fido_dev_t *dev, const char *pin, const char *oldpin)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_do_ecdh", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -397,7 +398,7 @@ fido_dev_change_pin_tx(fido_dev_t *dev, const char *pin, const char *oldpin)
|
||||
}
|
||||
|
||||
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -418,7 +419,7 @@ fido_dev_change_pin_tx(fido_dev_t *dev, const char *pin, const char *oldpin)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_set_pin_tx(fido_dev_t *dev, const char *pin)
|
||||
fido_dev_set_pin_tx(fido_dev_t *dev, const char *pin, int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
fido_blob_t *ppine = NULL;
|
||||
@ -430,7 +431,7 @@ fido_dev_set_pin_tx(fido_dev_t *dev, const char *pin)
|
||||
memset(&f, 0, sizeof(f));
|
||||
memset(argv, 0, sizeof(argv));
|
||||
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
|
||||
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_do_ecdh", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -451,7 +452,7 @@ fido_dev_set_pin_tx(fido_dev_t *dev, const char *pin)
|
||||
}
|
||||
|
||||
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -470,17 +471,18 @@ fido_dev_set_pin_tx(fido_dev_t *dev, const char *pin)
|
||||
|
||||
static int
|
||||
fido_dev_set_pin_wait(fido_dev_t *dev, const char *pin, const char *oldpin,
|
||||
int ms)
|
||||
int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (oldpin != NULL) {
|
||||
if ((r = fido_dev_change_pin_tx(dev, pin, oldpin)) != FIDO_OK) {
|
||||
if ((r = fido_dev_change_pin_tx(dev, pin, oldpin,
|
||||
ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_dev_change_pin_tx", __func__);
|
||||
return (r);
|
||||
}
|
||||
} else {
|
||||
if ((r = fido_dev_set_pin_tx(dev, pin)) != FIDO_OK) {
|
||||
if ((r = fido_dev_set_pin_tx(dev, pin, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_dev_set_pin_tx", __func__);
|
||||
return (r);
|
||||
}
|
||||
@ -502,7 +504,9 @@ fido_dev_set_pin_wait(fido_dev_t *dev, const char *pin, const char *oldpin,
|
||||
int
|
||||
fido_dev_set_pin(fido_dev_t *dev, const char *pin, const char *oldpin)
|
||||
{
|
||||
return (fido_dev_set_pin_wait(dev, pin, oldpin, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (fido_dev_set_pin_wait(dev, pin, oldpin, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -542,7 +546,7 @@ parse_uv_retry_count(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_get_retry_count_tx(fido_dev_t *dev, uint8_t subcmd)
|
||||
fido_dev_get_retry_count_tx(fido_dev_t *dev, uint8_t subcmd, int *ms)
|
||||
{
|
||||
fido_blob_t f;
|
||||
cbor_item_t *argv[2];
|
||||
@ -558,7 +562,7 @@ fido_dev_get_retry_count_tx(fido_dev_t *dev, uint8_t subcmd)
|
||||
}
|
||||
|
||||
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
|
||||
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -573,7 +577,7 @@ fido_dev_get_retry_count_tx(fido_dev_t *dev, uint8_t subcmd)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_get_pin_retry_count_rx(fido_dev_t *dev, int *retries, int ms)
|
||||
fido_dev_get_pin_retry_count_rx(fido_dev_t *dev, int *retries, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -597,11 +601,11 @@ fido_dev_get_pin_retry_count_rx(fido_dev_t *dev, int *retries, int ms)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_get_pin_retry_count_wait(fido_dev_t *dev, int *retries, int ms)
|
||||
fido_dev_get_pin_retry_count_wait(fido_dev_t *dev, int *retries, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = fido_dev_get_retry_count_tx(dev, 1)) != FIDO_OK ||
|
||||
if ((r = fido_dev_get_retry_count_tx(dev, 1, ms)) != FIDO_OK ||
|
||||
(r = fido_dev_get_pin_retry_count_rx(dev, retries, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -611,11 +615,13 @@ fido_dev_get_pin_retry_count_wait(fido_dev_t *dev, int *retries, int ms)
|
||||
int
|
||||
fido_dev_get_retry_count(fido_dev_t *dev, int *retries)
|
||||
{
|
||||
return (fido_dev_get_pin_retry_count_wait(dev, retries, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (fido_dev_get_pin_retry_count_wait(dev, retries, &ms));
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_get_uv_retry_count_rx(fido_dev_t *dev, int *retries, int ms)
|
||||
fido_dev_get_uv_retry_count_rx(fido_dev_t *dev, int *retries, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -639,11 +645,11 @@ fido_dev_get_uv_retry_count_rx(fido_dev_t *dev, int *retries, int ms)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_get_uv_retry_count_wait(fido_dev_t *dev, int *retries, int ms)
|
||||
fido_dev_get_uv_retry_count_wait(fido_dev_t *dev, int *retries, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = fido_dev_get_retry_count_tx(dev, 7)) != FIDO_OK ||
|
||||
if ((r = fido_dev_get_retry_count_tx(dev, 7, ms)) != FIDO_OK ||
|
||||
(r = fido_dev_get_uv_retry_count_rx(dev, retries, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -653,13 +659,15 @@ fido_dev_get_uv_retry_count_wait(fido_dev_t *dev, int *retries, int ms)
|
||||
int
|
||||
fido_dev_get_uv_retry_count(fido_dev_t *dev, int *retries)
|
||||
{
|
||||
return (fido_dev_get_uv_retry_count_wait(dev, retries, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (fido_dev_get_uv_retry_count_wait(dev, retries, &ms));
|
||||
}
|
||||
|
||||
int
|
||||
cbor_add_uv_params(fido_dev_t *dev, uint8_t cmd, const fido_blob_t *hmac_data,
|
||||
const es256_pk_t *pk, const fido_blob_t *ecdh, const char *pin,
|
||||
const char *rpid, cbor_item_t **auth, cbor_item_t **opt)
|
||||
const char *rpid, cbor_item_t **auth, cbor_item_t **opt, int *ms)
|
||||
{
|
||||
fido_blob_t *token = NULL;
|
||||
int r;
|
||||
@ -670,7 +678,7 @@ cbor_add_uv_params(fido_dev_t *dev, uint8_t cmd, const fido_blob_t *hmac_data,
|
||||
}
|
||||
|
||||
if ((r = fido_dev_get_uv_token(dev, cmd, pin, ecdh, pk, rpid,
|
||||
token)) != FIDO_OK) {
|
||||
token, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_dev_get_uv_token", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
12
src/reset.c
12
src/reset.c
@ -7,11 +7,11 @@
|
||||
#include "fido.h"
|
||||
|
||||
static int
|
||||
fido_dev_reset_tx(fido_dev_t *dev)
|
||||
fido_dev_reset_tx(fido_dev_t *dev, int *ms)
|
||||
{
|
||||
const unsigned char cbor[] = { CTAP_CBOR_RESET };
|
||||
|
||||
if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor)) < 0) {
|
||||
if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor), ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
return (FIDO_ERR_TX);
|
||||
}
|
||||
@ -20,11 +20,11 @@ fido_dev_reset_tx(fido_dev_t *dev)
|
||||
}
|
||||
|
||||
static int
|
||||
fido_dev_reset_wait(fido_dev_t *dev, int ms)
|
||||
fido_dev_reset_wait(fido_dev_t *dev, int *ms)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = fido_dev_reset_tx(dev)) != FIDO_OK ||
|
||||
if ((r = fido_dev_reset_tx(dev, ms)) != FIDO_OK ||
|
||||
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK)
|
||||
return (r);
|
||||
|
||||
@ -39,5 +39,7 @@ fido_dev_reset_wait(fido_dev_t *dev, int ms)
|
||||
int
|
||||
fido_dev_reset(fido_dev_t *dev)
|
||||
{
|
||||
return (fido_dev_reset_wait(dev, -1));
|
||||
int ms = dev->timeout_ms;
|
||||
|
||||
return (fido_dev_reset_wait(dev, &ms));
|
||||
}
|
||||
|
99
src/rs1.c
Normal file
99
src/rs1.c
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
|
||||
#include "fido.h"
|
||||
|
||||
#if defined(LIBRESSL_VERSION_NUMBER)
|
||||
static EVP_MD *
|
||||
rs1_get_EVP_MD(void)
|
||||
{
|
||||
const EVP_MD *from;
|
||||
EVP_MD *to = NULL;
|
||||
|
||||
if ((from = EVP_sha1()) != NULL && (to = malloc(sizeof(*to))) != NULL)
|
||||
memcpy(to, from, sizeof(*to));
|
||||
|
||||
return (to);
|
||||
}
|
||||
|
||||
static void
|
||||
rs1_free_EVP_MD(EVP_MD *md)
|
||||
{
|
||||
freezero(md, sizeof(*md));
|
||||
}
|
||||
#elif OPENSSL_VERSION_NUMBER >= 0x30000000
|
||||
static EVP_MD *
|
||||
rs1_get_EVP_MD(void)
|
||||
{
|
||||
return (EVP_MD_fetch(NULL, "SHA-1", NULL));
|
||||
}
|
||||
|
||||
static void
|
||||
rs1_free_EVP_MD(EVP_MD *md)
|
||||
{
|
||||
EVP_MD_free(md);
|
||||
}
|
||||
#else
|
||||
static EVP_MD *
|
||||
rs1_get_EVP_MD(void)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
|
||||
if ((md = EVP_sha1()) == NULL)
|
||||
return (NULL);
|
||||
|
||||
return (EVP_MD_meth_dup(md));
|
||||
}
|
||||
|
||||
static void
|
||||
rs1_free_EVP_MD(EVP_MD *md)
|
||||
{
|
||||
EVP_MD_meth_free(md);
|
||||
}
|
||||
#endif /* LIBRESSL_VERSION_NUMBER */
|
||||
|
||||
int
|
||||
rs1_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_MD *md = NULL;
|
||||
int ok = -1;
|
||||
|
||||
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
|
||||
fido_log_debug("%s: EVP_PKEY_base_id", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((md = rs1_get_EVP_MD()) == NULL) {
|
||||
fido_log_debug("%s: rs1_get_EVP_MD", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL ||
|
||||
EVP_PKEY_verify_init(pctx) != 1 ||
|
||||
EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) != 1 ||
|
||||
EVP_PKEY_CTX_set_signature_md(pctx, md) != 1) {
|
||||
fido_log_debug("%s: EVP_PKEY_CTX", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr,
|
||||
dgst->len) != 1) {
|
||||
fido_log_debug("%s: EVP_PKEY_verify", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
rs1_free_EVP_MD(md);
|
||||
|
||||
return (ok);
|
||||
}
|
131
src/rs256.c
131
src/rs256.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -11,31 +11,54 @@
|
||||
#include "fido.h"
|
||||
#include "fido/rs256.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
static int
|
||||
RSA_bits(const RSA *r)
|
||||
#if defined(LIBRESSL_VERSION_NUMBER)
|
||||
static EVP_MD *
|
||||
rs256_get_EVP_MD(void)
|
||||
{
|
||||
return (BN_num_bits(r->n));
|
||||
}
|
||||
const EVP_MD *from;
|
||||
EVP_MD *to = NULL;
|
||||
|
||||
static int
|
||||
RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
|
||||
{
|
||||
r->n = n;
|
||||
r->e = e;
|
||||
r->d = d;
|
||||
if ((from = EVP_sha256()) != NULL && (to = malloc(sizeof(*to))) != NULL)
|
||||
memcpy(to, from, sizeof(*to));
|
||||
|
||||
return (1);
|
||||
return (to);
|
||||
}
|
||||
|
||||
static void
|
||||
RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
|
||||
rs256_free_EVP_MD(EVP_MD *md)
|
||||
{
|
||||
*n = r->n;
|
||||
*e = r->e;
|
||||
*d = r->d;
|
||||
freezero(md, sizeof(*md));
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
#elif OPENSSL_VERSION_NUMBER >= 0x30000000
|
||||
static EVP_MD *
|
||||
rs256_get_EVP_MD(void)
|
||||
{
|
||||
return (EVP_MD_fetch(NULL, "SHA2-256", NULL));
|
||||
}
|
||||
|
||||
static void
|
||||
rs256_free_EVP_MD(EVP_MD *md)
|
||||
{
|
||||
EVP_MD_free(md);
|
||||
}
|
||||
#else
|
||||
static EVP_MD *
|
||||
rs256_get_EVP_MD(void)
|
||||
{
|
||||
const EVP_MD *md;
|
||||
|
||||
if ((md = EVP_sha256()) == NULL)
|
||||
return (NULL);
|
||||
|
||||
return (EVP_MD_meth_dup(md));
|
||||
}
|
||||
|
||||
static void
|
||||
rs256_free_EVP_MD(EVP_MD *md)
|
||||
{
|
||||
EVP_MD_meth_free(md);
|
||||
}
|
||||
#endif /* LIBRESSL_VERSION_NUMBER */
|
||||
|
||||
static int
|
||||
decode_bignum(const cbor_item_t *item, void *ptr, size_t len)
|
||||
@ -198,3 +221,75 @@ rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa)
|
||||
|
||||
return (FIDO_OK);
|
||||
}
|
||||
|
||||
int
|
||||
rs256_pk_from_EVP_PKEY(rs256_pk_t *pk, const EVP_PKEY *pkey)
|
||||
{
|
||||
RSA *rsa;
|
||||
|
||||
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA ||
|
||||
(rsa = EVP_PKEY_get0(pkey)) == NULL)
|
||||
return (FIDO_ERR_INVALID_ARGUMENT);
|
||||
|
||||
return (rs256_pk_from_RSA(pk, rsa));
|
||||
}
|
||||
|
||||
int
|
||||
rs256_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_MD *md = NULL;
|
||||
int ok = -1;
|
||||
|
||||
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
|
||||
fido_log_debug("%s: EVP_PKEY_base_id", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((md = rs256_get_EVP_MD()) == NULL) {
|
||||
fido_log_debug("%s: rs256_get_EVP_MD", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL ||
|
||||
EVP_PKEY_verify_init(pctx) != 1 ||
|
||||
EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) != 1 ||
|
||||
EVP_PKEY_CTX_set_signature_md(pctx, md) != 1) {
|
||||
fido_log_debug("%s: EVP_PKEY_CTX", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr,
|
||||
dgst->len) != 1) {
|
||||
fido_log_debug("%s: EVP_PKEY_verify", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
rs256_free_EVP_MD(md);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int
|
||||
rs256_pk_verify_sig(const fido_blob_t *dgst, const rs256_pk_t *pk,
|
||||
const fido_blob_t *sig)
|
||||
{
|
||||
EVP_PKEY *pkey;
|
||||
int ok = -1;
|
||||
|
||||
if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL ||
|
||||
rs256_verify_sig(dgst, pkey, sig) < 0) {
|
||||
fido_log_debug("%s: rs256_verify_sig", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
74
src/time.c
Normal file
74
src/time.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "fido.h"
|
||||
|
||||
static int
|
||||
timespec_to_ms(const struct timespec *ts)
|
||||
{
|
||||
int64_t x, y;
|
||||
|
||||
if (ts->tv_sec < 0 || ts->tv_nsec < 0 ||
|
||||
ts->tv_nsec >= 1000000000LL)
|
||||
return -1;
|
||||
|
||||
if ((uint64_t)ts->tv_sec >= INT64_MAX / 1000LL)
|
||||
return -1;
|
||||
|
||||
x = ts->tv_sec * 1000LL;
|
||||
y = ts->tv_nsec / 1000000LL;
|
||||
|
||||
if (INT64_MAX - x < y || x + y > INT_MAX)
|
||||
return -1;
|
||||
|
||||
return (int)(x + y);
|
||||
}
|
||||
|
||||
int
|
||||
fido_time_now(struct timespec *ts_now)
|
||||
{
|
||||
if (clock_gettime(CLOCK_MONOTONIC, ts_now) != 0) {
|
||||
fido_log_error(errno, "%s: clock_gettime", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fido_time_delta(const struct timespec *ts_start, int *ms_remain)
|
||||
{
|
||||
struct timespec ts_end, ts_delta;
|
||||
int ms;
|
||||
|
||||
if (*ms_remain < 0)
|
||||
return 0;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts_end) != 0) {
|
||||
fido_log_error(errno, "%s: clock_gettime", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (timespeccmp(&ts_end, ts_start, <)) {
|
||||
fido_log_debug("%s: timespeccmp", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
timespecsub(&ts_end, ts_start, &ts_delta);
|
||||
|
||||
if ((ms = timespec_to_ms(&ts_delta)) < 0) {
|
||||
fido_log_debug("%s: timespec_to_ms", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ms > *ms_remain)
|
||||
ms = *ms_remain;
|
||||
|
||||
*ms_remain -= ms;
|
||||
|
||||
return 0;
|
||||
}
|
286
src/tpm.c
Normal file
286
src/tpm.c
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Trusted Platform Module (TPM) 2.0 attestation support. Documentation
|
||||
* references are relative to revision 01.38 of the TPM 2.0 specification.
|
||||
*/
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "packed.h"
|
||||
#include "fido.h"
|
||||
|
||||
/* Part 1, 4.89: TPM_GENERATED_VALUE */
|
||||
#define TPM_MAGIC 0xff544347
|
||||
|
||||
/* Part 2, 6.3: TPM_ALG_ID */
|
||||
#define TPM_ALG_RSA 0x0001
|
||||
#define TPM_ALG_SHA256 0x000b
|
||||
#define TPM_ALG_NULL 0x0010
|
||||
|
||||
/* Part 2, 6.9: TPM_ST_ATTEST_CERTIFY */
|
||||
#define TPM_ST_CERTIFY 0x8017
|
||||
|
||||
/* Part 2, 8.3: TPMA_OBJECT */
|
||||
#define TPMA_RESERVED 0xfff8f309 /* reserved bits; must be zero */
|
||||
#define TPMA_FIXED 0x00000002 /* object has fixed hierarchy */
|
||||
#define TPMA_CLEAR 0x00000004 /* object persists */
|
||||
#define TPMA_FIXED_P 0x00000010 /* object has fixed parent */
|
||||
#define TPMA_SENSITIVE 0x00000020 /* data originates within tpm */
|
||||
#define TPMA_SIGN 0x00020000 /* object may sign */
|
||||
|
||||
/* Part 2, 10.4.2: TPM2B_DIGEST */
|
||||
PACKED_TYPE(tpm_sha256_digest_t,
|
||||
struct tpm_sha256_digest {
|
||||
uint16_t size; /* sizeof(body) */
|
||||
uint8_t body[32];
|
||||
})
|
||||
|
||||
/* Part 2, 10.4.3: TPM2B_DATA */
|
||||
PACKED_TYPE(tpm_sha1_data_t,
|
||||
struct tpm_sha1_data {
|
||||
uint16_t size; /* sizeof(body */
|
||||
uint8_t body[20];
|
||||
})
|
||||
|
||||
/* Part 2, 10.5.3: TPM2B_NAME */
|
||||
PACKED_TYPE(tpm_sha256_name_t,
|
||||
struct tpm_sha256_name {
|
||||
uint16_t size; /* sizeof(alg) + sizeof(body) */
|
||||
uint16_t alg; /* TPM_ALG_SHA256 */
|
||||
uint8_t body[32];
|
||||
})
|
||||
|
||||
/* Part 2, 10.11.1: TPMS_CLOCK_INFO */
|
||||
PACKED_TYPE(tpm_clock_info_t,
|
||||
struct tpm_clock_info {
|
||||
uint64_t timestamp_ms;
|
||||
uint32_t reset_count; /* obfuscated by tpm */
|
||||
uint32_t restart_count; /* obfuscated by tpm */
|
||||
uint8_t safe; /* 1 if timestamp_ms is current */
|
||||
})
|
||||
|
||||
/* Part 2, 10.12.8 TPMS_ATTEST */
|
||||
PACKED_TYPE(tpm_sha1_attest_t,
|
||||
struct tpm_sha1_attest {
|
||||
uint32_t magic; /* TPM_MAGIC */
|
||||
uint16_t type; /* TPM_ST_ATTEST_CERTIFY */
|
||||
tpm_sha256_name_t signer; /* full tpm path of signing key */
|
||||
tpm_sha1_data_t data; /* signed sha1 */
|
||||
tpm_clock_info_t clock;
|
||||
uint64_t fwversion; /* obfuscated by tpm */
|
||||
tpm_sha256_name_t name; /* sha256 of tpm_rsa2048_pubarea_t */
|
||||
tpm_sha256_name_t qual_name; /* full tpm path of attested key */
|
||||
})
|
||||
|
||||
/* Part 2, 11.2.4.5: TPM2B_PUBLIC_KEY_RSA */
|
||||
PACKED_TYPE(tpm_rsa2048_key_t,
|
||||
struct tpm_rsa2048_key {
|
||||
uint16_t size; /* sizeof(body) */
|
||||
uint8_t body[256];
|
||||
})
|
||||
|
||||
/* Part 2, 12.2.3.5: TPMS_RSA_PARMS */
|
||||
PACKED_TYPE(tpm_rsa2048_param_t,
|
||||
struct tpm_rsa2048_param {
|
||||
uint16_t symmetric; /* TPM_ALG_NULL */
|
||||
uint16_t scheme; /* TPM_ALG_NULL */
|
||||
uint16_t keybits; /* 2048 */
|
||||
uint32_t exponent; /* zero (meaning 2^16 + 1) */
|
||||
})
|
||||
|
||||
/* Part 2, 12.2.4: TPMT_PUBLIC */
|
||||
PACKED_TYPE(tpm_rsa2048_pubarea_t,
|
||||
struct tpm_rsa2048_pubarea {
|
||||
uint16_t alg; /* TPM_ALG_RSA */
|
||||
uint16_t hash; /* TPM_ALG_SHA256 */
|
||||
uint32_t attr;
|
||||
tpm_sha256_digest_t policy; /* must be present? */
|
||||
tpm_rsa2048_param_t param;
|
||||
tpm_rsa2048_key_t key;
|
||||
})
|
||||
|
||||
static int
|
||||
get_signed_sha1(tpm_sha1_data_t *dgst, const fido_blob_t *authdata,
|
||||
const fido_blob_t *clientdata)
|
||||
{
|
||||
const EVP_MD *md = NULL;
|
||||
EVP_MD_CTX *ctx = NULL;
|
||||
int ok = -1;
|
||||
|
||||
if ((dgst->size = sizeof(dgst->body)) != SHA_DIGEST_LENGTH ||
|
||||
(md = EVP_sha1()) == NULL ||
|
||||
(ctx = EVP_MD_CTX_new()) == NULL ||
|
||||
EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
|
||||
EVP_DigestUpdate(ctx, authdata->ptr, authdata->len) != 1 ||
|
||||
EVP_DigestUpdate(ctx, clientdata->ptr, clientdata->len) != 1 ||
|
||||
EVP_DigestFinal_ex(ctx, dgst->body, NULL) != 1) {
|
||||
fido_log_debug("%s: sha1", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
static int
|
||||
get_signed_name(tpm_sha256_name_t *name, const fido_blob_t *pubarea)
|
||||
{
|
||||
name->alg = TPM_ALG_SHA256;
|
||||
name->size = sizeof(name->alg) + sizeof(name->body);
|
||||
if (sizeof(name->body) != SHA256_DIGEST_LENGTH ||
|
||||
SHA256(pubarea->ptr, pubarea->len, name->body) != name->body) {
|
||||
fido_log_debug("%s: sha256", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
bswap_rsa2048_pubarea(tpm_rsa2048_pubarea_t *x)
|
||||
{
|
||||
x->alg = htobe16(x->alg);
|
||||
x->hash = htobe16(x->hash);
|
||||
x->attr = htobe32(x->attr);
|
||||
x->policy.size = htobe16(x->policy.size);
|
||||
x->param.symmetric = htobe16(x->param.symmetric);
|
||||
x->param.scheme = htobe16(x->param.scheme);
|
||||
x->param.keybits = htobe16(x->param.keybits);
|
||||
x->key.size = htobe16(x->key.size);
|
||||
}
|
||||
|
||||
static void
|
||||
bswap_sha1_certinfo(tpm_sha1_attest_t *x)
|
||||
{
|
||||
x->magic = htobe32(x->magic);
|
||||
x->type = htobe16(x->type);
|
||||
x->signer.size = htobe16(x->signer.size);
|
||||
x->data.size = htobe16(x->data.size);
|
||||
x->name.alg = htobe16(x->name.alg);
|
||||
x->name.size = htobe16(x->name.size);
|
||||
}
|
||||
|
||||
static int
|
||||
check_rsa2048_pubarea(const fido_blob_t *buf, const rs256_pk_t *pk)
|
||||
{
|
||||
const tpm_rsa2048_pubarea_t *actual;
|
||||
tpm_rsa2048_pubarea_t expected;
|
||||
int ok;
|
||||
|
||||
if (buf->len != sizeof(*actual)) {
|
||||
fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
|
||||
return -1;
|
||||
}
|
||||
actual = (const void *)buf->ptr;
|
||||
|
||||
memset(&expected, 0, sizeof(expected));
|
||||
expected.alg = TPM_ALG_RSA;
|
||||
expected.hash = TPM_ALG_SHA256;
|
||||
expected.attr = be32toh(actual->attr);
|
||||
expected.attr &= ~(TPMA_RESERVED|TPMA_CLEAR);
|
||||
expected.attr |= (TPMA_FIXED|TPMA_FIXED_P|TPMA_SENSITIVE|TPMA_SIGN);
|
||||
expected.policy = actual->policy;
|
||||
expected.policy.size = sizeof(expected.policy.body);
|
||||
expected.param.symmetric = TPM_ALG_NULL;
|
||||
expected.param.scheme = TPM_ALG_NULL;
|
||||
expected.param.keybits = 2048;
|
||||
expected.param.exponent = 0; /* meaning 2^16+1 */
|
||||
expected.key.size = sizeof(expected.key.body);
|
||||
memcpy(&expected.key.body, &pk->n, sizeof(expected.key.body));
|
||||
bswap_rsa2048_pubarea(&expected);
|
||||
|
||||
ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
|
||||
explicit_bzero(&expected, sizeof(expected));
|
||||
|
||||
return ok != 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
check_sha1_certinfo(const fido_blob_t *buf, const fido_blob_t *clientdata_hash,
|
||||
const fido_blob_t *authdata_raw, const fido_blob_t *pubarea)
|
||||
{
|
||||
const tpm_sha1_attest_t *actual;
|
||||
tpm_sha1_attest_t expected;
|
||||
tpm_sha1_data_t signed_data;
|
||||
tpm_sha256_name_t signed_name;
|
||||
int ok = -1;
|
||||
|
||||
memset(&signed_data, 0, sizeof(signed_data));
|
||||
memset(&signed_name, 0, sizeof(signed_name));
|
||||
|
||||
if (get_signed_sha1(&signed_data, authdata_raw, clientdata_hash) < 0 ||
|
||||
get_signed_name(&signed_name, pubarea) < 0) {
|
||||
fido_log_debug("%s: get_signed_sha1/name", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if (buf->len != sizeof(*actual)) {
|
||||
fido_log_debug("%s: buf->len=%zu", __func__, buf->len);
|
||||
goto fail;
|
||||
}
|
||||
actual = (const void *)buf->ptr;
|
||||
|
||||
memset(&expected, 0, sizeof(expected));
|
||||
expected.magic = TPM_MAGIC;
|
||||
expected.type = TPM_ST_CERTIFY;
|
||||
expected.signer = actual->signer;
|
||||
expected.signer.size = sizeof(expected.signer.alg) +
|
||||
sizeof(expected.signer.body);
|
||||
expected.data = signed_data;
|
||||
expected.clock = actual->clock;
|
||||
expected.clock.safe = 1;
|
||||
expected.fwversion = actual->fwversion;
|
||||
expected.name = signed_name;
|
||||
expected.qual_name = actual->qual_name;
|
||||
bswap_sha1_certinfo(&expected);
|
||||
|
||||
ok = timingsafe_bcmp(&expected, actual, sizeof(expected));
|
||||
fail:
|
||||
explicit_bzero(&expected, sizeof(expected));
|
||||
explicit_bzero(&signed_data, sizeof(signed_data));
|
||||
explicit_bzero(&signed_name, sizeof(signed_name));
|
||||
|
||||
return ok != 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
int
|
||||
fido_get_signed_hash_tpm(fido_blob_t *dgst, const fido_blob_t *clientdata_hash,
|
||||
const fido_blob_t *authdata_raw, const fido_attstmt_t *attstmt,
|
||||
const fido_attcred_t *attcred)
|
||||
{
|
||||
const fido_blob_t *pubarea = &attstmt->pubarea;
|
||||
const fido_blob_t *certinfo = &attstmt->certinfo;
|
||||
|
||||
if (attstmt->alg != COSE_RS1 || attcred->type != COSE_RS256) {
|
||||
fido_log_debug("%s: unsupported alg %d, type %d", __func__,
|
||||
attstmt->alg, attcred->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (check_rsa2048_pubarea(pubarea, &attcred->pubkey.rs256) < 0) {
|
||||
fido_log_debug("%s: check_rsa2048_pubarea", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (check_sha1_certinfo(certinfo, clientdata_hash, authdata_raw,
|
||||
pubarea) < 0) {
|
||||
fido_log_debug("%s: check_sha1_certinfo", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dgst->len < SHA_DIGEST_LENGTH ||
|
||||
SHA1(certinfo->ptr, certinfo->len, dgst->ptr) != dgst->ptr) {
|
||||
fido_log_debug("%s: sha1", __func__);
|
||||
return -1;
|
||||
}
|
||||
dgst->len = SHA_DIGEST_LENGTH;
|
||||
|
||||
return 0;
|
||||
}
|
76
src/types.c
Normal file
76
src/types.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "fido.h"
|
||||
|
||||
void
|
||||
fido_str_array_free(fido_str_array_t *sa)
|
||||
{
|
||||
for (size_t i = 0; i < sa->len; i++)
|
||||
free(sa->ptr[i]);
|
||||
|
||||
free(sa->ptr);
|
||||
sa->ptr = NULL;
|
||||
sa->len = 0;
|
||||
}
|
||||
|
||||
void
|
||||
fido_opt_array_free(fido_opt_array_t *oa)
|
||||
{
|
||||
for (size_t i = 0; i < oa->len; i++)
|
||||
free(oa->name[i]);
|
||||
|
||||
free(oa->name);
|
||||
free(oa->value);
|
||||
oa->name = NULL;
|
||||
oa->value = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
fido_byte_array_free(fido_byte_array_t *ba)
|
||||
{
|
||||
free(ba->ptr);
|
||||
|
||||
ba->ptr = NULL;
|
||||
ba->len = 0;
|
||||
}
|
||||
|
||||
void
|
||||
fido_algo_free(fido_algo_t *a)
|
||||
{
|
||||
free(a->type);
|
||||
a->type = NULL;
|
||||
a->cose = 0;
|
||||
}
|
||||
|
||||
void
|
||||
fido_algo_array_free(fido_algo_array_t *aa)
|
||||
{
|
||||
for (size_t i = 0; i < aa->len; i++)
|
||||
fido_algo_free(&aa->ptr[i]);
|
||||
|
||||
free(aa->ptr);
|
||||
aa->ptr = NULL;
|
||||
aa->len = 0;
|
||||
}
|
||||
|
||||
int
|
||||
fido_str_array_pack(fido_str_array_t *sa, const char * const *v, size_t n)
|
||||
{
|
||||
if ((sa->ptr = calloc(n, sizeof(char *))) == NULL) {
|
||||
fido_log_debug("%s: calloc", __func__);
|
||||
return -1;
|
||||
}
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if ((sa->ptr[i] = strdup(v[i])) == NULL) {
|
||||
fido_log_debug("%s: strdup", __func__);
|
||||
return -1;
|
||||
}
|
||||
sa->len++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
158
src/u2f.c
158
src/u2f.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Yubico AB. All rights reserved.
|
||||
* Copyright (c) 2018-2021 Yubico AB. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style
|
||||
* license that can be found in the LICENSE file.
|
||||
*/
|
||||
@ -10,10 +10,13 @@
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include "fido.h"
|
||||
#include "fido/es256.h"
|
||||
|
||||
#define U2F_PACE_MS (100)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
static int
|
||||
usleep(unsigned int usec)
|
||||
@ -24,6 +27,28 @@ usleep(unsigned int usec)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
delay_ms(unsigned int ms, int *ms_remain)
|
||||
{
|
||||
if (*ms_remain > -1 && (unsigned int)*ms_remain < ms)
|
||||
ms = (unsigned int)*ms_remain;
|
||||
|
||||
if (ms > UINT_MAX / 1000) {
|
||||
fido_log_debug("%s: ms=%u", __func__, ms);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (usleep(ms * 1000) < 0) {
|
||||
fido_log_error(errno, "%s: usleep", __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (*ms_remain > -1)
|
||||
*ms_remain -= (int)ms;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
sig_get(fido_blob_t *sig, const unsigned char **buf, size_t *len)
|
||||
{
|
||||
@ -115,7 +140,7 @@ authdata_fake(const char *rp_id, uint8_t flags, uint32_t sigcount,
|
||||
|
||||
/* TODO: use u2f_get_touch_begin & u2f_get_touch_status instead */
|
||||
static int
|
||||
send_dummy_register(fido_dev_t *dev, int ms)
|
||||
send_dummy_register(fido_dev_t *dev, int *ms)
|
||||
{
|
||||
iso7816_apdu_t *apdu = NULL;
|
||||
unsigned char challenge[SHA256_DIGEST_LENGTH];
|
||||
@ -123,10 +148,6 @@ send_dummy_register(fido_dev_t *dev, int ms)
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int r;
|
||||
|
||||
#ifdef FIDO_FUZZ
|
||||
ms = 0; /* XXX */
|
||||
#endif
|
||||
|
||||
/* dummy challenge & application */
|
||||
memset(&challenge, 0xff, sizeof(challenge));
|
||||
memset(&application, 0xff, sizeof(application));
|
||||
@ -142,7 +163,7 @@ send_dummy_register(fido_dev_t *dev, int ms)
|
||||
|
||||
do {
|
||||
if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
|
||||
iso7816_len(apdu)) < 0) {
|
||||
iso7816_len(apdu), ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -152,8 +173,8 @@ send_dummy_register(fido_dev_t *dev, int ms)
|
||||
r = FIDO_ERR_RX;
|
||||
goto fail;
|
||||
}
|
||||
if (usleep((unsigned)(ms == -1 ? 100 : ms) * 1000) < 0) {
|
||||
fido_log_debug("%s: usleep", __func__);
|
||||
if (delay_ms(U2F_PACE_MS, ms) != 0) {
|
||||
fido_log_debug("%s: delay_ms", __func__);
|
||||
r = FIDO_ERR_RX;
|
||||
goto fail;
|
||||
}
|
||||
@ -168,7 +189,7 @@ send_dummy_register(fido_dev_t *dev, int ms)
|
||||
|
||||
static int
|
||||
key_lookup(fido_dev_t *dev, const char *rp_id, const fido_blob_t *key_id,
|
||||
int *found, int ms)
|
||||
int *found, int *ms)
|
||||
{
|
||||
iso7816_apdu_t *apdu = NULL;
|
||||
unsigned char challenge[SHA256_DIGEST_LENGTH];
|
||||
@ -208,7 +229,7 @@ key_lookup(fido_dev_t *dev, const char *rp_id, const fido_blob_t *key_id,
|
||||
}
|
||||
|
||||
if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
|
||||
iso7816_len(apdu)) < 0) {
|
||||
iso7816_len(apdu), ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -274,7 +295,7 @@ parse_auth_reply(fido_blob_t *sig, fido_blob_t *ad, const char *rp_id,
|
||||
|
||||
static int
|
||||
do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id,
|
||||
const fido_blob_t *key_id, fido_blob_t *sig, fido_blob_t *ad, int ms)
|
||||
const fido_blob_t *key_id, fido_blob_t *sig, fido_blob_t *ad, int *ms)
|
||||
{
|
||||
iso7816_apdu_t *apdu = NULL;
|
||||
unsigned char rp_id_hash[SHA256_DIGEST_LENGTH];
|
||||
@ -284,7 +305,7 @@ do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id,
|
||||
int r;
|
||||
|
||||
#ifdef FIDO_FUZZ
|
||||
ms = 0; /* XXX */
|
||||
*ms = 0; /* XXX */
|
||||
#endif
|
||||
|
||||
if (cdh->len != SHA256_DIGEST_LENGTH || key_id->len > UINT8_MAX ||
|
||||
@ -317,7 +338,7 @@ do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id,
|
||||
|
||||
do {
|
||||
if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
|
||||
iso7816_len(apdu)) < 0) {
|
||||
iso7816_len(apdu), ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -328,8 +349,8 @@ do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id,
|
||||
r = FIDO_ERR_RX;
|
||||
goto fail;
|
||||
}
|
||||
if (usleep((unsigned)(ms == -1 ? 100 : ms) * 1000) < 0) {
|
||||
fido_log_debug("%s: usleep", __func__);
|
||||
if (delay_ms(U2F_PACE_MS, ms) != 0) {
|
||||
fido_log_debug("%s: delay_ms", __func__);
|
||||
r = FIDO_ERR_RX;
|
||||
goto fail;
|
||||
}
|
||||
@ -390,6 +411,71 @@ cbor_blob_from_ec_point(const uint8_t *ec_point, size_t ec_point_len,
|
||||
return (ok);
|
||||
}
|
||||
|
||||
static int
|
||||
encode_cred_attstmt(int cose_alg, const fido_blob_t *x5c,
|
||||
const fido_blob_t *sig, fido_blob_t *out)
|
||||
{
|
||||
cbor_item_t *item = NULL;
|
||||
cbor_item_t *x5c_cbor = NULL;
|
||||
const uint8_t alg_cbor = (uint8_t)(-cose_alg - 1);
|
||||
struct cbor_pair kv[3];
|
||||
size_t alloc_len;
|
||||
int ok = -1;
|
||||
|
||||
memset(&kv, 0, sizeof(kv));
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
if ((item = cbor_new_definite_map(3)) == NULL) {
|
||||
fido_log_debug("%s: cbor_new_definite_map", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((kv[0].key = cbor_build_string("alg")) == NULL ||
|
||||
(kv[0].value = cbor_build_negint8(alg_cbor)) == NULL ||
|
||||
!cbor_map_add(item, kv[0])) {
|
||||
fido_log_debug("%s: alg", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((kv[1].key = cbor_build_string("sig")) == NULL ||
|
||||
(kv[1].value = fido_blob_encode(sig)) == NULL ||
|
||||
!cbor_map_add(item, kv[1])) {
|
||||
fido_log_debug("%s: sig", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((kv[2].key = cbor_build_string("x5c")) == NULL ||
|
||||
(kv[2].value = cbor_new_definite_array(1)) == NULL ||
|
||||
(x5c_cbor = fido_blob_encode(x5c)) == NULL ||
|
||||
!cbor_array_push(kv[2].value, x5c_cbor) ||
|
||||
!cbor_map_add(item, kv[2])) {
|
||||
fido_log_debug("%s: x5c", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((out->len = cbor_serialize_alloc(item, &out->ptr,
|
||||
&alloc_len)) == 0) {
|
||||
fido_log_debug("%s: cbor_serialize_alloc", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
fail:
|
||||
if (item != NULL)
|
||||
cbor_decref(&item);
|
||||
if (x5c_cbor != NULL)
|
||||
cbor_decref(&x5c_cbor);
|
||||
|
||||
for (size_t i = 0; i < nitems(kv); i++) {
|
||||
if (kv[i].key)
|
||||
cbor_decref(&kv[i].key);
|
||||
if (kv[i].value)
|
||||
cbor_decref(&kv[i].value);
|
||||
}
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
static int
|
||||
encode_cred_authdata(const char *rp_id, const uint8_t *kh, uint8_t kh_len,
|
||||
const uint8_t *pubkey, size_t pubkey_len, fido_blob_t *out)
|
||||
@ -476,6 +562,7 @@ parse_register_reply(fido_cred_t *cred, const unsigned char *reply, size_t len)
|
||||
fido_blob_t x5c;
|
||||
fido_blob_t sig;
|
||||
fido_blob_t ad;
|
||||
fido_blob_t stmt;
|
||||
uint8_t dummy;
|
||||
uint8_t pubkey[65];
|
||||
uint8_t kh_len = 0;
|
||||
@ -485,6 +572,7 @@ parse_register_reply(fido_cred_t *cred, const unsigned char *reply, size_t len)
|
||||
memset(&x5c, 0, sizeof(x5c));
|
||||
memset(&sig, 0, sizeof(sig));
|
||||
memset(&ad, 0, sizeof(ad));
|
||||
memset(&stmt, 0, sizeof(stmt));
|
||||
r = FIDO_ERR_RX;
|
||||
|
||||
/* status word */
|
||||
@ -518,6 +606,12 @@ parse_register_reply(fido_cred_t *cred, const unsigned char *reply, size_t len)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* attstmt */
|
||||
if (encode_cred_attstmt(COSE_ES256, &x5c, &sig, &stmt) < 0) {
|
||||
fido_log_debug("%s: encode_cred_attstmt", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* authdata */
|
||||
if (encode_cred_authdata(cred->rp.id, kh, kh_len, pubkey,
|
||||
sizeof(pubkey), &ad) < 0) {
|
||||
@ -527,8 +621,7 @@ parse_register_reply(fido_cred_t *cred, const unsigned char *reply, size_t len)
|
||||
|
||||
if (fido_cred_set_fmt(cred, "fido-u2f") != FIDO_OK ||
|
||||
fido_cred_set_authdata(cred, ad.ptr, ad.len) != FIDO_OK ||
|
||||
fido_cred_set_x509(cred, x5c.ptr, x5c.len) != FIDO_OK ||
|
||||
fido_cred_set_sig(cred, sig.ptr, sig.len) != FIDO_OK) {
|
||||
fido_cred_set_attstmt(cred, stmt.ptr, stmt.len) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_cred_set", __func__);
|
||||
r = FIDO_ERR_INTERNAL;
|
||||
goto fail;
|
||||
@ -540,12 +633,13 @@ parse_register_reply(fido_cred_t *cred, const unsigned char *reply, size_t len)
|
||||
fido_blob_reset(&x5c);
|
||||
fido_blob_reset(&sig);
|
||||
fido_blob_reset(&ad);
|
||||
fido_blob_reset(&stmt);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
int
|
||||
u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms)
|
||||
u2f_register(fido_dev_t *dev, fido_cred_t *cred, int *ms)
|
||||
{
|
||||
iso7816_apdu_t *apdu = NULL;
|
||||
unsigned char rp_id_hash[SHA256_DIGEST_LENGTH];
|
||||
@ -554,10 +648,6 @@ u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms)
|
||||
int found;
|
||||
int r;
|
||||
|
||||
#ifdef FIDO_FUZZ
|
||||
ms = 0; /* XXX */
|
||||
#endif
|
||||
|
||||
if (cred->rk == FIDO_OPT_TRUE || cred->uv == FIDO_OPT_TRUE) {
|
||||
fido_log_debug("%s: rk=%d, uv=%d", __func__, cred->rk,
|
||||
cred->uv);
|
||||
@ -606,7 +696,7 @@ u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms)
|
||||
|
||||
do {
|
||||
if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
|
||||
iso7816_len(apdu)) < 0) {
|
||||
iso7816_len(apdu), ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -617,8 +707,8 @@ u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms)
|
||||
r = FIDO_ERR_RX;
|
||||
goto fail;
|
||||
}
|
||||
if (usleep((unsigned)(ms == -1 ? 100 : ms) * 1000) < 0) {
|
||||
fido_log_debug("%s: usleep", __func__);
|
||||
if (delay_ms(U2F_PACE_MS, ms) != 0) {
|
||||
fido_log_debug("%s: delay_ms", __func__);
|
||||
r = FIDO_ERR_RX;
|
||||
goto fail;
|
||||
}
|
||||
@ -637,7 +727,7 @@ u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms)
|
||||
|
||||
static int
|
||||
u2f_authenticate_single(fido_dev_t *dev, const fido_blob_t *key_id,
|
||||
fido_assert_t *fa, size_t idx, int ms)
|
||||
fido_assert_t *fa, size_t idx, int *ms)
|
||||
{
|
||||
fido_blob_t sig;
|
||||
fido_blob_t ad;
|
||||
@ -692,7 +782,7 @@ u2f_authenticate_single(fido_dev_t *dev, const fido_blob_t *key_id,
|
||||
}
|
||||
|
||||
int
|
||||
u2f_authenticate(fido_dev_t *dev, fido_assert_t *fa, int ms)
|
||||
u2f_authenticate(fido_dev_t *dev, fido_assert_t *fa, int *ms)
|
||||
{
|
||||
size_t nfound = 0;
|
||||
size_t nauth_ok = 0;
|
||||
@ -739,7 +829,7 @@ u2f_authenticate(fido_dev_t *dev, fido_assert_t *fa, int ms)
|
||||
}
|
||||
|
||||
int
|
||||
u2f_get_touch_begin(fido_dev_t *dev)
|
||||
u2f_get_touch_begin(fido_dev_t *dev, int *ms)
|
||||
{
|
||||
iso7816_apdu_t *apdu = NULL;
|
||||
const char *clientdata = FIDO_DUMMY_CLIENTDATA;
|
||||
@ -769,12 +859,12 @@ u2f_get_touch_begin(fido_dev_t *dev)
|
||||
}
|
||||
|
||||
if (dev->attr.flags & FIDO_CAP_WINK) {
|
||||
fido_tx(dev, CTAP_CMD_WINK, NULL, 0);
|
||||
fido_rx(dev, CTAP_CMD_WINK, &reply, sizeof(reply), 200);
|
||||
fido_tx(dev, CTAP_CMD_WINK, NULL, 0, ms);
|
||||
fido_rx(dev, CTAP_CMD_WINK, &reply, sizeof(reply), ms);
|
||||
}
|
||||
|
||||
if (fido_tx(dev, CTAP_CMD_MSG, iso7816_ptr(apdu),
|
||||
iso7816_len(apdu)) < 0) {
|
||||
iso7816_len(apdu), ms) < 0) {
|
||||
fido_log_debug("%s: fido_tx", __func__);
|
||||
r = FIDO_ERR_TX;
|
||||
goto fail;
|
||||
@ -788,7 +878,7 @@ u2f_get_touch_begin(fido_dev_t *dev)
|
||||
}
|
||||
|
||||
int
|
||||
u2f_get_touch_status(fido_dev_t *dev, int *touched, int ms)
|
||||
u2f_get_touch_status(fido_dev_t *dev, int *touched, int *ms)
|
||||
{
|
||||
unsigned char reply[FIDO_MAXMSG];
|
||||
int reply_len;
|
||||
@ -802,7 +892,7 @@ u2f_get_touch_status(fido_dev_t *dev, int *touched, int ms)
|
||||
|
||||
switch ((reply[reply_len - 2] << 8) | reply[reply_len - 1]) {
|
||||
case SW_CONDITIONS_NOT_SATISFIED:
|
||||
if ((r = u2f_get_touch_begin(dev)) != FIDO_OK) {
|
||||
if ((r = u2f_get_touch_begin(dev, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: u2f_get_touch_begin", __func__);
|
||||
return (r);
|
||||
}
|
||||
|
839
src/webauthn.h
Normal file
839
src/webauthn.h
Normal file
@ -0,0 +1,839 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#ifndef __WEBAUTHN_H_
|
||||
#define __WEBAUTHN_H_
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <winapifamily.h>
|
||||
|
||||
#pragma region Desktop Family or OneCore Family
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI
|
||||
#define WINAPI __stdcall
|
||||
#endif
|
||||
|
||||
#ifndef INITGUID
|
||||
#define INITGUID
|
||||
#include <guiddef.h>
|
||||
#undef INITGUID
|
||||
#else
|
||||
#include <guiddef.h>
|
||||
#endif
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// API Version Information.
|
||||
// Caller should check for WebAuthNGetApiVersionNumber to check the presence of relevant APIs
|
||||
// and features for their usage.
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_API_VERSION_1 1
|
||||
// WEBAUTHN_API_VERSION_1 : Baseline Version
|
||||
// Data Structures and their sub versions:
|
||||
// - WEBAUTHN_RP_ENTITY_INFORMATION : 1
|
||||
// - WEBAUTHN_USER_ENTITY_INFORMATION : 1
|
||||
// - WEBAUTHN_CLIENT_DATA : 1
|
||||
// - WEBAUTHN_COSE_CREDENTIAL_PARAMETER : 1
|
||||
// - WEBAUTHN_COSE_CREDENTIAL_PARAMETERS : Not Applicable
|
||||
// - WEBAUTHN_CREDENTIAL : 1
|
||||
// - WEBAUTHN_CREDENTIALS : Not Applicable
|
||||
// - WEBAUTHN_CREDENTIAL_EX : 1
|
||||
// - WEBAUTHN_CREDENTIAL_LIST : Not Applicable
|
||||
// - WEBAUTHN_EXTENSION : Not Applicable
|
||||
// - WEBAUTHN_EXTENSIONS : Not Applicable
|
||||
// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 3
|
||||
// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 4
|
||||
// - WEBAUTHN_COMMON_ATTESTATION : 1
|
||||
// - WEBAUTHN_CREDENTIAL_ATTESTATION : 3
|
||||
// - WEBAUTHN_ASSERTION : 1
|
||||
// Extensions:
|
||||
// - WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET
|
||||
// APIs:
|
||||
// - WebAuthNGetApiVersionNumber
|
||||
// - WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable
|
||||
// - WebAuthNAuthenticatorMakeCredential
|
||||
// - WebAuthNAuthenticatorGetAssertion
|
||||
// - WebAuthNFreeCredentialAttestation
|
||||
// - WebAuthNFreeAssertion
|
||||
// - WebAuthNGetCancellationId
|
||||
// - WebAuthNCancelCurrentOperation
|
||||
// - WebAuthNGetErrorName
|
||||
// - WebAuthNGetW3CExceptionDOMError
|
||||
|
||||
#define WEBAUTHN_API_VERSION_2 2
|
||||
// WEBAUTHN_API_VERSION_2 : Delta From WEBAUTHN_API_VERSION_1
|
||||
// Added Extensions:
|
||||
// - WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT
|
||||
//
|
||||
|
||||
#define WEBAUTHN_API_VERSION_3 3
|
||||
// WEBAUTHN_API_VERSION_3 : Delta From WEBAUTHN_API_VERSION_2
|
||||
// Data Structures and their sub versions:
|
||||
// - WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS : 4
|
||||
// - WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS : 5
|
||||
// - WEBAUTHN_CREDENTIAL_ATTESTATION : 4
|
||||
// - WEBAUTHN_ASSERTION : 2
|
||||
// Added Extensions:
|
||||
// - WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB
|
||||
// - WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH
|
||||
//
|
||||
|
||||
#define WEBAUTHN_API_CURRENT_VERSION WEBAUTHN_API_VERSION_3
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Information about an RP Entity
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_RP_ENTITY_INFORMATION_CURRENT_VERSION 1
|
||||
|
||||
typedef struct _WEBAUTHN_RP_ENTITY_INFORMATION {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
// This field is required and should be set to CURRENT_VERSION above.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Identifier for the RP. This field is required.
|
||||
PCWSTR pwszId;
|
||||
|
||||
// Contains the friendly name of the Relying Party, such as "Acme Corporation", "Widgets Inc" or "Awesome Site".
|
||||
// This field is required.
|
||||
PCWSTR pwszName;
|
||||
|
||||
// Optional URL pointing to RP's logo.
|
||||
PCWSTR pwszIcon;
|
||||
} WEBAUTHN_RP_ENTITY_INFORMATION, *PWEBAUTHN_RP_ENTITY_INFORMATION;
|
||||
typedef const WEBAUTHN_RP_ENTITY_INFORMATION *PCWEBAUTHN_RP_ENTITY_INFORMATION;
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Information about an User Entity
|
||||
//-------------------------------------------------------------------------------------------
|
||||
#define WEBAUTHN_MAX_USER_ID_LENGTH 64
|
||||
|
||||
#define WEBAUTHN_USER_ENTITY_INFORMATION_CURRENT_VERSION 1
|
||||
|
||||
typedef struct _WEBAUTHN_USER_ENTITY_INFORMATION {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
// This field is required and should be set to CURRENT_VERSION above.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Identifier for the User. This field is required.
|
||||
DWORD cbId;
|
||||
_Field_size_bytes_(cbId)
|
||||
PBYTE pbId;
|
||||
|
||||
// Contains a detailed name for this account, such as "john.p.smith@example.com".
|
||||
PCWSTR pwszName;
|
||||
|
||||
// Optional URL that can be used to retrieve an image containing the user's current avatar,
|
||||
// or a data URI that contains the image data.
|
||||
PCWSTR pwszIcon;
|
||||
|
||||
// For User: Contains the friendly name associated with the user account by the Relying Party, such as "John P. Smith".
|
||||
PCWSTR pwszDisplayName;
|
||||
} WEBAUTHN_USER_ENTITY_INFORMATION, *PWEBAUTHN_USER_ENTITY_INFORMATION;
|
||||
typedef const WEBAUTHN_USER_ENTITY_INFORMATION *PCWEBAUTHN_USER_ENTITY_INFORMATION;
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Information about client data.
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_HASH_ALGORITHM_SHA_256 L"SHA-256"
|
||||
#define WEBAUTHN_HASH_ALGORITHM_SHA_384 L"SHA-384"
|
||||
#define WEBAUTHN_HASH_ALGORITHM_SHA_512 L"SHA-512"
|
||||
|
||||
#define WEBAUTHN_CLIENT_DATA_CURRENT_VERSION 1
|
||||
|
||||
typedef struct _WEBAUTHN_CLIENT_DATA {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
// This field is required and should be set to CURRENT_VERSION above.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Size of the pbClientDataJSON field.
|
||||
DWORD cbClientDataJSON;
|
||||
// UTF-8 encoded JSON serialization of the client data.
|
||||
_Field_size_bytes_(cbClientDataJSON)
|
||||
PBYTE pbClientDataJSON;
|
||||
|
||||
// Hash algorithm ID used to hash the pbClientDataJSON field.
|
||||
LPCWSTR pwszHashAlgId;
|
||||
} WEBAUTHN_CLIENT_DATA, *PWEBAUTHN_CLIENT_DATA;
|
||||
typedef const WEBAUTHN_CLIENT_DATA *PCWEBAUTHN_CLIENT_DATA;
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Information about credential parameters.
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_CREDENTIAL_TYPE_PUBLIC_KEY L"public-key"
|
||||
|
||||
#define WEBAUTHN_COSE_ALGORITHM_ECDSA_P256_WITH_SHA256 -7
|
||||
#define WEBAUTHN_COSE_ALGORITHM_ECDSA_P384_WITH_SHA384 -35
|
||||
#define WEBAUTHN_COSE_ALGORITHM_ECDSA_P521_WITH_SHA512 -36
|
||||
|
||||
#define WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA256 -257
|
||||
#define WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA384 -258
|
||||
#define WEBAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA512 -259
|
||||
|
||||
#define WEBAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA256 -37
|
||||
#define WEBAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA384 -38
|
||||
#define WEBAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA512 -39
|
||||
|
||||
#define WEBAUTHN_COSE_CREDENTIAL_PARAMETER_CURRENT_VERSION 1
|
||||
|
||||
typedef struct _WEBAUTHN_COSE_CREDENTIAL_PARAMETER {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Well-known credential type specifying a credential to create.
|
||||
LPCWSTR pwszCredentialType;
|
||||
|
||||
// Well-known COSE algorithm specifying the algorithm to use for the credential.
|
||||
LONG lAlg;
|
||||
} WEBAUTHN_COSE_CREDENTIAL_PARAMETER, *PWEBAUTHN_COSE_CREDENTIAL_PARAMETER;
|
||||
typedef const WEBAUTHN_COSE_CREDENTIAL_PARAMETER *PCWEBAUTHN_COSE_CREDENTIAL_PARAMETER;
|
||||
|
||||
typedef struct _WEBAUTHN_COSE_CREDENTIAL_PARAMETERS {
|
||||
DWORD cCredentialParameters;
|
||||
_Field_size_(cCredentialParameters)
|
||||
PWEBAUTHN_COSE_CREDENTIAL_PARAMETER pCredentialParameters;
|
||||
} WEBAUTHN_COSE_CREDENTIAL_PARAMETERS, *PWEBAUTHN_COSE_CREDENTIAL_PARAMETERS;
|
||||
typedef const WEBAUTHN_COSE_CREDENTIAL_PARAMETERS *PCWEBAUTHN_COSE_CREDENTIAL_PARAMETERS;
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Information about credential.
|
||||
//-------------------------------------------------------------------------------------------
|
||||
#define WEBAUTHN_CREDENTIAL_CURRENT_VERSION 1
|
||||
|
||||
typedef struct _WEBAUTHN_CREDENTIAL {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Size of pbID.
|
||||
DWORD cbId;
|
||||
// Unique ID for this particular credential.
|
||||
_Field_size_bytes_(cbId)
|
||||
PBYTE pbId;
|
||||
|
||||
// Well-known credential type specifying what this particular credential is.
|
||||
LPCWSTR pwszCredentialType;
|
||||
} WEBAUTHN_CREDENTIAL, *PWEBAUTHN_CREDENTIAL;
|
||||
typedef const WEBAUTHN_CREDENTIAL *PCWEBAUTHN_CREDENTIAL;
|
||||
|
||||
typedef struct _WEBAUTHN_CREDENTIALS {
|
||||
DWORD cCredentials;
|
||||
_Field_size_(cCredentials)
|
||||
PWEBAUTHN_CREDENTIAL pCredentials;
|
||||
} WEBAUTHN_CREDENTIALS, *PWEBAUTHN_CREDENTIALS;
|
||||
typedef const WEBAUTHN_CREDENTIALS *PCWEBAUTHN_CREDENTIALS;
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Information about credential with extra information, such as, dwTransports
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_CTAP_TRANSPORT_USB 0x00000001
|
||||
#define WEBAUTHN_CTAP_TRANSPORT_NFC 0x00000002
|
||||
#define WEBAUTHN_CTAP_TRANSPORT_BLE 0x00000004
|
||||
#define WEBAUTHN_CTAP_TRANSPORT_TEST 0x00000008
|
||||
#define WEBAUTHN_CTAP_TRANSPORT_INTERNAL 0x00000010
|
||||
#define WEBAUTHN_CTAP_TRANSPORT_FLAGS_MASK 0x0000001F
|
||||
|
||||
#define WEBAUTHN_CREDENTIAL_EX_CURRENT_VERSION 1
|
||||
|
||||
typedef struct _WEBAUTHN_CREDENTIAL_EX {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Size of pbID.
|
||||
DWORD cbId;
|
||||
// Unique ID for this particular credential.
|
||||
_Field_size_bytes_(cbId)
|
||||
PBYTE pbId;
|
||||
|
||||
// Well-known credential type specifying what this particular credential is.
|
||||
LPCWSTR pwszCredentialType;
|
||||
|
||||
// Transports. 0 implies no transport restrictions.
|
||||
DWORD dwTransports;
|
||||
} WEBAUTHN_CREDENTIAL_EX, *PWEBAUTHN_CREDENTIAL_EX;
|
||||
typedef const WEBAUTHN_CREDENTIAL_EX *PCWEBAUTHN_CREDENTIAL_EX;
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Information about credential list with extra information
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
typedef struct _WEBAUTHN_CREDENTIAL_LIST {
|
||||
DWORD cCredentials;
|
||||
_Field_size_(cCredentials)
|
||||
PWEBAUTHN_CREDENTIAL_EX *ppCredentials;
|
||||
} WEBAUTHN_CREDENTIAL_LIST, *PWEBAUTHN_CREDENTIAL_LIST;
|
||||
typedef const WEBAUTHN_CREDENTIAL_LIST *PCWEBAUTHN_CREDENTIAL_LIST;
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Hmac-Secret extension
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET L"hmac-secret"
|
||||
// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_HMAC_SECRET
|
||||
// MakeCredential Input Type: BOOL.
|
||||
// - pvExtension must point to a BOOL with the value TRUE.
|
||||
// - cbExtension must contain the sizeof(BOOL).
|
||||
// MakeCredential Output Type: BOOL.
|
||||
// - pvExtension will point to a BOOL with the value TRUE if credential
|
||||
// was successfully created with HMAC_SECRET.
|
||||
// - cbExtension will contain the sizeof(BOOL).
|
||||
// GetAssertion Input Type: Not Supported
|
||||
// GetAssertion Output Type: Not Supported
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// credProtect extension
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_USER_VERIFICATION_ANY 0
|
||||
#define WEBAUTHN_USER_VERIFICATION_OPTIONAL 1
|
||||
#define WEBAUTHN_USER_VERIFICATION_OPTIONAL_WITH_CREDENTIAL_ID_LIST 2
|
||||
#define WEBAUTHN_USER_VERIFICATION_REQUIRED 3
|
||||
|
||||
typedef struct _WEBAUTHN_CRED_PROTECT_EXTENSION_IN {
|
||||
// One of the above WEBAUTHN_USER_VERIFICATION_* values
|
||||
DWORD dwCredProtect;
|
||||
// Set the following to TRUE to require authenticator support for the credProtect extension
|
||||
BOOL bRequireCredProtect;
|
||||
} WEBAUTHN_CRED_PROTECT_EXTENSION_IN, *PWEBAUTHN_CRED_PROTECT_EXTENSION_IN;
|
||||
typedef const WEBAUTHN_CRED_PROTECT_EXTENSION_IN *PCWEBAUTHN_CRED_PROTECT_EXTENSION_IN;
|
||||
|
||||
|
||||
#define WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT L"credProtect"
|
||||
// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_PROTECT
|
||||
// MakeCredential Input Type: WEBAUTHN_CRED_PROTECT_EXTENSION_IN.
|
||||
// - pvExtension must point to a WEBAUTHN_CRED_PROTECT_EXTENSION_IN struct
|
||||
// - cbExtension will contain the sizeof(WEBAUTHN_CRED_PROTECT_EXTENSION_IN).
|
||||
// MakeCredential Output Type: DWORD.
|
||||
// - pvExtension will point to a DWORD with one of the above WEBAUTHN_USER_VERIFICATION_* values
|
||||
// if credential was successfully created with CRED_PROTECT.
|
||||
// - cbExtension will contain the sizeof(DWORD).
|
||||
// GetAssertion Input Type: Not Supported
|
||||
// GetAssertion Output Type: Not Supported
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// credBlob extension
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
typedef struct _WEBAUTHN_CRED_BLOB_EXTENSION {
|
||||
// Size of pbCredBlob.
|
||||
DWORD cbCredBlob;
|
||||
_Field_size_bytes_(cbCredBlob)
|
||||
PBYTE pbCredBlob;
|
||||
} WEBAUTHN_CRED_BLOB_EXTENSION, *PWEBAUTHN_CRED_BLOB_EXTENSION;
|
||||
typedef const WEBAUTHN_CRED_BLOB_EXTENSION *PCWEBAUTHN_CRED_BLOB_EXTENSION;
|
||||
|
||||
|
||||
#define WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB L"credBlob"
|
||||
// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_CRED_BLOB
|
||||
// MakeCredential Input Type: WEBAUTHN_CRED_BLOB_EXTENSION.
|
||||
// - pvExtension must point to a WEBAUTHN_CRED_BLOB_EXTENSION struct
|
||||
// - cbExtension must contain the sizeof(WEBAUTHN_CRED_BLOB_EXTENSION).
|
||||
// MakeCredential Output Type: BOOL.
|
||||
// - pvExtension will point to a BOOL with the value TRUE if credBlob was successfully created
|
||||
// - cbExtension will contain the sizeof(BOOL).
|
||||
// GetAssertion Input Type: BOOL.
|
||||
// - pvExtension must point to a BOOL with the value TRUE to request the credBlob.
|
||||
// - cbExtension must contain the sizeof(BOOL).
|
||||
// GetAssertion Output Type: WEBAUTHN_CRED_BLOB_EXTENSION.
|
||||
// - pvExtension will point to a WEBAUTHN_CRED_BLOB_EXTENSION struct if the authenticator
|
||||
// returns the credBlob in the signed extensions
|
||||
// - cbExtension will contain the sizeof(WEBAUTHN_CRED_BLOB_EXTENSION).
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// minPinLength extension
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH L"minPinLength"
|
||||
// Below type definitions is for WEBAUTHN_EXTENSIONS_IDENTIFIER_MIN_PIN_LENGTH
|
||||
// MakeCredential Input Type: BOOL.
|
||||
// - pvExtension must point to a BOOL with the value TRUE to request the minPinLength.
|
||||
// - cbExtension must contain the sizeof(BOOL).
|
||||
// MakeCredential Output Type: DWORD.
|
||||
// - pvExtension will point to a DWORD with the minimum pin length if returned by the authenticator
|
||||
// - cbExtension will contain the sizeof(DWORD).
|
||||
// GetAssertion Input Type: Not Supported
|
||||
// GetAssertion Output Type: Not Supported
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Information about Extensions.
|
||||
//-------------------------------------------------------------------------------------------
|
||||
typedef struct _WEBAUTHN_EXTENSION {
|
||||
LPCWSTR pwszExtensionIdentifier;
|
||||
DWORD cbExtension;
|
||||
PVOID pvExtension;
|
||||
} WEBAUTHN_EXTENSION, *PWEBAUTHN_EXTENSION;
|
||||
typedef const WEBAUTHN_EXTENSION *PCWEBAUTHN_EXTENSION;
|
||||
|
||||
typedef struct _WEBAUTHN_EXTENSIONS {
|
||||
DWORD cExtensions;
|
||||
_Field_size_(cExtensions)
|
||||
PWEBAUTHN_EXTENSION pExtensions;
|
||||
} WEBAUTHN_EXTENSIONS, *PWEBAUTHN_EXTENSIONS;
|
||||
typedef const WEBAUTHN_EXTENSIONS *PCWEBAUTHN_EXTENSIONS;
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Options.
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY 0
|
||||
#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM 1
|
||||
#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM 2
|
||||
#define WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM_U2F_V2 3
|
||||
|
||||
#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_ANY 0
|
||||
#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED 1
|
||||
#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED 2
|
||||
#define WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED 3
|
||||
|
||||
#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ANY 0
|
||||
#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_NONE 1
|
||||
#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT 2
|
||||
#define WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT 3
|
||||
|
||||
#define WEBAUTHN_ENTERPRISE_ATTESTATION_NONE 0
|
||||
#define WEBAUTHN_ENTERPRISE_ATTESTATION_VENDOR_FACILITATED 1
|
||||
#define WEBAUTHN_ENTERPRISE_ATTESTATION_PLATFORM_MANAGED 2
|
||||
|
||||
#define WEBAUTHN_LARGE_BLOB_SUPPORT_NONE 0
|
||||
#define WEBAUTHN_LARGE_BLOB_SUPPORT_REQUIRED 1
|
||||
#define WEBAUTHN_LARGE_BLOB_SUPPORT_PREFERRED 2
|
||||
|
||||
#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_1 1
|
||||
#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_2 2
|
||||
#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_3 3
|
||||
#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4 4
|
||||
#define WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_CURRENT_VERSION WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4
|
||||
|
||||
typedef struct _WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Time that the operation is expected to complete within.
|
||||
// This is used as guidance, and can be overridden by the platform.
|
||||
DWORD dwTimeoutMilliseconds;
|
||||
|
||||
// Credentials used for exclusion.
|
||||
WEBAUTHN_CREDENTIALS CredentialList;
|
||||
|
||||
// Optional extensions to parse when performing the operation.
|
||||
WEBAUTHN_EXTENSIONS Extensions;
|
||||
|
||||
// Optional. Platform vs Cross-Platform Authenticators.
|
||||
DWORD dwAuthenticatorAttachment;
|
||||
|
||||
// Optional. Require key to be resident or not. Defaulting to FALSE.
|
||||
BOOL bRequireResidentKey;
|
||||
|
||||
// User Verification Requirement.
|
||||
DWORD dwUserVerificationRequirement;
|
||||
|
||||
// Attestation Conveyance Preference.
|
||||
DWORD dwAttestationConveyancePreference;
|
||||
|
||||
// Reserved for future Use
|
||||
DWORD dwFlags;
|
||||
|
||||
//
|
||||
// The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_2
|
||||
//
|
||||
|
||||
// Cancellation Id - Optional - See WebAuthNGetCancellationId
|
||||
GUID *pCancellationId;
|
||||
|
||||
//
|
||||
// The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_3
|
||||
//
|
||||
|
||||
// Exclude Credential List. If present, "CredentialList" will be ignored.
|
||||
PWEBAUTHN_CREDENTIAL_LIST pExcludeCredentialList;
|
||||
|
||||
//
|
||||
// The following fields have been added in WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_4
|
||||
//
|
||||
|
||||
// Enterprise Attestation
|
||||
DWORD dwEnterpriseAttestation;
|
||||
|
||||
// Large Blob Support: none, required or preferred
|
||||
//
|
||||
// NTE_INVALID_PARAMETER when large blob required or preferred and
|
||||
// both bRequireResidentKey and bPreferResidentKey are set to FALSE.
|
||||
DWORD dwLargeBlobSupport;
|
||||
|
||||
// Optional. Prefer key to be resident. Defaulting to FALSE. When TRUE,
|
||||
// overrides the above bRequireResidentKey.
|
||||
BOOL bPreferResidentKey;
|
||||
|
||||
} WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS, *PWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS;
|
||||
typedef const WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS *PCWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS;
|
||||
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_NONE 0
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_GET 1
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_SET 2
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_OPERATION_DELETE 3
|
||||
|
||||
#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_1 1
|
||||
#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_2 2
|
||||
#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3 3
|
||||
#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4 4
|
||||
#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5 5
|
||||
#define WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_CURRENT_VERSION WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5
|
||||
|
||||
typedef struct _WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Time that the operation is expected to complete within.
|
||||
// This is used as guidance, and can be overridden by the platform.
|
||||
DWORD dwTimeoutMilliseconds;
|
||||
|
||||
// Allowed Credentials List.
|
||||
WEBAUTHN_CREDENTIALS CredentialList;
|
||||
|
||||
// Optional extensions to parse when performing the operation.
|
||||
WEBAUTHN_EXTENSIONS Extensions;
|
||||
|
||||
// Optional. Platform vs Cross-Platform Authenticators.
|
||||
DWORD dwAuthenticatorAttachment;
|
||||
|
||||
// User Verification Requirement.
|
||||
DWORD dwUserVerificationRequirement;
|
||||
|
||||
// Reserved for future Use
|
||||
DWORD dwFlags;
|
||||
|
||||
//
|
||||
// The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_2
|
||||
//
|
||||
|
||||
// Optional identifier for the U2F AppId. Converted to UTF8 before being hashed. Not lower cased.
|
||||
PCWSTR pwszU2fAppId;
|
||||
|
||||
// If the following is non-NULL, then, set to TRUE if the above pwszU2fAppid was used instead of
|
||||
// PCWSTR pwszRpId;
|
||||
BOOL *pbU2fAppId;
|
||||
|
||||
//
|
||||
// The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_3
|
||||
//
|
||||
|
||||
// Cancellation Id - Optional - See WebAuthNGetCancellationId
|
||||
GUID *pCancellationId;
|
||||
|
||||
//
|
||||
// The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_4
|
||||
//
|
||||
|
||||
// Allow Credential List. If present, "CredentialList" will be ignored.
|
||||
PWEBAUTHN_CREDENTIAL_LIST pAllowCredentialList;
|
||||
|
||||
//
|
||||
// The following fields have been added in WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_5
|
||||
//
|
||||
|
||||
DWORD dwCredLargeBlobOperation;
|
||||
|
||||
// Size of pbCredLargeBlob
|
||||
DWORD cbCredLargeBlob;
|
||||
_Field_size_bytes_(cbCredLargeBlob)
|
||||
PBYTE pbCredLargeBlob;
|
||||
} WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS, *PWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS;
|
||||
typedef const WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS *PCWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS;
|
||||
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// Attestation Info.
|
||||
//
|
||||
//-------------------------------------------------------------------------------------------
|
||||
#define WEBAUTHN_ATTESTATION_DECODE_NONE 0
|
||||
#define WEBAUTHN_ATTESTATION_DECODE_COMMON 1
|
||||
// WEBAUTHN_ATTESTATION_DECODE_COMMON supports format types
|
||||
// L"packed"
|
||||
// L"fido-u2f"
|
||||
|
||||
#define WEBAUTHN_ATTESTATION_VER_TPM_2_0 L"2.0"
|
||||
|
||||
typedef struct _WEBAUTHN_X5C {
|
||||
// Length of X.509 encoded certificate
|
||||
DWORD cbData;
|
||||
// X.509 encoded certificate bytes
|
||||
_Field_size_bytes_(cbData)
|
||||
PBYTE pbData;
|
||||
} WEBAUTHN_X5C, *PWEBAUTHN_X5C;
|
||||
|
||||
// Supports either Self or Full Basic Attestation
|
||||
|
||||
// Note, new fields will be added to the following data structure to
|
||||
// support additional attestation format types, such as, TPM.
|
||||
// When fields are added, the dwVersion will be incremented.
|
||||
//
|
||||
// Therefore, your code must make the following check:
|
||||
// "if (dwVersion >= WEBAUTHN_COMMON_ATTESTATION_CURRENT_VERSION)"
|
||||
|
||||
#define WEBAUTHN_COMMON_ATTESTATION_CURRENT_VERSION 1
|
||||
|
||||
typedef struct _WEBAUTHN_COMMON_ATTESTATION {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Hash and Padding Algorithm
|
||||
//
|
||||
// The following won't be set for "fido-u2f" which assumes "ES256".
|
||||
PCWSTR pwszAlg;
|
||||
LONG lAlg; // COSE algorithm
|
||||
|
||||
// Signature that was generated for this attestation.
|
||||
DWORD cbSignature;
|
||||
_Field_size_bytes_(cbSignature)
|
||||
PBYTE pbSignature;
|
||||
|
||||
// Following is set for Full Basic Attestation. If not, set then, this is Self Attestation.
|
||||
// Array of X.509 DER encoded certificates. The first certificate is the signer, leaf certificate.
|
||||
DWORD cX5c;
|
||||
_Field_size_(cX5c)
|
||||
PWEBAUTHN_X5C pX5c;
|
||||
|
||||
// Following are also set for tpm
|
||||
PCWSTR pwszVer; // L"2.0"
|
||||
DWORD cbCertInfo;
|
||||
_Field_size_bytes_(cbCertInfo)
|
||||
PBYTE pbCertInfo;
|
||||
DWORD cbPubArea;
|
||||
_Field_size_bytes_(cbPubArea)
|
||||
PBYTE pbPubArea;
|
||||
} WEBAUTHN_COMMON_ATTESTATION, *PWEBAUTHN_COMMON_ATTESTATION;
|
||||
typedef const WEBAUTHN_COMMON_ATTESTATION *PCWEBAUTHN_COMMON_ATTESTATION;
|
||||
|
||||
#define WEBAUTHN_ATTESTATION_TYPE_PACKED L"packed"
|
||||
#define WEBAUTHN_ATTESTATION_TYPE_U2F L"fido-u2f"
|
||||
#define WEBAUTHN_ATTESTATION_TYPE_TPM L"tpm"
|
||||
#define WEBAUTHN_ATTESTATION_TYPE_NONE L"none"
|
||||
|
||||
#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_1 1
|
||||
#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2 2
|
||||
#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3 3
|
||||
#define WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4 4
|
||||
#define WEBAUTHN_CREDENTIAL_ATTESTATION_CURRENT_VERSION WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4
|
||||
|
||||
typedef struct _WEBAUTHN_CREDENTIAL_ATTESTATION {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Attestation format type
|
||||
PCWSTR pwszFormatType;
|
||||
|
||||
// Size of cbAuthenticatorData.
|
||||
DWORD cbAuthenticatorData;
|
||||
// Authenticator data that was created for this credential.
|
||||
_Field_size_bytes_(cbAuthenticatorData)
|
||||
PBYTE pbAuthenticatorData;
|
||||
|
||||
// Size of CBOR encoded attestation information
|
||||
//0 => encoded as CBOR null value.
|
||||
DWORD cbAttestation;
|
||||
//Encoded CBOR attestation information
|
||||
_Field_size_bytes_(cbAttestation)
|
||||
PBYTE pbAttestation;
|
||||
|
||||
DWORD dwAttestationDecodeType;
|
||||
// Following depends on the dwAttestationDecodeType
|
||||
// WEBAUTHN_ATTESTATION_DECODE_NONE
|
||||
// NULL - not able to decode the CBOR attestation information
|
||||
// WEBAUTHN_ATTESTATION_DECODE_COMMON
|
||||
// PWEBAUTHN_COMMON_ATTESTATION;
|
||||
PVOID pvAttestationDecode;
|
||||
|
||||
// The CBOR encoded Attestation Object to be returned to the RP.
|
||||
DWORD cbAttestationObject;
|
||||
_Field_size_bytes_(cbAttestationObject)
|
||||
PBYTE pbAttestationObject;
|
||||
|
||||
// The CredentialId bytes extracted from the Authenticator Data.
|
||||
// Used by Edge to return to the RP.
|
||||
DWORD cbCredentialId;
|
||||
_Field_size_bytes_(cbCredentialId)
|
||||
PBYTE pbCredentialId;
|
||||
|
||||
//
|
||||
// Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_2
|
||||
//
|
||||
|
||||
WEBAUTHN_EXTENSIONS Extensions;
|
||||
|
||||
//
|
||||
// Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_3
|
||||
//
|
||||
|
||||
// One of the WEBAUTHN_CTAP_TRANSPORT_* bits will be set corresponding to
|
||||
// the transport that was used.
|
||||
DWORD dwUsedTransport;
|
||||
|
||||
//
|
||||
// Following fields have been added in WEBAUTHN_CREDENTIAL_ATTESTATION_VERSION_4
|
||||
//
|
||||
|
||||
BOOL bEpAtt;
|
||||
BOOL bLargeBlobSupported;
|
||||
BOOL bResidentKey;
|
||||
|
||||
} WEBAUTHN_CREDENTIAL_ATTESTATION, *PWEBAUTHN_CREDENTIAL_ATTESTATION;
|
||||
typedef const WEBAUTHN_CREDENTIAL_ATTESTATION *PCWEBAUTHN_CREDENTIAL_ATTESTATION;
|
||||
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// authenticatorGetAssertion output.
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_NONE 0
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_SUCCESS 1
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_NOT_SUPPORTED 2
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_INVALID_DATA 3
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_INVALID_PARAMETER 4
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_NOT_FOUND 5
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_MULTIPLE_CREDENTIALS 6
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_LACK_OF_SPACE 7
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_PLATFORM_ERROR 8
|
||||
#define WEBAUTHN_CRED_LARGE_BLOB_STATUS_AUTHENTICATOR_ERROR 9
|
||||
|
||||
#define WEBAUTHN_ASSERTION_VERSION_1 1
|
||||
#define WEBAUTHN_ASSERTION_VERSION_2 2
|
||||
#define WEBAUTHN_ASSERTION_CURRENT_VERSION WEBAUTHN_ASSERTION_VERSION_2
|
||||
|
||||
typedef struct _WEBAUTHN_ASSERTION {
|
||||
// Version of this structure, to allow for modifications in the future.
|
||||
DWORD dwVersion;
|
||||
|
||||
// Size of cbAuthenticatorData.
|
||||
DWORD cbAuthenticatorData;
|
||||
// Authenticator data that was created for this assertion.
|
||||
_Field_size_bytes_(cbAuthenticatorData)
|
||||
PBYTE pbAuthenticatorData;
|
||||
|
||||
// Size of pbSignature.
|
||||
DWORD cbSignature;
|
||||
// Signature that was generated for this assertion.
|
||||
_Field_size_bytes_(cbSignature)
|
||||
PBYTE pbSignature;
|
||||
|
||||
// Credential that was used for this assertion.
|
||||
WEBAUTHN_CREDENTIAL Credential;
|
||||
|
||||
// Size of User Id
|
||||
DWORD cbUserId;
|
||||
// UserId
|
||||
_Field_size_bytes_(cbUserId)
|
||||
PBYTE pbUserId;
|
||||
|
||||
//
|
||||
// Following fields have been added in WEBAUTHN_ASSERTION_VERSION_2
|
||||
//
|
||||
|
||||
WEBAUTHN_EXTENSIONS Extensions;
|
||||
|
||||
// Size of pbCredLargeBlob
|
||||
DWORD cbCredLargeBlob;
|
||||
_Field_size_bytes_(cbCredLargeBlob)
|
||||
PBYTE pbCredLargeBlob;
|
||||
|
||||
DWORD dwCredLargeBlobStatus;
|
||||
|
||||
} WEBAUTHN_ASSERTION, *PWEBAUTHN_ASSERTION;
|
||||
typedef const WEBAUTHN_ASSERTION *PCWEBAUTHN_ASSERTION;
|
||||
|
||||
//+------------------------------------------------------------------------------------------
|
||||
// APIs.
|
||||
//-------------------------------------------------------------------------------------------
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
WebAuthNGetApiVersionNumber();
|
||||
|
||||
HRESULT
|
||||
WINAPI
|
||||
WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable(
|
||||
_Out_ BOOL *pbIsUserVerifyingPlatformAuthenticatorAvailable);
|
||||
|
||||
|
||||
HRESULT
|
||||
WINAPI
|
||||
WebAuthNAuthenticatorMakeCredential(
|
||||
_In_ HWND hWnd,
|
||||
_In_ PCWEBAUTHN_RP_ENTITY_INFORMATION pRpInformation,
|
||||
_In_ PCWEBAUTHN_USER_ENTITY_INFORMATION pUserInformation,
|
||||
_In_ PCWEBAUTHN_COSE_CREDENTIAL_PARAMETERS pPubKeyCredParams,
|
||||
_In_ PCWEBAUTHN_CLIENT_DATA pWebAuthNClientData,
|
||||
_In_opt_ PCWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS pWebAuthNMakeCredentialOptions,
|
||||
_Outptr_result_maybenull_ PWEBAUTHN_CREDENTIAL_ATTESTATION *ppWebAuthNCredentialAttestation);
|
||||
|
||||
|
||||
HRESULT
|
||||
WINAPI
|
||||
WebAuthNAuthenticatorGetAssertion(
|
||||
_In_ HWND hWnd,
|
||||
_In_ LPCWSTR pwszRpId,
|
||||
_In_ PCWEBAUTHN_CLIENT_DATA pWebAuthNClientData,
|
||||
_In_opt_ PCWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS pWebAuthNGetAssertionOptions,
|
||||
_Outptr_result_maybenull_ PWEBAUTHN_ASSERTION *ppWebAuthNAssertion);
|
||||
|
||||
void
|
||||
WINAPI
|
||||
WebAuthNFreeCredentialAttestation(
|
||||
_In_opt_ PWEBAUTHN_CREDENTIAL_ATTESTATION pWebAuthNCredentialAttestation);
|
||||
|
||||
void
|
||||
WINAPI
|
||||
WebAuthNFreeAssertion(
|
||||
_In_ PWEBAUTHN_ASSERTION pWebAuthNAssertion);
|
||||
|
||||
HRESULT
|
||||
WINAPI
|
||||
WebAuthNGetCancellationId(
|
||||
_Out_ GUID* pCancellationId);
|
||||
|
||||
HRESULT
|
||||
WINAPI
|
||||
WebAuthNCancelCurrentOperation(
|
||||
_In_ const GUID* pCancellationId);
|
||||
|
||||
//
|
||||
// Returns the following Error Names:
|
||||
// L"Success" - S_OK
|
||||
// L"InvalidStateError" - NTE_EXISTS
|
||||
// L"ConstraintError" - HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED),
|
||||
// NTE_NOT_SUPPORTED,
|
||||
// NTE_TOKEN_KEYSET_STORAGE_FULL
|
||||
// L"NotSupportedError" - NTE_INVALID_PARAMETER
|
||||
// L"NotAllowedError" - NTE_DEVICE_NOT_FOUND,
|
||||
// NTE_NOT_FOUND,
|
||||
// HRESULT_FROM_WIN32(ERROR_CANCELLED),
|
||||
// NTE_USER_CANCELLED,
|
||||
// HRESULT_FROM_WIN32(ERROR_TIMEOUT)
|
||||
// L"UnknownError" - All other hr values
|
||||
//
|
||||
PCWSTR
|
||||
WINAPI
|
||||
WebAuthNGetErrorName(
|
||||
_In_ HRESULT hr);
|
||||
|
||||
HRESULT
|
||||
WINAPI
|
||||
WebAuthNGetW3CExceptionDOMError(
|
||||
_In_ HRESULT hr);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // Balance extern "C" above
|
||||
#endif
|
||||
|
||||
#endif // WINAPI_FAMILY_PARTITION
|
||||
#pragma endregion
|
||||
|
||||
#endif // __WEBAUTHN_H_
|
387
src/winhello.c
387
src/winhello.c
@ -8,9 +8,9 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
#include <webauthn.h>
|
||||
|
||||
#include "fido.h"
|
||||
#include "webauthn.h"
|
||||
|
||||
#define MAXCHARS 128
|
||||
#define MAXCREDS 128
|
||||
@ -40,6 +40,87 @@ struct winhello_cred {
|
||||
wchar_t *display_name;
|
||||
};
|
||||
|
||||
static TLS BOOL webauthn_loaded;
|
||||
static TLS HMODULE webauthn_handle;
|
||||
static TLS DWORD (*webauthn_get_api_version)(void);
|
||||
static TLS PCWSTR (*webauthn_strerr)(HRESULT);
|
||||
static TLS HRESULT (*webauthn_get_assert)(HWND, LPCWSTR,
|
||||
PCWEBAUTHN_CLIENT_DATA,
|
||||
PCWEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS,
|
||||
PWEBAUTHN_ASSERTION *);
|
||||
static TLS HRESULT (*webauthn_make_cred)(HWND,
|
||||
PCWEBAUTHN_RP_ENTITY_INFORMATION,
|
||||
PCWEBAUTHN_USER_ENTITY_INFORMATION,
|
||||
PCWEBAUTHN_COSE_CREDENTIAL_PARAMETERS,
|
||||
PCWEBAUTHN_CLIENT_DATA,
|
||||
PCWEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS,
|
||||
PWEBAUTHN_CREDENTIAL_ATTESTATION *);
|
||||
static TLS void (*webauthn_free_assert)(PWEBAUTHN_ASSERTION);
|
||||
static TLS void (*webauthn_free_attest)(PWEBAUTHN_CREDENTIAL_ATTESTATION);
|
||||
|
||||
static int
|
||||
webauthn_load(void)
|
||||
{
|
||||
if (webauthn_loaded || webauthn_handle != NULL) {
|
||||
fido_log_debug("%s: already loaded", __func__);
|
||||
return -1;
|
||||
}
|
||||
if ((webauthn_handle = LoadLibrary("webauthn.dll")) == NULL) {
|
||||
fido_log_debug("%s: LoadLibrary", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((webauthn_get_api_version = (void *)GetProcAddress(webauthn_handle,
|
||||
"WebAuthNGetApiVersionNumber")) == NULL) {
|
||||
fido_log_debug("%s: WebAuthNGetApiVersionNumber", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((webauthn_strerr = (void *)GetProcAddress(webauthn_handle,
|
||||
"WebAuthNGetErrorName")) == NULL) {
|
||||
fido_log_debug("%s: WebAuthNGetErrorName", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((webauthn_get_assert = (void *)GetProcAddress(webauthn_handle,
|
||||
"WebAuthNAuthenticatorGetAssertion")) == NULL) {
|
||||
fido_log_debug("%s: WebAuthNAuthenticatorGetAssertion",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((webauthn_make_cred = (void *)GetProcAddress(webauthn_handle,
|
||||
"WebAuthNAuthenticatorMakeCredential")) == NULL) {
|
||||
fido_log_debug("%s: WebAuthNAuthenticatorMakeCredential",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((webauthn_free_assert = (void *)GetProcAddress(webauthn_handle,
|
||||
"WebAuthNFreeAssertion")) == NULL) {
|
||||
fido_log_debug("%s: WebAuthNFreeAssertion", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((webauthn_free_attest = (void *)GetProcAddress(webauthn_handle,
|
||||
"WebAuthNFreeCredentialAttestation")) == NULL) {
|
||||
fido_log_debug("%s: WebAuthNFreeCredentialAttestation",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
webauthn_loaded = true;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
fido_log_debug("%s: GetProcAddress", __func__);
|
||||
webauthn_get_api_version = NULL;
|
||||
webauthn_strerr = NULL;
|
||||
webauthn_get_assert = NULL;
|
||||
webauthn_make_cred = NULL;
|
||||
webauthn_free_assert = NULL;
|
||||
webauthn_free_attest = NULL;
|
||||
FreeLibrary(webauthn_handle);
|
||||
webauthn_handle = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static wchar_t *
|
||||
to_utf16(const char *utf8)
|
||||
{
|
||||
@ -97,24 +178,6 @@ to_utf8(const wchar_t *utf16)
|
||||
return utf8;
|
||||
}
|
||||
|
||||
static int
|
||||
to_fido_str_array(fido_str_array_t *sa, const char **v, size_t n)
|
||||
{
|
||||
if ((sa->ptr = calloc(n, sizeof(char *))) == NULL) {
|
||||
fido_log_debug("%s: calloc", __func__);
|
||||
return -1;
|
||||
}
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if ((sa->ptr[i] = strdup(v[i])) == NULL) {
|
||||
fido_log_debug("%s: strdup", __func__);
|
||||
return -1;
|
||||
}
|
||||
sa->len++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
to_fido(HRESULT hr)
|
||||
{
|
||||
@ -210,7 +273,7 @@ set_uv(DWORD *out, fido_opt_t uv, const char *pin)
|
||||
|
||||
static int
|
||||
pack_rp(wchar_t **id, wchar_t **name, WEBAUTHN_RP_ENTITY_INFORMATION *out,
|
||||
fido_rp_t *in)
|
||||
const fido_rp_t *in)
|
||||
{
|
||||
/* keep non-const copies of pwsz* for free() */
|
||||
out->dwVersion = WEBAUTHN_RP_ENTITY_INFORMATION_CURRENT_VERSION;
|
||||
@ -227,7 +290,7 @@ pack_rp(wchar_t **id, wchar_t **name, WEBAUTHN_RP_ENTITY_INFORMATION *out,
|
||||
|
||||
static int
|
||||
pack_user(wchar_t **name, wchar_t **icon, wchar_t **display_name,
|
||||
WEBAUTHN_USER_ENTITY_INFORMATION *out, fido_user_t *in)
|
||||
WEBAUTHN_USER_ENTITY_INFORMATION *out, const fido_user_t *in)
|
||||
{
|
||||
if (in->id.ptr == NULL || in->id.len > ULONG_MAX) {
|
||||
fido_log_debug("%s: id", __func__);
|
||||
@ -287,7 +350,7 @@ pack_cose(WEBAUTHN_COSE_CREDENTIAL_PARAMETER *alg,
|
||||
}
|
||||
|
||||
static int
|
||||
pack_cred_ext(WEBAUTHN_EXTENSIONS *out, fido_cred_ext_t *in)
|
||||
pack_cred_ext(WEBAUTHN_EXTENSIONS *out, const fido_cred_ext_t *in)
|
||||
{
|
||||
WEBAUTHN_EXTENSION *e;
|
||||
WEBAUTHN_CRED_PROTECT_EXTENSION_IN *p;
|
||||
@ -342,94 +405,7 @@ pack_cred_ext(WEBAUTHN_EXTENSIONS *out, fido_cred_ext_t *in)
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_fmt(fido_cred_t *cred, WEBAUTHN_CREDENTIAL_ATTESTATION *att)
|
||||
{
|
||||
char *fmt;
|
||||
int r;
|
||||
|
||||
if ((fmt = to_utf8(att->pwszFormatType)) == NULL) {
|
||||
fido_log_debug("%s: fmt", __func__);
|
||||
return -1;
|
||||
}
|
||||
r = fido_cred_set_fmt(cred, fmt);
|
||||
free(fmt);
|
||||
fmt = NULL;
|
||||
if (r != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_cred_set_fmt: %s", __func__,
|
||||
fido_strerr(r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_cred_authdata(fido_cred_t *cred, WEBAUTHN_CREDENTIAL_ATTESTATION *att)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (att->cbAuthenticatorData > SIZE_MAX) {
|
||||
fido_log_debug("%s: cbAuthenticatorData", __func__);
|
||||
return -1;
|
||||
}
|
||||
if ((r = fido_cred_set_authdata_raw(cred, att->pbAuthenticatorData,
|
||||
(size_t)att->cbAuthenticatorData)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_cred_set_authdata_raw: %s", __func__,
|
||||
fido_strerr(r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_cred_sig(fido_cred_t *cred, WEBAUTHN_COMMON_ATTESTATION *attr)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (attr->cbSignature > SIZE_MAX) {
|
||||
fido_log_debug("%s: cbSignature", __func__);
|
||||
return -1;
|
||||
}
|
||||
if ((r = fido_cred_set_sig(cred, attr->pbSignature,
|
||||
(size_t)attr->cbSignature)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_cred_set_sig: %s", __func__,
|
||||
fido_strerr(r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_x5c(fido_cred_t *cred, WEBAUTHN_COMMON_ATTESTATION *attr)
|
||||
{
|
||||
int r;
|
||||
|
||||
fido_log_debug("%s: %u cert(s)", __func__, attr->cX5c);
|
||||
|
||||
if (attr->cX5c == 0)
|
||||
return 0; /* self-attestation */
|
||||
if (attr->lAlg != WEBAUTHN_COSE_ALGORITHM_ECDSA_P256_WITH_SHA256) {
|
||||
fido_log_debug("%s: lAlg %d", __func__, attr->lAlg);
|
||||
return -1;
|
||||
}
|
||||
if (attr->pX5c[0].cbData > SIZE_MAX) {
|
||||
fido_log_debug("%s: cbData", __func__);
|
||||
return -1;
|
||||
}
|
||||
if ((r = fido_cred_set_x509(cred, attr->pX5c[0].pbData,
|
||||
(size_t)attr->pX5c[0].cbData)) != FIDO_OK) {
|
||||
fido_log_debug("%s: fido_cred_set_x509: %s", __func__,
|
||||
fido_strerr(r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_assert_authdata(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
unpack_assert_authdata(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -448,7 +424,7 @@ unpack_assert_authdata(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_assert_sig(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
unpack_assert_sig(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -467,7 +443,7 @@ unpack_assert_sig(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_cred_id(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
unpack_cred_id(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)
|
||||
{
|
||||
if (wa->Credential.cbId > SIZE_MAX) {
|
||||
fido_log_debug("%s: Credential.cbId", __func__);
|
||||
@ -483,7 +459,7 @@ unpack_cred_id(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
}
|
||||
|
||||
static int
|
||||
unpack_user_id(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
unpack_user_id(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)
|
||||
{
|
||||
if (wa->cbUserId == 0)
|
||||
return 0; /* user id absent */
|
||||
@ -501,8 +477,8 @@ unpack_user_id(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
}
|
||||
|
||||
static int
|
||||
translate_fido_assert(struct winhello_assert *ctx, fido_assert_t *assert,
|
||||
const char *pin)
|
||||
translate_fido_assert(struct winhello_assert *ctx, const fido_assert_t *assert,
|
||||
const char *pin, int ms)
|
||||
{
|
||||
WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS *opt;
|
||||
|
||||
@ -527,7 +503,7 @@ translate_fido_assert(struct winhello_assert *ctx, fido_assert_t *assert,
|
||||
/* options */
|
||||
opt = &ctx->opt;
|
||||
opt->dwVersion = WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS_VERSION_1;
|
||||
opt->dwTimeoutMilliseconds = MAXMSEC;
|
||||
opt->dwTimeoutMilliseconds = ms < 0 ? MAXMSEC : (DWORD)ms;
|
||||
if (pack_credlist(&opt->CredentialList, &assert->allow_list) < 0) {
|
||||
fido_log_debug("%s: pack_credlist", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
@ -541,7 +517,7 @@ translate_fido_assert(struct winhello_assert *ctx, fido_assert_t *assert,
|
||||
}
|
||||
|
||||
static int
|
||||
translate_winhello_assert(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
translate_winhello_assert(fido_assert_t *assert, const WEBAUTHN_ASSERTION *wa)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -575,8 +551,8 @@ translate_winhello_assert(fido_assert_t *assert, WEBAUTHN_ASSERTION *wa)
|
||||
}
|
||||
|
||||
static int
|
||||
translate_fido_cred(struct winhello_cred *ctx, fido_cred_t *cred,
|
||||
const char *pin)
|
||||
translate_fido_cred(struct winhello_cred *ctx, const fido_cred_t *cred,
|
||||
const char *pin, int ms)
|
||||
{
|
||||
WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS *opt;
|
||||
|
||||
@ -600,7 +576,9 @@ translate_fido_cred(struct winhello_cred *ctx, fido_cred_t *cred,
|
||||
/* options */
|
||||
opt = &ctx->opt;
|
||||
opt->dwVersion = WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS_VERSION_1;
|
||||
opt->dwTimeoutMilliseconds = MAXMSEC;
|
||||
opt->dwTimeoutMilliseconds = ms < 0 ? MAXMSEC : (DWORD)ms;
|
||||
opt->dwAttestationConveyancePreference =
|
||||
WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT;
|
||||
if (pack_credlist(&opt->CredentialList, &cred->excl) < 0) {
|
||||
fido_log_debug("%s: pack_credlist", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
@ -609,7 +587,8 @@ translate_fido_cred(struct winhello_cred *ctx, fido_cred_t *cred,
|
||||
fido_log_debug("%s: pack_cred_ext", __func__);
|
||||
return FIDO_ERR_UNSUPPORTED_EXTENSION;
|
||||
}
|
||||
if (set_uv(&opt->dwUserVerificationRequirement, cred->uv, pin) < 0) {
|
||||
if (set_uv(&opt->dwUserVerificationRequirement, (cred->ext.mask &
|
||||
FIDO_EXT_CRED_PROTECT) ? FIDO_OPT_TRUE : cred->uv, pin) < 0) {
|
||||
fido_log_debug("%s: set_uv", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
@ -621,67 +600,94 @@ translate_fido_cred(struct winhello_cred *ctx, fido_cred_t *cred,
|
||||
}
|
||||
|
||||
static int
|
||||
translate_winhello_cred(fido_cred_t *cred, WEBAUTHN_CREDENTIAL_ATTESTATION *att)
|
||||
decode_attobj(const cbor_item_t *key, const cbor_item_t *val, void *arg)
|
||||
{
|
||||
if (unpack_fmt(cred, att) < 0) {
|
||||
fido_log_debug("%s: unpack_fmt", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
if (unpack_cred_authdata(cred, att) < 0) {
|
||||
fido_log_debug("%s: unpack_cred_authdata", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
fido_cred_t *cred = arg;
|
||||
char *name = NULL;
|
||||
int ok = -1;
|
||||
|
||||
if (cbor_string_copy(key, &name) < 0) {
|
||||
fido_log_debug("%s: cbor type", __func__);
|
||||
ok = 0; /* ignore */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (att->dwAttestationDecodeType) {
|
||||
case WEBAUTHN_ATTESTATION_DECODE_NONE:
|
||||
if (att->pvAttestationDecode != NULL) {
|
||||
fido_log_debug("%s: pvAttestationDecode", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
if (!strcmp(name, "fmt")) {
|
||||
if (cbor_decode_fmt(val, &cred->fmt) < 0) {
|
||||
fido_log_debug("%s: cbor_decode_fmt", __func__);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case WEBAUTHN_ATTESTATION_DECODE_COMMON:
|
||||
if (att->pvAttestationDecode == NULL) {
|
||||
fido_log_debug("%s: pvAttestationDecode", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
} else if (!strcmp(name, "attStmt")) {
|
||||
if (cbor_decode_attstmt(val, &cred->attstmt) < 0) {
|
||||
fido_log_debug("%s: cbor_decode_attstmt", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if (unpack_cred_sig(cred, att->pvAttestationDecode) < 0) {
|
||||
fido_log_debug("%s: unpack_cred_sig", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
} else if (!strcmp(name, "authData")) {
|
||||
if (cbor_decode_cred_authdata(val, cred->type,
|
||||
&cred->authdata_cbor, &cred->authdata, &cred->attcred,
|
||||
&cred->authdata_ext) < 0) {
|
||||
fido_log_debug("%s: cbor_decode_cred_authdata",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
if (unpack_x5c(cred, att->pvAttestationDecode) < 0) {
|
||||
fido_log_debug("%s: unpack_x5c", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fido_log_debug("%s: dwAttestationDecodeType: %u", __func__,
|
||||
att->dwAttestationDecodeType);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
return FIDO_OK;
|
||||
ok = 0;
|
||||
fail:
|
||||
free(name);
|
||||
|
||||
return (ok);
|
||||
}
|
||||
|
||||
static int
|
||||
winhello_manifest(BOOL *present)
|
||||
translate_winhello_cred(fido_cred_t *cred, const WEBAUTHN_CREDENTIAL_ATTESTATION *att)
|
||||
{
|
||||
|
||||
cbor_item_t *item = NULL;
|
||||
struct cbor_load_result cbor;
|
||||
int r = FIDO_ERR_INTERNAL;
|
||||
|
||||
if (att->pbAttestationObject == NULL ||
|
||||
att->cbAttestationObject > SIZE_MAX) {
|
||||
fido_log_debug("%s: pbAttestationObject", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((item = cbor_load(att->pbAttestationObject,
|
||||
(size_t)att->cbAttestationObject, &cbor)) == NULL) {
|
||||
fido_log_debug("%s: cbor_load", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if (cbor_isa_map(item) == false ||
|
||||
cbor_map_is_definite(item) == false ||
|
||||
cbor_map_iter(item, cred, decode_attobj) < 0) {
|
||||
fido_log_debug("%s: cbor type", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = FIDO_OK;
|
||||
fail:
|
||||
if (item != NULL)
|
||||
cbor_decref(&item);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
winhello_manifest(void)
|
||||
{
|
||||
DWORD n;
|
||||
HRESULT hr;
|
||||
int r = FIDO_OK;
|
||||
|
||||
if ((n = WebAuthNGetApiVersionNumber()) < 1) {
|
||||
if (!webauthn_loaded && webauthn_load() < 0) {
|
||||
fido_log_debug("%s: webauthn_load", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
if ((n = webauthn_get_api_version()) < 1) {
|
||||
fido_log_debug("%s: unsupported api %u", __func__, n);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
fido_log_debug("%s: api version %u", __func__, n);
|
||||
hr = WebAuthNIsUserVerifyingPlatformAuthenticatorAvailable(present);
|
||||
if (hr != S_OK) {
|
||||
r = to_fido(hr);
|
||||
fido_log_debug("%s: %ls -> %s", __func__,
|
||||
WebAuthNGetErrorName(hr), fido_strerr(r));
|
||||
}
|
||||
|
||||
return r;
|
||||
return FIDO_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -690,12 +696,11 @@ winhello_get_assert(HWND w, struct winhello_assert *ctx)
|
||||
HRESULT hr;
|
||||
int r = FIDO_OK;
|
||||
|
||||
hr = WebAuthNAuthenticatorGetAssertion(w, ctx->rp_id, &ctx->cd,
|
||||
&ctx->opt, &ctx->assert);
|
||||
if (hr != S_OK) {
|
||||
if ((hr = webauthn_get_assert(w, ctx->rp_id, &ctx->cd, &ctx->opt,
|
||||
&ctx->assert)) != S_OK) {
|
||||
r = to_fido(hr);
|
||||
fido_log_debug("%s: %ls -> %s", __func__,
|
||||
WebAuthNGetErrorName(hr), fido_strerr(r));
|
||||
fido_log_debug("%s: %ls -> %s", __func__, webauthn_strerr(hr),
|
||||
fido_strerr(r));
|
||||
}
|
||||
|
||||
return r;
|
||||
@ -707,12 +712,11 @@ winhello_make_cred(HWND w, struct winhello_cred *ctx)
|
||||
HRESULT hr;
|
||||
int r = FIDO_OK;
|
||||
|
||||
hr = WebAuthNAuthenticatorMakeCredential(w, &ctx->rp, &ctx->user,
|
||||
&ctx->cose, &ctx->cd, &ctx->opt, &ctx->att);
|
||||
if (hr != S_OK) {
|
||||
if ((hr = webauthn_make_cred(w, &ctx->rp, &ctx->user, &ctx->cose,
|
||||
&ctx->cd, &ctx->opt, &ctx->att)) != S_OK) {
|
||||
r = to_fido(hr);
|
||||
fido_log_debug("%s: %ls -> %s", __func__,
|
||||
WebAuthNGetErrorName(hr), fido_strerr(r));
|
||||
fido_log_debug("%s: %ls -> %s", __func__, webauthn_strerr(hr),
|
||||
fido_strerr(r));
|
||||
}
|
||||
|
||||
return r;
|
||||
@ -724,7 +728,7 @@ winhello_assert_free(struct winhello_assert *ctx)
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
if (ctx->assert != NULL)
|
||||
WebAuthNFreeAssertion(ctx->assert);
|
||||
webauthn_free_assert(ctx->assert);
|
||||
|
||||
free(ctx->rp_id);
|
||||
free(ctx->opt.CredentialList.pCredentials);
|
||||
@ -737,7 +741,7 @@ winhello_cred_free(struct winhello_cred *ctx)
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
if (ctx->att != NULL)
|
||||
WebAuthNFreeCredentialAttestation(ctx->att);
|
||||
webauthn_free_attest(ctx->att);
|
||||
|
||||
free(ctx->rp_id);
|
||||
free(ctx->rp_name);
|
||||
@ -758,7 +762,6 @@ int
|
||||
fido_winhello_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
|
||||
{
|
||||
int r;
|
||||
BOOL present;
|
||||
fido_dev_info_t *di;
|
||||
|
||||
if (ilen == 0) {
|
||||
@ -767,14 +770,10 @@ fido_winhello_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
|
||||
if (devlist == NULL) {
|
||||
return FIDO_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
if ((r = winhello_manifest(&present)) != FIDO_OK) {
|
||||
if ((r = winhello_manifest()) != FIDO_OK) {
|
||||
fido_log_debug("%s: winhello_manifest", __func__);
|
||||
return r;
|
||||
}
|
||||
if (present == false) {
|
||||
fido_log_debug("%s: not present", __func__);
|
||||
return FIDO_OK;
|
||||
}
|
||||
|
||||
di = &devlist[*olen];
|
||||
memset(di, 0, sizeof(*di));
|
||||
@ -799,9 +798,12 @@ fido_winhello_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen)
|
||||
int
|
||||
fido_winhello_open(fido_dev_t *dev)
|
||||
{
|
||||
if (!webauthn_loaded && webauthn_load() < 0) {
|
||||
fido_log_debug("%s: webauthn_load", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
if (dev->flags != 0)
|
||||
return FIDO_ERR_INVALID_ARGUMENT;
|
||||
|
||||
dev->attr.flags = FIDO_CAP_CBOR | FIDO_CAP_WINK;
|
||||
dev->flags = FIDO_DEV_WINHELLO | FIDO_DEV_CRED_PROT | FIDO_DEV_PIN_SET;
|
||||
|
||||
@ -826,7 +828,7 @@ fido_winhello_cancel(fido_dev_t *dev)
|
||||
|
||||
int
|
||||
fido_winhello_get_assert(fido_dev_t *dev, fido_assert_t *assert,
|
||||
const char *pin)
|
||||
const char *pin, int ms)
|
||||
{
|
||||
HWND w;
|
||||
struct winhello_assert *ctx;
|
||||
@ -834,6 +836,8 @@ fido_winhello_get_assert(fido_dev_t *dev, fido_assert_t *assert,
|
||||
|
||||
(void)dev;
|
||||
|
||||
fido_assert_reset_rx(assert);
|
||||
|
||||
if ((ctx = calloc(1, sizeof(*ctx))) == NULL) {
|
||||
fido_log_debug("%s: calloc", __func__);
|
||||
goto fail;
|
||||
@ -842,7 +846,7 @@ fido_winhello_get_assert(fido_dev_t *dev, fido_assert_t *assert,
|
||||
fido_log_debug("%s: GetForegroundWindow", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((r = translate_fido_assert(ctx, assert, pin)) != FIDO_OK) {
|
||||
if ((r = translate_fido_assert(ctx, assert, pin, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: translate_fido_assert", __func__);
|
||||
goto fail;
|
||||
}
|
||||
@ -873,10 +877,10 @@ fido_winhello_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
|
||||
|
||||
fido_cbor_info_reset(ci);
|
||||
|
||||
if (to_fido_str_array(&ci->versions, v, nitems(v)) < 0 ||
|
||||
to_fido_str_array(&ci->extensions, e, nitems(e)) < 0 ||
|
||||
to_fido_str_array(&ci->transports, t, nitems(t)) < 0) {
|
||||
fido_log_debug("%s: to_fido_str_array", __func__);
|
||||
if (fido_str_array_pack(&ci->versions, v, nitems(v)) < 0 ||
|
||||
fido_str_array_pack(&ci->extensions, e, nitems(e)) < 0 ||
|
||||
fido_str_array_pack(&ci->transports, t, nitems(t)) < 0) {
|
||||
fido_log_debug("%s: fido_str_array_pack", __func__);
|
||||
return FIDO_ERR_INTERNAL;
|
||||
}
|
||||
if ((ci->options.name = calloc(nitems(o), sizeof(char *))) == NULL ||
|
||||
@ -897,7 +901,8 @@ fido_winhello_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
|
||||
}
|
||||
|
||||
int
|
||||
fido_winhello_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
|
||||
fido_winhello_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin,
|
||||
int ms)
|
||||
{
|
||||
HWND w;
|
||||
struct winhello_cred *ctx;
|
||||
@ -905,6 +910,8 @@ fido_winhello_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
|
||||
|
||||
(void)dev;
|
||||
|
||||
fido_cred_reset_rx(cred);
|
||||
|
||||
if ((ctx = calloc(1, sizeof(*ctx))) == NULL) {
|
||||
fido_log_debug("%s: calloc", __func__);
|
||||
goto fail;
|
||||
@ -913,7 +920,7 @@ fido_winhello_make_cred(fido_dev_t *dev, fido_cred_t *cred, const char *pin)
|
||||
fido_log_debug("%s: GetForegroundWindow", __func__);
|
||||
goto fail;
|
||||
}
|
||||
if ((r = translate_fido_cred(ctx, cred, pin)) != FIDO_OK) {
|
||||
if ((r = translate_fido_cred(ctx, cred, pin, ms)) != FIDO_OK) {
|
||||
fido_log_debug("%s: translate_fido_cred", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
@ -3,10 +3,13 @@
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
list(APPEND COMPAT_SOURCES
|
||||
../openbsd-compat/bsd-getpagesize.c
|
||||
../openbsd-compat/explicit_bzero.c
|
||||
../openbsd-compat/freezero.c
|
||||
../openbsd-compat/recallocarray.c
|
||||
../openbsd-compat/strlcat.c
|
||||
../openbsd-compat/strlcpy.c
|
||||
../openbsd-compat/strsep.c
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT CYGWIN AND NOT MSYS)
|
||||
|
@ -147,3 +147,51 @@ config_force_pin_change(char *path)
|
||||
|
||||
exit(ok);
|
||||
}
|
||||
|
||||
int
|
||||
config_pin_minlen_rpid(char *path, const char *rpids)
|
||||
{
|
||||
fido_dev_t *dev;
|
||||
char *otmp, *tmp, *cp;
|
||||
char *pin = NULL, **rpid = NULL;
|
||||
int r, ok = 1;
|
||||
size_t n;
|
||||
|
||||
if ((tmp = strdup(rpids)) == NULL)
|
||||
err(1, "strdup");
|
||||
otmp = tmp;
|
||||
for (n = 0; (cp = strsep(&tmp, ",")) != NULL; n++) {
|
||||
if (n == SIZE_MAX || (rpid = recallocarray(rpid, n, n + 1,
|
||||
sizeof(*rpid))) == NULL)
|
||||
err(1, "recallocarray");
|
||||
if ((rpid[n] = strdup(cp)) == NULL)
|
||||
err(1, "strdup");
|
||||
if (*rpid[n] == '\0')
|
||||
errx(1, "empty rpid");
|
||||
}
|
||||
free(otmp);
|
||||
if (rpid == NULL || n == 0)
|
||||
errx(1, "could not parse rp_id");
|
||||
dev = open_dev(path);
|
||||
if ((r = fido_dev_set_pin_minlen_rpid(dev, (const char * const *)rpid,
|
||||
n, NULL)) != FIDO_OK && should_retry_with_pin(dev, r)) {
|
||||
if ((pin = get_pin(path)) == NULL)
|
||||
goto out;
|
||||
r = fido_dev_set_pin_minlen_rpid(dev, (const char * const *)rpid,
|
||||
n, pin);
|
||||
freezero(pin, PINBUF_LEN);
|
||||
pin = NULL;
|
||||
}
|
||||
if (r != FIDO_OK) {
|
||||
warnx("fido_dev_set_pin_minlen_rpid: %s (0x%x)",
|
||||
fido_strerr(r), r);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ok = 0;
|
||||
out:
|
||||
fido_dev_close(dev);
|
||||
fido_dev_free(&dev);
|
||||
|
||||
exit(ok);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ struct blob {
|
||||
size_t len;
|
||||
};
|
||||
|
||||
#define TOKEN_OPT "CDGILPRSVabcdefi:k:l:n:p:ru"
|
||||
#define TOKEN_OPT "CDGILPRSVabcdefi:k:l:m:n:p:ru"
|
||||
|
||||
#define FLAG_DEBUG 0x01
|
||||
#define FLAG_QUIET 0x02
|
||||
@ -62,6 +62,7 @@ int config_always_uv(char *, int);
|
||||
int config_entattest(char *);
|
||||
int config_force_pin_change(char *);
|
||||
int config_pin_minlen(char *, const char *);
|
||||
int config_pin_minlen_rpid(char *, const char *);
|
||||
int cose_type(const char *, int *);
|
||||
int cred_make(int, char **);
|
||||
int cred_verify(int, char **);
|
||||
|
@ -28,6 +28,7 @@ usage(void)
|
||||
" fido2-token -S [-adefu] [-l pin_length] [-i template_id -n template_name] device\n"
|
||||
" fido2-token -Sb [-k key_path] [-i cred_id -n rp_id] blob_path device\n"
|
||||
" fido2-token -Sc -i cred_id -k user_id -n name -p display_name device\n"
|
||||
" fido2-token -Sm rp_id device\n"
|
||||
" fido2-token -V\n"
|
||||
);
|
||||
|
||||
@ -59,6 +60,7 @@ main(int argc, char **argv)
|
||||
case 'i':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'p':
|
||||
case 'r':
|
||||
|
@ -352,6 +352,7 @@ token_set(int argc, char **argv, char *path)
|
||||
char *len = NULL;
|
||||
char *display_name = NULL;
|
||||
char *name = NULL;
|
||||
char *rpid = NULL;
|
||||
int blob = 0;
|
||||
int cred = 0;
|
||||
int ch;
|
||||
@ -391,6 +392,9 @@ token_set(int argc, char **argv, char *path)
|
||||
case 'p':
|
||||
display_name = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
rpid = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
name = optarg;
|
||||
break;
|
||||
@ -440,6 +444,8 @@ token_set(int argc, char **argv, char *path)
|
||||
|
||||
if (len)
|
||||
return (config_pin_minlen(path, len));
|
||||
if (rpid)
|
||||
return (config_pin_minlen_rpid(path, rpid));
|
||||
if (force)
|
||||
return (config_force_pin_change(path));
|
||||
if (uv)
|
||||
|
@ -1,140 +1,136 @@
|
||||
# Copyright (c) 2021 Yubico AB. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
param(
|
||||
[string]$CMakePath = "C:\Program Files\CMake\bin\cmake.exe",
|
||||
[string]$GitPath = "C:\Program Files\Git\bin\git.exe",
|
||||
[string]$SevenZPath = "C:\Program Files\7-Zip\7z.exe",
|
||||
[string]$GPGPath = "C:\Program Files (x86)\GnuPG\bin\gpg.exe",
|
||||
[string]$WinSDK = "",
|
||||
[string]$Config = "Release",
|
||||
[string]$Arch = "x64",
|
||||
[string]$Type = "dynamic",
|
||||
[string]$Fido2Flags = ""
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
# LibreSSL coordinates.
|
||||
New-Variable -Name 'LIBRESSL_URL' `
|
||||
-Value 'https://fastly.cdn.openbsd.org/pub/OpenBSD/LibreSSL' -Option Constant
|
||||
New-Variable -Name 'LIBRESSL' -Value 'libressl-3.2.5' -Option Constant
|
||||
. "$PSScriptRoot\const.ps1"
|
||||
|
||||
# libcbor coordinates.
|
||||
New-Variable -Name 'LIBCBOR' -Value 'libcbor-0.8.0' -Option Constant
|
||||
New-Variable -Name 'LIBCBOR_BRANCH' -Value 'v0.8.0' -Option Constant
|
||||
New-Variable -Name 'LIBCBOR_GIT' -Value 'https://github.com/pjk/libcbor' `
|
||||
-Option Constant
|
||||
Function ExitOnError() {
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "A command exited with status $LastExitCode"
|
||||
}
|
||||
}
|
||||
|
||||
# zlib coordinates.
|
||||
New-Variable -Name 'ZLIB' -Value 'zlib-1.2.11' -Option Constant
|
||||
New-Variable -Name 'ZLIB_BRANCH' -Value 'v1.2.11' -Option Constant
|
||||
New-Variable -Name 'ZLIB_GIT' -Value 'https://github.com/madler/zlib' `
|
||||
-Option Constant
|
||||
|
||||
# Work directories.
|
||||
New-Variable -Name 'BUILD' -Value "$PSScriptRoot\..\build" -Option Constant
|
||||
New-Variable -Name 'OUTPUT' -Value "$PSScriptRoot\..\output" -Option Constant
|
||||
|
||||
# Find CMake.
|
||||
$CMake = $(Get-Command cmake -ErrorAction Ignore | Select-Object -ExpandProperty Source)
|
||||
if([string]::IsNullOrEmpty($CMake)) {
|
||||
$CMake = $CMakePath
|
||||
Function GitClone(${REPO}, ${BRANCH}, ${DIR}) {
|
||||
Write-Host "Cloning ${REPO}..."
|
||||
& $Git -c advice.detachedHead=false clone --quiet --depth=1 `
|
||||
--branch "${BRANCH}" "${REPO}" "${DIR}"
|
||||
Write-Host "${REPO}'s ${BRANCH} HEAD is:"
|
||||
& $Git -C "${DIR}" show -s HEAD
|
||||
}
|
||||
|
||||
# Find Git.
|
||||
$Git = $(Get-Command git -ErrorAction Ignore | Select-Object -ExpandProperty Source)
|
||||
if([string]::IsNullOrEmpty($Git)) {
|
||||
$Git = $(Get-Command git -ErrorAction Ignore | `
|
||||
Select-Object -ExpandProperty Source)
|
||||
if ([string]::IsNullOrEmpty($Git)) {
|
||||
$Git = $GitPath
|
||||
}
|
||||
if (-Not (Test-Path $Git)) {
|
||||
throw "Unable to find Git at $Git"
|
||||
}
|
||||
|
||||
# Find CMake.
|
||||
$CMake = $(Get-Command cmake -ErrorAction Ignore | `
|
||||
Select-Object -ExpandProperty Source)
|
||||
if ([string]::IsNullOrEmpty($CMake)) {
|
||||
$CMake = $CMakePath
|
||||
}
|
||||
if (-Not (Test-Path $CMake)) {
|
||||
throw "Unable to find CMake at $CMake"
|
||||
}
|
||||
|
||||
# Find 7z.
|
||||
$SevenZ = $(Get-Command 7z -ErrorAction Ignore | Select-Object -ExpandProperty Source)
|
||||
if([string]::IsNullOrEmpty($SevenZ)) {
|
||||
$SevenZ = $(Get-Command 7z -ErrorAction Ignore | `
|
||||
Select-Object -ExpandProperty Source)
|
||||
if ([string]::IsNullOrEmpty($SevenZ)) {
|
||||
$SevenZ = $SevenZPath
|
||||
}
|
||||
if (-Not (Test-Path $SevenZ)) {
|
||||
throw "Unable to find 7z at $SevenZ"
|
||||
}
|
||||
|
||||
# Find GPG.
|
||||
$GPG = $(Get-Command gpg -ErrorAction Ignore | Select-Object -ExpandProperty Source)
|
||||
if([string]::IsNullOrEmpty($GPG)) {
|
||||
$GPG = $(Get-Command gpg -ErrorAction Ignore | `
|
||||
Select-Object -ExpandProperty Source)
|
||||
if ([string]::IsNullOrEmpty($GPG)) {
|
||||
$GPG = $GPGPath
|
||||
}
|
||||
if (-Not (Test-Path $GPG)) {
|
||||
throw "Unable to find GPG at $GPG"
|
||||
}
|
||||
|
||||
# Override CMAKE_SYSTEM_VERSION if $WinSDK is set.
|
||||
if(-Not ([string]::IsNullOrEmpty($WinSDK))) {
|
||||
if (-Not ([string]::IsNullOrEmpty($WinSDK))) {
|
||||
$CMAKE_SYSTEM_VERSION = "-DCMAKE_SYSTEM_VERSION='$WinSDK'"
|
||||
} else {
|
||||
$CMAKE_SYSTEM_VERSION = ''
|
||||
}
|
||||
|
||||
if(-Not (Test-Path $CMake)) {
|
||||
throw "Unable to find CMake at $CMake"
|
||||
}
|
||||
|
||||
if(-Not (Test-Path $Git)) {
|
||||
throw "Unable to find Git at $Git"
|
||||
}
|
||||
|
||||
if(-Not (Test-Path $SevenZ)) {
|
||||
throw "Unable to find 7z at $SevenZ"
|
||||
}
|
||||
|
||||
if(-Not (Test-Path $GPG)) {
|
||||
throw "Unable to find GPG at $GPG"
|
||||
}
|
||||
|
||||
Write-Host "WinSDK: $WinSDK"
|
||||
Write-Host "Config: $Config"
|
||||
Write-Host "Arch: $Arch"
|
||||
Write-Host "Type: $Type"
|
||||
Write-Host "Git: $Git"
|
||||
Write-Host "CMake: $CMake"
|
||||
Write-Host "7z: $SevenZ"
|
||||
Write-Host "GPG: $GPG"
|
||||
|
||||
New-Item -Type Directory ${BUILD}
|
||||
New-Item -Type Directory ${BUILD}\32
|
||||
New-Item -Type Directory ${BUILD}\32\dynamic
|
||||
New-Item -Type Directory ${BUILD}\32\static
|
||||
New-Item -Type Directory ${BUILD}\64
|
||||
New-Item -Type Directory ${BUILD}\64\dynamic
|
||||
New-Item -Type Directory ${BUILD}\64\static
|
||||
New-Item -Type Directory ${OUTPUT}
|
||||
New-Item -Type Directory ${OUTPUT}\pkg\Win64\Release\v142\dynamic
|
||||
New-Item -Type Directory ${OUTPUT}\pkg\Win32\Release\v142\dynamic
|
||||
New-Item -Type Directory ${OUTPUT}\pkg\Win64\Release\v142\static
|
||||
New-Item -Type Directory ${OUTPUT}\pkg\Win32\Release\v142\static
|
||||
# Create build directories.
|
||||
New-Item -Type Directory "${BUILD}" -Force
|
||||
New-Item -Type Directory "${BUILD}\${Arch}" -Force
|
||||
New-Item -Type Directory "${BUILD}\${Arch}\${Type}" -Force
|
||||
New-Item -Type Directory "${STAGE}\${LIBRESSL}" -Force
|
||||
New-Item -Type Directory "${STAGE}\${LIBCBOR}" -Force
|
||||
New-Item -Type Directory "${STAGE}\${ZLIB}" -Force
|
||||
|
||||
# Create output directories.
|
||||
New-Item -Type Directory "${OUTPUT}" -Force
|
||||
New-Item -Type Directory "${OUTPUT}\${Arch}" -Force
|
||||
New-Item -Type Directory "${OUTPUT}\${Arch}\${Type}" -force
|
||||
|
||||
# Fetch and verify dependencies.
|
||||
Push-Location ${BUILD}
|
||||
|
||||
try {
|
||||
if (Test-Path .\${LIBRESSL}) {
|
||||
Remove-Item .\${LIBRESSL} -Recurse -ErrorAction Stop
|
||||
}
|
||||
if (-Not (Test-Path .\${LIBRESSL})) {
|
||||
if (-Not (Test-Path .\${LIBRESSL}.tar.gz -PathType leaf)) {
|
||||
Invoke-WebRequest ${LIBRESSL_URL}/${LIBRESSL}.tar.gz `
|
||||
-OutFile .\${LIBRESSL}.tar.gz
|
||||
}
|
||||
if (-Not (Test-Path .\${LIBRESSL}.tar.gz.asc -PathType leaf)) {
|
||||
Invoke-WebRequest ${LIBRESSL_URL}/${LIBRESSL}.tar.gz.asc `
|
||||
-OutFile .\${LIBRESSL}.tar.gz.asc
|
||||
}
|
||||
|
||||
if(-Not (Test-Path .\${LIBRESSL}.tar.gz -PathType leaf)) {
|
||||
Invoke-WebRequest ${LIBRESSL_URL}/${LIBRESSL}.tar.gz `
|
||||
-OutFile .\${LIBRESSL}.tar.gz
|
||||
Copy-Item "$PSScriptRoot\libressl.gpg" -Destination "${BUILD}"
|
||||
& $GPG --list-keys
|
||||
& $GPG --quiet --no-default-keyring --keyring ./libressl.gpg `
|
||||
--verify .\${LIBRESSL}.tar.gz.asc .\${LIBRESSL}.tar.gz
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "GPG signature verification failed"
|
||||
}
|
||||
& $SevenZ e .\${LIBRESSL}.tar.gz
|
||||
& $SevenZ x .\${LIBRESSL}.tar
|
||||
Remove-Item -Force .\${LIBRESSL}.tar
|
||||
}
|
||||
if(-Not (Test-Path .\${LIBRESSL}.tar.gz.asc -PathType leaf)) {
|
||||
Invoke-WebRequest ${LIBRESSL_URL}/${LIBRESSL}.tar.gz.asc `
|
||||
-OutFile .\${LIBRESSL}.tar.gz.asc
|
||||
if (-Not (Test-Path .\${LIBCBOR})) {
|
||||
GitClone "${LIBCBOR_GIT}" "${LIBCBOR_BRANCH}" ".\${LIBCBOR}"
|
||||
}
|
||||
|
||||
Copy-Item "$PSScriptRoot\libressl.gpg" -Destination "${BUILD}"
|
||||
& $GPG --list-keys
|
||||
& $GPG -v --no-default-keyring --keyring ./libressl.gpg `
|
||||
--verify .\${LIBRESSL}.tar.gz.asc .\${LIBRESSL}.tar.gz
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "GPG signature verification failed"
|
||||
}
|
||||
|
||||
& $SevenZ e .\${LIBRESSL}.tar.gz
|
||||
& $SevenZ x .\${LIBRESSL}.tar
|
||||
Remove-Item -Force .\${LIBRESSL}.tar
|
||||
|
||||
if(-Not (Test-Path .\${LIBCBOR})) {
|
||||
Write-Host "Cloning ${LIBCBOR}..."
|
||||
& $Git clone --branch ${LIBCBOR_BRANCH} ${LIBCBOR_GIT} `
|
||||
.\${LIBCBOR}
|
||||
}
|
||||
|
||||
if(-Not (Test-Path .\${ZLIB})) {
|
||||
Write-Host "Cloning ${ZLIB}..."
|
||||
& $Git clone --branch ${ZLIB_BRANCH} ${ZLIB_GIT} `
|
||||
.\${ZLIB}
|
||||
if (-Not (Test-Path .\${ZLIB})) {
|
||||
GitClone "${ZLIB_GIT}" "${ZLIB_BRANCH}" ".\${ZLIB}"
|
||||
}
|
||||
} catch {
|
||||
throw "Failed to fetch and verify dependencies"
|
||||
@ -142,131 +138,103 @@ try {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
Function Build(${OUTPUT}, ${GENERATOR}, ${ARCH}, ${SHARED}, ${FLAGS}) {
|
||||
if (-Not (Test-Path .\${LIBRESSL})) {
|
||||
New-Item -Type Directory .\${LIBRESSL} -ErrorAction Stop
|
||||
}
|
||||
|
||||
Push-Location .\${LIBRESSL}
|
||||
& $CMake ..\..\..\${LIBRESSL} -G "${GENERATOR}" -A "${ARCH}" `
|
||||
-DBUILD_SHARED_LIBS="${SHARED}" -DLIBRESSL_TESTS=OFF `
|
||||
-DCMAKE_C_FLAGS_RELEASE="${FLAGS} /Zi /guard:cf /sdl" `
|
||||
-DCMAKE_INSTALL_PREFIX="${OUTPUT}" "${CMAKE_SYSTEM_VERSION}"
|
||||
& $CMake --build . --config Release --verbose
|
||||
& $CMake --build . --config Release --target install --verbose
|
||||
# Build LibreSSL.
|
||||
Push-Location ${STAGE}\${LIBRESSL}
|
||||
try {
|
||||
& $CMake ..\..\..\${LIBRESSL} -A "${Arch}" `
|
||||
-DBUILD_SHARED_LIBS="${SHARED}" -DLIBRESSL_TESTS=OFF `
|
||||
-DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" `
|
||||
-DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" `
|
||||
-DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
|
||||
ExitOnError
|
||||
& $CMake --build . --config ${Config} --verbose; ExitOnError
|
||||
& $CMake --build . --config ${Config} --target install --verbose; `
|
||||
ExitOnError
|
||||
} catch {
|
||||
throw "Failed to build LibreSSL"
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
if (-Not (Test-Path .\${LIBCBOR})) {
|
||||
New-Item -Type Directory .\${LIBCBOR} -ErrorAction Stop
|
||||
}
|
||||
|
||||
Push-Location .\${LIBCBOR}
|
||||
& $CMake ..\..\..\${LIBCBOR} -G "${GENERATOR}" -A "${ARCH}" `
|
||||
-DBUILD_SHARED_LIBS="${SHARED}" `
|
||||
-DCMAKE_C_FLAGS_RELEASE="${FLAGS} /Zi /guard:cf /sdl" `
|
||||
-DCMAKE_INSTALL_PREFIX="${OUTPUT}" "${CMAKE_SYSTEM_VERSION}"
|
||||
& $CMake --build . --config Release --verbose
|
||||
& $CMake --build . --config Release --target install --verbose
|
||||
# Build libcbor.
|
||||
Push-Location ${STAGE}\${LIBCBOR}
|
||||
try {
|
||||
& $CMake ..\..\..\${LIBCBOR} -A "${Arch}" `
|
||||
-DWITH_EXAMPLES=OFF `
|
||||
-DBUILD_SHARED_LIBS="${SHARED}" `
|
||||
-DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" `
|
||||
-DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" `
|
||||
-DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
|
||||
ExitOnError
|
||||
& $CMake --build . --config ${Config} --verbose; ExitOnError
|
||||
& $CMake --build . --config ${Config} --target install --verbose; `
|
||||
ExitOnError
|
||||
} catch {
|
||||
throw "Failed to build libcbor"
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
if(-Not (Test-Path .\${ZLIB})) {
|
||||
New-Item -Type Directory .\${ZLIB} -ErrorAction Stop
|
||||
# Build zlib.
|
||||
Push-Location ${STAGE}\${ZLIB}
|
||||
try {
|
||||
& $CMake ..\..\..\${ZLIB} -A "${Arch}" `
|
||||
-DBUILD_SHARED_LIBS="${SHARED}" `
|
||||
-DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG}" `
|
||||
-DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE}" `
|
||||
-DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
|
||||
ExitOnError
|
||||
& $CMake --build . --config ${Config} --verbose; ExitOnError
|
||||
& $CMake --build . --config ${Config} --target install --verbose; `
|
||||
ExitOnError
|
||||
# Patch up zlib's resulting names when built with --config Debug.
|
||||
if ("${Config}" -eq "Debug") {
|
||||
if ("${Type}" -eq "Dynamic") {
|
||||
Copy-Item "${PREFIX}/lib/zlibd.lib" `
|
||||
-Destination "${PREFIX}/lib/zlib.lib" -Force
|
||||
Copy-Item "${PREFIX}/bin/zlibd1.dll" `
|
||||
-Destination "${PREFIX}/bin/zlib1.dll" -Force
|
||||
} else {
|
||||
Copy-Item "${PREFIX}/lib/zlibstaticd.lib" `
|
||||
-Destination "${PREFIX}/lib/zlib.lib" -Force
|
||||
}
|
||||
}
|
||||
|
||||
Push-Location .\${ZLIB}
|
||||
& $CMake ..\..\..\${ZLIB} -G "${GENERATOR}" -A "${ARCH}" `
|
||||
-DBUILD_SHARED_LIBS="${SHARED}" `
|
||||
-DCMAKE_C_FLAGS_RELEASE="${FLAGS} /Zi /guard:cf /sdl" `
|
||||
-DCMAKE_INSTALL_PREFIX="${OUTPUT}" "${CMAKE_SYSTEM_VERSION}"
|
||||
& $CMake --build . --config Release --verbose
|
||||
& $CMake --build . --config Release --target install --verbose
|
||||
} catch {
|
||||
throw "Failed to build zlib"
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
& $CMake ..\..\.. -G "${GENERATOR}" -A "${ARCH}" `
|
||||
-DBUILD_SHARED_LIBS="${SHARED}" `
|
||||
-DCBOR_INCLUDE_DIRS="${OUTPUT}\include" `
|
||||
-DCBOR_LIBRARY_DIRS="${OUTPUT}\lib" `
|
||||
-DZLIB_INCLUDE_DIRS="${OUTPUT}\include" `
|
||||
-DZLIB_LIBRARY_DIRS="${OUTPUT}\lib" `
|
||||
-DCRYPTO_INCLUDE_DIRS="${OUTPUT}\include" `
|
||||
-DCRYPTO_LIBRARY_DIRS="${OUTPUT}\lib" `
|
||||
-DCMAKE_C_FLAGS_RELEASE="${FLAGS} /Zi /guard:cf /sdl ${Fido2Flags}" `
|
||||
-DCMAKE_INSTALL_PREFIX="${OUTPUT}" "${CMAKE_SYSTEM_VERSION}"
|
||||
& $CMake --build . --config Release --verbose
|
||||
& $CMake --build . --config Release --target install --verbose
|
||||
# Build libfido2.
|
||||
Push-Location ${STAGE}
|
||||
try {
|
||||
& $CMake ..\..\.. -A "${Arch}" `
|
||||
-DCMAKE_BUILD_TYPE="${Config}" `
|
||||
-DBUILD_SHARED_LIBS="${SHARED}" `
|
||||
-DCBOR_INCLUDE_DIRS="${PREFIX}\include" `
|
||||
-DCBOR_LIBRARY_DIRS="${PREFIX}\lib" `
|
||||
-DCBOR_BIN_DIRS="${PREFIX}\bin" `
|
||||
-DZLIB_INCLUDE_DIRS="${PREFIX}\include" `
|
||||
-DZLIB_LIBRARY_DIRS="${PREFIX}\lib" `
|
||||
-DZLIB_BIN_DIRS="${PREFIX}\bin" `
|
||||
-DCRYPTO_INCLUDE_DIRS="${PREFIX}\include" `
|
||||
-DCRYPTO_LIBRARY_DIRS="${PREFIX}\lib" `
|
||||
-DCRYPTO_BIN_DIRS="${PREFIX}\bin" `
|
||||
-DCMAKE_C_FLAGS_DEBUG="${CFLAGS_DEBUG} ${Fido2Flags}" `
|
||||
-DCMAKE_C_FLAGS_RELEASE="${CFLAGS_RELEASE} ${Fido2Flags}" `
|
||||
-DCMAKE_INSTALL_PREFIX="${PREFIX}" "${CMAKE_SYSTEM_VERSION}"; `
|
||||
ExitOnError
|
||||
& $CMake --build . --config ${Config} --verbose; ExitOnError
|
||||
& $CMake --build . --config ${Config} --target install --verbose; `
|
||||
ExitOnError
|
||||
# Copy DLLs.
|
||||
if ("${SHARED}" -eq "ON") {
|
||||
"cbor.dll", "crypto-46.dll", "zlib1.dll" | %{ Copy-Item "${OUTPUT}\bin\$_" `
|
||||
-Destination "examples\Release" }
|
||||
"cbor.dll", "crypto-46.dll", "zlib1.dll" | `
|
||||
%{ Copy-Item "${PREFIX}\bin\$_" `
|
||||
-Destination "examples\${Config}" }
|
||||
}
|
||||
} catch {
|
||||
throw "Failed to build libfido2"
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
Function Package-Headers() {
|
||||
Copy-Item "${OUTPUT}\64\dynamic\include" -Destination "${OUTPUT}\pkg" `
|
||||
-Recurse -ErrorAction Stop
|
||||
}
|
||||
|
||||
Function Package-Dynamic(${SRC}, ${DEST}) {
|
||||
Copy-Item "${SRC}\bin\cbor.dll" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\lib\cbor.lib" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\bin\zlib1.dll" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\lib\zlib.lib" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\bin\crypto-46.dll" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\lib\crypto-46.lib" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\bin\fido2.dll" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\lib\fido2.lib" "${DEST}" -ErrorAction Stop
|
||||
}
|
||||
|
||||
Function Package-Static(${SRC}, ${DEST}) {
|
||||
Copy-Item "${SRC}/lib/cbor.lib" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}/lib/zlib.lib" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}/lib/crypto-46.lib" "${DEST}" -ErrorAction Stop
|
||||
Copy-Item "${SRC}/lib/fido2_static.lib" "${DEST}/fido2.lib" `
|
||||
-ErrorAction Stop
|
||||
}
|
||||
|
||||
Function Package-PDBs(${SRC}, ${DEST}) {
|
||||
Copy-Item "${SRC}\${LIBRESSL}\crypto\crypto.dir\Release\vc142.pdb" `
|
||||
"${DEST}\crypto-46.pdb" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\${LIBCBOR}\src\cbor.dir\Release\vc142.pdb" `
|
||||
"${DEST}\cbor.pdb" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\${ZLIB}\zlib.dir\Release\vc142.pdb" `
|
||||
"${DEST}\zlib.pdb" -ErrorAction Stop
|
||||
Copy-Item "${SRC}\src\fido2_shared.dir\Release\vc142.pdb" `
|
||||
"${DEST}\fido2.pdb" -ErrorAction Stop
|
||||
}
|
||||
|
||||
Function Package-Tools(${SRC}, ${DEST}) {
|
||||
Copy-Item "${SRC}\tools\Release\fido2-assert.exe" `
|
||||
"${DEST}\fido2-assert.exe" -ErrorAction stop
|
||||
Copy-Item "${SRC}\tools\Release\fido2-cred.exe" `
|
||||
"${DEST}\fido2-cred.exe" -ErrorAction stop
|
||||
Copy-Item "${SRC}\tools\Release\fido2-token.exe" `
|
||||
"${DEST}\fido2-token.exe" -ErrorAction stop
|
||||
}
|
||||
|
||||
Push-Location ${BUILD}\64\dynamic
|
||||
Build ${OUTPUT}\64\dynamic "Visual Studio 16 2019" "x64" "ON" "/MD"
|
||||
Pop-Location
|
||||
Push-Location ${BUILD}\32\dynamic
|
||||
Build ${OUTPUT}\32\dynamic "Visual Studio 16 2019" "Win32" "ON" "/MD"
|
||||
Pop-Location
|
||||
|
||||
Push-Location ${BUILD}\64\static
|
||||
Build ${OUTPUT}\64\static "Visual Studio 16 2019" "x64" "OFF" "/MT"
|
||||
Pop-Location
|
||||
Push-Location ${BUILD}\32\static
|
||||
Build ${OUTPUT}\32\static "Visual Studio 16 2019" "Win32" "OFF" "/MT"
|
||||
Pop-Location
|
||||
|
||||
Package-Headers
|
||||
|
||||
Package-Dynamic ${OUTPUT}\64\dynamic ${OUTPUT}\pkg\Win64\Release\v142\dynamic
|
||||
Package-PDBs ${BUILD}\64\dynamic ${OUTPUT}\pkg\Win64\Release\v142\dynamic
|
||||
Package-Tools ${BUILD}\64\dynamic ${OUTPUT}\pkg\Win64\Release\v142\dynamic
|
||||
|
||||
Package-Dynamic ${OUTPUT}\32\dynamic ${OUTPUT}\pkg\Win32\Release\v142\dynamic
|
||||
Package-PDBs ${BUILD}\32\dynamic ${OUTPUT}\pkg\Win32\Release\v142\dynamic
|
||||
Package-Tools ${BUILD}\32\dynamic ${OUTPUT}\pkg\Win32\Release\v142\dynamic
|
||||
|
||||
Package-Static ${OUTPUT}\64\static ${OUTPUT}\pkg\Win64\Release\v142\static
|
||||
Package-Static ${OUTPUT}\32\static ${OUTPUT}\pkg\Win32\Release\v142\static
|
||||
|
42
windows/const.ps1
Normal file
42
windows/const.ps1
Normal file
@ -0,0 +1,42 @@
|
||||
# Copyright (c) 2021 Yubico AB. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
# LibreSSL coordinates.
|
||||
New-Variable -Name 'LIBRESSL_URL' `
|
||||
-Value 'https://fastly.cdn.openbsd.org/pub/OpenBSD/LibreSSL' `
|
||||
-Option Constant
|
||||
New-Variable -Name 'LIBRESSL' -Value 'libressl-3.3.4' -Option Constant
|
||||
|
||||
# libcbor coordinates.
|
||||
New-Variable -Name 'LIBCBOR' -Value 'libcbor-0.8.0' -Option Constant
|
||||
New-Variable -Name 'LIBCBOR_BRANCH' -Value 'v0.8.0' -Option Constant
|
||||
New-Variable -Name 'LIBCBOR_GIT' -Value 'https://github.com/pjk/libcbor' `
|
||||
-Option Constant
|
||||
|
||||
# zlib coordinates.
|
||||
New-Variable -Name 'ZLIB' -Value 'zlib-1.2.11' -Option Constant
|
||||
New-Variable -Name 'ZLIB_BRANCH' -Value 'v1.2.11' -Option Constant
|
||||
New-Variable -Name 'ZLIB_GIT' -Value 'https://github.com/madler/zlib' `
|
||||
-Option Constant
|
||||
|
||||
# Work directories.
|
||||
New-Variable -Name 'BUILD' -Value "$PSScriptRoot\..\build" -Option Constant
|
||||
New-Variable -Name 'OUTPUT' -Value "$PSScriptRoot\..\output" -Option Constant
|
||||
|
||||
# Prefixes.
|
||||
New-Variable -Name 'STAGE' -Value "${BUILD}\${Arch}\${Type}" -Option Constant
|
||||
New-Variable -Name 'PREFIX' -Value "${OUTPUT}\${Arch}\${Type}" -Option Constant
|
||||
|
||||
# Build flags.
|
||||
if ("${Type}" -eq "dynamic") {
|
||||
New-Variable -Name 'RUNTIME' -Value '/MD' -Option Constant
|
||||
New-Variable -Name 'SHARED' -Value 'ON' -Option Constant
|
||||
} else {
|
||||
New-Variable -Name 'RUNTIME' -Value '/MT' -Option Constant
|
||||
New-Variable -Name 'SHARED' -Value 'OFF' -Option Constant
|
||||
}
|
||||
New-Variable -Name 'CFLAGS_DEBUG' -Value "${RUNTIME}d /Zi /guard:cf /sdl" `
|
||||
-Option Constant
|
||||
New-Variable -Name 'CFLAGS_RELEASE' -Value "${RUNTIME} /Zi /guard:cf /sdl" `
|
||||
-Option Constant
|
84
windows/release.ps1
Normal file
84
windows/release.ps1
Normal file
@ -0,0 +1,84 @@
|
||||
# Copyright (c) 2021 Yubico AB. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$Architectures = @('x64', 'Win32', 'ARM64', 'ARM')
|
||||
$InstallPrefixes = @('Win64', 'Win32', 'ARM64', 'ARM')
|
||||
$Types = @('dynamic', 'static')
|
||||
$Config = 'Release'
|
||||
$LibCrypto = '46'
|
||||
$SDK = '142'
|
||||
|
||||
. "$PSScriptRoot\const.ps1"
|
||||
|
||||
foreach ($Arch in $Architectures) {
|
||||
foreach ($Type in $Types) {
|
||||
./build.ps1 -Arch ${Arch} -Type ${Type} -Config ${Config}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($InstallPrefix in $InstallPrefixes) {
|
||||
foreach ($Type in $Types) {
|
||||
New-Item -Type Directory `
|
||||
"${OUTPUT}/pkg/${InstallPrefix}/${Config}/v${SDK}/${Type}"
|
||||
}
|
||||
}
|
||||
|
||||
Function Package-Headers() {
|
||||
Copy-Item "${OUTPUT}\x64\dynamic\include" -Destination "${OUTPUT}\pkg" `
|
||||
-Recurse -ErrorAction Stop
|
||||
}
|
||||
|
||||
Function Package-Dynamic(${SRC}, ${DEST}) {
|
||||
Copy-Item "${SRC}\bin\cbor.dll" "${DEST}"
|
||||
Copy-Item "${SRC}\lib\cbor.lib" "${DEST}"
|
||||
Copy-Item "${SRC}\bin\zlib1.dll" "${DEST}"
|
||||
Copy-Item "${SRC}\lib\zlib.lib" "${DEST}"
|
||||
Copy-Item "${SRC}\bin\crypto-${LibCrypto}.dll" "${DEST}"
|
||||
Copy-Item "${SRC}\lib\crypto-${LibCrypto}.lib" "${DEST}"
|
||||
Copy-Item "${SRC}\bin\fido2.dll" "${DEST}"
|
||||
Copy-Item "${SRC}\lib\fido2.lib" "${DEST}"
|
||||
}
|
||||
|
||||
Function Package-Static(${SRC}, ${DEST}) {
|
||||
Copy-Item "${SRC}/lib/cbor.lib" "${DEST}"
|
||||
Copy-Item "${SRC}/lib/zlib.lib" "${DEST}"
|
||||
Copy-Item "${SRC}/lib/crypto-${LibCrypto}.lib" "${DEST}"
|
||||
Copy-Item "${SRC}/lib/fido2_static.lib" "${DEST}/fido2.lib"
|
||||
}
|
||||
|
||||
Function Package-PDBs(${SRC}, ${DEST}) {
|
||||
Copy-Item "${SRC}\${LIBRESSL}\crypto\crypto.dir\${Config}\vc${SDK}.pdb" `
|
||||
"${DEST}\crypto-${LibCrypto}.pdb"
|
||||
Copy-Item "${SRC}\${LIBCBOR}\src\cbor.dir\${Config}\vc${SDK}.pdb" `
|
||||
"${DEST}\cbor.pdb"
|
||||
Copy-Item "${SRC}\${ZLIB}\zlib.dir\${Config}\vc${SDK}.pdb" `
|
||||
"${DEST}\zlib.pdb"
|
||||
Copy-Item "${SRC}\src\fido2_shared.dir\${Config}\vc${SDK}.pdb" `
|
||||
"${DEST}\fido2.pdb"
|
||||
}
|
||||
|
||||
Function Package-Tools(${SRC}, ${DEST}) {
|
||||
Copy-Item "${SRC}\tools\${Config}\fido2-assert.exe" `
|
||||
"${DEST}\fido2-assert.exe"
|
||||
Copy-Item "${SRC}\tools\${Config}\fido2-cred.exe" `
|
||||
"${DEST}\fido2-cred.exe"
|
||||
Copy-Item "${SRC}\tools\${Config}\fido2-token.exe" `
|
||||
"${DEST}\fido2-token.exe"
|
||||
}
|
||||
|
||||
Package-Headers
|
||||
|
||||
for ($i = 0; $i -lt $Architectures.Length; $i++) {
|
||||
$Arch = $Architectures[$i]
|
||||
$InstallPrefix = $InstallPrefixes[$i]
|
||||
Package-Dynamic "${OUTPUT}\${Arch}\dynamic" `
|
||||
"${OUTPUT}\pkg\${InstallPrefix}\${Config}\v${SDK}\dynamic"
|
||||
Package-PDBs "${BUILD}\${Arch}\dynamic" `
|
||||
"${OUTPUT}\pkg\${InstallPrefix}\${Config}\v${SDK}\dynamic"
|
||||
Package-Tools "${BUILD}\${Arch}\dynamic" `
|
||||
"${OUTPUT}\pkg\${InstallPrefix}\${Config}\v${SDK}\dynamic"
|
||||
Package-Static "${OUTPUT}\${Arch}\static" `
|
||||
"${OUTPUT}\pkg\${InstallPrefix}\${Config}\v${SDK}\static"
|
||||
}
|
Loading…
Reference in New Issue
Block a user