/* * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * * http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include "../sgd.h" #include "skf.h" #include "skf_ext.h" #include "skf_int.h" int skf_load_library(const char *so_path, const char *vendor) { if (SKF_LoadLibrary((LPSTR)so_path, (LPSTR)vendor) != SAR_OK) { error_print(); return -1; } return 1; } void skf_unload_library(void) { SKF_UnloadLibrary(); } static int skf_open_app(SKF_DEVICE *dev, const char *appname, const char *pin, HAPPLICATION *phApp) { int ret = 0; HAPPLICATION hApp = NULL; ULONG ulPINType = USER_TYPE; ULONG numRetry; if (SKF_OpenApplication(dev->handle, (LPSTR)appname, &hApp) != SAR_OK) { error_print(); return -1; } if (SKF_VerifyPIN(hApp, ulPINType, (CHAR *)pin, &numRetry) != SAR_OK) { fprintf(stderr, "Invalid user PIN, retry count = %u\n", numRetry); error_print(); goto end; } *phApp = hApp; hApp = NULL; ret = 1; end: if (hApp) SKF_CloseApplication(hApp); return ret; } static const uint8_t zeros[ECC_MAX_XCOORDINATE_BITS_LEN/8 - 32] = {0}; static int SKF_ECCPUBLICKEYBLOB_to_SM2_KEY(const ECCPUBLICKEYBLOB *blob, SM2_KEY *sm2_key) { SM2_POINT point; if (blob->BitLen != 256) { error_print(); return -1; } if (memcmp(blob->XCoordinate, zeros, sizeof(zeros)) != 0 || memcmp(blob->YCoordinate, zeros, sizeof(zeros)) != 0) { error_print(); return -1; } if (sm2_point_from_xy(&point, blob->XCoordinate + ECC_MAX_XCOORDINATE_BITS_LEN/8 - 32, blob->YCoordinate + ECC_MAX_YCOORDINATE_BITS_LEN/8 - 32) != 1 || sm2_key_set_public_key(sm2_key, &point) != 1) { error_print(); return -1; } return SAR_OK; } static int SKF_ECCSIGNATUREBLOB_to_SM2_SIGNATURE(const ECCSIGNATUREBLOB *blob, SM2_SIGNATURE *sig) { if (memcmp(blob->r, zeros, sizeof(zeros)) != 0 || memcmp(blob->s, zeros, sizeof(zeros)) != 0) { error_print(); return -1; } memset(sig, 0, sizeof(SM2_SIGNATURE)); memcpy(sig->r, blob->r + ECC_MAX_XCOORDINATE_BITS_LEN/8 - 32, 32); memcpy(sig->s, blob->s + ECC_MAX_XCOORDINATE_BITS_LEN/8 - 32, 32); return SAR_OK; } int skf_rand_bytes(SKF_DEVICE *dev, uint8_t *buf, size_t len) { if (SKF_GenRandom(dev->handle, buf, (ULONG)len) != SAR_OK) { error_print(); return -1; } return 1; } int skf_load_sign_key(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name, SKF_KEY *key) { int ret = -1; HAPPLICATION hApp = NULL; HCONTAINER hContainer = NULL; ULONG containerType = 0; BOOL bSign = SGD_TRUE; ECCPUBLICKEYBLOB publicKeyBlob; ULONG ulBlobLen = sizeof(ECCPUBLICKEYBLOB); SM2_KEY public_key; if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_OpenContainer(hApp, (LPSTR)container_name, &hContainer) != SAR_OK || SKF_GetContainerType(hContainer, &containerType) != SAR_OK) { error_print(); goto end; } if (containerType != SKF_CONTAINER_TYPE_ECC) { error_print(); goto end; } if (SKF_ExportPublicKey(hContainer, bSign, (BYTE *)&publicKeyBlob, &ulBlobLen) != SAR_OK) { error_print(); goto end; } if (ulBlobLen != sizeof(ECCPUBLICKEYBLOB)) { error_print(); goto end; } if (SKF_ECCPUBLICKEYBLOB_to_SM2_KEY(&publicKeyBlob, &public_key) != SAR_OK) { error_print(); goto end; } memset(key, 0, sizeof(SKF_KEY)); key->public_key = public_key; key->app_handle = hApp; hApp = NULL; strncpy(key->app_name, appname, 64); key->container_handle = hContainer; hContainer = NULL; strncpy(key->container_name, container_name, 64); ret = 1; end: if (hApp) SKF_CloseApplication(hApp); if (hContainer) SKF_CloseContainer(hContainer); return ret; } int skf_sign(SKF_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen) { ECCSIGNATUREBLOB sigBlob; SM2_SIGNATURE sm2_sig; if (SKF_ECCSignData(key->container_handle, (BYTE *)dgst, 32, &sigBlob) != SAR_OK) { error_print(); return -1; } if (SKF_ECCSIGNATUREBLOB_to_SM2_SIGNATURE(&sigBlob, &sm2_sig) != SAR_OK) { error_print(); return -1; } *siglen = 0; if (sm2_signature_to_der(&sm2_sig, &sig, siglen) != 1) { error_print(); return -1; } return 1; } int skf_release_key(SKF_KEY *key) { if (key->app_handle) { if (SKF_ClearSecureState(key->app_handle) != SAR_OK || SKF_CloseApplication(key->app_handle) != SAR_OK) { error_print(); return -1; } key->app_handle = NULL; } if (key->container_handle) { if (SKF_CloseContainer(key->container_handle) != SAR_OK) { error_print(); return -1; } } memset(key, 0, sizeof(SKF_KEY)); return 1; } int skf_close_device(SKF_DEVICE *dev) { if (SKF_UnlockDev(dev->handle) != SAR_OK || SKF_DisConnectDev(dev->handle) != SAR_OK) { error_print(); return -1; } memset(dev, 0, sizeof(SKF_DEVICE)); return 1; } int skf_list_devices(FILE *fp, int fmt, int ind, const char *label) { int ret = -1; BOOL bPresent = TRUE; char *nameList = NULL; ULONG nameListLen = 0; const char *name; int i; format_print(fp, fmt, ind, "%s\n", label); ind += 4; if (SKF_EnumDev(bPresent, NULL, &nameListLen) != SAR_OK) { error_print(); return -1; } if (nameListLen == 0) { return 0; } if (!(nameList = malloc(nameListLen))) { error_print(); return -1; } if (SKF_EnumDev(bPresent, (LPSTR)nameList, &nameListLen) != SAR_OK) { error_print(); goto end; } for (name = nameList, i = 0; *name; name += strlen(name) + 1, i++) { (void)format_print(fp, fmt, ind, "%s\n", name); } ret = 1; end: free(nameList); return ret; } int skf_print_device_info(FILE *fp, int fmt, int ind, const char *devname) { int ret = 0; DEVHANDLE hDev = NULL; ULONG devState = 0; LPSTR devStateName = NULL; DEVINFO devInfo = {{0,0}}; format_print(fp, fmt, ind, "%s\n", devname); ind += 4; if (SKF_GetDevState((LPSTR)devname, &devState) != SAR_OK || SKF_GetDevStateName(devState, &devStateName) != SAR_OK || SKF_ConnectDev((LPSTR)devname, &hDev) != SAR_OK || SKF_GetDevInfo(hDev, &devInfo) != SAR_OK) { error_print(); goto end; } (void)format_print(fp, fmt, ind, "DeviceState: %s\n", (char *)devStateName); //(void)SKF_PrintDevInfo(fp, fmt, ind, "DeviceInfo", &devInfo); ret = 1; end: if (hDev) SKF_DisConnectDev(hDev); return ret; } int skf_set_label(SKF_DEVICE *dev, const char *label) { if (SKF_SetLabel(dev->handle, (LPSTR)label) != SAR_OK) { error_print(); return -1; } return 1; } int skf_open_device(SKF_DEVICE *dev, const char *devname, const uint8_t authkey[16]) { DEVHANDLE hDev = NULL; DEVINFO devInfo = {{0,0}}; ULONG ulTimeOut = 0xffffffff; BYTE authRand[16] = {0}; BYTE authData[16] = {0}; ULONG authRandLen = SKF_AUTHRAND_LENGTH; ULONG authDataLen = sizeof(authData); BLOCKCIPHERPARAM encParam = {{0}, 0, 0, 0}; if (SKF_OpenDevice((LPSTR)devname, (BYTE *)authkey, &devInfo, &hDev) != SAR_OK || SKF_LockDev(hDev, ulTimeOut) != SAR_OK) { error_print(); return -1; } memset(dev, 0, sizeof(SKF_DEVICE)); dev->handle = hDev; hDev = NULL; return 1; } int skf_change_authkey(SKF_DEVICE *dev, const uint8_t authkey[16]) { if (SKF_ChangeDevAuthKey(dev->handle, (BYTE *)authkey, 16) != SAR_OK) { error_print(); return -1; } return 1; } int skf_list_apps(SKF_DEVICE *dev, int fmt, int ind, const char *label, FILE *fp) { int ret = 0; HAPPLICATION hApp = NULL; char *nameList = NULL; ULONG nameListLen = 0; const char *name; int i; format_print(fp, fmt, ind, "%s\n", label); ind += 4; if (SKF_EnumApplication(dev->handle, NULL, &nameListLen) != SAR_OK) { error_print(); return -1; } if (nameListLen <= 1) { return 0; } if (!(nameList = malloc(nameListLen))) { error_print(); return -1; } if (SKF_EnumApplication(dev->handle, (LPSTR)nameList, &nameListLen) != SAR_OK) { error_print(); goto end; } for (name = nameList, i = 0; *name; name += strlen(name) + 1, i++) { ULONG adminMaxRetry; ULONG adminMinRetry; ULONG userMaxRetry; ULONG userMinRetry; BOOL adminDefaultPin; BOOL userDefaultPin; if (SKF_OpenApplication(dev->handle, (LPSTR)name, &hApp) != SAR_OK || SKF_GetPINInfo(hApp, ADMIN_TYPE, &adminMaxRetry, &adminMinRetry, &adminDefaultPin) != SAR_OK || SKF_GetPINInfo(hApp, USER_TYPE, &userMaxRetry, &userMinRetry, &userDefaultPin) != SAR_OK || SKF_CloseApplication(hApp) != SAR_OK) { error_print(); goto end; } hApp = NULL; (void)format_print(fp, fmt, ind, "Application %d:\n", i); (void)format_print(fp, fmt, ind + 4, "ApplicationName", name); (void)format_print(fp, fmt, ind + 4, "AdminPinMaxRetry: %s\n", adminMaxRetry); (void)format_print(fp, fmt, ind + 4, "AdminPinMinRetry: %u\n", adminMinRetry); (void)format_print(fp, fmt, ind + 4, "AdminDefaultPin: %s\n", adminDefaultPin ? "True" : "False"); (void)format_print(fp, fmt, ind + 4, "UserPinMaxRetry: %u\n", userMaxRetry); (void)format_print(fp, fmt, ind + 4, "UserPinMinRetry: %u\n", userMinRetry); (void)format_print(fp, fmt, ind + 4, "UserDefaultPin: %s\n", userDefaultPin ? "True" : "False"); } ret = 1; end: if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_create_app(SKF_DEVICE *dev, const char *appname, const char *admin_pin, const char *user_pin) { int ret = 0; HAPPLICATION hApp = NULL; ULONG appRights = SECURE_ANYONE_ACCOUNT; if (SKF_CreateApplication(dev->handle, (LPSTR)appname, (CHAR *)admin_pin, SKF_DEFAULT_ADMIN_PIN_RETRY_COUNT, (CHAR *)user_pin, SKF_DEFAULT_USER_PIN_RETRY_COUNT, appRights, &hApp) != SAR_OK) { error_print(); return -1; } if (SKF_CloseApplication(hApp) != SAR_OK) { error_print(); return -1; } return 1; } int skf_delete_app(SKF_DEVICE *dev, const char *appname) { if (SKF_DeleteApplication(dev->handle, (LPSTR)appname) != SAR_OK) { error_print(); return -1; } return 1; } int skf_change_app_admin_pin(SKF_DEVICE *dev, const char *appname, const char *oid_pin, const char *new_pin) { int ret = -1; HAPPLICATION hApp = NULL; ULONG ulPINType = ADMIN_TYPE; ULONG ulRetryCount = 0; if (SKF_OpenApplication(dev->handle, (LPSTR)appname, &hApp) != SAR_OK || SKF_ChangePIN(hApp, ulPINType, (CHAR *)oid_pin, (CHAR *)new_pin, &ulRetryCount) != SAR_OK) { fprintf(stderr, "Retry Count = %u\n", ulRetryCount); error_print(); goto end; } ret = 1; end: if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_change_app_user_pin(SKF_DEVICE *dev, const char *appname, const char *oid_pin, const char *new_pin) { int ret = -1; HAPPLICATION hApp = NULL; ULONG ulPINType = USER_TYPE; ULONG ulRetryCount = 0; if (SKF_OpenApplication(dev->handle, (LPSTR)appname, &hApp) != SAR_OK || SKF_ChangePIN(hApp, ulPINType, (CHAR *)oid_pin, (CHAR *)new_pin, &ulRetryCount) != SAR_OK) { fprintf(stderr, "Retry Count = %u\n", ulRetryCount); goto end; } ret = 1; end: if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_unblock_user_pin(SKF_DEVICE *dev, const char *appname, const char *admin_pin, const char *new_user_pin) { int ret = -1; HAPPLICATION hApp = NULL; ULONG ulRetryCount = 0; if (SKF_OpenApplication(dev->handle, (LPSTR)appname, &hApp) != SAR_OK || SKF_UnblockPIN(hApp, (CHAR *)admin_pin, (CHAR *)new_user_pin, &ulRetryCount) != SAR_OK) { fprintf(stderr, "Invalid admin PIN, retry count = %u\n", ulRetryCount); error_print(); goto end; } ret = 1; end: if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_list_objects(FILE *fp, int fmt, int ind, const char *label, SKF_DEVICE *dev, const char *appname, const char *pin) { int ret = -1; HAPPLICATION hApp = NULL; char *nameList = NULL; ULONG nameListLen = 0; const char *name; int i; format_print(fp, fmt, ind, "%s\n", label); ind += 4; if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_EnumFiles(hApp, NULL, &nameListLen) != SAR_OK) { error_print(); goto end; } if (nameListLen <= 1) { ret = 0; goto end; } if (!(nameList = malloc(nameListLen))) { error_print(); goto end; } if (SKF_EnumFiles(hApp, (LPSTR)nameList, &nameListLen) != SAR_OK) { error_print(); goto end; } for (name = nameList, i = 0; *name; name += strlen(name) + 1, i++) { FILEATTRIBUTE fileInfo; if (SKF_GetFileInfo(hApp, (LPSTR)name, &fileInfo) != SAR_OK) { error_print(); goto end; } format_print(fp, fmt, ind, "Object:\n"); format_print(fp, fmt, ind + 4, "Name: %s\n", (char *)&(fileInfo.FileName)); format_print(fp, fmt, ind + 4, "Size: %u\n", fileInfo.FileSize); format_print(fp, fmt, ind + 4, "ReadRights: %08X\n", fileInfo.ReadRights); format_print(fp, fmt, ind + 4, "WriteRights: %08X\n", fileInfo.WriteRights); } ret = 1; end: if (hApp) SKF_CloseApplication(hApp); if (nameList) free(nameList); return ret; } int skf_import_object(SKF_DEVICE *dev, const char *appname, const char *pin, const char *objname, const uint8_t *data, size_t datalen) { int ret = -1; HAPPLICATION hApp = NULL; ULONG ulReadRights = SECURE_ANYONE_ACCOUNT; ULONG ulWriteRights = SECURE_USER_ACCOUNT; if (!dev || !appname || !pin || !objname || !data || !datalen) { error_print(); return -1; } if (datalen > SKF_MAX_FILE_SIZE) { error_print(); return -1; } if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_CreateFile(hApp, (LPSTR)objname, (ULONG)datalen, ulReadRights, ulWriteRights) != SAR_OK || SKF_WriteFile(hApp, (LPSTR)objname, 0, (BYTE *)data, (ULONG)datalen) != SAR_OK) { error_print(); goto end; } ret = 1; end: if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_export_object(SKF_DEVICE *dev, const char *appname, const char *pin, const char *objname, uint8_t *out, size_t *outlen) { int ret = -1; HAPPLICATION hApp = NULL; FILEATTRIBUTE fileInfo; ULONG ulen; if (!dev || !appname || !pin || !objname || !outlen) { error_print(); return -1; } if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_GetFileInfo(hApp, (LPSTR)objname, &fileInfo) != SAR_OK) { error_print(); goto end; } if (fileInfo.FileSize > SKF_MAX_FILE_SIZE) { error_print(); goto end; } if (!out) { *outlen = (size_t)fileInfo.FileSize; ret = 1; goto end; } ulen = fileInfo.FileSize; if (SKF_ReadFile(hApp, (LPSTR)objname, 0, fileInfo.FileSize, out, &ulen) != SAR_OK) { goto end; } if (ulen != fileInfo.FileSize) { error_print(); goto end; } *outlen = ulen; ret = 1; end: if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_delete_object(SKF_DEVICE *dev, const char *appname, const char *pin, const char *objname) { int ret = -1; HAPPLICATION hApp = NULL; if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_DeleteFile(hApp, (LPSTR)objname) != SAR_OK) { error_print(); goto end; } ret = 1; end: if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_list_containers(FILE *fp, int fmt, int ind, const char *label, SKF_DEVICE *dev, const char *appname, const char *pin) { int ret = -1; HAPPLICATION hApp = NULL; HCONTAINER hContainer = NULL; char *nameList = NULL; ULONG nameListLen = 0; const char *name; int i; format_print(fp, fmt, ind, "%s\n", label); ind += 4; if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_EnumContainer(hApp, NULL, &nameListLen) != SAR_OK) { error_print(); goto end; } if (nameListLen <= 1) { ret = 0; goto end; } if (!(nameList = malloc(nameListLen))) { error_print(); goto end; } if (SKF_EnumContainer(hApp, (LPSTR)nameList, &nameListLen) != SAR_OK) { error_print(); goto end; } for (name = nameList, i = 0; *name; name += strlen(name) + 1, i++) { ULONG containerType; LPSTR containerTypeName; if (SKF_OpenContainer(hApp, (LPSTR)name, &hContainer) != SAR_OK || SKF_GetContainerType(hContainer, &containerType) != SAR_OK || SKF_GetContainerTypeName(containerType, &containerTypeName) != SAR_OK || SKF_CloseContainer(hContainer) != SAR_OK) { error_print(); goto end; } hContainer = NULL; (void)format_print(fp, fmt, ind, "Container:\n"); (void)format_print(fp, fmt, ind + 4, "Name: %s\n", name); (void)format_print(fp, fmt, ind + 4, "Type: %s\n", (char *)containerTypeName); } ret = 1; end: if (hContainer) SKF_CloseContainer(hContainer); if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_create_container(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name) { int ret = -1; HAPPLICATION hApp = NULL; HCONTAINER hContainer = NULL; ECCPUBLICKEYBLOB publicKey = {0, {0}, {0}}; if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_CreateContainer(hApp, (LPSTR)container_name, &hContainer) != SAR_OK || SKF_GenECCKeyPair(hContainer, SGD_SM2_1, &publicKey) != SAR_OK) { error_print(); goto end; } ret = 1; end: if (hContainer) SKF_CloseContainer(hContainer); if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_delete_container(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name) { int ret = -1; HAPPLICATION hApp = NULL; if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_DeleteContainer(hApp, (LPSTR)container_name) != SAR_OK) { error_print(); goto end; } ret = 1; end: if (hApp) SKF_CloseApplication(hApp); return 1; } int skf_import_sign_cert(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name, const uint8_t *cert, size_t certlen) { int ret = 0; HAPPLICATION hApp = NULL; HCONTAINER hContainer = NULL; ULONG containerType; BOOL bSign = SGD_TRUE; if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_GetContainerType(hContainer, &containerType) != SAR_OK) { error_print(); goto end; } if (containerType == SKF_CONTAINER_TYPE_UNDEF) { error_print(); goto end; } if (containerType != SKF_CONTAINER_TYPE_ECC) { error_print(); goto end; } // FIXME: 判断导入证书的类型是否为签名证书 if (SKF_ImportCertificate(hContainer, bSign, (BYTE *)cert, (ULONG)certlen) != SAR_OK) { error_print(); goto end; } ret = 1; end: if (hContainer) SKF_CloseContainer(hContainer); if (hApp) SKF_CloseApplication(hApp); return ret; } int skf_export_sign_cert(SKF_DEVICE *dev, const char *appname, const char *pin, const char *container_name, uint8_t *cert, size_t *certlen) { int ret = -1; HAPPLICATION hApp = NULL; HCONTAINER hContainer = NULL; ULONG containerType; BOOL bSign = SGD_TRUE; ULONG ulCertLen = 0; if (skf_open_app(dev, appname, pin, &hApp) != 1) { error_print(); return -1; } if (SKF_GetContainerType(hContainer, &containerType) != SAR_OK) { error_print(); goto end; } if (containerType != SKF_CONTAINER_TYPE_ECC) { error_print(); goto end; } if (SKF_ExportCertificate(hContainer, bSign, (BYTE *)cert, &ulCertLen) != SAR_OK) { error_print(); goto end; } ret = 1; end: if (hContainer) SKF_CloseContainer(hContainer); if (hApp) SKF_CloseApplication(hApp); return ret; }