/* $OpenBSD: sk-usbhid.c,v 1.37 2021/12/07 22:06:45 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl
* Copyright (c) 2020 Pedro Martelletto
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifdef ENABLE_SK_INTERNAL
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include <time.h>
#ifdef HAVE_SHA2_H
#include <sha2.h>
#endif
/*
* Almost every use of OpenSSL in this file is for ECDSA-NISTP256.
* This is strictly a larger hammer than necessary, but it reduces changes
* with upstream.
*/
#ifndef OPENSSL_HAS_ECC
# undef WITH_OPENSSL
#endif
#ifdef WITH_OPENSSL
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#endif /* WITH_OPENSSL */
#include <fido.h>
#include <fido/credman.h>
/* backwards compat for libfido2 */
#ifndef HAVE_FIDO_CRED_PROT
#define fido_cred_prot(x) (0)
#endif
#ifndef HAVE_FIDO_CRED_SET_PROT
#define fido_cred_set_prot(x, y) (FIDO_ERR_UNSUPPORTED_OPTION)
#endif
#ifndef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT
#define fido_dev_supports_cred_prot(x) (0)
#endif
#ifndef HAVE_FIDO_DEV_GET_TOUCH_BEGIN
#define fido_dev_get_touch_begin(x) (FIDO_ERR_UNSUPPORTED_OPTION)
#endif
#ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS
#define fido_dev_get_touch_status(x, y, z) (FIDO_ERR_UNSUPPORTED_OPTION)
#endif
#ifndef FIDO_CRED_PROT_UV_REQUIRED
#define FIDO_CRED_PROT_UV_REQUIRED 0
#endif
#ifndef FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID
#define FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID 0
#endif
#ifndef SK_STANDALONE
# include "log.h"
# include "xmalloc.h"
# include "misc.h"
/*
* If building as part of OpenSSH, then rename exported functions.
* This must be done before including sk-api.h.
*/
# define sk_api_version ssh_sk_api_version
# define sk_enroll ssh_sk_enroll
# define sk_sign ssh_sk_sign
# define sk_load_resident_keys ssh_sk_load_resident_keys
#endif /* !SK_STANDALONE */
#include "sk-api.h"
/* #define SK_DEBUG 1 */
#ifdef SK_DEBUG
#define SSH_FIDO_INIT_ARG FIDO_DEBUG
#else
#define SSH_FIDO_INIT_ARG 0
#endif
#define MAX_FIDO_DEVICES 8
#define FIDO_POLL_MS 50
#define SELECT_MS 15000
#define POLL_SLEEP_NS 200000000
/* Compatibility with OpenSSH 1.0.x */
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
#define ECDSA_SIG_get0(sig, pr, ps) \
do { \
(*pr) = sig->r; \
(*ps) = sig->s; \
} while (0)
#endif
#ifndef FIDO_ERR_OPERATION_DENIED