240 lines
6.2 KiB
C
240 lines
6.2 KiB
C
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
|
|
#include <winscard.h>
|
|
|
|
#include "sc-pkcs11.h"
|
|
#include "../sc.h"
|
|
|
|
struct sc_context *ctx = NULL;
|
|
struct sc_pkcs15_card *p15card[PKCS11_MAX_CARDS];
|
|
struct pkcs11_session *session[PKCS11_MAX_SESSIONS];
|
|
|
|
void LOG(char *format, ...)
|
|
{
|
|
va_list valist;
|
|
FILE *out;
|
|
|
|
out = fopen("/tmp/libsc-pkcs11.log", "a");
|
|
if (out != NULL) {
|
|
va_start(valist, format);
|
|
vfprintf(out, format, valist);
|
|
va_end(valist);
|
|
fclose(out);
|
|
}
|
|
}
|
|
|
|
CK_RV C_Initialize(CK_VOID_PTR pReserved)
|
|
{
|
|
int rv;
|
|
|
|
LOG("C_Initialize(0x%x)\n", pReserved);
|
|
|
|
memset(session, 0, sizeof(session));
|
|
memset(p15card, 0, sizeof(p15card));
|
|
|
|
ctx = NULL;
|
|
rv = sc_establish_context(&ctx);
|
|
if (rv != 0) {
|
|
LOG("ERROR: Unable to connect to Resource Manager\n");
|
|
return CKR_DEVICE_ERROR;
|
|
}
|
|
return CKR_OK;
|
|
}
|
|
|
|
CK_RV C_Finalize(CK_VOID_PTR pReserved)
|
|
{
|
|
int i;
|
|
|
|
LOG("C_Finalize(0x%x)\n", pReserved);
|
|
|
|
for (i=0; i < PKCS11_MAX_CARDS; i++) {
|
|
if (p15card[i] != NULL) {
|
|
sc_disconnect_card(p15card[i]->card);
|
|
sc_pkcs15_destroy(p15card[i]);
|
|
p15card[i] = NULL;
|
|
}
|
|
}
|
|
sc_destroy_context(ctx);
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
CK_RV C_GetInfo(CK_INFO_PTR pInfo)
|
|
{
|
|
LOG("C_GetInfo(0x%x)\n", pInfo);
|
|
memset(pInfo, 0, sizeof(CK_INFO));
|
|
pInfo->cryptokiVersion.major = 2;
|
|
pInfo->cryptokiVersion.minor = 11;
|
|
strcpy(pInfo->manufacturerID, "Timo Teras & Juha Yrjola");
|
|
strcpy(pInfo->libraryDescription, "PC/SC PKCS#15 SmartCard reader");
|
|
pInfo->libraryVersion.major = 0;
|
|
pInfo->libraryVersion.minor = 1;
|
|
return CKR_OK;
|
|
}
|
|
|
|
CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
|
|
{
|
|
LOG("C_GetFunctionList(0x%x)\n", ppFunctionList);
|
|
*ppFunctionList = &function_list;
|
|
return CKR_OK;
|
|
}
|
|
|
|
CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token present */
|
|
CK_SLOT_ID_PTR pSlotList, /* receives the array of slot IDs */
|
|
CK_ULONG_PTR pulCount) /* receives the number of slots */
|
|
{
|
|
int i;
|
|
|
|
LOG("C_GetSlotList(%d, 0x%x, 0x%x)\n", tokenPresent, pSlotList, pulCount);
|
|
|
|
if (pSlotList == NULL_PTR) {
|
|
*pulCount = ctx->reader_count;
|
|
return CKR_OK;
|
|
}
|
|
|
|
if (*pulCount < ctx->reader_count) {
|
|
*pulCount = ctx->reader_count;
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
for (i = 0; i < ctx->reader_count; i++)
|
|
pSlotList[i] = i;
|
|
*pulCount = ctx->reader_count;
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
|
|
{
|
|
LOG("C_GetSlotInfo(%d, 0x%x)\n", slotID, pInfo);
|
|
|
|
if (slotID < 0 || slotID >= ctx->reader_count)
|
|
return CKR_SLOT_ID_INVALID;
|
|
|
|
memset(pInfo, 0, sizeof(CK_SLOT_INFO));
|
|
strncpy(pInfo->slotDescription, ctx->readers[slotID],
|
|
sizeof(pInfo->slotDescription));
|
|
strcpy(pInfo->manufacturerID, "PC/SC interface");
|
|
pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
|
|
if (sc_detect_card(ctx, slotID) == 1) {
|
|
LOG("Detected card in slot %d\n", slotID);
|
|
pInfo->flags |= CKF_TOKEN_PRESENT;
|
|
} else {
|
|
if (p15card[slotID] != NULL) {
|
|
sc_disconnect_card(p15card[slotID]->card);
|
|
sc_pkcs15_destroy(p15card[slotID]);
|
|
p15card[slotID] = NULL;
|
|
}
|
|
}
|
|
pInfo->hardwareVersion.major = 1;
|
|
pInfo->firmwareVersion.major = 1;
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
|
|
{
|
|
int r;
|
|
struct sc_card *card;
|
|
|
|
LOG("C_GetTokenInfo(%d, 0x%x)\n", slotID, pInfo);
|
|
if (slotID < 0 || slotID >= ctx->reader_count)
|
|
return CKR_SLOT_ID_INVALID;
|
|
|
|
memset(pInfo, 0, sizeof(CK_SLOT_INFO));
|
|
|
|
if (p15card[slotID] == NULL) {
|
|
r = sc_connect_card(ctx, slotID, &card);
|
|
if (r) {
|
|
LOG("Failed to connect in slot %d (r=%d)\n", slotID, r);
|
|
return CKR_DEVICE_ERROR;
|
|
}
|
|
r = sc_pkcs15_init(card, &p15card[slotID]);
|
|
if (r) {
|
|
LOG("sc_pkcs15_init failed for slot %d (r=%d)\n", slotID, r);
|
|
/* PKCS#15 compatible SC probably not present */
|
|
sc_disconnect_card(card);
|
|
return CKR_DEVICE_ERROR;
|
|
}
|
|
}
|
|
strncpy(pInfo->label, p15card[slotID]->label, 32);
|
|
pInfo->label[31] = 0;
|
|
strncpy(pInfo->manufacturerID, p15card[slotID]->manufacturer_id, 32);
|
|
pInfo->manufacturerID[31] = 0;
|
|
strcpy(pInfo->model, "PKCS#15 SC");
|
|
strncpy(pInfo->serialNumber, p15card[slotID]->serial_number, 16);
|
|
pInfo->serialNumber[15] = 0;
|
|
pInfo->flags = CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED;
|
|
pInfo->ulMaxSessionCount = 1; /* opened in exclusive mode */
|
|
pInfo->ulSessionCount = 0;
|
|
pInfo->ulMaxRwSessionCount = 1;
|
|
pInfo->ulRwSessionCount = 0;
|
|
if (p15card[slotID]->pins[0].magic == SC_PKCS15_PIN_MAGIC) {
|
|
pInfo->ulMaxPinLen = p15card[slotID]->pins[0].stored_length;
|
|
pInfo->ulMinPinLen = p15card[slotID]->pins[0].min_length;
|
|
} else {
|
|
/* choose reasonable defaults */
|
|
pInfo->ulMaxPinLen = 8;
|
|
pInfo->ulMinPinLen = 4;
|
|
}
|
|
pInfo->ulTotalPublicMemory = 0;
|
|
pInfo->ulFreePublicMemory = 0;
|
|
pInfo->ulTotalPrivateMemory = 0;
|
|
pInfo->ulFreePrivateMemory = 0;
|
|
pInfo->hardwareVersion.major = 1;
|
|
pInfo->hardwareVersion.minor = 0;
|
|
pInfo->firmwareVersion.major = 1;
|
|
pInfo->firmwareVersion.minor = 0;
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
CK_RV C_GetMechanismList(CK_SLOT_ID slotID,
|
|
CK_MECHANISM_TYPE_PTR pMechanismList,
|
|
CK_ULONG_PTR pulCount)
|
|
{
|
|
static const CK_MECHANISM_TYPE mechanism_list[] = {
|
|
CKM_RSA_PKCS,
|
|
CKM_RSA_X_509
|
|
};
|
|
const int numMechanisms = sizeof(mechanism_list) / sizeof(mechanism_list[0]);
|
|
|
|
LOG("C_GetMechanismList(%d, 0x%x, 0x%x)\n", slotID, pMechanismList, pulCount);
|
|
if (slotID < 0 || slotID >= ctx->reader_count)
|
|
return CKR_SLOT_ID_INVALID;
|
|
|
|
if (pMechanismList == NULL_PTR) {
|
|
*pulCount = numMechanisms;
|
|
return CKR_OK;
|
|
}
|
|
|
|
if (*pulCount < numMechanisms) {
|
|
*pulCount = numMechanisms;
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
}
|
|
memcpy(pMechanismList, &mechanism_list, sizeof(mechanism_list));
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
|
|
CK_MECHANISM_TYPE type,
|
|
CK_MECHANISM_INFO_PTR pInfo)
|
|
{
|
|
LOG("C_GetMechanismInfo(%d, %d, 0x%x)\n", slotID, type, pInfo);
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
}
|
|
|
|
CK_RV C_InitToken(CK_SLOT_ID slotID,
|
|
CK_CHAR_PTR pPin,
|
|
CK_ULONG ulPinLen,
|
|
CK_CHAR_PTR pLabel)
|
|
{
|
|
LOG("C_InitToken(%d, '%s', %d, '%s')\n", slotID, pPin, ulPinLen, pLabel);
|
|
return CKR_FUNCTION_NOT_SUPPORTED;
|
|
}
|
|
|
|
|