CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { CK_RV rv; struct sc_pkcs11_session *session; struct sc_pkcs11_slot *slot; if ((pOldPin == NULL_PTR && ulOldLen > 0) || (pNewPin == NULL_PTR && ulNewLen > 0)) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; session = list_seek(&sessions, &hSession); if (!session) { rv = CKR_SESSION_HANDLE_INVALID; goto out; } slot = session->slot; sc_log(context, "Changing PIN (session 0x%lx; login user %d)", hSession, slot->login_user); if (!(session->flags & CKF_RW_SESSION)) { rv = CKR_SESSION_READ_ONLY; goto out; } rv = slot->card->framework->change_pin(slot, pOldPin, ulOldLen, pNewPin, ulNewLen); out: sc_pkcs11_unlock(); return rv; }
CK_RV C_Verify(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* plaintext data (digest) to compare */ CK_ULONG ulDataLen, /* length of data (digest) in bytes */ CK_BYTE_PTR pSignature, /* the signature to be verified */ CK_ULONG ulSignatureLen) /* count of bytes of signature */ { #ifndef ENABLE_OPENSSL return CKR_FUNCTION_NOT_SUPPORTED; #else int rv; struct sc_pkcs11_session *session; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = pool_find(&session_pool, hSession, (void**) &session); if (rv != CKR_OK) goto out; rv = sc_pkcs11_verif_update(session, pData, ulDataLen); if (rv == CKR_OK) rv = sc_pkcs11_verif_final(session, pSignature, ulSignatureLen); out: sc_debug(context, "Verify result was %d\n", rv); sc_pkcs11_unlock(); return rv; #endif }
CK_RV C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* data to be digested */ CK_ULONG ulDataLen, /* bytes of data to be digested */ CK_BYTE_PTR pDigest, /* receives the message digest */ CK_ULONG_PTR pulDigestLen) /* receives byte length of digest */ { CK_RV rv; struct sc_pkcs11_session *session; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_Digest(hSession=0x%lx)", hSession); rv = get_session(hSession, &session); if (rv != CKR_OK) goto out; rv = sc_pkcs11_md_update(session, pData, ulDataLen); if (rv == CKR_OK) rv = sc_pkcs11_md_final(session, pDigest, pulDigestLen); out: sc_log(context, "C_Digest() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
CK_RV C_GetInfo(CK_INFO_PTR pInfo) { CK_RV rv = CKR_OK; if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_GetInfo()"); memset(pInfo, 0, sizeof(CK_INFO)); pInfo->cryptokiVersion.major = 2; pInfo->cryptokiVersion.minor = 20; strcpy_bp(pInfo->manufacturerID, OPENSC_VS_FF_COMPANY_NAME, sizeof(pInfo->manufacturerID)); strcpy_bp(pInfo->libraryDescription, OPENSC_VS_FF_PRODUCT_NAME, sizeof(pInfo->libraryDescription)); pInfo->libraryVersion.major = OPENSC_VERSION_MAJOR; pInfo->libraryVersion.minor = OPENSC_VERSION_MINOR; sc_pkcs11_unlock(); return rv; }
CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject) /* the object's handle */ { CK_RV rv; struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; CK_BBOOL is_token = FALSE; CK_ATTRIBUTE token_attribure = {CKA_TOKEN, &is_token, sizeof(is_token)}; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_DestroyObject(hSession=0x%lx, hObject=0x%lx)", hSession, hObject); rv = get_object_from_session(hSession, hObject, &session, &object); if (rv != CKR_OK) goto out; object->ops->get_attribute(session, object, &token_attribure); if (is_token == TRUE && !(session->flags & CKF_RW_SESSION)) { rv = CKR_SESSION_READ_ONLY; goto out; } if (object->ops->destroy_object == NULL) rv = CKR_FUNCTION_NOT_SUPPORTED; else rv = object->ops->destroy_object(session, object); out: sc_pkcs11_unlock(); return rv; }
CK_RV C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* data to be digested */ CK_ULONG ulDataLen, /* bytes of data to be digested */ CK_BYTE_PTR pDigest, /* receives the message digest */ CK_ULONG_PTR pulDigestLen) /* receives byte length of digest */ { int rv; struct sc_pkcs11_session *session; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = pool_find(&session_pool, hSession, (void**) &session); if (rv != CKR_OK) goto out; rv = sc_pkcs11_md_update(session, pData, ulDataLen); if (rv == CKR_OK) rv = sc_pkcs11_md_final(session, pDigest, pulDigestLen); out: sc_debug(context, "C_Digest returns %d\n", rv); sc_pkcs11_unlock(); return rv; }
CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSignature, /* the signature to be verified */ CK_ULONG ulSignatureLen) { /* count of bytes of signature */ #ifndef ENABLE_OPENSSL return CKR_FUNCTION_NOT_SUPPORTED; #else CK_RV rv; struct sc_pkcs11_session *session; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_session(hSession, &session); if (rv == CKR_OK) { rv = restore_login_state(session->slot); if (rv == CKR_OK) rv = sc_pkcs11_verif_final(session, pSignature, ulSignatureLen); rv = reset_login_state(session->slot, rv); } sc_log(context, "C_VerifyFinal() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; #endif }
CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject) /* the object's handle */ { struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; char object_name[64]; int rv; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; snprintf(object_name, sizeof(object_name), "C_DestroyObject : Object %lu", (unsigned long) hObject); sc_debug( context, object_name ); rv = pool_find(&session_pool, hSession, (void**) &session); if (rv != CKR_OK) goto out; rv = pool_find_and_delete(&session->slot->object_pool, hObject, (void**) &object); if (rv != CKR_OK) goto out; if (object->ops->destroy_object == NULL) rv = CKR_FUNCTION_NOT_SUPPORTED; else rv = object->ops->destroy_object(session, object); out: sc_pkcs11_unlock(); return rv; }
CK_RV C_Logout(CK_SESSION_HANDLE hSession) { /* the session's handle */ CK_RV rv; struct sc_pkcs11_session *session; struct sc_pkcs11_slot *slot; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; session = list_seek(&sessions, &hSession); if (!session) { rv = CKR_SESSION_HANDLE_INVALID; goto out; } sc_log(context, "C_Logout(hSession:0x%lx)", hSession); slot = session->slot; if (slot->login_user >= 0) { slot->login_user = -1; rv = slot->card->framework->logout(slot); } else rv = CKR_USER_NOT_LOGGED_IN; out:sc_pkcs11_unlock(); return rv; }
CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSignature, /* the signature to be verified */ CK_ULONG ulSignatureLen) /* count of bytes of signature */ { #ifndef ENABLE_OPENSSL return CKR_FUNCTION_NOT_SUPPORTED; #else struct sc_pkcs11_session *session; int rv; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = pool_find(&session_pool, hSession, (void**) &session); if (rv != CKR_OK) goto out; rv = sc_pkcs11_verif_final(session, pSignature, ulSignatureLen); out: sc_debug(context, "C_VerifyFinal returns %d\n", rv); sc_pkcs11_unlock(); return rv; #endif }
CK_RV C_GetInfo(CK_INFO_PTR pInfo) { CK_RV rv = CKR_OK; if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_GetInfo()"); memset(pInfo, 0, sizeof(CK_INFO)); pInfo->cryptokiVersion.major = 2; if (sc_pkcs11_conf.plug_and_play) { pInfo->cryptokiVersion.minor = 20; } else { pInfo->cryptokiVersion.minor = 11; } strcpy_bp(pInfo->manufacturerID, "OpenSC (www.opensc-project.org)", sizeof(pInfo->manufacturerID)); strcpy_bp(pInfo->libraryDescription, "Smart card PKCS#11 API", sizeof(pInfo->libraryDescription)); pInfo->libraryVersion.major = 0; pInfo->libraryVersion.minor = 0; /* FIXME: use 0.116 for 0.11.6 from autoconf */ sc_pkcs11_unlock(); return rv; }
CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pSeed, /* the seed material */ CK_ULONG ulSeedLen) /* count of bytes of seed material */ { struct sc_pkcs11_session *session; struct sc_pkcs11_slot *slot; int rv; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = pool_find(&session_pool, hSession, (void**) &session); if (rv == CKR_OK) { slot = session->slot; if (slot->card->framework->get_random == NULL) rv = CKR_RANDOM_NO_RNG; else if (slot->card->framework->seed_random == NULL) rv = CKR_RANDOM_SEED_NOT_SUPPORTED; else rv = slot->card->framework->seed_random(slot->card, pSeed, ulSeedLen); } sc_pkcs11_unlock(); return rv; }
CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pEncryptedData, /* input encrypted data */ CK_ULONG ulEncryptedDataLen, /* count of bytes of input */ CK_BYTE_PTR pData, /* receives decrypted output */ CK_ULONG_PTR pulDataLen) { /* receives decrypted byte count */ CK_RV rv; struct sc_pkcs11_session *session; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_session(hSession, &session); if (rv == CKR_OK) { rv = restore_login_state(session->slot); if (rv == CKR_OK) { rv = sc_pkcs11_decr(session, pEncryptedData, ulEncryptedDataLen, pData, pulDataLen); } rv = reset_login_state(session->slot, rv); } sc_log(context, "C_Decrypt() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
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. */ { struct sc_pkcs11_session *session; struct sc_pkcs11_card *card; int rv; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; dump_template("C_CreateObject()", pTemplate, ulCount); rv = pool_find(&session_pool, hSession, (void**) &session); if (rv != CKR_OK) goto out; card = session->slot->card; if (card->framework->create_object == NULL) rv = CKR_FUNCTION_NOT_SUPPORTED; else rv = card->framework->create_object(card, session->slot, pTemplate, ulCount, phObject); out: sc_pkcs11_unlock(); return rv; }
CK_RV C_Verify(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* plaintext data (digest) to compare */ CK_ULONG ulDataLen, /* length of data (digest) in bytes */ CK_BYTE_PTR pSignature, /* the signature to be verified */ CK_ULONG ulSignatureLen) { /* count of bytes of signature */ #ifndef ENABLE_OPENSSL return CKR_FUNCTION_NOT_SUPPORTED; #else CK_RV rv; struct sc_pkcs11_session *session; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_session(hSession, &session); if (rv != CKR_OK) goto out; rv = sc_pkcs11_verif_update(session, pData, ulDataLen); if (rv == CKR_OK) rv = sc_pkcs11_verif_final(session, pSignature, ulSignatureLen); out: sc_log(context, "C_Verify() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; #endif }
CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_USER_TYPE userType, /* the user type */ CK_CHAR_PTR pPin, /* the user's PIN */ CK_ULONG ulPinLen) { /* the length of the PIN */ CK_RV rv; struct sc_pkcs11_session *session; struct sc_pkcs11_slot *slot; if (pPin == NULL_PTR && ulPinLen > 0) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; if (userType != CKU_USER && userType != CKU_SO && userType != CKU_CONTEXT_SPECIFIC) { rv = CKR_USER_TYPE_INVALID; goto out; } session = list_seek(&sessions, &hSession); if (!session) { rv = CKR_SESSION_HANDLE_INVALID; goto out; } sc_log(context, "C_Login(0x%lx, %d)", hSession, userType); slot = session->slot; if (!(slot->token_info.flags & CKF_USER_PIN_INITIALIZED)) { rv = CKR_USER_PIN_NOT_INITIALIZED; goto out; } /* TODO: check if context specific is valid */ if (userType == CKU_CONTEXT_SPECIFIC) { if (slot->login_user == -1) { rv = CKR_OPERATION_NOT_INITIALIZED; goto out; } else rv = slot->card->framework->login(slot, userType, pPin, ulPinLen); } else { if (slot->login_user >= 0) { if ((CK_USER_TYPE) slot->login_user == userType) rv = CKR_USER_ALREADY_LOGGED_IN; else rv = CKR_USER_ANOTHER_ALREADY_LOGGED_IN; goto out; } rv = slot->card->framework->login(slot, userType, pPin, ulPinLen); if (rv == CKR_OK) slot->login_user = userType; } out:sc_pkcs11_unlock(); return rv; }
CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { struct sc_pkcs11_slot *slot; sc_timestamp_t now; CK_RV rv; if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_GetSlotInfo(0x%lx)", slotID); if (sc_pkcs11_conf.init_sloppy) { /* Most likely virtual_slots only contains the hotplug slot and has not * been initialized because the caller has *not* called C_GetSlotList * before C_GetSlotInfo, as required by PKCS#11. Initialize * virtual_slots to make things work and hope the caller knows what * it's doing... */ card_detect_all(); } rv = slot_get_slot(slotID, &slot); sc_log(context, "C_GetSlotInfo() get slot rv %lu", rv); if (rv == CKR_OK) { if (slot->reader == NULL) { rv = CKR_TOKEN_NOT_PRESENT; } else { now = get_current_time(); if (now >= slot->slot_state_expires || now == 0) { /* Update slot status */ rv = card_detect(slot->reader); sc_log(context, "C_GetSlotInfo() card detect rv 0x%lX", rv); if (rv == CKR_TOKEN_NOT_RECOGNIZED || rv == CKR_OK) slot->slot_info.flags |= CKF_TOKEN_PRESENT; /* Don't ask again within the next second */ slot->slot_state_expires = now + 1000; } } } if (rv == CKR_TOKEN_NOT_PRESENT || rv == CKR_TOKEN_NOT_RECOGNIZED) rv = CKR_OK; if (rv == CKR_OK) memcpy(pInfo, &slot->slot_info, sizeof(CK_SLOT_INFO)); sc_log(context, "C_GetSlotInfo() flags 0x%lX", pInfo->flags); sc_log(context, "C_GetSlotInfo(0x%lx) = %s", slotID, lookup_enum( RV_T, rv)); sc_pkcs11_unlock(); return rv; }
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 */ { CK_RV rv; CK_BBOOL can_sign; CK_KEY_TYPE key_type; CK_ATTRIBUTE sign_attribute = { CKA_SIGN, &can_sign, sizeof(can_sign) }; CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) }; struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; /* FIXME #47: C_SignRecover is not implemented */ return CKR_FUNCTION_NOT_SUPPORTED; if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_object_from_session(hSession, hKey, &session, &object); if (rv != CKR_OK) { if (rv == CKR_OBJECT_HANDLE_INVALID) rv = CKR_KEY_HANDLE_INVALID; goto out; } if (object->ops->sign == NULL_PTR) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = object->ops->get_attribute(session, object, &sign_attribute); if (rv != CKR_OK || !can_sign) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = object->ops->get_attribute(session, object, &key_type_attr); if (rv != CKR_OK) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } /* XXX: need to tell the signature algorithm that we want * to recover the signature */ sc_log(context, "SignRecover operation initialized\n"); rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type); out: sc_log(context, "C_SignRecoverInit() = %sn", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
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 */ CK_BBOOL can_decrypt, can_unwrap; CK_KEY_TYPE key_type; CK_ATTRIBUTE decrypt_attribute = { CKA_DECRYPT, &can_decrypt, sizeof(can_decrypt) }; CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) }; CK_ATTRIBUTE unwrap_attribute = { CKA_UNWRAP, &can_unwrap, sizeof(can_unwrap) }; struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; CK_RV rv; if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_object_from_session(hSession, hKey, &session, &object); if (rv != CKR_OK) { if (rv == CKR_OBJECT_HANDLE_INVALID) rv = CKR_KEY_HANDLE_INVALID; goto out; } if (object->ops->decrypt == NULL_PTR) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = object->ops->get_attribute(session, object, &decrypt_attribute); if (rv != CKR_OK || !can_decrypt) { /* Also accept UNWRAP - apps call Decrypt when they mean Unwrap */ rv = object->ops->get_attribute(session, object, &unwrap_attribute); if (rv != CKR_OK || !can_unwrap) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } } rv = object->ops->get_attribute(session, object, &key_type_attr); if (rv != CKR_OK) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = sc_pkcs11_decr_init(session, pMechanism, object, key_type); out: sc_log(context, "C_DecryptInit() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */ CK_FLAGS flags, /* defined in CK_SESSION_INFO */ CK_VOID_PTR pApplication, /* pointer passed to callback */ CK_NOTIFY Notify, /* notification callback function */ CK_SESSION_HANDLE_PTR phSession) { /* receives new session handle */ CK_RV rv; struct sc_pkcs11_slot *slot; struct sc_pkcs11_session *session; if (!(flags & CKF_SERIAL_SESSION)) return CKR_SESSION_PARALLEL_NOT_SUPPORTED; if (flags & ~(CKF_SERIAL_SESSION | CKF_RW_SESSION)) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_OpenSession(0x%lx)", slotID); rv = slot_get_token(slotID, &slot); if (rv != CKR_OK) goto out; /* Check that no conflictions sessions exist */ if (!(flags & CKF_RW_SESSION) && (slot->login_user == CKU_SO)) { rv = CKR_SESSION_READ_WRITE_SO_EXISTS; goto out; } session = (struct sc_pkcs11_session *)calloc(1, sizeof(struct sc_pkcs11_session)); if (session == NULL) { rv = CKR_HOST_MEMORY; goto out; } session->slot = slot; session->notify_callback = Notify; session->notify_data = pApplication; session->flags = flags; slot->nsessions++; session->handle = (CK_SESSION_HANDLE) session; /* cast a pointer to long */ list_append(&sessions, session); *phSession = session->handle; sc_log(context, "C_OpenSession handle: 0x%lx", session->handle); out: sc_log(context, "C_OpenSession() = %s", lookup_enum(RV_T, rv)); sc_pkcs11_unlock(); return rv; }
CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the key gen. mech. */ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* pub. attr. template */ CK_ULONG ulPublicKeyAttributeCount, /* # of pub. attrs. */ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* priv. attr. template */ CK_ULONG ulPrivateKeyAttributeCount, /* # of priv. attrs. */ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub. key handle */ CK_OBJECT_HANDLE_PTR phPrivateKey) { /* gets priv. key handle */ CK_RV rv; struct sc_pkcs11_session *session; struct sc_pkcs11_slot *slot; if (pMechanism == NULL_PTR || (pPublicKeyTemplate == NULL_PTR && ulPublicKeyAttributeCount > 0) || (pPrivateKeyTemplate == NULL_PTR && ulPrivateKeyAttributeCount > 0)) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; dump_template(SC_LOG_DEBUG_NORMAL, "C_GenerateKeyPair(), PrivKey attrs", pPrivateKeyTemplate, ulPrivateKeyAttributeCount); dump_template(SC_LOG_DEBUG_NORMAL, "C_GenerateKeyPair(), PubKey attrs", pPublicKeyTemplate, ulPublicKeyAttributeCount); rv = get_session(hSession, &session); if (rv != CKR_OK) goto out; if (!(session->flags & CKF_RW_SESSION)) { rv = CKR_SESSION_READ_ONLY; goto out; } slot = session->slot; if (slot->p11card->framework->gen_keypair == NULL) rv = CKR_FUNCTION_NOT_SUPPORTED; else { rv = restore_login_state(slot); if (rv == CKR_OK) rv = slot->p11card->framework->gen_keypair(slot, pMechanism, pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, phPublicKey, phPrivateKey); rv = reset_login_state(session->slot, rv); } out: sc_pkcs11_unlock(); return rv; }
CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ CK_OBJECT_HANDLE hKey) { /* handle of the verification key */ #ifndef ENABLE_OPENSSL return CKR_FUNCTION_NOT_SUPPORTED; #else #if 0 CK_BBOOL can_verify; CK_ATTRIBUTE verify_attribute = { CKA_VERIFY, &can_verify, sizeof(can_verify) }; #endif CK_KEY_TYPE key_type; CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) }; CK_RV rv; struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_object_from_session(hSession, hKey, &session, &object); if (rv != CKR_OK) { if (rv == CKR_OBJECT_HANDLE_INVALID) rv = CKR_KEY_HANDLE_INVALID; goto out; } #if 0 rv = object->ops->get_attribute(session, object, &verify_attribute); if (rv != CKR_OK || !can_verify) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } #endif rv = object->ops->get_attribute(session, object, &key_type_attr); if (rv != CKR_OK) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = sc_pkcs11_verif_init(session, pMechanism, object, key_type); out: sc_log(context, "C_VerifyInit() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; #endif }
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 */ { CK_BBOOL can_sign; CK_KEY_TYPE key_type; CK_ATTRIBUTE sign_attribute = { CKA_SIGN, &can_sign, sizeof(can_sign) }; CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) }; struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; CK_RV rv; if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_object_from_session(hSession, hKey, &session, &object); if (rv != CKR_OK) { if (rv == CKR_OBJECT_HANDLE_INVALID) rv = CKR_KEY_HANDLE_INVALID; goto out; } if (object->ops->sign == NULL_PTR) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = object->ops->get_attribute(session, object, &sign_attribute); if (rv != CKR_OK || !can_sign) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = object->ops->get_attribute(session, object, &key_type_attr); if (rv != CKR_OK) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type); out: sc_log(context, "C_SignInit() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
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 */ { CK_BBOOL can_sign; CK_KEY_TYPE key_type; CK_ATTRIBUTE sign_attribute = { CKA_SIGN, &can_sign, sizeof(can_sign) }; CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) }; struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; int rv; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = pool_find(&session_pool, hSession, (void**) &session); if (rv != CKR_OK) goto out; rv = pool_find(&session->slot->object_pool, hKey, (void**) &object); if (rv != CKR_OK) goto out; if (object->ops->sign == NULL_PTR) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = object->ops->get_attribute(session, object, &sign_attribute); if (rv != CKR_OK || !can_sign) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = object->ops->get_attribute(session, object, &key_type_attr); if (rv != CKR_OK) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } /* XXX: need to tell the signature algorithm that we want * to recover the signature */ sc_debug(context, "SignRecover operation initialized\n"); rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type); out: sc_debug(context, "Sign initialization returns %d\n", rv); sc_pkcs11_unlock(); return rv; }
CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */ CK_OBJECT_HANDLE hKey) /* handle of the verification key */ { #ifndef ENABLE_OPENSSL return CKR_FUNCTION_NOT_SUPPORTED; #else #if 0 CK_BBOOL can_verify; CK_ATTRIBUTE verify_attribute = { CKA_VERIFY, &can_verify, sizeof(can_verify) }; #endif CK_KEY_TYPE key_type; CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) }; struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; int rv; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = pool_find(&session_pool, hSession, (void**) &session); if (rv != CKR_OK) goto out; rv = pool_find(&session->slot->object_pool, hKey, (void**) &object); if (rv != CKR_OK) goto out; #if 0 rv = object->ops->get_attribute(session, object, &verify_attribute); if (rv != CKR_OK || !can_verify) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } #endif rv = object->ops->get_attribute(session, object, &key_type_attr); if (rv != CKR_OK) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = sc_pkcs11_verif_init(session, pMechanism, object, key_type); out: sc_debug(context, "Verify initialization returns %d\n", rv); sc_pkcs11_unlock(); return rv; #endif }
CK_RV C_Finalize(CK_VOID_PTR pReserved) { int i; void *p; sc_pkcs11_slot_t *slot; CK_RV rv; if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD; #if !defined(_WIN32) sc_notify_close(); #endif if (context == NULL) return CKR_CRYPTOKI_NOT_INITIALIZED; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_Finalize()"); /* cancel pending calls */ in_finalize = 1; sc_cancel(context); /* remove all cards from readers */ for (i=0; i < (int)sc_ctx_get_reader_count(context); i++) card_removed(sc_ctx_get_reader(context, i)); while ((p = list_fetch(&sessions))) free(p); list_destroy(&sessions); while ((slot = list_fetch(&virtual_slots))) { list_destroy(&slot->objects); list_destroy(&slot->logins); free(slot); } list_destroy(&virtual_slots); sc_release_context(context); context = NULL; /* Release and destroy the mutex */ sc_pkcs11_free_lock(); return rv; }
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) { /* the session's handle */ CK_RV rv; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_CloseSession(0x%lx)", hSession); rv = sc_pkcs11_close_session(hSession); sc_pkcs11_unlock(); return rv; }
CK_RV C_InitToken(CK_SLOT_ID slotID, CK_CHAR_PTR pPin, CK_ULONG ulPinLen, CK_CHAR_PTR pLabel) { struct sc_pkcs11_session *session; struct sc_pkcs11_slot *slot; CK_RV rv; unsigned int i; sc_log(context, "C_InitToken(pLabel='%s') called", pLabel); rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = slot_get_token(slotID, &slot); if (rv != CKR_OK) { sc_log(context, "C_InitToken() get token error 0x%lX", rv); goto out; } if (!slot->p11card || !slot->p11card->framework || !slot->p11card->framework->init_token) { sc_log(context, "C_InitToken() not supported by framework"); rv = CKR_FUNCTION_NOT_SUPPORTED; goto out; } /* Make sure there's no open session for this token */ for (i=0; i<list_size(&sessions); i++) { session = (struct sc_pkcs11_session*)list_get_at(&sessions, i); if (session->slot == slot) { rv = CKR_SESSION_EXISTS; goto out; } } rv = slot->p11card->framework->init_token(slot,slot->fw_data, pPin, ulPinLen, pLabel); if (rv == CKR_OK) { /* Now we should re-bind all tokens so they get the * corresponding function vector and flags */ } out: sc_pkcs11_unlock(); sc_log(context, "C_InitToken(pLabel='%s') returns 0x%lX", pLabel, rv); return rv; }
CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { struct sc_pkcs11_slot *slot; sc_timestamp_t now; CK_RV rv; if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_GetSlotInfo(0x%lx)", slotID); rv = slot_get_slot(slotID, &slot); sc_log(context, "C_GetSlotInfo() get slot rv %i", rv); if (rv == CKR_OK) { if (slot->reader == NULL) { rv = CKR_TOKEN_NOT_PRESENT; } else { now = get_current_time(); if (now >= slot->slot_state_expires || now == 0) { /* Update slot status */ rv = card_detect(slot->reader); sc_log(context, "C_GetSlotInfo() card detect rv 0x%X", rv); if (rv == CKR_TOKEN_NOT_RECOGNIZED || rv == CKR_OK) slot->slot_info.flags |= CKF_TOKEN_PRESENT; /* Don't ask again within the next second */ slot->slot_state_expires = now + 1000; } } } if (rv == CKR_TOKEN_NOT_PRESENT || rv == CKR_TOKEN_NOT_RECOGNIZED) rv = CKR_OK; if (rv == CKR_OK) memcpy(pInfo, &slot->slot_info, sizeof(CK_SLOT_INFO)); sc_log(context, "C_GetSlotInfo() flags 0x%X", pInfo->flags); sc_log(context, "C_GetSlotInfo(0x%lx) = %s", slotID, lookup_enum( RV_T, rv)); sc_pkcs11_unlock(); return rv; }
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 */ { CK_BBOOL can_decrypt; CK_KEY_TYPE key_type; CK_ATTRIBUTE decrypt_attribute = { CKA_DECRYPT, &can_decrypt, sizeof(can_decrypt) }; CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) }; struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; int rv; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = pool_find(&session_pool, hSession, (void**) &session); if (rv != CKR_OK) goto out; rv = pool_find(&session->slot->object_pool, hKey, (void**) &object); if (rv != CKR_OK) goto out; if (object->ops->decrypt == NULL_PTR) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = object->ops->get_attribute(session, object, &decrypt_attribute); if (rv != CKR_OK || !can_decrypt) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = object->ops->get_attribute(session, object, &key_type_attr); if (rv != CKR_OK) { rv = CKR_KEY_TYPE_INCONSISTENT; goto out; } rv = sc_pkcs11_decr_init(session, pMechanism, object, key_type); out: sc_debug(context, "Decrypt initialization returns %d\n", rv); sc_pkcs11_unlock(); return rv; }