From 919d46a3371e4770ca13ac25e5ce3fd996710d9e Mon Sep 17 00:00:00 2001 From: luoqing Date: Thu, 13 Apr 2023 15:41:16 +0800 Subject: [PATCH] feature(ukey):The UKey device is adapted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 完成UKey设备适配 --- data/drivers.conf | 6 +- include/auth-enum.h | 4 +- include/kiran-auth-device-i.h | 7 + include/third-party-device.h | 5 +- include/ukey-skf.h | 325 +++++++++++ src/CMakeLists.txt | 9 +- src/auth-device-manager.cpp | 45 +- src/auth-device-manager.h | 24 +- src/context/context-factory.cpp | 25 +- src/context/context-factory.h | 11 +- src/context/finger-vein/fv-sd-context.cpp | 1 + src/context/ukey/ukey-ft-context.cpp | 57 ++ src/context/ukey/ukey-ft-context.h | 27 + src/device/auth-device.cpp | 228 ++++---- src/device/auth-device.h | 65 +-- src/device/bio-device.cpp | 104 ++++ src/device/bio-device.h | 47 ++ src/device/finger-vein/fv-sd-device.cpp | 28 +- src/device/finger-vein/fv-sd-device.h | 10 +- src/device/fingerprint/fp-device.cpp | 2 +- src/device/fingerprint/fp-device.h | 4 +- src/device/fingerprint/fp-zk-device.cpp | 22 +- src/device/fingerprint/fp-zk-device.h | 7 +- src/device/ukey/ukey-ft-device.cpp | 400 ++++++++++++++ src/device/ukey/ukey-ft-device.h | 68 +++ src/driver/ukey/ukey-skf-driver.cpp | 516 ++++++++++++++++++ src/driver/ukey/ukey-skf-driver.h | 62 +++ .../kiran-authentication-devices.zh_CN.ts | 82 ++- 28 files changed, 1916 insertions(+), 275 deletions(-) create mode 100644 include/ukey-skf.h create mode 100644 src/context/ukey/ukey-ft-context.cpp create mode 100644 src/context/ukey/ukey-ft-context.h create mode 100644 src/device/bio-device.cpp create mode 100644 src/device/bio-device.h create mode 100644 src/device/ukey/ukey-ft-device.cpp create mode 100644 src/device/ukey/ukey-ft-device.h create mode 100644 src/driver/ukey/ukey-skf-driver.cpp create mode 100644 src/driver/ukey/ukey-skf-driver.h diff --git a/data/drivers.conf b/data/drivers.conf index e2be3f1..ef3f9f8 100644 --- a/data/drivers.conf +++ b/data/drivers.conf @@ -8,4 +8,8 @@ Type=0 [sdfv] Enable=true -Type=2 \ No newline at end of file +Type=2 + +[es_3000gm] +Enable=true +Type=5 \ No newline at end of file diff --git a/include/auth-enum.h b/include/auth-enum.h index 19f98d1..a29e9b5 100644 --- a/include/auth-enum.h +++ b/include/auth-enum.h @@ -93,7 +93,9 @@ enum IdentifyProcess // 匹配 IDENTIFY_PROCESS_MACTCH, // 不匹配 - IDENTIFY_PROCESS_NO_MATCH + IDENTIFY_PROCESS_NO_MATCH, + // PIN码不正确 + IDENTIFY_PROCESS_PIN_INCORRECT }; } // namespace Kiran \ No newline at end of file diff --git a/include/kiran-auth-device-i.h b/include/kiran-auth-device-i.h index 8422eaf..89e4000 100644 --- a/include/kiran-auth-device-i.h +++ b/include/kiran-auth-device-i.h @@ -26,6 +26,11 @@ extern "C" #define GENERAL_AUTH_DEVICE_DBUS_OBJECT_PATH "/com/kylinsec/Kiran/AuthDevice/Device" #define GENERAL_AUTH_DEVICE_DBUS_INTERFACE_NAME "com.kylinsec.Kiran.AuthDevice.Device" +#define AUTH_DEVICE_JSON_KEY_UKEY "ukey" +#define AUTH_DEVICE_JSON_KEY_PIN "pin" +#define AUTH_DEVICE_JSON_KEY_REBINDING "rebinding" +#define AUTH_DEVICE_JSON_KEY_FEATURE_IDS "feature_ids" + // 录入结果 enum EnrollResult { @@ -37,6 +42,8 @@ extern "C" ENROLL_RESULT_PASS, // 因为扫描质量或者用户扫描过程中发生的问题引起 ENROLL_RESULT_RETRY, + // UKey已经存在绑定关系 + ENROLL_RESULT_UKEY_EXIST_BINDING }; // 识别结果 diff --git a/include/third-party-device.h b/include/third-party-device.h index d06a4a2..2b118d3 100644 --- a/include/third-party-device.h +++ b/include/third-party-device.h @@ -19,7 +19,7 @@ namespace Kiran { #define ZK_ID_VENDOR "1b55" #define SD_ID_VENDOR "05e3" - +#define FT_ID_VENDOR "096e" static const struct ThirdPartyDeviceSupported { @@ -35,7 +35,8 @@ static const struct ThirdPartyDeviceSupported QString description; }ThirdPartyDeviceSupportedTable[] = { {DEVICE_TYPE_FingerPrint,"1b55","0120","","ZK"}, - {DEVICE_TYPE_FingerVein,"05e3","0608","","SD"} + {DEVICE_TYPE_FingerVein,"05e3","0608","","SD"}, + {DEVICE_TYPE_UKey,"096e","0309","","FT"} }; } \ No newline at end of file diff --git a/include/ukey-skf.h b/include/ukey-skf.h new file mode 100644 index 0000000..d1b6a6f --- /dev/null +++ b/include/ukey-skf.h @@ -0,0 +1,325 @@ +/** + * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiran-biometrics is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: luoqing + */ + +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef int8_t INT8; +typedef int16_t INT16; +typedef int32_t INT32; +typedef unsigned char UINT8; +typedef uint16_t UINT16; +typedef uint32_t UINT32; +typedef long BOOL; + +typedef UINT8 BYTE; +typedef UINT8 CHAR; +typedef INT16 SHORT; +typedef UINT16 USHORT; +typedef INT32 LONG; +typedef UINT32 ULONG; +typedef UINT32 UINT; +typedef UINT16 WORD; +typedef UINT32 DWORD; +typedef UINT32 FLAGS; +typedef CHAR *LPSTR; +typedef void *HANDLE; +typedef HANDLE DEVHANDLE; +typedef HANDLE HAPPLICATION; +typedef HANDLE HCONTAINER; + +#define MAX_RSA_MODULUS_LEN 256 +#define MAX_RSA_EXPONENT_LEN 4 +#define ECC_MAX_XCOORDINATE_BITS_LEN 512 +#define ECC_MAX_YCOORDINATE_BITS_LEN 512 +#define ECC_MAX_MODULUS_BITS_LEN 512 + +#define MAX_IV_LEN 32 +#define MAX_FILE_NAME_SIZE 32 +#define MAX_FILE_CONTAINER_NAME_SIZE 64 + +/*Permission type*/ +#define SECURE_NEVER_ACCOUNT 0x00000000 +#define SECURE_ADM_ACCOUNT 0x00000001 +#define SECURE_USER_ACCOUNT 0x00000010 +#define SECURE_ANYONE_ACCOUNT 0x000000FF + +#ifndef FALSE +#define FALSE 0x00000000 +#endif + +#ifndef TRUE +#define TRUE 0x00000001 +#endif + +#ifndef ADMIN_TYPE +#define ADMIN_TYPE 0 +#endif + +#ifndef USER_TYPE +#define USER_TYPE 1 +#endif + +/* public key usage */ +#define SGD_PK_SIGN 0x0100 +#define SGD_PK_DH 0x0200 +#define SGD_PK_ENC 0x0400 + +/* public key types */ +#define SGD_RSA 0x00010000 +#define SGD_RSA_SIGN (SGD_RSA | SGD_PK_SIGN) +#define SGD_RSA_ENC (SGD_RSA | SGD_PK_ENC) +#define SGD_SM2 0x00020000 +#define SGD_SM2_1 (SGD_SM2 | SGD_PK_SIGN) +#define SGD_SM2_2 (SGD_SM2 | SGD_PK_DH) +#define SGD_SM2_3 (SGD_SM2 | SGD_PK_ENC) + +/* hash */ +#define SGD_SM3 0x00000001 +#define SGD_SHA1 0x00000002 +#define SGD_SHA256 0x00000004 +#define SGD_HASH_FROM 0x00000008 +#define SGD_HASH_TO 0x000000FF + +/* signatue schemes */ +#define SGD_SM3_RSA (SGD_SM3|SGD_RSA) +#define SGD_SHA1_RSA (SGD_SHA1|SGD_RSA) +#define SGD_SHA256_RSA (SGD_SHA256|SGD_RSA) +#define SGD_SM3_SM2 (SGD_SM3|SGD_SM2) +#define SGD_SIG_FROM 0x00040000 +#define SGD_SIG_TO 0x800000FF + +#pragma pack(1) + typedef struct Struct_Version + { + BYTE major; + BYTE minor; + } VERSION; + + typedef struct Struct_DEVINFO + { + VERSION Version; + CHAR Manufacturer[64]; + CHAR Issuer[64]; + CHAR Label[32]; + CHAR SerialNumber[32]; + VERSION HWVersion; + VERSION FirmwareVersion; + ULONG AlgSymCap; + ULONG AlgAsymCap; + ULONG AlgHashCap; + ULONG DevAuthAlgId; + ULONG TotalSpace; + ULONG FreeSpace; + ULONG MaxECCBufferSize; + ULONG MaxBufferSize; + BYTE Reserved[64]; + } DEVINFO, *PDEVINFO; + + typedef struct Struct_RSAPUBLICKEYBLOB + { + ULONG AlgID; + ULONG BitLen; + BYTE Modulus[MAX_RSA_MODULUS_LEN]; + BYTE PublicExponent[MAX_RSA_EXPONENT_LEN]; + } RSAPUBLICKEYBLOB, *PRSAPUBLICKEYBLOB; + + typedef struct Struct_RSAPRIVATEKEYBLOB + { + ULONG AlgID; + ULONG BitLen; + BYTE Modulus[MAX_RSA_MODULUS_LEN]; + BYTE PublicExponent[MAX_RSA_EXPONENT_LEN]; + BYTE PrivateExponent[MAX_RSA_MODULUS_LEN]; + BYTE Prime1[MAX_RSA_MODULUS_LEN / 2]; + BYTE Prime2[MAX_RSA_MODULUS_LEN / 2]; + BYTE Prime1Exponent[MAX_RSA_MODULUS_LEN / 2]; + BYTE Prime2Exponent[MAX_RSA_MODULUS_LEN / 2]; + BYTE Coefficient[MAX_RSA_MODULUS_LEN / 2]; + } RSAPRIVATEKEYBLOB, *PRSAPRIVATEKEYBLOB; + + typedef struct Struct_ECCPUBLICKEYBLOB + { + ULONG BitLen; + BYTE XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN / 8]; + BYTE YCoordinate[ECC_MAX_YCOORDINATE_BITS_LEN / 8]; + } ECCPUBLICKEYBLOB, *PECCPUBLICKEYBLOB; + + typedef struct Struct_ECCPRIVATEKEYBLOB + { + ULONG BitLen; + BYTE PrivateKey[ECC_MAX_MODULUS_BITS_LEN / 8]; + } ECCPRIVATEKEYBLOB, *PECCPRIVATEKEYBLOB; + + typedef struct Struct_ECCCIPHERBLOB + { + BYTE XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN / 8]; + BYTE YCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN / 8]; + BYTE HASH[32]; + ULONG CipherLen; + BYTE Cipher[1]; + } ECCCIPHERBLOB, *PECCCIPHERBLOB; + + typedef struct Struct_ECCSIGNATUREBLOB + { + BYTE r[ECC_MAX_XCOORDINATE_BITS_LEN / 8]; + BYTE s[ECC_MAX_XCOORDINATE_BITS_LEN / 8]; + } ECCSIGNATUREBLOB, *PECCSIGNATUREBLOB; + + typedef struct Struct_BLOCKCIPHERPARAM + { + BYTE IV[MAX_IV_LEN]; + ULONG IVLen; + ULONG PaddingType; + ULONG FeedBitLen; + } BLOCKCIPHERPARAM, *PBLOCKCIPHERPARAM; + + typedef struct SKF_ENVELOPEDKEYBLOB + { + ULONG Version; + ULONG ulSymmAlgID; + ULONG ulBits; + BYTE cbEncryptedPriKey[64]; + ECCPUBLICKEYBLOB PubKey; + ECCCIPHERBLOB ECCCipherBlob; + } ENVELOPEDKEYBLOB, *PENVELOPEDKEYBLOB; + + typedef struct Struct_FILEATTRIBUTE + { + CHAR FileName[MAX_FILE_NAME_SIZE]; + ULONG FileSize; + ULONG ReadRights; + ULONG WriteRights; + } FILEATTRIBUTE, *PFILEATTRIBUTE; +#pragma pack() + +#define SAR_OK 0x00000000 +#define SAR_FAIL 0x0A000001 +#define SAR_UNKNOWNERR 0x0A000002 +#define SAR_NOTSUPPORTYETERR 0x0A000003 +#define SAR_FILEERR 0x0A000004 +#define SAR_INVALIDHANDLEERR 0x0A000005 +#define SAR_INVALIDPARAMERR 0x0A000006 +#define SAR_READFILEERR 0x0A000007 +#define SAR_WRITEFILEERR 0x0A000008 +#define SAR_NAMELENERR 0x0A000009 +#define SAR_KEYUSAGEERR 0x0A00000A +#define SAR_MODULUSLENERR 0x0A00000B +#define SAR_NOTINITIALIZEERR 0x0A00000C +#define SAR_OBJERR 0x0A00000D +#define SAR_MEMORYERR 0x0A00000E +#define SAR_TIMEOUTERR 0x0A00000F +#define SAR_INDATALENERR 0x0A000010 +#define SAR_INDATAERR 0x0A000011 +#define SAR_GENRANDERR 0x0A000012 +#define SAR_HASHOBJERR 0x0A000013 +#define SAR_HASHERR 0x0A000014 +#define SAR_GENRSAKEYERR 0x0A000015 +#define SAR_RSAMODULUSLENERR 0x0A000016 +#define SAR_CSPIMPRTPUBKEYERR 0x0A000017 +#define SAR_RSAENCERR 0x0A000018 +#define SAR_RSADECERR 0x0A000019 +#define SAR_HASHNOTEQUALERR 0x0A00001A +#define SAR_KEYNOTFOUNTERR 0x0A00001B +#define SAR_CERTNOTFOUNTERR 0x0A00001C +#define SAR_NOTEXPORTERR 0x0A00001D +#define SAR_DECRYPTPADERR 0x0A00001E +#define SAR_MACLENERR 0x0A00001F +#define SAR_BUFFER_TOO_SMALL 0x0A000020 +#define SAR_KEYINFOTYPEERR 0x0A000021 +#define SAR_NOT_EVENTERR 0x0A000022 +#define SAR_DEVICE_REMOVED 0x0A000023 +#define SAR_PIN_INCORRECT 0x0A000024 +#define SAR_PIN_LOCKED 0x0A000025 +#define SAR_PIN_INVALID 0x0A000026 +#define SAR_PIN_LEN_RANGE 0x0A000027 +#define SAR_USER_ALREADY_LOGGED_IN 0x0A000028 +#define SAR_USER_PIN_NOT_INITIALIZED 0x0A000029 +#define SAR_USER_TYPE_INVALID 0x0A00002A +#define SAR_APPLICATION_NAME_INVALID 0x0A00002B +#define SAR_APPLICATION_EXISTS 0x0A00002C +#define SAR_USER_NOT_LOGGED_IN 0x0A00002D +#define SAR_APPLICATION_NOT_EXISTS 0x0A00002E +#define SAR_FILE_ALREADY_EXIST 0x0A00002F +#define SAR_NO_ROOM 0x0A000030 +#define SAR_FILE_NOT_EXIST 0x0A000031 +#define SAR_REACH_MAX_CONTAINER_COUNT 0x0A000032 + +typedef struct { + ULONG err; + QString reason; +} SKF_ERR_REASON; + +static SKF_ERR_REASON skf_errors[] = { + { SAR_OK, "success" }, + { SAR_FAIL, "failure" }, + { SAR_UNKNOWNERR, "unknown error" }, + { SAR_NOTSUPPORTYETERR, "operation not supported" }, + { SAR_FILEERR, "file error" }, + { SAR_INVALIDHANDLEERR, "invalid handle" }, + { SAR_INVALIDPARAMERR, "invalid parameter" }, + { SAR_READFILEERR, "read file failure" }, + { SAR_WRITEFILEERR, "write file failure" }, + { SAR_NAMELENERR, "invalid name length" }, + { SAR_KEYUSAGEERR, "invalid key usage" }, + { SAR_MODULUSLENERR, "invalid modulus length" }, + { SAR_NOTINITIALIZEERR, "not initialized" }, + { SAR_OBJERR, "invalid object" }, + { SAR_MEMORYERR, "memory error" }, + { SAR_TIMEOUTERR, "timeout" }, + { SAR_INDATALENERR, "invalid input length" }, + { SAR_INDATAERR, "invalid input value" }, + { SAR_GENRANDERR, "random generation failed" }, + { SAR_HASHOBJERR, "invalid digest handle" }, + { SAR_HASHERR, "digest error" }, + { SAR_GENRSAKEYERR, "rsa key generation failure" }, + { SAR_RSAMODULUSLENERR, "invalid rsa modulus length" }, + { SAR_CSPIMPRTPUBKEYERR, "csp import public key error" }, + { SAR_RSAENCERR, "rsa encryption failure" }, + { SAR_RSADECERR, "rsa decryption failure" }, + { SAR_HASHNOTEQUALERR, "hash not equal" }, + { SAR_KEYNOTFOUNTERR, "key not found" }, + { SAR_CERTNOTFOUNTERR, "certificate not found" }, + { SAR_NOTEXPORTERR, "export failed" }, + { SAR_DECRYPTPADERR, "decrypt invalid padding" }, + { SAR_MACLENERR, "invalid mac length" }, + { SAR_BUFFER_TOO_SMALL, "buffer too small" }, + { SAR_KEYINFOTYPEERR, "invalid key info type" }, + { SAR_NOT_EVENTERR, "no event" }, + { SAR_DEVICE_REMOVED, "device removed" }, + { SAR_PIN_INCORRECT, "pin incorrect" }, + { SAR_PIN_LOCKED, "pin locked" }, + { SAR_PIN_INVALID, "invalid pin" }, + { SAR_PIN_LEN_RANGE, "invalid pin length" }, + { SAR_USER_ALREADY_LOGGED_IN, "user already logged in" }, + { SAR_USER_PIN_NOT_INITIALIZED, "user pin not initialized" }, + { SAR_USER_TYPE_INVALID, "invalid user type" }, + { SAR_APPLICATION_NAME_INVALID, "invalid application name" }, + { SAR_APPLICATION_EXISTS, "application already exist" }, + { SAR_USER_NOT_LOGGED_IN, "user not logged in" }, + { SAR_APPLICATION_NOT_EXISTS, "application not exist" }, + { SAR_FILE_ALREADY_EXIST, "file already exist" }, + { SAR_NO_ROOM, "no space" }, + { SAR_FILE_NOT_EXIST, "file not exist" }, +}; + +#ifdef __cplusplus +} +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 39c8dc5..cac6cb4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,11 +37,14 @@ qt_add_dbus_adaptor( set(DEVICE_SDK ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}-sdk) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) -set(CMAKE_INSTALL_RPATH ${DEVICE_SDK}/finger-vein/sd:${DEVICE_SDK}/fingerprint/zk) +set(CMAKE_INSTALL_RPATH ${DEVICE_SDK}/finger-vein/sd:${DEVICE_SDK}/fingerprint/zk:${DEVICE_SDK}/ukey/ft) set(TS_FILES "${PROJECT_SOURCE_DIR}/translations/${PROJECT_NAME}.zh_CN.ts") -qt_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${TS_FILES}) +qt_create_translation(QM_FILES + ${CMAKE_CURRENT_SOURCE_DIR} + ${TS_FILES} + ) add_executable(${PROJECT_NAME} ${SRC_H_FILES} @@ -58,7 +61,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${KLOG_QT5_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} ) - + target_link_libraries(${PROJECT_NAME} ${KLOG_QT5_LIBRARIES} ${LIBUDEV_LIBRARIES} diff --git a/src/auth-device-manager.cpp b/src/auth-device-manager.cpp index 984d3c1..a0ac795 100644 --- a/src/auth-device-manager.cpp +++ b/src/auth-device-manager.cpp @@ -18,9 +18,9 @@ #include #include #include -#include "device/auth-device.h" #include "auth_device_manager_adaptor.h" #include "context/context-factory.h" +#include "device/auth-device.h" #include "feature-db.h" #include "kiran-auth-device-i.h" #include "polkit-proxy.h" @@ -148,7 +148,7 @@ void AuthDeviceManager::onRemove(const QDBusMessage& message, const QString& fea { bool result = FeatureDB::getInstance()->deleteFeature(feature_id); KLOG_DEBUG() << "deleteFeature:" << feature_id - << "result" << result; + << "exec:" << result; auto replyMessage = message.createReply(); QDBusConnection::systemBus().send(replyMessage); } @@ -192,10 +192,9 @@ CHECK_AUTH_WITH_2ARGS(AuthDeviceManager, SetEnableDriver, onSetEnableDriver, AUT void AuthDeviceManager::init() { - m_dbusAdaptor = new AuthDeviceManagerAdaptor(this); - m_contextFactory = ContextFactory::instance(); - m_timer = new QTimer(this); - connect(m_timer, &QTimer::timeout, this, &AuthDeviceManager::handleDeviceReCreate); + m_dbusAdaptor = QSharedPointer(new AuthDeviceManagerAdaptor(this)); + m_contextFactory = QSharedPointer(ContextFactory::instance()); + connect(&m_timer, &QTimer::timeout, this, &AuthDeviceManager::handleDeviceReCreate); QDBusConnection dbusConnection = QDBusConnection::systemBus(); if (!dbusConnection.registerService(AUTH_DEVICE_DBUS_NAME)) @@ -214,14 +213,14 @@ void AuthDeviceManager::init() KLOG_ERROR() << "Can't register object:" << dbusConnection.lastError(); } - m_udev = udev_new(); + m_udev = QSharedPointer (udev_new()); if (!m_udev) { KLOG_ERROR() << "new udev error"; } - initDeviceMonitor(m_udev); - auto usbInfoList = enumerateDevices(m_udev); + initDeviceMonitor(m_udev.data()); + auto usbInfoList = enumerateDevices(m_udev.data()); // 枚举设备后,生成设备对象 Q_FOREACH (auto deviceInfo, usbInfoList) { @@ -243,16 +242,16 @@ void AuthDeviceManager::init() void AuthDeviceManager::initDeviceMonitor(struct udev* udev) { // 创建一个新的monitor - m_monitor = udev_monitor_new_from_netlink(udev, "udev"); + m_monitor = QSharedPointer (udev_monitor_new_from_netlink(udev, "udev")); // 增加一个udev事件过滤器 - udev_monitor_filter_add_match_subsystem_devtype(m_monitor, "usb", nullptr); + udev_monitor_filter_add_match_subsystem_devtype(m_monitor.data(), "usb", nullptr); // 启动监控 - udev_monitor_enable_receiving(m_monitor); + udev_monitor_enable_receiving(m_monitor.data()); // 获取该监控的文件描述符,fd就代表了这个监控 - m_fd = udev_monitor_get_fd(m_monitor); + m_fd = udev_monitor_get_fd(m_monitor.data()); - m_socketNotifierRead = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); - connect(m_socketNotifierRead, &QSocketNotifier::activated, this, &AuthDeviceManager::handleSocketNotifierRead); + m_socketNotifierRead = QSharedPointer(new QSocketNotifier(m_fd, QSocketNotifier::Read, this)); + connect(m_socketNotifierRead.data(), &QSocketNotifier::activated, this, &AuthDeviceManager::handleSocketNotifierRead); } void AuthDeviceManager::handleSocketNotifierRead(int socket) @@ -274,7 +273,7 @@ void AuthDeviceManager::handleSocketNotifierRead(int socket) return; // 获取产生事件的设备映射 - struct udev_device* dev = udev_monitor_receive_device(m_monitor); + struct udev_device* dev = udev_monitor_receive_device(m_monitor.data()); if (!dev) return; @@ -317,11 +316,11 @@ void AuthDeviceManager::handleSocketNotifierRead(int socket) QList AuthDeviceManager::enumerateDevices(struct udev* udev) { // 创建一个枚举器用于扫描已连接的设备 - struct udev_enumerate* enumerate = udev_enumerate_new(udev); + struct udev_enumerate* enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, SUBSYSTEM); udev_enumerate_scan_devices(enumerate); // 返回一个存储了设备所有属性信息的链表 - struct udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate); + struct udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate); struct udev_list_entry* entry; QList usbInfoList; @@ -329,7 +328,7 @@ QList AuthDeviceManager::enumerateDevices(struct udev* udev) { const char* path = udev_list_entry_get_name(entry); // 创建一个udev设备的映射 - struct udev_device* dev = udev_device_new_from_syspath(udev, path); + struct udev_device* dev = udev_device_new_from_syspath(udev, path); DeviceInfo usbInfo; usbInfo.idVendor = udev_device_get_sysattr_value(dev, "idVendor"); usbInfo.idProduct = udev_device_get_sysattr_value(dev, "idProduct"); @@ -419,16 +418,16 @@ void AuthDeviceManager::handleDeviceCreateFail(DeviceInfo deviceInfo) m_retreyCreateDeviceMap.insert(deviceInfo, 0); if (m_retreyCreateDeviceMap.count() != 0) { - if (!m_timer->isActive()) + if (!m_timer.isActive()) { - m_timer->start(1000); + m_timer.start(1000); } } } void AuthDeviceManager::handleDeviceDeleted() { - QList newUsbInfoList = enumerateDevices(m_udev); + QList newUsbInfoList = enumerateDevices(m_udev.data()); QStringList newBusList; Q_FOREACH (auto newUsbInfo, newUsbInfoList) { @@ -468,7 +467,7 @@ void AuthDeviceManager::handleDeviceReCreate() { if (m_retreyCreateDeviceMap.count() == 0) { - m_timer->stop(); + m_timer.stop(); } else { diff --git a/src/auth-device-manager.h b/src/auth-device-manager.h index fcf56bd..0993a55 100644 --- a/src/auth-device-manager.h +++ b/src/auth-device-manager.h @@ -15,12 +15,13 @@ #pragma once #include +#include #include #include +#include #include #include #include "auth-enum.h" -#include class AuthDeviceManagerAdaptor; @@ -43,7 +44,7 @@ public: public Q_SLOTS: QString GetDevices(); - QString GetDevicesByType(int device_type); + QString GetDevicesByType(int device_type); QDBusObjectPath GetDevice(const QString &device_id); QStringList GetAllFeatureIDs(); QString GetDriversByType(int device_type); @@ -64,8 +65,8 @@ private: void processDevice(struct udev_device *dev); void deviceSimpleInfo(struct udev_device *dev); - void onRemove(const QDBusMessage &message,const QString &feature_id); - void onSetEnableDriver(const QDBusMessage &message,const QString &driver_name, bool enable); + void onRemove(const QDBusMessage &message, const QString &feature_id); + void onSetEnableDriver(const QDBusMessage &message, const QString &driver_name, bool enable); Q_SIGNALS: void DeviceAdded(int device_type, const QString &device_id); @@ -73,19 +74,18 @@ Q_SIGNALS: private: static AuthDeviceManager *m_instance; - struct udev *m_udev; - struct udev_monitor *m_monitor; + QSharedPointer m_udev; + QSharedPointer m_monitor; int m_fd; - AuthDeviceManagerAdaptor *m_dbusAdaptor; - QSocketNotifier *m_socketNotifierRead; + QSharedPointer m_dbusAdaptor; + QSharedPointer m_socketNotifierRead; // 总线 -- AuthDevice对象对应 QMap m_deviceMap; - ContextFactory *m_contextFactory; - - QTimer *m_timer; + QSharedPointer m_contextFactory; + QTimer m_timer; // 设备信息-重试次数 - QMap m_retreyCreateDeviceMap; + QMap m_retreyCreateDeviceMap; }; } // namespace Kiran diff --git a/src/context/context-factory.cpp b/src/context/context-factory.cpp index 82c9c6b..f489d8f 100644 --- a/src/context/context-factory.cpp +++ b/src/context/context-factory.cpp @@ -15,11 +15,12 @@ #include "context-factory.h" #include #include +#include "finger-vein/fv-sd-context.h" #include "fingerprint/fp-builtin-context.h" #include "fingerprint/fp-zk-context.h" -#include "finger-vein/fv-sd-context.h" #include "kiran-auth-device-i.h" #include "third-party-device.h" +#include "ukey/ukey-ft-context.h" namespace Kiran { @@ -47,9 +48,10 @@ ContextFactory::ContextFactory(QObject* parent) void ContextFactory::init() { - m_fpZKContext = new FPZKContext(); - m_fpBuiltInContext = new FPBuiltInContext(); - m_fvSDContext = new FVSDContext(); + m_fpZKContext = QSharedPointer(new FPZKContext()); + m_fpBuiltInContext = QSharedPointer(new FPBuiltInContext()); + m_fvSDContext = QSharedPointer(new FVSDContext()); + m_ukeyFTContext = QSharedPointer(new UKeyFTContext()); } AuthDevice* ContextFactory::createDevice(const QString& idVendor, const QString& idProduct) @@ -72,6 +74,9 @@ AuthDevice* ContextFactory::createDevice(const QString& idVendor, const QString& case DEVICE_TYPE_FingerVein: device = createFingerVeinDevice(idVendor, idProduct); break; + case DEVICE_TYPE_UKey: + device = createUKeyDevice(idVendor, idProduct); + break; default: break; } @@ -120,6 +125,18 @@ AuthDevice* ContextFactory::createFingerVeinDevice(const QString& idVendor, cons return nullptr; } +AuthDevice* ContextFactory::createUKeyDevice(const QString& idVendor, const QString& idProduct) +{ + if (idVendor == FT_ID_VENDOR) + { + return m_ukeyFTContext->createDevice(idVendor, idProduct); + } + else + { + return nullptr; + }; +} + Context* ContextFactory::CreateContext() { return nullptr; diff --git a/src/context/context-factory.h b/src/context/context-factory.h index f2d510a..5d06839 100644 --- a/src/context/context-factory.h +++ b/src/context/context-factory.h @@ -15,13 +15,14 @@ #include #include "context.h" - +#include namespace Kiran { class FPZKContext; class FPBuiltInContext; class FVSDContext; +class UKeyFTContext; class ContextFactory : public QObject { @@ -43,11 +44,13 @@ private: void init(); AuthDevice* createFingerPrintDevice(const QString& idVendor, const QString& idProduct); AuthDevice* createFingerVeinDevice(const QString& idVendor, const QString& idProduct); + AuthDevice* createUKeyDevice(const QString& idVendor, const QString& idProduct); private: QStringList m_idVendorList; - FPZKContext* m_fpZKContext; - FPBuiltInContext* m_fpBuiltInContext; - FVSDContext* m_fvSDContext; + QSharedPointer m_fpZKContext; + QSharedPointer m_fpBuiltInContext; + QSharedPointer m_fvSDContext; + QSharedPointer m_ukeyFTContext; }; } // namespace Kiran diff --git a/src/context/finger-vein/fv-sd-context.cpp b/src/context/finger-vein/fv-sd-context.cpp index a2e9dc7..d898564 100644 --- a/src/context/finger-vein/fv-sd-context.cpp +++ b/src/context/finger-vein/fv-sd-context.cpp @@ -24,6 +24,7 @@ FVSDContext::FVSDContext(QObject* parent) { } +//TODO:createDevice 流程类似,考虑优化,减少重复代码 // fp-zk-context 需要管理多个so,可以生成不同 so的设备 AuthDevice* FVSDContext::createDevice(const QString& idVendor, const QString& idProduct) { diff --git a/src/context/ukey/ukey-ft-context.cpp b/src/context/ukey/ukey-ft-context.cpp new file mode 100644 index 0000000..40e9df3 --- /dev/null +++ b/src/context/ukey/ukey-ft-context.cpp @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiran-biometrics is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: luoqing + */ + +#include "ukey-ft-context.h" +#include +#include "device/ukey/ukey-ft-device.h" +#include "utils.h" + +namespace Kiran +{ +UKeyFTContext::UKeyFTContext(QObject* parent) + : Context{parent} +{ +} + +AuthDevice* UKeyFTContext::createDevice(const QString& idVendor, const QString& idProduct) +{ + auto ftDevice = new UKeyFTDevice(); + if (!Utils::driverEnabled(ftDevice->deviceDriver())) + { + KLOG_INFO() << QString("driver %1 is disabled! device %2:%3 can't be used") + .arg(ftDevice->deviceDriver()) + .arg(idVendor) + .arg(idProduct); + return nullptr; + } + if (ftDevice->init()) + { + QString deviceName = Utils::getDeviceName(idVendor, idProduct); + if (deviceName.isEmpty()) + { + deviceName = "Feitian Technologies"; + } + ftDevice->setDeviceName(deviceName); + ftDevice->setDeviceInfo(idVendor, idProduct); + m_deviceMap.insert(ftDevice->deviceID(), ftDevice); + return ftDevice; + } + else + { + KLOG_ERROR() << QString("device %1:%2 init failed!").arg(idVendor).arg(idProduct); + ftDevice->deleteLater(); + return nullptr; + } +} +} // namespace Kiran diff --git a/src/context/ukey/ukey-ft-context.h b/src/context/ukey/ukey-ft-context.h new file mode 100644 index 0000000..48bd40d --- /dev/null +++ b/src/context/ukey/ukey-ft-context.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiran-biometrics is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: luoqing + */ +#pragma once +#include "context/context.h" + +namespace Kiran +{ +class AuthDevice; +class UKeyFTContext : public Context +{ +public: + explicit UKeyFTContext(QObject *parent = nullptr); + AuthDevice* createDevice(const QString& idVendor, const QString& idProduct) override; +}; + +} // namespace Kiran diff --git a/src/device/auth-device.cpp b/src/device/auth-device.cpp index 0b890ec..d906fd1 100644 --- a/src/device/auth-device.cpp +++ b/src/device/auth-device.cpp @@ -42,7 +42,7 @@ bool AuthDevice::init() { if (initDevice()) { - m_dbusAdaptor = new AuthDeviceAdaptor(this); + m_dbusAdaptor = QSharedPointer(new AuthDeviceAdaptor(this)); m_deviceID = QUuid::createUuid().toString(QUuid::WithoutBraces); m_deviceStatus = DEVICE_STATUS_IDLE; registerDBusObject(); @@ -71,17 +71,17 @@ void AuthDevice::registerDBusObject() void AuthDevice::initFutureWatcher() { - m_futureWatcher = new QFutureWatcher(this); - connect(m_futureWatcher, &QFutureWatcher::finished, this, &AuthDevice::handleAcquiredFeature); + m_futureWatcher = QSharedPointer>(new QFutureWatcher(this)); + connect(m_futureWatcher.data(), &QFutureWatcher::finished, this, &AuthDevice::handleAcquiredFeature); connect(this, &AuthDevice::retry, this, &AuthDevice::handleRetry); } void AuthDevice::initServiceWatcher() { - m_serviceWatcher = new QDBusServiceWatcher(this); + m_serviceWatcher = QSharedPointer(new QDBusServiceWatcher(this)); this->m_serviceWatcher->setConnection(QDBusConnection::systemBus()); this->m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); - connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &AuthDevice::onNameLost); + connect(m_serviceWatcher.data(), &QDBusServiceWatcher::serviceUnregistered, this, &AuthDevice::onNameLost); } void AuthDevice::onNameLost(const QString& serviceName) @@ -110,6 +110,15 @@ void AuthDevice::clearWatchedServices() } } +DeviceInfo AuthDevice::deviceInfo() +{ + DeviceInfo deviceInfo; + deviceInfo.idVendor = m_idVendor; + deviceInfo.idProduct = m_idProduct; + deviceInfo.busPath = ""; + return deviceInfo; +} + void AuthDevice::setDeviceType(DeviceType deviceType) { m_deviceType = deviceType; @@ -153,8 +162,36 @@ void AuthDevice::onEnrollStart(const QDBusMessage& dbusMessage, const QString& e KLOG_DEBUG() << message; return; } + QJsonValue ukeyValue = Utils::getValueFromJsonString(extraInfo, AUTH_DEVICE_JSON_KEY_UKEY); + if (ukeyValue.isNull()) + { + onBioEnrollStart(dbusMessage); + } + else + { + onUKeyEnrollStart(dbusMessage, ukeyValue); + } +} - // 获取当前保存的指纹模板,判断是否达到最大指纹数目 +void AuthDevice::onEnrollStop(const QDBusMessage& dbusMessage) +{ + if (deviceStatus() == DEVICE_STATUS_DOING_ENROLL) + { + acquireFeatureStop(); + m_enrollTemplates.clear(); + setDeviceStatus(DEVICE_STATUS_IDLE); + clearWatchedServices(); + KLOG_DEBUG() << "EnrollStop"; + } + + auto replyMessage = dbusMessage.createReply(); + QDBusConnection::systemBus().send(replyMessage); +} + +void AuthDevice::onBioEnrollStart(const QDBusMessage& dbusMessage) +{ + QString message; + // 获取当前保存的特征模板,判断是否达到最大数目 QByteArrayList saveList = FeatureDB::getInstance()->getFeatures(m_idVendor, m_idProduct); if (saveList.count() == TEMPLATE_MAX_NUMBER) { @@ -163,32 +200,35 @@ void AuthDevice::onEnrollStart(const QDBusMessage& dbusMessage, const QString& e KLOG_ERROR() << message; return; } - setDeviceStatus(DEVICE_STATUS_DOING_ENROLL); - m_doEnroll = true; - auto future = QtConcurrent::run(this, &AuthDevice::acquireFeature); m_futureWatcher->setFuture(future); m_serviceWatcher->addWatchedService(dbusMessage.service()); - auto replyMessage = dbusMessage.createReply(); QDBusConnection::systemBus().send(replyMessage); } -void AuthDevice::onEnrollStop(const QDBusMessage& dbusMessage) +void AuthDevice::onUKeyEnrollStart(const QDBusMessage& dbusMessage, QJsonValue ukeyValue) { - if (deviceStatus() == DEVICE_STATUS_DOING_ENROLL) + QString message; + auto jsonObject = ukeyValue.toObject(); + m_pin = jsonObject.value(AUTH_DEVICE_JSON_KEY_PIN).toString(); + bool rebinding = jsonObject.value(AUTH_DEVICE_JSON_KEY_REBINDING).toBool(); + if (m_pin.isEmpty()) { - acquireFeatureStop(); - m_doEnroll = false; - m_enrollTemplates.clear(); - setDeviceStatus(DEVICE_STATUS_IDLE); - clearWatchedServices(); - KLOG_DEBUG() << "EnrollStop"; + message = tr("The pin code cannot be empty!"); + Q_EMIT m_dbusAdaptor->EnrollStatus("", 0, ENROLL_RESULT_FAIL, message); + KLOG_ERROR() << message; + return; + } + else + { + setDeviceStatus(DEVICE_STATUS_DOING_ENROLL); + doingUKeyEnrollStart(m_pin, rebinding); + m_serviceWatcher->addWatchedService(dbusMessage.service()); + auto replyMessage = dbusMessage.createReply(); + QDBusConnection::systemBus().send(replyMessage); } - - auto replyMessage = dbusMessage.createReply(); - QDBusConnection::systemBus().send(replyMessage); } void AuthDevice::onIdentifyStart(const QDBusMessage& dbusMessage, const QString& value) @@ -202,10 +242,7 @@ void AuthDevice::onIdentifyStart(const QDBusMessage& dbusMessage, const QString& return; } - setDeviceStatus(DEVICE_STATUS_DOING_IDENTIFY); - m_doIdentify = true; - - QJsonArray jsonArray = Utils::getValueFromJsonString(value, "feature_ids").toArray(); + QJsonArray jsonArray = Utils::getValueFromJsonString(value, AUTH_DEVICE_JSON_KEY_FEATURE_IDS).toArray(); if (!jsonArray.isEmpty()) { QVariantList varList = jsonArray.toVariantList(); @@ -214,12 +251,16 @@ void AuthDevice::onIdentifyStart(const QDBusMessage& dbusMessage, const QString& m_identifyIDs << var.toString(); } } - auto future = QtConcurrent::run(this, &AuthDevice::acquireFeature); - m_futureWatcher->setFuture(future); - m_serviceWatcher->addWatchedService(dbusMessage.service()); - auto replyMessage = dbusMessage.createReply(); - QDBusConnection::systemBus().send(replyMessage); + QJsonValue ukeyValue = Utils::getValueFromJsonString(value, AUTH_DEVICE_JSON_KEY_UKEY); + if (ukeyValue.isUndefined()) + { + onBioIdentifyStart(dbusMessage); + } + else + { + onUKeyIdentifyStart(dbusMessage, ukeyValue); + } } void AuthDevice::onIdentifyStop(const QDBusMessage& message) @@ -227,7 +268,6 @@ void AuthDevice::onIdentifyStop(const QDBusMessage& message) if (deviceStatus() == DEVICE_STATUS_DOING_IDENTIFY) { acquireFeatureStop(); - m_doIdentify = false; m_identifyIDs.clear(); setDeviceStatus(DEVICE_STATUS_IDLE); clearWatchedServices(); @@ -237,90 +277,49 @@ void AuthDevice::onIdentifyStop(const QDBusMessage& message) QDBusConnection::systemBus().send(replyMessage); } -CHECK_AUTH_WITH_1ARGS(AuthDevice, EnrollStart, onEnrollStart, AUTH_USER_ADMIN, const QString&) -CHECK_AUTH_WITH_1ARGS(AuthDevice, IdentifyStart, onIdentifyStart, AUTH_USER_ADMIN, const QString&) -CHECK_AUTH(AuthDevice, EnrollStop, onEnrollStop, AUTH_USER_ADMIN) -CHECK_AUTH(AuthDevice, IdentifyStop, onIdentifyStop, AUTH_USER_ADMIN) - -QStringList AuthDevice::GetFeatureIDList() +void AuthDevice::onBioIdentifyStart(const QDBusMessage& dbusMessage) { - QStringList featureIDs = FeatureDB::getInstance()->getFeatureIDs(m_idVendor, m_idProduct); - return featureIDs; + setDeviceStatus(DEVICE_STATUS_DOING_IDENTIFY); + auto future = QtConcurrent::run(this, &AuthDevice::acquireFeature); + m_futureWatcher->setFuture(future); + + m_serviceWatcher->addWatchedService(dbusMessage.service()); + auto replyMessage = dbusMessage.createReply(); + QDBusConnection::systemBus().send(replyMessage); } -void AuthDevice::doingEnrollProcess(QByteArray feature) +void AuthDevice::onUKeyIdentifyStart(const QDBusMessage& dbusMessage, QJsonValue ukeyValue) { - if (!m_doEnroll) - { - return; - } QString message; - if (feature.isEmpty()) - { - acquireFeatureFail(); - return; - } + auto jsonObject = ukeyValue.toObject(); + m_pin = jsonObject.value(AUTH_DEVICE_JSON_KEY_PIN).toString(); - int templatesCount = enrollTemplatesFromCache().count(); - if (templatesCount == 0) + if (m_pin.isEmpty()) { - // 第一个指纹模板入录时,检查该指纹是否录入过 - QString featureID = isFeatureEnrolled(feature); - if (featureID.isEmpty()) - { - saveEnrollTemplateToCache(feature); - enrollProcessRetry(); - } - else - { - notifyEnrollProcess(ENROLL_PROCESS_REPEATED_ENROLL, featureID); - internalStopEnroll(); - } - } - else if (templatesCount < needTemplatesCountForEnroll()) - { - // 判断录入时是否录的是同一根手指 - int matchResult = templateMatch(m_enrollTemplates.value(0), feature); - if (matchResult == GENERAL_RESULT_OK) - { - saveEnrollTemplateToCache(feature); - } - else - { - notifyEnrollProcess(ENROLL_PROCESS_INCONSISTENT_FEATURE); - } - enrollProcessRetry(); - } - else if (enrollTemplatesFromCache().count() == needTemplatesCountForEnroll()) - { - enrollTemplateMerge(); - } -} - -void AuthDevice::doingIdentifyProcess(QByteArray feature) -{ - if (!m_doIdentify) - { - KLOG_DEBUG() << "device busy"; - return; - } - if (feature.isEmpty()) - { - acquireFeatureFail(); + message = tr("The pin code cannot be empty!"); + Q_EMIT m_dbusAdaptor->IdentifyStatus("", IDENTIFY_RESULT_NOT_MATCH, message); + KLOG_ERROR() << message; return; } - - QString featureID = identifyFeature(feature, m_identifyIDs); - if (!featureID.isEmpty()) - { - notifyIdentifyProcess(IDENTIFY_PROCESS_MACTCH,featureID); - } else { - notifyIdentifyProcess(IDENTIFY_PROCESS_NO_MATCH); + setDeviceStatus(DEVICE_STATUS_DOING_IDENTIFY); + doingUKeyIdentifyStart(m_pin); + m_serviceWatcher->addWatchedService(dbusMessage.service()); + auto replyMessage = dbusMessage.createReply(); + QDBusConnection::systemBus().send(replyMessage); } +} + +CHECK_AUTH_WITH_1ARGS(AuthDevice, EnrollStart, onEnrollStart, AUTH_USER_ADMIN, const QString&) +CHECK_AUTH_WITH_1ARGS(AuthDevice, IdentifyStart, onIdentifyStart, AUTH_USER_ADMIN, const QString&) +CHECK_AUTH(AuthDevice, EnrollStop, onEnrollStop, AUTH_USER_ADMIN) +CHECK_AUTH(AuthDevice, IdentifyStop, onIdentifyStop, AUTH_USER_ADMIN) - internalStopIdentify(); +QStringList AuthDevice::GetFeatureIDList() +{ + QStringList featureIDs = FeatureDB::getInstance()->getFeatureIDs(m_idVendor, m_idProduct); + return featureIDs; } void AuthDevice::internalStopEnroll() @@ -328,7 +327,6 @@ void AuthDevice::internalStopEnroll() if (deviceStatus() == DEVICE_STATUS_DOING_ENROLL) { acquireFeatureStop(); - m_doEnroll = false; m_enrollTemplates.clear(); setDeviceStatus(DEVICE_STATUS_IDLE); clearWatchedServices(); @@ -341,7 +339,6 @@ void AuthDevice::internalStopIdentify() if (deviceStatus() == DEVICE_STATUS_DOING_IDENTIFY) { acquireFeatureStop(); - m_doIdentify = false; m_identifyIDs.clear(); setDeviceStatus(DEVICE_STATUS_IDLE); clearWatchedServices(); @@ -349,28 +346,15 @@ void AuthDevice::internalStopIdentify() } } -void AuthDevice::enrollProcessRetry() -{ - Q_EMIT this->retry(); -} - -void AuthDevice::saveEnrollTemplateToCache(QByteArray enrollTemplate) +void AuthDevice::handleAcquiredFeature() { - if (!enrollTemplate.isEmpty()) + QByteArray feature = m_futureWatcher->result(); + if (feature.isEmpty()) { - m_enrollTemplates << enrollTemplate; - KLOG_DEBUG() << "enroll template:" << enrollTemplate; - notifyEnrollProcess(ENROLL_PROCESS_PASS); + acquireFeatureFail(); + return; } -} - -QByteArrayList AuthDevice::enrollTemplatesFromCache() -{ - return m_enrollTemplates; -} -void AuthDevice::handleAcquiredFeature() -{ switch (deviceStatus()) { case DEVICE_STATUS_DOING_ENROLL: diff --git a/src/device/auth-device.h b/src/device/auth-device.h index 03997bc..0d9a9c8 100644 --- a/src/device/auth-device.h +++ b/src/device/auth-device.h @@ -14,7 +14,6 @@ #pragma once -// #include "auth_device_adaptor.h" #include #include #include @@ -22,12 +21,13 @@ #include #include "auth-enum.h" #include "kiran-auth-device-i.h" +#include class AuthDeviceAdaptor; namespace Kiran { -typedef void* Handle; +typedef void *Handle; class BDriver; class AuthDevice : public QObject, protected QDBusContext @@ -40,19 +40,21 @@ class AuthDevice : public QObject, protected QDBusContext public: explicit AuthDevice(QObject *parent = nullptr); + virtual ~AuthDevice(); bool init(); virtual bool initDevice() = 0; virtual BDriver *getDriver() = 0; - QDBusObjectPath getObjectPath() { return m_objectPath; }; + QDBusObjectPath getObjectPath() { return m_objectPath; }; QString deviceID() { return m_deviceID; }; QString deviceDriver() { return m_deviceDriver; }; int deviceType() { return m_deviceType; }; int deviceStatus() { return m_deviceStatus; } - QString deviceName() { return m_deviceName; }; + DeviceInfo deviceInfo(); + void setDeviceType(DeviceType deviceType); void setDeviceStatus(DeviceStatus deviceStatus); void setDeviceName(const QString &deviceName); @@ -71,24 +73,6 @@ protected: virtual void acquireFeatureStop() = 0; virtual void acquireFeatureFail() = 0; - virtual void doingEnrollProcess(QByteArray feature); - virtual void doingIdentifyProcess(QByteArray feature); - - virtual void enrollProcessFail(const QString &featureID){}; - virtual void enrollProcessRetry(); - virtual void enrollTemplateMerge() = 0; - - virtual QString isFeatureEnrolled(QByteArray fpTemplate) = 0; - virtual QString identifyFeature(QByteArray feature, QStringList featureIDs) = 0; - virtual int templateMatch(QByteArray fpTemplate1, QByteArray fpTemplate2) = 0; - - virtual void saveEnrollTemplateToCache(QByteArray enrollTemplate); - QByteArrayList enrollTemplatesFromCache(); - - virtual void notifyEnrollProcess(EnrollProcess process, const QString &featureID = QString()) = 0; - virtual void notifyIdentifyProcess(IdentifyProcess process, const QString &featureID = QString()) = 0; - virtual int needTemplatesCountForEnroll() = 0; - private Q_SLOTS: void onNameLost(const QString &serviceName); void handleAcquiredFeature(); @@ -96,8 +80,8 @@ private Q_SLOTS: protected: void clearWatchedServices(); - void internalStopEnroll(); - void internalStopIdentify(); + virtual void internalStopEnroll(); + virtual void internalStopIdentify(); private: void registerDBusObject(); @@ -106,33 +90,42 @@ private: void onEnrollStart(const QDBusMessage &message, const QString &extraInfo); void onEnrollStop(const QDBusMessage &message); + void onBioEnrollStart(const QDBusMessage &dbusMessage); + void onUKeyEnrollStart(const QDBusMessage &dbusMessage, QJsonValue jsonValue); + void onIdentifyStart(const QDBusMessage &message, const QString &value); void onIdentifyStop(const QDBusMessage &message); + void onBioIdentifyStart(const QDBusMessage &dbusMessage); + void onUKeyIdentifyStart(const QDBusMessage &dbusMessage, QJsonValue jsonValue); + + virtual void doingEnrollProcess(QByteArray feature){}; + virtual void doingIdentifyProcess(QByteArray feature){}; + + virtual void doingUKeyEnrollStart(const QString &pin, bool rebinding = false){}; + virtual void doingUKeyIdentifyStart(const QString &pin){}; Q_SIGNALS: void retry(); protected: - QString m_deviceID; QString m_deviceDriver; + QSharedPointer m_dbusAdaptor; + bool m_doAcquire = true; + QStringList m_identifyIDs; + QByteArrayList m_enrollTemplates; + QSharedPointer> m_futureWatcher; + QString m_pin; + +private: + QString m_deviceID; int m_deviceType; int m_deviceStatus; QString m_deviceName; QString m_idVendor; QString m_idProduct; QDBusObjectPath m_objectPath; - QDBusServiceWatcher *m_serviceWatcher; - AuthDeviceAdaptor *m_dbusAdaptor; + QSharedPointer m_serviceWatcher; - bool m_doAcquire = true; - bool m_doIdentify = true; - bool m_doEnroll = true; - QStringList m_identifyIDs; - QByteArrayList m_enrollTemplates; - - QFutureWatcher *m_futureWatcher; - -private: /** * 用于注册com.kylinsec.Kiran.AuthDevice.Device服务时的编号 * 在生成AuthDevice对象,注册dbus服务成功后,数值加1 diff --git a/src/device/bio-device.cpp b/src/device/bio-device.cpp new file mode 100644 index 0000000..7342928 --- /dev/null +++ b/src/device/bio-device.cpp @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiran-biometrics is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: luoqing + */ + +#include "bio-device.h" +#include +namespace Kiran +{ +BioDevice::BioDevice(QObject *parent) : AuthDevice{parent} +{ +} + +BioDevice::~BioDevice() +{ +} + +void BioDevice::doingEnrollProcess(QByteArray feature) +{ + int templatesCount = enrollTemplatesFromCache().count(); + if (templatesCount == 0) + { + // 第一个指纹模板入录时,检查该指纹是否录入过 + QString featureID = isFeatureEnrolled(feature); + if (featureID.isEmpty()) + { + saveEnrollTemplateToCache(feature); + enrollProcessRetry(); + } + else + { + notifyEnrollProcess(ENROLL_PROCESS_REPEATED_ENROLL, featureID); + internalStopEnroll(); + } + } + else if (templatesCount < mergeTemplateCount()) + { + // 判断录入时是否录的是同一根手指 + int matchResult = templateMatch(m_enrollTemplates.value(0), feature); + if (matchResult == GENERAL_RESULT_OK) + { + saveEnrollTemplateToCache(feature); + } + else + { + notifyEnrollProcess(ENROLL_PROCESS_INCONSISTENT_FEATURE); + } + enrollProcessRetry(); + } + else if (enrollTemplatesFromCache().count() == mergeTemplateCount()) + { + enrollTemplateMerge(); + } +} + +void BioDevice::doingIdentifyProcess(QByteArray feature) +{ + QString featureID = identifyFeature(feature, m_identifyIDs); + if (!featureID.isEmpty()) + { + notifyIdentifyProcess(IDENTIFY_PROCESS_MACTCH, featureID); + } + else + { + notifyIdentifyProcess(IDENTIFY_PROCESS_NO_MATCH); + } + + internalStopIdentify(); +} +QByteArrayList BioDevice::enrollTemplatesFromCache() +{ + return m_enrollTemplates; +} + +void BioDevice::saveEnrollTemplateToCache(QByteArray enrollTemplate) +{ + if (!enrollTemplate.isEmpty()) + { + m_enrollTemplates << enrollTemplate; + KLOG_DEBUG() << "enroll template:" << enrollTemplate; + notifyEnrollProcess(ENROLL_PROCESS_PASS); + } +} + +void BioDevice::enrollProcessRetry() +{ + Q_EMIT this->retry(); +} + +QString BioDevice::isFeatureEnrolled(QByteArray fpTemplate) +{ + return identifyFeature(fpTemplate, QStringList()); +} + +} // namespace Kiran \ No newline at end of file diff --git a/src/device/bio-device.h b/src/device/bio-device.h new file mode 100644 index 0000000..c55aa84 --- /dev/null +++ b/src/device/bio-device.h @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiran-biometrics is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: luoqing + */ +#pragma once +#include "auth-device.h" + +namespace Kiran +{ +class BioDevice : public AuthDevice +{ + Q_OBJECT +public: + explicit BioDevice(QObject *parent = nullptr); + ~BioDevice(); + +protected: + void doingEnrollProcess(QByteArray feature) override; + void doingIdentifyProcess(QByteArray feature) override; + + virtual void enrollProcessRetry(); + + virtual void enrollTemplateMerge() = 0; + virtual int templateMatch(QByteArray fpTemplate1, QByteArray fpTemplate2) = 0; + virtual QString identifyFeature(QByteArray feature, QStringList featureIDs) = 0; + + virtual int mergeTemplateCount() = 0; + virtual void notifyEnrollProcess(EnrollProcess process, const QString &featureID = QString()) = 0; + virtual void notifyIdentifyProcess(IdentifyProcess process, const QString &featureID = QString()) = 0; + + QByteArrayList enrollTemplatesFromCache(); + virtual void saveEnrollTemplateToCache(QByteArray enrollTemplate); + +private: + virtual QString isFeatureEnrolled(QByteArray fpTemplate); +}; + +} // namespace Kiran diff --git a/src/device/finger-vein/fv-sd-device.cpp b/src/device/finger-vein/fv-sd-device.cpp index 43faad7..5ae6605 100644 --- a/src/device/finger-vein/fv-sd-device.cpp +++ b/src/device/finger-vein/fv-sd-device.cpp @@ -111,7 +111,7 @@ struct DriverLib TGSetDevLedFunc TGSetDevLed; }; -FVSDDevice::FVSDDevice(QObject *parent) : AuthDevice{parent}, +FVSDDevice::FVSDDevice(QObject *parent) : BioDevice{parent}, m_driverLib(nullptr), m_libProcessHandle(nullptr), m_libComHandle(nullptr) @@ -125,17 +125,10 @@ FVSDDevice::~FVSDDevice() if (!deviceID().isEmpty()) { acquireFeatureStop(); - m_futureWatcher->deleteLater(); KLOG_DEBUG() << "TGGetDevStatus():" << m_driverLib->TGGetDevStatus(); m_driverLib->TGCloseDev(); } - if (m_driverLib) - { - delete m_driverLib; - m_driverLib = nullptr; - } - if (m_libComHandle) { dlclose(m_libComHandle); @@ -166,7 +159,7 @@ bool FVSDDevice::loadLib() return false; } - m_driverLib = new DriverLib; + m_driverLib = QSharedPointer(new DriverLib); m_driverLib->TGInitFVProcess = (TGInitFVProcessFunc)dlsym(m_libProcessHandle, "TGInitFVProcess"); m_driverLib->TGImgExtractFeatureVerify = (TGImgExtractFeatureVerifyFunc)dlsym(m_libProcessHandle, "TGImgExtractFeatureVerify"); m_driverLib->TGFeaturesFusionTmpl = (TGFeaturesFusionTmplFunc)dlsym(m_libProcessHandle, "TGFeaturesFusionTmpl"); @@ -221,11 +214,11 @@ bool FVSDDevice::initDevice() } KLOG_DEBUG() << "Device opened successfully:" << ret; - ret = m_driverLib->TGGetDevFW(fw); + m_driverLib->TGGetDevFW(fw); KLOG_DEBUG() << "Get firmware version:" << fw; - ret = m_driverLib->TGGetDevSN(sn); + m_driverLib->TGGetDevSN(sn); KLOG_DEBUG() << "Obtain device SN number:" << sn; - ret = m_driverLib->TGPlayDevVoice(VOICE_VOLUME1); + m_driverLib->TGPlayDevVoice(VOICE_VOLUME1); return true; } @@ -291,7 +284,7 @@ QByteArray FVSDDevice::acquireFeature() void FVSDDevice::acquireFeatureStop() { m_driverLib->TGCancelGetImage(); - if (m_futureWatcher != nullptr) + if (m_futureWatcher.data() != nullptr) { m_futureWatcher->waitForFinished(); } @@ -357,9 +350,7 @@ void FVSDDevice::enrollTemplateMerge() { QString id = QCryptographicHash::hash(mergedTemplate, QCryptographicHash::Md5).toHex(); - DeviceInfo deviceInfo; - deviceInfo.idVendor = m_idVendor; - deviceInfo.idProduct = m_idProduct; + DeviceInfo deviceInfo = this->deviceInfo(); bool save = FeatureDB::getInstance()->addFeature(id, mergedTemplate, deviceInfo); if (save) { @@ -396,9 +387,10 @@ QString FVSDDevice::identifyFeature(QByteArray feature, QStringList featureIDs) { QList saveList; QString featureID; + DeviceInfo deviceInfo = this->deviceInfo(); if (featureIDs.isEmpty()) { - saveList = FeatureDB::getInstance()->getFeatures(m_idVendor, m_idProduct); + saveList = FeatureDB::getInstance()->getFeatures(deviceInfo.idVendor, deviceInfo.idProduct); } else { @@ -481,7 +473,7 @@ BDriver *FVSDDevice::getDriver() return nullptr; } -int FVSDDevice::needTemplatesCountForEnroll() +int FVSDDevice::mergeTemplateCount() { return TEMPLATE_FV_NUM; } diff --git a/src/device/finger-vein/fv-sd-device.h b/src/device/finger-vein/fv-sd-device.h index d1fa8c7..09b372b 100644 --- a/src/device/finger-vein/fv-sd-device.h +++ b/src/device/finger-vein/fv-sd-device.h @@ -14,7 +14,8 @@ #pragma once #include -#include "device/auth-device.h" +#include "device/bio-device.h" +#include namespace Kiran { @@ -25,7 +26,7 @@ enum ExtractFeatureMode }; struct DriverLib; -class FVSDDevice : public AuthDevice +class FVSDDevice : public BioDevice { Q_OBJECT public: @@ -53,13 +54,14 @@ private: QByteArray getFeatureFromImage(QByteArray image, ExtractFeatureMode mode); - int needTemplatesCountForEnroll() override; + int mergeTemplateCount() override; int templateMatch(QByteArray fpTemplate1, QByteArray fpTemplate2) override; void notifyEnrollProcess(EnrollProcess process, const QString &featureID = QString()) override; void notifyIdentifyProcess(IdentifyProcess process, const QString &featureID = QString()) override; private: - DriverLib *m_driverLib; + QSharedPointer m_driverLib; + Handle m_libProcessHandle; Handle m_libComHandle; }; diff --git a/src/device/fingerprint/fp-device.cpp b/src/device/fingerprint/fp-device.cpp index d610844..cddaadd 100644 --- a/src/device/fingerprint/fp-device.cpp +++ b/src/device/fingerprint/fp-device.cpp @@ -17,7 +17,7 @@ namespace Kiran { FPDevice::FPDevice(QObject *parent) - : AuthDevice{parent} + : BioDevice{parent} { } diff --git a/src/device/fingerprint/fp-device.h b/src/device/fingerprint/fp-device.h index abbbcd1..7a792ba 100644 --- a/src/device/fingerprint/fp-device.h +++ b/src/device/fingerprint/fp-device.h @@ -13,11 +13,11 @@ */ #pragma once -#include "device/auth-device.h" +#include "device/bio-device.h" namespace Kiran { -class FPDevice : public AuthDevice +class FPDevice : public BioDevice { public: explicit FPDevice(QObject *parent = nullptr); diff --git a/src/device/fingerprint/fp-zk-device.cpp b/src/device/fingerprint/fp-zk-device.cpp index 1862446..8236787 100644 --- a/src/device/fingerprint/fp-zk-device.cpp +++ b/src/device/fingerprint/fp-zk-device.cpp @@ -140,18 +140,15 @@ FPZKDevice::FPZKDevice(QObject* parent) FPZKDevice::~FPZKDevice() { acquireFeatureStop(); - m_futureWatcher->deleteLater(); if (m_hDBCache) { m_driverLib->ZKFPM_DBFree(m_hDBCache); m_hDBCache = NULL; } - if (m_driverLib) + if (m_driverLib.data()) { m_driverLib->ZKFPM_Terminate(); // 释放资源 - delete m_driverLib; - m_driverLib = nullptr; } if (m_libHandle) @@ -193,7 +190,7 @@ bool FPZKDevice::loadLib() return false; } - m_driverLib = new DriverLib; + m_driverLib = QSharedPointer(new DriverLib); m_driverLib->ZKFPM_Init = (T_ZKFPM_Init)dlsym(m_libHandle, "ZKFPM_Init"); if (NULL == m_driverLib->ZKFPM_Init) { @@ -323,7 +320,7 @@ QByteArray FPZKDevice::acquireFeature() void FPZKDevice::acquireFeatureStop() { m_doAcquire = false; - if (m_futureWatcher != nullptr) + if (m_futureWatcher.data() != nullptr) { m_futureWatcher->waitForFinished(); } @@ -374,18 +371,15 @@ int FPZKDevice::templateMatch(QByteArray fpTemplate1, QByteArray fpTemplate2) return score > 0 ? GENERAL_RESULT_OK : GENERAL_RESULT_FAIL; } -QString FPZKDevice::isFeatureEnrolled(QByteArray fpTemplate) -{ - return identifyFeature(fpTemplate, QStringList()); -} QString FPZKDevice::identifyFeature(QByteArray fpTemplate, QStringList featureIDs) { QList saveList; QString featureID; + DeviceInfo info = this->deviceInfo(); if (featureIDs.isEmpty()) { - saveList = FeatureDB::getInstance()->getFeatures(m_idVendor, m_idProduct); + saveList = FeatureDB::getInstance()->getFeatures(info.idVendor, info.idProduct); } else { @@ -416,9 +410,7 @@ QString FPZKDevice::identifyFeature(QByteArray fpTemplate, QStringList featureID bool FPZKDevice::saveFPrintTemplate(QByteArray fpTemplate, const QString& featureID) { - DeviceInfo deviceInfo; - deviceInfo.idVendor = m_idVendor; - deviceInfo.idProduct = m_idProduct; + DeviceInfo deviceInfo = this->deviceInfo(); bool save = FeatureDB::getInstance()->addFeature(featureID, fpTemplate, deviceInfo); return save; } @@ -469,7 +461,7 @@ void FPZKDevice::enrollTemplateMerge() internalStopEnroll(); } -int FPZKDevice::needTemplatesCountForEnroll() +int FPZKDevice::mergeTemplateCount() { return FP_ZK_MEGER_TEMPLATE_COUNT; } diff --git a/src/device/fingerprint/fp-zk-device.h b/src/device/fingerprint/fp-zk-device.h index 30e4e93..3379e2e 100644 --- a/src/device/fingerprint/fp-zk-device.h +++ b/src/device/fingerprint/fp-zk-device.h @@ -14,6 +14,7 @@ #pragma once #include +#include #include "auth-enum.h" #include "fp-device.h" @@ -39,8 +40,8 @@ private: void acquireFeatureStop() override; void acquireFeatureFail() override; void enrollTemplateMerge() override; - int needTemplatesCountForEnroll() override; - QString isFeatureEnrolled(QByteArray fpTemplate) override; + int mergeTemplateCount() override; + void notifyEnrollProcess(EnrollProcess process, const QString& featureID = QString()) override; void notifyIdentifyProcess(IdentifyProcess process, const QString& featureID = QString()) override; @@ -63,6 +64,6 @@ private: private: Handle m_libHandle; Handle m_hDBCache; - DriverLib* m_driverLib; + QSharedPointer m_driverLib; }; } // namespace Kiran diff --git a/src/device/ukey/ukey-ft-device.cpp b/src/device/ukey/ukey-ft-device.cpp new file mode 100644 index 0000000..38017c6 --- /dev/null +++ b/src/device/ukey/ukey-ft-device.cpp @@ -0,0 +1,400 @@ +/** + * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiran-biometrics is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: luoqing + */ + +#include "ukey-ft-device.h" +#include +#include +#include +#include "auth-enum.h" +#include "auth_device_adaptor.h" +#include "feature-db.h" + +namespace Kiran +{ +#define FT_UKEY_DRIVER_LIB "libes_3000gm.so" +#define UKEY_APP_NAME "KIRAN-AUTHENTICATION-DEVICES" +#define UKEY_CONTAINER_NAME "1003-3001" + +UKeyFTDevice::UKeyFTDevice(QObject *parent) : AuthDevice{parent}, + m_libHandle(nullptr), + m_appHandle(nullptr), + m_devHandle(nullptr), + m_containerHandle(nullptr) +{ + setDeviceType(DEVICE_TYPE_UKey); + setDeviceDriver(FT_UKEY_DRIVER_LIB); +} + +UKeyFTDevice::~UKeyFTDevice() +{ + m_driver->closeContainer(m_containerHandle); + m_driver->closeApplication(m_appHandle); + m_driver->disConnectDev(m_devHandle); + m_containerHandle = nullptr; + m_appHandle = nullptr; + m_devHandle = nullptr; +} + +bool UKeyFTDevice::initDevice() +{ + m_driver = QSharedPointer(new UKeySKFDriver()); + if (!m_driver->loadLibrary(FT_UKEY_DRIVER_LIB)) + { + return false; + } + m_devHandle = m_driver->connectDev(); + if (!m_devHandle) + { + KLOG_DEBUG() << ""; + return false; + } + + return true; +} + +BDriver *UKeyFTDevice::getDriver() +{ + return nullptr; +} + +void UKeyFTDevice::doingUKeyEnrollStart(const QString &pin, bool rebinding) +{ + if (rebinding) + { + ULONG ulReval = m_driver->devAuth(m_devHandle); + if (ulReval == SAR_OK) + { + m_driver->deleteAllApplication(m_devHandle); + DeviceInfo deviceInfo = this->deviceInfo(); + QStringList idList = FeatureDB::getInstance()->getFeatureIDs(deviceInfo.idVendor, deviceInfo.idProduct); + Q_FOREACH (auto id, idList) + { + FeatureDB::getInstance()->deleteFeature(id); + } + bindingCurrentUser(); + } + else + { + KLOG_ERROR() << "rebinding failed"; + } + } + else + { + bindingCurrentUser(); + } + internalStopEnroll(); +} + +void UKeyFTDevice::bindingCurrentUser() +{ + if (isExistPublicKey()) + { + notifyUKeyEnrollProcess(ENROLL_PROCESS_REPEATED_ENROLL); + return; + } + + ECCPUBLICKEYBLOB publicKey = genKeyPair(); + if (publicKey.BitLen != 0) + { + /** + * 存入PublicKey,生成FID,并返回FID,FID标识PublicKey + * 不用保存PublicKey和systemUser的关系,目前只有一个用户 + */ + QByteArray keyFeature; + QByteArray xCoordinateArray((char *)publicKey.XCoordinate, 64); + QByteArray yCoordinateArray((char *)publicKey.YCoordinate, 64); + keyFeature.append(publicKey.BitLen); + keyFeature.append(xCoordinateArray); + keyFeature.append(yCoordinateArray); + KLOG_DEBUG() << "keyFeature:" << keyFeature; + + QString featureID = QCryptographicHash::hash(keyFeature, QCryptographicHash::Md5).toHex(); + DeviceInfo deviceInfo = this->deviceInfo(); + + if (FeatureDB::getInstance()->addFeature(featureID, keyFeature, deviceInfo)) + { + notifyUKeyEnrollProcess(ENROLL_PROCESS_SUCCESS, SAR_OK, featureID); + } + else + { + KLOG_DEBUG() << "save feature fail"; + notifyUKeyEnrollProcess(ENROLL_PROCESS_SAVE_FAIL); + } + } + else + { + notifyUKeyEnrollProcess(ENROLL_PROCESS_SAVE_FAIL); + } +} + +bool UKeyFTDevice::isExistPublicKey() +{ + DeviceInfo deviceInfo = this->deviceInfo(); + auto features = FeatureDB::getInstance()->getFeatures(deviceInfo.idVendor, deviceInfo.idProduct); + if (features.count() != 0) + { + return true; + } + else + { + return false; + } +} + +ECCPUBLICKEYBLOB UKeyFTDevice::genKeyPair() +{ + ECCPUBLICKEYBLOB publicKey = {0}; + if (!isExistsApplication(UKEY_APP_NAME)) + { + // NOTE:必须通过设备认证后才能在设备内创建和删除应用 + ULONG ulReval = m_driver->devAuth(m_devHandle); + if (ulReval != SAR_OK) + { + KLOG_ERROR() << "Device auth failure: " << m_driver->getErrorReason(ulReval); + return publicKey; + } + else + { + KLOG_DEBUG() << "device auth success"; + } + m_driver->deleteAllApplication(m_devHandle); + KLOG_DEBUG() << "m_devHandle:" << m_devHandle; + KLOG_DEBUG() << "m_pin:" << m_pin; + m_appHandle = m_driver->createApplication(m_devHandle, m_pin, UKEY_APP_NAME); + m_containerHandle = m_driver->createContainer(m_appHandle, m_pin, UKEY_CONTAINER_NAME, &m_retryCount); + if (!m_appHandle || !m_containerHandle) + { + return publicKey; + } + } + + m_appHandle = m_driver->onOpenApplication(m_devHandle, (LPSTR)UKEY_APP_NAME); + m_containerHandle = m_driver->onOpenContainer(m_appHandle, m_pin, UKEY_CONTAINER_NAME, &m_retryCount); + if (!m_appHandle || !m_containerHandle) + { + return publicKey; + } + + ULONG ret = m_driver->genECCKeyPair(m_containerHandle, &publicKey); + if (ret == SAR_OK) + { + KLOG_DEBUG() << "gen ecc key pair success"; + } + else + { + KLOG_ERROR() << "gen ecc key pair failed:" << m_driver->getErrorReason(ret); + } + + return publicKey; +} + +bool UKeyFTDevice::isExistsApplication(const QString &appName) +{ + QString appNames = m_driver->enumApplication(m_devHandle); + KLOG_DEBUG() << "enum app names:" << appNames; + if (appNames.contains(appName)) + { + return true; + } + return false; +} + +void UKeyFTDevice::doingUKeyIdentifyStart(const QString &pin) +{ + QList saveList; + DeviceInfo deviceInfo = this->deviceInfo(); + if (m_identifyIDs.isEmpty()) + { + saveList = FeatureDB::getInstance()->getFeatures(deviceInfo.idVendor, deviceInfo.idProduct); + } + else + { + Q_FOREACH (auto id, m_identifyIDs) + { + QByteArray feature = FeatureDB::getInstance()->getFeature(id); + if (!feature.isEmpty()) + saveList << feature; + } + } + + if (saveList.count() != 0) + { + for (int j = 0; j < saveList.count(); j++) + { + auto saveTemplate = saveList.value(j); + identifyKeyFeature(saveTemplate); + } + } + else + { + KLOG_DEBUG() << "no found feature id"; + } + + internalStopIdentify(); +} + +void UKeyFTDevice::internalStopEnroll() +{ + if (deviceStatus() == DEVICE_STATUS_DOING_ENROLL) + { + m_driver->closeContainer(m_containerHandle); + m_driver->closeApplication(m_appHandle); + acquireFeatureStop(); + m_enrollTemplates.clear(); + setDeviceStatus(DEVICE_STATUS_IDLE); + clearWatchedServices(); + KLOG_DEBUG() << "stop Enroll"; + } +} + +void UKeyFTDevice::internalStopIdentify() +{ + if (deviceStatus() == DEVICE_STATUS_DOING_IDENTIFY) + { + m_driver->closeContainer(m_containerHandle); + m_driver->closeApplication(m_appHandle); + acquireFeatureStop(); + m_identifyIDs.clear(); + setDeviceStatus(DEVICE_STATUS_IDLE); + clearWatchedServices(); + KLOG_DEBUG() << "stopIdentify"; + } +} + +void UKeyFTDevice::identifyKeyFeature(QByteArray keyFeature) +{ + m_appHandle = m_driver->onOpenApplication(m_devHandle, (LPSTR)UKEY_APP_NAME); + if (m_appHandle == nullptr) + { + notifyUKeyIdentifyProcess(IDENTIFY_PROCESS_NO_MATCH); + return; + } + + m_containerHandle = m_driver->onOpenContainer(m_appHandle, m_pin, UKEY_CONTAINER_NAME, &m_retryCount); + if (m_containerHandle == nullptr) + { + notifyUKeyIdentifyProcess(IDENTIFY_PROCESS_NO_MATCH); + return; + } + + ECCSIGNATUREBLOB Signature = {0}; + ULONG ret = m_driver->authSignData(m_containerHandle, m_devHandle, Signature); + if (ret != SAR_OK) + { + KLOG_DEBUG() << "auth sign data failed:" << m_driver->getErrorReason(ret); + notifyUKeyIdentifyProcess(IDENTIFY_PROCESS_NO_MATCH, ret); + return; + } + + ECCPUBLICKEYBLOB eccPubKey; + eccPubKey.BitLen = keyFeature.left(1).at(0); + auto xCoordinateArray = keyFeature.mid(1, sizeof(eccPubKey.XCoordinate)); + auto yCoordinateArray = keyFeature.mid(sizeof(eccPubKey.XCoordinate) + 1); + + memcpy(eccPubKey.XCoordinate, (unsigned char *)xCoordinateArray.data(), ECC_MAX_XCOORDINATE_BITS_LEN / 8); + memcpy(eccPubKey.YCoordinate, (unsigned char *)yCoordinateArray.data(), ECC_MAX_YCOORDINATE_BITS_LEN / 8); + + ret = m_driver->verifyData(m_devHandle, Signature, eccPubKey); + if (ret != SAR_OK) + { + KLOG_DEBUG() << "verify data failed:" << m_driver->getErrorReason(ret); + notifyUKeyIdentifyProcess(IDENTIFY_PROCESS_NO_MATCH, ret); + } + else + { + notifyUKeyIdentifyProcess(IDENTIFY_PROCESS_MACTCH); + } +} + +QByteArray UKeyFTDevice::acquireFeature() +{ + return QByteArray(); +} + +void UKeyFTDevice::acquireFeatureStop() +{ +} +void UKeyFTDevice::acquireFeatureFail() +{ +} + +void UKeyFTDevice::notifyUKeyEnrollProcess(EnrollProcess process, ULONG error, const QString &featureID) +{ + QString message; + switch (process) + { + case ENROLL_PROCESS_SUCCESS: + message = tr("Successed binding user"); + Q_EMIT m_dbusAdaptor->EnrollStatus(featureID, 100, ENROLL_RESULT_COMPLETE, message); + break; + case ENROLL_PROCESS_SAVE_FAIL: + message = tr("Binding user failed"); + Q_EMIT m_dbusAdaptor->EnrollStatus("", 0, ENROLL_RESULT_FAIL, message); + break; + case ENROLL_PROCESS_REPEATED_ENROLL: + message = tr("UKey has been bound"); + Q_EMIT m_dbusAdaptor->EnrollStatus("", 0, ENROLL_RESULT_UKEY_EXIST_BINDING, message); + default: + break; + } + if (!message.isEmpty()) + { + if (!featureID.isEmpty()) + { + KLOG_DEBUG() << QString("%1, feature id:%2").arg(message).arg(featureID); + } + else + { + KLOG_DEBUG() << message; + } + } +} + +void UKeyFTDevice::notifyUKeyIdentifyProcess(IdentifyProcess process, ULONG error, const QString &featureID) +{ + QString message, reason; + if (error != SAR_OK) + { + reason = m_driver->getErrorReason(error); + KLOG_DEBUG() << "fail reason:" << reason; + } + + KLOG_DEBUG() << "m_retryCount:" << m_retryCount; + switch (process) + { + case IDENTIFY_PROCESS_NO_MATCH: + message = tr("identify fail!"); + // 目前只需要返回有关pin码的错误信息 + if (reason.contains("pin")) + { + message.append(reason); + } + message.append(QString(",remaining retry count: %1").arg(m_retryCount)); + Q_EMIT m_dbusAdaptor->IdentifyStatus("", IDENTIFY_RESULT_NOT_MATCH, message); + break; + case IDENTIFY_PROCESS_MACTCH: + message = tr("identify ukey success"); + Q_EMIT m_dbusAdaptor->IdentifyStatus(featureID, IDENTIFY_RESULT_MATCH, message); + break; + default: + break; + } + + if (!message.isEmpty()) + { + KLOG_DEBUG() << QString("%1, feature id:%2").arg(message).arg(featureID); + } +} + +} // namespace Kiran diff --git a/src/device/ukey/ukey-ft-device.h b/src/device/ukey/ukey-ft-device.h new file mode 100644 index 0000000..901393b --- /dev/null +++ b/src/device/ukey/ukey-ft-device.h @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiran-biometrics is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: luoqing + */ + +#pragma once +#include +#include "device/auth-device.h" +#include "driver/ukey/ukey-skf-driver.h" +#include "ukey-skf.h" +#include + +namespace Kiran +{ +struct DriverLib; + +class UKeyFTDevice : public AuthDevice +{ + Q_OBJECT +public: + explicit UKeyFTDevice(QObject *parent = nullptr); + ~UKeyFTDevice(); + + bool initDevice() override; + BDriver *getDriver() override; + +private: + void doingUKeyEnrollStart(const QString &pin, bool rebinding = false) override; + void doingUKeyIdentifyStart(const QString &pin) override; + + void internalStopEnroll() override; + void internalStopIdentify() override; + + void identifyKeyFeature(QByteArray keyFeature); + + bool isExistPublicKey(); + void bindingCurrentUser(); + ECCPUBLICKEYBLOB genKeyPair(); + + bool isExistsApplication(const QString &appName); + + void notifyUKeyEnrollProcess(EnrollProcess process, ULONG error = SAR_OK, const QString &featureID = QString()); + void notifyUKeyIdentifyProcess(IdentifyProcess process, ULONG error = SAR_OK, const QString &featureID = QString()); + + QByteArray acquireFeature() override; + void acquireFeatureStop() override; + void acquireFeatureFail() override; + +private: + Handle m_libHandle; + DEVHANDLE m_devHandle; + HAPPLICATION m_appHandle; + HCONTAINER m_containerHandle; + ULONG m_retryCount = 1000000; + + QSharedPointer m_driver; +}; + +} // namespace Kiran diff --git a/src/driver/ukey/ukey-skf-driver.cpp b/src/driver/ukey/ukey-skf-driver.cpp new file mode 100644 index 0000000..b81bda4 --- /dev/null +++ b/src/driver/ukey/ukey-skf-driver.cpp @@ -0,0 +1,516 @@ +/** + * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiran-biometrics is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: luoqing + */ +#include "ukey-skf-driver.h" +#include +#include +#include +#include + +namespace Kiran +{ +// 签名者ID +#define CONF_DEFAULT_KEY_PUC_ID "PucId" +#define CONF_DEFAULT_KEY_DEV_KEY "DevKey" + +#define CONF_DEFAULT_KEY_ADMIN_PINCODE "AdminPinCode" +#define CONF_DEFAULT_KEY_USER_PINCODE "UserPinCode" + +#define SIGN_DATA "kiran-authentication-devices" + +#define UKEY_DEFAULT_CONFIG "/etc/kiran-authentication-devices-sdk/ukey-skf.conf" +#define ADMIN_PIN_RETRY_COUNT 10 +#define USER_PIN_RETRY_COUNT 10 + +extern "C" +{ + typedef ULONG (*SKF_EnumDev_Func)(BOOL bPresent, LPSTR szNameList, ULONG *pulSize); + typedef ULONG (*SKF_ConnectDev_Func)(LPSTR szName, DEVHANDLE *phDev); + typedef ULONG (*SKF_DisConnectDev_Func)(DEVHANDLE hDev); + typedef ULONG (*SKF_GetDevState_Func)(LPSTR szDevName, ULONG *pulDevState); + typedef ULONG (*SKF_GetDevInfo_Func)(DEVHANDLE hDev, DEVINFO *pDevInfo); + typedef ULONG (*SKF_SetLabel_Func)(DEVHANDLE hDev, LPSTR szLabel); + typedef ULONG (*SKF_OpenApplication_Func)(DEVHANDLE hDev, LPSTR szAppName, HAPPLICATION *phApplication); + typedef ULONG (*SKF_VerifyPIN_Func)(HAPPLICATION hApplication, ULONG ulPINType, LPSTR szPIN, ULONG *pulRetryCount); + typedef ULONG (*SKF_OpenContainer_Func)(HAPPLICATION hApplication, LPSTR szContainerName, HCONTAINER *phContainer); + typedef ULONG (*SKF_GenECCKeyPair_Func)(HCONTAINER hContainer, ULONG ulAlgId, ECCPUBLICKEYBLOB *pBlob); + typedef ULONG (*SKF_CloseContainer_Func)(HCONTAINER hContainer); + typedef ULONG (*SKF_CloseApplication_Func)(HAPPLICATION hApplication); + typedef ULONG (*SKF_CreateApplication_Func)(DEVHANDLE hDev, LPSTR szAppName, LPSTR szAdminPin, + DWORD dwAdminPinRetryCount, LPSTR szUserPin, DWORD dwUserPinRetryCount, + DWORD dwCreateFileRights, HAPPLICATION *phApplication); + + typedef ULONG (*SKF_EnumApplication_Func)(DEVHANDLE hDev, LPSTR szAppName, ULONG *pulSize); + typedef ULONG (*SKF_ExportPublicKey_Func)(HCONTAINER hContainer, BOOL bSignFlag, BYTE *pbBlob, ULONG *pulBlobLen); + typedef ULONG (*SKF_Digest_Func)(HANDLE hHash, BYTE *pbData, ULONG ulDataLen, BYTE *pbHashData, ULONG *pulHashLen); + typedef ULONG (*SKF_DigestInit_Func)(DEVHANDLE hDev, ULONG ulAlgID, ECCPUBLICKEYBLOB *pPubKey, + unsigned char *pucID, ULONG ulIDLen, HANDLE *phHash); + typedef ULONG (*SKF_ECCSignData_Func)(HCONTAINER hContainer, BYTE *pbData, ULONG ulDataLen, PECCSIGNATUREBLOB pSignature); + typedef ULONG (*SKF_ECCVerify_Func)(DEVHANDLE hDev, ECCPUBLICKEYBLOB *pECCPubKeyBlob, BYTE *pbData, + ULONG ulDataLen, PECCSIGNATUREBLOB pSignature); + + typedef ULONG (*SKF_GenRandom_Func)(DEVHANDLE hDev, BYTE *pbRandom, ULONG ulRandomLen); + typedef ULONG (*SKF_SetSymmKey_Func)(DEVHANDLE hDev, BYTE *pbKey, ULONG ulAlgID, HANDLE *phKey); + typedef ULONG (*SKF_EncryptInit_Func)(HANDLE hKey, BLOCKCIPHERPARAM EncryptParam); + typedef ULONG (*SKF_Encrypt_Func)(HANDLE hKey, BYTE *pbData, ULONG ulDataLen, BYTE *pbEncryptedData, ULONG *pulEncryptedLen); + typedef ULONG (*SKF_DevAuth_Func)(DEVHANDLE hDev, BYTE *pbAuthData, ULONG ulLen); + typedef ULONG (*SKF_DeleteApplication_Func)(DEVHANDLE hDev, LPSTR szAppName); + typedef ULONG (*SKF_CreateContainer_Func)(HAPPLICATION hApplication, LPSTR szContainerName, HCONTAINER *phContainer); +} + +struct DriverLib +{ + SKF_EnumDev_Func SKF_EnumDev; + SKF_ConnectDev_Func SKF_ConnectDev; + SKF_DisConnectDev_Func SKF_DisConnectDev; + SKF_GetDevState_Func SKF_GetDevState; + SKF_GetDevInfo_Func SKF_GetDevInfo; + SKF_SetLabel_Func SKF_SetLabel; + SKF_OpenApplication_Func SKF_OpenApplication; + SKF_VerifyPIN_Func SKF_VerifyPIN; + SKF_OpenContainer_Func SKF_OpenContainer; + SKF_GenECCKeyPair_Func SKF_GenECCKeyPair; + SKF_CloseContainer_Func SKF_CloseContainer; + SKF_CloseApplication_Func SKF_CloseApplication; + SKF_CreateApplication_Func SKF_CreateApplication; + SKF_EnumApplication_Func SKF_EnumApplication; + SKF_ExportPublicKey_Func SKF_ExportPublicKey; + SKF_Digest_Func SKF_Digest; + SKF_DigestInit_Func SKF_DigestInit; + SKF_ECCSignData_Func SKF_ECCSignData; + SKF_ECCVerify_Func SKF_ECCVerify; + SKF_GenRandom_Func SKF_GenRandom; + SKF_SetSymmKey_Func SKF_SetSymmKey; + SKF_EncryptInit_Func SKF_EncryptInit; + SKF_Encrypt_Func SKF_Encrypt; + SKF_DevAuth_Func SKF_DevAuth; + SKF_DeleteApplication_Func SKF_DeleteApplication; + SKF_CreateContainer_Func SKF_CreateContainer; +}; + +UKeySKFDriver::UKeySKFDriver(QObject *parent) : BDriver(parent) +{ +} + +UKeySKFDriver::~UKeySKFDriver() +{ + if (m_libHandle) + { + dlclose(m_libHandle); + m_libHandle = NULL; + } +} + +QString UKeySKFDriver::getName() +{ + return QString(); +} +QString UKeySKFDriver::getFullName() +{ + return QString(); +} +quint16 UKeySKFDriver::getDriverId() +{ + return 0; +} + +bool UKeySKFDriver::loadLibrary(QString libPath) +{ + if (!QFile::exists(UKEY_DEFAULT_CONFIG)) + { + return false; + } + + m_libHandle = dlopen(libPath.toStdString().c_str(), RTLD_NOW); + if (m_libHandle == nullptr) + { + KLOG_ERROR() << "Load ukey lib failed,error:" << dlerror(); + return false; + } + + m_driverLib = QSharedPointer(new DriverLib); + m_driverLib->SKF_EnumDev = (SKF_EnumDev_Func)dlsym(m_libHandle, "SKF_EnumDev"); + m_driverLib->SKF_ConnectDev = (SKF_ConnectDev_Func)dlsym(m_libHandle, "SKF_ConnectDev"); + m_driverLib->SKF_DisConnectDev = (SKF_DisConnectDev_Func)dlsym(m_libHandle, "SKF_DisConnectDev"); + m_driverLib->SKF_GetDevState = (SKF_GetDevState_Func)dlsym(m_libHandle, "SKF_GetDevState"); + m_driverLib->SKF_GetDevInfo = (SKF_GetDevInfo_Func)dlsym(m_libHandle, "SKF_GetDevInfo"); + m_driverLib->SKF_SetLabel = (SKF_SetLabel_Func)dlsym(m_libHandle, "SKF_SetLabel"); + m_driverLib->SKF_OpenApplication = (SKF_OpenApplication_Func)dlsym(m_libHandle, "SKF_OpenApplication"); + m_driverLib->SKF_VerifyPIN = (SKF_VerifyPIN_Func)dlsym(m_libHandle, "SKF_VerifyPIN"); + m_driverLib->SKF_OpenContainer = (SKF_OpenContainer_Func)dlsym(m_libHandle, "SKF_OpenContainer"); + m_driverLib->SKF_GenECCKeyPair = (SKF_GenECCKeyPair_Func)dlsym(m_libHandle, "SKF_GenECCKeyPair"); + m_driverLib->SKF_CloseContainer = (SKF_CloseContainer_Func)dlsym(m_libHandle, "SKF_CloseContainer"); + m_driverLib->SKF_CloseApplication = (SKF_CloseApplication_Func)dlsym(m_libHandle, "SKF_CloseApplication"); + m_driverLib->SKF_CreateApplication = (SKF_CreateApplication_Func)dlsym(m_libHandle, "SKF_CreateApplication"); + m_driverLib->SKF_EnumApplication = (SKF_EnumApplication_Func)dlsym(m_libHandle, "SKF_EnumApplication"); + m_driverLib->SKF_ExportPublicKey = (SKF_ExportPublicKey_Func)dlsym(m_libHandle, "SKF_ExportPublicKey"); + m_driverLib->SKF_Digest = (SKF_Digest_Func)dlsym(m_libHandle, "SKF_Digest"); + m_driverLib->SKF_DigestInit = (SKF_DigestInit_Func)dlsym(m_libHandle, "SKF_DigestInit"); + m_driverLib->SKF_ECCSignData = (SKF_ECCSignData_Func)dlsym(m_libHandle, "SKF_ECCSignData"); + m_driverLib->SKF_ECCVerify = (SKF_ECCVerify_Func)dlsym(m_libHandle, "SKF_ECCVerify"); + m_driverLib->SKF_GenRandom = (SKF_GenRandom_Func)dlsym(m_libHandle, "SKF_GenRandom"); + m_driverLib->SKF_SetSymmKey = (SKF_SetSymmKey_Func)dlsym(m_libHandle, "SKF_SetSymmKey"); + m_driverLib->SKF_EncryptInit = (SKF_EncryptInit_Func)dlsym(m_libHandle, "SKF_EncryptInit"); + m_driverLib->SKF_Encrypt = (SKF_Encrypt_Func)dlsym(m_libHandle, "SKF_Encrypt"); + m_driverLib->SKF_DevAuth = (SKF_DevAuth_Func)dlsym(m_libHandle, "SKF_DevAuth"); + m_driverLib->SKF_DeleteApplication = (SKF_DeleteApplication_Func)dlsym(m_libHandle, "SKF_DeleteApplication"); + m_driverLib->SKF_CreateContainer = (SKF_CreateContainer_Func)dlsym(m_libHandle, "SKF_CreateContainer"); + + return true; +} + +DEVHANDLE UKeySKFDriver::connectDev() +{ + ULONG ulBufSize = 0; + ULONG ulReval = m_driverLib->SKF_EnumDev(TRUE, NULL, &ulBufSize); + + if (ulReval != SAR_OK) + { + KLOG_DEBUG() << "Enum Dev error:" << getErrorReason(ulReval); + return nullptr; + } + + LPSTR szNameList = (LPSTR)malloc(ulBufSize * sizeof(CHAR)); + memset(szNameList, '\0', ulBufSize); + ulReval = m_driverLib->SKF_EnumDev(TRUE, szNameList, &ulBufSize); + if (ulReval == SAR_OK) + { + LPSTR pszTemp = szNameList; + if (NULL == pszTemp) + { + KLOG_DEBUG() << "no found ukey device"; + return nullptr; + } + while (*pszTemp != '\0') + { + DEVHANDLE devHandle; + ulReval = m_driverLib->SKF_ConnectDev(pszTemp, &devHandle); + if (SAR_OK == ulReval) + { + return devHandle; + } + else + { + KLOG_ERROR() << "Connect Dev failed:" << getErrorReason(ulReval); + } + pszTemp += strlen((const char *)pszTemp) + 1; + } + } + free(szNameList); + return nullptr; +} + +void UKeySKFDriver::deleteAllApplication(DEVHANDLE devHandle) +{ + ULONG ulReval = SAR_FAIL; + char szAppNames[256] = {0}; + ULONG ulSize = 256; + + ulReval = m_driverLib->SKF_EnumApplication(devHandle, (LPSTR)szAppNames, &ulSize); + if (SAR_OK == ulReval) + { + char *pszTemp = szAppNames; + if (*pszTemp == '\0') + { + m_driverLib->SKF_DeleteApplication(devHandle, (LPSTR)pszTemp); + } + + while (*pszTemp != '\0') + { + m_driverLib->SKF_DeleteApplication(devHandle, (LPSTR)pszTemp); + pszTemp += strlen((const char *)pszTemp) + 1; + } + } + KLOG_DEBUG() << "clear all application"; +} + +QString UKeySKFDriver::enumApplication(DEVHANDLE devHandle) +{ + char szAppNames[256] = {0}; + ULONG ulSize = 256; + ULONG ret = m_driverLib->SKF_EnumApplication(devHandle, (LPSTR)szAppNames, &ulSize); + if (ret == SAR_OK) + { + QString appNames(szAppNames); + KLOG_DEBUG() << "enum app names:" << appNames; + return appNames; + } + else + { + return QString(); + } +} + +ULONG UKeySKFDriver::devAuth(DEVHANDLE devHandle) +{ + BYTE random[16] = {0}; + BYTE devKey[16] = {0}; + BLOCKCIPHERPARAM param = {0}; + BYTE devkeyenc[16] = {0}; + ULONG dwResultLen = 16; + ULONG ulReval; + DEVINFO devInfo; + HANDLE hSessionKey; + + QString defaultDevKey = getDefaultValueFromConf(CONF_DEFAULT_KEY_DEV_KEY); + QByteArray byteArray = defaultDevKey.toLatin1(); + unsigned char *key = (unsigned char *)byteArray.data(); + + memcpy(devKey, key, 16); + + ulReval = m_driverLib->SKF_GenRandom(devHandle, random, 8); + if (SAR_OK != ulReval) + return ulReval; + + ulReval = m_driverLib->SKF_GetDevInfo(devHandle, &devInfo); + if (SAR_OK != ulReval) + return ulReval; + + ulReval = m_driverLib->SKF_SetSymmKey(devHandle, devKey, devInfo.DevAuthAlgId, &hSessionKey); + if (SAR_OK != ulReval) + return ulReval; + + ulReval = m_driverLib->SKF_EncryptInit(hSessionKey, param); + if (SAR_OK != ulReval) + return ulReval; + + ulReval = m_driverLib->SKF_Encrypt(hSessionKey, random, 16, devkeyenc, &dwResultLen); + if (SAR_OK != ulReval) + return ulReval; + + ulReval = m_driverLib->SKF_DevAuth(devHandle, devkeyenc, 16); + + return ulReval; +} + +HAPPLICATION UKeySKFDriver::onOpenApplication(DEVHANDLE devHandle, LPSTR szAppName) +{ + HAPPLICATION phApplication = nullptr; + ULONG ret = m_driverLib->SKF_OpenApplication(devHandle, szAppName, &phApplication); + if (ret != SAR_OK) + { + KLOG_DEBUG() << "open Application failed:" << getErrorReason(ret); + return nullptr; + } + return phApplication; +} + +HCONTAINER UKeySKFDriver::onOpenContainer(HAPPLICATION appHandle, const QString &pin, QString containerName, ULONG *retryCount) +{ + QByteArray byteArray = pin.toLatin1(); + unsigned char *szPIN = (unsigned char *)byteArray.data(); + ULONG ret = m_driverLib->SKF_VerifyPIN(appHandle, USER_TYPE, szPIN, retryCount); + if (ret == SAR_OK) + { + HCONTAINER containerHandle = nullptr; + ret = m_driverLib->SKF_OpenContainer(appHandle, (LPSTR)containerName.data(), &containerHandle); + if (ret == SAR_OK) + { + KLOG_DEBUG() << "open container success"; + return containerHandle; + } + else + { + KLOG_ERROR() << "open container failed:" << getErrorReason(ret); + } + } + else + { + KLOG_DEBUG() << "Verify PIN failed:" << getErrorReason(ret); + KLOG_DEBUG() << "Retry Count:" << retryCount; + } + return nullptr; +} + +void UKeySKFDriver::closeApplication(HAPPLICATION appHandle) +{ + m_driverLib->SKF_CloseApplication(appHandle); +} +void UKeySKFDriver::closeContainer(HCONTAINER containerHandle) +{ + m_driverLib->SKF_CloseContainer(containerHandle); +} + +void UKeySKFDriver::disConnectDev(DEVHANDLE devHandle) +{ + m_driverLib->SKF_DisConnectDev(devHandle); +} + +HAPPLICATION UKeySKFDriver::createApplication(DEVHANDLE devHandle, QString pin, QString appName) +{ + QByteArray pinArray = pin.toLatin1(); + unsigned char *userPin = (unsigned char *)pinArray.data(); + + QByteArray appNameArray = appName.toLatin1(); + unsigned char *szAppName = (unsigned char *)appNameArray.data(); + + QString defaultAdminPin = getDefaultValueFromConf(CONF_DEFAULT_KEY_ADMIN_PINCODE); + QByteArray byteArray = defaultAdminPin.toLatin1(); + unsigned char *adminPIn = (unsigned char *)byteArray.data(); + + HAPPLICATION appHandle = nullptr; + ULONG ulReval = m_driverLib->SKF_CreateApplication(devHandle, szAppName, adminPIn, + ADMIN_PIN_RETRY_COUNT, userPin, USER_PIN_RETRY_COUNT, + SECURE_USER_ACCOUNT, &appHandle); + ULONG retryCount; + if (ulReval != SAR_OK) + { + KLOG_ERROR() << "create application failed:" << getErrorReason(ulReval); + return nullptr; + } + + return appHandle; +} + +HCONTAINER UKeySKFDriver::createContainer(HAPPLICATION appHandle, QString pin, QString containerName, ULONG *retryCount) +{ + QByteArray byteArray = pin.toLatin1(); + unsigned char *userPin = (unsigned char *)byteArray.data(); + ULONG ulReval = m_driverLib->SKF_VerifyPIN(appHandle, USER_TYPE, userPin, retryCount); + if (ulReval != SAR_OK) + { + KLOG_ERROR() << "verifyPin failed:" << getErrorReason(ulReval); + return nullptr; + } + + HCONTAINER containerHandle = nullptr; + ulReval = m_driverLib->SKF_CreateContainer(appHandle, (LPSTR)containerName.data(), &containerHandle); + if (ulReval != SAR_OK) + { + KLOG_ERROR() << "create container failed:" << getErrorReason(ulReval); + return nullptr; + } + KLOG_DEBUG() << "create new application and container success"; + return containerHandle; +} + +ULONG UKeySKFDriver::genECCKeyPair(HCONTAINER containerHandle, ECCPUBLICKEYBLOB *pBlob) +{ + return m_driverLib->SKF_GenECCKeyPair(containerHandle, SGD_SM2_1, pBlob); +} + +ULONG UKeySKFDriver::authSignData(HCONTAINER containerHandle, DEVHANDLE devHandle, ECCSIGNATUREBLOB &Signature) +{ + unsigned char *pPubKey = NULL; + ULONG ulPubKeyLen = 0; + ECCPUBLICKEYBLOB EccPubKey = {0}; + unsigned char pucId[32] = {0}; + ULONG ulIdLen = 16; + HANDLE hHash = nullptr; + ULONG ulHashLen = 64; + int signDataLen = strlen(SIGN_DATA); + unsigned char pbHashData[33] = {0}; + + QString defaultPucId = getDefaultValueFromConf(CONF_DEFAULT_KEY_PUC_ID); + QByteArray byteArray = defaultPucId.toLatin1(); + unsigned char *PUC_ID = (unsigned char *)byteArray.data(); + + ULONG ret = m_driverLib->SKF_ExportPublicKey(containerHandle, TRUE, pPubKey, &ulPubKeyLen); + if (ret != SAR_OK) + { + goto end; + } + + pPubKey = (unsigned char *)malloc(ulPubKeyLen); + if (pPubKey == NULL) + { + goto end; + } + + ret = m_driverLib->SKF_ExportPublicKey(containerHandle, TRUE, pPubKey, &ulPubKeyLen); + if (ret != SAR_OK) + { + goto end; + } + + if (ulPubKeyLen != sizeof(ECCPUBLICKEYBLOB)) + { + goto end; + } + + memcpy(&EccPubKey, pPubKey, ulPubKeyLen); + memcpy(pucId, PUC_ID, 16); + + ret = m_driverLib->SKF_DigestInit(devHandle, SGD_SM3, &EccPubKey, pucId, ulIdLen, &hHash); + if (ret != SAR_OK) + { + goto end; + } + + ret = m_driverLib->SKF_Digest(hHash, (BYTE *)SIGN_DATA, signDataLen, pbHashData, &ulHashLen); + if (ret != SAR_OK) + { + goto end; + } + + ret = m_driverLib->SKF_ECCSignData(containerHandle, pbHashData, ulHashLen, &Signature); + +end: + getErrorReason(ret); + return ret; +} + +ULONG UKeySKFDriver::verifyData(DEVHANDLE devHandle, ECCSIGNATUREBLOB &Signature, ECCPUBLICKEYBLOB &publicKey) +{ + unsigned char *pbInData = NULL, pbHashData[33] = {0}, pbOutData[256] = {0}; + ULONG ulInLen = 0, ulOutLen = 0, ulHashLen = 0, ulIdLen = 7; + unsigned char pucId[32] = {0}; + HANDLE hHash; + ULONG ulPubKeyLen = 0; + int signDataLen = strlen(SIGN_DATA); + QString defaultPucId = getDefaultValueFromConf(CONF_DEFAULT_KEY_PUC_ID); + QByteArray byteArray = defaultPucId.toLatin1(); + unsigned char *PUC_ID = (unsigned char *)byteArray.data(); + + memcpy(pucId, PUC_ID, 16); + ulIdLen = 16; + ULONG ulReval = m_driverLib->SKF_DigestInit(devHandle, SGD_SM3, &publicKey, pucId, ulIdLen, &hHash); + if (ulReval != SAR_OK) + { + goto end; + } + + ulHashLen = 64; + ulReval = m_driverLib->SKF_Digest(hHash, (BYTE *)SIGN_DATA, signDataLen, pbHashData, &ulHashLen); + if (ulReval != SAR_OK) + { + goto end; + } + + ulReval = m_driverLib->SKF_ECCVerify(devHandle, &publicKey, pbHashData, ulHashLen, &Signature); + +end: + getErrorReason(ulReval); + return ulReval; +} + +QString UKeySKFDriver::getErrorReason(ULONG error) +{ + for (int i = 0; i < sizeof(skf_errors) / sizeof(skf_errors[0]); i++) + { + if (error == skf_errors[i].err) + { + return skf_errors[i].reason; + } + } + return QString(); +} + +QString UKeySKFDriver::getDefaultValueFromConf(const QString &key) +{ + QSettings confSettings(UKEY_DEFAULT_CONFIG, QSettings::NativeFormat); + QVariant value = confSettings.value(QString("default/%1").arg(key)); + return value.toString(); +} + +} // namespace Kiran diff --git a/src/driver/ukey/ukey-skf-driver.h b/src/driver/ukey/ukey-skf-driver.h new file mode 100644 index 0000000..4952ff6 --- /dev/null +++ b/src/driver/ukey/ukey-skf-driver.h @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2020 ~ 2021 KylinSec Co., Ltd. + * kiran-biometrics is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: luoqing + */ +#pragma once +#include "driver/driver.h" +#include "ukey-skf.h" +#include + +namespace Kiran +{ +struct DriverLib; + +class UKeySKFDriver : public BDriver +{ +public: + UKeySKFDriver(QObject *parent = nullptr); + ~UKeySKFDriver(); + QString getName() override; + QString getFullName() override; + quint16 getDriverId() override; + + bool loadLibrary(QString libPath); + DEVHANDLE connectDev(); + void deleteAllApplication(DEVHANDLE devHandle); + QString enumApplication(DEVHANDLE devHandle); + + ULONG devAuth(DEVHANDLE devHandle); + HAPPLICATION onOpenApplication(DEVHANDLE hDev, LPSTR szAppName); + HCONTAINER onOpenContainer(HAPPLICATION appHandle,const QString &pin,QString containerName,ULONG *retryCount); + + void closeApplication(HAPPLICATION appHandle); + void closeContainer(HCONTAINER containerHandle); + void disConnectDev(DEVHANDLE devHandle); + + HAPPLICATION createApplication(DEVHANDLE devHandle,QString pin,QString appName); + HCONTAINER createContainer(HAPPLICATION appHandle, QString pin,QString containerName,ULONG *retryCount); + + ULONG genECCKeyPair(HCONTAINER containerHandle,ECCPUBLICKEYBLOB *pBlob); + + ULONG authSignData(HCONTAINER containerHandle,DEVHANDLE devHandle,ECCSIGNATUREBLOB &Signature); + ULONG verifyData(DEVHANDLE devHandle,ECCSIGNATUREBLOB &Signature, ECCPUBLICKEYBLOB &publicKey); + + QString getErrorReason(ULONG error); + + QString getDefaultValueFromConf(const QString &key); + +private: + QSharedPointer m_driverLib; + HANDLE m_libHandle; +}; + +} // namespace Kiran \ No newline at end of file diff --git a/translations/kiran-authentication-devices.zh_CN.ts b/translations/kiran-authentication-devices.zh_CN.ts index 40aef0a..540aadb 100644 --- a/translations/kiran-authentication-devices.zh_CN.ts +++ b/translations/kiran-authentication-devices.zh_CN.ts @@ -4,63 +4,69 @@ Kiran::AuthDevice - - + + Device Busy 设备忙 - + feature has reached the upper limit of %1 录入的特征已达上限 %1 + + + + The pin code cannot be empty! + pin码不能为空! + Kiran::FPZKDevice - - + + acquire fingerprint fail! 获取指纹失败! - + Partial fingerprint feature entry 录入部分指纹特征 - + The fingerprint has been enrolled 指纹重复录入 - + Please place the same finger! 请放置相同的手指! - - + + Failed to enroll fingerprint, please enroll again 录入指纹失败,请重新录入 - + Successed save finger 录入指纹成功 - + Save Finger Failed! 录入指纹失败! - + Fingerprint match 指纹匹配 - + Fingerprint not match, place again 指纹不匹配,请重试 @@ -68,52 +74,52 @@ Kiran::FVSDDevice - + Finger vein image not obtained 未获取到指静脉图像 - + Partial finger vein feature entry 录入部分指静脉特征 - + The finger vein has been enrolled 指静脉重复录入 - + Please place the same finger! 请放置相同的手指! - + Finger vein template merged failed 指静脉模板融合失败 - + Successed save feature 录入特征成功 - + Save Feature Failed! 录入特征失败! - + timeout, acquire finger vein fail! 超时,获取指静脉失败! - + Feature Match 特征匹配 - + Feature not match, place again 特征不匹配,请重试 @@ -126,4 +132,32 @@ 授权失败. + + Kiran::UKeyFTDevice + + + Successed binding user + 绑定用户成功 + + + + Binding user failed + 绑定用户失败 + + + + UKey has been bound + UKey已经被绑定 + + + + identify fail! + 认证失败! + + + + identify ukey success + ukey认证成功 + + -- 2.33.0