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_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_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_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_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_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_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_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_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; }
void print_mech_list(FILE *f, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG ulMechCount) { CK_ULONG imech; if(pMechanismList) { for (imech = 0; imech < ulMechCount; imech++) { const char *name = lookup_enum(MEC_T, pMechanismList[imech]); if (name) { fprintf(f, "%30s \n", name); } else { fprintf(f, " Unknown Mechanism (%08lx) \n", pMechanismList[imech]); } } } else { fprintf(f, "Count is %ld\n", ulMechCount); } }
CK_RV C_Sign(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pData, /* the data (digest) to be signed */ CK_ULONG ulDataLen, /* count of bytes to be signed */ CK_BYTE_PTR pSignature, /* receives the signature */ CK_ULONG_PTR pulSignatureLen) /* receives byte count of signature */ { CK_RV rv; struct sc_pkcs11_session *session; CK_ULONG length; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_session(hSession, &session); if (rv != CKR_OK) goto out; /* According to the pkcs11 specs, we must not do any calls that * change our crypto state if the caller is just asking for the * signature buffer size, or if the result would be * CKR_BUFFER_TOO_SMALL. Thus we cannot do the sign_update call * below. */ if ((rv = sc_pkcs11_sign_size(session, &length)) != CKR_OK) goto out; if (pSignature == NULL || length > *pulSignatureLen) { *pulSignatureLen = length; rv = pSignature ? CKR_BUFFER_TOO_SMALL : CKR_OK; goto out; } rv = sc_pkcs11_sign_update(session, pData, ulDataLen); if (rv == CKR_OK) { rv = restore_login_state(session->slot); if (rv == CKR_OK) rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen); rv = reset_login_state(session->slot, rv); } out: sc_log(context, "C_Sign() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_SESSION_INFO_PTR pInfo) { /* receives session information */ CK_RV rv; struct sc_pkcs11_session *session; struct sc_pkcs11_slot *slot; if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_GetSessionInfo(hSession:0x%lx)", hSession); session = list_seek(&sessions, &hSession); if (!session) { rv = CKR_SESSION_HANDLE_INVALID; goto out; } sc_log(context, "C_GetSessionInfo(slot:0x%lx)", session->slot->id); pInfo->slotID = session->slot->id; pInfo->flags = session->flags; pInfo->ulDeviceError = 0; slot = session->slot; if (slot->login_user == CKU_SO) { pInfo->state = CKS_RW_SO_FUNCTIONS; } else if (slot->login_user == CKU_USER || (!(slot->token_info.flags & CKF_LOGIN_REQUIRED))) { pInfo->state = (session->flags & CKF_RW_SESSION) ? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS; } else { pInfo->state = (session->flags & CKF_RW_SESSION) ? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION; } out: sc_log(context, "C_GetSessionInfo(0x%lx) = %s", hSession, lookup_enum(RV_T, rv)); sc_pkcs11_unlock(); return rv; }
void print_session_info(FILE *f, CK_SESSION_INFO *info) { int i; enum_specs ck_flags[2] = { CONSTANT(CKF_RW_SESSION), CONSTANT(CKF_SERIAL_SESSION) }; fprintf(f, "%20s: %ld\n", "Slot ID", info->slotID); fprintf(f, "%20s: '%32.32s'\n", "State", lookup_enum(STA_T, info->state)); fprintf(f, "%20s: %0lx\n", "Flags", info->flags); for(i = 0; i < 2; i++) { if(info->flags & ck_flags[i].type) { fprintf(f, "%32s%s\n", "", ck_flags[i].name); } } fprintf(f, "%20s: %0lx\n", "Device Error", info->ulDeviceError); }
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; CK_ULONG ulBuflen = 0; 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; /* if pDigest == NULL, buffer size request */ if (pDigest) { /* As per PKCS#11 2.20 we need to check if buffer too small before update */ rv = sc_pkcs11_md_final(session, NULL, &ulBuflen); if (rv != CKR_OK) goto out; if (ulBuflen > *pulDigestLen) { *pulDigestLen = ulBuflen; rv = CKR_BUFFER_TOO_SMALL; 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_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 */ { 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 = sc_pkcs11_sign_update(session, pPart, ulPartLen); sc_log(context, "C_SignUpdate() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
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 */ { 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 = sc_pkcs11_md_final(session, pDigest, pulDigestLen); sc_log(context, "C_DigestFinal() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
void print_mech_info(FILE *f, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR minfo) { const char *name = lookup_enum(MEC_T, type); CK_ULONG known_flags = CKF_HW|CKF_ENCRYPT|CKF_DECRYPT|CKF_DIGEST| CKF_SIGN|CKF_SIGN_RECOVER|CKF_VERIFY|CKF_VERIFY_RECOVER| CKF_GENERATE|CKF_GENERATE_KEY_PAIR|CKF_WRAP|CKF_UNWRAP| CKF_DERIVE|CKF_EC_F_P|CKF_EC_F_2M|CKF_EC_ECPARAMETERS| CKF_EC_NAMEDCURVE|CKF_EC_UNCOMPRESS|CKF_EC_COMPRESS; if (name) { fprintf(f, "%-30s: ", name); } else { fprintf(f, " Unknown Mechanism (%08lx): ", type); } printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", (minfo->flags & CKF_HW) ? "Hardware " : "", (minfo->flags & CKF_ENCRYPT) ? "Encrypt " : "", (minfo->flags & CKF_DECRYPT) ? "Decrypt " : "", (minfo->flags & CKF_DIGEST) ? "Digest " : "", (minfo->flags & CKF_SIGN) ? "Sign " : "", (minfo->flags & CKF_SIGN_RECOVER) ? "SigRecov " : "", (minfo->flags & CKF_VERIFY) ? "Verify " : "", (minfo->flags & CKF_VERIFY_RECOVER) ? "VerRecov " : "", (minfo->flags & CKF_GENERATE) ? "Generate " : "", (minfo->flags & CKF_GENERATE_KEY_PAIR) ? "KeyPair " : "", (minfo->flags & CKF_WRAP) ? "Wrap " : "", (minfo->flags & CKF_UNWRAP) ? "Unwrap " : "", (minfo->flags & CKF_DERIVE) ? "Derive " : "", (minfo->flags & CKF_EC_F_P) ? "F(P) " : "", (minfo->flags & CKF_EC_F_2M) ? "F(2^M) " : "", (minfo->flags & CKF_EC_ECPARAMETERS) ? "EcParams " : "", (minfo->flags & CKF_EC_NAMEDCURVE) ? "NamedCurve " : "", (minfo->flags & CKF_EC_UNCOMPRESS) ? "Uncompress " : "", (minfo->flags & CKF_EC_COMPRESS) ? "Compress " : "", (minfo->flags & ~known_flags) ? "Unknown " : ""); fprintf(f, "%32s(min:%lu max:%lu flags:0x%06lX)\n", "", minfo->ulMinKeySize, minfo->ulMaxKeySize, minfo->flags); }
/* * Below here all functions are wrappers to pass all object attribute and method * handling to appropriate object layer. */ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_MECHANISM_PTR pMechanism) /* the digesting mechanism */ { CK_RV rv; struct sc_pkcs11_session *session; if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; sc_log(context, "C_DigestInit(hSession=0x%lx)", hSession); rv = get_session(hSession, &session); if (rv == CKR_OK) rv = sc_pkcs11_md_init(session, pMechanism); sc_log(context, "C_DigestInit() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_BYTE_PTR pPart, /* plaintext data (digest) to compare */ CK_ULONG ulPartLen) { /* length of data (digest) in bytes */ #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 = sc_pkcs11_verif_update(session, pPart, ulPartLen); sc_log(context, "C_VerifyUpdate() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; #endif }
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 */ { struct sc_pkcs11_session *session; CK_ULONG length; CK_RV rv; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_session(hSession, &session); if (rv != CKR_OK) goto out; /* According to the pkcs11 specs, we must not do any calls that * change our crypto state if the caller is just asking for the * signature buffer size, or if the result would be * CKR_BUFFER_TOO_SMALL. */ if ((rv = sc_pkcs11_sign_size(session, &length)) != CKR_OK) goto out; if (pSignature == NULL || length > *pulSignatureLen) { *pulSignatureLen = length; rv = pSignature ? CKR_BUFFER_TOO_SMALL : CKR_OK; } else { rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen); } out: sc_log(context, "C_SignFinal() = %s", lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ CK_VOID_PTR pReserved) /* reserved. Should be NULL_PTR */ { sc_reader_t *found; unsigned int mask, events; void *reader_states = NULL; CK_SLOT_ID slot_id; CK_RV rv; int r; if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD; sc_log(context, "C_WaitForSlotEvent(block=%d)", !(flags & CKF_DONT_BLOCK)); #ifndef PCSCLITE_GOOD /* Not all pcsc-lite versions implement consistently used functions as they are */ if (!(flags & CKF_DONT_BLOCK)) return CKR_FUNCTION_NOT_SUPPORTED; #endif /* PCSCLITE_GOOD */ rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; mask = SC_EVENT_CARD_EVENTS | SC_EVENT_READER_EVENTS; /* Detect and add new slots for added readers v2.20 */ rv = slot_find_changed(&slot_id, mask); if ((rv == CKR_OK) || (flags & CKF_DONT_BLOCK)) goto out; again: sc_log(context, "C_WaitForSlotEvent() reader_states:%p", reader_states); sc_pkcs11_unlock(); r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states); if (events & SC_EVENT_READER_ATTACHED) { rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; goto out; } /* Was C_Finalize called ? */ if (in_finalize == 1) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((rv = sc_pkcs11_lock()) != CKR_OK) return rv; if (r != SC_SUCCESS) { sc_log(context, "sc_wait_for_event() returned %d\n", r); rv = sc_to_cryptoki_error(r, "C_WaitForSlotEvent"); goto out; } /* If no changed slot was found (maybe an unsupported card * was inserted/removed) then go waiting again */ rv = slot_find_changed(&slot_id, mask); if (rv != CKR_OK) goto again; out: if (pSlot) *pSlot = slot_id; /* Free allocated readers states holder */ if (reader_states) { sc_log(context, "free reader states"); sc_wait_for_event(context, 0, NULL, NULL, -1, &reader_states); } sc_log(context, "C_WaitForSlotEvent() = %s", lookup_enum (RV_T, rv)); sc_pkcs11_unlock(); return rv; }
CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle */ CK_OBJECT_HANDLE hObject, /* the object's handle */ CK_ATTRIBUTE_PTR pTemplate, /* specifies attributes, gets values */ CK_ULONG ulCount) /* attributes in template */ { static int precedence[] = { CKR_OK, CKR_BUFFER_TOO_SMALL, CKR_ATTRIBUTE_TYPE_INVALID, CKR_ATTRIBUTE_SENSITIVE, -1 }; char object_name[64]; int j; CK_RV rv; struct sc_pkcs11_session *session; struct sc_pkcs11_object *object; int res, res_type; unsigned int i; if (pTemplate == NULL_PTR || ulCount == 0) return CKR_ARGUMENTS_BAD; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; rv = get_object_from_session(hSession, hObject, &session, &object); if (rv != CKR_OK) goto out; /* Debug printf */ snprintf(object_name, sizeof(object_name), "Object %lu", (unsigned long)hObject); res_type = 0; for (i = 0; i < ulCount; i++) { res = object->ops->get_attribute(session, object, &pTemplate[i]); if (res != CKR_OK) pTemplate[i].ulValueLen = (CK_ULONG) - 1; dump_template(SC_LOG_DEBUG_NORMAL, object_name, &pTemplate[i], 1); /* the pkcs11 spec has complicated rules on * what errors take precedence: * CKR_ATTRIBUTE_SENSITIVE * CKR_ATTRIBUTE_INVALID * CKR_BUFFER_TOO_SMALL * It does not exactly specify how other errors * should be handled - we give them highest * precedence */ for (j = 0; precedence[j] != -1; j++) { if (precedence[j] == res) break; } if (j > res_type) { res_type = j; rv = res; } } out: sc_log(context, "C_GetAttributeValue(hSession=0x%lx, hObject=0x%lx) = %s", hSession, hObject, lookup_enum ( RV_T, rv )); sc_pkcs11_unlock(); return rv; }
CK_RV C_Initialize(CK_VOID_PTR pInitArgs) { CK_RV rv; #if !defined(_WIN32) pid_t current_pid = getpid(); #endif int rc; unsigned int i; sc_context_param_t ctx_opts; /* Handle fork() exception */ #if !defined(_WIN32) if (current_pid != initialized_pid) { C_Finalize(NULL_PTR); } initialized_pid = current_pid; in_finalize = 0; #endif if (context != NULL) { sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_Initialize(): Cryptoki already initialized\n"); return CKR_CRYPTOKI_ALREADY_INITIALIZED; } rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pInitArgs); if (rv != CKR_OK) goto out; /* set context options */ memset(&ctx_opts, 0, sizeof(sc_context_param_t)); ctx_opts.ver = 0; ctx_opts.app_name = "opensc-pkcs11"; ctx_opts.thread_ctx = &sc_thread_ctx; rc = sc_context_create(&context, &ctx_opts); if (rc != SC_SUCCESS) { rv = CKR_GENERAL_ERROR; goto out; } /* Load configuration */ load_pkcs11_parameters(&sc_pkcs11_conf, context); /* List of sessions */ list_init(&sessions); list_attributes_seeker(&sessions, session_list_seeker); /* List of slots */ list_init(&virtual_slots); list_attributes_seeker(&virtual_slots, slot_list_seeker); /* Create a slot for a future "PnP" stuff. */ if (sc_pkcs11_conf.plug_and_play) { create_slot(NULL); } /* Create slots for readers found on initialization */ for (i=0; i<sc_ctx_get_reader_count(context); i++) { initialize_reader(sc_ctx_get_reader(context, i)); } /* Set initial event state on slots */ for (i=0; i<list_size(&virtual_slots); i++) { sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); slot->events = 0; /* Initially there are no events */ } out: if (context != NULL) sc_debug(context, SC_LOG_DEBUG_NORMAL, "C_Initialize() = %s", lookup_enum ( RV_T, rv )); if (rv != CKR_OK) { if (context != NULL) { sc_release_context(context); context = NULL; } /* Release and destroy the mutex */ sc_pkcs11_free_lock(); } return rv; }
CK_RV C_Initialize(CK_VOID_PTR pInitArgs) { CK_RV rv; #if !defined(_WIN32) pid_t current_pid = getpid(); #endif int rc; unsigned int i; sc_context_param_t ctx_opts; #if !defined(_WIN32) /* Handle fork() exception */ if (current_pid != initialized_pid) { if (context) context->flags |= SC_CTX_FLAG_TERMINATE; C_Finalize(NULL_PTR); } initialized_pid = current_pid; in_finalize = 0; #endif if (context != NULL) { sc_log(context, "C_Initialize(): Cryptoki already initialized\n"); return CKR_CRYPTOKI_ALREADY_INITIALIZED; } rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pInitArgs); if (rv != CKR_OK) goto out; /* set context options */ memset(&ctx_opts, 0, sizeof(sc_context_param_t)); ctx_opts.ver = 0; ctx_opts.app_name = MODULE_APP_NAME; ctx_opts.thread_ctx = &sc_thread_ctx; rc = sc_context_create(&context, &ctx_opts); if (rc != SC_SUCCESS) { rv = CKR_GENERAL_ERROR; goto out; } /* Load configuration */ load_pkcs11_parameters(&sc_pkcs11_conf, context); /* List of sessions */ list_init(&sessions); list_attributes_seeker(&sessions, session_list_seeker); /* List of slots */ list_init(&virtual_slots); list_attributes_seeker(&virtual_slots, slot_list_seeker); /* Create a slot for a future "PnP" stuff. */ if (sc_pkcs11_conf.plug_and_play) { create_slot(NULL); } /* Create slots for readers found on initialization, only if in 2.11 mode */ if (!sc_pkcs11_conf.plug_and_play) { for (i=0; i<sc_ctx_get_reader_count(context); i++) { initialize_reader(sc_ctx_get_reader(context, i)); } } out: if (context != NULL) sc_log(context, "C_Initialize() = %s", lookup_enum ( RV_T, rv )); if (rv != CKR_OK) { if (context != NULL) { sc_release_context(context); context = NULL; } /* Release and destroy the mutex */ sc_pkcs11_free_lock(); } return rv; }
CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ CK_VOID_PTR pReserved) /* reserved. Should be NULL_PTR */ { sc_reader_t *found; unsigned int mask, events; void *reader_states = NULL; CK_SLOT_ID slot_id; CK_RV rv; int r; if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD; sc_log(context, "C_WaitForSlotEvent(block=%d)", !(flags & CKF_DONT_BLOCK)); /* Not all pcsc-lite versions implement consistently used functions as they are */ /* FIXME: add proper checking into build to check correct pcsc-lite version for SCardStatusChange/SCardCancel */ if (!(flags & CKF_DONT_BLOCK)) return CKR_FUNCTION_NOT_SUPPORTED; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; mask = SC_EVENT_CARD_EVENTS; /* Detect and add new slots for added readers v2.20 */ if (sc_pkcs11_conf.plug_and_play) { mask |= SC_EVENT_READER_EVENTS; } rv = slot_find_changed(&slot_id, mask); if ((rv == CKR_OK) || (flags & CKF_DONT_BLOCK)) goto out; again: sc_log(context, "C_WaitForSlotEvent() reader_states:%p", reader_states); sc_pkcs11_unlock(); r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states); if (sc_pkcs11_conf.plug_and_play && events & SC_EVENT_READER_ATTACHED) { /* NSS/Firefox Triggers a C_GetSlotList(NULL) only if a slot ID is returned that it does not know yet Change the first hotplug slot id on every call to make this happen. */ sc_pkcs11_slot_t *hotplug_slot = list_get_at(&virtual_slots, 0); *pSlot= hotplug_slot->id -1; rv = sc_pkcs11_lock(); if (rv != CKR_OK) return rv; goto out; } /* Was C_Finalize called ? */ if (in_finalize == 1) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((rv = sc_pkcs11_lock()) != CKR_OK) return rv; if (r != SC_SUCCESS) { sc_log(context, "sc_wait_for_event() returned %d\n", r); rv = sc_to_cryptoki_error(r, "C_WaitForSlotEvent"); goto out; } /* If no changed slot was found (maybe an unsupported card * was inserted/removed) then go waiting again */ rv = slot_find_changed(&slot_id, mask); if (rv != CKR_OK) goto again; out: if (pSlot) *pSlot = slot_id; /* Free allocated readers states holder */ if (reader_states) { sc_log(context, "free reader states"); sc_wait_for_event(context, 0, NULL, NULL, -1, &reader_states); } sc_log(context, "C_WaitForSlotEvent() = %s", lookup_enum (RV_T, rv)); sc_pkcs11_unlock(); return rv; }
void show_error(FILE *f, char *str, CK_RV rc) { fprintf(f, "%s returned: %ld %s", str, rc, lookup_enum(RV_T, rc)); fprintf(f, "\n"); }