diff options
Diffstat (limited to 'contrib/libfido2/src/dev.c')
-rw-r--r-- | contrib/libfido2/src/dev.c | 229 |
1 files changed, 37 insertions, 192 deletions
diff --git a/contrib/libfido2/src/dev.c b/contrib/libfido2/src/dev.c index fb8faba0a06c..2d662a6cc48b 100644 --- a/contrib/libfido2/src/dev.c +++ b/contrib/libfido2/src/dev.c @@ -1,37 +1,18 @@ /* - * Copyright (c) 2018 Yubico AB. All rights reserved. + * Copyright (c) 2018-2022 Yubico AB. All rights reserved. * Use of this source code is governed by a BSD-style * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause */ -#include <openssl/sha.h> #include "fido.h" #ifndef TLS #define TLS #endif -typedef struct dev_manifest_func_node { - dev_manifest_func_t manifest_func; - struct dev_manifest_func_node *next; -} dev_manifest_func_node_t; - -static TLS dev_manifest_func_node_t *manifest_funcs = NULL; static TLS bool disable_u2f_fallback; -static void -find_manifest_func_node(dev_manifest_func_t f, dev_manifest_func_node_t **curr, - dev_manifest_func_node_t **prev) -{ - *prev = NULL; - *curr = manifest_funcs; - - while (*curr != NULL && (*curr)->manifest_func != f) { - *prev = *curr; - *curr = (*curr)->next; - } -} - #ifdef FIDO_FUZZ static void set_random_report_len(fido_dev_t *dev) @@ -63,13 +44,15 @@ fido_dev_set_option_flags(fido_dev_t *dev, const fido_cbor_info_t *info) for (size_t i = 0; i < len; i++) if (strcmp(ptr[i], "clientPin") == 0) { - dev->flags |= val[i] ? FIDO_DEV_PIN_SET : FIDO_DEV_PIN_UNSET; + dev->flags |= val[i] ? + FIDO_DEV_PIN_SET : FIDO_DEV_PIN_UNSET; } else if (strcmp(ptr[i], "credMgmt") == 0 || strcmp(ptr[i], "credentialMgmtPreview") == 0) { if (val[i]) dev->flags |= FIDO_DEV_CREDMAN; } else if (strcmp(ptr[i], "uv") == 0) { - dev->flags |= val[i] ? FIDO_DEV_UV_SET : FIDO_DEV_UV_UNSET; + dev->flags |= val[i] ? + FIDO_DEV_UV_SET : FIDO_DEV_UV_UNSET; } else if (strcmp(ptr[i], "pinUvAuthToken") == 0) { if (val[i]) dev->flags |= FIDO_DEV_TOKEN_PERMS; @@ -257,75 +240,40 @@ fido_dev_open_wait(fido_dev_t *dev, const char *path, int *ms) return (FIDO_OK); } -int -fido_dev_register_manifest_func(const dev_manifest_func_t f) -{ - dev_manifest_func_node_t *prev, *curr, *n; - - find_manifest_func_node(f, &curr, &prev); - if (curr != NULL) - return (FIDO_OK); - - if ((n = calloc(1, sizeof(*n))) == NULL) { - fido_log_debug("%s: calloc", __func__); - return (FIDO_ERR_INTERNAL); - } - - n->manifest_func = f; - n->next = manifest_funcs; - manifest_funcs = n; - - return (FIDO_OK); -} - -void -fido_dev_unregister_manifest_func(const dev_manifest_func_t f) +static void +run_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen, + const char *type, int (*manifest)(fido_dev_info_t *, size_t, size_t *)) { - dev_manifest_func_node_t *prev, *curr; + size_t ndevs = 0; + int r; - find_manifest_func_node(f, &curr, &prev); - if (curr == NULL) + if (*olen >= ilen) { + fido_log_debug("%s: skipping %s", __func__, type); return; - if (prev != NULL) - prev->next = curr->next; - else - manifest_funcs = curr->next; - - free(curr); + } + if ((r = manifest(devlist + *olen, ilen - *olen, &ndevs)) != FIDO_OK) + fido_log_debug("%s: %s: 0x%x", __func__, type, r); + fido_log_debug("%s: found %zu %s device%s", __func__, ndevs, type, + ndevs == 1 ? "" : "s"); + *olen += ndevs; } int fido_dev_info_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) { - dev_manifest_func_node_t *curr = NULL; - dev_manifest_func_t m_func; - size_t curr_olen; - int r; - *olen = 0; - if (fido_dev_register_manifest_func(fido_hid_manifest) != FIDO_OK) - return (FIDO_ERR_INTERNAL); -#ifdef NFC_LINUX - if (fido_dev_register_manifest_func(fido_nfc_manifest) != FIDO_OK) - return (FIDO_ERR_INTERNAL); + run_manifest(devlist, ilen, olen, "hid", fido_hid_manifest); +#ifdef USE_NFC + run_manifest(devlist, ilen, olen, "nfc", fido_nfc_manifest); +#endif +#ifdef USE_PCSC + run_manifest(devlist, ilen, olen, "pcsc", fido_pcsc_manifest); #endif #ifdef USE_WINHELLO - if (fido_dev_register_manifest_func(fido_winhello_manifest) != FIDO_OK) - return (FIDO_ERR_INTERNAL); + run_manifest(devlist, ilen, olen, "winhello", fido_winhello_manifest); #endif - for (curr = manifest_funcs; curr != NULL; curr = curr->next) { - curr_olen = 0; - m_func = curr->manifest_func; - r = m_func(devlist + *olen, ilen - *olen, &curr_olen); - if (r != FIDO_OK) - return (r); - *olen += curr_olen; - if (*olen == ilen) - break; - } - return (FIDO_OK); } @@ -345,19 +293,16 @@ fido_dev_open(fido_dev_t *dev, const char *path) { int ms = dev->timeout_ms; -#ifdef NFC_LINUX - if (strncmp(path, FIDO_NFC_PREFIX, strlen(FIDO_NFC_PREFIX)) == 0) { - dev->io_own = true; - dev->io = (fido_dev_io_t) { - fido_nfc_open, - fido_nfc_close, - fido_nfc_read, - fido_nfc_write, - }; - dev->transport = (fido_dev_transport_t) { - fido_nfc_rx, - fido_nfc_tx, - }; +#ifdef USE_NFC + if (fido_is_nfc(path) && fido_dev_set_nfc(dev) < 0) { + fido_log_debug("%s: fido_dev_set_nfc", __func__); + return FIDO_ERR_INTERNAL; + } +#endif +#ifdef USE_PCSC + if (fido_is_pcsc(path) && fido_dev_set_pcsc(dev) < 0) { + fido_log_debug("%s: fido_dev_set_pcsc", __func__); + return FIDO_ERR_INTERNAL; } #endif @@ -387,7 +332,7 @@ fido_dev_set_sigmask(fido_dev_t *dev, const fido_sigset_t *sigmask) if (dev->io_handle == NULL || sigmask == NULL) return (FIDO_ERR_INVALID_ARGUMENT); -#ifdef NFC_LINUX +#ifdef USE_NFC if (dev->transport.rx == fido_nfc_rx && dev->io.read == fido_nfc_read) return (fido_nfc_set_sigmask(dev->io_handle, sigmask)); #endif @@ -415,106 +360,6 @@ fido_dev_cancel(fido_dev_t *dev) } int -fido_dev_get_touch_begin(fido_dev_t *dev) -{ - fido_blob_t f; - cbor_item_t *argv[9]; - const char *clientdata = FIDO_DUMMY_CLIENTDATA; - const uint8_t user_id = FIDO_DUMMY_USER_ID; - unsigned char cdh[SHA256_DIGEST_LENGTH]; - fido_rp_t rp; - fido_user_t user; - int ms = dev->timeout_ms; - int r = FIDO_ERR_INTERNAL; - - memset(&f, 0, sizeof(f)); - memset(argv, 0, sizeof(argv)); - memset(cdh, 0, sizeof(cdh)); - memset(&rp, 0, sizeof(rp)); - memset(&user, 0, sizeof(user)); - - if (fido_dev_is_fido2(dev) == false) - return (u2f_get_touch_begin(dev, &ms)); - - if (SHA256((const void *)clientdata, strlen(clientdata), cdh) != cdh) { - fido_log_debug("%s: sha256", __func__); - return (FIDO_ERR_INTERNAL); - } - - if ((rp.id = strdup(FIDO_DUMMY_RP_ID)) == NULL || - (user.name = strdup(FIDO_DUMMY_USER_NAME)) == NULL) { - fido_log_debug("%s: strdup", __func__); - goto fail; - } - - if (fido_blob_set(&user.id, &user_id, sizeof(user_id)) < 0) { - fido_log_debug("%s: fido_blob_set", __func__); - goto fail; - } - - if ((argv[0] = cbor_build_bytestring(cdh, sizeof(cdh))) == NULL || - (argv[1] = cbor_encode_rp_entity(&rp)) == NULL || - (argv[2] = cbor_encode_user_entity(&user)) == NULL || - (argv[3] = cbor_encode_pubkey_param(COSE_ES256)) == NULL) { - fido_log_debug("%s: cbor encode", __func__); - goto fail; - } - - if (fido_dev_supports_pin(dev)) { - if ((argv[7] = cbor_new_definite_bytestring()) == NULL || - (argv[8] = cbor_encode_pin_opt(dev)) == NULL) { - fido_log_debug("%s: cbor encode", __func__); - goto fail; - } - } - - if (cbor_build_frame(CTAP_CBOR_MAKECRED, argv, nitems(argv), &f) < 0 || - fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, &ms) < 0) { - fido_log_debug("%s: fido_tx", __func__); - r = FIDO_ERR_TX; - goto fail; - } - - r = FIDO_OK; -fail: - cbor_vector_free(argv, nitems(argv)); - free(f.ptr); - free(rp.id); - free(user.name); - free(user.id.ptr); - - return (r); -} - -int -fido_dev_get_touch_status(fido_dev_t *dev, int *touched, int ms) -{ - int r; - - *touched = 0; - - if (fido_dev_is_fido2(dev) == false) - return (u2f_get_touch_status(dev, touched, &ms)); - - switch ((r = fido_rx_cbor_status(dev, &ms))) { - case FIDO_ERR_PIN_AUTH_INVALID: - case FIDO_ERR_PIN_INVALID: - case FIDO_ERR_PIN_NOT_SET: - case FIDO_ERR_SUCCESS: - *touched = 1; - break; - case FIDO_ERR_RX: - /* ignore */ - break; - default: - fido_log_debug("%s: fido_rx_cbor_status", __func__); - return (r); - } - - return (FIDO_OK); -} - -int fido_dev_set_io_functions(fido_dev_t *dev, const fido_dev_io_t *io) { if (dev->io_handle != NULL) { |