- New mechanism framework
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@775 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
a01b8d0b24
commit
21dfabee27
|
@ -87,6 +87,7 @@ struct pkcs15_pubkey_object {
|
||||||
struct sc_pkcs15_pubkey *key;
|
struct sc_pkcs15_pubkey *key;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int register_mechanisms(struct sc_pkcs11_card *p11card);
|
||||||
static int get_public_exponent(struct sc_pkcs15_pubkey *,
|
static int get_public_exponent(struct sc_pkcs15_pubkey *,
|
||||||
CK_ATTRIBUTE_PTR);
|
CK_ATTRIBUTE_PTR);
|
||||||
static int get_modulus(struct sc_pkcs15_pubkey *,
|
static int get_modulus(struct sc_pkcs15_pubkey *,
|
||||||
|
@ -95,9 +96,6 @@ static int get_modulus_bits(struct sc_pkcs15_pubkey *,
|
||||||
CK_ATTRIBUTE_PTR);
|
CK_ATTRIBUTE_PTR);
|
||||||
static int asn1_sequence_wrapper(const u8 *, size_t, CK_ATTRIBUTE_PTR);
|
static int asn1_sequence_wrapper(const u8 *, size_t, CK_ATTRIBUTE_PTR);
|
||||||
static void cache_pin(void *, int, const void *, size_t);
|
static void cache_pin(void *, int, const void *, size_t);
|
||||||
#ifdef HAVE_OPENSSL
|
|
||||||
static void hash_sha1(const void *, size_t, unsigned char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* PKCS#15 Framework */
|
/* PKCS#15 Framework */
|
||||||
|
|
||||||
|
@ -106,7 +104,9 @@ static CK_RV pkcs15_bind(struct sc_pkcs11_card *p11card)
|
||||||
int rc = sc_pkcs15_bind(p11card->card,
|
int rc = sc_pkcs15_bind(p11card->card,
|
||||||
(struct sc_pkcs15_card**) &p11card->fw_data);
|
(struct sc_pkcs15_card**) &p11card->fw_data);
|
||||||
debug(context, "Binding to PKCS#15, rc=%d\n", rc);
|
debug(context, "Binding to PKCS#15, rc=%d\n", rc);
|
||||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
if (rc < 0)
|
||||||
|
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||||
|
return register_mechanisms(p11card);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CK_RV pkcs15_unbind(struct sc_pkcs11_card *p11card)
|
static CK_RV pkcs15_unbind(struct sc_pkcs11_card *p11card)
|
||||||
|
@ -411,9 +411,6 @@ static CK_RV pkcs15_get_mechanism_list(struct sc_pkcs11_card *p11card,
|
||||||
static const CK_MECHANISM_TYPE mechanism_list[] = {
|
static const CK_MECHANISM_TYPE mechanism_list[] = {
|
||||||
CKM_RSA_PKCS,
|
CKM_RSA_PKCS,
|
||||||
CKM_RSA_X_509,
|
CKM_RSA_X_509,
|
||||||
#ifdef HAVE_OPENSSL
|
|
||||||
CKM_SHA1_RSA_PKCS,
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
const int numMechanisms = sizeof(mechanism_list) / sizeof(mechanism_list[0]);
|
const int numMechanisms = sizeof(mechanism_list) / sizeof(mechanism_list[0]);
|
||||||
|
|
||||||
|
@ -439,8 +436,9 @@ static CK_RV pkcs15_get_mechanism_info(struct sc_pkcs11_card *p11card,
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CKM_RSA_PKCS:
|
case CKM_RSA_PKCS:
|
||||||
case CKM_SHA1_RSA_PKCS:
|
case CKM_RSA_X_509:
|
||||||
pInfo->flags = CKF_HW | CKF_SIGN;
|
/* FIXME: we should consult the card on what it supports */
|
||||||
|
pInfo->flags = CKF_HW | CKF_SIGN | CKF_UNWRAP;
|
||||||
pInfo->ulMinKeySize = 512;
|
pInfo->ulMinKeySize = 512;
|
||||||
pInfo->ulMaxKeySize = 2048;
|
pInfo->ulMaxKeySize = 2048;
|
||||||
break;
|
break;
|
||||||
|
@ -1132,9 +1130,6 @@ CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
|
||||||
{
|
{
|
||||||
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj;
|
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj;
|
||||||
int rv, flags = 0;
|
int rv, flags = 0;
|
||||||
#ifdef HAVE_OPENSSL
|
|
||||||
unsigned char digest[20];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
debug(context, "Initiating signing operation.\n");
|
debug(context, "Initiating signing operation.\n");
|
||||||
|
|
||||||
|
@ -1166,15 +1161,7 @@ CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
|
||||||
case CKM_RSA_X_509:
|
case CKM_RSA_X_509:
|
||||||
flags = SC_ALGORITHM_RSA_RAW;
|
flags = SC_ALGORITHM_RSA_RAW;
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_OPENSSL
|
/* CKM_SHA1_RSA_PKCS et al are handled at the mechanism layer */
|
||||||
case CKM_SHA1_RSA_PKCS:
|
|
||||||
|
|
||||||
flags |= SC_ALGORITHM_RSA_HASH_SHA1;
|
|
||||||
hash_sha1(pData, ulDataLen, digest);
|
|
||||||
pData = digest;
|
|
||||||
ulDataLen = 20;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
return CKR_MECHANISM_INVALID;
|
return CKR_MECHANISM_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -1491,16 +1478,30 @@ cache_pin(void *p, int user, const void *pin, size_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL
|
/*
|
||||||
#include <openssl/sha.h>
|
* Mechanism handling
|
||||||
|
* FIXME: We should consult the card's algorithm list to
|
||||||
static void
|
* find out what operations it supports
|
||||||
hash_sha1(const void *data, size_t size, unsigned char *digest)
|
*/
|
||||||
|
int
|
||||||
|
register_mechanisms(struct sc_pkcs11_card *p11card)
|
||||||
{
|
{
|
||||||
SHA_CTX ctx;
|
CK_MECHANISM_INFO mech_info;
|
||||||
|
int rc;
|
||||||
|
|
||||||
SHA1_Init(&ctx);
|
mech_info.flags = CKF_HW | CKF_SIGN | CKF_UNWRAP;
|
||||||
SHA1_Update(&ctx, data, size);
|
mech_info.ulMinKeySize = 512;
|
||||||
SHA1_Final(digest, &ctx);
|
mech_info.ulMaxKeySize = 2048;
|
||||||
|
rc = sc_pkcs11_register_mechanism(p11card,
|
||||||
|
sc_pkcs11_new_fw_mechanism(CKM_RSA_PKCS, &mech_info, CKK_RSA, NULL));
|
||||||
|
if (rc != CKR_OK)
|
||||||
|
return rc;
|
||||||
|
rc = sc_pkcs11_register_mechanism(p11card,
|
||||||
|
sc_pkcs11_new_fw_mechanism(CKM_RSA_X_509, &mech_info, CKK_RSA, NULL));
|
||||||
|
if (rc != CKR_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Register generic mechanisms (e.g. digest mechanisms, software encryption/
|
||||||
|
* decryption stuff, and hash+sign algorithms */
|
||||||
|
return sc_pkcs11_register_generic_mechanisms(p11card);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -0,0 +1,461 @@
|
||||||
|
/*
|
||||||
|
* Generic handling of PKCS11 mechanisms
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 Olaf Kirch <okir@lst.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sc-pkcs11.h"
|
||||||
|
|
||||||
|
struct hash_signature_info {
|
||||||
|
CK_MECHANISM_TYPE mech;
|
||||||
|
CK_MECHANISM_TYPE hash_mech;
|
||||||
|
CK_MECHANISM_TYPE sign_mech;
|
||||||
|
sc_pkcs11_mechanism_type_t *hash_type;
|
||||||
|
sc_pkcs11_mechanism_type_t *sign_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct signature_data {
|
||||||
|
struct sc_pkcs11_object *key;
|
||||||
|
struct hash_signature_info *info;
|
||||||
|
sc_pkcs11_operation_t * md;
|
||||||
|
CK_BYTE buffer[4096/8];
|
||||||
|
unsigned int buffer_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register a mechanism
|
||||||
|
*/
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_register_mechanism(struct sc_pkcs11_card *p11card,
|
||||||
|
sc_pkcs11_mechanism_type_t *mt)
|
||||||
|
{
|
||||||
|
sc_pkcs11_mechanism_type_t **p;
|
||||||
|
|
||||||
|
if (mt == NULL)
|
||||||
|
return CKR_HOST_MEMORY;
|
||||||
|
|
||||||
|
p = (sc_pkcs11_mechanism_type_t **) realloc(p11card->mechanisms,
|
||||||
|
(p11card->nmechanisms + 2) * sizeof(*p));
|
||||||
|
if (p == NULL)
|
||||||
|
return CKR_HOST_MEMORY;
|
||||||
|
p11card->mechanisms = p;
|
||||||
|
p[p11card->nmechanisms++] = mt;
|
||||||
|
p[p11card->nmechanisms] = NULL;
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up a mechanism
|
||||||
|
*/
|
||||||
|
sc_pkcs11_mechanism_type_t *
|
||||||
|
sc_pkcs11_find_mechanism(struct sc_pkcs11_card *p11card, CK_MECHANISM_TYPE mech, int flags)
|
||||||
|
{
|
||||||
|
sc_pkcs11_mechanism_type_t *mt;
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
|
for (n = 0; n < p11card->nmechanisms; n++) {
|
||||||
|
mt = p11card->mechanisms[n];
|
||||||
|
if (mt && mt->mech == mech && ((mt->mech_info.flags & flags) == flags))
|
||||||
|
return mt;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Query mechanisms.
|
||||||
|
* We do this by looping over all registered mechanisms and
|
||||||
|
* checked whether it's supported by the current token.
|
||||||
|
*
|
||||||
|
* XXX: We may want to cache this list on a per slot/token basis
|
||||||
|
*/
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_get_mechanism_list(struct sc_pkcs11_card *p11card,
|
||||||
|
CK_MECHANISM_TYPE_PTR pList,
|
||||||
|
CK_ULONG_PTR pulCount)
|
||||||
|
{
|
||||||
|
sc_pkcs11_mechanism_type_t *mt;
|
||||||
|
unsigned int n, count = 0;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
for (n = 0; n < p11card->nmechanisms; n++) {
|
||||||
|
if (!(mt = p11card->mechanisms[n]))
|
||||||
|
continue;
|
||||||
|
if (count < *pulCount && pList)
|
||||||
|
pList[count] = mt->mech;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = CKR_OK;
|
||||||
|
if (count > *pulCount)
|
||||||
|
rv = CKR_BUFFER_TOO_SMALL;
|
||||||
|
*pulCount = count;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_get_mechanism_info(struct sc_pkcs11_card *p11card,
|
||||||
|
CK_MECHANISM_TYPE mechanism,
|
||||||
|
CK_MECHANISM_INFO_PTR pInfo)
|
||||||
|
{
|
||||||
|
sc_pkcs11_mechanism_type_t *mt;
|
||||||
|
|
||||||
|
if (!(mt = sc_pkcs11_find_mechanism(p11card, mechanism, 0)))
|
||||||
|
return CKR_MECHANISM_INVALID;
|
||||||
|
memcpy(pInfo, &mt->mech_info, sizeof(*pInfo));
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create/destroy operation handle
|
||||||
|
*/
|
||||||
|
sc_pkcs11_operation_t *
|
||||||
|
sc_pkcs11_new_operation(sc_pkcs11_session_t *session,
|
||||||
|
sc_pkcs11_mechanism_type_t *type)
|
||||||
|
{
|
||||||
|
sc_pkcs11_operation_t *res;
|
||||||
|
|
||||||
|
res = (sc_pkcs11_operation_t *) calloc(1, type->obj_size);
|
||||||
|
if (res) {
|
||||||
|
res->session = session;
|
||||||
|
res->type = type;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_pkcs11_release_operation(sc_pkcs11_operation_t **ptr)
|
||||||
|
{
|
||||||
|
sc_pkcs11_operation_t *operation = *ptr;
|
||||||
|
|
||||||
|
if (!operation)
|
||||||
|
return;
|
||||||
|
if (operation->type && operation->type->release)
|
||||||
|
operation->type->release(operation);
|
||||||
|
memset(operation, 0, sizeof(*operation));
|
||||||
|
free(operation);
|
||||||
|
*ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_md_init(struct sc_pkcs11_session *session,
|
||||||
|
CK_MECHANISM_PTR pMechanism)
|
||||||
|
{
|
||||||
|
struct sc_pkcs11_card *p11card;
|
||||||
|
sc_pkcs11_operation_t *operation;
|
||||||
|
sc_pkcs11_mechanism_type_t *mt;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (!session || !session->slot
|
||||||
|
|| !(p11card = session->slot->card))
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
|
||||||
|
/* See if we support this mechanism type */
|
||||||
|
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_DIGEST);
|
||||||
|
if (mt == NULL)
|
||||||
|
return CKR_MECHANISM_INVALID;
|
||||||
|
|
||||||
|
rv = session_start_operation(session, SC_PKCS11_OPERATION_DIGEST, mt, &operation);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
|
||||||
|
|
||||||
|
return mt->md_init(operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_md_update(struct sc_pkcs11_session *session,
|
||||||
|
CK_BYTE_PTR pData, CK_ULONG ulDataLen)
|
||||||
|
{
|
||||||
|
sc_pkcs11_operation_t *op;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = session_get_operation(session, SC_PKCS11_OPERATION_DIGEST, &op);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
return op->type->md_update(op, pData, ulDataLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_md_final(struct sc_pkcs11_session *session,
|
||||||
|
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
|
||||||
|
{
|
||||||
|
sc_pkcs11_operation_t *op;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = session_get_operation(session, SC_PKCS11_OPERATION_DIGEST, &op);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = op->type->md_final(op, pData, pulDataLen);
|
||||||
|
if (rv != CKR_BUFFER_TOO_SMALL && pData != NULL)
|
||||||
|
session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize a signing context. When we get here, we know
|
||||||
|
* the key object is capable of signing _something_
|
||||||
|
*/
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_sign_init(struct sc_pkcs11_session *session,
|
||||||
|
CK_MECHANISM_PTR pMechanism,
|
||||||
|
struct sc_pkcs11_object *key,
|
||||||
|
CK_MECHANISM_TYPE key_type)
|
||||||
|
{
|
||||||
|
struct sc_pkcs11_card *p11card;
|
||||||
|
sc_pkcs11_operation_t *operation;
|
||||||
|
sc_pkcs11_mechanism_type_t *mt;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (!session || !session->slot
|
||||||
|
|| !(p11card = session->slot->card))
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
|
||||||
|
/* See if we support this mechanism type */
|
||||||
|
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_SIGN);
|
||||||
|
if (mt == NULL)
|
||||||
|
return CKR_MECHANISM_INVALID;
|
||||||
|
|
||||||
|
/* See if compatible with key type */
|
||||||
|
if (mt->key_type != key_type)
|
||||||
|
return CKR_KEY_TYPE_INCONSISTENT;
|
||||||
|
|
||||||
|
rv = session_start_operation(session, SC_PKCS11_OPERATION_SIGN, mt, &operation);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
|
||||||
|
return mt->sign_init(operation, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_sign_update(struct sc_pkcs11_session *session,
|
||||||
|
CK_BYTE_PTR pData, CK_ULONG ulDataLen)
|
||||||
|
{
|
||||||
|
sc_pkcs11_operation_t *op;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
if (op->type->sign_update == NULL)
|
||||||
|
return CKR_KEY_TYPE_INCONSISTENT;
|
||||||
|
|
||||||
|
return op->type->sign_update(op, pData, ulDataLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_sign_final(struct sc_pkcs11_session *session,
|
||||||
|
CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
|
||||||
|
{
|
||||||
|
sc_pkcs11_operation_t *op;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/* Bail out for signature mechanisms that don't do hashing */
|
||||||
|
if (op->type->sign_final == NULL)
|
||||||
|
return CKR_KEY_TYPE_INCONSISTENT;
|
||||||
|
|
||||||
|
rv = op->type->sign_final(op, pSignature, pulSignatureLen);
|
||||||
|
|
||||||
|
if (rv != CKR_BUFFER_TOO_SMALL && pSignature != NULL)
|
||||||
|
session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize a signature operation
|
||||||
|
*/
|
||||||
|
static CK_RV
|
||||||
|
sc_pkcs11_signature_init(sc_pkcs11_operation_t *operation,
|
||||||
|
struct sc_pkcs11_object *key)
|
||||||
|
{
|
||||||
|
struct hash_signature_info *info;
|
||||||
|
struct signature_data *data;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (!(data = (struct signature_data *) calloc(1, sizeof(*data))))
|
||||||
|
return CKR_HOST_MEMORY;
|
||||||
|
|
||||||
|
data->info = NULL;
|
||||||
|
data->key = key;
|
||||||
|
|
||||||
|
/* If this is a signature with hash operation, set up the
|
||||||
|
* hash operation */
|
||||||
|
info = (struct hash_signature_info *) operation->type->mech_data;
|
||||||
|
if (info != NULL) {
|
||||||
|
/* Initialize hash operation */
|
||||||
|
data->md = sc_pkcs11_new_operation(operation->session,
|
||||||
|
info->hash_type);
|
||||||
|
if (data->md == NULL)
|
||||||
|
rv = CKR_HOST_MEMORY;
|
||||||
|
else
|
||||||
|
rv = info->hash_type->md_init(data->md);
|
||||||
|
if (rv != CKR_OK) {
|
||||||
|
sc_pkcs11_release_operation(&data->md);
|
||||||
|
free(data);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
data->info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
operation->priv_data = data;
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CK_RV
|
||||||
|
sc_pkcs11_signature_update(sc_pkcs11_operation_t *operation,
|
||||||
|
CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
|
||||||
|
{
|
||||||
|
struct signature_data *data;
|
||||||
|
|
||||||
|
data = (struct signature_data *) operation->priv_data;
|
||||||
|
if (data->md) {
|
||||||
|
sc_pkcs11_operation_t *md = data->md;
|
||||||
|
|
||||||
|
return md->type->md_update(md, pPart, ulPartLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This signature mechanism operates on the raw data */
|
||||||
|
if (data->buffer_len + ulPartLen > sizeof(data->buffer))
|
||||||
|
return CKR_DATA_LEN_RANGE;
|
||||||
|
memcpy(data->buffer + data->buffer_len, pPart, ulPartLen);
|
||||||
|
data->buffer_len += ulPartLen;
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CK_RV
|
||||||
|
sc_pkcs11_signature_final(sc_pkcs11_operation_t *operation,
|
||||||
|
CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
|
||||||
|
{
|
||||||
|
CK_MECHANISM mechanism;
|
||||||
|
struct signature_data *data;
|
||||||
|
struct sc_pkcs11_object *key;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
data = (struct signature_data *) operation->priv_data;
|
||||||
|
|
||||||
|
if (data->md) {
|
||||||
|
sc_pkcs11_operation_t *md = data->md;
|
||||||
|
CK_ULONG len = sizeof(data->buffer);
|
||||||
|
|
||||||
|
rv = md->type->md_final(md, data->buffer, &len);
|
||||||
|
if (rv == CKR_BUFFER_TOO_SMALL)
|
||||||
|
rv = CKR_FUNCTION_FAILED;
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
data->buffer_len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The mechanism we pass to the framework's sign operation
|
||||||
|
* contains the parameters we got from the caller, plus
|
||||||
|
* the mechanism type of the underlying signature operation */
|
||||||
|
mechanism = operation->mechanism;
|
||||||
|
if (data->info)
|
||||||
|
mechanism.mechanism = data->info->sign_mech;
|
||||||
|
|
||||||
|
key = data->key;
|
||||||
|
return key->ops->sign(operation->session,
|
||||||
|
key, &mechanism,
|
||||||
|
data->buffer, data->buffer_len,
|
||||||
|
pSignature, pulSignatureLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_pkcs11_signature_release(sc_pkcs11_operation_t *operation)
|
||||||
|
{
|
||||||
|
struct signature_data *data;
|
||||||
|
|
||||||
|
data = (struct signature_data *) operation->priv_data;
|
||||||
|
sc_pkcs11_release_operation(&data->md);
|
||||||
|
memset(data, 0, sizeof(*data));
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create new mechanism type for a mechanism supported by
|
||||||
|
* the card
|
||||||
|
*/
|
||||||
|
sc_pkcs11_mechanism_type_t *
|
||||||
|
sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE mech,
|
||||||
|
CK_MECHANISM_INFO_PTR pInfo,
|
||||||
|
CK_KEY_TYPE key_type,
|
||||||
|
void *priv_data)
|
||||||
|
{
|
||||||
|
sc_pkcs11_mechanism_type_t *mt;
|
||||||
|
|
||||||
|
mt = (sc_pkcs11_mechanism_type_t *) calloc(1, sizeof(*mt));
|
||||||
|
if (mt == NULL)
|
||||||
|
return mt;
|
||||||
|
mt->mech = mech;
|
||||||
|
mt->mech_info = *pInfo;
|
||||||
|
mt->key_type = key_type;
|
||||||
|
mt->mech_data = priv_data;
|
||||||
|
mt->obj_size = sizeof(sc_pkcs11_operation_t);
|
||||||
|
|
||||||
|
mt->release = sc_pkcs11_signature_release;
|
||||||
|
|
||||||
|
if (pInfo->flags & CKF_SIGN) {
|
||||||
|
mt->sign_init = sc_pkcs11_signature_init;
|
||||||
|
mt->sign_update = sc_pkcs11_signature_update;
|
||||||
|
mt->sign_final = sc_pkcs11_signature_final;
|
||||||
|
}
|
||||||
|
if (pInfo->flags & CKF_UNWRAP) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
return mt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support for sign+hash
|
||||||
|
*/
|
||||||
|
static struct hash_signature_info sig_hash_mechs[] = {
|
||||||
|
{ CKM_SHA1_RSA_PKCS, CKM_SHA_1, CKM_RSA_PKCS },
|
||||||
|
{ CKM_MD5_RSA_PKCS, CKM_MD5, CKM_RSA_PKCS },
|
||||||
|
{ CKM_RIPEMD160_RSA_PKCS, CKM_RIPEMD160, CKM_RSA_PKCS },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register generic mechanisms, i.e.
|
||||||
|
* - software only algorithms such as digests
|
||||||
|
* - sign+hash mechanisms that use the card's
|
||||||
|
* signature ops and a generic digest mechanism
|
||||||
|
*/
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_register_generic_mechanisms(struct sc_pkcs11_card *p11card)
|
||||||
|
{
|
||||||
|
struct hash_signature_info *info;
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
sc_pkcs11_register_openssl_mechanisms(p11card);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (info = sig_hash_mechs; info->mech; info++) {
|
||||||
|
sc_pkcs11_mechanism_type_t *hash_type, *sign_type, *new_type;
|
||||||
|
|
||||||
|
hash_type = sc_pkcs11_find_mechanism(p11card, info->hash_mech, 0);
|
||||||
|
sign_type = sc_pkcs11_find_mechanism(p11card, info->sign_mech, CKF_SIGN);
|
||||||
|
if (!hash_type || !sign_type)
|
||||||
|
continue;
|
||||||
|
info->sign_type = sign_type;
|
||||||
|
info->hash_type = hash_type;
|
||||||
|
|
||||||
|
new_type = sc_pkcs11_new_fw_mechanism(info->mech,
|
||||||
|
&sign_type->mech_info,
|
||||||
|
sign_type->key_type,
|
||||||
|
info);
|
||||||
|
if (new_type)
|
||||||
|
sc_pkcs11_register_mechanism(p11card, new_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -165,40 +165,58 @@ CK_RV pool_find_and_delete(struct sc_pkcs11_pool *pool, CK_ULONG handle, void **
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Session manipulation */
|
/* Session manipulation */
|
||||||
CK_RV session_start_operation(struct sc_pkcs11_session *session, int type,
|
CK_RV session_start_operation(struct sc_pkcs11_session *session,
|
||||||
int size, struct sc_pkcs11_operation **operation)
|
int type,
|
||||||
|
sc_pkcs11_mechanism_type_t *mech,
|
||||||
|
struct sc_pkcs11_operation **operation)
|
||||||
{
|
{
|
||||||
|
sc_pkcs11_operation_t *op;
|
||||||
|
|
||||||
if (context == NULL)
|
if (context == NULL)
|
||||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||||
|
|
||||||
if (session->operation != NULL)
|
if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
|
||||||
|
if (session->operation[type] != NULL)
|
||||||
return CKR_OPERATION_ACTIVE;
|
return CKR_OPERATION_ACTIVE;
|
||||||
|
|
||||||
session->operation = (struct sc_pkcs11_operation*) malloc(size);
|
if (!(op = sc_pkcs11_new_operation(session, mech)))
|
||||||
session->operation->type = type;
|
return CKR_HOST_MEMORY;
|
||||||
*operation = session->operation;
|
|
||||||
|
session->operation[type] = op;
|
||||||
|
if (operation)
|
||||||
|
*operation = op;
|
||||||
|
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV session_check_operation(struct sc_pkcs11_session *session, int type)
|
CK_RV session_get_operation(struct sc_pkcs11_session *session, int type,
|
||||||
|
sc_pkcs11_operation_t **operation)
|
||||||
{
|
{
|
||||||
if (session->operation == NULL)
|
sc_pkcs11_operation_t *op;
|
||||||
|
|
||||||
|
if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
|
||||||
|
if (!(op = session->operation[type]))
|
||||||
return CKR_OPERATION_NOT_INITIALIZED;
|
return CKR_OPERATION_NOT_INITIALIZED;
|
||||||
|
|
||||||
if (session->operation->type != type)
|
if (operation)
|
||||||
return CKR_OPERATION_NOT_INITIALIZED;
|
*operation = op;
|
||||||
|
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV session_stop_operation(struct sc_pkcs11_session *session)
|
CK_RV session_stop_operation(struct sc_pkcs11_session *session, int type)
|
||||||
{
|
{
|
||||||
if (session->operation == NULL)
|
if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
|
||||||
|
if (session->operation[type] == NULL)
|
||||||
return CKR_OPERATION_NOT_INITIALIZED;
|
return CKR_OPERATION_NOT_INITIALIZED;
|
||||||
|
|
||||||
free(session->operation);
|
sc_pkcs11_release_operation(&session->operation[type]);
|
||||||
session->operation = NULL;
|
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* OpenSSL helper functions, e.g. for implementing MD5 support
|
||||||
|
* et al
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002 Olaf Kirch <okir@lst.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sc-pkcs11.h"
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
|
||||||
|
static CK_RV sc_pkcs11_openssl_md_init(sc_pkcs11_operation_t *);
|
||||||
|
static CK_RV sc_pkcs11_openssl_md_update(sc_pkcs11_operation_t *,
|
||||||
|
CK_BYTE_PTR, CK_ULONG);
|
||||||
|
static CK_RV sc_pkcs11_openssl_md_final(sc_pkcs11_operation_t *,
|
||||||
|
CK_BYTE_PTR, CK_ULONG_PTR);
|
||||||
|
static void sc_pkcs11_openssl_md_release(sc_pkcs11_operation_t *);
|
||||||
|
|
||||||
|
static sc_pkcs11_mechanism_type_t openssl_sha1_mech = {
|
||||||
|
CKM_SHA_1,
|
||||||
|
{ 0, 0, CKF_DIGEST }, 0,
|
||||||
|
sizeof(struct sc_pkcs11_operation),
|
||||||
|
sc_pkcs11_openssl_md_release,
|
||||||
|
sc_pkcs11_openssl_md_init,
|
||||||
|
sc_pkcs11_openssl_md_update,
|
||||||
|
sc_pkcs11_openssl_md_final
|
||||||
|
};
|
||||||
|
|
||||||
|
static sc_pkcs11_mechanism_type_t openssl_md5_mech = {
|
||||||
|
CKM_MD5,
|
||||||
|
{ 0, 0, CKF_DIGEST }, 0,
|
||||||
|
sizeof(struct sc_pkcs11_operation),
|
||||||
|
sc_pkcs11_openssl_md_release,
|
||||||
|
sc_pkcs11_openssl_md_init,
|
||||||
|
sc_pkcs11_openssl_md_update,
|
||||||
|
sc_pkcs11_openssl_md_final
|
||||||
|
};
|
||||||
|
|
||||||
|
static sc_pkcs11_mechanism_type_t openssl_ripemd160_mech = {
|
||||||
|
CKM_RIPEMD160,
|
||||||
|
{ 0, 0, CKF_DIGEST }, 0,
|
||||||
|
sizeof(struct sc_pkcs11_operation),
|
||||||
|
sc_pkcs11_openssl_md_release,
|
||||||
|
sc_pkcs11_openssl_md_init,
|
||||||
|
sc_pkcs11_openssl_md_update,
|
||||||
|
sc_pkcs11_openssl_md_final
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *card)
|
||||||
|
{
|
||||||
|
openssl_sha1_mech.mech_data = EVP_sha1();
|
||||||
|
sc_pkcs11_register_mechanism(card, &openssl_sha1_mech);
|
||||||
|
openssl_md5_mech.mech_data = EVP_md5();
|
||||||
|
sc_pkcs11_register_mechanism(card, &openssl_md5_mech);
|
||||||
|
openssl_ripemd160_mech.mech_data = EVP_ripemd160();
|
||||||
|
sc_pkcs11_register_mechanism(card, &openssl_ripemd160_mech);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle OpenSSL digest functions
|
||||||
|
*/
|
||||||
|
#define DIGEST_CTX(op) \
|
||||||
|
((EVP_MD_CTX *) (op)->priv_data)
|
||||||
|
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_openssl_md_init(sc_pkcs11_operation_t *op)
|
||||||
|
{
|
||||||
|
sc_pkcs11_mechanism_type_t *mt;
|
||||||
|
EVP_MD_CTX *md_ctx;
|
||||||
|
EVP_MD *md;
|
||||||
|
|
||||||
|
if (!op || !(mt = op->type) || !(md = (EVP_MD *) mt->mech_data))
|
||||||
|
return CKR_ARGUMENTS_BAD;
|
||||||
|
|
||||||
|
if (!(md_ctx = calloc(1, sizeof(*md_ctx))))
|
||||||
|
return CKR_HOST_MEMORY;
|
||||||
|
EVP_DigestInit(md_ctx, md);
|
||||||
|
op->priv_data = md_ctx;
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_openssl_md_update(sc_pkcs11_operation_t *op,
|
||||||
|
CK_BYTE_PTR pData, CK_ULONG pDataLen)
|
||||||
|
{
|
||||||
|
EVP_DigestUpdate(DIGEST_CTX(op), pData, pDataLen);
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CK_RV
|
||||||
|
sc_pkcs11_openssl_md_final(sc_pkcs11_operation_t *op,
|
||||||
|
CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
|
||||||
|
{
|
||||||
|
EVP_MD_CTX *md_ctx = DIGEST_CTX(op);
|
||||||
|
unsigned int len = *pulDigestLen;
|
||||||
|
|
||||||
|
if (len < EVP_MD_CTX_size(md_ctx)) {
|
||||||
|
*pulDigestLen = EVP_MD_CTX_size(md_ctx);
|
||||||
|
return CKR_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
EVP_DigestFinal(md_ctx, pDigest, &len);
|
||||||
|
*pulDigestLen = len;
|
||||||
|
|
||||||
|
return CKR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_pkcs11_openssl_md_release(sc_pkcs11_operation_t *op)
|
||||||
|
{
|
||||||
|
EVP_MD_CTX *md_ctx = DIGEST_CTX(op);
|
||||||
|
|
||||||
|
if (md_ctx)
|
||||||
|
free(md_ctx);
|
||||||
|
op->priv_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -180,10 +180,7 @@ CK_RV C_GetMechanismList(CK_SLOT_ID slotID,
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
return slot->card->framework->get_mechanism_list(slot->card,
|
return sc_pkcs11_get_mechanism_list(slot->card, pMechanismList, pulCount);
|
||||||
slot->fw_data,
|
|
||||||
pMechanismList,
|
|
||||||
pulCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
|
CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
|
||||||
|
@ -197,10 +194,7 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
return slot->card->framework->get_mechanism_info(slot->card,
|
return sc_pkcs11_get_mechanism_info(slot->card, type, pInfo);
|
||||||
slot->fw_data,
|
|
||||||
type,
|
|
||||||
pInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV C_InitToken(CK_SLOT_ID slotID,
|
CK_RV C_InitToken(CK_SLOT_ID slotID,
|
||||||
|
|
|
@ -22,6 +22,12 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "sc-pkcs11.h"
|
#include "sc-pkcs11.h"
|
||||||
|
|
||||||
|
/* Pseudo mechanism for the Find operation */
|
||||||
|
static sc_pkcs11_mechanism_type_t find_mechanism = {
|
||||||
|
0, { 0 }, 0,
|
||||||
|
sizeof(struct sc_pkcs11_find_operation),
|
||||||
|
};
|
||||||
|
|
||||||
CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, /* the session's handle */
|
CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
|
CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
|
||||||
CK_ULONG ulCount, /* attributes in template */
|
CK_ULONG ulCount, /* attributes in template */
|
||||||
|
@ -171,9 +177,8 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
debug(context, "C_FindObjectsInit(slot = %d)\n", session->slot->id);
|
debug(context, "C_FindObjectsInit(slot = %d)\n", session->slot->id);
|
||||||
dump_template("C_FindObjectsInit()", pTemplate, ulCount);
|
dump_template("C_FindObjectsInit()", pTemplate, ulCount);
|
||||||
|
|
||||||
rv = session_start_operation(session,
|
rv = session_start_operation(session, SC_PKCS11_OPERATION_FIND,
|
||||||
SC_PKCS11_OPERATION_FIND,
|
&find_mechanism,
|
||||||
sizeof(struct sc_pkcs11_find_operation),
|
|
||||||
(struct sc_pkcs11_operation**) &operation);
|
(struct sc_pkcs11_operation**) &operation);
|
||||||
|
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
|
@ -245,12 +250,11 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's han
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
rv = session_check_operation(session, SC_PKCS11_OPERATION_FIND);
|
rv = session_get_operation(session, SC_PKCS11_OPERATION_FIND,
|
||||||
|
(sc_pkcs11_operation_t **) &operation);
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
operation = (struct sc_pkcs11_find_operation*) session->operation;
|
|
||||||
|
|
||||||
to_return = operation->num_handles - operation->current_handle;
|
to_return = operation->num_handles - operation->current_handle;
|
||||||
if (to_return > ulMaxObjectCount)
|
if (to_return > ulMaxObjectCount)
|
||||||
to_return = ulMaxObjectCount;
|
to_return = ulMaxObjectCount;
|
||||||
|
@ -275,11 +279,11 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) /* the session's handle */
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
rv = session_check_operation(session, SC_PKCS11_OPERATION_FIND);
|
rv = session_get_operation(session, SC_PKCS11_OPERATION_FIND, NULL);
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
session_stop_operation(session);
|
session_stop_operation(session, SC_PKCS11_OPERATION_FIND);
|
||||||
return CKR_OK;
|
return CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +295,17 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) /* the session's handle */
|
||||||
CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
CK_MECHANISM_PTR pMechanism) /* the digesting mechanism */
|
CK_MECHANISM_PTR pMechanism) /* the digesting mechanism */
|
||||||
{
|
{
|
||||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
int rv;
|
||||||
|
struct sc_pkcs11_session *session;
|
||||||
|
|
||||||
|
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = sc_pkcs11_md_init(session, pMechanism);
|
||||||
|
|
||||||
|
debug(context, "C_DigestInit returns %d\n", rv);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */
|
CK_RV C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
|
@ -300,14 +314,36 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
CK_BYTE_PTR pDigest, /* receives the message digest */
|
CK_BYTE_PTR pDigest, /* receives the message digest */
|
||||||
CK_ULONG_PTR pulDigestLen) /* receives byte length of digest */
|
CK_ULONG_PTR pulDigestLen) /* receives byte length of digest */
|
||||||
{
|
{
|
||||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
int rv;
|
||||||
|
struct sc_pkcs11_session *session;
|
||||||
|
|
||||||
|
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = sc_pkcs11_md_update(session, pData, ulDataLen);
|
||||||
|
if (rv == CKR_OK)
|
||||||
|
rv = sc_pkcs11_md_final(session, pDigest, pulDigestLen);
|
||||||
|
|
||||||
|
debug(context, "C_Digest returns %d\n", rv);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
|
CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
CK_BYTE_PTR pPart, /* data to be digested */
|
CK_BYTE_PTR pPart, /* data to be digested */
|
||||||
CK_ULONG ulPartLen) /* bytes of data to be digested */
|
CK_ULONG ulPartLen) /* bytes of data to be digested */
|
||||||
{
|
{
|
||||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
int rv;
|
||||||
|
struct sc_pkcs11_session *session;
|
||||||
|
|
||||||
|
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = sc_pkcs11_md_update(session, pPart, ulPartLen);
|
||||||
|
|
||||||
|
debug(context, "C_DigestUpdate returns %d\n", rv);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, /* the session's handle */
|
CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
|
@ -320,7 +356,17 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
CK_BYTE_PTR pDigest, /* receives the message digest */
|
CK_BYTE_PTR pDigest, /* receives the message digest */
|
||||||
CK_ULONG_PTR pulDigestLen) /* receives byte count of digest */
|
CK_ULONG_PTR pulDigestLen) /* receives byte count of digest */
|
||||||
{
|
{
|
||||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
int rv;
|
||||||
|
struct sc_pkcs11_session *session;
|
||||||
|
|
||||||
|
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = sc_pkcs11_md_final(session, pDigest, pulDigestLen);
|
||||||
|
|
||||||
|
debug(context, "C_DigestFinal returns %d\n", rv);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV C_SignInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
CK_RV C_SignInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
|
@ -328,12 +374,13 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
CK_OBJECT_HANDLE hKey) /* handle of the signature key */
|
CK_OBJECT_HANDLE hKey) /* handle of the signature key */
|
||||||
{
|
{
|
||||||
CK_BBOOL can_sign;
|
CK_BBOOL can_sign;
|
||||||
|
CK_KEY_TYPE key_type;
|
||||||
CK_ATTRIBUTE sign_attribute = { CKA_SIGN, &can_sign, sizeof(can_sign) };
|
CK_ATTRIBUTE sign_attribute = { CKA_SIGN, &can_sign, sizeof(can_sign) };
|
||||||
|
CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) };
|
||||||
|
|
||||||
int rv;
|
int rv;
|
||||||
struct sc_pkcs11_session *session;
|
struct sc_pkcs11_session *session;
|
||||||
struct sc_pkcs11_object *object;
|
struct sc_pkcs11_object *object;
|
||||||
struct sc_pkcs11_sign_operation *operation;
|
|
||||||
|
|
||||||
rv = pool_find(&session_pool, hSession, (void**) &session);
|
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
|
@ -349,22 +396,15 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
rv = object->ops->get_attribute(session, object, &sign_attribute);
|
rv = object->ops->get_attribute(session, object, &sign_attribute);
|
||||||
if (rv != CKR_OK || !can_sign)
|
if (rv != CKR_OK || !can_sign)
|
||||||
return CKR_KEY_TYPE_INCONSISTENT;
|
return CKR_KEY_TYPE_INCONSISTENT;
|
||||||
|
rv = object->ops->get_attribute(session, object, &key_type_attr);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return CKR_KEY_TYPE_INCONSISTENT;
|
||||||
|
|
||||||
debug(context, "Sign operation initialized\n");
|
debug(context, "Sign operation initialized\n");
|
||||||
|
|
||||||
rv = session_start_operation(session,
|
rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type);
|
||||||
SC_PKCS11_OPERATION_SIGN,
|
|
||||||
sizeof(struct sc_pkcs11_sign_operation),
|
|
||||||
(struct sc_pkcs11_operation**) &operation);
|
|
||||||
|
|
||||||
if (rv != CKR_OK)
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
operation->key = object;
|
|
||||||
memcpy((void*) &operation->mechanism, (void*) pMechanism, sizeof(CK_MECHANISM));
|
|
||||||
|
|
||||||
debug(context, "Sign initialization succesful\n");
|
|
||||||
|
|
||||||
|
debug(context, "Sign initialization returns %d\n", rv);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,29 +416,16 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
struct sc_pkcs11_session *session;
|
struct sc_pkcs11_session *session;
|
||||||
struct sc_pkcs11_object *object;
|
|
||||||
struct sc_pkcs11_sign_operation *operation;
|
|
||||||
|
|
||||||
rv = pool_find(&session_pool, hSession, (void**) &session);
|
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
rv = session_check_operation(session, SC_PKCS11_OPERATION_SIGN);
|
rv = sc_pkcs11_sign_update(session, pData, ulDataLen);
|
||||||
if (rv != CKR_OK)
|
if (rv == CKR_OK)
|
||||||
return rv;
|
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
|
||||||
|
|
||||||
operation = (struct sc_pkcs11_sign_operation *) session->operation;
|
|
||||||
object = operation->key;
|
|
||||||
|
|
||||||
rv = object->ops->sign(session, object, &operation->mechanism,
|
|
||||||
pData, ulDataLen,
|
|
||||||
pSignature, pulSignatureLen);
|
|
||||||
|
|
||||||
debug(context, "Signing result was %d\n", rv);
|
debug(context, "Signing result was %d\n", rv);
|
||||||
|
|
||||||
if (rv != CKR_BUFFER_TOO_SMALL && pSignature != NULL_PTR)
|
|
||||||
session_stop_operation(session);
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -407,21 +434,73 @@ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
CK_BYTE_PTR pPart, /* the data (digest) to be signed */
|
CK_BYTE_PTR pPart, /* the data (digest) to be signed */
|
||||||
CK_ULONG ulPartLen) /* count of bytes to be signed */
|
CK_ULONG ulPartLen) /* count of bytes to be signed */
|
||||||
{
|
{
|
||||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
int rv;
|
||||||
|
struct sc_pkcs11_session *session;
|
||||||
|
|
||||||
|
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = sc_pkcs11_sign_update(session, pPart, ulPartLen);
|
||||||
|
debug(context, "C_SignUpdate returns %d\n", rv);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
|
CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
CK_BYTE_PTR pSignature, /* receives the signature */
|
CK_BYTE_PTR pSignature, /* receives the signature */
|
||||||
CK_ULONG_PTR pulSignatureLen) /* receives byte count of signature */
|
CK_ULONG_PTR pulSignatureLen) /* receives byte count of signature */
|
||||||
{
|
{
|
||||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
int rv;
|
||||||
|
struct sc_pkcs11_session *session;
|
||||||
|
|
||||||
|
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
|
||||||
|
debug(context, "C_SignFinal returns %d\n", rv);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
|
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
|
||||||
CK_OBJECT_HANDLE hKey) /* handle of the signature key */
|
CK_OBJECT_HANDLE hKey) /* handle of the signature key */
|
||||||
{
|
{
|
||||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
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) };
|
||||||
|
|
||||||
|
int rv;
|
||||||
|
struct sc_pkcs11_session *session;
|
||||||
|
struct sc_pkcs11_object *object;
|
||||||
|
|
||||||
|
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = pool_find(&session->slot->object_pool, hKey, (void**) &object);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
if (object->ops->sign == NULL_PTR)
|
||||||
|
return CKR_KEY_TYPE_INCONSISTENT;
|
||||||
|
|
||||||
|
rv = object->ops->get_attribute(session, object, &sign_attribute);
|
||||||
|
if (rv != CKR_OK || !can_sign)
|
||||||
|
return CKR_KEY_TYPE_INCONSISTENT;
|
||||||
|
rv = object->ops->get_attribute(session, object, &key_type_attr);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
return CKR_KEY_TYPE_INCONSISTENT;
|
||||||
|
|
||||||
|
/* XXX: need to tell the signature algorithm that we want
|
||||||
|
* to recover the signature */
|
||||||
|
debug(context, "SignRecover operation initialized\n");
|
||||||
|
|
||||||
|
rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type);
|
||||||
|
|
||||||
|
debug(context, "Sign initialization returns %d\n", rv);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, /* the session's handle */
|
CK_RV C_SignRecover(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||||
|
|
|
@ -163,6 +163,10 @@ struct sc_pkcs11_card {
|
||||||
struct sc_card *card;
|
struct sc_card *card;
|
||||||
struct sc_pkcs11_framework_ops *framework;
|
struct sc_pkcs11_framework_ops *framework;
|
||||||
void *fw_data;
|
void *fw_data;
|
||||||
|
|
||||||
|
/* List of supported mechanisms */
|
||||||
|
struct sc_pkcs11_mechanism_type **mechanisms;
|
||||||
|
unsigned int nmechanisms;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_pkcs11_slot {
|
struct sc_pkcs11_slot {
|
||||||
|
@ -183,21 +187,57 @@ struct sc_pkcs11_slot {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward decl */
|
||||||
|
typedef struct sc_pkcs11_operation sc_pkcs11_operation_t;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SC_PKCS11_OPERATION_FIND = 0,
|
||||||
|
SC_PKCS11_OPERATION_SIGN,
|
||||||
|
SC_PKCS11_OPERATION_DIGEST,
|
||||||
|
SC_PKCS11_OPERATION_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This describes a PKCS11 mechanism */
|
||||||
|
struct sc_pkcs11_mechanism_type {
|
||||||
|
CK_MECHANISM_TYPE mech; /* algorithm: md5, sha1, ... */
|
||||||
|
CK_MECHANISM_INFO mech_info; /* mechanism info */
|
||||||
|
CK_MECHANISM_TYPE key_type; /* for sign/decipher ops */
|
||||||
|
unsigned int obj_size;
|
||||||
|
|
||||||
|
/* General management */
|
||||||
|
void (*release)(sc_pkcs11_operation_t *);
|
||||||
|
|
||||||
|
/* Digest/sign Operations */
|
||||||
|
CK_RV (*md_init)(sc_pkcs11_operation_t *);
|
||||||
|
CK_RV (*md_update)(sc_pkcs11_operation_t *,
|
||||||
|
CK_BYTE_PTR, CK_ULONG);
|
||||||
|
CK_RV (*md_final)(sc_pkcs11_operation_t *,
|
||||||
|
CK_BYTE_PTR, CK_ULONG_PTR);
|
||||||
|
|
||||||
|
CK_RV (*sign_init)(sc_pkcs11_operation_t *,
|
||||||
|
struct sc_pkcs11_object *);
|
||||||
|
CK_RV (*sign_update)(sc_pkcs11_operation_t *,
|
||||||
|
CK_BYTE_PTR, CK_ULONG);
|
||||||
|
CK_RV (*sign_final)(sc_pkcs11_operation_t *,
|
||||||
|
CK_BYTE_PTR, CK_ULONG_PTR);
|
||||||
|
|
||||||
|
/* mechanism specific data */
|
||||||
|
void * mech_data;
|
||||||
|
};
|
||||||
|
typedef struct sc_pkcs11_mechanism_type sc_pkcs11_mechanism_type_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic operation
|
||||||
|
*/
|
||||||
struct sc_pkcs11_operation {
|
struct sc_pkcs11_operation {
|
||||||
int type;
|
sc_pkcs11_mechanism_type_t *type;
|
||||||
};
|
CK_MECHANISM mechanism;
|
||||||
|
struct sc_pkcs11_session *session;
|
||||||
#define SC_PKCS11_OPERATION_FIND 1
|
void * priv_data;
|
||||||
#define SC_PKCS11_OPERATION_SIGN 2
|
|
||||||
|
|
||||||
struct sc_pkcs11_sign_operation {
|
|
||||||
struct sc_pkcs11_operation operation;
|
|
||||||
struct sc_pkcs11_object *key;
|
|
||||||
CK_MECHANISM mechanism;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Find Operation */
|
||||||
#define SC_PKCS11_FIND_MAX_HANDLES 32
|
#define SC_PKCS11_FIND_MAX_HANDLES 32
|
||||||
|
|
||||||
struct sc_pkcs11_find_operation {
|
struct sc_pkcs11_find_operation {
|
||||||
struct sc_pkcs11_operation operation;
|
struct sc_pkcs11_operation operation;
|
||||||
int num_handles, current_handle;
|
int num_handles, current_handle;
|
||||||
|
@ -215,9 +255,10 @@ struct sc_pkcs11_session {
|
||||||
/* Notifications */
|
/* Notifications */
|
||||||
CK_NOTIFY notify_callback;
|
CK_NOTIFY notify_callback;
|
||||||
CK_VOID_PTR notify_data;
|
CK_VOID_PTR notify_data;
|
||||||
/* Active operation */
|
/* Active operations - one per type */
|
||||||
struct sc_pkcs11_operation *operation;
|
struct sc_pkcs11_operation *operation[SC_PKCS11_OPERATION_MAX];
|
||||||
};
|
};
|
||||||
|
typedef struct sc_pkcs11_session sc_pkcs11_session_t;
|
||||||
|
|
||||||
/* Module variables */
|
/* Module variables */
|
||||||
extern struct sc_context *context;
|
extern struct sc_context *context;
|
||||||
|
@ -250,9 +291,12 @@ CK_RV pool_find(struct sc_pkcs11_pool *, CK_ULONG, void **);
|
||||||
CK_RV pool_find_and_delete(struct sc_pkcs11_pool *, CK_ULONG, void **);
|
CK_RV pool_find_and_delete(struct sc_pkcs11_pool *, CK_ULONG, void **);
|
||||||
|
|
||||||
/* Session manipulation */
|
/* Session manipulation */
|
||||||
CK_RV session_start_operation(struct sc_pkcs11_session *, int, int, struct sc_pkcs11_operation **);
|
CK_RV session_start_operation(struct sc_pkcs11_session *,
|
||||||
CK_RV session_check_operation(struct sc_pkcs11_session *, int);
|
int, sc_pkcs11_mechanism_type_t *,
|
||||||
CK_RV session_stop_operation(struct sc_pkcs11_session *);
|
struct sc_pkcs11_operation **);
|
||||||
|
CK_RV session_get_operation(struct sc_pkcs11_session *, int,
|
||||||
|
struct sc_pkcs11_operation **);
|
||||||
|
CK_RV session_stop_operation(struct sc_pkcs11_session *, int);
|
||||||
|
|
||||||
/* Generic secret key stuff */
|
/* Generic secret key stuff */
|
||||||
CK_RV sc_pkcs11_create_secret_key(struct sc_pkcs11_session *,
|
CK_RV sc_pkcs11_create_secret_key(struct sc_pkcs11_session *,
|
||||||
|
@ -269,6 +313,35 @@ CK_RV attr_find_ptr(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void **, size_t *);
|
||||||
CK_RV attr_find_var(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void *, size_t *);
|
CK_RV attr_find_var(CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, void *, size_t *);
|
||||||
CK_RV attr_extract(CK_ATTRIBUTE_PTR, void *, size_t *);
|
CK_RV attr_extract(CK_ATTRIBUTE_PTR, void *, size_t *);
|
||||||
|
|
||||||
|
/* Generic Mechanism functions */
|
||||||
|
CK_RV sc_pkcs11_register_mechanism(struct sc_pkcs11_card *,
|
||||||
|
sc_pkcs11_mechanism_type_t *);
|
||||||
|
CK_RV sc_pkcs11_get_mechanism_list(struct sc_pkcs11_card *,
|
||||||
|
CK_MECHANISM_TYPE_PTR, CK_ULONG_PTR);
|
||||||
|
CK_RV sc_pkcs11_get_mechanism_info(struct sc_pkcs11_card *, CK_MECHANISM_TYPE,
|
||||||
|
CK_MECHANISM_INFO_PTR);
|
||||||
|
CK_RV sc_pkcs11_md_init(struct sc_pkcs11_session *, CK_MECHANISM_PTR);
|
||||||
|
CK_RV sc_pkcs11_md_update(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG);
|
||||||
|
CK_RV sc_pkcs11_md_final(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG_PTR);
|
||||||
|
CK_RV sc_pkcs11_sign_init(struct sc_pkcs11_session *, CK_MECHANISM_PTR,
|
||||||
|
struct sc_pkcs11_object *, CK_MECHANISM_TYPE);
|
||||||
|
CK_RV sc_pkcs11_sign_update(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG);
|
||||||
|
CK_RV sc_pkcs11_sign_final(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG_PTR);
|
||||||
|
CK_RV sc_pkcs11_sign_hash(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG,
|
||||||
|
CK_BYTE_PTR, CK_ULONG_PTR);
|
||||||
|
sc_pkcs11_mechanism_type_t *sc_pkcs11_find_mechanism(struct sc_pkcs11_card *,
|
||||||
|
CK_MECHANISM_TYPE, int);
|
||||||
|
sc_pkcs11_mechanism_type_t *sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE,
|
||||||
|
CK_MECHANISM_INFO_PTR, CK_KEY_TYPE,
|
||||||
|
void *);
|
||||||
|
sc_pkcs11_operation_t *sc_pkcs11_new_operation(sc_pkcs11_session_t *,
|
||||||
|
sc_pkcs11_mechanism_type_t *);
|
||||||
|
void sc_pkcs11_release_operation(sc_pkcs11_operation_t **);
|
||||||
|
CK_RV sc_pkcs11_register_generic_mechanisms(struct sc_pkcs11_card *);
|
||||||
|
#ifdef HAVE_OPENSSL
|
||||||
|
void sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue