Added implementation of C_UnwrapKey all the way from PKCS#11 interface to the card driver level.

Not yet complete, but can be run with CKA_TOKEN=FALSE set in the target object. Currently unwrapping emulated
with a decrypt operation in card-myeid.c. To be improved.
This commit is contained in:
Hannu Honkanen 2017-09-22 15:03:31 +03:00
parent e2b1fb81e0
commit 5f51d5d315
14 changed files with 405 additions and 28 deletions

View File

@ -227,6 +227,9 @@ static int myeid_init(struct sc_card *card)
/* State that we have an RNG */
card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO;
/* if (card->version.fw_major >= 41) */ /* TODO: check the version number that actually supports these ops */
card->caps |= SC_CARD_CAP_WRAP_KEY | SC_CARD_CAP_UNWRAP_KEY;
card->max_recv_size = 255;
card->max_send_size = 255;
@ -632,6 +635,10 @@ static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t *
apdu.p1 = 0x41;
apdu.p2 = 0xB6;
break;
case SC_SEC_OPERATION_UNWRAP:
apdu.p1 = 0x41; /* emulating unwrapping with DECIPHER operation */
apdu.p2 = 0xB8; /* TODO: set correct params when operation is implemented on card */
break;
default:
return SC_ERROR_INVALID_ARGUMENTS;
}
@ -1185,6 +1192,31 @@ static int myeid_decipher(struct sc_card *card, const u8 * crgram,
}
static int myeid_wrap_key(struct sc_card *card, u8 *out, size_t outlen)
{
int r;
LOG_FUNC_CALLED(card->ctx);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
static int myeid_unwrap_key(struct sc_card *card, const u8 *crgram, size_t crgram_len)
{
int r;
u8 out[512];
size_t outlen = 512;
LOG_FUNC_CALLED(card->ctx);
/* Emulate unwrapping with decipher */
r = myeid_decipher(card, crgram, crgram_len, out, outlen);
LOG_FUNC_RETURN(card->ctx, r);
/*LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); */
}
/* Write internal data, e.g. add default pin-records to pin */
static int myeid_putdata(struct sc_card *card, struct sc_cardctl_myeid_data_obj* data_obj)
{
@ -1601,6 +1633,8 @@ static struct sc_card_driver * sc_get_driver(void)
myeid_ops.process_fci = myeid_process_fci;
myeid_ops.card_ctl = myeid_card_ctl;
myeid_ops.pin_cmd = myeid_pin_cmd;
myeid_ops.wrap = myeid_wrap_key;
myeid_ops.unwrap = myeid_unwrap_key;
return &myeid_drv;
}

View File

@ -1273,7 +1273,9 @@ static struct sc_card_operations iso_ops = {
NULL, /* put_data */
NULL, /* delete_record */
NULL, /* read_public_key */
NULL /* card_reader_lock_obtained */
NULL, /* card_reader_lock_obtained */
NULL, /* wrap */
NULL /* unwrap */
};
static struct sc_card_driver iso_driver = {

View File

@ -175,7 +175,7 @@ sc_pkcs15_encode_pubkey_dsa
sc_pkcs15_encode_pubkey_rsa
sc_pkcs15_encode_pubkey_ec
sc_pkcs15_encode_pubkey_gostr3410
sc_pkcs15_encode_pubkey_as_spki
sc_pkcs15_encode_pubkey_as_spki
sc_pkcs15_encode_pukdf_entry
sc_pkcs15_encode_tokeninfo
sc_pkcs15_encode_unusedspace
@ -237,6 +237,7 @@ sc_pkcs15_remove_unusedspace
sc_pkcs15_search_objects
sc_pkcs15_unbind
sc_pkcs15_unblock_pin
sc_pkcs15_unwrap
sc_pkcs15_verify_pin
sc_pkcs15_get_pin_info
sc_pkcs15_verify_pin_with_session_pin

View File

@ -57,6 +57,8 @@ extern "C" {
#define SC_SEC_OPERATION_SIGN 0x0002
#define SC_SEC_OPERATION_AUTHENTICATE 0x0003
#define SC_SEC_OPERATION_DERIVE 0x0004
#define SC_SEC_OPERATION_WRAP 0x0005
#define SC_SEC_OPERATION_UNWRAP 0x0006
/* sc_security_env flags */
#define SC_SEC_ENV_ALG_REF_PRESENT 0x0001
@ -525,6 +527,17 @@ struct sc_reader_operations {
/* Card (or card driver) supports generating a session PIN */
#define SC_CARD_CAP_SESSION_PIN 0x00000200
/* Card and driver supports handling on card session objects.
* If a driver has this capability, the driver handles storage and operations
* with objects that CKA_TOKEN set to FALSE. If a driver doesn't support this,
* OpenSC handles them as in memory objects.*/
#define SC_CARD_CAP_ONCARD_SESSION_OBJECTS 0x00000400
/* Card (or card driver) supports key wrapping operations */
#define SC_CARD_CAP_WRAP_KEY 0x00000800
/* Card (or card driver) supports key unwrapping operations */
#define SC_CARD_CAP_UNWRAP_KEY 0x00001000
typedef struct sc_card {
struct sc_context *ctx;
struct sc_reader *reader;
@ -689,6 +702,10 @@ struct sc_card_operations {
unsigned char **, size_t *);
int (*card_reader_lock_obtained)(struct sc_card *, int was_reset);
int (*wrap)(struct sc_card *card, u8 *out, size_t outlen);
int (*unwrap)(struct sc_card *card, const u8 *crgram, size_t crgram_len);
};
typedef struct sc_card_driver {
@ -1192,6 +1209,8 @@ int sc_decipher(struct sc_card *card, const u8 * crgram, size_t crgram_len,
u8 * out, size_t outlen);
int sc_compute_signature(struct sc_card *card, const u8 * data,
size_t data_len, u8 * out, size_t outlen);
int sc_unwrap(struct sc_card *card, const u8 * data,
size_t data_len, u8 * out, size_t outlen);
int sc_verify(struct sc_card *card, unsigned int type, int ref, const u8 *buf,
size_t buflen, int *tries_left);
/**

View File

@ -297,6 +297,53 @@ int sc_pkcs15_derive(struct sc_pkcs15_card *p15card,
LOG_FUNC_RETURN(ctx, r);
}
/*
* Unwrap a key into a key object on card.
* in holds the wrapped key data
* the target file that target_key points to must be created before calling this function
* Use pkcs15init to peform the complete unwrapping operation and create the pkcs#15 object for the new key.
*/
int sc_pkcs15_unwrap(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_object *key,
struct sc_pkcs15_object *target_key,
unsigned long flags,
const u8 * in, size_t inlen)
{
sc_context_t *ctx = p15card->card->ctx;
int r;
sc_algorithm_info_t *alg_info = NULL;
sc_security_env_t senv;
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) key->data;
unsigned long pad_flags = 0, sec_flags = 0;
u8 *out = 0;
size_t poutlen = 0;
LOG_FUNC_CALLED(ctx);
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_UNWRAP)))
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for unwrapping");
if (!(key->type == SC_PKCS15_TYPE_PRKEY_RSA ||
(key->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_SKEY)) {
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,"Key type not supported");
}
r = format_senv(p15card, key, &senv, &alg_info);
LOG_TEST_RET(ctx, r, "Could not initialize security environment");
senv.operation = SC_SEC_OPERATION_UNWRAP;
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
LOG_TEST_RET(ctx, r, "cannot encode security operation flags");
senv.algorithm_flags = sec_flags;
r = use_key(p15card, key, &senv, sc_unwrap, in, inlen, out,
poutlen);
LOG_TEST_RET(ctx, r, "use_key() failed");
LOG_FUNC_RETURN(ctx, r);
}
/* copied from pkcs15-cardos.c */
#define USAGE_ANY_SIGN (SC_PKCS15_PRKEY_USAGE_SIGN|\
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)

