diff --git a/src/pkcs11/digestsign.c b/src/pkcs11/digestsign.c index 04da89d6..7245a740 100644 --- a/src/pkcs11/digestsign.c +++ b/src/pkcs11/digestsign.c @@ -3,6 +3,7 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism) /* the digesting mechanism */ { + LOG("C_DigestInit\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -12,6 +13,7 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pDigest, /* receives the message digest */ CK_ULONG_PTR pulDigestLen) /* receives byte length of digest */ { + LOG("C_Digest\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -19,12 +21,14 @@ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pPart, /* data to be digested */ CK_ULONG ulPartLen) /* bytes of data to be digested */ { + LOG("C_DigestUpdate\n"); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hKey) /* handle of secret key to digest */ { + LOG("C_DigestKey\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -32,6 +36,7 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pDigest, /* receives the message digest */ CK_ULONG_PTR pulDigestLen) /* receives byte count of digest */ { + LOG("C_DigestFinal\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -39,6 +44,7 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ CK_OBJECT_HANDLE hKey) /* handle of the signature key */ { + LOG("C_SignInit\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -48,6 +54,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSignature, /* receives the signature */ CK_ULONG_PTR pulSignatureLen) /* receives byte count of signature */ { + LOG("C_Sign\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -55,6 +62,7 @@ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pPart, /* the data (digest) to be signed */ CK_ULONG ulPartLen) /* count of bytes to be signed */ { + LOG("C_SignUpdate\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -62,6 +70,7 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSignature, /* receives the signature */ CK_ULONG_PTR pulSignatureLen) /* receives byte count of signature */ { + LOG("C_SignFinal\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -69,6 +78,7 @@ CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */ CK_OBJECT_HANDLE hKey) /* handle of the signature key */ { + LOG("C_SignRecoverInit\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -78,6 +88,7 @@ CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, /* the session's handle * CK_BYTE_PTR pSignature, /* receives the signature */ CK_ULONG_PTR pulSignatureLen) /* receives byte count of signature */ { + LOG("C_SignRecover\n"); return CKR_FUNCTION_NOT_SUPPORTED; } diff --git a/src/pkcs11/endecrypt.c b/src/pkcs11/endecrypt.c index 1ff0c6bb..3f8f3173 100644 --- a/src/pkcs11/endecrypt.c +++ b/src/pkcs11/endecrypt.c @@ -4,6 +4,7 @@ CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */ CK_OBJECT_HANDLE hKey) /* handle of encryption key */ { + LOG("C_EncryptInit\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -13,6 +14,7 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, /* the session's handle * CK_BYTE_PTR pEncryptedData, /* receives encrypted data */ CK_ULONG_PTR pulEncryptedDataLen) /* receives encrypted byte count */ { + LOG("C_Encrypt\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -22,6 +24,7 @@ CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, /* the session's han CK_BYTE_PTR pEncryptedPart, /* receives encrypted data */ CK_ULONG_PTR pulEncryptedPartLen)/* receives encrypted byte count */ { + LOG("C_EncryptUpdate\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -29,6 +32,7 @@ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, /* the session's CK_BYTE_PTR pLastEncryptedPart, /* receives encrypted last part */ CK_ULONG_PTR pulLastEncryptedPartLen) /* receives byte count */ { + LOG("C_EncryptFinal\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -37,6 +41,7 @@ CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */ CK_OBJECT_HANDLE hKey) /* handle of the decryption key */ { + LOG("C_DecryptInit\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -46,6 +51,7 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* receives decrypted output */ CK_ULONG_PTR pulDataLen) /* receives decrypted byte count */ { + LOG("C_Decrypt\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -55,6 +61,7 @@ CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, /* the session's ha CK_BYTE_PTR pPart, /* receives decrypted output */ CK_ULONG_PTR pulPartLen) /* receives decrypted byte count */ { + LOG("C_DecryptUpdate\n"); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -62,6 +69,7 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, /* the session's handle * CK_BYTE_PTR pLastPart, /* receives decrypted output */ CK_ULONG_PTR pulLastPartLen) /* receives decrypted byte count */ { + LOG("C_DecryptFinal\n"); return CKR_FUNCTION_NOT_SUPPORTED; } diff --git a/src/pkcs11/generic.c b/src/pkcs11/generic.c index 441ca627..b993946f 100644 --- a/src/pkcs11/generic.c +++ b/src/pkcs11/generic.c @@ -8,8 +8,8 @@ #include "../sc.h" struct sc_context *ctx = NULL; -struct sc_pkcs15_card *p15card[PKCS11_MAX_CARDS]; -struct pkcs11_session *session[PKCS11_MAX_SESSIONS]; +struct pkcs11_slot slot[PKCS11_MAX_SLOTS]; +struct pkcs11_session *session[PKCS11_MAX_SESSIONS+1]; void LOG(char *format, ...) { @@ -32,7 +32,7 @@ CK_RV C_Initialize(CK_VOID_PTR pReserved) LOG("C_Initialize(0x%x)\n", pReserved); memset(session, 0, sizeof(session)); - memset(p15card, 0, sizeof(p15card)); + memset(slot, 0, sizeof(slot)); ctx = NULL; rv = sc_establish_context(&ctx); @@ -49,15 +49,10 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved) 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); + for (i=0; i < PKCS11_MAX_SLOTS; i++) + slot_disconnect(i); + sc_destroy_context(ctx); return CKR_OK; } @@ -122,11 +117,7 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) 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; - } + slot_disconnect(slotID); } pInfo->hardwareVersion.major = 1; pInfo->firmwareVersion.major = 1; @@ -137,7 +128,6 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) 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) @@ -145,35 +135,27 @@ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) 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; - } + if (!(slot[slotID].flags & SLOT_CONNECTED)) { + r = slot_connect(slotID); + if (r) + return r; } - strncpy(pInfo->label, p15card[slotID]->label, 32); + strncpy(pInfo->label, slot[slotID].p15card->label, 32); pInfo->label[31] = 0; - strncpy(pInfo->manufacturerID, p15card[slotID]->manufacturer_id, 32); + strncpy(pInfo->manufacturerID, slot[slotID].p15card->manufacturer_id, 32); pInfo->manufacturerID[31] = 0; strcpy(pInfo->model, "PKCS#15 SC"); - strncpy(pInfo->serialNumber, p15card[slotID]->serial_number, 16); + strncpy(pInfo->serialNumber, slot[slotID].p15card->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; + if (slot[slotID].p15card->pins[0].magic == SC_PKCS15_PIN_MAGIC) { + pInfo->ulMaxPinLen = slot[slotID].p15card->pins[0].stored_length; + pInfo->ulMinPinLen = slot[slotID].p15card->pins[0].min_length; } else { /* choose reasonable defaults */ pInfo->ulMaxPinLen = 8; diff --git a/src/pkcs11/object.c b/src/pkcs11/object.c index 1d228dc5..4b6d191c 100644 --- a/src/pkcs11/object.c +++ b/src/pkcs11/object.c @@ -1,10 +1,41 @@ +#include + #include "sc-pkcs11.h" +#define min(a,b) (((a)<(b))?(a):(b)) + +static void dump_template(char *info, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) +{ + int i, j; + + for (i = 0; i < ulCount; i++) { + char foo[1024] = ""; + unsigned char *value = (unsigned char*) pTemplate[i].pValue; + + if (pTemplate[i].pValue) { + if (pTemplate[i].ulValueLen < 16) { + for (j = 0; j < pTemplate[i].ulValueLen; j++) + sprintf(&foo[j*2], "%02X", value[j]); + + LOG("%s: Attribute 0x%x = %s (length=%d)\n", + info, pTemplate[i].type, foo, pTemplate[i].ulValueLen); + } else { + LOG("%s: Attribute 0x%x = ... (length=%d)\n", + info, pTemplate[i].type, pTemplate[i].ulValueLen); + } + } else { + LOG("%s: Attribute 0x%x, length inquiry\n", + info, pTemplate[i].type); + } + } +} + CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */ CK_ULONG ulCount, /* attributes in template */ CK_OBJECT_HANDLE_PTR phObject) /* receives new object's handle. */ { + LOG("C_CreateObject(%d, 0x%x, %d, 0x%d)\n", hSession, pTemplate, ulCount, phObject); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -14,12 +45,15 @@ CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_ULONG ulCount, /* attributes in template */ CK_OBJECT_HANDLE_PTR phNewObject) /* receives handle of copy */ { + LOG("C_CopyObject(%d, %d, 0x%d, %d, 0x%x)\n", + hSession, hObject, pTemplate, ulCount, phNewObject); return CKR_FUNCTION_NOT_SUPPORTED; } CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject) /* the object's handle */ { + LOG("C_DestroyObject(%d, %d)\n", hSession, hObject); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -27,6 +61,7 @@ CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject, /* the object's handle */ CK_ULONG_PTR pulSize) /* receives size of object */ { + LOG("C_GetObjectSize(%d, %d, 0x%x)\n", hSession, hObject, pulSize); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -35,7 +70,65 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle CK_ATTRIBUTE_PTR pTemplate, /* specifies attributes, gets values */ CK_ULONG ulCount) /* attributes in template */ { - return CKR_FUNCTION_NOT_SUPPORTED; + struct pkcs11_slot *slt; + struct pkcs11_object *object; + int i, j; + + LOG("C_GetAttributeValue(%d, %d, 0x%x, %d)\n", hSession, hObject, pTemplate, ulCount); + dump_template("C_GetAttributeValue", pTemplate, ulCount); + + if (hSession < 1 || hSession > PKCS11_MAX_SESSIONS || session[hSession] == NULL) + return CKR_SESSION_HANDLE_INVALID; + slt = &slot[session[hSession]->slot]; + + if (hObject < 1 || hObject > slt->num_objects) + return CKR_OBJECT_HANDLE_INVALID; + + object = slt->object[hObject]; + + LOG("C_GetAttributeValue: Slot %d, Object: 0x%x, Attributes: %d\n", + session[hSession]->slot, object, object->num_attributes); + + for (i = 0; i < ulCount; i++) { + // For each request attribute + + // 1. Find matching attribute + for (j = 0; j < object->num_attributes; j++) { + if (pTemplate[i].type == object->attribute[j].type) + break; + } + + // 2. If object doesn't posses attribute + if (j >= object->num_attributes) { + pTemplate[i].ulValueLen = -1; + continue; + } + + // 3. If pValue is NULL_PTR then it's a size inquiry + if (pTemplate[i].pValue == NULL_PTR) { + pTemplate[i].ulValueLen = object->attribute[j].ulValueLen; + + LOG("C_GetAttributeValue: Attribute 0x%x length %d\n", + pTemplate[i].type, object->attribute[j].ulValueLen); + continue; + } + + // 4. If value fits then copy it and update true length + if (pTemplate[i].ulValueLen >= object->attribute[j].ulValueLen) { + LOG("C_GetAttributeValue: Copying attribute 0x%x length %d\n", + pTemplate[i].type, object->attribute[j].ulValueLen); + pTemplate[i].ulValueLen = object->attribute[j].ulValueLen; + memcpy(pTemplate[i].pValue, + object->attribute[j].pValue, + object->attribute[j].ulValueLen); + continue; + } + + // 5. Otherwise set length to minus one + pTemplate[i].ulValueLen = -1; + } + + return CKR_OK; } CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle */ @@ -43,6 +136,9 @@ CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle CK_ATTRIBUTE_PTR pTemplate, /* specifies attributes and values */ CK_ULONG ulCount) /* attributes in template */ { + LOG("C_SetAttributeValue(%d, %d, 0x%x, %d)\n", hSession, hObject, pTemplate, ulCount); + dump_template("C_SetAttributeValue", pTemplate, ulCount); + return CKR_FUNCTION_NOT_SUPPORTED; } @@ -50,7 +146,26 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */ CK_ULONG ulCount) /* attributes in search template */ { - return CKR_FUNCTION_NOT_SUPPORTED; + struct pkcs11_session *ses; + + LOG("C_FindObjectsInit(%d, %d, 0x%x, %d)\n", hSession, pTemplate, ulCount); + dump_template("C_FindObjectsInit", pTemplate, ulCount); + + if (hSession < 1 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL) + return CKR_SESSION_HANDLE_INVALID; + + if (ulCount != 1 || pTemplate[0].type != CKA_CLASS) + return CKR_ATTRIBUTE_TYPE_INVALID; + + if (pTemplate[0].ulValueLen != 4 || *((CK_ULONG_PTR) pTemplate[0].pValue) != CKO_CERTIFICATE) + return CKR_ATTRIBUTE_VALUE_INVALID; + + ses = session[hSession]; + ses->search.num_matches = 1; + ses->search.position = 0; + ses->search.handles[0] = 1; + + return CKR_OK; } CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's handle */ @@ -58,12 +173,40 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's han CK_ULONG ulMaxObjectCount, /* max handles to be returned */ CK_ULONG_PTR pulObjectCount) /* actual number returned */ { - return CKR_FUNCTION_NOT_SUPPORTED; + struct pkcs11_session *ses; + int to_return; + + LOG("C_FindObjects(%d, 0x%x, %d, 0x%x)\n", hSession, phObject, ulMaxObjectCount, pulObjectCount); + if (hSession < 1 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL) + return CKR_SESSION_HANDLE_INVALID; + + ses = session[hSession]; + + to_return = min(ulMaxObjectCount, ses->search.num_matches - ses->search.position); + *pulObjectCount = to_return; + + memcpy(phObject, + &ses->search.handles[ses->search.position], + to_return * sizeof(CK_OBJECT_HANDLE)); + + ses->search.position += to_return; + + return CKR_OK; } CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) /* the session's handle */ { - return CKR_FUNCTION_NOT_SUPPORTED; + struct pkcs11_session *ses; + + LOG("C_FindObjectsFinal(%d)\n", hSession); + if (hSession < 1 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL) + return CKR_SESSION_HANDLE_INVALID; + + ses = session[hSession]; + ses->search.num_matches = 0; + ses->search.position = 0; + + return CKR_OK; } diff --git a/src/pkcs11/sc-pkcs11.h b/src/pkcs11/sc-pkcs11.h index 57f8ffdd..1b950962 100644 --- a/src/pkcs11/sc-pkcs11.h +++ b/src/pkcs11/sc-pkcs11.h @@ -6,23 +6,55 @@ #include "pkcs11/pkcs11.h" #include "../sc.h" -#define PKCS11_MAX_CARDS 4 +#define PKCS11_MAX_SLOTS 4 #define PKCS11_MAX_SESSIONS 8 +#define PKCS11_MAX_OBJECTS 16 +// Object information +struct pkcs11_object { + int num_attributes; + CK_ATTRIBUTE_PTR attribute; +}; + +// Search information +struct pkcs11_search_context { + int num_matches, position; + CK_OBJECT_HANDLE handles[PKCS11_MAX_OBJECTS]; +}; + +// Per session information; "context" struct pkcs11_session { int slot; CK_STATE state; CK_FLAGS flags; CK_NOTIFY notify_callback; - CK_VOID_PTR notify_parameter; + CK_VOID_PTR notify_parameter; + + struct pkcs11_search_context search; + //... +}; + +// Per slot (=card) information +#define SLOT_CONNECTED 1 +#define SLOT_LOGGED_IN 2 +struct pkcs11_slot { + int flags; + struct sc_pkcs15_card *p15card; + + int num_objects; + struct pkcs11_object *object[PKCS11_MAX_OBJECTS+1]; }; extern CK_FUNCTION_LIST function_list; extern void LOG(char *format, ...); extern struct sc_context *ctx; -extern struct sc_pkcs15_card *p15card[PKCS11_MAX_CARDS]; -extern struct pkcs11_session *session[PKCS11_MAX_SESSIONS]; +extern struct pkcs11_slot slot[PKCS11_MAX_SLOTS]; +extern struct pkcs11_session *session[PKCS11_MAX_SESSIONS+1]; + + +extern int slot_connect(int id); +extern int slot_disconnect(int id); #endif diff --git a/src/pkcs11/session.c b/src/pkcs11/session.c index 490b69f2..698bdde4 100644 --- a/src/pkcs11/session.c +++ b/src/pkcs11/session.c @@ -18,38 +18,17 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */ if (!(flags & CKF_SERIAL_SESSION)) return CKR_SESSION_PARALLEL_NOT_SUPPORTED; - for (i=0; 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); - } + if (!(slot[slotID].flags & SLOT_CONNECTED)) { + rc = slot_connect(slotID); + if (rc) + return rc; } ses = session[i] = (struct pkcs11_session*) malloc(sizeof(struct pkcs11_session)); @@ -68,8 +47,8 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */ CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) /* the session's handle */ { - LOG("C_CloseSession(0x%x)\n", hSession); - if (hSession < 0 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL) + LOG("C_CloseSession(%d)\n", hSession); + if (hSession < 1 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL) return CKR_SESSION_HANDLE_INVALID; free(session[hSession]); @@ -95,8 +74,8 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ { struct pkcs11_session *ses; - LOG("C_GetSessionInfo(0x%x, 0x%x)\n", hSession, pInfo); - if (hSession < 0 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL) + LOG("C_GetSessionInfo(%d, 0x%x)\n", hSession, pInfo); + if (hSession < 1 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL) return CKR_SESSION_HANDLE_INVALID; ses = session[hSession]; @@ -112,7 +91,7 @@ CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, /* the session 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, + LOG("C_GetOperationState(%d, %0x%x, %d)\n", hSession, pOperationState, pulOperationStateLen); return CKR_FUNCTION_NOT_SUPPORTED; } @@ -123,7 +102,7 @@ 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", + LOG("C_SetOperationState(%d, 0x%x, %d, 0x%x, 0x%x)\n", hSession, pOperationState, ulOperationStateLen, hEncryptionKey, hAuthenticationKey); return CKR_FUNCTION_NOT_SUPPORTED; @@ -138,8 +117,8 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */ 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) + LOG("C_Login(%d, %d, 0x%x, %d)\n", hSession, userType, pPin, ulPinLen); + if (hSession < 1 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL) return CKR_SESSION_HANDLE_INVALID; if (userType != CKU_USER) { @@ -151,7 +130,7 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */ return CKR_PIN_LEN_RANGE; ses = session[hSession]; - card = p15card[ses->slot]; + card = slot[ses->slot].p15card; if (ses->state != CKS_RO_PUBLIC_SESSION && ses->state != CKS_RW_PUBLIC_SESSION) @@ -181,8 +160,8 @@ 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) + LOG("C_Logout(%d)\n", hSession); + if (hSession < 1 || hSession >= PKCS11_MAX_SESSIONS || session[hSession] == NULL) return CKR_SESSION_HANDLE_INVALID; ses = session[hSession]; @@ -221,14 +200,14 @@ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, 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) + if (hSession < 1 || 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]; + card = slot[ses->slot].p15card; LOG("Master PIN code update starts.\n"); rc = sc_pkcs15_change_pin(card, &card->pins[0], pOldPin, ulOldLen, pNewPin, ulNewLen); diff --git a/src/pkcs11/slot.c b/src/pkcs11/slot.c new file mode 100644 index 00000000..b0c73c2d --- /dev/null +++ b/src/pkcs11/slot.c @@ -0,0 +1,109 @@ +#include +#include +#include "sc-pkcs11.h" + +static CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; +static CK_BYTE cert_value[] = +"\x30\x82\x03\x8f\x30\x82\x02\x77\xa0\x03\x02\x01\x02\x02\x02\x68\xf6\x30\x0d\x06" +"\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x30\x4c\x31\x0b\x30\x09\x06\x03" +"\x55\x04\x06\x13\x02\x46\x49\x31\x1c\x30\x1a\x06\x03\x55\x04\x0a\x14\x13\x56\x52" +"\x4b\x2d\x46\x49\x4e\x53\x49\x47\x4e\x20\x47\x6f\x76\x2e\x20\x43\x41\x31\x1f\x30" +"\x1d\x06\x03\x55\x04\x03\x14\x16\x46\x49\x4e\x53\x49\x47\x4e\x20\x43\x41\x20\x66" +"\x6f\x72\x20\x43\x69\x74\x69\x7a\x65\x6e\x30\x1e\x17\x0d\x30\x31\x30\x39\x31\x32" +"\x32\x33\x35\x39\x35\x39\x5a\x17\x0d\x30\x34\x30\x39\x30\x35\x32\x33\x35\x39\x35" +"\x39\x5a\x30\x5f\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x0e\x30" +"\x0c\x06\x03\x55\x04\x04\x14\x05\x54\x45\x52\xc4\x53\x31\x0d\x30\x0b\x06\x03\x55" +"\x04\x2a\x14\x04\x54\x49\x4d\x4f\x31\x1d\x30\x1b\x06\x03\x55\x04\x03\x14\x14\x54" +"\x45\x52\xc4\x53\x20\x54\x49\x4d\x4f\x20\x31\x30\x30\x31\x30\x33\x30\x33\x30\x31" +"\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x31\x30\x30\x31\x30\x33\x30\x33\x30\x30" +"\x81\x9f\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x81\x8d" +"\x00\x30\x81\x89\x02\x81\x81\x00\xba\xb3\xc3\x65\xfb\xab\xd3\x4f\xf1\xe8\x72\xb8" +"\xaa\x48\x6a\x82\x31\x43\xc9\x3e\xe6\xff\x6b\xb6\x0e\xa3\x82\xb4\xda\x3f\xed\xa6" +"\x0b\xbc\xf2\xd3\xad\x53\x88\x88\x14\x14\x3f\x2b\x24\x8d\xd7\x3f\x4b\xb3\xe6\xc1" +"\xb9\xb1\x4d\x3a\x10\xc4\x65\xdc\xe2\xa1\x27\xd2\x8f\xb2\x67\x54\x34\x73\x53\xeb" +"\xec\x84\xab\xdd\xc1\x76\xc9\x73\x49\x4c\x7c\x18\x98\xd3\x40\xc4\x1c\xfd\x0d\x6b" +"\xae\xb7\x9f\x44\xc6\x0a\x5a\x89\x91\xb8\x6e\x20\x38\x2b\xff\x42\xf7\xfe\x95\xc0" +"\x1f\xa5\xca\x07\x2e\x4a\xb0\x9c\x07\x60\x02\x61\xe1\x8b\x25\x01\x02\x03\x01\x00" +"\x01\xa3\x81\xeb\x30\x81\xe8\x30\x11\x06\x03\x55\x1d\x0e\x04\x0a\x04\x08\x43\x9b" +"\x88\x1f\x86\xef\x7c\x8c\x30\x14\x06\x03\x55\x1d\x20\x04\x0d\x30\x0b\x30\x09\x06" +"\x07\x2a\x81\x76\x84\x05\x01\x01\x30\x13\x06\x03\x55\x1d\x23\x04\x0c\x30\x0a\x80" +"\x08\x46\x49\x4e\x43\x41\x4b\x30\x31\x30\x0e\x06\x03\x55\x1d\x0f\x01\x01\xff\x04" +"\x04\x03\x02\x04\xb0\x30\x81\x97\x06\x03\x55\x1d\x1f\x04\x81\x8f\x30\x81\x8c\x30" +"\x81\x89\xa0\x81\x86\xa0\x81\x83\x86\x81\x80\x6c\x64\x61\x70\x3a\x2f\x2f\x31\x39" +"\x33\x2e\x32\x32\x39\x2e\x30\x2e\x32\x31\x30\x3a\x33\x38\x39\x2f\x63\x6e\x3d\x66" +"\x69\x6e\x73\x69\x67\x6e\x25\x32\x30\x63\x61\x25\x32\x30\x66\x6f\x72\x25\x32\x30" +"\x63\x69\x74\x69\x7a\x65\x6e\x2c\x6f\x3d\x76\x72\x6b\x2d\x66\x69\x6e\x73\x69\x67" +"\x6e\x25\x32\x30\x67\x6f\x76\x2e\x25\x32\x30\x63\x61\x2c\x64\x6d\x64\x6e\x61\x6d" +"\x65\x3d\x66\x69\x6e\x65\x69\x64\x2c\x63\x3d\x46\x49\x3f\x63\x65\x72\x74\x69\x66" +"\x69\x63\x61\x74\x65\x72\x65\x76\x6f\x63\x61\x74\x69\x6f\x6e\x6c\x69\x73\x74\x30" +"\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7d" +"\x4d\xc2\x22\xcb\x63\x82\x9f\xee\x09\x73\xda\x2d\xef\x2f\xb5\x82\x30\x61\x32\x42" +"\x1a\xee\x1c\x41\xac\x24\x36\xd3\x70\xdc\xd9\x02\x84\x58\x47\x11\xb3\x93\xc2\x7b" +"\xa3\x12\x82\x64\xa5\xf2\x8b\x33\x63\x38\x2d\x19\xe7\xfd\xe0\xb0\xf8\x70\xa2\xde" +"\xa3\xd2\x11\xdf\x8c\x41\xcb\x9b\x9a\xa0\xf8\x2c\xdb\xf9\x75\x97\x36\x92\x2d\x90" +"\xd9\x32\x10\xb4\x66\x9c\x21\xd9\xfe\xe5\x46\x59\xbf\x9b\x08\x19\x21\x6a\x52\x30" +"\x19\xac\x35\xc2\x98\x15\x49\x90\x5b\x22\x28\x84\xbd\x61\x3e\xd5\xf6\xa4\xba\x90" +"\x24\xa1\x58\x6f\x8c\xe4\x52\x96\xf7\x31\xb8\x82\xf2\xaa\x9d\x4d\xb0\xf7\xfc\x6a" +"\x1d\x7f\xec\xc4\x39\x50\x3a\x98\x87\xe2\x7b\x59\x16\x42\x3e\xe9\x32\x05\x07\xf0" +"\x5d\x35\xc1\x49\x7f\x91\xde\x75\x58\x30\xd3\xfd\x5f\xb9\x24\x90\xe7\xd9\xd4\x11" +"\x60\x93\x5c\x73\x97\x16\x20\x52\x8f\x04\x9d\x3b\x77\x0f\x12\xb9\x84\x02\x68\x47" +"\x92\x15\xa2\xbb\x79\x10\x04\x28\x24\xa4\xed\x60\x2c\x9f\xd0\xfd\x7b\xa6\xb3\xf7" +"\x80\xe0\x2d\x4d\xdf\x00\x52\x0a\x3b\xbe\x26\x3a\xb5\xed\xf7\x87\x35\x39\x3a\xe8" +"\x0a\x80\x06\x67\x60\x24\x38\xc4\x79\x0b\xa4\x17\x65\x62\x14"; + +static CK_BYTE cert_id[] = "\x01"; +static CK_BYTE cert_label[] = "Timo Teras / Verification certificate"; + +static CK_ATTRIBUTE certificate[] = { + { CKA_CLASS, &cert_class, sizeof(cert_class) }, + { CKA_VALUE, cert_value, sizeof(cert_value)-1 }, + { CKA_ID, cert_id, sizeof(cert_id)-1 }, + { CKA_LABEL, cert_label, sizeof(cert_label) } +}; + +int slot_connect(int id) +{ + struct sc_card *card; + struct sc_pkcs15_pin_object pin; + int r, c = 0; + + r = sc_connect_card(ctx, id, &card); + if (r) { + LOG("Failed to connect in slot %d (r=%d)\n", id, r); + return CKR_TOKEN_NOT_PRESENT; + } + + r = sc_pkcs15_init(card, &slot[id].p15card); + if (r) { + LOG("sc_pkcs15_init failed for slot %d (r=%d)\n", id, r); + /* PKCS#15 compatible SC probably not present */ + sc_disconnect_card(card); + return CKR_TOKEN_NOT_RECOGNIZED; + } + + while (sc_pkcs15_read_pin_object(slot[id].p15card, ++c, &pin) == 0); + LOG("Found total of %d PIN codes.\n", c); + slot[id].flags = SLOT_CONNECTED; + + // KLUDGE: + slot[id].num_objects = 1; + slot[id].object[1] = (struct pkcs11_object*) malloc(sizeof(struct pkcs11_object)); + slot[id].object[1]->num_attributes = sizeof(certificate) / sizeof(certificate[0]); + slot[id].object[1]->attribute = certificate; + + return CKR_OK; +} + +int slot_disconnect(int id) +{ + LOG("Disconnecting from slot %d\n", id); + slot[id].flags = 0; + if (slot[id].p15card != NULL) { + sc_disconnect_card(slot[id].p15card->card); + sc_pkcs15_destroy(slot[id].p15card); + slot[id].p15card = NULL; + } + + return CKR_OK; +} +