예제 #1
0
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
}
예제 #3
0
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #7
0
파일: pkcs11-object.c 프로젝트: jpki/OpenSC
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;
}
예제 #9
0
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
}
예제 #11
0
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;
}
예제 #13
0
파일: pkcs11-object.c 프로젝트: jpki/OpenSC
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;
}
예제 #15
0
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
}
예제 #16
0
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;
}
예제 #17
0
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;
}
예제 #18
0
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;
}
예제 #19
0
파일: pkcs11-object.c 프로젝트: jpki/OpenSC
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;
}
예제 #20
0
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;
}
예제 #21
0
파일: pkcs11-object.c 프로젝트: jpki/OpenSC
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;
}
예제 #22
0
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
}
예제 #23
0
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
}
예제 #26
0
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;
}
예제 #27
0
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;
}
예제 #28
0
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;
}
예제 #29
0
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;
}