opensc/src/pkcs11/generic.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;
}