View File

@ -452,6 +452,7 @@ typedef struct sc_pkcs15_skey_info sc_pkcs15_skey_info_t;
#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_SKEY_AES 0x305
#define SC_PKCS15_TYPE_CERT 0x400
#define SC_PKCS15_TYPE_CERT_X509 0x401
@ -660,6 +661,12 @@ int sc_pkcs15_derive(struct sc_pkcs15_card *p15card,
unsigned long flags,
const u8 *in, size_t inlen, u8 *out, unsigned long *poutlen);
int sc_pkcs15_unwrap(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_object *key,
struct sc_pkcs15_object *target_key,
unsigned long flags,
const u8 * in, size_t inlen);
int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_object *prkey_obj,
unsigned long alg_flags, const u8 *in,
@ -687,7 +694,7 @@ int sc_pkcs15_decode_pubkey(struct sc_context *,
struct sc_pkcs15_pubkey *, const u8 *, size_t);
int sc_pkcs15_encode_pubkey(struct sc_context *,
struct sc_pkcs15_pubkey *, u8 **, size_t *);
int sc_pkcs15_encode_pubkey_as_spki(struct sc_context *,
int sc_pkcs15_encode_pubkey_as_spki(struct sc_context *,
struct sc_pkcs15_pubkey *, u8 **, size_t *);
void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *);
void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey *);

