Added basic session management.
Implemented login, logout and change pin functions. Improved card management. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@9 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
4636ef6516
commit
86bbeffc40
|
@ -1,7 +1,7 @@
|
|||
#include "sc-pkcs11.h"
|
||||
|
||||
CK_FUNCTION_LIST function_list = {
|
||||
{ 2, 10 },
|
||||
{ 2, 11 },
|
||||
// generic.c
|
||||
C_Initialize,
|
||||
C_Finalize,
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
#include "../sc.h"
|
||||
|
||||
struct sc_context *ctx = NULL;
|
||||
struct sc_pkcs15_card *p15card = NULL;
|
||||
struct sc_pkcs15_card *p15card[PKCS11_MAX_CARDS];
|
||||
struct pkcs11_session *session[PKCS11_MAX_SESSIONS];
|
||||
|
||||
void LOG(char *format, ...)
|
||||
{
|
||||
|
@ -26,11 +27,13 @@ void LOG(char *format, ...)
|
|||
|
||||
CK_RV C_Initialize(CK_VOID_PTR pReserved)
|
||||
{
|
||||
int reader_count, reader_buf_size, rv;
|
||||
char *reader_buf, *p;
|
||||
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) {
|
||||
|
@ -42,13 +45,16 @@ CK_RV C_Initialize(CK_VOID_PTR pReserved)
|
|||
|
||||
CK_RV C_Finalize(CK_VOID_PTR pReserved)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
LOG("C_Finalize(0x%x)\n", pReserved);
|
||||
|
||||
if (p15card != NULL) {
|
||||
sc_disconnect_card(p15card->card);
|
||||
sc_pkcs15_destroy(p15card);
|
||||
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);
|
||||
|
||||
|
@ -60,7 +66,7 @@ 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 = 10;
|
||||
pInfo->cryptokiVersion.minor = 11;
|
||||
strcpy(pInfo->manufacturerID, "Timo Teras & Juha Yrjola");
|
||||
strcpy(pInfo->libraryDescription, "PC/SC PKCS#15 SmartCard reader");
|
||||
pInfo->libraryVersion.major = 0;
|
||||
|
@ -79,7 +85,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese
|
|||
CK_SLOT_ID_PTR pSlotList, /* receives the array of slot IDs */
|
||||
CK_ULONG_PTR pulCount) /* receives the number of slots */
|
||||
{
|
||||
int i, num;
|
||||
int i;
|
||||
|
||||
LOG("C_GetSlotList(%d, 0x%x, 0x%x)\n", tokenPresent, pSlotList, pulCount);
|
||||
|
||||
|
@ -88,10 +94,14 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
num = ctx->reader_count > *pulCount ? *pulCount : ctx->reader_count;
|
||||
for (i = 0; i < num; i++)
|
||||
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 = num;
|
||||
*pulCount = ctx->reader_count;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
@ -108,13 +118,14 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
|
|||
sizeof(pInfo->slotDescription));
|
||||
strcpy(pInfo->manufacturerID, "PC/SC interface");
|
||||
pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
|
||||
if (sc_detect_card(ctx, slotID) == 1)
|
||||
if (sc_detect_card(ctx, slotID) == 1) {
|
||||
LOG("Detected card in slot %d\n", slotID);
|
||||
pInfo->flags |= CKF_TOKEN_PRESENT;
|
||||
else {
|
||||
if (p15card != NULL) {
|
||||
sc_disconnect_card(p15card->card);
|
||||
sc_pkcs15_destroy(p15card);
|
||||
p15card = NULL;
|
||||
} else {
|
||||
if (p15card[slotID] != NULL) {
|
||||
sc_disconnect_card(p15card[slotID]->card);
|
||||
sc_pkcs15_destroy(p15card[slotID]);
|
||||
p15card[slotID] = NULL;
|
||||
}
|
||||
}
|
||||
pInfo->hardwareVersion.major = 1;
|
||||
|
@ -134,18 +145,21 @@ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
|
|||
|
||||
memset(pInfo, 0, sizeof(CK_SLOT_INFO));
|
||||
|
||||
if (p15card == NULL) {
|
||||
if (p15card[slotID] == NULL) {
|
||||
r = sc_connect_card(ctx, slotID, &card);
|
||||
if (r)
|
||||
return CKR_DEVICE_ERROR;
|
||||
r = sc_pkcs15_init(card, &p15card);
|
||||
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;
|
||||
}
|
||||
}
|
||||
strcpy(pInfo->label, p15card->label);
|
||||
strcpy(pInfo->label, p15card[slotID]->label);
|
||||
strcpy(pInfo->manufacturerID, "unknown");
|
||||
strcpy(pInfo->model, "unknown");
|
||||
strcpy(pInfo->serialNumber, "unknown");
|
||||
|
@ -172,15 +186,35 @@ CK_RV C_GetMechanismList(CK_SLOT_ID slotID,
|
|||
CK_MECHANISM_TYPE_PTR pMechanismList,
|
||||
CK_ULONG_PTR pulCount)
|
||||
{
|
||||
LOG("C_GetMechanismList(%d, 0x%x, 0x%x)\n", slotID, pMechanismList, pulCount);
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
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);
|
||||
LOG("C_GetMechanismInfo(%d, %d, 0x%x)\n", slotID, type, pInfo);
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -193,20 +227,4 @@ CK_RV C_InitToken(CK_SLOT_ID slotID,
|
|||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
CK_RV C_InitPIN(CK_SESSION_HANDLE hSession,
|
||||
CK_CHAR_PTR pPin,
|
||||
CK_ULONG ulPinLen)
|
||||
{
|
||||
LOG("C_InitPIN(%d, '%s', %d)\n", hSession, pPin, ulPinLen);
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
|
||||
CK_CHAR_PTR pOldPin,
|
||||
CK_ULONG ulOldLen,
|
||||
CK_CHAR_PTR pNewPin,
|
||||
CK_ULONG ulNewLen)
|
||||
{
|
||||
LOG("C_SetPIN(%d, '%s', %d, '%s', %d)\n", hSession, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,28 @@
|
|||
#ifndef __sc_pkcs11_h__
|
||||
#define __sc_pkcs11_h__
|
||||
|
||||
#include "pkcs11/pkcs11.h"
|
||||
#include <winscard.h>
|
||||
|
||||
#include "pkcs11/pkcs11.h"
|
||||
#include "../sc.h"
|
||||
|
||||
#define PKCS11_MAX_CARDS 4
|
||||
#define PKCS11_MAX_SESSIONS 8
|
||||
|
||||
struct pkcs11_session {
|
||||
int slot;
|
||||
CK_STATE state;
|
||||
CK_FLAGS flags;
|
||||
CK_NOTIFY notify_callback;
|
||||
CK_VOID_PTR notify_parameter;
|
||||
};
|
||||
|
||||
extern CK_FUNCTION_LIST function_list;
|
||||
extern void LOG(char *format, ...);
|
||||
|
||||
extern SCARDCONTEXT sc_ctx;
|
||||
extern struct sc_context *ctx;
|
||||
extern struct sc_pkcs15_card *p15card[PKCS11_MAX_CARDS];
|
||||
extern struct pkcs11_session *session[PKCS11_MAX_SESSIONS];
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include "sc-pkcs11.h"
|
||||
|
||||
|
||||
|
@ -7,29 +9,111 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */
|
|||
CK_NOTIFY Notify, /* notification callback function */
|
||||
CK_SESSION_HANDLE_PTR phSession) /* receives new session handle */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
int i, rc;
|
||||
struct pkcs11_session *ses;
|
||||
|
||||
LOG("C_OpenSession(%d, 0x%x, 0x%x, 0x%x, 0x%x)\n",
|
||||
slotID, flags, pApplication, Notify, phSession);
|
||||
|
||||
if (!(flags & CKF_SERIAL_SESSION))
|
||||
return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
|
||||
|
||||
for (i=0; i<PKCS11_MAX_SESSIONS; i++)
|
||||
if (session[i] == NULL)
|
||||
break;
|
||||
|
||||
if (i >= PKCS11_MAX_SESSIONS)
|
||||
return CKR_SESSION_COUNT;
|
||||
|
||||
if (p15card[slotID] == NULL) {
|
||||
struct sc_card *card;
|
||||
|
||||
rc = sc_connect_card(ctx, slotID, &card);
|
||||
if (rc) {
|
||||
LOG("Failed to connect in slot %d (rc=%d)\n", slotID, rc);
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
rc = sc_pkcs15_init(card, &p15card[slotID]);
|
||||
if (rc) {
|
||||
LOG("sc_pkcs15_init failed for slot %d (rc=%d)\n", slotID, rc);
|
||||
/* PKCS#15 compatible SC probably not present */
|
||||
sc_disconnect_card(card);
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (p15card[slotID]->pins[0].magic != SC_PKCS15_PIN_MAGIC) {
|
||||
struct sc_pkcs15_pin_object pin;
|
||||
int c = 0;
|
||||
|
||||
LOG("Searching for PIN codes...\n");
|
||||
while (sc_pkcs15_read_pin_object(p15card[slotID], ++c, &pin) == 0) {
|
||||
sc_pkcs15_print_pin_object(&pin);
|
||||
}
|
||||
}
|
||||
|
||||
ses = session[i] = (struct pkcs11_session*) malloc(sizeof(struct pkcs11_session));
|
||||
memset(ses, 0, sizeof(struct pkcs11_session));
|
||||
ses->slot = slotID;
|
||||
if (flags & CKF_RW_SESSION)
|
||||
ses->state = CKS_RW_PUBLIC_SESSION;
|
||||
else ses->state = CKS_RO_PUBLIC_SESSION;
|
||||
ses->flags = flags;
|
||||
ses->notify_callback = Notify;
|
||||
ses->notify_parameter = pApplication;
|
||||
|
||||
*phSession = i;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) /* the session's handle */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
LOG("C_CloseSession(0x%x)\n", hSession);
|
||||
if (hSession < 0 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
free(session[hSession]);
|
||||
session[hSession] = NULL;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) /* the token's slot */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
int i;
|
||||
|
||||
LOG("C_CloseAllSessions(%d)\n", slotID);
|
||||
for (i = 0; i < PKCS11_MAX_SESSIONS; i++) {
|
||||
if (session[i] && session[i]->slot == slotID)
|
||||
C_CloseSession(i);
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_SESSION_INFO_PTR pInfo) /* receives session information */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
struct pkcs11_session *ses;
|
||||
|
||||
LOG("C_GetSessionInfo(0x%x, 0x%x)\n", hSession, pInfo);
|
||||
if (hSession < 0 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
ses = session[hSession];
|
||||
pInfo->slotID = ses->slot;
|
||||
pInfo->state = ses->state;
|
||||
pInfo->flags = ses->flags;
|
||||
pInfo->ulDeviceError = 0;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pOperationState, /* location receiving state */
|
||||
CK_ULONG_PTR pulOperationStateLen) /* location receiving state length */
|
||||
{
|
||||
LOG("C_GetOperationState(0x%x, %0x%x, %d)\n", hSession,
|
||||
pOperationState, pulOperationStateLen);
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -39,6 +123,9 @@ CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, /* the session'
|
|||
CK_OBJECT_HANDLE hEncryptionKey, /* handle of en/decryption key */
|
||||
CK_OBJECT_HANDLE hAuthenticationKey) /* handle of sign/verify key */
|
||||
{
|
||||
LOG("C_SetOperationState(0x%x, 0x%x, %d, 0x%x, 0x%x)\n",
|
||||
hSession, pOperationState, ulOperationStateLen,
|
||||
hEncryptionKey, hAuthenticationKey);
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -47,12 +134,116 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
CK_CHAR_PTR pPin, /* the user's PIN */
|
||||
CK_ULONG ulPinLen) /* the length of the PIN */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
struct pkcs11_session *ses;
|
||||
struct sc_pkcs15_card *card;
|
||||
int rc;
|
||||
|
||||
LOG("C_Login(0x%x, %d, 0x%x, %d)\n", hSession, userType, pPin, ulPinLen);
|
||||
if (hSession < 0 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
if (userType != CKU_USER) {
|
||||
LOG("Login tried for Security Officer\n");
|
||||
return CKR_USER_TYPE_INVALID;
|
||||
}
|
||||
|
||||
if (ulPinLen < 4 || ulPinLen > 8)
|
||||
return CKR_PIN_LEN_RANGE;
|
||||
|
||||
ses = session[hSession];
|
||||
card = p15card[ses->slot];
|
||||
|
||||
if (ses->state != CKS_RO_PUBLIC_SESSION &&
|
||||
ses->state != CKS_RW_PUBLIC_SESSION)
|
||||
return CKR_USER_ALREADY_LOGGED_IN;
|
||||
|
||||
LOG("Master PIN code verification starts.\n");
|
||||
rc = sc_pkcs15_verify_pin(card, &card->pins[0], pPin, ulPinLen);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
LOG("Master PIN code verified succesfully.\n");
|
||||
if (ses->state == CKS_RO_PUBLIC_SESSION)
|
||||
ses->state = CKS_RO_USER_FUNCTIONS;
|
||||
else ses->state = CKS_RW_USER_FUNCTIONS;
|
||||
break;
|
||||
case SC_ERROR_PIN_CODE_INCORRECT:
|
||||
LOG("Master PIN code INVALID!\n");
|
||||
return CKR_PIN_INCORRECT;
|
||||
default:
|
||||
LOG("Device error!? rc=%d\n", rc);
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV C_Logout(CK_SESSION_HANDLE hSession) /* the session's handle */
|
||||
{
|
||||
struct pkcs11_session *ses;
|
||||
|
||||
LOG("C_Logout(0x%x)\n", hSession);
|
||||
if (hSession < 0 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
ses = session[hSession];
|
||||
switch (ses->state) {
|
||||
case CKS_RO_PUBLIC_SESSION:
|
||||
case CKS_RW_PUBLIC_SESSION:
|
||||
return CKR_USER_NOT_LOGGED_IN;
|
||||
case CKS_RO_USER_FUNCTIONS:
|
||||
ses->state = CKS_RO_PUBLIC_SESSION;
|
||||
break;
|
||||
case CKS_RW_USER_FUNCTIONS:
|
||||
case CKS_RW_SO_FUNCTIONS:
|
||||
ses->state = CKS_RW_PUBLIC_SESSION;
|
||||
break;
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV C_InitPIN(CK_SESSION_HANDLE hSession,
|
||||
CK_CHAR_PTR pPin,
|
||||
CK_ULONG ulPinLen)
|
||||
{
|
||||
LOG("C_InitPIN(%d, '%s', %d)\n", hSession, pPin, ulPinLen);
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
|
||||
CK_CHAR_PTR pOldPin,
|
||||
CK_ULONG ulOldLen,
|
||||
CK_CHAR_PTR pNewPin,
|
||||
CK_ULONG ulNewLen)
|
||||
{
|
||||
struct pkcs11_session *ses;
|
||||
struct sc_pkcs15_card *card;
|
||||
int rc;
|
||||
|
||||
LOG("C_SetPIN(%d, '%s', %d, '%s', %d)\n", hSession, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||
if (hSession < 0 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
//if (!(ses->flags & CKF_RW_SESSION))
|
||||
// return CKR_SESSION_READ_ONLY;
|
||||
|
||||
ses = session[hSession];
|
||||
card = p15card[ses->slot];
|
||||
|
||||
LOG("Master PIN code update starts.\n");
|
||||
rc = sc_pkcs15_change_pin(card, &card->pins[0], pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||
switch (rc) {
|
||||
case 0:
|
||||
LOG("Master PIN code CHANGED succesfully.\n");
|
||||
break;
|
||||
case SC_ERROR_PIN_CODE_INCORRECT:
|
||||
LOG("Master PIN code INVALID!\n");
|
||||
return CKR_PIN_INCORRECT;
|
||||
default:
|
||||
LOG("Device error!? rc=%d\n", rc);
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue