mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-02 01:25:13 -05:00
Initial ykcore import into code base
This commit is contained in:
parent
0450bf3487
commit
6e27dd8db5
@ -458,13 +458,6 @@ include_directories(SYSTEM ${ZLIB_INCLUDE_DIR})
|
||||
# QREncode required for TOTP
|
||||
find_package(QREncode REQUIRED)
|
||||
|
||||
# Optional
|
||||
if(WITH_XC_YUBIKEY)
|
||||
find_package(YubiKey REQUIRED)
|
||||
|
||||
include_directories(SYSTEM ${YUBIKEY_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
check_cxx_source_compiles("#include <sys/prctl.h>
|
||||
int main() { prctl(PR_SET_DUMPABLE, 0); return 0; }"
|
||||
|
6
COPYING
6
COPYING
@ -238,3 +238,9 @@ Files: share/icons/application/scalable/actions/hibp.svg
|
||||
share/icons/database/C64_Apple.svg
|
||||
Copyright: GPL-2+
|
||||
Comment: from the Simple Icons repo (https://github.com/simple-icons/simple-icons/)
|
||||
|
||||
Files: src/thirdparty/ykcore/yk*
|
||||
src/thirdparty/ykcore/yubikey.h
|
||||
Copyright: 2006-2015, Yubico AB
|
||||
License: BSD-2-Clause
|
||||
Comment: from the yubikey-personalization repo (https://github.com/Yubico/yubikey-personalization)
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
set(EXCLUDED_DIRS
|
||||
# third-party directories
|
||||
src/thirdparty/
|
||||
src/zxcvbn/
|
||||
# objective-c directories
|
||||
src/touchid/
|
||||
@ -29,9 +30,6 @@ set(EXCLUDED_FILES
|
||||
gui/KMessageWidget.cpp
|
||||
gui/MainWindowAdaptor.h
|
||||
gui/MainWindowAdaptor.cpp
|
||||
crypto/ssh/bcrypt_pbkdf.cpp
|
||||
crypto/ssh/blf.h
|
||||
crypto/ssh/blowfish.c
|
||||
tests/modeltest.cpp
|
||||
tests/modeltest.h
|
||||
# objective-c files
|
||||
|
@ -262,6 +262,8 @@ if(WITH_XC_FDOSECRETS)
|
||||
set(fdosecrets_LIB fdosecrets)
|
||||
endif()
|
||||
|
||||
add_subdirectory(thirdparty)
|
||||
|
||||
set(autotype_SOURCES
|
||||
core/Tools.cpp
|
||||
autotype/AutoType.cpp
|
||||
@ -318,9 +320,9 @@ target_link_libraries(keepassx_core
|
||||
Qt5::Network
|
||||
Qt5::Widgets
|
||||
${BOTAN2_LIBRARIES}
|
||||
${YUBIKEY_LIBRARIES}
|
||||
${ZXCVBN_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${thirdparty_LIBRARIES}
|
||||
)
|
||||
|
||||
if(WITH_XC_SSHAGENT)
|
||||
|
@ -16,15 +16,14 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ykcore.h>
|
||||
#include <ykdef.h>
|
||||
#include <ykpers-version.h>
|
||||
#include <ykstatus.h>
|
||||
#include "YubiKey.h"
|
||||
|
||||
#include "core/Tools.h"
|
||||
#include "crypto/Random.h"
|
||||
|
||||
#include "YubiKey.h"
|
||||
#include "thirdparty/ykcore/ykcore.h"
|
||||
#include "thirdparty/ykcore/ykdef.h"
|
||||
#include "thirdparty/ykcore/ykstatus.h"
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
@ -38,16 +37,11 @@ namespace
|
||||
if (onlyKey) {
|
||||
*onlyKey = false;
|
||||
}
|
||||
#if YKPERS_VERSION_NUMBER >= 0x011200
|
||||
// This function is only available in ykcore >= 1.18.0
|
||||
key = yk_open_key(ykIndex);
|
||||
#else
|
||||
// Only allow for the first found key to be used
|
||||
if (ykIndex == 0) {
|
||||
key = yk_open_first_key();
|
||||
}
|
||||
#endif
|
||||
#if YKPERS_VERSION_NUMBER >= 0x011400
|
||||
|
||||
// New fuction available in yubikey-personalization version >= 1.20.0 that allows
|
||||
// selecting device VID/PID (yk_open_key_vid_pid)
|
||||
if (!key) {
|
||||
@ -57,9 +51,6 @@ namespace
|
||||
*onlyKey = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(okIndex);
|
||||
#endif
|
||||
return key;
|
||||
}
|
||||
|
||||
|
@ -19,3 +19,4 @@ set(qrcode_SOURCES
|
||||
|
||||
add_library(qrcode STATIC ${qrcode_SOURCES})
|
||||
target_link_libraries(qrcode Qt5::Core Qt5::Widgets Qt5::Svg ${QRENCODE_LIBRARY})
|
||||
target_include_directories(qrcode PRIVATE ${QRENCODE_INCLUDE_DIR})
|
||||
|
19
src/thirdparty/CMakeLists.txt
vendored
Normal file
19
src/thirdparty/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 or (at your option)
|
||||
# version 3 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if(WITH_XC_YUBIKEY)
|
||||
add_subdirectory(ykcore)
|
||||
set(thirdparty_LIBRARIES ${thirdparty_LIBRARIES} ykcore PARENT_SCOPE)
|
||||
endif()
|
42
src/thirdparty/ykcore/CMakeLists.txt
vendored
Normal file
42
src/thirdparty/ykcore/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
# Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 or (at your option)
|
||||
# version 3 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(ykcore_SOURCES
|
||||
ykcore.c
|
||||
ykstatus.c
|
||||
ykcrc.c
|
||||
)
|
||||
|
||||
add_library(ykcore STATIC ${ykcore_SOURCES})
|
||||
|
||||
if(WIN32)
|
||||
target_sources(ykcore PRIVATE ykcore_windows.c)
|
||||
target_link_libraries(ykcore PRIVATE uuid setupapi hid)
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
target_sources(ykcore PRIVATE ykcore_libusb-1.0.c)
|
||||
|
||||
find_library(LIBUSB_LIBRARY NAMES usb-1.0)
|
||||
find_path(LIBUSB_INCLUDE_DIR NAMES libusb.h PATH_SUFFIXES "libusb-1.0" "libusb")
|
||||
if(NOT LIBUSB_LIBRARY OR NOT LIBUSB_INCLUDE_DIR)
|
||||
message(FATAL_ERROR "libusb-1.0 dev package required, but not found")
|
||||
endif()
|
||||
|
||||
target_link_libraries(ykcore PRIVATE ${LIBUSB_LIBRARY})
|
||||
target_include_directories(ykcore PRIVATE ${LIBUSB_INCLUDE_DIR})
|
||||
target_compile_definitions(ykcore PRIVATE _GNU_SOURCE)
|
||||
elseif(APPLE)
|
||||
target_sources(ykcore PRIVATE ykcore_osx.c)
|
||||
target_link_libraries(ykcore PUBLIC "-framework IOKit")
|
||||
endif()
|
62
src/thirdparty/ykcore/ykbzero.h
vendored
Normal file
62
src/thirdparty/ykcore/ykbzero.h
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Copyright (c) 2008-2019 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef __YKBZERO_H_INCLUDED__
|
||||
#define __YKBZERO_H_INCLUDED__
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define insecure_memzero(buf, len) SecureZeroMemory(buf, len)
|
||||
#elif defined(HAVE_MEMSET_S)
|
||||
#define insecure_memzero(buf, len) memset_s(buf, len, 0, len)
|
||||
#elif defined(HAVE_EXPLICIT_BZERO)
|
||||
#define insecure_memzero(buf, len) explicit_bzero(buf, len)
|
||||
#elif defined(HAVE_EXPLICIT_MEMSET)
|
||||
#define insecure_memzero(buf, len) explicit_memset(buf, 0, len)
|
||||
#elif defined(HAVE_INLINE_ASM)
|
||||
#define insecure_memzero(buf, len) do { \
|
||||
memset(buf, 0, len); \
|
||||
__asm__ __volatile__ ("" : : "r"(buf) : "memory"); \
|
||||
} while (0)
|
||||
#else
|
||||
#define insecure_memzero(buf, len) do { \
|
||||
volatile unsigned char *volatile __buf_ = \
|
||||
(volatile unsigned char *volatile)buf; \
|
||||
size_t __i_ = 0; \
|
||||
while (__i_ < len) __buf_[__i_++] = 0; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* __YKBZERO_H_INCLUDED__ */
|
782
src/thirdparty/ykcore/ykcore.c
vendored
Normal file
782
src/thirdparty/ykcore/ykcore.c
vendored
Normal file
@ -0,0 +1,782 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Copyright (c) 2008-2015 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#include "ykcore_lcl.h"
|
||||
#include "ykcore_backend.h"
|
||||
#include "yktsd.h"
|
||||
#include "ykbzero.h"
|
||||
|
||||
/* To get modhex and crc16 */
|
||||
#include "yubikey.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#ifndef _WIN32
|
||||
#include <time.h>
|
||||
#define Sleep(milliseconds) \
|
||||
struct timespec ts; \
|
||||
ts.tv_sec = milliseconds / (unsigned int) 1e3; \
|
||||
ts.tv_nsec = (milliseconds % (unsigned int) 1e3) * 1e6; \
|
||||
nanosleep(&ts, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef YK_DEBUG
|
||||
#define _yk_hexdump(buffer, size) \
|
||||
do { \
|
||||
unsigned char *p = buffer; \
|
||||
int i; \
|
||||
fprintf(stderr, "%25s: ", __func__); \
|
||||
for(i = 0; i < size; i++) { \
|
||||
fprintf(stderr, "%02x ", *p++); \
|
||||
} \
|
||||
fprintf(stderr, "\n"); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Yubikey low-level interface section 2.4 (Report arbitration polling) specifies
|
||||
* a 600 ms timeout for a Yubikey to process something written to it.
|
||||
* Where can that document be found?
|
||||
* It has been discovered that for swap 600 is not enough, swapping can worst
|
||||
* case take 920 ms, which we then add 25% to for safety margin, arriving at
|
||||
* 1150 ms.
|
||||
*/
|
||||
#define WAIT_FOR_WRITE_FLAG 1150
|
||||
|
||||
int yk_init(void)
|
||||
{
|
||||
return _ykusb_start();
|
||||
}
|
||||
|
||||
int yk_release(void)
|
||||
{
|
||||
return _ykusb_stop();
|
||||
}
|
||||
|
||||
YK_KEY *yk_open_first_key(void)
|
||||
{
|
||||
return yk_open_key(0);
|
||||
}
|
||||
|
||||
YK_KEY *yk_open_key_vid_pid(int vid, const int* pids, size_t pids_len, int index)
|
||||
{
|
||||
YK_KEY *yk = _ykusb_open_device(vid, pids, pids_len, index);
|
||||
int rc = yk_errno;
|
||||
|
||||
if (yk) {
|
||||
YK_STATUS st;
|
||||
|
||||
if (!yk_get_status(yk, &st)) {
|
||||
rc = yk_errno;
|
||||
yk_close_key(yk);
|
||||
yk = NULL;
|
||||
}
|
||||
}
|
||||
yk_errno = rc;
|
||||
return yk;
|
||||
}
|
||||
|
||||
static const int yubico_pids[] = {YUBIKEY_PID, NEO_OTP_PID, NEO_OTP_CCID_PID,
|
||||
NEO_OTP_U2F_PID, NEO_OTP_U2F_CCID_PID, YK4_OTP_PID,
|
||||
YK4_OTP_U2F_PID, YK4_OTP_CCID_PID, YK4_OTP_U2F_CCID_PID,
|
||||
PLUS_U2F_OTP_PID};
|
||||
|
||||
YK_KEY *yk_open_key(int index)
|
||||
{
|
||||
return yk_open_key_vid_pid(YUBICO_VID, yubico_pids, sizeof(yubico_pids) / sizeof(yubico_pids[0]), index);
|
||||
}
|
||||
|
||||
int yk_close_key(YK_KEY *yk)
|
||||
{
|
||||
return _ykusb_close_device(yk);
|
||||
}
|
||||
|
||||
int yk_check_firmware_version(YK_KEY *k)
|
||||
{
|
||||
YK_STATUS st;
|
||||
|
||||
if (!yk_get_status(k, &st))
|
||||
return 0;
|
||||
|
||||
return yk_check_firmware_version2(&st);
|
||||
}
|
||||
|
||||
|
||||
int yk_check_firmware_version2(YK_STATUS *st)
|
||||
{
|
||||
(void)st;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int yk_get_status(YK_KEY *k, YK_STATUS *status)
|
||||
{
|
||||
unsigned int status_count = 0;
|
||||
|
||||
if (!yk_read_from_key(k, 0, status, sizeof(YK_STATUS), &status_count))
|
||||
return 0;
|
||||
|
||||
if (status_count != sizeof(YK_STATUS)) {
|
||||
yk_errno = YK_EWRONGSIZ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
status->touchLevel = yk_endian_swap_16(status->touchLevel);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read the factory programmed serial number from a YubiKey.
|
||||
* The possibility to retreive the serial number might be disabled
|
||||
* using configuration, so it should not be considered a fatal error
|
||||
* to not be able to read the serial number using this function.
|
||||
*
|
||||
* Serial number reading might also be configured to require user
|
||||
* interaction (YubiKey button press) on startup, in which case flags
|
||||
* might have to have YK_FLAG_MAYBLOCK set - haven't tried that.
|
||||
*
|
||||
* The slot parameter is here for future purposes only.
|
||||
*/
|
||||
int yk_get_serial(YK_KEY *yk, uint8_t slot, unsigned int flags, unsigned int *serial)
|
||||
{
|
||||
unsigned char buf[FEATURE_RPT_SIZE * 2];
|
||||
unsigned int response_len = 0;
|
||||
unsigned int expect_bytes = 0;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (!yk_write_to_key(yk, SLOT_DEVICE_SERIAL, &buf, 0))
|
||||
return 0;
|
||||
|
||||
expect_bytes = 4;
|
||||
|
||||
if (! yk_read_response_from_key(yk, slot, flags,
|
||||
&buf, sizeof(buf),
|
||||
expect_bytes,
|
||||
&response_len))
|
||||
return 0;
|
||||
|
||||
/* Serial number is stored in big endian byte order, despite
|
||||
* everything else in the YubiKey being little endian - for
|
||||
* some good reason I don't remember.
|
||||
*/
|
||||
*serial =
|
||||
(buf[0] << 24) +
|
||||
(buf[1] << 16) +
|
||||
(buf[2] << 8) +
|
||||
(buf[3]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int yk_get_capabilities(YK_KEY *yk, uint8_t slot, unsigned int flags,
|
||||
unsigned char *capabilities, unsigned int *len)
|
||||
{
|
||||
unsigned int response_len = 0;
|
||||
|
||||
if (!yk_write_to_key(yk, SLOT_YK4_CAPABILITIES, capabilities, 0))
|
||||
return 0;
|
||||
|
||||
if (! yk_read_response_from_key(yk, slot, flags,
|
||||
capabilities, *len, 0, /* we have no idea how much data we'll get */
|
||||
&response_len))
|
||||
return 0;
|
||||
|
||||
/* the first data of the capabilities string is the length */
|
||||
response_len = capabilities[0];
|
||||
response_len++;
|
||||
|
||||
/* validate the length we got back from the hardware */
|
||||
if (response_len > *len) {
|
||||
yk_errno = YK_EWRONGSIZ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*len = response_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _yk_write(YK_KEY *yk, uint8_t yk_cmd, unsigned char *buf, size_t len)
|
||||
{
|
||||
YK_STATUS stat;
|
||||
int seq;
|
||||
|
||||
/* Get current sequence # from status block */
|
||||
|
||||
if (!yk_get_status(yk, &stat /*, 0*/))
|
||||
return 0;
|
||||
|
||||
seq = stat.pgmSeq;
|
||||
|
||||
/* Write to Yubikey */
|
||||
if (!yk_write_to_key(yk, yk_cmd, buf, len))
|
||||
return 0;
|
||||
|
||||
/* When the Yubikey clears the SLOT_WRITE_FLAG, it has processed the last write.
|
||||
* This wait can't be done in yk_write_to_key since some users of that function
|
||||
* want to get the bytes in the status message, but when writing configuration
|
||||
* we don't expect any data back.
|
||||
*/
|
||||
if(!yk_wait_for_key_status(yk, yk_cmd, 0, WAIT_FOR_WRITE_FLAG, false, SLOT_WRITE_FLAG, NULL))
|
||||
return 0;
|
||||
|
||||
/* Verify update */
|
||||
|
||||
if (!yk_get_status(yk, &stat /*, 0*/))
|
||||
return 0;
|
||||
|
||||
yk_errno = YK_EWRITEERR;
|
||||
|
||||
/* when both configurations from a YubiKey is erased it will return
|
||||
* pgmSeq 0, if one is still configured after an erase pgmSeq is
|
||||
* counted up as usual. */
|
||||
if((stat.touchLevel & (CONFIG1_VALID | CONFIG2_VALID)) == 0 && stat.pgmSeq == 0) {
|
||||
return 1;
|
||||
}
|
||||
return stat.pgmSeq != seq;
|
||||
}
|
||||
|
||||
int yk_write_device_info(YK_KEY *yk, unsigned char *buf, unsigned int len)
|
||||
{
|
||||
return _yk_write(yk, SLOT_YK4_SET_DEVICE_INFO, buf, len);
|
||||
}
|
||||
|
||||
|
||||
int yk_write_command(YK_KEY *yk, YK_CONFIG *cfg, uint8_t command,
|
||||
unsigned char *acc_code)
|
||||
{
|
||||
int ret;
|
||||
unsigned char buf[sizeof(YK_CONFIG) + ACC_CODE_SIZE];
|
||||
|
||||
/* Update checksum and insert config block in buffer if present */
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (cfg) {
|
||||
cfg->crc = ~yubikey_crc16 ((unsigned char *) cfg,
|
||||
sizeof(YK_CONFIG) - sizeof(cfg->crc));
|
||||
cfg->crc = yk_endian_swap_16(cfg->crc);
|
||||
memcpy(buf, cfg, sizeof(YK_CONFIG));
|
||||
}
|
||||
|
||||
/* Append current access code if present */
|
||||
|
||||
if (acc_code)
|
||||
memcpy(buf + sizeof(YK_CONFIG), acc_code, ACC_CODE_SIZE);
|
||||
|
||||
ret = _yk_write(yk, command, buf, sizeof(buf));
|
||||
insecure_memzero(buf, sizeof(buf));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int yk_write_config(YK_KEY *yk, YK_CONFIG *cfg, int confnum,
|
||||
unsigned char *acc_code)
|
||||
{
|
||||
uint8_t command;
|
||||
switch(confnum) {
|
||||
case 1:
|
||||
command = SLOT_CONFIG;
|
||||
break;
|
||||
case 2:
|
||||
command = SLOT_CONFIG2;
|
||||
break;
|
||||
default:
|
||||
yk_errno = YK_EINVALIDCMD;
|
||||
return 0;
|
||||
}
|
||||
if(!yk_write_command(yk, cfg, command, acc_code)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int yk_write_ndef(YK_KEY *yk, YK_NDEF *ndef)
|
||||
{
|
||||
/* just wrap yk_write_ndef2() with confnum 1 */
|
||||
return yk_write_ndef2(yk, ndef, 1);
|
||||
}
|
||||
|
||||
int yk_write_ndef2(YK_KEY *yk, YK_NDEF *ndef, int confnum)
|
||||
{
|
||||
unsigned char buf[sizeof(YK_NDEF)];
|
||||
uint8_t command;
|
||||
|
||||
switch(confnum) {
|
||||
case 1:
|
||||
command = SLOT_NDEF;
|
||||
break;
|
||||
case 2:
|
||||
command = SLOT_NDEF2;
|
||||
break;
|
||||
default:
|
||||
yk_errno = YK_EINVALIDCMD;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Insert config block in buffer */
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memcpy(buf, ndef, sizeof(YK_NDEF));
|
||||
|
||||
return _yk_write(yk, command, buf, sizeof(YK_NDEF));
|
||||
}
|
||||
|
||||
int yk_write_device_config(YK_KEY *yk, YK_DEVICE_CONFIG *device_config)
|
||||
{
|
||||
unsigned char buf[sizeof(YK_DEVICE_CONFIG)];
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memcpy(buf, device_config, sizeof(YK_DEVICE_CONFIG));
|
||||
|
||||
return _yk_write(yk, SLOT_DEVICE_CONFIG, buf, sizeof(YK_DEVICE_CONFIG));
|
||||
}
|
||||
|
||||
int yk_write_scan_map(YK_KEY *yk, unsigned char *scan_map)
|
||||
{
|
||||
return _yk_write(yk, SLOT_SCAN_MAP, scan_map, strlen(SCAN_MAP));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is for doing HMAC-SHA1 or Yubico challenge-response with a key.
|
||||
*/
|
||||
int yk_challenge_response(YK_KEY *yk, uint8_t yk_cmd, int may_block,
|
||||
unsigned int challenge_len, const unsigned char *challenge,
|
||||
unsigned int response_len, unsigned char *response)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
unsigned int bytes_read = 0;
|
||||
unsigned int expect_bytes = 0;
|
||||
|
||||
switch(yk_cmd) {
|
||||
case SLOT_CHAL_HMAC1:
|
||||
case SLOT_CHAL_HMAC2:
|
||||
expect_bytes = 20;
|
||||
break;
|
||||
case SLOT_CHAL_OTP1:
|
||||
case SLOT_CHAL_OTP2:
|
||||
expect_bytes = 16;
|
||||
break;
|
||||
default:
|
||||
yk_errno = YK_EINVALIDCMD;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (may_block)
|
||||
flags |= YK_FLAG_MAYBLOCK;
|
||||
|
||||
if (! yk_write_to_key(yk, yk_cmd, challenge, challenge_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (! yk_read_response_from_key(yk, yk_cmd, flags,
|
||||
response, response_len,
|
||||
expect_bytes,
|
||||
&bytes_read)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int * _yk_errno_location(void)
|
||||
{
|
||||
static int tsd_init = 0;
|
||||
static int nothread_errno = 0;
|
||||
YK_DEFINE_TSD_METADATA(errno_key);
|
||||
int rc = 0;
|
||||
|
||||
if (tsd_init == 0) {
|
||||
if ((rc = YK_TSD_INIT(errno_key, free)) == 0) {
|
||||
tsd_init = 1;
|
||||
} else {
|
||||
tsd_init = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(YK_TSD_GET(int *, errno_key) == NULL) {
|
||||
void *p = calloc(1, sizeof(int));
|
||||
if (!p) {
|
||||
tsd_init = -1;
|
||||
} else {
|
||||
(void)!YK_TSD_SET(errno_key, p);
|
||||
}
|
||||
}
|
||||
if (tsd_init == 1) {
|
||||
return YK_TSD_GET(int *, errno_key);
|
||||
}
|
||||
return ¬hread_errno;
|
||||
}
|
||||
|
||||
static const char *errtext[] = {
|
||||
"",
|
||||
"USB error",
|
||||
"wrong size",
|
||||
"write error",
|
||||
"timeout",
|
||||
"no yubikey present",
|
||||
"unsupported firmware version",
|
||||
"out of memory",
|
||||
"no status structure given",
|
||||
"not yet implemented",
|
||||
"checksum mismatch",
|
||||
"operation would block",
|
||||
"invalid command for operation",
|
||||
"expected only one YubiKey but several present",
|
||||
"no data returned from device",
|
||||
};
|
||||
const char *yk_strerror(int errnum)
|
||||
{
|
||||
if (errnum < (int)(sizeof(errtext)/sizeof(errtext[0])))
|
||||
return errtext[errnum];
|
||||
return NULL;
|
||||
}
|
||||
const char *yk_usb_strerror(void)
|
||||
{
|
||||
return _ykusb_strerror();
|
||||
}
|
||||
|
||||
/* This function would've been better named 'yk_read_status_from_key'. Because
|
||||
* it disregards the first byte in each feature report, it can't be used to read
|
||||
* generic feature reports from the Yubikey, and this behaviour can't be changed
|
||||
* without breaking compatibility with existing programs.
|
||||
*
|
||||
* See yk_read_response_from_key() for a generic purpose data reading function.
|
||||
*
|
||||
* The slot parameter is here for future purposes only.
|
||||
*/
|
||||
int yk_read_from_key(YK_KEY *yk, uint8_t slot,
|
||||
void *buf, unsigned int bufsize, unsigned int *bufcount)
|
||||
{
|
||||
(void)slot;
|
||||
unsigned char data[FEATURE_RPT_SIZE];
|
||||
|
||||
if (bufsize > FEATURE_RPT_SIZE - 1) {
|
||||
yk_errno = YK_EWRONGSIZ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
if (!_ykusb_read(yk, REPORT_TYPE_FEATURE, 0, (char *)data, FEATURE_RPT_SIZE))
|
||||
return 0;
|
||||
|
||||
/* This makes it apparent that there's some mysterious value in
|
||||
the first byte... I wonder what... /Richard Levitte */
|
||||
memcpy(buf, data + 1, bufsize);
|
||||
*bufcount = bufsize;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Wait for the Yubikey to either set or clear (controlled by the boolean logic_and)
|
||||
* the bits in mask.
|
||||
*
|
||||
* The slot parameter is here for future purposes only.
|
||||
*/
|
||||
int yk_wait_for_key_status(YK_KEY *yk, uint8_t slot, unsigned int flags,
|
||||
unsigned int max_time_ms,
|
||||
bool logic_and, unsigned char mask,
|
||||
unsigned char *last_data)
|
||||
{
|
||||
unsigned char data[FEATURE_RPT_SIZE];
|
||||
|
||||
unsigned int sleepval = 1;
|
||||
unsigned int slept_time = 0;
|
||||
int blocking = 0;
|
||||
|
||||
/* Non-zero slot breaks on Windows (libusb-1.0.8-win32), while working fine
|
||||
* on Linux (and probably MacOS X).
|
||||
*
|
||||
* The YubiKey doesn't support per-slot status anyways at the moment (2.2),
|
||||
* so we just set it to 0 (meaning slot 1).
|
||||
*/
|
||||
slot = 0;
|
||||
|
||||
while (slept_time < max_time_ms) {
|
||||
Sleep(sleepval);
|
||||
slept_time += sleepval;
|
||||
/* exponential backoff, up to 500 ms */
|
||||
sleepval *= 2;
|
||||
if (sleepval > 500)
|
||||
sleepval = 500;
|
||||
|
||||
/* Read a status report from the key */
|
||||
memset(data, 0, sizeof(data));
|
||||
if (!_ykusb_read(yk, REPORT_TYPE_FEATURE, slot, (char *) &data, FEATURE_RPT_SIZE))
|
||||
return 0;
|
||||
#ifdef YK_DEBUG
|
||||
_yk_hexdump(data, FEATURE_RPT_SIZE);
|
||||
#endif
|
||||
|
||||
if (last_data != NULL)
|
||||
memcpy(last_data, data, sizeof(data));
|
||||
|
||||
/* The status byte from the key is now in last byte of data */
|
||||
if (logic_and) {
|
||||
/* Check if Yubikey has SET the bit(s) in mask */
|
||||
if ((data[FEATURE_RPT_SIZE - 1] & mask) == mask) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* Check if Yubikey has CLEARED the bit(s) in mask */
|
||||
if (! (data[FEATURE_RPT_SIZE - 1] & mask)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if Yubikey says it will wait for user interaction */
|
||||
if ((data[FEATURE_RPT_SIZE - 1] & RESP_TIMEOUT_WAIT_FLAG) == RESP_TIMEOUT_WAIT_FLAG) {
|
||||
if ((flags & YK_FLAG_MAYBLOCK) == YK_FLAG_MAYBLOCK) {
|
||||
if (! blocking) {
|
||||
/* Extend timeout first time we see RESP_TIMEOUT_WAIT_FLAG. */
|
||||
blocking = 1;
|
||||
max_time_ms += 256 * 1000;
|
||||
}
|
||||
} else {
|
||||
/* Reset read mode of Yubikey before aborting. */
|
||||
yk_force_key_update(yk);
|
||||
yk_errno = YK_EWOULDBLOCK;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (blocking) {
|
||||
/* YubiKey timed out waiting for user interaction */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yk_errno = YK_ETIMEOUT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read one or more feature reports from a Yubikey and put them together.
|
||||
*
|
||||
* Bufsize must be able to hold at least 2 more bytes than you are expecting
|
||||
* (the CRC), but since all read requests return 7 bytes of data bufsize needs
|
||||
* to be up to 7 bytes more than you expect.
|
||||
*
|
||||
* If the key returns more data than bufsize, we fail and set yk_errno to
|
||||
* YK_EWRONGSIZ. If that happens there will be partial data in buf.
|
||||
*
|
||||
* If we read a response from a Yubikey that is configured to block and wait for
|
||||
* a button press (in challenge response), this function will abort unless
|
||||
* flags contain YK_FLAG_MAYBLOCK, in which case it might take up to 15 seconds
|
||||
* for this function to return.
|
||||
*
|
||||
* The slot parameter is here for future purposes only.
|
||||
*/
|
||||
int yk_read_response_from_key(YK_KEY *yk, uint8_t slot, unsigned int flags,
|
||||
void *buf, unsigned int bufsize, unsigned int expect_bytes,
|
||||
unsigned int *bytes_read)
|
||||
{
|
||||
unsigned char data[FEATURE_RPT_SIZE];
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
memset(buf, 0, bufsize);
|
||||
*bytes_read = 0;
|
||||
|
||||
#ifdef YK_DEBUG
|
||||
fprintf(stderr, "YK_DEBUG: Read %i bytes from YubiKey :\n", expect_bytes);
|
||||
#endif
|
||||
/* Wait for the key to turn on RESP_PENDING_FLAG */
|
||||
if (! yk_wait_for_key_status(yk, slot, flags, 1000, true, RESP_PENDING_FLAG, (unsigned char *) &data))
|
||||
return 0;
|
||||
|
||||
/* The first part of the response was read by yk_wait_for_key_status(). We need
|
||||
* to copy it to buf.
|
||||
*/
|
||||
memcpy((char*)buf + *bytes_read, data, sizeof(data) - 1);
|
||||
*bytes_read += sizeof(data) - 1;
|
||||
|
||||
while (*bytes_read + FEATURE_RPT_SIZE <= bufsize) {
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
if (!_ykusb_read(yk, REPORT_TYPE_FEATURE, 0, (char *)data, FEATURE_RPT_SIZE))
|
||||
return 0;
|
||||
#ifdef YK_DEBUG
|
||||
_yk_hexdump(data, FEATURE_RPT_SIZE);
|
||||
#endif
|
||||
if (data[FEATURE_RPT_SIZE - 1] & RESP_PENDING_FLAG) {
|
||||
/* The lower five bits of the status byte has the response sequence
|
||||
* number. If that gets reset to zero we are done.
|
||||
*/
|
||||
if ((data[FEATURE_RPT_SIZE - 1] & 31) == 0) {
|
||||
if (expect_bytes > 0) {
|
||||
/* Size of response is known. Verify CRC. */
|
||||
expect_bytes += 2;
|
||||
int crc = yubikey_crc16(buf, expect_bytes);
|
||||
if (crc != YK_CRC_OK_RESIDUAL) {
|
||||
yk_errno = YK_ECHECKSUM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* since we get data in chunks of 7 we need to round expect bytes out to the closest higher multiple of 7 */
|
||||
if(expect_bytes % 7 != 0) {
|
||||
expect_bytes += 7 - (expect_bytes % 7);
|
||||
}
|
||||
|
||||
if (*bytes_read != expect_bytes) {
|
||||
yk_errno = YK_EWRONGSIZ;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset read mode of Yubikey before returning. */
|
||||
yk_force_key_update(yk);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy((char*)buf + *bytes_read, data, sizeof(data) - 1);
|
||||
*bytes_read += sizeof(data) - 1;
|
||||
} else {
|
||||
/* Reset read mode of Yubikey before returning. */
|
||||
yk_force_key_update(yk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* We're out of buffer space, abort reading */
|
||||
yk_force_key_update(yk);
|
||||
|
||||
yk_errno = YK_EWRONGSIZ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send something to the YubiKey. The command, as well as the slot, is
|
||||
* given in the 'slot' parameter (e.g. SLOT_CHAL_HMAC2 to send a HMAC-SHA1
|
||||
* challenge to slot 2).
|
||||
*/
|
||||
int yk_write_to_key(YK_KEY *yk, uint8_t slot, const void *buf, int bufcount)
|
||||
{
|
||||
YK_FRAME frame;
|
||||
unsigned char repbuf[FEATURE_RPT_SIZE];
|
||||
int i, seq;
|
||||
int ret = 0;
|
||||
unsigned char *ptr, *end;
|
||||
|
||||
if (bufcount > (int)sizeof(frame.payload)) {
|
||||
yk_errno = YK_EWRONGSIZ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Insert data and set slot # */
|
||||
|
||||
memset(&frame, 0, sizeof(frame));
|
||||
memcpy(frame.payload, buf, bufcount);
|
||||
frame.slot = slot;
|
||||
|
||||
/* Append slot checksum */
|
||||
|
||||
i = yubikey_crc16 (frame.payload, sizeof(frame.payload));
|
||||
frame.crc = yk_endian_swap_16(i);
|
||||
|
||||
/* Chop up the data into parts that fits into the payload of a
|
||||
feature report. Set the sequence number | 0x80 in the end
|
||||
of the feature report. When the Yubikey has processed it,
|
||||
it will clear this byte, signaling that the next part can be
|
||||
sent */
|
||||
|
||||
ptr = (unsigned char *) &frame;
|
||||
end = (unsigned char *) &frame + sizeof(frame);
|
||||
|
||||
#ifdef YK_DEBUG
|
||||
fprintf(stderr, "YK_DEBUG: Write %i bytes to YubiKey :\n", bufcount);
|
||||
#endif
|
||||
for (seq = 0; ptr < end; seq++) {
|
||||
int all_zeros = 1;
|
||||
/* Ignore parts that are all zeroes except first and last
|
||||
to speed up the transfer */
|
||||
|
||||
for (i = 0; i < (FEATURE_RPT_SIZE - 1); i++) {
|
||||
if ((repbuf[i] = *ptr++)) all_zeros = 0;
|
||||
}
|
||||
if (all_zeros && (seq > 0) && (ptr < end))
|
||||
continue;
|
||||
|
||||
/* sequence number goes into lower bits of last byte */
|
||||
repbuf[i] = seq | SLOT_WRITE_FLAG;
|
||||
|
||||
/* When the Yubikey clears the SLOT_WRITE_FLAG, the
|
||||
* next part can be sent.
|
||||
*/
|
||||
if (! yk_wait_for_key_status(yk, slot, 0, WAIT_FOR_WRITE_FLAG,
|
||||
false, SLOT_WRITE_FLAG, NULL))
|
||||
goto end;
|
||||
#ifdef YK_DEBUG
|
||||
_yk_hexdump(repbuf, FEATURE_RPT_SIZE);
|
||||
#endif
|
||||
if (!_ykusb_write(yk, REPORT_TYPE_FEATURE, 0,
|
||||
(char *)repbuf, FEATURE_RPT_SIZE))
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
insecure_memzero(&frame, sizeof(YK_FRAME));
|
||||
insecure_memzero(repbuf, sizeof(repbuf));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int yk_force_key_update(YK_KEY *yk)
|
||||
{
|
||||
unsigned char buf[FEATURE_RPT_SIZE];
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
buf[FEATURE_RPT_SIZE - 1] = DUMMY_REPORT_WRITE; /* Invalid sequence = update only */
|
||||
if (!_ykusb_write(yk, REPORT_TYPE_FEATURE, 0, (char *)buf, FEATURE_RPT_SIZE))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int yk_get_key_vid_pid(YK_KEY *yk, int *vid, int *pid) {
|
||||
return _ykusb_get_vid_pid(yk, vid, pid);
|
||||
}
|
||||
|
||||
uint16_t yk_endian_swap_16(uint16_t x)
|
||||
{
|
||||
static int testflag = -1;
|
||||
|
||||
if (testflag == -1) {
|
||||
uint16_t testword = 0x0102;
|
||||
unsigned char *testchars = (unsigned char *)&testword;
|
||||
if (*testchars == '\1')
|
||||
testflag = 1; /* Big endian arch, swap needed */
|
||||
else
|
||||
testflag = 0; /* Little endian arch, no swap needed */
|
||||
}
|
||||
|
||||
if (testflag)
|
||||
x = (x >> 8) | ((x & 0xff) << 8);
|
||||
|
||||
return x;
|
||||
}
|
191
src/thirdparty/ykcore/ykcore.h
vendored
Normal file
191
src/thirdparty/ykcore/ykcore.h
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Copyright (c) 2008-2015 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef __YKCORE_H_INCLUDED__
|
||||
#define __YKCORE_H_INCLUDED__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/*************************************************************************
|
||||
**
|
||||
** N O T E : For all functions that return a value, 0 and NULL indicates
|
||||
** an error, other values indicate success.
|
||||
**
|
||||
************************************************************************/
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Structures used. They are further defined in ykdef.h
|
||||
*
|
||||
****/
|
||||
|
||||
typedef struct yk_key_st YK_KEY; /* Really a USB device handle. */
|
||||
typedef struct yk_status_st YK_STATUS; /* Status structure,
|
||||
filled by yk_get_status(). */
|
||||
|
||||
typedef struct yk_ticket_st YK_TICKET; /* Ticket structure... */
|
||||
typedef struct yk_config_st YK_CONFIG; /* Configuration structure.
|
||||
Other libraries provide access. */
|
||||
typedef struct yk_nav_st YK_NAV; /* Navigation structure.
|
||||
Other libraries provide access. */
|
||||
typedef struct yk_frame_st YK_FRAME; /* Data frame for write operation */
|
||||
typedef struct ndef_st YK_NDEF;
|
||||
typedef struct yk_device_config_st YK_DEVICE_CONFIG;
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Library initialisation functions.
|
||||
*
|
||||
****/
|
||||
extern int yk_init(void);
|
||||
extern int yk_release(void);
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Functions to get and release the key itself.
|
||||
*
|
||||
****/
|
||||
/* opens first key available. For backwards compatability */
|
||||
extern YK_KEY *yk_open_first_key(void);
|
||||
extern YK_KEY *yk_open_key(int); /* opens nth key available */
|
||||
extern YK_KEY *yk_open_key_vid_pid(int, const int*, size_t, int);
|
||||
extern int yk_close_key(YK_KEY *k); /* closes a previously opened key */
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Functions to get data from the key.
|
||||
*
|
||||
****/
|
||||
/* fetches key status into the structure given by `status' */
|
||||
extern int yk_get_status(YK_KEY *k, YK_STATUS *status /*, int forceUpdate */);
|
||||
/* checks that the firmware revision of the key is supported */
|
||||
extern int yk_check_firmware_version(YK_KEY *k);
|
||||
extern int yk_check_firmware_version2(YK_STATUS *status);
|
||||
/* Read the factory set serial number from a YubiKey 2.0 or higher. */
|
||||
extern int yk_get_serial(YK_KEY *yk, uint8_t slot, unsigned int flags, unsigned int *serial);
|
||||
/* Wait for the key to either set or clear bits in it's status byte */
|
||||
extern int yk_wait_for_key_status(YK_KEY *yk, uint8_t slot, unsigned int flags,
|
||||
unsigned int max_time_ms,
|
||||
bool logic_and, unsigned char mask,
|
||||
unsigned char *last_data);
|
||||
/* Read the response to a command from the YubiKey */
|
||||
extern int yk_read_response_from_key(YK_KEY *yk, uint8_t slot, unsigned int flags,
|
||||
void *buf, unsigned int bufsize, unsigned int expect_bytes,
|
||||
unsigned int *bytes_read);
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Functions to write data to the key.
|
||||
*
|
||||
****/
|
||||
|
||||
/* writes the given configuration to the key. If the configuration is NULL,
|
||||
zap the key configuration.
|
||||
acc_code has to be provided of the key has a protecting access code. */
|
||||
extern int yk_write_command(YK_KEY *k, YK_CONFIG *cfg, uint8_t command,
|
||||
unsigned char *acc_code);
|
||||
/* wrapper function of yk_write_command */
|
||||
extern int yk_write_config(YK_KEY *k, YK_CONFIG *cfg, int confnum,
|
||||
unsigned char *acc_code);
|
||||
/* writes the given ndef to the key as SLOT_NDEF */
|
||||
extern int yk_write_ndef(YK_KEY *yk, YK_NDEF *ndef);
|
||||
/* writes the given ndef to the key. */
|
||||
extern int yk_write_ndef2(YK_KEY *yk, YK_NDEF *ndef, int confnum);
|
||||
/* writes a device config block to the key. */
|
||||
extern int yk_write_device_config(YK_KEY *yk, YK_DEVICE_CONFIG *device_config);
|
||||
/* writes a scanmap to the key. */
|
||||
extern int yk_write_scan_map(YK_KEY *yk, unsigned char *scan_map);
|
||||
/* Write something to the YubiKey (a command that is). */
|
||||
extern int yk_write_to_key(YK_KEY *yk, uint8_t slot, const void *buf, int bufcount);
|
||||
/* Do a challenge-response round with the key. */
|
||||
extern int yk_challenge_response(YK_KEY *yk, uint8_t yk_cmd, int may_block,
|
||||
unsigned int challenge_len, const unsigned char *challenge,
|
||||
unsigned int response_len, unsigned char *response);
|
||||
|
||||
extern int yk_force_key_update(YK_KEY *yk);
|
||||
/* Get the VID and PID of an opened device. */
|
||||
extern int yk_get_key_vid_pid(YK_KEY *yk, int *vid, int *pid);
|
||||
/* Get the YK4 capabilities */
|
||||
int yk_get_capabilities(YK_KEY *yk, uint8_t slot, unsigned int flags,
|
||||
unsigned char *capabilities, unsigned int *len);
|
||||
/* Set the device info (TLV string) */
|
||||
int yk_write_device_info(YK_KEY *yk, unsigned char *buf, unsigned int len);
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Error handling fuctions
|
||||
*
|
||||
****/
|
||||
extern int * _yk_errno_location(void);
|
||||
#define yk_errno (*_yk_errno_location())
|
||||
const char *yk_strerror(int errnum);
|
||||
/* The following function is only useful if yk_errno == YK_EUSBERR and
|
||||
no other USB-related operations have been performed since the time of
|
||||
error. */
|
||||
const char *yk_usb_strerror(void);
|
||||
|
||||
|
||||
/* Swaps the two bytes between little and big endian on big endian machines */
|
||||
extern uint16_t yk_endian_swap_16(uint16_t x);
|
||||
|
||||
#define YK_EUSBERR 0x01 /* USB error reporting should be used */
|
||||
#define YK_EWRONGSIZ 0x02
|
||||
#define YK_EWRITEERR 0x03
|
||||
#define YK_ETIMEOUT 0x04
|
||||
#define YK_ENOKEY 0x05
|
||||
#define YK_EFIRMWARE 0x06
|
||||
#define YK_ENOMEM 0x07
|
||||
#define YK_ENOSTATUS 0x08
|
||||
#define YK_ENOTYETIMPL 0x09
|
||||
#define YK_ECHECKSUM 0x0a /* checksum validation failed */
|
||||
#define YK_EWOULDBLOCK 0x0b /* operation would block */
|
||||
#define YK_EINVALIDCMD 0x0c /* supplied command is invalid for this operation */
|
||||
#define YK_EMORETHANONE 0x0d /* expected to find only one key but found more */
|
||||
#define YK_ENODATA 0x0e /* no data was returned from a read */
|
||||
|
||||
/* Flags for response reading. Use high numbers to not exclude the possibility
|
||||
* to combine these with for example SLOT commands from ykdef.h in the future.
|
||||
*/
|
||||
#define YK_FLAG_MAYBLOCK 0x01 << 16
|
||||
|
||||
#define YK_CRC_OK_RESIDUAL 0xf0b8
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif /* __YKCORE_H_INCLUDED__ */
|
54
src/thirdparty/ykcore/ykcore_backend.h
vendored
Normal file
54
src/thirdparty/ykcore/ykcore_backend.h
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Written by Richard Levitte <richar@levitte.org>
|
||||
* Copyright (c) 2008-2014 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef __YKCORE_BACKEND_H_INCLUDED__
|
||||
#define __YKCORE_BACKEND_H_INCLUDED__
|
||||
|
||||
#define FEATURE_RPT_SIZE 8
|
||||
|
||||
#define REPORT_TYPE_FEATURE 0x03
|
||||
|
||||
int _ykusb_start(void);
|
||||
int _ykusb_stop(void);
|
||||
|
||||
void * _ykusb_open_device(int vendor_id, const int *product_ids, size_t pids_len, int index);
|
||||
int _ykusb_close_device(void *);
|
||||
|
||||
int _ykusb_read(void *dev, int report_type, int report_number,
|
||||
char *buffer, int buffer_size);
|
||||
int _ykusb_write(void *dev, int report_type, int report_number,
|
||||
char *buffer, int buffer_size);
|
||||
|
||||
int _ykusb_get_vid_pid(void *dev, int *vid, int *pid);
|
||||
|
||||
const char *_ykusb_strerror(void);
|
||||
|
||||
#endif /* __YKCORE_BACKEND_H_INCLUDED__ */
|
69
src/thirdparty/ykcore/ykcore_lcl.h
vendored
Normal file
69
src/thirdparty/ykcore/ykcore_lcl.h
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef __YKCORE_LCL_H_INCLUDED__
|
||||
#define __YKCORE_LCL_H_INCLUDED__
|
||||
|
||||
/* This is a hack to map official structure names (in ykcore.h) to
|
||||
internal ones (in ykdef.h) */
|
||||
#define yk_key_st yubikey_st
|
||||
#define yk_status_st status_st
|
||||
#define yk_ticket_st ticket_st
|
||||
#define yk_config_st config_st
|
||||
#define yk_nav_st nav_st
|
||||
#define yk_frame_st frame_st
|
||||
#define yk_device_config_st device_config_st
|
||||
|
||||
#include "ykcore.h"
|
||||
#include "ykdef.h"
|
||||
|
||||
/*************************************************************************
|
||||
**
|
||||
** = = = = = = = = = B I G F A T W A R N I N G = = = = = = = = =
|
||||
**
|
||||
** DO NOT USE THE FOLLOWING FUCTIONS DIRECTLY UNLESS YOU WRITE CORE ROUTINES!
|
||||
**
|
||||
** These functions are declared here only to make sure they get defined
|
||||
** correctly internally.
|
||||
**
|
||||
** YOU HAVE BEEN WARNED!
|
||||
**
|
||||
****/
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* Functions to send and receive data to/from the key.
|
||||
*
|
||||
****/
|
||||
extern int yk_read_from_key(YK_KEY *k, uint8_t slot,
|
||||
void *buf, unsigned int bufsize,
|
||||
unsigned int *bufcount);
|
||||
|
||||
#endif /* __YKCORE_LCL_H_INCLUDED__ */
|
296
src/thirdparty/ykcore/ykcore_libusb-1.0.c
vendored
Normal file
296
src/thirdparty/ykcore/ykcore_libusb-1.0.c
vendored
Normal file
@ -0,0 +1,296 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Yubico AB
|
||||
* Copyright (c) 2009 Tollef Fog Heen <tfheen@err.no>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#include <libusb.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ykcore.h"
|
||||
#include "ykdef.h"
|
||||
#include "ykcore_backend.h"
|
||||
|
||||
#define HID_GET_REPORT 0x01
|
||||
#define HID_SET_REPORT 0x09
|
||||
|
||||
static int ykl_errno;
|
||||
static int libusb_inited = 0;
|
||||
static libusb_context *usb_ctx = NULL;
|
||||
|
||||
/*************************************************************************
|
||||
** function _ykusb_write **
|
||||
** Set HID report **
|
||||
** **
|
||||
** int _ykusb_write(YUBIKEY *yk, int report_type, int report_number, **
|
||||
** char *buffer, int size) **
|
||||
** **
|
||||
** Where: **
|
||||
** "yk" is handle to open Yubikey **
|
||||
** "report_type" is HID report type (in, out or feature) **
|
||||
** "report_number" is report identifier **
|
||||
** "buffer" is pointer to in buffer **
|
||||
** "size" is size of the buffer **
|
||||
** **
|
||||
** Returns: Nonzero if successful, zero otherwise **
|
||||
** **
|
||||
*************************************************************************/
|
||||
|
||||
int _ykusb_write(void *dev, int report_type, int report_number,
|
||||
char *buffer, int size)
|
||||
{
|
||||
ykl_errno = libusb_claim_interface((libusb_device_handle *)dev, 0);
|
||||
|
||||
if (ykl_errno == 0) {
|
||||
int rc2;
|
||||
ykl_errno = libusb_control_transfer((libusb_device_handle *)dev,
|
||||
LIBUSB_REQUEST_TYPE_CLASS |
|
||||
LIBUSB_RECIPIENT_INTERFACE |
|
||||
LIBUSB_ENDPOINT_OUT,
|
||||
HID_SET_REPORT,
|
||||
report_type << 8 | report_number, 0,
|
||||
(unsigned char *)buffer, size,
|
||||
1000);
|
||||
/* preserve a control message error over an interface
|
||||
release one */
|
||||
rc2 = libusb_release_interface((libusb_device_handle *)dev, 0);
|
||||
if (ykl_errno > 0 && rc2 < 0)
|
||||
ykl_errno = rc2;
|
||||
}
|
||||
if (ykl_errno > 0)
|
||||
return 1;
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
** function _ykusb_read **
|
||||
** Get HID report **
|
||||
** **
|
||||
** int _ykusb_read(YUBIKEY *dev, int report_type, int report_number, **
|
||||
** char *buffer, int size) **
|
||||
** **
|
||||
** Where: **
|
||||
** "dev" is handle to open Yubikey **
|
||||
** "report_type" is HID report type (in, out or feature) **
|
||||
** "report_number" is report identifier **
|
||||
** "buffer" is pointer to in buffer **
|
||||
** "size" is size of the buffer **
|
||||
** **
|
||||
** Returns: Number of bytes read. Zero if failure **
|
||||
** **
|
||||
*************************************************************************/
|
||||
|
||||
int _ykusb_read(void *dev, int report_type, int report_number,
|
||||
char *buffer, int size)
|
||||
{
|
||||
ykl_errno = libusb_claim_interface((libusb_device_handle *)dev, 0);
|
||||
|
||||
if (ykl_errno == 0) {
|
||||
int rc2;
|
||||
ykl_errno = libusb_control_transfer((libusb_device_handle *)dev,
|
||||
LIBUSB_REQUEST_TYPE_CLASS |
|
||||
LIBUSB_RECIPIENT_INTERFACE |
|
||||
LIBUSB_ENDPOINT_IN,
|
||||
HID_GET_REPORT,
|
||||
report_type << 8 | report_number, 0,
|
||||
(unsigned char *)buffer, size,
|
||||
1000);
|
||||
/* preserve a control message error over an interface
|
||||
release one */
|
||||
rc2 = libusb_release_interface((libusb_device_handle *)dev, 0);
|
||||
if (ykl_errno > 0 && rc2 < 0)
|
||||
ykl_errno = rc2;
|
||||
}
|
||||
if (ykl_errno > 0) {
|
||||
return ykl_errno;
|
||||
} else if(ykl_errno == 0) {
|
||||
yk_errno = YK_ENODATA;
|
||||
} else {
|
||||
yk_errno = YK_EUSBERR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _ykusb_start(void)
|
||||
{
|
||||
ykl_errno = libusb_init(&usb_ctx);
|
||||
if(ykl_errno) {
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
libusb_inited = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern int _ykusb_stop(void)
|
||||
{
|
||||
if (libusb_inited == 1) {
|
||||
libusb_exit(usb_ctx);
|
||||
usb_ctx = NULL;
|
||||
libusb_inited = 0;
|
||||
return 1;
|
||||
}
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *_ykusb_open_device(int vendor_id, const int *product_ids, size_t pids_len, int index)
|
||||
{
|
||||
libusb_device *dev = NULL;
|
||||
libusb_device_handle *h = NULL;
|
||||
struct libusb_device_descriptor desc;
|
||||
libusb_device **list;
|
||||
ssize_t cnt = libusb_get_device_list(usb_ctx, &list);
|
||||
ssize_t i = 0;
|
||||
int rc = YK_ENOKEY;
|
||||
const int desired_cfg = 1;
|
||||
int found = 0;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
ykl_errno = libusb_get_device_descriptor(list[i], &desc);
|
||||
if (ykl_errno != 0)
|
||||
goto done;
|
||||
|
||||
if (desc.idVendor == vendor_id) {
|
||||
size_t j;
|
||||
for(j = 0; j < pids_len; j++) {
|
||||
if (desc.idProduct == product_ids[j]) {
|
||||
found++;
|
||||
if (found-1 == index) {
|
||||
dev = list[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
int current_cfg;
|
||||
rc = YK_EUSBERR;
|
||||
ykl_errno = libusb_open(dev, &h);
|
||||
if (ykl_errno != 0)
|
||||
goto done;
|
||||
ykl_errno = libusb_kernel_driver_active(h, 0);
|
||||
if (ykl_errno == 1) {
|
||||
ykl_errno = libusb_detach_kernel_driver(h, 0);
|
||||
if (ykl_errno != 0)
|
||||
goto done;
|
||||
} else if (ykl_errno != 0)
|
||||
goto done;
|
||||
/* This is needed for yubikey-personalization to work inside virtualbox virtualization. */
|
||||
ykl_errno = libusb_get_configuration(h, ¤t_cfg);
|
||||
if (ykl_errno != 0)
|
||||
goto done;
|
||||
if (desired_cfg != current_cfg) {
|
||||
ykl_errno = libusb_set_configuration(h, desired_cfg);
|
||||
if (ykl_errno != 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
done:
|
||||
libusb_free_device_list(list, 1);
|
||||
if (h == NULL)
|
||||
yk_errno = rc;
|
||||
return h;
|
||||
}
|
||||
|
||||
int _ykusb_close_device(void *yk)
|
||||
{
|
||||
libusb_attach_kernel_driver(yk, 0);
|
||||
libusb_close((libusb_device_handle *) yk);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _ykusb_get_vid_pid(void *yk, int *vid, int *pid)
|
||||
{
|
||||
struct libusb_device_descriptor desc;
|
||||
libusb_device *dev = libusb_get_device(yk);
|
||||
int rc = libusb_get_device_descriptor(dev, &desc);
|
||||
|
||||
if (rc == 0) {
|
||||
*vid = desc.idVendor;
|
||||
*pid = desc.idProduct;
|
||||
return 1;
|
||||
}
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *_ykusb_strerror(void)
|
||||
{
|
||||
static const char *buf;
|
||||
switch (ykl_errno) {
|
||||
case LIBUSB_SUCCESS:
|
||||
buf = "Success (no error)";
|
||||
break;
|
||||
case LIBUSB_ERROR_IO:
|
||||
buf = "Input/output error";
|
||||
break;
|
||||
case LIBUSB_ERROR_INVALID_PARAM:
|
||||
buf = "Invalid parameter";
|
||||
break;
|
||||
case LIBUSB_ERROR_ACCESS:
|
||||
buf = "Access denied (insufficient permissions)";
|
||||
break;
|
||||
case LIBUSB_ERROR_NO_DEVICE:
|
||||
buf = "No such device (it may have been disconnected)";
|
||||
break;
|
||||
case LIBUSB_ERROR_NOT_FOUND:
|
||||
buf = "Entity not found";
|
||||
break;
|
||||
case LIBUSB_ERROR_BUSY:
|
||||
buf = "Resource busy";
|
||||
break;
|
||||
case LIBUSB_ERROR_TIMEOUT:
|
||||
buf = "Operation timed out";
|
||||
break;
|
||||
case LIBUSB_ERROR_OVERFLOW:
|
||||
buf = "Overflow";
|
||||
break;
|
||||
case LIBUSB_ERROR_PIPE:
|
||||
buf = "Pipe error";
|
||||
break;
|
||||
case LIBUSB_ERROR_INTERRUPTED:
|
||||
buf = "System call interrupted (perhaps due to signal)";
|
||||
break;
|
||||
case LIBUSB_ERROR_NO_MEM:
|
||||
buf = "Insufficient memory";
|
||||
break;
|
||||
case LIBUSB_ERROR_NOT_SUPPORTED:
|
||||
buf = "Operation not supported or unimplemented on this platform";
|
||||
break;
|
||||
case LIBUSB_ERROR_OTHER:
|
||||
default:
|
||||
buf = "Other/unknown error";
|
||||
break;
|
||||
}
|
||||
return buf;
|
||||
}
|
216
src/thirdparty/ykcore/ykcore_libusb.c
vendored
Normal file
216
src/thirdparty/ykcore/ykcore_libusb.c
vendored
Normal file
@ -0,0 +1,216 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#include <usb.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ykcore.h"
|
||||
#include "ykdef.h"
|
||||
#include "ykcore_backend.h"
|
||||
|
||||
#define HID_GET_REPORT 0x01
|
||||
#define HID_SET_REPORT 0x09
|
||||
|
||||
/*************************************************************************
|
||||
** function _ykusb_write **
|
||||
** Set HID report **
|
||||
** **
|
||||
** int _ykusb_write(YUBIKEY *yk, int report_type, int report_number, **
|
||||
** char *buffer, int size) **
|
||||
** **
|
||||
** Where: **
|
||||
** "yk" is handle to open Yubikey **
|
||||
** "report_type" is HID report type (in, out or feature) **
|
||||
** "report_number" is report identifier **
|
||||
** "buffer" is pointer to in buffer **
|
||||
** "size" is size of the buffer **
|
||||
** **
|
||||
** Returns: Nonzero if successful, zero otherwise **
|
||||
** **
|
||||
*************************************************************************/
|
||||
|
||||
int _ykusb_write(void *dev, int report_type, int report_number,
|
||||
char *buffer, int size)
|
||||
{
|
||||
int rc = usb_claim_interface((usb_dev_handle *)dev, 0);
|
||||
|
||||
if (rc >= 0) {
|
||||
int rc2;
|
||||
rc = usb_control_msg((usb_dev_handle *)dev,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_OUT,
|
||||
HID_SET_REPORT,
|
||||
report_type << 8 | report_number, 0,
|
||||
buffer, size,
|
||||
1000);
|
||||
/* preserve a control message error over an interface
|
||||
release one */
|
||||
rc2 = usb_release_interface((usb_dev_handle *)dev, 0);
|
||||
if (rc >= 0 && rc2 < 0)
|
||||
rc = rc2;
|
||||
}
|
||||
if (rc >= 0)
|
||||
return 1;
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
** function _ykusb_read **
|
||||
** Get HID report **
|
||||
** **
|
||||
** int _ykusb_read(YUBIKEY *dev, int report_type, int report_number, **
|
||||
** char *buffer, int size) **
|
||||
** **
|
||||
** Where: **
|
||||
** "dev" is handle to open Yubikey **
|
||||
** "report_type" is HID report type (in, out or feature) **
|
||||
** "report_number" is report identifier **
|
||||
** "buffer" is pointer to in buffer **
|
||||
** "size" is size of the buffer **
|
||||
** **
|
||||
** Returns: Number of bytes read. Zero if failure **
|
||||
** **
|
||||
*************************************************************************/
|
||||
|
||||
int _ykusb_read(void *dev, int report_type, int report_number,
|
||||
char *buffer, int size)
|
||||
{
|
||||
int rc = usb_claim_interface((usb_dev_handle *)dev, 0);
|
||||
|
||||
if (rc >= 0) {
|
||||
int rc2;
|
||||
rc = usb_control_msg((usb_dev_handle *)dev,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_ENDPOINT_IN,
|
||||
HID_GET_REPORT,
|
||||
report_type << 8 | report_number, 0,
|
||||
buffer, size,
|
||||
1000);
|
||||
/* preserve a control message error over an interface
|
||||
release one */
|
||||
rc2 = usb_release_interface((usb_dev_handle *)dev, 0);
|
||||
if (rc >= 0 && rc2 < 0)
|
||||
rc = rc2;
|
||||
}
|
||||
if (rc >= 0)
|
||||
return rc;
|
||||
if(rc == 0)
|
||||
yk_errno = YK_ENODATA;
|
||||
else
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _ykusb_start(void)
|
||||
{
|
||||
int rc;
|
||||
usb_init();
|
||||
|
||||
rc = usb_find_busses();
|
||||
if (rc >= 0)
|
||||
rc = usb_find_devices();
|
||||
|
||||
if (rc >= 0)
|
||||
return 1;
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int _ykusb_stop(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *_ykusb_open_device(int vendor_id, const int *product_ids, size_t pids_len, int index)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *yk_device = NULL;
|
||||
struct usb_dev_handle *h = NULL;
|
||||
int rc = YK_EUSBERR;
|
||||
int found = 0;
|
||||
|
||||
for (bus = usb_get_busses(); bus; bus = bus->next) {
|
||||
struct usb_device *dev;
|
||||
rc = YK_ENOKEY;
|
||||
for (dev = bus->devices; dev; dev = dev->next) {
|
||||
if (dev->descriptor.idVendor == vendor_id) {
|
||||
size_t j;
|
||||
for (j = 0; j < pids_len; j++) {
|
||||
if (dev->descriptor.idProduct == product_ids[j]) {
|
||||
found++;
|
||||
if (found-1 == index) {
|
||||
yk_device = dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(yk_device != NULL) {
|
||||
rc = YK_EUSBERR;
|
||||
h = usb_open(yk_device);
|
||||
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
|
||||
if (h != NULL)
|
||||
usb_detach_kernel_driver_np(h, 0);
|
||||
#endif
|
||||
/* This is needed for yubikey-personalization to work inside virtualbox virtualization. */
|
||||
if (h != NULL)
|
||||
usb_set_configuration(h, 1);
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
if (h == NULL)
|
||||
yk_errno = rc;
|
||||
return h;
|
||||
}
|
||||
|
||||
int _ykusb_close_device(void *yk)
|
||||
{
|
||||
int rc = usb_close((usb_dev_handle *) yk);
|
||||
|
||||
if (rc >= 0)
|
||||
return 1;
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _ykusb_get_vid_pid(void *yk, int *vid, int *pid) {
|
||||
struct usb_dev_handle *h = yk;
|
||||
struct usb_device *dev = usb_device(h);
|
||||
*vid = dev->descriptor.idVendor;
|
||||
*pid = dev->descriptor.idProduct;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *_ykusb_strerror(void)
|
||||
{
|
||||
return usb_strerror();
|
||||
}
|
280
src/thirdparty/ykcore/ykcore_osx.c
vendored
Normal file
280
src/thirdparty/ykcore/ykcore_osx.c
vendored
Normal file
@ -0,0 +1,280 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Yubico AB
|
||||
* Copyright (c) 2009 Christer Kaivo-oja <christer.kaivooja@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#include "ykcore.h"
|
||||
#include "ykdef.h"
|
||||
#include "ykcore_backend.h"
|
||||
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/hid/IOHIDKeys.h>
|
||||
#include <IOKit/hid/IOHIDUsageTables.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include "ykcore_backend.h"
|
||||
|
||||
#define FEATURE_RPT_SIZE 8
|
||||
#define FIDO_HID_USAGE_PAGE 0xF1D0
|
||||
#define FIDO_U2F_DEVICE_USAGE 0x01
|
||||
|
||||
static IOHIDManagerRef ykosxManager = NULL;
|
||||
static IOReturn _ykusb_IOReturn = 0;
|
||||
|
||||
int _ykusb_start(void)
|
||||
{
|
||||
ykosxManager = IOHIDManagerCreate( kCFAllocatorDefault, 0L );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _ykusb_stop(void)
|
||||
{
|
||||
if (ykosxManager != NULL) {
|
||||
CFRelease(ykosxManager);
|
||||
ykosxManager = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _ykosx_CopyToCFArray(const void *value, void *context)
|
||||
{
|
||||
CFArrayAppendValue( ( CFMutableArrayRef ) context, value );
|
||||
}
|
||||
|
||||
static int _ykosx_getIntProperty( IOHIDDeviceRef dev, CFStringRef key )
|
||||
{
|
||||
int result = 0;
|
||||
CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty( dev, key );
|
||||
if ( tCFTypeRef ) {
|
||||
if ( CFNumberGetTypeID( ) == CFGetTypeID( tCFTypeRef ) ) {
|
||||
CFNumberGetValue( ( CFNumberRef ) tCFTypeRef, kCFNumberSInt32Type, &result );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static IOHIDDeviceRef _ykosx_getHIDDeviceMatching(CFArrayRef devices,
|
||||
int primaryUsagePage,
|
||||
int primaryUsage,
|
||||
const int *productIDs,
|
||||
size_t productIDsCount,
|
||||
int index)
|
||||
{
|
||||
IOHIDDeviceRef matchingDevice = NULL;
|
||||
size_t cnt, i, j;
|
||||
int found = 0;
|
||||
|
||||
cnt = CFArrayGetCount( devices );
|
||||
|
||||
for(i = 0; i < cnt; ++i) {
|
||||
IOHIDDeviceRef dev = (IOHIDDeviceRef)CFArrayGetValueAtIndex( devices, i );
|
||||
const int usagePage = _ykosx_getIntProperty( dev, CFSTR( kIOHIDPrimaryUsagePageKey ));
|
||||
const int usage = _ykosx_getIntProperty( dev, CFSTR( kIOHIDPrimaryUsageKey ));
|
||||
const int devProductId = _ykosx_getIntProperty( dev, CFSTR( kIOHIDProductIDKey ));
|
||||
|
||||
if (usagePage != primaryUsagePage || usage != primaryUsage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(j = 0; j < productIDsCount; j++) {
|
||||
if(productIDs[j] == devProductId) {
|
||||
found++;
|
||||
if(found - 1 == index) {
|
||||
matchingDevice = dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matchingDevice;
|
||||
}
|
||||
|
||||
void *_ykusb_open_device(int vendor_id, const int *product_ids, size_t pids_len, int index)
|
||||
{
|
||||
IOHIDDeviceRef yk = NULL;
|
||||
|
||||
int rc = YK_ENOKEY;
|
||||
|
||||
IOHIDManagerSetDeviceMatchingMultiple( ykosxManager, NULL );
|
||||
|
||||
CFSetRef devSet = IOHIDManagerCopyDevices( ykosxManager );
|
||||
|
||||
if ( devSet ) {
|
||||
CFMutableArrayRef array = CFArrayCreateMutable( kCFAllocatorDefault, 0, NULL );
|
||||
|
||||
CFSetApplyFunction( devSet, _ykosx_CopyToCFArray, array );
|
||||
|
||||
/* ensure that we are attempting to open the FIDO interface instead
|
||||
of the keyboard interface. macOS requires explicit user
|
||||
authorization before we are able to open HID devices such as
|
||||
keyboards and mice, while it is not required for FIDO devices
|
||||
that communicate over HID. */
|
||||
yk = _ykosx_getHIDDeviceMatching(
|
||||
array, // devices
|
||||
FIDO_HID_USAGE_PAGE, // primaryUsagePage
|
||||
FIDO_U2F_DEVICE_USAGE, // primaryUsage
|
||||
product_ids, // productIDs
|
||||
pids_len, // productIDsCount
|
||||
index // index
|
||||
);
|
||||
|
||||
if(yk == NULL) {
|
||||
/* fallback to the keyboard device if it is present. */
|
||||
yk = _ykosx_getHIDDeviceMatching(
|
||||
array, // devices
|
||||
kHIDPage_GenericDesktop, // primaryUsagePage
|
||||
kHIDUsage_GD_Keyboard, // primaryUsage
|
||||
product_ids, // productIDs
|
||||
pids_len, // productIDsCount
|
||||
index // index
|
||||
);
|
||||
}
|
||||
|
||||
/* this is a workaround for a memory leak in IOHIDManagerCopyDevices() in 10.8 */
|
||||
IOHIDManagerScheduleWithRunLoop( ykosxManager, CFRunLoopGetCurrent( ), kCFRunLoopDefaultMode );
|
||||
IOHIDManagerUnscheduleFromRunLoop( ykosxManager, CFRunLoopGetCurrent( ), kCFRunLoopDefaultMode );
|
||||
|
||||
CFRelease( array );
|
||||
CFRelease( devSet );
|
||||
}
|
||||
|
||||
if (yk) {
|
||||
CFRetain(yk);
|
||||
_ykusb_IOReturn = IOHIDDeviceOpen( yk, 0L );
|
||||
|
||||
if ( _ykusb_IOReturn != kIOReturnSuccess ) {
|
||||
CFRelease(yk);
|
||||
rc = YK_EUSBERR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return (void *)yk;
|
||||
}
|
||||
|
||||
error:
|
||||
yk_errno = rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _ykusb_close_device(void *dev)
|
||||
{
|
||||
_ykusb_IOReturn = IOHIDDeviceClose( dev, 0L );
|
||||
CFRelease(dev);
|
||||
|
||||
if ( _ykusb_IOReturn == kIOReturnSuccess )
|
||||
return 1;
|
||||
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _ykusb_read(void *dev, int report_type, int report_number,
|
||||
char *buffer, int size)
|
||||
{
|
||||
CFIndex sizecf = (CFIndex)size;
|
||||
|
||||
if (report_type != REPORT_TYPE_FEATURE)
|
||||
{
|
||||
yk_errno = YK_ENOTYETIMPL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ykusb_IOReturn = IOHIDDeviceGetReport( dev, kIOHIDReportTypeFeature, report_number, (uint8_t *)buffer, (CFIndex *) &sizecf );
|
||||
|
||||
if ( _ykusb_IOReturn != kIOReturnSuccess )
|
||||
{
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sizecf == 0)
|
||||
yk_errno = YK_ENODATA;
|
||||
|
||||
return (int)sizecf;
|
||||
}
|
||||
|
||||
int _ykusb_write(void *dev, int report_type, int report_number,
|
||||
char *buffer, int size)
|
||||
{
|
||||
if (report_type != REPORT_TYPE_FEATURE)
|
||||
{
|
||||
yk_errno = YK_ENOTYETIMPL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ykusb_IOReturn = IOHIDDeviceSetReport( dev, kIOHIDReportTypeFeature, report_number, (unsigned char *)buffer, size);
|
||||
|
||||
if ( _ykusb_IOReturn != kIOReturnSuccess )
|
||||
{
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _ykusb_get_vid_pid(void *yk, int *vid, int *pid) {
|
||||
IOHIDDeviceRef dev = (IOHIDDeviceRef)yk;
|
||||
*vid = _ykosx_getIntProperty( dev, CFSTR( kIOHIDVendorIDKey ));
|
||||
*pid = _ykosx_getIntProperty( dev, CFSTR( kIOHIDProductIDKey ));
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *_ykusb_strerror()
|
||||
{
|
||||
switch (_ykusb_IOReturn) {
|
||||
case kIOReturnSuccess:
|
||||
return "kIOReturnSuccess";
|
||||
case kIOReturnNotOpen:
|
||||
return "kIOReturnNotOpen";
|
||||
case kIOReturnNoDevice:
|
||||
return "kIOReturnNoDevice";
|
||||
case kIOReturnExclusiveAccess:
|
||||
return "kIOReturnExclusiveAccess";
|
||||
case kIOReturnError:
|
||||
return "kIOReturnError";
|
||||
case kIOReturnBadArgument:
|
||||
return "kIOReturnBadArgument";
|
||||
case kIOReturnAborted:
|
||||
return "kIOReturnAborted";
|
||||
case kIOReturnNotResponding:
|
||||
return "kIOReturnNotResponding";
|
||||
case kIOReturnOverrun:
|
||||
return "kIOReturnOverrun";
|
||||
case kIOReturnCannotWire:
|
||||
return "kIOReturnCannotWire";
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
}
|
210
src/thirdparty/ykcore/ykcore_windows.c
vendored
Normal file
210
src/thirdparty/ykcore/ykcore_windows.c
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#include "ykcore.h"
|
||||
#include "ykdef.h"
|
||||
#include "ykcore_backend.h"
|
||||
|
||||
#define INITGUID
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <ntddkbd.h>
|
||||
#include <hidsdi.h>
|
||||
|
||||
int _ykusb_start(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _ykusb_stop(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void * _ykusb_open_device(int vendor_id, const int *product_ids, size_t pids_len, int index)
|
||||
{
|
||||
HDEVINFO hi;
|
||||
SP_DEVICE_INTERFACE_DATA di;
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA pi;
|
||||
int i;
|
||||
DWORD len, rc;
|
||||
HANDLE ret_handle = NULL;
|
||||
int found = 0;
|
||||
|
||||
yk_errno = YK_EUSBERR;
|
||||
|
||||
hi = SetupDiGetClassDevs(&GUID_DEVINTERFACE_KEYBOARD, 0, 0,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if (hi == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
di.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
if (!SetupDiEnumDeviceInterfaces(hi, 0, &GUID_DEVINTERFACE_KEYBOARD, i, &di))
|
||||
break;
|
||||
|
||||
if (SetupDiGetDeviceInterfaceDetail(hi, &di, 0, 0, &len, 0) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
break;
|
||||
|
||||
pi = malloc (len);
|
||||
if (!pi) {
|
||||
yk_errno = YK_ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
pi->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
|
||||
rc = SetupDiGetDeviceInterfaceDetail(hi, &di, pi, len, &len, 0);
|
||||
if (rc) {
|
||||
HANDLE m_handle;
|
||||
|
||||
m_handle = CreateFile(pi->DevicePath, GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (m_handle != INVALID_HANDLE_VALUE) {
|
||||
HIDD_ATTRIBUTES devInfo;
|
||||
|
||||
if (HidD_GetAttributes(m_handle, &devInfo)) {
|
||||
if (devInfo.VendorID == vendor_id) {
|
||||
size_t j;
|
||||
for (j = 0; j < pids_len; j++) {
|
||||
if (devInfo.ProductID == product_ids[j]) {
|
||||
found++;
|
||||
if (found-1 == index) {
|
||||
ret_handle = m_handle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ret_handle == NULL) {
|
||||
CloseHandle (m_handle);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (pi);
|
||||
}
|
||||
if(ret_handle != NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
yk_errno = YK_ENOKEY;
|
||||
|
||||
done:
|
||||
SetupDiDestroyDeviceInfoList(hi);
|
||||
return ret_handle;
|
||||
}
|
||||
|
||||
int _ykusb_close_device(void *yk)
|
||||
{
|
||||
HANDLE h = yk;
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define EXPECT_SIZE 8
|
||||
#define FEATURE_BUF_SIZE 9
|
||||
|
||||
int _ykusb_read(void *dev, int report_type, int report_number,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
(void)report_type;
|
||||
(void)report_number;
|
||||
|
||||
HANDLE h = dev;
|
||||
BYTE buf[FEATURE_BUF_SIZE];
|
||||
|
||||
if (buffer_size != EXPECT_SIZE) {
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (!HidD_GetFeature(h, buf, sizeof (buf))) {
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy (buffer, buf + 1, buffer_size);
|
||||
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
int _ykusb_write(void *dev, int report_type, int report_number,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
(void)report_type;
|
||||
(void)report_number;
|
||||
|
||||
HANDLE h = dev;
|
||||
BYTE buf[FEATURE_BUF_SIZE];
|
||||
|
||||
if (buffer_size != EXPECT_SIZE) {
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
memcpy (buf + 1, buffer, buffer_size);
|
||||
|
||||
if (!HidD_SetFeature(h, buf, sizeof (buf))) {
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _ykusb_get_vid_pid(void *yk, int *vid, int *pid) {
|
||||
HIDD_ATTRIBUTES devInfo;
|
||||
int rc = HidD_GetAttributes(yk, &devInfo);
|
||||
if (rc) {
|
||||
*vid = devInfo.VendorID;
|
||||
*pid = devInfo.ProductID;
|
||||
return 1;
|
||||
}
|
||||
yk_errno = YK_EUSBERR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *_ykusb_strerror(void)
|
||||
{
|
||||
static char buf[1024];
|
||||
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
|
||||
buf, sizeof(buf), NULL);
|
||||
return buf;
|
||||
}
|
54
src/thirdparty/ykcore/ykcrc.c
vendored
Normal file
54
src/thirdparty/ykcore/ykcrc.c
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
/* ykcrc.c --- Implementation of YubiKey CRC-16 function.
|
||||
*
|
||||
* Written by Simon Josefsson <simon@josefsson.org>.
|
||||
* Copyright (c) 2006-2012 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "yubikey.h"
|
||||
|
||||
uint16_t
|
||||
yubikey_crc16 (const uint8_t * buf, size_t buf_size)
|
||||
{
|
||||
uint16_t m_crc = 0xffff;
|
||||
|
||||
while (buf_size--)
|
||||
{
|
||||
int i, j;
|
||||
m_crc ^= (uint8_t) * buf++ & 0xFF;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
j = m_crc & 1;
|
||||
m_crc >>= 1;
|
||||
if (j)
|
||||
m_crc ^= 0x8408;
|
||||
}
|
||||
}
|
||||
|
||||
return m_crc;
|
||||
}
|
310
src/thirdparty/ykcore/ykdef.h
vendored
Normal file
310
src/thirdparty/ykcore/ykdef.h
vendored
Normal file
@ -0,0 +1,310 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*****************************************************************************************
|
||||
** **
|
||||
** Y K D E F - Common Yubikey project header **
|
||||
** **
|
||||
** Date / Rev / Sign / Remark **
|
||||
** 06-06-03 / 0.9.0 / J E / Main **
|
||||
** 06-08-25 / 1.0.0 / J E / Rewritten for final spec **
|
||||
** 08-06-03 / 1.3.0 / J E / Added static OTP feature **
|
||||
** 09-06-02 / 2.0.0 / J E / Added version 2 flags **
|
||||
** 09-09-23 / 2.1.0 / J E / Added version 2.1 flags (OATH-HOTP) **
|
||||
** 10-05-01 / 2.2.0 / J E / Added support for 2.2 ext. + frame **
|
||||
** 11-04-15 / 2.3.0 / J E / Added support for 2.3 extensions **
|
||||
** 11-12-05 / 2.4.0 / J E / Added support for NFC and NDEF **
|
||||
** 12-10-28 / 3.0.0 / J E / NEO changes **
|
||||
** 13-03-05 / 3.1.0 / J E / Added EXTFLAG_LED_INV flag **
|
||||
** 13-03-06 / 3.1.0 / J E / Added NEO startup busy flag **
|
||||
** 14-06-13 / 3.3.0 / J E / Added U2F mode modifiers **
|
||||
** 14-11-20 / 4.0.0 / J E / Updated with Yubikey 4 PIDs **
|
||||
** 15-03-27 / 4.1.0 / K L / Added YK4 Capabilities **
|
||||
** 15-06-23 / 4.2.0 / K L / Added more YK4 Capabilities **
|
||||
** **
|
||||
*****************************************************************************************/
|
||||
|
||||
#ifndef __YKDEF_H_INCLUDED__
|
||||
#define __YKDEF_H_INCLUDED__
|
||||
|
||||
/* We need the structures defined here to be packed byte-wise */
|
||||
#if defined(_WIN32) || defined(__GNUC__)
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
|
||||
/* Slot entries */
|
||||
|
||||
#define SLOT_CONFIG 1 /* First (default / V1) configuration */
|
||||
#define SLOT_NAV 2 /* V1 only */
|
||||
#define SLOT_CONFIG2 3 /* Second (V2) configuration */
|
||||
#define SLOT_UPDATE1 4 /* Update slot 1 */
|
||||
#define SLOT_UPDATE2 5 /* Update slot 2 */
|
||||
#define SLOT_SWAP 6 /* Swap slot 1 and 2 */
|
||||
#define SLOT_NDEF 8 /* Write NDEF record */
|
||||
#define SLOT_NDEF2 9 /* Write NDEF record for slot 2 */
|
||||
|
||||
#define SLOT_DEVICE_SERIAL 0x10 /* Device serial number */
|
||||
#define SLOT_DEVICE_CONFIG 0x11 /* Write device configuration record */
|
||||
#define SLOT_SCAN_MAP 0x12 /* Write scancode map */
|
||||
#define SLOT_YK4_CAPABILITIES 0x13 /* Read YK4 capabilities (device info) list */
|
||||
#define SLOT_YK4_SET_DEVICE_INFO 0x15 /* Write device info */
|
||||
|
||||
#define SLOT_CHAL_OTP1 0x20 /* Write 6 byte challenge to slot 1, get Yubico OTP response */
|
||||
#define SLOT_CHAL_OTP2 0x28 /* Write 6 byte challenge to slot 2, get Yubico OTP response */
|
||||
|
||||
#define SLOT_CHAL_HMAC1 0x30 /* Write 64 byte challenge to slot 1, get HMAC-SHA1 response */
|
||||
#define SLOT_CHAL_HMAC2 0x38 /* Write 64 byte challenge to slot 2, get HMAC-SHA1 response */
|
||||
|
||||
#define RESP_ITEM_MASK 0x07 /* Mask for slice item # in responses */
|
||||
|
||||
#define RESP_TIMEOUT_WAIT_MASK 0x1f /* Mask to get timeout value */
|
||||
#define RESP_TIMEOUT_WAIT_FLAG 0x20 /* Waiting for timeout operation - seconds left in lower 5 bits */
|
||||
#define RESP_PENDING_FLAG 0x40 /* Response pending flag */
|
||||
#define SLOT_WRITE_FLAG 0x80 /* Write flag - set by app - cleared by device */
|
||||
|
||||
#define DUMMY_REPORT_WRITE 0x8f /* Write a dummy report to force update or abort */
|
||||
#define NEO_STARTUP_BUSY 0x9f /* Status during startup (writes blocked) */
|
||||
|
||||
#define SHA1_MAX_BLOCK_SIZE 64 /* Max size of input SHA1 block */
|
||||
#define SHA1_DIGEST_SIZE 20 /* Size of SHA1 digest = 160 bits */
|
||||
|
||||
#define SERIAL_NUMBER_SIZE 4 /* Size of device serial number */
|
||||
|
||||
/* Frame structure */
|
||||
|
||||
#define SLOT_DATA_SIZE 64
|
||||
|
||||
struct frame_st {
|
||||
unsigned char payload[SLOT_DATA_SIZE]; /* Frame payload */
|
||||
unsigned char slot; /* Slot # field */
|
||||
unsigned short crc; /* CRC field */
|
||||
unsigned char filler[3]; /* Filler */
|
||||
};
|
||||
|
||||
/* Ticket structure */
|
||||
|
||||
#define UID_SIZE 6 /* Size of secret ID field */
|
||||
|
||||
struct ticket_st {
|
||||
unsigned char uid[UID_SIZE]; /* Unique (secret) ID */
|
||||
unsigned short useCtr; /* Use counter (incremented by 1 at first use after power up) + usage flag in msb */
|
||||
unsigned short tstpl; /* Timestamp incremented by approx 8Hz (low part) */
|
||||
unsigned char tstph; /* Timestamp (high part) */
|
||||
unsigned char sessionCtr; /* Number of times used within session. 0 for first use. After it wraps from 0xff to 1 */
|
||||
unsigned short rnd; /* Pseudo-random value */
|
||||
unsigned short crc; /* CRC16 value of all fields */
|
||||
};
|
||||
|
||||
/* Activation modifier of sessionUse field (bitfields not uses as they are not portable) */
|
||||
|
||||
#define TICKET_ACT_HIDRPT 0x8000 /* Ticket generated at activation by keyboard (scroll/num/caps) */
|
||||
#define TICKET_CTR_MASK 0x7fff /* Mask for useCtr value (except HID flag) */
|
||||
|
||||
/* Configuration structure */
|
||||
|
||||
#define FIXED_SIZE 16 /* Max size of fixed field */
|
||||
#define KEY_SIZE 16 /* Size of AES key */
|
||||
#define KEY_SIZE_OATH 20 /* Size of OATH-HOTP key (key field + first 4 of UID field) */
|
||||
#define ACC_CODE_SIZE 6 /* Size of access code to re-program device */
|
||||
|
||||
struct config_st {
|
||||
unsigned char fixed[FIXED_SIZE];/* Fixed data in binary format */
|
||||
unsigned char uid[UID_SIZE]; /* Fixed UID part of ticket */
|
||||
unsigned char key[KEY_SIZE]; /* AES key */
|
||||
unsigned char accCode[ACC_CODE_SIZE]; /* Access code to re-program device */
|
||||
unsigned char fixedSize; /* Number of bytes in fixed field (0 if not used) */
|
||||
unsigned char extFlags; /* Extended flags - YubiKey 2.? and above */
|
||||
unsigned char tktFlags; /* Ticket configuration flags */
|
||||
unsigned char cfgFlags; /* General configuration flags */
|
||||
unsigned char rfu[2]; /* Reserved for future use */
|
||||
unsigned short crc; /* CRC16 value of all fields */
|
||||
};
|
||||
|
||||
/* Ticket flags **************************************************************/
|
||||
|
||||
/* Yubikey 1 and above */
|
||||
#define TKTFLAG_TAB_FIRST 0x01 /* Send TAB before first part */
|
||||
#define TKTFLAG_APPEND_TAB1 0x02 /* Send TAB after first part */
|
||||
#define TKTFLAG_APPEND_TAB2 0x04 /* Send TAB after second part */
|
||||
#define TKTFLAG_APPEND_DELAY1 0x08 /* Add 0.5s delay after first part */
|
||||
#define TKTFLAG_APPEND_DELAY2 0x10 /* Add 0.5s delay after second part */
|
||||
#define TKTFLAG_APPEND_CR 0x20 /* Append CR as final character */
|
||||
|
||||
/* Yubikey 2 and above */
|
||||
#define TKTFLAG_PROTECT_CFG2 0x80 /* Block update of config 2 unless config 2 is configured and has this bit set */
|
||||
|
||||
/* Configuration flags *******************************************************/
|
||||
|
||||
/* Yubikey 1 and above */
|
||||
#define CFGFLAG_SEND_REF 0x01 /* Send reference string (0..F) before data */
|
||||
#define CFGFLAG_PACING_10MS 0x04 /* Add 10ms intra-key pacing */
|
||||
#define CFGFLAG_PACING_20MS 0x08 /* Add 20ms intra-key pacing */
|
||||
#define CFGFLAG_STATIC_TICKET 0x20 /* Static ticket generation */
|
||||
|
||||
/* Yubikey 1 only */
|
||||
#define CFGFLAG_TICKET_FIRST 0x02 /* Send ticket first (default is fixed part) */
|
||||
#define CFGFLAG_ALLOW_HIDTRIG 0x10 /* Allow trigger through HID/keyboard */
|
||||
|
||||
/* Yubikey 2 and above */
|
||||
#define CFGFLAG_SHORT_TICKET 0x02 /* Send truncated ticket (half length) */
|
||||
#define CFGFLAG_STRONG_PW1 0x10 /* Strong password policy flag #1 (mixed case) */
|
||||
#define CFGFLAG_STRONG_PW2 0x40 /* Strong password policy flag #2 (subtitute 0..7 to digits) */
|
||||
#define CFGFLAG_MAN_UPDATE 0x80 /* Allow manual (local) update of static OTP */
|
||||
|
||||
/* Yubikey 2.1 and above */
|
||||
#define TKTFLAG_OATH_HOTP 0x40 /* OATH HOTP mode */
|
||||
#define CFGFLAG_OATH_HOTP8 0x02 /* Generate 8 digits HOTP rather than 6 digits */
|
||||
#define CFGFLAG_OATH_FIXED_MODHEX1 0x10 /* First byte in fixed part sent as modhex */
|
||||
#define CFGFLAG_OATH_FIXED_MODHEX2 0x40 /* First two bytes in fixed part sent as modhex */
|
||||
#define CFGFLAG_OATH_FIXED_MODHEX 0x50 /* Fixed part sent as modhex */
|
||||
#define CFGFLAG_OATH_FIXED_MASK 0x50 /* Mask to get out fixed flags */
|
||||
|
||||
/* Yubikey 2.2 and above */
|
||||
|
||||
#define TKTFLAG_CHAL_RESP 0x40 /* Challenge-response enabled (both must be set) */
|
||||
#define CFGFLAG_CHAL_YUBICO 0x20 /* Challenge-response enabled - Yubico OTP mode */
|
||||
#define CFGFLAG_CHAL_HMAC 0x22 /* Challenge-response enabled - HMAC-SHA1 */
|
||||
#define CFGFLAG_HMAC_LT64 0x04 /* Set when HMAC message is less than 64 bytes */
|
||||
#define CFGFLAG_CHAL_BTN_TRIG 0x08 /* Challenge-response operation requires button press */
|
||||
|
||||
#define EXTFLAG_SERIAL_BTN_VISIBLE 0x01 /* Serial number visible at startup (button press) */
|
||||
#define EXTFLAG_SERIAL_USB_VISIBLE 0x02 /* Serial number visible in USB iSerial field */
|
||||
#define EXTFLAG_SERIAL_API_VISIBLE 0x04 /* Serial number visible via API call */
|
||||
|
||||
/* V2.3 flags only */
|
||||
|
||||
#define EXTFLAG_USE_NUMERIC_KEYPAD 0x08 /* Use numeric keypad for digits */
|
||||
#define EXTFLAG_FAST_TRIG 0x10 /* Use fast trig if only cfg1 set */
|
||||
#define EXTFLAG_ALLOW_UPDATE 0x20 /* Allow update of existing configuration (selected flags + access code) */
|
||||
#define EXTFLAG_DORMANT 0x40 /* Dormant configuration (can be woken up and flag removed = requires update flag) */
|
||||
|
||||
/* V2.4/3.1 flags only */
|
||||
|
||||
#define EXTFLAG_LED_INV 0x80 /* LED idle state is off rather than on */
|
||||
|
||||
/* Flags valid for update */
|
||||
|
||||
#define TKTFLAG_UPDATE_MASK (TKTFLAG_TAB_FIRST | TKTFLAG_APPEND_TAB1 | TKTFLAG_APPEND_TAB2 | TKTFLAG_APPEND_DELAY1 | TKTFLAG_APPEND_DELAY2 | TKTFLAG_APPEND_CR)
|
||||
#define CFGFLAG_UPDATE_MASK (CFGFLAG_PACING_10MS | CFGFLAG_PACING_20MS)
|
||||
#define EXTFLAG_UPDATE_MASK (EXTFLAG_SERIAL_BTN_VISIBLE | EXTFLAG_SERIAL_USB_VISIBLE | EXTFLAG_SERIAL_API_VISIBLE | EXTFLAG_USE_NUMERIC_KEYPAD | EXTFLAG_FAST_TRIG | EXTFLAG_ALLOW_UPDATE | EXTFLAG_DORMANT | EXTFLAG_LED_INV)
|
||||
|
||||
/* NDEF structure */
|
||||
#define NDEF_DATA_SIZE 54
|
||||
|
||||
/* backwards compatibility with version 1.7.0 */
|
||||
typedef struct ndef_st YKNDEF;
|
||||
|
||||
struct ndef_st {
|
||||
unsigned char len; /* Payload length */
|
||||
unsigned char type; /* NDEF type specifier */
|
||||
unsigned char data[NDEF_DATA_SIZE]; /* Payload size */
|
||||
unsigned char curAccCode[ACC_CODE_SIZE]; /* Access code */
|
||||
};
|
||||
|
||||
|
||||
/* Navigation */
|
||||
|
||||
/* NOTE: Navigation isn't available since Yubikey 1.3.5 and is strongly
|
||||
discouraged. */
|
||||
#define MAX_URL 48
|
||||
|
||||
struct nav_st {
|
||||
unsigned char scancode[MAX_URL];/* Scancode (lower 7 bits) */
|
||||
unsigned char scanmod[MAX_URL >> 2]; /* Modifier fields (packed 2 bits each) */
|
||||
unsigned char flags; /* NAVFLAG_xxx flags */
|
||||
unsigned char filler; /* Filler byte */
|
||||
unsigned short crc; /* CRC16 value of all fields */
|
||||
};
|
||||
|
||||
#define SCANMOD_SHIFT 0x80 /* Highest bit in scancode */
|
||||
#define SCANMOD_ALT_GR 0x01 /* Lowest bit in mod */
|
||||
#define SCANMOD_WIN 0x02 /* WIN key */
|
||||
|
||||
/* Navigation flags */
|
||||
|
||||
#define NAVFLAG_INSERT_TRIG 0x01 /* Automatic trigger when device is inserted */
|
||||
#define NAVFLAG_APPEND_TKT 0x02 /* Append ticket to URL */
|
||||
#define NAVFLAG_DUAL_KEY_USAGE 0x04 /* Dual usage of key: Short = ticket Long = Navigate */
|
||||
|
||||
/* Device configuration block (version 3.0) */
|
||||
|
||||
struct device_config_st {
|
||||
unsigned char mode; /* Device mode */
|
||||
unsigned char crTimeout; /* Challenge-response timeout in seconds */
|
||||
unsigned short autoEjectTime; /* Auto eject time in x10 seconds */
|
||||
};
|
||||
|
||||
#define MODE_OTP 0x00 /* OTP only */
|
||||
#define MODE_CCID 0x01 /* CCID only, no eject */
|
||||
#define MODE_OTP_CCID 0x02 /* OTP + CCID composite */
|
||||
#define MODE_U2F 0x03 /* U2F mode */
|
||||
#define MODE_OTP_U2F 0x04 /* OTP + U2F composite */
|
||||
#define MODE_U2F_CCID 0x05 /* U2F + CCID composite */
|
||||
#define MODE_OTP_U2F_CCID 0x06 /* OTP + U2F + CCID composite */
|
||||
#define MODE_MASK 0x07 /* Mask for mode bits */
|
||||
|
||||
#define MODE_FLAG_EJECT 0x80 /* CCID device supports eject (mode 1 only) */
|
||||
|
||||
#define DEFAULT_CHAL_TIMEOUT 15 /* Default challenge timeout in seconds */
|
||||
|
||||
/* Scancode mapping (version 3.0) */
|
||||
|
||||
#define SCAN_MAP "cbdefghijklnrtuvCBDEFGHIJKLNRTUV0123456789!\t\r"
|
||||
#define SHIFT_FLAG 0x80 /* Flag for shifted scan codes */
|
||||
|
||||
/* Status block */
|
||||
|
||||
struct status_st {
|
||||
unsigned char versionMajor; /* Firmware version information */
|
||||
unsigned char versionMinor;
|
||||
unsigned char versionBuild;
|
||||
unsigned char pgmSeq; /* Programming sequence number. 0 if no valid configuration */
|
||||
unsigned short touchLevel; /* Level from touch detector */
|
||||
};
|
||||
|
||||
#define CONFIG1_VALID 0x01 /* Bit in touchLevel indicating that configuration 1 is valid (from firmware 2.1) */
|
||||
#define CONFIG2_VALID 0x02 /* Bit in touchLevel indicating that configuration 2 is valid (from firmware 2.1) */
|
||||
#define CONFIG1_TOUCH 0x04 /* Bit in touchLevel indicating that configuration 1 requires touch (from firmware 3.0) */
|
||||
#define CONFIG2_TOUCH 0x08 /* Bit in touchLevel indicating that configuration 2 requires touch (from firmware 3.0) */
|
||||
#define CONFIG_LED_INV 0x10 /* Bit in touchLevel indicating that LED behavior is inverted (EXTFLAG_LED_INV mirror) */
|
||||
#define CONFIG_STATUS_MASK 0x1f /* Mask for status bits */
|
||||
|
||||
/* Modified hex string mapping */
|
||||
|
||||
#define MODHEX_MAP "cbdefghijklnrtuv"
|
||||
|
||||
/* USB vendor ID (VID) and product ID (PID) mapping */
|
||||
|
||||
#define YUBICO_VID 0x1050 /* Global vendor ID */
|
||||
#define YUBIKEY_PID 0x0010 /* Yubikey (version 1 and 2) */
|
||||
#define NEO_OTP_PID 0x0110 /* Yubikey NEO - OTP only */
|
||||
#define NEO_OTP_CCID_PID 0x0111 /* Yubikey NEO - OTP and CCID */
|
||||
#define NEO_CCID_PID 0x0112 /* Yubikey NEO - CCID only */
|
||||
#define NEO_U2F_PID 0x0113 /* Yubikey NEO - U2F only */
|
||||
#define NEO_OTP_U2F_PID 0x0114 /* Yubikey NEO - OTP and U2F */
|
||||
#define NEO_U2F_CCID_PID 0x0115 /* Yubikey NEO - U2F and CCID */
|
||||
#define NEO_OTP_U2F_CCID_PID 0x0116 /* Yubikey NEO - OTP, U2F and CCID */
|
||||
|
||||
#define YK4_OTP_PID 0x0401 /* Yubikey 4 - OTP only */
|
||||
#define YK4_U2F_PID 0x0402 /* Yubikey 4 - U2F only */
|
||||
#define YK4_OTP_U2F_PID 0x0403 /* Yubikey 4 - OTP and U2F */
|
||||
#define YK4_CCID_PID 0x0404 /* Yubikey 4 - CCID only */
|
||||
#define YK4_OTP_CCID_PID 0x0405 /* Yubikey 4 - OTP and CCID */
|
||||
#define YK4_U2F_CCID_PID 0x0406 /* Yubikey 4 - U2F and CCID */
|
||||
#define YK4_OTP_U2F_CCID_PID 0x0407 /* Yubikey 4 - OTP, U2F and CCID */
|
||||
|
||||
#define PLUS_U2F_OTP_PID 0x0410 /* Yubikey plus - OTP+U2F */
|
||||
|
||||
#define YK4_CAPA_TAG 0x01 /* TAG for capabilities */
|
||||
#define YK4_SERIAL_TAG 0x02 /* TAG for serial number */
|
||||
|
||||
#define YK4_CAPA1_OTP 0x01 /* Capability bit for OTP functonality */
|
||||
#define YK4_CAPA1_U2F 0x02 /* Capability bit for U2F functionality */
|
||||
#define YK4_CAPA1_CCID 0x04 /* Capability bit for CCID functionality */
|
||||
#define YK4_CAPA1_OPGP 0x08 /* Capability bit for OpenPGP functionality */
|
||||
#define YK4_CAPA1_PIV 0x10 /* Capability bit for PIV functionality */
|
||||
#define YK4_CAPA1_OATH 0x20 /* Capability bit for OATH functionality */
|
||||
|
||||
#if defined(_WIN32) || defined(__GNUC__)
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
#endif /* __YKDEF_H_INCLUDED__ */
|
90
src/thirdparty/ykcore/ykstatus.c
vendored
Normal file
90
src/thirdparty/ykcore/ykstatus.c
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Written by Richard Levitte <richard@levitte.org>
|
||||
* Copyright (c) 2008-2012 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#include "ykcore_lcl.h"
|
||||
#include "ykdef.h"
|
||||
#include "ykstatus.h"
|
||||
|
||||
YK_STATUS *ykds_alloc(void)
|
||||
{
|
||||
YK_STATUS *st = malloc(sizeof(YK_STATUS));
|
||||
if (!st) {
|
||||
yk_errno = YK_ENOMEM;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
void ykds_free(YK_STATUS *st)
|
||||
{
|
||||
free(st);
|
||||
}
|
||||
|
||||
YK_STATUS *ykds_static(void)
|
||||
{
|
||||
static YK_STATUS st;
|
||||
return &st;
|
||||
}
|
||||
|
||||
extern int ykds_version_major(const YK_STATUS *st)
|
||||
{
|
||||
if (st)
|
||||
return st->versionMajor;
|
||||
yk_errno = YK_ENOSTATUS;
|
||||
return 0;
|
||||
}
|
||||
extern int ykds_version_minor(const YK_STATUS *st)
|
||||
{
|
||||
if (st)
|
||||
return st->versionMinor;
|
||||
yk_errno = YK_ENOSTATUS;
|
||||
return 0;
|
||||
}
|
||||
extern int ykds_version_build(const YK_STATUS *st)
|
||||
{
|
||||
if (st)
|
||||
return st->versionBuild;
|
||||
yk_errno = YK_ENOSTATUS;
|
||||
return 0;
|
||||
}
|
||||
extern int ykds_pgm_seq(const YK_STATUS *st)
|
||||
{
|
||||
if (st)
|
||||
return st->pgmSeq;
|
||||
yk_errno = YK_ENOSTATUS;
|
||||
return 0;
|
||||
}
|
||||
extern int ykds_touch_level(const YK_STATUS *st)
|
||||
{
|
||||
if (st)
|
||||
return st->touchLevel;
|
||||
yk_errno = YK_ENOSTATUS;
|
||||
return 0;
|
||||
}
|
60
src/thirdparty/ykcore/ykstatus.h
vendored
Normal file
60
src/thirdparty/ykcore/ykstatus.h
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- mode:C; c-file-style: "bsd" -*- */
|
||||
/*
|
||||
* Written by Richard Levitte <richard@levitte.org>
|
||||
* Copyright (c) 2008-2013 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef __YKSTATUS_H_INCLUDED__
|
||||
#define __YKSTATUS_H_INCLUDED__
|
||||
|
||||
#include "ykcore.h"
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/* Allocate and free status structures */
|
||||
extern YK_STATUS *ykds_alloc(void);
|
||||
extern void ykds_free(YK_STATUS *st);
|
||||
|
||||
/* Return static status structure, to be used for quick checks.
|
||||
USE WITH CAUTION, as this is a SHARED OBJECT. */
|
||||
extern YK_STATUS *ykds_static(void);
|
||||
|
||||
/* Accessor functions */
|
||||
extern int ykds_version_major(const YK_STATUS *st);
|
||||
extern int ykds_version_minor(const YK_STATUS *st);
|
||||
extern int ykds_version_build(const YK_STATUS *st);
|
||||
extern int ykds_pgm_seq(const YK_STATUS *st);
|
||||
extern int ykds_touch_level(const YK_STATUS *st);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif /* __YKSTATUS_H_INCLUDED__ */
|
61
src/thirdparty/ykcore/yktsd.h
vendored
Normal file
61
src/thirdparty/ykcore/yktsd.h
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/* yktsd.h -*- mode:C; c-file-style: "gnu" -*- */
|
||||
/* Note: this file is copied from Levitte Programming's LPlib and reworked
|
||||
for ykcore */
|
||||
/*
|
||||
* Copyright (c) 2008-2012 Yubico AB
|
||||
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
|
||||
* Copyright (c) 2003, 2004 Richard Levitte <richard@levitte.org>.
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*/
|
||||
|
||||
#ifndef YKTSD_H
|
||||
#define YKTSD_H
|
||||
|
||||
/* Define thread-specific data primitives */
|
||||
#if defined _WIN32
|
||||
#include <windows.h>
|
||||
#include <errno.h>
|
||||
#define yk__TSD_TYPE DWORD
|
||||
#define yk__TSD_ALLOC(key,nop) ((key = TlsAlloc()) == TLS_OUT_OF_INDEXES ? EAGAIN : 0)
|
||||
#define yk__TSD_FREE(key) (!TlsFree(key))
|
||||
#define yk__TSD_SET(key,value) (!TlsSetValue(key,value))
|
||||
#define yk__TSD_GET(key) TlsGetValue(key)
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#define yk__TSD_TYPE pthread_key_t
|
||||
#define yk__TSD_ALLOC(key,destr) pthread_key_create(&key, destr)
|
||||
#define yk__TSD_FREE(key) pthread_key_delete(key)
|
||||
#define yk__TSD_SET(key,value) pthread_setspecific(key,(void *)value)
|
||||
#define yk__TSD_GET(key) pthread_getspecific(key)
|
||||
#endif
|
||||
|
||||
/* Define the high-level macros that we use. */
|
||||
#define YK_TSD_METADATA(x) yk__tsd_##x
|
||||
#define YK_DEFINE_TSD_METADATA(x) static yk__TSD_TYPE YK_TSD_METADATA(x)
|
||||
#define YK_TSD_INIT(x,destr) yk__TSD_ALLOC(YK_TSD_METADATA(x),destr)
|
||||
#define YK_TSD_DESTROY(x) yk__TSD_FREE(YK_TSD_METADATA(x))
|
||||
#define YK_TSD_SET(x,value) yk__TSD_SET(YK_TSD_METADATA(x),value)
|
||||
#define YK_TSD_GET(type,x) (type)yk__TSD_GET(YK_TSD_METADATA(x))
|
||||
|
||||
#endif
|
136
src/thirdparty/ykcore/yubikey.h
vendored
Normal file
136
src/thirdparty/ykcore/yubikey.h
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
/* yubikey.h --- Prototypes for low-level YubiKey OTP functions.
|
||||
*
|
||||
* Written by Simon Josefsson <simon@josefsson.org>.
|
||||
* Copyright (c) 2006-2012 Yubico AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||
* OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef YUBIKEY_H
|
||||
#define YUBIKEY_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define YUBIKEY_BLOCK_SIZE 16
|
||||
#define YUBIKEY_KEY_SIZE 16
|
||||
#define YUBIKEY_UID_SIZE 6
|
||||
#define YUBIKEY_OTP_SIZE (2 * YUBIKEY_BLOCK_SIZE)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Unique (secret) ID. */
|
||||
uint8_t uid[YUBIKEY_UID_SIZE];
|
||||
/* Session counter (incremented by 1 at each startup). High bit
|
||||
indicates whether caps-lock triggered the token. */
|
||||
uint16_t ctr;
|
||||
/* Timestamp incremented by approx 8Hz (low part). */
|
||||
uint16_t tstpl;
|
||||
/* Timestamp (high part). */
|
||||
uint8_t tstph;
|
||||
/* Number of times used within session + activation flags. */
|
||||
uint8_t use;
|
||||
/* Pseudo-random value. */
|
||||
uint16_t rnd;
|
||||
/* CRC16 value of all fields. */
|
||||
uint16_t crc;
|
||||
} yubikey_token_st;
|
||||
|
||||
typedef yubikey_token_st *yubikey_token_t;
|
||||
|
||||
/* High-level functions. */
|
||||
|
||||
|
||||
/* Decrypt TOKEN using KEY and store output in OUT structure. Note
|
||||
that there is no error checking whether the output data is valid or
|
||||
not, use yubikey_check_* for that. */
|
||||
extern void yubikey_parse (const uint8_t token[YUBIKEY_BLOCK_SIZE],
|
||||
const uint8_t key[YUBIKEY_KEY_SIZE],
|
||||
yubikey_token_t out);
|
||||
|
||||
/* Generate OTP */
|
||||
extern void yubikey_generate (yubikey_token_t token,
|
||||
const uint8_t key[YUBIKEY_KEY_SIZE],
|
||||
char out[YUBIKEY_OTP_SIZE + 1]);
|
||||
|
||||
#define yubikey_counter(ctr) ((ctr) & 0x7FFF)
|
||||
#define yubikey_capslock(ctr) ((ctr) & 0x8000)
|
||||
#define yubikey_crc_ok_p(tok) \
|
||||
(yubikey_crc16 ((tok), YUBIKEY_BLOCK_SIZE) == YUBIKEY_CRC_OK_RESIDUE)
|
||||
|
||||
/*
|
||||
* Low-level functions; ModHex.
|
||||
*/
|
||||
|
||||
#define YUBIKEY_MODHEX_MAP "cbdefghijklnrtuv"
|
||||
|
||||
/* ModHex encode input string SRC of length SRCSIZE and put the zero
|
||||
terminated output string in DST. The size of the output string DST
|
||||
must be at least 2*SRCSIZE+1. The output string is always
|
||||
2*SRCSIZE large plus the terminating zero. */
|
||||
extern void yubikey_modhex_encode (char *dst,
|
||||
const char *src, size_t srcsize);
|
||||
|
||||
/* ModHex decode input string SRC of length DSTSIZE/2 into output
|
||||
string DST. The output string DST is always DSTSIZE/2 large plus
|
||||
the terminating zero. */
|
||||
extern void yubikey_modhex_decode (char *dst,
|
||||
const char *src, size_t dstsize);
|
||||
|
||||
/* Hex encode/decode data, same interface as modhex functions. */
|
||||
extern void yubikey_hex_encode (char *dst, const char *src, size_t srcsize);
|
||||
extern void yubikey_hex_decode (char *dst, const char *src, size_t dstsize);
|
||||
|
||||
/* Return non-zero if zero-terminated input STR is a valid (mod)hex
|
||||
string, and zero if any non-alphabetic characters are found. */
|
||||
extern int yubikey_modhex_p (const char *str);
|
||||
extern int yubikey_hex_p (const char *str);
|
||||
|
||||
/*
|
||||
* Low-level functions; CRC.
|
||||
*/
|
||||
|
||||
#define YUBIKEY_CRC_OK_RESIDUE 0xf0b8
|
||||
extern uint16_t yubikey_crc16 (const uint8_t * buf, size_t buf_size);
|
||||
|
||||
/* Low-level functions; AES. */
|
||||
|
||||
/* AES-decrypt/encrypt one 16-byte block STATE using the 128-bit KEY,
|
||||
leaving the decrypted/encrypted output in the STATE buffer. */
|
||||
extern void yubikey_aes_decrypt (uint8_t * state, const uint8_t * key);
|
||||
extern void yubikey_aes_encrypt (uint8_t * state, const uint8_t * key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user