Beispiel #1
0
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;
}
Beispiel #2
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
}
Beispiel #3
0
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
}
Beispiel #4
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;
}
Beispiel #5
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;
}
Beispiel #6
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;
}
Beispiel #7
0
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;
}
Beispiel #8
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;
}
Beispiel #9
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
}
Beispiel #10
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;
}
Beispiel #11
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;
}
Beispiel #12
0
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);
    }
}
Beispiel #13
0
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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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);
}
Beispiel #16
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;
	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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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);
}
Beispiel #20
0
/*
 * 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;
}
Beispiel #21
0
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
}
Beispiel #22
0
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;
}
Beispiel #23
0
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;
}
Beispiel #24
0
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;
}
Beispiel #26
0
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;
}
Beispiel #27
0
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;
}
Beispiel #28
0
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");
}