View File

@ -63,6 +63,21 @@ int sc_compute_signature(sc_card_t *card,
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
}
int sc_unwrap(sc_card_t *card,
const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
{
int r;
if (card == NULL || crgram == NULL) {
return SC_ERROR_INVALID_ARGUMENTS;
}
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_NORMAL);
if (card->ops->unwrap == NULL)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
r = card->ops->unwrap(card, crgram, crgram_len);
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
}
int sc_set_security_env(sc_card_t *card,
const sc_security_env_t *env,
int se_num)

View File

@ -2207,7 +2207,7 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile
struct sc_pkcs15_skey_info *skey_info;
CK_KEY_TYPE key_type;
CK_BBOOL _token = FALSE;
int rv;
int rv, rc;
char label[SC_PKCS15_MAX_LABEL_SIZE];
memset(&args, 0, sizeof(args));
@ -2228,6 +2228,9 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile
switch (key_type) {
/* Only support GENERIC_SECRET for now */
case CKK_GENERIC_SECRET:
case CKK_AES:
case CKK_DES3:
case CKK_DES:
break;
default:
return CKR_ATTRIBUTE_VALUE_INVALID;
@ -2283,7 +2286,7 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile
}
/* If creating a PKCS#11 session object, i.e. one that is only in memory */
if (_token == FALSE) {
if (_token == FALSE && (fw_data->p15_card->card->caps & SC_CARD_CAP_ONCARD_SESSION_OBJECTS) == 0) {
/* TODO Have 3 choices as to how to create the object.
* (1)create a sc_pkcs15init_store_secret_key routine like the others
@ -2303,11 +2306,11 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile
key_obj->flags = 2; /* TODO not sure what these mean */
skey_info = calloc(1, sizeof(sc_pkcs15_skey_info_t));
if (skey_info == NULL) {
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 */
@ -2319,18 +2322,11 @@ pkcs15_create_secret_key(struct sc_pkcs11_slot *slot, struct sc_profile *profile
args.key.data = NULL;
}
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 */
@ -3480,6 +3476,7 @@ struct sc_pkcs11_object_ops pkcs15_cert_ops = {
NULL, /* derive */
NULL, /* can_do */
NULL /* init_params */
NULL /* wrap_key */
};
/*
@ -3910,6 +3907,69 @@ pkcs15_prkey_sign(struct sc_pkcs11_session *session, void *obj,
}
static CK_RV
pkcs15_prkey_unwrap(struct sc_pkcs11_session *session, void *obj,
CK_MECHANISM_PTR pMechanism, CK_BYTE_PTR pWrappedKey,
CK_ULONG ulWrappedKeyLen,
void *targetKey)
/* CK_ATTRIBUTE_PTR pAttributes, CK_ULONG ulAttributesLen,
void ** pUnwrappedKey)*/
{
struct sc_pkcs11_card *p11card = session->slot->p11card;
struct pkcs15_fw_data *fw_data = NULL;
struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj;
struct sc_pkcs11_object *targetKeyObj = (struct sc_pkcs11_object *) targetKey;
int rv, flags = 0;
sc_log(context, "Initiating unwrapping with private key.");
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_UnwrapKey");
sc_log(context, "unwrapping %p %p %p %p %lu %p", session, obj,
pMechanism, pWrappedKey, ulWrappedKeyLen, targetKeyObj);
if (pMechanism == NULL || pWrappedKey == NULL || ulWrappedKeyLen == 0 || targetKeyObj == NULL)
return CKR_ARGUMENTS_BAD;
/* See which of the alternative keys supports unwrap */
while (prkey && !(prkey->prv_info->usage & SC_PKCS15_PRKEY_USAGE_UNWRAP))
prkey = prkey->prv_next;
if (prkey == NULL)
return CKR_KEY_FUNCTION_NOT_PERMITTED;
/* Select the proper padding mechanism */
switch (pMechanism->mechanism) {
case CKM_RSA_PKCS:
flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
break;
case CKM_RSA_X_509:
flags |= SC_ALGORITHM_RSA_RAW;
break;
default:
return CKR_MECHANISM_INVALID;
}
rv = sc_lock(p11card->card);
if (rv < 0)
return sc_to_cryptoki_error(rv, "C_UnwrapKey");
/* Call the card to do the unwrap operation */
rv = sc_pkcs15_unwrap(fw_data->p15_card, prkey->prv_p15obj, (struct sc_pkcs15_object *) targetKeyObj, 0,
pWrappedKey, ulWrappedKeyLen);
sc_unlock(p11card->card);
if (rv < 0)
return sc_to_cryptoki_error(rv, "C_UnwrapKey");
return CKR_OK;
}
static CK_RV
pkcs15_prkey_decrypt(struct sc_pkcs11_session *session, void *obj,
CK_MECHANISM_PTR pMechanism,
@ -4183,11 +4243,12 @@ struct sc_pkcs11_object_ops pkcs15_prkey_ops = {
pkcs15_any_destroy,
NULL, /* get_size */
pkcs15_prkey_sign,
NULL, /* unwrap */
pkcs15_prkey_unwrap,
pkcs15_prkey_decrypt,
pkcs15_prkey_derive,
pkcs15_prkey_can_do,
pkcs15_prkey_init_params,
NULL /* wrap_key */
};
/*
@ -4426,6 +4487,7 @@ struct sc_pkcs11_object_ops pkcs15_pubkey_ops = {
NULL, /* derive */
NULL, /* can_do */
NULL /* init_params */
NULL /* wrap_key */
};
@ -4605,6 +4667,7 @@ struct sc_pkcs11_object_ops pkcs15_dobj_ops = {
NULL, /* derive */
NULL, /* can_do */
NULL /* init_params */
NULL /* wrap_key */
};
@ -4735,6 +4798,7 @@ struct sc_pkcs11_object_ops pkcs15_skey_ops = {
NULL, /* derive */
NULL, /* can_do */
NULL /* init_params */
pkcs15_skey_wrap /* wrap_key */
};
/*
@ -5084,6 +5148,9 @@ register_mechanisms(struct sc_pkcs11_card *p11card)
/* That practise definitely conflicts with CKF_HW -- andre 2010-11-28 */
mech_info.flags |= CKF_VERIFY;
#endif
if ((card->caps & SC_CARD_CAP_UNWRAP_KEY) == SC_CARD_CAP_UNWRAP_KEY)
mech_info.flags |= CKF_UNWRAP;
mech_info.ulMinKeySize = ~0;
mech_info.ulMaxKeySize = 0;
ec_min_key_size = ~0;

View File

@ -830,6 +830,64 @@ sc_pkcs11_decr(struct sc_pkcs11_session *session,
return rv;
}
/*
* Unwrap a wrapped key into card. A new key object is created on card.
*/
CK_RV
sc_pkcs11_unwrap(struct sc_pkcs11_session *session,
CK_MECHANISM_PTR pMechanism,
struct sc_pkcs11_object *unwrappingKey,
CK_KEY_TYPE key_type, /* type of the unwrapping key */
CK_SESSION_HANDLE hSession,
CK_BYTE_PTR pWrappedKey, /* the wrapped key */
CK_ULONG ulWrappedKeyLen, /* bytes length of wrapped key */
struct sc_pkcs11_object *targetKey)
{
struct sc_pkcs11_card *p11card;
sc_pkcs11_operation_t *operation;
sc_pkcs11_mechanism_type_t *mt;
CK_RV rv;
if (!session || !session->slot
|| !(p11card = session->slot->p11card))
return CKR_ARGUMENTS_BAD;
/* See if we support this mechanism type */
mt = sc_pkcs11_find_mechanism(p11card, pMechanism->mechanism, CKF_UNWRAP);
if (mt == NULL)
return CKR_MECHANISM_INVALID;
/* See if compatible with key type */
/* TODO: what if there are several mechanisms with different key types? Should we loop through them? */
if (mt->key_type != key_type)
return CKR_KEY_TYPE_INCONSISTENT;
rv = session_start_operation(session, SC_PKCS11_OPERATION_UNWRAP, mt, &operation);
if (rv != CKR_OK)
return rv;
memcpy(&operation->mechanism, pMechanism, sizeof(CK_MECHANISM));
/*
* TODO: does it make sense to support unwrapping to a in memory key object?
* This implementation assumes that the key should be unwrapped into a
* key object on card, regardless whether CKA_TOKEN = FALSE
* CKA_TOKEN = FALSE is considered an on card session object.
*/
rv = operation->type->unwrap(operation, unwrappingKey,
pWrappedKey, ulWrappedKeyLen,
targetKey);
session_stop_operation(session, SC_PKCS11_OPERATION_UNWRAP);
return rv;
}
/* Derive one key from another, and return results in created object */
CK_RV
sc_pkcs11_deri(struct sc_pkcs11_session *session,
@ -990,6 +1048,29 @@ sc_pkcs11_derive(sc_pkcs11_operation_t *operation,
pData, pulDataLen);
}
static CK_RV
sc_pkcs11_unwrap_operation(sc_pkcs11_operation_t *operation,
struct sc_pkcs11_object *unwrappingKey,
CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
struct sc_pkcs11_object *targetKey)
/* CK_ATTRIBUTE_PTR pAttributes, CK_ULONG ulAttresLen,
void** phUnwrappedKey)*/
{
return unwrappingKey->ops->unwrap_key(operation->session,
unwrappingKey,
&operation->mechanism,
pWrappedKey, ulWrappedKeyLen,
targetKey);
/*return unwrappingKey->ops->unwrap_key(operation->session,
unwrappingKey,
&operation->mechanism,
pmechParam, ulmechParamLen,
pAttributes, ulAttresLen,
phUnwrappedKey);*/
}
/*
* Create new mechanism type for a mechanism supported by
* the card
@ -1027,7 +1108,7 @@ sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE mech,
#endif
}
if (pInfo->flags & CKF_UNWRAP) {
/* TODO */
mt->unwrap = sc_pkcs11_unwrap_operation;
}
if (pInfo->flags & CKF_DERIVE) {
mt->derive = sc_pkcs11_derive;

View File

@ -64,6 +64,8 @@ static sc_pkcs11_mechanism_type_t openssl_sha1_mech = {
NULL, NULL, NULL, /* verif_* */
NULL, NULL, /* decrypt_* */
NULL, /* derive */
NULL, /* wrap */
NULL, /* unwrap */
NULL, /* mech_data */
NULL, /* free_mech_data */
};
@ -98,6 +100,8 @@ static sc_pkcs11_mechanism_type_t openssl_sha256_mech = {
NULL, NULL, NULL, /* verif_* */
NULL, NULL, /* decrypt_* */
NULL, /* derive */
NULL, /* wrap */
NULL, /* unwrap */
NULL, /* mech_data */
NULL, /* free_mech_data */
};
@ -115,6 +119,8 @@ static sc_pkcs11_mechanism_type_t openssl_sha384_mech = {
NULL, NULL, NULL, /* verif_* */
NULL, NULL, /* decrypt_* */
NULL, /* derive */
NULL, /* wrap */
NULL, /* unwrap */
NULL, /* mech_data */
NULL, /* free_mech_data */
};
@ -132,6 +138,8 @@ static sc_pkcs11_mechanism_type_t openssl_sha512_mech = {
NULL, NULL, NULL, /* verif_* */
NULL, NULL, /* decrypt_* */
NULL, /* derive */
NULL, /* wrap */
NULL, /* unwrap */
NULL, /* mech_data */
NULL, /* free_mech_data */
};
@ -150,6 +158,8 @@ static sc_pkcs11_mechanism_type_t openssl_gostr3411_mech = {
NULL, NULL, NULL, /* verif_* */
NULL, NULL, /* decrypt_* */
NULL, /* derive */
NULL, /* wrap */
NULL, /* unwrap */
NULL, /* mech_data */
NULL, /* free_mech_data */
};
@ -168,6 +178,8 @@ static sc_pkcs11_mechanism_type_t openssl_md5_mech = {
NULL, NULL, NULL, /* verif_* */
NULL, NULL, /* decrypt_* */
NULL, /* derive */
NULL, /* wrap */
NULL, /* unwrap */
NULL, /* mech_data */
NULL, /* free_mech_data */
};
@ -185,6 +197,8 @@ static sc_pkcs11_mechanism_type_t openssl_ripemd160_mech = {
NULL, NULL, NULL, /* verif_* */
NULL, NULL, /* decrypt_* */
NULL, /* derive */
NULL, /* wrap */
NULL, /* unwrap */
NULL, /* mech_data */
NULL, /* free_mech_data */
};

View File

@ -47,6 +47,8 @@ static sc_pkcs11_mechanism_type_t find_mechanism = {
NULL, /* decrypt_init */
NULL, /* decrypt */
NULL, /* derive */
NULL, /* wrap */
NULL, /* unwrap */
NULL, /* mech_data */
NULL, /* free_mech_data */
};
@ -1049,7 +1051,67 @@ CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, /* the session's handle */
CK_ULONG ulAttributeCount, /* # of attributes in template */
CK_OBJECT_HANDLE_PTR phKey)
{ /* gets handle of recovered key */
return CKR_FUNCTION_NOT_SUPPORTED;
CK_RV rv;
CK_BBOOL can_unwrap;
CK_KEY_TYPE key_type;
CK_ATTRIBUTE unwrap_attribute = { CKA_UNWRAP, &can_unwrap, sizeof(can_unwrap) };
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, hUnwrappingKey, &session, &object);
if (rv != CKR_OK) {
if (rv == CKR_OBJECT_HANDLE_INVALID)
rv = CKR_KEY_HANDLE_INVALID;
goto out;
}
if (object->ops->unwrap_key == NULL_PTR) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
rv = object->ops->get_attribute(session, object, &unwrap_attribute);
if (rv != CKR_OK || !can_unwrap) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
rv = object->ops->get_attribute(session, object, &key_type_attr);
if (rv != CKR_OK) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
/* Create the target object in memory */
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 = restore_login_state(session->slot);
if (rv == CKR_OK)
rv = sc_pkcs11_unwrap(session, pMechanism, object, key_type,
hSession, pWrappedKey, ulWrappedKeyLen, key_object);
/* TODO if (rv != CK_OK) need to destroy the object */
rv = reset_login_state(session->slot, rv);
out:
sc_pkcs11_unlock();
return rv;
}
CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, /* the session's handle */

View File

@ -104,8 +104,7 @@ struct sc_pkcs11_object_ops {
CK_RV (*unwrap_key)(struct sc_pkcs11_session *, void *,
CK_MECHANISM_PTR,
CK_BYTE_PTR pData, CK_ULONG ulDataLen,
CK_ATTRIBUTE_PTR, CK_ULONG,
void **);
void *targetKey);
CK_RV (*decrypt)(struct sc_pkcs11_session *, void *,
CK_MECHANISM_PTR,
CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
@ -122,6 +121,11 @@ struct sc_pkcs11_object_ops {
/* General validation of mechanism parameters (sign, encrypt, etc) */
CK_RV (*init_params)(struct sc_pkcs11_session *, CK_MECHANISM_PTR);
CK_RV (*wrap_key)(struct sc_pkcs11_session *, void *,
CK_MECHANISM_PTR,
void*,
CK_BYTE_PTR pData, CK_ULONG_PTR ulDataLen);
/* Others to be added when implemented */
};
@ -237,6 +241,8 @@ enum {
SC_PKCS11_OPERATION_DIGEST,
SC_PKCS11_OPERATION_DECRYPT,
SC_PKCS11_OPERATION_DERIVE,
SC_PKCS11_OPERATION_WRAP,
SC_PKCS11_OPERATION_UNWRAP,
SC_PKCS11_OPERATION_MAX
};
@ -280,6 +286,15 @@ struct sc_pkcs11_mechanism_type {
struct sc_pkcs11_object *,
CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG_PTR);
CK_RV (*wrap)(sc_pkcs11_operation_t *,
struct sc_pkcs11_object *,
struct sc_pkcs11_object *,
CK_BYTE_PTR, CK_ULONG_PTR);
CK_RV (*unwrap)(sc_pkcs11_operation_t *,
struct sc_pkcs11_object *,
CK_BYTE_PTR, CK_ULONG,
struct sc_pkcs11_object *);
/* mechanism specific data */
const void * mech_data;
/* free mechanism specific data */
@ -419,6 +434,7 @@ CK_RV sc_pkcs11_verif_final(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG);
#endif
CK_RV sc_pkcs11_decr_init(struct sc_pkcs11_session *, CK_MECHANISM_PTR, struct sc_pkcs11_object *, CK_MECHANISM_TYPE);
CK_RV sc_pkcs11_decr(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR);
CK_RV sc_pkcs11_unwrap(struct sc_pkcs11_session *,CK_MECHANISM_PTR, struct sc_pkcs11_object *, CK_KEY_TYPE, CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, struct sc_pkcs11_object *);
CK_RV sc_pkcs11_deri(struct sc_pkcs11_session *, CK_MECHANISM_PTR,
struct sc_pkcs11_object *, CK_KEY_TYPE,
CK_SESSION_HANDLE, CK_OBJECT_HANDLE, struct sc_pkcs11_object *);

View File

@ -418,6 +418,12 @@ extern int sc_pkcs15init_sanity_check(struct sc_pkcs15_card *, struct sc_profile
extern int sc_pkcs15init_finalize_profile(struct sc_card *card, struct sc_profile *profile,
struct sc_aid *aid);
extern int sc_pkcs15init_unwrap_key(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
struct sc_pkcs15_object *key, u8* wrapped_key, size_t wrapped_key_len,
struct sc_pkcs15init_skeyargs *keyargs, struct sc_pkcs15_object **res_obj);
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_gpk_ops(void);
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_miocos_ops(void);
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_cryptoflex_ops(void);

View File

@ -175,6 +175,7 @@ static struct sc_pkcs15init_callbacks callbacks = {
NULL,
};
static void sc_pkcs15init_empty_callback(void *ptr)
{
}
@ -1880,8 +1881,9 @@ sc_pkcs15init_store_secret_key(struct sc_pkcs15_card *p15card, struct sc_profile
if (check_key_compatibility(p15card, keyargs->algorithm, NULL, 0, keyargs->key.data_len * 8, 0)) {
/* Make sure the caller explicitly tells us to store
* the key as extractable. */
if (!(keyargs->access_flags & SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE))
LOG_TEST_RET(ctx, SC_ERROR_INCOMPATIBLE_KEY, "Card does not support this key.");
/* Commented out. I don't understand why one couldn't store a key as non extractable. -HH */
/* if (!(keyargs->access_flags & SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE))
LOG_TEST_RET(ctx, SC_ERROR_INCOMPATIBLE_KEY, "Card does not support this key.");*/
}
#ifdef ENABLE_OPENSSL
@ -1908,12 +1910,16 @@ sc_pkcs15init_store_secret_key(struct sc_pkcs15_card *p15card, struct sc_profile
r = profile->ops->create_key(profile, p15card, object);
LOG_TEST_RET(ctx, r, "Card specific 'create key' failed");
if (profile->ops->store_key) {
struct sc_pkcs15_prkey key;
memset(&key, 0, sizeof(key));
key.algorithm = keyargs->algorithm;
key.u.secret = keyargs->key;
r = profile->ops->store_key(profile, p15card, object, &key);
/* If no key data, only an empty EF is created.
* It can be used to receive an unwrapped key later. */
if (keyargs->key.data_len > 0) {
if (profile->ops->store_key) {
struct sc_pkcs15_prkey key;
memset(&key, 0, sizeof(key));
key.algorithm = keyargs->algorithm;
key.u.secret = keyargs->key;
r = profile->ops->store_key(profile, p15card, object, &key);
}
}
LOG_TEST_RET(ctx, r, "Card specific 'store key' failed");