pkcs11: ECHD and secret keys support from Douglas
This support were initially proposed by Douglas (https://github.com/dengert/OpenSC/commits/ecdh) and then merged into SM branch (https://github.com/viktorTarasov/OpenSC-SM/tree/secure-messaging).
This commit is contained in:
parent
76b8ad8ad6
commit
9c5dbea883
|
@ -413,6 +413,21 @@ struct sc_pkcs15_pubkey_info {
|
|||
};
|
||||
typedef struct sc_pkcs15_pubkey_info sc_pkcs15_pubkey_info_t;
|
||||
|
||||
struct sc_pkcs15_skey_info {
|
||||
struct sc_pkcs15_id id;
|
||||
unsigned int usage, access_flags;
|
||||
int native, key_reference;
|
||||
size_t value_len;
|
||||
unsigned long key_type;
|
||||
int algo_refs[SC_MAX_SUPPORTED_ALGORITHMS];
|
||||
struct sc_path path; /* if on card */
|
||||
struct sc_pkcs15_der data;
|
||||
};
|
||||
typedef struct sc_pkcs15_skey_info sc_pkcs15_skey_info_t;
|
||||
|
||||
#define sc_pkcs15_skey sc_pkcs15_data
|
||||
#define sc_pkcs15_skey_t sc_pkcs15_data_t
|
||||
|
||||
#define SC_PKCS15_TYPE_CLASS_MASK 0xF00
|
||||
|
||||
#define SC_PKCS15_TYPE_PRKEY 0x100
|
||||
|
@ -427,6 +442,12 @@ typedef struct sc_pkcs15_pubkey_info sc_pkcs15_pubkey_info_t;
|
|||
#define SC_PKCS15_TYPE_PUBKEY_GOSTR3410 0x203
|
||||
#define SC_PKCS15_TYPE_PUBKEY_EC 0x204
|
||||
|
||||
#define SC_PKCS15_TYPE_SKEY 0x300
|
||||
#define SC_PKCS15_TYPE_SKEY_GENERIC 0x301
|
||||
#define SC_PKCS15_TYPE_SKEY_DES 0x302
|
||||
#define SC_PKCS15_TYPE_SKEY_2DES 0x303
|
||||
#define SC_PKCS15_TYPE_SKEY_3DES 0x304
|
||||
|
||||
#define SC_PKCS15_TYPE_CERT 0x400
|
||||
#define SC_PKCS15_TYPE_CERT_X509 0x401
|
||||
#define SC_PKCS15_TYPE_CERT_SPKI 0x402
|
||||
|
|
|
@ -10,7 +10,7 @@ OBJECTS = pkcs11-global.obj pkcs11-session.obj pkcs11-object.obj misc.obj slot
|
|||
OBJECTS3 = pkcs11-spy.obj pkcs11-display.obj \
|
||||
$(TOPDIR)\win32\versioninfo.res
|
||||
|
||||
all: $(TOPDIR)\win32\versioninfo.res $(TARGET0) $(TARGET1) $(TARGET3)
|
||||
all: $(TOPDIR)\win32\versioninfo.res $(TARGET1) $(TARGET3)
|
||||
|
||||
!INCLUDE $(TOPDIR)\win32\Make.rules.mak
|
||||
|
||||
|
|
|
@ -115,10 +115,22 @@ struct pkcs15_data_object {
|
|||
#define data_p15obj base.p15_object
|
||||
#define is_data(obj) (__p15_type(obj) == SC_PKCS15_TYPE_DATA_OBJECT)
|
||||
|
||||
struct pkcs15_skey_object {
|
||||
struct pkcs15_any_object base;
|
||||
|
||||
struct sc_pkcs15_skey_info *info;
|
||||
struct sc_pkcs15_skey *valueXXXX;
|
||||
};
|
||||
|
||||
#define skey_flags base.base.flags
|
||||
#define skey_p15obj base.p15_object
|
||||
#define is_skey(obj) ((__p15_type(obj) & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_SKEY_OBJECT)
|
||||
|
||||
extern struct sc_pkcs11_object_ops pkcs15_cert_ops;
|
||||
extern struct sc_pkcs11_object_ops pkcs15_prkey_ops;
|
||||
extern struct sc_pkcs11_object_ops pkcs15_pubkey_ops;
|
||||
extern struct sc_pkcs11_object_ops pkcs15_dobj_ops;
|
||||
extern struct sc_pkcs11_object_ops pkcs15_skey_ops;
|
||||
|
||||
#define GOST_PARAMS_OID_SIZE 9
|
||||
static const struct {
|
||||
|
@ -150,9 +162,12 @@ static int lock_card(struct pkcs15_fw_data *);
|
|||
static int unlock_card(struct pkcs15_fw_data *);
|
||||
static int reselect_app_df(sc_pkcs15_card_t *p15card);
|
||||
|
||||
static CK_RV set_gost_params(struct sc_pkcs15init_keyarg_gost_params *,
|
||||
struct sc_pkcs15init_keyarg_gost_params *,
|
||||
CK_ATTRIBUTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG);
|
||||
static CK_RV set_gost_params(struct sc_pkcs15init_keyarg_gost_params *,
|
||||
struct sc_pkcs15init_keyarg_gost_params *,
|
||||
CK_ATTRIBUTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG);
|
||||
static CK_RV pkcs15_create_slot(struct sc_pkcs11_card *p11card, struct pkcs15_fw_data *fw_data,
|
||||
struct sc_pkcs15_object *auth, struct sc_app_info *app,
|
||||
struct sc_pkcs11_slot **out);
|
||||
|
||||
/* Returns forst available WF data or WF data corresponding to the given application */
|
||||
static struct pkcs15_fw_data *
|
||||
|
@ -621,7 +636,7 @@ __pkcs15_create_prkey_object(struct pkcs15_fw_data *fw_data,
|
|||
|
||||
static int
|
||||
__pkcs15_create_data_object(struct pkcs15_fw_data *fw_data,
|
||||
struct sc_pkcs15_object *object, struct pkcs15_any_object **data_object)
|
||||
struct sc_pkcs15_object *object, struct pkcs15_any_object **data_object)
|
||||
{
|
||||
struct pkcs15_data_object *dobj = NULL;
|
||||
int rv;
|
||||
|
@ -641,6 +656,26 @@ __pkcs15_create_data_object(struct pkcs15_fw_data *fw_data,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
__pkcs15_create_secret_key_object(struct pkcs15_fw_data *fw_data,
|
||||
struct sc_pkcs15_object *object, struct pkcs15_any_object **skey_object)
|
||||
{
|
||||
struct pkcs15_skey_object *skey = NULL;
|
||||
int rv;
|
||||
|
||||
rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &skey,
|
||||
object, &pkcs15_skey_ops,
|
||||
sizeof(struct pkcs15_skey_object));
|
||||
if (rv >= 0) {
|
||||
skey->info = (struct sc_pkcs15_skey_info *) object->data;
|
||||
}
|
||||
|
||||
if (skey_object != NULL)
|
||||
*skey_object = (struct pkcs15_any_object *) skey;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pkcs15_create_pkcs11_objects(struct pkcs15_fw_data *fw_data,
|
||||
int p15_type, const char *name,
|
||||
|
@ -1191,11 +1226,8 @@ pkcs15_create_tokens(struct sc_pkcs11_card *p11card, struct sc_app_info *app_inf
|
|||
{
|
||||
struct pkcs15_fw_data *fw_data = NULL, *ffda = NULL;
|
||||
struct sc_pkcs15_object *auth_user_pin = NULL, *auth_sign_pin = NULL, *fauo = NULL;
|
||||
// struct sc_pkcs15_object *auths[SC_PKCS15_MAX_PINS];
|
||||
struct sc_pkcs11_slot *slot = NULL;
|
||||
// int auth_count, found_auth_count = 0;
|
||||
int i, rv, idx;
|
||||
// unsigned int j;
|
||||
|
||||
sc_log(context, "create PKCS#15 tokens; fws:%p,%p,%p",
|
||||
p11card->fws_data[0], p11card->fws_data[1], p11card->fws_data[2]);
|
||||
|
@ -1564,18 +1596,19 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot,
|
|||
int login_user = slot->login_user;
|
||||
int rc;
|
||||
|
||||
if (!(pin_obj = slot_data_auth(slot->fw_data)))
|
||||
pin_obj = slot_data_auth(slot->fw_data);
|
||||
if (!pin_obj)
|
||||
return CKR_USER_PIN_NOT_INITIALIZED;
|
||||
|
||||
if (!(auth_info = slot_data_auth_info(slot->fw_data)))
|
||||
auth_info = slot_data_auth_info(slot->fw_data);
|
||||
if (!auth_info)
|
||||
return CKR_USER_PIN_NOT_INITIALIZED;
|
||||
|
||||
fw_data = (struct pkcs15_fw_data *) p11card->fws_data[slot->fw_data_idx];
|
||||
if (!fw_data)
|
||||
return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_SetPin");
|
||||
|
||||
sc_log(context, "Change '%s', reference %i; login type %i",
|
||||
pin_obj->label, auth_info->attrs.pin.reference, login_user);
|
||||
sc_log(context, "Change '%s' (ref:%i,type:%i)", pin_obj->label, auth_info->attrs.pin.reference, login_user);
|
||||
if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
|
||||
/* pPin should be NULL in case of a pin pad reader, but
|
||||
* some apps (e.g. older Netscapes) don't know about it.
|
||||
|
@ -1872,6 +1905,167 @@ out: return rv;
|
|||
}
|
||||
|
||||
|
||||
/* TODO Only Session secret key objects are supported for now
|
||||
* Sesison objects have CKA_TOKEN=false
|
||||
* This is used by the C_DeriveKey with ECDH to hold the
|
||||
* key, and the calling application can then retrieve tha attributes as needed.
|
||||
* TODO If a card can support secret key objects on the card, this
|
||||
* code will need to be expanded.
|
||||
*/
|
||||
static CK_RV
|
||||
pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile,
|
||||
CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
||||
CK_OBJECT_HANDLE_PTR phObject)
|
||||
{
|
||||
struct sc_pkcs11_card *p11card = slot->card;
|
||||
struct pkcs15_fw_data *fw_data = NULL;
|
||||
struct sc_pkcs15init_skeyargs args;
|
||||
struct pkcs15_any_object *key_any_obj = NULL;
|
||||
struct sc_pkcs15_object *key_obj = NULL;
|
||||
struct sc_pkcs15_skey_info *skey_info;
|
||||
CK_KEY_TYPE key_type;
|
||||
CK_BBOOL _token = FALSE;
|
||||
int rv;
|
||||
char label[SC_PKCS15_MAX_LABEL_SIZE];
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
fw_data = (struct pkcs15_fw_data *) p11card->fws_data[slot->fw_data_idx];
|
||||
if (!fw_data)
|
||||
return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_CreateObject");
|
||||
#if 0
|
||||
/* See if the "slot" is pin protected. If so, get the
|
||||
* PIN id */
|
||||
if ((pin = slot_data_auth_info(slot->fw_data)) != NULL)
|
||||
args.auth_id = pin->auth_id;
|
||||
#endif
|
||||
|
||||
/* Get the key type */
|
||||
rv = attr_find(pTemplate, ulCount, CKA_KEY_TYPE, &key_type, NULL);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
||||
/* CKA_TOKEN defaults to false */
|
||||
attr_find(pTemplate, ulCount, CKA_TOKEN, &_token, NULL);
|
||||
|
||||
switch (key_type) {
|
||||
/* Only support GENERIC_SECRET for now */
|
||||
case CKK_GENERIC_SECRET:
|
||||
break;
|
||||
default:
|
||||
return CKR_ATTRIBUTE_VALUE_INVALID;
|
||||
}
|
||||
|
||||
while (ulCount--) {
|
||||
CK_ATTRIBUTE_PTR attr = pTemplate++;
|
||||
|
||||
switch (attr->type) {
|
||||
/* Skip attrs we already know or don't care for */
|
||||
case CKA_CLASS:
|
||||
case CKA_KEY_TYPE:
|
||||
case CKA_MODULUS_BITS:
|
||||
case CKA_PRIVATE:
|
||||
break;
|
||||
case CKA_LABEL:
|
||||
args.label = set_cka_label(attr, label);
|
||||
break;
|
||||
case CKA_ID:
|
||||
args.id.len = sizeof(args.id.value);
|
||||
rv = attr_extract(attr, args.id.value, &args.id.len);
|
||||
if (rv != CKR_OK)
|
||||
goto out;
|
||||
break;
|
||||
case CKA_VALUE_LEN:
|
||||
attr_extract(attr, &args.value_len, NULL);
|
||||
break;
|
||||
case CKA_VALUE:
|
||||
if (attr->pValue) {
|
||||
args.data_value.value = calloc(1,attr->ulValueLen);
|
||||
if (!args.data_value.value)
|
||||
return CKR_HOST_MEMORY;
|
||||
memcpy(args.data_value.value, attr->pValue, attr->ulValueLen);
|
||||
args.data_value.len = attr->ulValueLen;
|
||||
}
|
||||
break;
|
||||
case CKA_DECRYPT:
|
||||
args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_DECRYPT);
|
||||
break;
|
||||
case CKA_ENCRYPT:
|
||||
args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_ENCRYPT);
|
||||
break;
|
||||
case CKA_WRAP:
|
||||
args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_WRAP);
|
||||
break;
|
||||
case CKA_UNWRAP:
|
||||
args.usage |= pkcs15_check_bool_cka(attr, SC_PKCS15_PRKEY_USAGE_UNWRAP);
|
||||
break;
|
||||
default:
|
||||
/* ignore unknown attrs, or flag error? */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* If creating a PKCS#11 session object, i.e. one that is only in memory */
|
||||
if (_token == FALSE) {
|
||||
|
||||
/* TODO Have 3 choices as to how to create the object.
|
||||
* (1)create a sc_pkcs15init_store_secret_key routine like the others
|
||||
* (2)use the sc_pkcs15emu_ routines
|
||||
* (3)do it inline here (Will do this for now)
|
||||
*/
|
||||
|
||||
key_obj = calloc(1, sizeof(sc_pkcs15_object_t));
|
||||
if (key_obj == NULL) {
|
||||
rv = CKR_HOST_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
key_obj->type = SC_PKCS15_TYPE_SKEY;
|
||||
|
||||
if (args.id.len)
|
||||
memcpy(key_obj->label, args.id.value, args.id.len);
|
||||
|
||||
key_obj->flags = 2; /* TODO not sure what these mean */
|
||||
|
||||
skey_info = calloc(1, sizeof(sc_pkcs15_skey_info_t));
|
||||
if (skey_info == NULL) {
|
||||
rv = CKR_HOST_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
key_obj->data = skey_info;
|
||||
skey_info->usage = args.usage;
|
||||
skey_info->native = 0; /* card can not use this */
|
||||
skey_info->access_flags = 0; /* looks like not needed */
|
||||
skey_info->key_type = key_type; /* PKCS#11 CKK_* */
|
||||
skey_info->data.value = args.data_value.value;
|
||||
skey_info->data.len = args.data_value.len;
|
||||
skey_info->value_len = args.value_len; /* callers prefered length */
|
||||
|
||||
}
|
||||
else {
|
||||
#if 1
|
||||
rv = CKR_FUNCTION_NOT_SUPPORTED;
|
||||
goto out;
|
||||
#else
|
||||
/* TODO add support for secret key on the card with something like this: */
|
||||
|
||||
rc = sc_pkcs15init_store_secret_key(fw_data->p15_card, profile, &args, &key_obj);
|
||||
if (rc < 0) {
|
||||
rv = sc_to_cryptoki_error(rc, "C_CreateObject");
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Create a new pkcs11 object for it */
|
||||
__pkcs15_create_secret_key_object(fw_data, key_obj, &key_any_obj);
|
||||
pkcs15_add_object(slot, key_any_obj, phObject);
|
||||
|
||||
rv = CKR_OK;
|
||||
|
||||
out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static CK_RV
|
||||
pkcs15_create_public_key(struct sc_pkcs11_slot *slot,
|
||||
struct sc_profile *profile,
|
||||
|
@ -2146,6 +2340,7 @@ pkcs15_create_object(struct sc_pkcs11_slot *slot, CK_ATTRIBUTE_PTR pTemplate, CK
|
|||
struct pkcs15_fw_data *fw_data = NULL;
|
||||
struct sc_profile *profile = NULL;
|
||||
CK_OBJECT_CLASS _class;
|
||||
CK_BBOOL _token = FALSE;
|
||||
int rv, rc;
|
||||
|
||||
fw_data = (struct pkcs15_fw_data *) p11card->fws_data[slot->fw_data_idx];
|
||||
|
@ -2156,17 +2351,50 @@ pkcs15_create_object(struct sc_pkcs11_slot *slot, CK_ATTRIBUTE_PTR pTemplate, CK
|
|||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
||||
rc = sc_lock(p11card->card);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, "C_CreateObject");
|
||||
|
||||
/* Bind the profile */
|
||||
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, slot->app_info, &profile);
|
||||
if (rc < 0) {
|
||||
sc_unlock(p11card->card);
|
||||
return sc_to_cryptoki_error(rc, "C_CreateObject");
|
||||
rv = attr_find(pTemplate, ulCount, CKA_TOKEN, &_token, NULL);
|
||||
if (rv == CKR_TEMPLATE_INCOMPLETE) {
|
||||
/* TODO OpenSC has not checked CKA_TOKEN == TRUE, so only
|
||||
* so only enforce for secret_key
|
||||
*/
|
||||
if (_class != CKO_SECRET_KEY)
|
||||
_token = TRUE; /* default if not in template */
|
||||
}
|
||||
else if (rv != CKR_OK) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* TODO The previous code does not check for CKA_TOKEN=TRUE
|
||||
* PKCS#11 CreatObject examples always have it, but
|
||||
* PKCS#11 says the default is false.
|
||||
* for backward compatability, will default to TRUE
|
||||
*/
|
||||
/* Dont need profile id creating session only objects */
|
||||
if (_token == TRUE) {
|
||||
struct sc_aid *aid = NULL;
|
||||
|
||||
rc = sc_lock(p11card->card);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, "C_CreateObject");
|
||||
|
||||
/* Bind the profile */
|
||||
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, slot->app_info, &profile);
|
||||
if (rc < 0) {
|
||||
sc_unlock(p11card->card);
|
||||
return sc_to_cryptoki_error(rc, "C_CreateObject");
|
||||
}
|
||||
|
||||
if (slot->app_info)
|
||||
aid = &slot->app_info->aid;
|
||||
|
||||
rc = sc_pkcs15init_finalize_profile(p11card->card, profile, aid);
|
||||
if (rc != CKR_OK) {
|
||||
sc_log(context, "Cannot finalize profile: %i", rc);
|
||||
sc_unlock(p11card->card);
|
||||
return sc_to_cryptoki_error(rc, "C_CreateObject");
|
||||
}
|
||||
|
||||
sc_pkcs15init_set_p15card(profile, fw_data->p15_card);
|
||||
}
|
||||
switch (_class) {
|
||||
case CKO_PRIVATE_KEY:
|
||||
rv = pkcs15_create_private_key(slot, profile, pTemplate, ulCount, phObject);
|
||||
|
@ -2180,12 +2408,17 @@ pkcs15_create_object(struct sc_pkcs11_slot *slot, CK_ATTRIBUTE_PTR pTemplate, CK
|
|||
case CKO_DATA:
|
||||
rv = pkcs15_create_data(slot, profile, pTemplate, ulCount, phObject);
|
||||
break;
|
||||
case CKO_SECRET_KEY:
|
||||
rv = pkcs15_create_secret_key(slot, profile, pTemplate, ulCount, phObject);
|
||||
break;
|
||||
default:
|
||||
rv = CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
sc_pkcs15init_unbind(profile);
|
||||
sc_unlock(p11card->card);
|
||||
if (_token == TRUE) {
|
||||
sc_pkcs15init_unbind(profile);
|
||||
sc_unlock(p11card->card);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -2211,7 +2444,7 @@ get_X509_usage_privk(CK_ATTRIBUTE_PTR pTempl, CK_ULONG ulCount, unsigned long *x
|
|||
if (typ == OPENSC_CKA_NON_REPUDIATION && *val)
|
||||
*x509_usage |= SC_PKCS15INIT_X509_NON_REPUDIATION;
|
||||
if (typ == CKA_VERIFY || typ == CKA_WRAP || typ == CKA_ENCRYPT) {
|
||||
sc_log(context, "get_X509_usage_privk(): invalid typ = 0x%0x\n", typ);
|
||||
sc_log(context, "get_X509_usage_privk(): invalid typ = 0x%0x", typ);
|
||||
return CKR_ATTRIBUTE_TYPE_INVALID;
|
||||
}
|
||||
}
|
||||
|
@ -2466,6 +2699,36 @@ kpgen_done:
|
|||
#endif
|
||||
|
||||
|
||||
static CK_RV
|
||||
pkcs15_skey_destroy(struct sc_pkcs11_session *session, void *object)
|
||||
{
|
||||
struct pkcs15_any_object *any_obj = (struct pkcs15_any_object*) object;
|
||||
struct sc_pkcs11_card *p11card = session->slot->card;
|
||||
struct pkcs15_fw_data *fw_data = NULL;
|
||||
int rv;
|
||||
|
||||
fw_data = (struct pkcs15_fw_data *) p11card->fws_data[session->slot->fw_data_idx];
|
||||
if (!fw_data)
|
||||
return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_GenerateKeyPair");
|
||||
/* TODO assuming this is a session only object. */
|
||||
rv = sc_lock(p11card->card);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, "C_DestroyObject");
|
||||
|
||||
/* Oppose to pkcs15_add_object */
|
||||
--any_obj->refcount; /* correct refcont */
|
||||
list_delete(&session->slot->objects, any_obj);
|
||||
/* Delete object in pkcs15 */
|
||||
rv = __pkcs15_delete_object(fw_data, any_obj);
|
||||
|
||||
sc_unlock(p11card->card);
|
||||
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, "C_DestroyObject");
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
pkcs15_any_destroy(struct sc_pkcs11_session *session, void *object)
|
||||
{
|
||||
|
@ -2862,23 +3125,36 @@ pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session,
|
|||
sc_log(context, "use friend public key data %p", key);
|
||||
}
|
||||
else {
|
||||
/* Try to find a certificate with the public key */
|
||||
/* Try to find public key or certificate with the public key */
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < fw_data->num_objects; i++) {
|
||||
struct pkcs15_any_object *obj = fw_data->objects[i];
|
||||
struct pkcs15_cert_object *cert;
|
||||
|
||||
if (!is_cert(obj))
|
||||
continue;
|
||||
if (is_cert(obj)) {
|
||||
cert = (struct pkcs15_cert_object*) obj;
|
||||
|
||||
cert = (struct pkcs15_cert_object*) obj;
|
||||
if (cert->cert_prvkey != prkey)
|
||||
continue;
|
||||
|
||||
if (cert->cert_prvkey != prkey)
|
||||
continue;
|
||||
if (check_cert_data_read(fw_data, cert) == 0) {
|
||||
key = cert->cert_pubkey->pub_data;
|
||||
sc_log(context, "found friend certificate's public key %p", key);
|
||||
}
|
||||
}
|
||||
else if (is_pubkey(obj)) {
|
||||
struct pkcs15_pubkey_object *pubkey = (struct pkcs15_pubkey_object *) obj;
|
||||
|
||||
if (check_cert_data_read(fw_data, cert) == 0)
|
||||
key = cert->cert_pubkey->pub_data;
|
||||
if (!pubkey->pub_data)
|
||||
continue;
|
||||
|
||||
if (sc_pkcs15_compare_id(&pubkey->pub_info->id, &prkey->prv_info->id)) {
|
||||
prkey->prv_pubkey = pubkey;
|
||||
key = pubkey->pub_data;
|
||||
sc_log(context, "found friend public key %p", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3180,18 +3456,142 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj,
|
|||
}
|
||||
|
||||
|
||||
static CK_RV
|
||||
pkcs15_prkey_derive(struct sc_pkcs11_session *session, void *obj,
|
||||
CK_MECHANISM_PTR pMechanism,
|
||||
CK_BYTE_PTR pParameters, CK_ULONG ulParametersLen,
|
||||
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
|
||||
{
|
||||
struct sc_pkcs11_card *p11card = session->slot->card;
|
||||
struct pkcs15_fw_data *fw_data = NULL;
|
||||
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj;
|
||||
int need_unlock = 0;
|
||||
int rv, flags = 0;
|
||||
CK_BYTE_PTR pSeedData = NULL;
|
||||
CK_ULONG ulSeedDataLen = 0;
|
||||
|
||||
sc_log(context, "Initiating derivation");
|
||||
|
||||
fw_data = (struct pkcs15_fw_data *) p11card->fws_data[session->slot->fw_data_idx];
|
||||
if (!fw_data)
|
||||
return sc_to_cryptoki_error(SC_ERROR_INTERNAL, "C_DeriveKey");
|
||||
|
||||
sc_log(context, "derivation %p %p %p %p %d %p %d", session, obj, pMechanism, pParameters, ulParametersLen, pData, *pulDataLen);
|
||||
|
||||
/* See which of the alternative keys supports derivation */
|
||||
while (prkey && !(prkey->prv_info->usage & SC_PKCS15_PRKEY_USAGE_DERIVE))
|
||||
prkey = prkey->prv_next;
|
||||
|
||||
if (prkey == NULL)
|
||||
return CKR_KEY_FUNCTION_NOT_PERMITTED;
|
||||
|
||||
if (pData != NULL && *pulDataLen > 0) { /* TODO DEE only test for NULL? */
|
||||
need_unlock = 1;
|
||||
rv = sc_lock(p11card->card);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, "C_DeriveKey");
|
||||
|
||||
if (!sc_pkcs11_conf.lock_login) {
|
||||
rv = reselect_app_df(fw_data->p15_card);
|
||||
if (rv < 0) {
|
||||
sc_unlock(p11card->card);
|
||||
return sc_to_cryptoki_error(rv, "C_DeriveKey");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO DEE This may not be the place to get the parameters,
|
||||
* But its the last PKCS11 aware routine.
|
||||
* RSA parameters would be null.
|
||||
*/
|
||||
switch (prkey->base.p15_object->type) {
|
||||
case SC_PKCS15_TYPE_PRKEY_EC:
|
||||
{
|
||||
CK_ECDH1_DERIVE_PARAMS * ecdh_params = (CK_ECDH1_DERIVE_PARAMS *) pParameters;
|
||||
ulSeedDataLen = ecdh_params->ulPublicDataLen;
|
||||
pSeedData = ecdh_params->pPublicData;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
rv = sc_pkcs15_derive(fw_data->p15_card, prkey->prv_p15obj,
|
||||
flags, pSeedData, ulSeedDataLen,
|
||||
pData, pulDataLen);
|
||||
/* this may have been a request for size */
|
||||
|
||||
if (need_unlock)
|
||||
sc_unlock(p11card->card);
|
||||
|
||||
sc_log(context, "Derivation complete. Result %d.", rv);
|
||||
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, "C_DeriveKey");
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
static CK_RV
|
||||
pkcs15_prkey_can_do(struct sc_pkcs11_session *session, void *obj,
|
||||
CK_MECHANISM_TYPE mech_type, unsigned int flags)
|
||||
{
|
||||
struct sc_pkcs11_card *p11card = session->slot->card;
|
||||
struct pkcs15_fw_data *fw_data = NULL;
|
||||
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj;
|
||||
struct sc_pkcs15_prkey_info *pkinfo = NULL;
|
||||
struct sc_supported_algo_info *token_algos = NULL;
|
||||
int ii, jj;
|
||||
|
||||
if (!prkey || !prkey->prv_info)
|
||||
return CKR_KEY_FUNCTION_NOT_PERMITTED;
|
||||
|
||||
pkinfo = prkey->prv_info;
|
||||
/* Return in there are no usage algorithms specified for this key. */
|
||||
if (!pkinfo->algo_refs[0])
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
|
||||
fw_data = (struct pkcs15_fw_data *) p11card->fws_data[session->slot->fw_data_idx];
|
||||
token_algos = &fw_data->p15_card->tokeninfo->supported_algos[0];
|
||||
|
||||
for (ii=0;ii<SC_MAX_SUPPORTED_ALGORITHMS && pkinfo->algo_refs[ii];ii++) {
|
||||
/* Look for algorithm supported by token referenced in the list of key's algorithms */
|
||||
for (jj=0;jj<SC_MAX_SUPPORTED_ALGORITHMS && (token_algos + jj)->reference; jj++)
|
||||
if (pkinfo->algo_refs[ii] == (token_algos + jj)->reference)
|
||||
break;
|
||||
if ((jj == SC_MAX_SUPPORTED_ALGORITHMS) || !(token_algos + jj)->reference)
|
||||
return CKR_GENERAL_ERROR;
|
||||
|
||||
if ((token_algos + jj)->mechanism != mech_type)
|
||||
continue;
|
||||
|
||||
if (flags == CKF_SIGN)
|
||||
if ((token_algos + jj)->operations & SC_PKCS15_ALGO_OP_COMPUTE_SIGNATURE)
|
||||
break;
|
||||
|
||||
if (flags == CKF_DECRYPT)
|
||||
if ((token_algos + jj)->operations & SC_PKCS15_ALGO_OP_DECIPHER)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ii == SC_MAX_SUPPORTED_ALGORITHMS || !pkinfo->algo_refs[ii])
|
||||
return CKR_MECHANISM_INVALID;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
struct sc_pkcs11_object_ops pkcs15_prkey_ops = {
|
||||
pkcs15_prkey_release,
|
||||
pkcs15_prkey_set_attribute,
|
||||
pkcs15_prkey_get_attribute,
|
||||
sc_pkcs11_any_cmp_attribute,
|
||||
pkcs15_any_destroy,
|
||||
NULL,
|
||||
NULL, /* get_size */
|
||||
pkcs15_prkey_sign,
|
||||
NULL, /* unwrap */
|
||||
pkcs15_prkey_decrypt,
|
||||
NULL, /* derive */
|
||||
NULL /* can_do */
|
||||
pkcs15_prkey_derive,
|
||||
pkcs15_prkey_can_do
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -3532,6 +3932,172 @@ struct sc_pkcs11_object_ops pkcs15_dobj_ops = {
|
|||
NULL /* can_do */
|
||||
};
|
||||
|
||||
|
||||
/* PKCS#15 Secret Key Objects */
|
||||
/* TODO Currently only session objects */
|
||||
static void
|
||||
pkcs15_skey_release(void *object)
|
||||
{
|
||||
__pkcs15_release_object((struct pkcs15_any_object *) object);
|
||||
}
|
||||
|
||||
|
||||
static CK_RV
|
||||
pkcs15_skey_set_attribute(struct sc_pkcs11_session *session,
|
||||
void *object, CK_ATTRIBUTE_PTR attr)
|
||||
{
|
||||
struct pkcs15_skey_object *skey = (struct pkcs15_skey_object*) object;
|
||||
|
||||
/* TODO DEE Assume a session based token, and only
|
||||
* change in memory, and only selected types
|
||||
* The pkcs15_set_attrib assumes the object is on the card....
|
||||
* When skey support on the card is added this needs to be changed */
|
||||
|
||||
switch (attr->type) {
|
||||
case CKA_VALUE:
|
||||
if (attr->pValue) {
|
||||
skey->info->data.value = calloc(1,attr->ulValueLen);
|
||||
if (!skey->info->data.value)
|
||||
return CKR_HOST_MEMORY;
|
||||
memcpy(skey->info->data.value, attr->pValue, attr->ulValueLen);
|
||||
skey->info->data.len = attr->ulValueLen;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return pkcs15_set_attrib(session, skey->base.p15_object, attr);
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int pkcs15_skey_get_value(struct sc_pkcs11_session *session,
|
||||
struct pkcs15_skey_object *skey,
|
||||
struct sc_pkcs15_skey **out_data)
|
||||
{
|
||||
int rv;
|
||||
struct sc_pkcs15_skey * skey_data = NULL;
|
||||
struct pkcs15_fw_data *fw_data =
|
||||
(struct pkcs15_fw_data *) session->slot->card->fw_data;
|
||||
sc_card_t *card = session->slot->card->card;
|
||||
|
||||
if (!out_data)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
/*TODO could try and read extractable secret keys
|
||||
* but for now we only work with session objects
|
||||
* derived from other keys
|
||||
*/
|
||||
skey_data= malloc(sizeof(struct sc_pkcs15_skey));
|
||||
if (skey_data == NULL)
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
memset(skey_data, 0, sizeof(struct sc_pkcs15_skey));
|
||||
|
||||
if (skey->value && skey->value->data_len) {
|
||||
skey_data->data = malloc(skey_data->data_len);
|
||||
if (skey_data->data == NULL) {
|
||||
free(skey_data);
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
skey_data->data_len = skey->value->data_len;
|
||||
memcpy(skey_data->data, skey->value->data, skey->value->data_len);
|
||||
return 0;
|
||||
}
|
||||
*out_data = skey_data;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static CK_RV
|
||||
pkcs15_skey_get_attribute(struct sc_pkcs11_session *session,
|
||||
void *object, CK_ATTRIBUTE_PTR attr)
|
||||
{
|
||||
struct pkcs15_skey_object *skey = (struct pkcs15_skey_object*) object;
|
||||
size_t len;
|
||||
|
||||
switch (attr->type) {
|
||||
case CKA_CLASS:
|
||||
check_attribute_buffer(attr, sizeof(CK_OBJECT_CLASS));
|
||||
*(CK_OBJECT_CLASS*)attr->pValue = CKO_SECRET_KEY;
|
||||
break;
|
||||
case CKA_TOKEN:
|
||||
/*TODO DEE change if on card skeys are supported */
|
||||
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
||||
*(CK_BBOOL*)attr->pValue = FALSE;
|
||||
break;
|
||||
case CKA_PRIVATE:
|
||||
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
||||
*(CK_BBOOL*)attr->pValue = (skey->base.p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE) != 0;
|
||||
break;
|
||||
case CKA_MODIFIABLE:
|
||||
check_attribute_buffer(attr, sizeof(CK_BBOOL));
|
||||
*(CK_BBOOL*)attr->pValue = (skey->base.p15_object->flags & 0x02) != 0;
|
||||
/*TODO Why no definition of the flag */
|
||||
break;
|
||||
case CKA_LABEL:
|
||||
len = strlen(skey->base.p15_object->label);
|
||||
check_attribute_buffer(attr, len);
|
||||
memcpy(attr->pValue, skey->base.p15_object->label, len);
|
||||
break;
|
||||
case CKA_KEY_TYPE:
|
||||
check_attribute_buffer(attr, sizeof(CK_KEY_TYPE));
|
||||
if (skey->info)
|
||||
*(CK_OBJECT_CLASS*)attr->pValue = skey->info->key_type;
|
||||
break;
|
||||
case CKA_ENCRYPT:
|
||||
case CKA_DECRYPT:
|
||||
case CKA_SIGN:
|
||||
case CKA_SIGN_RECOVER:
|
||||
case CKA_WRAP:
|
||||
case CKA_UNWRAP:
|
||||
case CKA_VERIFY:
|
||||
case CKA_VERIFY_RECOVER:
|
||||
case CKA_DERIVE:
|
||||
if (skey->info)
|
||||
return get_usage_bit(skey->info->usage, attr);
|
||||
else
|
||||
return get_usage_bit(SC_PKCS15_PRKEY_USAGE_ENCRYPT
|
||||
|SC_PKCS15_PRKEY_USAGE_DECRYPT
|
||||
|SC_PKCS15_PRKEY_USAGE_WRAP
|
||||
|SC_PKCS15_PRKEY_USAGE_UNWRAP, attr);
|
||||
break;
|
||||
case CKA_ID:
|
||||
check_attribute_buffer(attr, skey->info->id.len);
|
||||
memcpy(attr->pValue, skey->info->id.value, skey->info->id.len);
|
||||
break;
|
||||
case CKA_VALUE_LEN:
|
||||
check_attribute_buffer(attr, sizeof(CK_ULONG));
|
||||
*(CK_ULONG*)attr->pValue = skey->info->data.len;
|
||||
break;
|
||||
case CKA_VALUE:
|
||||
check_attribute_buffer(attr, skey->info->data.len);
|
||||
memcpy(attr->pValue, skey->info->data.value, skey->info->data.len);
|
||||
break;
|
||||
default:
|
||||
return CKR_ATTRIBUTE_TYPE_INVALID;
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Secret key objects, currently used only to retrieve derived session key
|
||||
*/
|
||||
struct sc_pkcs11_object_ops pkcs15_skey_ops = {
|
||||
pkcs15_skey_release,
|
||||
pkcs15_skey_set_attribute,
|
||||
pkcs15_skey_get_attribute,
|
||||
sc_pkcs11_any_cmp_attribute,
|
||||
pkcs15_skey_destroy,
|
||||
NULL, /* get_size */
|
||||
NULL, /* sign */
|
||||
NULL, /* unwrap_key */
|
||||
NULL, /* decrypt */
|
||||
NULL, /* derive */
|
||||
NULL /* can_do */
|
||||
};
|
||||
|
||||
/*
|
||||
* get_attribute helpers
|
||||
*/
|
||||
|
@ -3803,6 +4369,24 @@ static int register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags,
|
|||
if (rc != CKR_OK)
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
/* ADD ECDH mechanisms */
|
||||
/* The PIV uses curves where CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE produce the same results */
|
||||
mech_info.flags &= ~CKF_SIGN;
|
||||
mech_info.flags |= CKF_DERIVE;
|
||||
|
||||
mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_COFACTOR_DERIVE, &mech_info, CKK_EC, NULL);
|
||||
|
||||
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
||||
if (rc != CKR_OK)
|
||||
return rc;
|
||||
|
||||
mt = sc_pkcs11_new_fw_mechanism(CKM_ECDH1_DERIVE, &mech_info, CKK_EC, NULL);
|
||||
|
||||
rc = sc_pkcs11_register_mechanism(p11card, mt);
|
||||
if (rc != CKR_OK)
|
||||
return rc;
|
||||
|
||||
if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) {
|
||||
mech_info.flags = CKF_HW | CKF_GENERATE_KEY_PAIR;
|
||||
mech_info.flags |= ec_flags;
|
||||
|
@ -3814,22 +4398,9 @@ static int register_ec_mechanisms(struct sc_pkcs11_card *p11card, int flags,
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* TODO: -DEE Add CKM_ECDH1_COFACTOR_DERIVE as PIV can do this */
|
||||
/* TODO: -DEE But this requires C_DeriveKey to be implemented */
|
||||
|
||||
mech_info.flags &= ~CKF_SIGN;
|
||||
mech_info.flags |= CKF_DRIVE;
|
||||
|
||||
sc_pkcs11_new_fw_mechanism(CKM_ECDH1_COFACTOR_DERIVE,
|
||||
CKM_ECDH1_COFACTOR_DERIVE, NULL);
|
||||
#endif
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mechanism handling
|
||||
* FIXME: We should consult the card's algorithm list to
|
||||
|
@ -3981,7 +4552,9 @@ register_mechanisms(struct sc_pkcs11_card *p11card)
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
static int lock_card(struct pkcs15_fw_data *fw_data)
|
||||
|
||||
static int
|
||||
lock_card(struct pkcs15_fw_data *fw_data)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
@ -3993,7 +4566,9 @@ static int lock_card(struct pkcs15_fw_data *fw_data)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int unlock_card(struct pkcs15_fw_data *fw_data)
|
||||
|
||||
static int
|
||||
unlock_card(struct pkcs15_fw_data *fw_data)
|
||||
{
|
||||
while (fw_data->locked) {
|
||||
sc_unlock(fw_data->p15_card->card);
|
||||
|
@ -4003,13 +4578,13 @@ static int unlock_card(struct pkcs15_fw_data *fw_data)
|
|||
}
|
||||
|
||||
|
||||
static int reselect_app_df(sc_pkcs15_card_t *p15card)
|
||||
static int
|
||||
reselect_app_df(sc_pkcs15_card_t *p15card)
|
||||
{
|
||||
int r = SC_SUCCESS;
|
||||
|
||||
if (p15card->file_app != NULL) {
|
||||
/* if the application df (of the pkcs15 application) is
|
||||
* specified select it */
|
||||
/* if the application df (of the pkcs15 application) is specified select it */
|
||||
sc_path_t *tpath = &p15card->file_app->path;
|
||||
sc_log(p15card->card->ctx, "reselect application df");
|
||||
r = sc_select_file(p15card->card, tpath, NULL);
|
||||
|
|
|
@ -151,18 +151,18 @@ sc_pkcs11_md_init(struct sc_pkcs11_session *session,
|
|||
sc_pkcs11_mechanism_type_t *mt;
|
||||
int rv;
|
||||
|
||||
if (!session || !session->slot
|
||||
|| !(p11card = session->slot->card))
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
LOG_FUNC_CALLED(context);
|
||||
if (!session || !session->slot || !(p11card = session->slot->card))
|
||||
LOG_FUNC_RETURN(context, 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;
|
||||
LOG_FUNC_RETURN(context, CKR_MECHANISM_INVALID);
|
||||
|
||||
rv = session_start_operation(session, SC_PKCS11_OPERATION_DIGEST, mt, &operation);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
|
||||
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
|
||||
|
||||
|
@ -171,7 +171,7 @@ sc_pkcs11_md_init(struct sc_pkcs11_session *session,
|
|||
if (rv != CKR_OK)
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST);
|
||||
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
CK_RV
|
||||
|
@ -191,7 +191,7 @@ done:
|
|||
if (rv != CKR_OK)
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST);
|
||||
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
CK_RV
|
||||
|
@ -203,19 +203,18 @@ sc_pkcs11_md_final(struct sc_pkcs11_session *session,
|
|||
|
||||
rv = session_get_operation(session, SC_PKCS11_OPERATION_DIGEST, &op);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
|
||||
/* This is a request for the digest length */
|
||||
if (pData == NULL)
|
||||
*pulDataLen = 0;
|
||||
|
||||
rv = op->type->md_final(op, pData, pulDataLen);
|
||||
|
||||
if (rv == CKR_BUFFER_TOO_SMALL)
|
||||
return pData == NULL ? CKR_OK : rv;
|
||||
LOG_FUNC_RETURN(context, pData == NULL ? CKR_OK : CKR_BUFFER_TOO_SMALL);
|
||||
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_DIGEST);
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -223,40 +222,38 @@ sc_pkcs11_md_final(struct sc_pkcs11_session *session,
|
|||
* 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)
|
||||
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;
|
||||
LOG_FUNC_CALLED(context);
|
||||
if (!session || !session->slot || !(p11card = session->slot->card))
|
||||
LOG_FUNC_RETURN(context, CKR_ARGUMENTS_BAD);
|
||||
|
||||
/* See if we support this mechanism type */
|
||||
sc_log(context, "mechanism 0x%X, key-type 0x%X", pMechanism->mechanism, key_type);
|
||||
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_SIGN);
|
||||
if (mt == NULL)
|
||||
return CKR_MECHANISM_INVALID;
|
||||
LOG_FUNC_RETURN(context, CKR_MECHANISM_INVALID);
|
||||
|
||||
/* See if compatible with key type */
|
||||
if (mt->key_type != key_type)
|
||||
return CKR_KEY_TYPE_INCONSISTENT;
|
||||
LOG_FUNC_RETURN(context, CKR_KEY_TYPE_INCONSISTENT);
|
||||
|
||||
rv = session_start_operation(session, SC_PKCS11_OPERATION_SIGN, mt, &operation);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
|
||||
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
|
||||
rv = mt->sign_init(operation, key);
|
||||
|
||||
if (rv != CKR_OK)
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
|
||||
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
CK_RV
|
||||
|
@ -266,9 +263,10 @@ sc_pkcs11_sign_update(struct sc_pkcs11_session *session,
|
|||
sc_pkcs11_operation_t *op;
|
||||
int rv;
|
||||
|
||||
LOG_FUNC_CALLED(context);
|
||||
rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
|
||||
if (op->type->sign_update == NULL) {
|
||||
rv = CKR_KEY_TYPE_INCONSISTENT;
|
||||
|
@ -281,7 +279,7 @@ done:
|
|||
if (rv != CKR_OK)
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
|
||||
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
CK_RV
|
||||
|
@ -291,9 +289,10 @@ sc_pkcs11_sign_final(struct sc_pkcs11_session *session,
|
|||
sc_pkcs11_operation_t *op;
|
||||
int rv;
|
||||
|
||||
LOG_FUNC_CALLED(context);
|
||||
rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
|
||||
/* Bail out for signature mechanisms that don't do hashing */
|
||||
if (op->type->sign_final == NULL) {
|
||||
|
@ -307,7 +306,7 @@ done:
|
|||
if (rv != CKR_BUFFER_TOO_SMALL && pSignature != NULL)
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
|
||||
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
CK_RV
|
||||
|
@ -318,7 +317,7 @@ sc_pkcs11_sign_size(struct sc_pkcs11_session *session, CK_ULONG_PTR pLength)
|
|||
|
||||
rv = session_get_operation(session, SC_PKCS11_OPERATION_SIGN, &op);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
|
||||
/* Bail out for signature mechanisms that don't do hashing */
|
||||
if (op->type->sign_size == NULL) {
|
||||
|
@ -332,7 +331,7 @@ done:
|
|||
if (rv != CKR_OK)
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_SIGN);
|
||||
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -340,25 +339,44 @@ done:
|
|||
*/
|
||||
static CK_RV
|
||||
sc_pkcs11_signature_init(sc_pkcs11_operation_t *operation,
|
||||
struct sc_pkcs11_object *key)
|
||||
struct sc_pkcs11_object *key)
|
||||
{
|
||||
struct hash_signature_info *info;
|
||||
struct signature_data *data;
|
||||
int rv;
|
||||
CK_RV rv;
|
||||
int can_do_it = 0;
|
||||
|
||||
LOG_FUNC_CALLED(context);
|
||||
if (!(data = calloc(1, sizeof(*data))))
|
||||
return CKR_HOST_MEMORY;
|
||||
|
||||
LOG_FUNC_RETURN(context, CKR_HOST_MEMORY);
|
||||
data->info = NULL;
|
||||
data->key = key;
|
||||
|
||||
/* If this is a signature with hash operation, set up the
|
||||
* hash operation */
|
||||
if (key->ops->can_do) {
|
||||
rv = key->ops->can_do(operation->session, key, operation->type->mech, CKF_SIGN);
|
||||
if (rv == CKR_OK) {
|
||||
/* Mechanism recognised and can be performed by pkcs#15 card */
|
||||
can_do_it = 1;
|
||||
}
|
||||
else if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
|
||||
/* Mechanism not recognised by pkcs#15 card */
|
||||
can_do_it = 0;
|
||||
}
|
||||
else {
|
||||
/* Mechanism recognised but cannot be performed by pkcs#15 card, or some general error. */
|
||||
free(data);
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a signature with hash operation,
|
||||
* and card cannot perform itself signature with hash operation,
|
||||
* set up the hash operation */
|
||||
info = (struct hash_signature_info *) operation->type->mech_data;
|
||||
if (info != NULL) {
|
||||
if (info != NULL && !can_do_it) {
|
||||
/* Initialize hash operation */
|
||||
data->md = sc_pkcs11_new_operation(operation->session,
|
||||
info->hash_type);
|
||||
|
||||
data->md = sc_pkcs11_new_operation(operation->session, info->hash_type);
|
||||
if (data->md == NULL)
|
||||
rv = CKR_HOST_MEMORY;
|
||||
else
|
||||
|
@ -366,46 +384,48 @@ sc_pkcs11_signature_init(sc_pkcs11_operation_t *operation,
|
|||
if (rv != CKR_OK) {
|
||||
sc_pkcs11_release_operation(&data->md);
|
||||
free(data);
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
data->info = info;
|
||||
}
|
||||
|
||||
operation->priv_data = data;
|
||||
return CKR_OK;
|
||||
LOG_FUNC_RETURN(context, CKR_OK);
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
sc_pkcs11_signature_update(sc_pkcs11_operation_t *operation,
|
||||
CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
|
||||
CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
|
||||
{
|
||||
struct signature_data *data;
|
||||
|
||||
LOG_FUNC_CALLED(context);
|
||||
sc_log(context, "data part length %li", ulPartLen);
|
||||
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);
|
||||
CK_RV rv = data->md->type->md_update(data->md, pPart, ulPartLen);
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
/* This signature mechanism operates on the raw data */
|
||||
if (data->buffer_len + ulPartLen > sizeof(data->buffer))
|
||||
return CKR_DATA_LEN_RANGE;
|
||||
LOG_FUNC_RETURN(context, CKR_DATA_LEN_RANGE);
|
||||
memcpy(data->buffer + data->buffer_len, pPart, ulPartLen);
|
||||
data->buffer_len += ulPartLen;
|
||||
return CKR_OK;
|
||||
sc_log(context, "data length %li", data->buffer_len);
|
||||
LOG_FUNC_RETURN(context, CKR_OK);
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
sc_pkcs11_signature_final(sc_pkcs11_operation_t *operation,
|
||||
CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
|
||||
CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
|
||||
{
|
||||
struct signature_data *data;
|
||||
struct sc_pkcs11_object *key;
|
||||
int rv;
|
||||
CK_RV rv;
|
||||
|
||||
LOG_FUNC_CALLED(context);
|
||||
data = (struct signature_data *) operation->priv_data;
|
||||
|
||||
sc_log(context, "data length %li", data->buffer_len);
|
||||
if (data->md) {
|
||||
sc_pkcs11_operation_t *md = data->md;
|
||||
CK_ULONG len = sizeof(data->buffer);
|
||||
|
@ -414,15 +434,14 @@ sc_pkcs11_signature_final(sc_pkcs11_operation_t *operation,
|
|||
if (rv == CKR_BUFFER_TOO_SMALL)
|
||||
rv = CKR_FUNCTION_FAILED;
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
data->buffer_len = len;
|
||||
}
|
||||
|
||||
key = data->key;
|
||||
return key->ops->sign(operation->session,
|
||||
key, &operation->mechanism,
|
||||
data->buffer, data->buffer_len,
|
||||
pSignature, pulSignatureLen);
|
||||
sc_log(context, "%li bytes to sign", data->buffer_len);
|
||||
rv = data->key->ops->sign(operation->session, data->key, &operation->mechanism,
|
||||
data->buffer, data->buffer_len, pSignature, pulSignatureLen);
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
|
@ -465,7 +484,7 @@ sc_pkcs11_signature_size(sc_pkcs11_operation_t *operation, CK_ULONG_PTR pLength)
|
|||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -474,6 +493,8 @@ sc_pkcs11_signature_release(sc_pkcs11_operation_t *operation)
|
|||
struct signature_data *data;
|
||||
|
||||
data = (struct signature_data *) operation->priv_data;
|
||||
if (!data)
|
||||
return;
|
||||
sc_pkcs11_release_operation(&data->md);
|
||||
memset(data, 0, sizeof(*data));
|
||||
free(data);
|
||||
|
@ -485,10 +506,8 @@ sc_pkcs11_signature_release(sc_pkcs11_operation_t *operation)
|
|||
* the key object is capable of verifying _something_
|
||||
*/
|
||||
CK_RV
|
||||
sc_pkcs11_verif_init(struct sc_pkcs11_session *session,
|
||||
CK_MECHANISM_PTR pMechanism,
|
||||
struct sc_pkcs11_object *key,
|
||||
CK_MECHANISM_TYPE key_type)
|
||||
sc_pkcs11_verif_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;
|
||||
|
@ -741,6 +760,104 @@ sc_pkcs11_decr(struct sc_pkcs11_session *session,
|
|||
return rv;
|
||||
}
|
||||
|
||||
/* Derive one key from another, and return results in created object */
|
||||
CK_RV
|
||||
sc_pkcs11_deri(struct sc_pkcs11_session *session,
|
||||
CK_MECHANISM_PTR pMechanism,
|
||||
struct sc_pkcs11_object * basekey,
|
||||
CK_KEY_TYPE key_type,
|
||||
CK_SESSION_HANDLE hSession,
|
||||
CK_OBJECT_HANDLE hdkey,
|
||||
struct sc_pkcs11_object * dkey)
|
||||
{
|
||||
|
||||
struct sc_pkcs11_card *p11card;
|
||||
sc_pkcs11_operation_t *operation;
|
||||
sc_pkcs11_mechanism_type_t *mt;
|
||||
CK_BYTE_PTR keybuf = NULL;
|
||||
CK_ULONG ulDataLen = 0;
|
||||
CK_ATTRIBUTE template[] = {
|
||||
{CKA_VALUE, keybuf, 0}
|
||||
};
|
||||
|
||||
CK_RV 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_DERIVE);
|
||||
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_DERIVE, mt, &operation);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
||||
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
|
||||
|
||||
/* Get the size of the data to be returned
|
||||
* If the card could derive a key an leave it on the card
|
||||
* then no data is returned.
|
||||
* If the card returns the data, we will store it in the sercet key CKA_VALUE
|
||||
*/
|
||||
|
||||
ulDataLen = 0;
|
||||
rv = operation->type->derive(operation, basekey,
|
||||
pMechanism->pParameter, pMechanism->ulParameterLen,
|
||||
NULL, &ulDataLen);
|
||||
if (rv != CKR_OK)
|
||||
goto out;
|
||||
|
||||
if (ulDataLen > 0)
|
||||
keybuf = calloc(1,ulDataLen);
|
||||
else
|
||||
keybuf = calloc(1,8); /* pass in dummy buffer */
|
||||
|
||||
if (!keybuf) {
|
||||
rv = CKR_HOST_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Now do the actuall derivation */
|
||||
|
||||
rv = operation->type->derive(operation, basekey,
|
||||
pMechanism->pParameter, pMechanism->ulParameterLen,
|
||||
keybuf, &ulDataLen);
|
||||
if (rv != CKR_OK)
|
||||
goto out;
|
||||
|
||||
|
||||
/* add the CKA_VALUE attribute to the template if it was returned
|
||||
* if not assume it is on the card...
|
||||
* But for now PIV with ECDH returns the generic key data
|
||||
* TODO need to support truncation, if CKA_VALUE_LEN < ulDataLem
|
||||
*/
|
||||
if (ulDataLen > 0) {
|
||||
template[0].pValue = keybuf;
|
||||
template[0].ulValueLen = ulDataLen;
|
||||
|
||||
dkey->ops->set_attribute(session, dkey, &template[0]);
|
||||
|
||||
memset(keybuf,0,ulDataLen);
|
||||
}
|
||||
|
||||
out:
|
||||
session_stop_operation(session, SC_PKCS11_OPERATION_DERIVE);
|
||||
|
||||
if (keybuf)
|
||||
free(keybuf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize a signature operation
|
||||
*/
|
||||
|
@ -776,6 +893,19 @@ sc_pkcs11_decrypt(sc_pkcs11_operation_t *operation,
|
|||
pData, pulDataLen);
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
sc_pkcs11_derive(sc_pkcs11_operation_t *operation,
|
||||
struct sc_pkcs11_object *basekey,
|
||||
CK_BYTE_PTR pmechParam, CK_ULONG ulmechParamLen,
|
||||
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
|
||||
{
|
||||
|
||||
return basekey->ops->derive(operation->session,
|
||||
basekey,
|
||||
&operation->mechanism,
|
||||
pmechParam, ulmechParamLen,
|
||||
pData, pulDataLen);
|
||||
}
|
||||
/*
|
||||
* Create new mechanism type for a mechanism supported by
|
||||
* the card
|
||||
|
@ -814,7 +944,7 @@ sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE mech,
|
|||
/* TODO */
|
||||
}
|
||||
if (pInfo->flags & CKF_DERIVE) {
|
||||
/* TODO: -DEE CKM_ECDH1_COFACTOR_DERIVE for PIV */
|
||||
mt->derive = sc_pkcs11_derive;
|
||||
}
|
||||
if (pInfo->flags & CKF_DECRYPT) {
|
||||
mt->decrypt_init = sc_pkcs11_decrypt_init;
|
||||
|
|
|
@ -34,7 +34,9 @@ struct sc_to_cryptoki_error_conversion {
|
|||
};
|
||||
|
||||
static struct sc_to_cryptoki_error_conversion sc_to_cryptoki_error_map[] = {
|
||||
{ "C_GenerateKeyPair", SC_ERROR_INVALID_PIN_LENGTH, CKR_GENERAL_ERROR },
|
||||
{ "C_GenerateKeyPair", SC_ERROR_INVALID_PIN_LENGTH, CKR_GENERAL_ERROR },
|
||||
{ "C_Sign", SC_ERROR_NOT_ALLOWED, CKR_FUNCTION_FAILED},
|
||||
{ "C_Decrypt", SC_ERROR_NOT_ALLOWED, CKR_FUNCTION_FAILED},
|
||||
{NULL, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -199,11 +201,13 @@ CK_RV attr_extract(CK_ATTRIBUTE_PTR pAttr, void *ptr, size_t * sizep)
|
|||
size = sizeof(CK_KEY_TYPE);
|
||||
break;
|
||||
case CKA_PRIVATE:
|
||||
case CKA_TOKEN:
|
||||
size = sizeof(CK_BBOOL);
|
||||
break;
|
||||
case CKA_CERTIFICATE_TYPE:
|
||||
size = sizeof(CK_CERTIFICATE_TYPE);
|
||||
break;
|
||||
case CKA_VALUE_LEN:
|
||||
case CKA_MODULUS_BITS:
|
||||
size = sizeof(CK_ULONG);
|
||||
break;
|
||||
|
|
|
@ -50,25 +50,26 @@ static sc_pkcs11_mechanism_type_t find_mechanism = {
|
|||
NULL /* mech_data */
|
||||
};
|
||||
|
||||
static void sc_find_release(sc_pkcs11_operation_t *operation)
|
||||
static void
|
||||
sc_find_release(sc_pkcs11_operation_t *operation)
|
||||
{
|
||||
struct sc_pkcs11_find_operation *fop =
|
||||
(struct sc_pkcs11_find_operation *)operation;
|
||||
struct sc_pkcs11_find_operation *fop = (struct sc_pkcs11_find_operation *)operation;
|
||||
|
||||
sc_log(context,"freeing %d handles used %d at %p",
|
||||
fop->allocated_handles, fop->num_handles, fop->handles);
|
||||
sc_log(context,"freeing %d handles used %d at %p", fop->allocated_handles, fop->num_handles, fop->handles);
|
||||
if (fop->handles) {
|
||||
free(fop->handles);
|
||||
fop->handles = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static CK_RV get_object_from_session(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
|
||||
struct sc_pkcs11_session **session,
|
||||
struct sc_pkcs11_object **object)
|
||||
|
||||
static CK_RV
|
||||
get_object_from_session(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
|
||||
struct sc_pkcs11_session **session, struct sc_pkcs11_object **object)
|
||||
{
|
||||
CK_RV rv;
|
||||
struct sc_pkcs11_session *sess;
|
||||
CK_RV rv;
|
||||
|
||||
rv = get_session(hSession, &sess);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
@ -80,23 +81,29 @@ static CK_RV get_object_from_session(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDL
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
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. */
|
||||
CK_RV rv;
|
||||
/* C_CreateObject can be called from C_DeriveKey
|
||||
* which is holding the sc_pkcs11_lock
|
||||
* So dont get the lock again. */
|
||||
static
|
||||
CK_RV sc_create_object_int(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. */
|
||||
int use_lock)
|
||||
{
|
||||
CK_RV rv = CKR_OK;
|
||||
struct sc_pkcs11_session *session;
|
||||
struct sc_pkcs11_card *card;
|
||||
|
||||
LOG_FUNC_CALLED(context);
|
||||
if (pTemplate == NULL_PTR || ulCount == 0)
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
||||
rv = sc_pkcs11_lock();
|
||||
if (rv != CKR_OK)
|
||||
if (use_lock) {
|
||||
rv = sc_pkcs11_lock();
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
LOG_FUNC_CALLED(context);
|
||||
|
||||
}
|
||||
|
||||
dump_template(SC_LOG_DEBUG_NORMAL, "C_CreateObject()", pTemplate, ulCount);
|
||||
|
||||
|
@ -106,48 +113,68 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
goto out;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* TODO DEE what should we check here */
|
||||
if (!(session->flags & CKF_RW_SESSION)) {
|
||||
rv = CKR_SESSION_READ_ONLY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#endif
|
||||
card = session->slot->card;
|
||||
if (card->framework->create_object == NULL)
|
||||
rv = CKR_FUNCTION_NOT_SUPPORTED;
|
||||
else
|
||||
rv = card->framework->create_object(session->slot, pTemplate, ulCount, phObject);
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:
|
||||
if (use_lock)
|
||||
sc_pkcs11_unlock();
|
||||
LOG_FUNC_RETURN(context, rv);
|
||||
}
|
||||
|
||||
CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
|
||||
CK_ULONG ulCount, /* attributes in template */
|
||||
CK_OBJECT_HANDLE_PTR phNewObject)/* receives handle of copy */
|
||||
|
||||
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)
|
||||
{
|
||||
return sc_create_object_int(hSession, pTemplate, ulCount, phObject, 1);
|
||||
}
|
||||
|
||||
|
||||
CK_RV
|
||||
C_CopyObject(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
|
||||
CK_ULONG ulCount, /* attributes in template */
|
||||
CK_OBJECT_HANDLE_PTR phNewObject) /* receives handle of copy */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject)
|
||||
{ /* the object's handle */
|
||||
|
||||
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;
|
||||
|
||||
if (!(session->flags & CKF_RW_SESSION)) {
|
||||
object->ops->get_attribute(session, object, &token_attribure);
|
||||
if (is_token == TRUE && !(session->flags & CKF_RW_SESSION)) {
|
||||
rv = CKR_SESSION_READ_ONLY;
|
||||
goto out;
|
||||
}
|
||||
|
@ -157,22 +184,27 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
else
|
||||
rv = object->ops->destroy_object(session, object);
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
|
||||
CK_RV
|
||||
C_GetObjectSize(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ULONG_PTR pulSize)
|
||||
{ /* receives size of object */
|
||||
CK_ULONG_PTR pulSize) /* receives size of object */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
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,
|
||||
|
@ -235,11 +267,13 @@ out: sc_log(context, "C_GetAttributeValue(hSession=0x%lx, hObject=0x%lx) = %s",
|
|||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* specifies attributes and values */
|
||||
CK_ULONG ulCount)
|
||||
{ /* attributes in template */
|
||||
|
||||
CK_RV
|
||||
C_SetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hObject, /* the object's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* specifies attributes and values */
|
||||
CK_ULONG ulCount) /* attributes in template */
|
||||
{
|
||||
CK_RV rv;
|
||||
unsigned int i;
|
||||
struct sc_pkcs11_session *session;
|
||||
|
@ -273,14 +307,17 @@ CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
}
|
||||
}
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
|
||||
CK_ULONG ulCount)
|
||||
{ /* attributes in search template */
|
||||
|
||||
CK_RV
|
||||
C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
|
||||
CK_ULONG ulCount) /* attributes in search template */
|
||||
{
|
||||
CK_RV rv;
|
||||
CK_BBOOL is_private = TRUE;
|
||||
CK_ATTRIBUTE private_attribute = { CKA_PRIVATE, &is_private, sizeof(is_private) };
|
||||
|
@ -374,15 +411,18 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
|
||||
sc_log(context, "%d matching objects\n", operation->num_handles);
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE_PTR phObject, /* receives object handle array */
|
||||
CK_ULONG ulMaxObjectCount, /* max handles to be returned */
|
||||
CK_ULONG_PTR pulObjectCount)
|
||||
{ /* actual number returned */
|
||||
|
||||
CK_RV
|
||||
C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE_PTR phObject, /* receives object handle array */
|
||||
CK_ULONG ulMaxObjectCount, /* max handles to be returned */
|
||||
CK_ULONG_PTR pulObjectCount) /* actual number returned */
|
||||
{
|
||||
CK_RV rv;
|
||||
CK_ULONG to_return;
|
||||
struct sc_pkcs11_session *session;
|
||||
|
@ -399,8 +439,7 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
if (rv != CKR_OK)
|
||||
goto out;
|
||||
|
||||
rv = session_get_operation(session, SC_PKCS11_OPERATION_FIND,
|
||||
(sc_pkcs11_operation_t **) & operation);
|
||||
rv = session_get_operation(session, SC_PKCS11_OPERATION_FIND, (sc_pkcs11_operation_t **) & operation);
|
||||
if (rv != CKR_OK)
|
||||
goto out;
|
||||
|
||||
|
@ -410,9 +449,7 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
|
||||
*pulObjectCount = to_return;
|
||||
|
||||
memcpy(phObject,
|
||||
&operation->handles[operation->current_handle],
|
||||
to_return * sizeof(CK_OBJECT_HANDLE));
|
||||
memcpy(phObject, &operation->handles[operation->current_handle], to_return * sizeof(CK_OBJECT_HANDLE));
|
||||
|
||||
operation->current_handle += to_return;
|
||||
|
||||
|
@ -420,8 +457,10 @@ out: sc_pkcs11_unlock();
|
|||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
|
||||
{ /* the session's handle */
|
||||
|
||||
CK_RV
|
||||
C_FindObjectsFinal(CK_SESSION_HANDLE hSession) /* the session's handle */
|
||||
{
|
||||
CK_RV rv;
|
||||
struct sc_pkcs11_session *session;
|
||||
|
||||
|
@ -445,10 +484,10 @@ out: sc_pkcs11_unlock();
|
|||
* 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
|
||||
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;
|
||||
|
||||
|
@ -469,12 +508,14 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
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 */
|
||||
|
||||
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;
|
||||
|
||||
|
@ -496,10 +537,12 @@ out: sc_log(context, "C_Digest() = %s", lookup_enum ( RV_T, rv ));
|
|||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pPart, /* data to be digested */
|
||||
CK_ULONG ulPartLen)
|
||||
{ /* bytes of data to be digested */
|
||||
|
||||
CK_RV
|
||||
C_DigestUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pPart, /* data to be digested */
|
||||
CK_ULONG ulPartLen) /* bytes of data to be digested */
|
||||
{
|
||||
CK_RV rv;
|
||||
struct sc_pkcs11_session *session;
|
||||
|
||||
|
@ -516,16 +559,20 @@ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hKey)
|
||||
{ /* handle of secret key to digest */
|
||||
|
||||
CK_RV
|
||||
C_DigestKey(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_OBJECT_HANDLE hKey) /* handle of secret key to digest */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
|
@ -542,17 +589,19 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
return rv;
|
||||
}
|
||||
|
||||
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_RV rv;
|
||||
|
||||
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;
|
||||
|
@ -586,17 +635,20 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
|
||||
rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type);
|
||||
|
||||
out: sc_log(context, "C_SignInit() = %s", lookup_enum ( RV_T, rv ));
|
||||
out:
|
||||
sc_log(context, "C_SignInit() = %s", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
|
@ -627,15 +679,18 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
if (rv == CKR_OK)
|
||||
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
|
||||
|
||||
out: sc_log(context, "C_Sign() = %s", lookup_enum ( RV_T, rv ));
|
||||
out:
|
||||
sc_log(context, "C_Sign() = %s", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pPart, /* the data (digest) to be signed */
|
||||
CK_ULONG ulPartLen)
|
||||
{ /* count of bytes to be signed */
|
||||
|
||||
CK_RV
|
||||
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;
|
||||
|
||||
|
@ -652,10 +707,12 @@ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
return rv;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
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;
|
||||
|
@ -683,15 +740,18 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
|
||||
}
|
||||
|
||||
out: sc_log(context, "C_SignFinal() = %s", lookup_enum ( RV_T, rv ));
|
||||
out:
|
||||
sc_log(context, "C_SignFinal() = %s", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
|
||||
CK_OBJECT_HANDLE hKey)
|
||||
{ /* handle of the signature key */
|
||||
|
||||
CK_RV
|
||||
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;
|
||||
|
@ -739,27 +799,33 @@ CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
|
||||
rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type);
|
||||
|
||||
out: sc_log(context, "C_SignRecoverInit() = %sn", lookup_enum ( RV_T, rv ));
|
||||
out:
|
||||
sc_log(context, "C_SignRecoverInit() = %sn", lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_SignRecover(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
|
||||
C_SignRecover(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 */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
|
||||
CK_OBJECT_HANDLE hKey)
|
||||
{ /* handle of encryption key */
|
||||
|
||||
CK_RV
|
||||
C_EncryptInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
|
||||
CK_OBJECT_HANDLE hKey) /* handle of encryption key */
|
||||
{
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pData, /* the plaintext data */
|
||||
CK_ULONG ulDataLen, /* bytes of plaintext data */
|
||||
|
@ -789,13 +855,14 @@ 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_RV rv;
|
||||
CK_BBOOL can_decrypt;
|
||||
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 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;
|
||||
|
@ -818,8 +885,12 @@ CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
|
||||
rv = object->ops->get_attribute(session, object, &decrypt_attribute);
|
||||
if (rv != CKR_OK || !can_decrypt) {
|
||||
rv = CKR_KEY_TYPE_INCONSISTENT;
|
||||
goto out;
|
||||
/* 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) {
|
||||
|
@ -953,21 +1024,20 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
}
|
||||
|
||||
slot = session->slot;
|
||||
if (slot->card->framework->gen_keypair == NULL) {
|
||||
if (slot->card->framework->gen_keypair == NULL)
|
||||
rv = CKR_FUNCTION_NOT_SUPPORTED;
|
||||
} else {
|
||||
rv = slot->card->framework->gen_keypair(slot,
|
||||
pMechanism, pPublicKeyTemplate,
|
||||
ulPublicKeyAttributeCount,
|
||||
pPrivateKeyTemplate,
|
||||
ulPrivateKeyAttributeCount, phPublicKey,
|
||||
phPrivateKey);
|
||||
}
|
||||
else
|
||||
rv = slot->card->framework->gen_keypair(slot, pMechanism,
|
||||
pPublicKeyTemplate, ulPublicKeyAttributeCount,
|
||||
pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
|
||||
phPublicKey, phPrivateKey);
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
CK_RV C_WrapKey(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
|
||||
CK_OBJECT_HANDLE hWrappingKey, /* handle of the wrapping key */
|
||||
|
@ -995,10 +1065,78 @@ CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
CK_OBJECT_HANDLE hBaseKey, /* handle of the base key */
|
||||
CK_ATTRIBUTE_PTR pTemplate, /* template for the new key */
|
||||
CK_ULONG ulAttributeCount, /* # of attributes in template */
|
||||
CK_OBJECT_HANDLE_PTR phKey)
|
||||
{ /* gets handle of derived key */
|
||||
CK_OBJECT_HANDLE_PTR phKey) /* gets handle of derived key */
|
||||
{
|
||||
/* TODO: -DEE ECDH with Cofactor on PIV is an example */
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
/* TODO: need to do a lot of checking, will only support ECDH for now.*/
|
||||
CK_RV rv;
|
||||
CK_BBOOL can_derive;
|
||||
CK_KEY_TYPE key_type;
|
||||
CK_ATTRIBUTE derive_attribute = { CKA_DERIVE, &can_derive, sizeof(can_derive) };
|
||||
CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) };
|
||||
struct sc_pkcs11_session *session;
|
||||
struct sc_pkcs11_object *object;
|
||||
struct sc_pkcs11_object *key_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, hBaseKey, &session, &object);
|
||||
if (rv != CKR_OK) {
|
||||
if (rv == CKR_OBJECT_HANDLE_INVALID)
|
||||
rv = CKR_KEY_HANDLE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (object->ops->derive == NULL_PTR) {
|
||||
rv = CKR_KEY_TYPE_INCONSISTENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = object->ops->get_attribute(session, object, &derive_attribute);
|
||||
if (rv != CKR_OK || !can_derive) {
|
||||
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;
|
||||
}
|
||||
/* TODO DEE Should also check SENSITIVE, ALWAYS_SENSITIVE, EXTRACTABLE,
|
||||
NEVER_EXTRACTABLE of the BaseKey against the template for the newkey.
|
||||
*/
|
||||
|
||||
switch(key_type) {
|
||||
case CKK_EC:
|
||||
|
||||
rv = sc_create_object_int(hSession, pTemplate, ulAttributeCount, phKey, 0);
|
||||
if (rv != CKR_OK)
|
||||
goto out;
|
||||
|
||||
rv = get_object_from_session(hSession, *phKey, &session, &key_object);
|
||||
if (rv != CKR_OK) {
|
||||
if (rv == CKR_OBJECT_HANDLE_INVALID)
|
||||
rv = CKR_KEY_HANDLE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = sc_pkcs11_deri(session, pMechanism, object, key_type,
|
||||
hSession, *phKey, key_object);
|
||||
/* TODO if (rv != CK_OK) need to destroy the object */
|
||||
|
||||
break;
|
||||
default:
|
||||
rv = CKR_KEY_TYPE_INCONSISTENT;
|
||||
}
|
||||
|
||||
out:
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
|
|
|
@ -721,6 +721,17 @@ struct ck_mechanism_info
|
|||
/* Flags for C_WaitForSlotEvent. */
|
||||
#define CKF_DONT_BLOCK (1UL)
|
||||
|
||||
/* Flags for Key derivation */
|
||||
#define CKD_NULL (1UL << 0)
|
||||
|
||||
typedef struct CK_ECDH1_DERIVE_PARAMS {
|
||||
unsigned long kdf;
|
||||
unsigned long ulSharedDataLen;
|
||||
unsigned char * pSharedData;
|
||||
unsigned long ulPublicDataLen;
|
||||
unsigned char * pPublicData;
|
||||
} CK_ECDH1_DERIVE_PARAMS;
|
||||
|
||||
|
||||
typedef unsigned long ck_rv_t;
|
||||
|
||||
|
|
|
@ -248,6 +248,18 @@ struct sc_pkcs15init_dataargs {
|
|||
struct sc_pkcs15_der der_encoded; /* Wrong name: is not DER encoded */
|
||||
};
|
||||
|
||||
struct sc_pkcs15init_skeyargs {
|
||||
struct sc_pkcs15_id id;
|
||||
struct sc_pkcs15_id auth_id;
|
||||
const char * label;
|
||||
unsigned long usage;
|
||||
unsigned int flags;
|
||||
unsigned int access_flags;
|
||||
unsigned long value_len; /* User requested length */
|
||||
|
||||
struct sc_pkcs15_der data_value; /* Wrong name: is not DER encoded */
|
||||
};
|
||||
|
||||
struct sc_pkcs15init_certargs {
|
||||
struct sc_pkcs15_id id;
|
||||
const char * label;
|
||||
|
|
Loading…
Reference in New Issue