From 96732186c970eb6d426f0fa22d4dc81470fd6476 Mon Sep 17 00:00:00 2001 From: Aveen Ismail <42414844+aveenismail@users.noreply.github.com> Date: Sun, 1 Jan 2023 12:06:27 +0100 Subject: [PATCH] Opaque Meta Object (#289) PKCS11: Add support for editing an object's SKA_ID and CKA_LABEL by implementing a data opaque object. --- pkcs11/util_pkcs11.c | 704 +++++++++++++++++++++++++++++----------- pkcs11/util_pkcs11.h | 34 +- pkcs11/yubihsm_pkcs11.c | 519 ++++++++++++++++++++++------- pkcs11/yubihsm_pkcs11.h | 21 +- 4 files changed, 971 insertions(+), 307 deletions(-) diff --git a/pkcs11/util_pkcs11.c b/pkcs11/util_pkcs11.c index bc608b2d..e8bf9504 100644 --- a/pkcs11/util_pkcs11.c +++ b/pkcs11/util_pkcs11.c @@ -612,6 +612,286 @@ CK_RV get_mechanism_info(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE type, return CKR_OK; } +#define PKCS11_ID_TAG 1 +#define PKCS11_LABEL_TAG 2 +const char META_OBJECT_VERSION[4] = "MDB1"; + +/* + * Meta object value structure: + * byte 0-3 : META_OBJECT_VERSION (always present) + * byte 4: Original object type (always present) + * byte 5 and 6: Original object ID (always present) + * byte 7: original object sequence + * byte 8 and onward: TLV tripplets + */ +static CK_RV read_meta_object(yubihsm_pkcs11_slot *slot, uint16_t opaque_id, + pkcs11_meta_object *meta_object) { + + uint8_t opaque_value[YH_MSG_BUF_SIZE] = {0}; + size_t opaque_value_len = sizeof(opaque_value); + yh_rc yrc = yh_util_get_opaque(slot->device_session, opaque_id, opaque_value, + &opaque_value_len); + if (yrc != YHR_SUCCESS) { + DBG_ERR("Failed to read meta object 0x%x from device", opaque_id); + return yrc_to_rv(yrc); + } + + // 4 (version) + 1 (object type) + 2 (id) + 1 (sequence) + if (opaque_value_len < 8) { + DBG_ERR("Opaque value to import is too small to be a meta obeject data"); + return CKR_DATA_INVALID; + } + + uint8_t *p = opaque_value; + if (memcmp(p, META_OBJECT_VERSION, sizeof(META_OBJECT_VERSION)) != 0) { + DBG_ERR("Meta object value has unexpected version"); + return CKR_DATA_INVALID; + } + p += sizeof(META_OBJECT_VERSION); + + meta_object->target_type = *p++; + + meta_object->target_id = ntohs(*(uint16_t *) p); + p += 2; + + meta_object->target_sequence = *p++; + + while (p < opaque_value + opaque_value_len) { + switch (*p) { + case PKCS11_ID_TAG: + p++; // Tag byte + meta_object->cka_id_len = ntohs(*(uint16_t *) p); + p += 2; + memcpy(&meta_object->cka_id, p, meta_object->cka_id_len); + p += meta_object->cka_id_len; + break; + case PKCS11_LABEL_TAG: + p++; // Tag byte + meta_object->cka_label_len = ntohs(*(uint16_t *) p); + p += 2; + memcpy(&meta_object->cka_label, p, meta_object->cka_label_len); + p += meta_object->cka_label_len; + break; + default: + DBG_ERR("Unknown tag in value of opaque PKCS11 object"); + return CKR_DATA_INVALID; + } + } + return CKR_OK; +} + +yubihsm_pkcs11_object_desc *_get_object_desc(yubihsm_pkcs11_slot *slot, + uint16_t id, uint8_t type, + uint16_t sequence) { + + yubihsm_pkcs11_object_desc *object = NULL; + for (uint16_t i = 0; i < YH_MAX_ITEMS_COUNT; i++) { + if (slot->objects[i].object.id == id && + (slot->objects[i].object.type & 0x7f) == (type & 0x7f)) { + object = &slot->objects[i]; + if (sequence != 0xffff && + object->object.sequence != + sequence) { // Force refresh if cache entry has wrong sequence + memset(object, 0, sizeof(yubihsm_pkcs11_object_desc)); + } + break; + } + } + + if (!object) { + uint16_t low = 0; + struct timeval *low_time = NULL; + + for (uint16_t i = 0; i < YH_MAX_ITEMS_COUNT; i++) { + if (slot->objects[i].tv.tv_sec == 0) { + low = i; + low_time = &slot->objects[i].tv; + break; + } else { + if (!low_time || slot->objects[i].tv.tv_sec < low_time->tv_sec || + (slot->objects[i].tv.tv_sec == low_time->tv_sec && + slot->objects[i].tv.tv_usec < low_time->tv_usec)) { + + low_time = &slot->objects[i].tv; + low = i; + } + } + } + object = &slot->objects[low]; + memset(object, 0, sizeof(yubihsm_pkcs11_object_desc)); + } + + if (object->tv.tv_sec == 0) { + yh_rc yrc = yh_util_get_object_info(slot->device_session, id, type & 0x7f, + &object->object); + if (yrc != YHR_SUCCESS) { + return NULL; + } + + if (is_meta_object(&object->object)) { + // fill in the meta_object value + CK_RV rv = + read_meta_object(slot, object->object.id, &object->meta_object); + if (rv != CKR_OK) { + DBG_ERR("Failed to refresh meta object 0x%x", object->object.id); + return NULL; + } + } + } + + object->object.type = type; + gettimeofday(&object->tv, NULL); + + if (sequence != 0xffff && object->object.sequence != sequence) { + return NULL; // Only return for correct sequence + } + return object; +} + +yubihsm_pkcs11_object_desc *get_object_desc(yubihsm_pkcs11_slot *slot, + CK_OBJECT_HANDLE objHandle) { + uint16_t id = objHandle & 0xffff; + uint8_t type = (objHandle >> 16); + uint8_t sequence = objHandle >> 24; + return _get_object_desc(slot, id, type, sequence); +} + +CK_RV write_meta_object(yubihsm_pkcs11_slot *slot, + pkcs11_meta_object *meta_object, bool replace) { + size_t opaque_value_len = + 8 /* 4 version + 1 original type + 2 original ID 1 opaque sequence */ + + (meta_object->cka_id_len == 0 ? 0 : 3 + meta_object->cka_id_len) + + (meta_object->cka_label_len == 0 ? 0 : 3 + meta_object->cka_label_len); + // 3: 1 tag + 2 value length + + if (opaque_value_len > (YH_MSG_BUF_SIZE - 20)) { + DBG_ERR("Failed to write meta object to device. Meta object too large."); + return CKR_DATA_INVALID; + } + + uint8_t opaque_value[YH_MSG_BUF_SIZE] = {0}; + uint8_t *p = opaque_value; + + memcpy(p, META_OBJECT_VERSION, sizeof(META_OBJECT_VERSION)); // ObjectID + p += sizeof(META_OBJECT_VERSION); + + *p++ = meta_object->target_type; + + *(uint16_t *) p = htons(meta_object->target_id); + p += 2; + + *p++ = meta_object->target_sequence; + + if (meta_object->cka_id_len > 0) { + *p++ = PKCS11_ID_TAG; + *(uint16_t *) p = htons(meta_object->cka_id_len); + p += 2; + memcpy(p, &meta_object->cka_id, meta_object->cka_id_len); + p += meta_object->cka_id_len; + } + + if (meta_object->cka_label_len > 0) { + *p++ = PKCS11_LABEL_TAG; + *(uint16_t *) p = htons(meta_object->cka_label_len); + p += 2; + memcpy(p, &meta_object->cka_label, meta_object->cka_label_len); + } + + char opaque_label[YH_OBJ_LABEL_LEN] = {0}; + sprintf(opaque_label, "Meta object for 0x%x", meta_object->target_id); + + yh_rc rc = YHR_SUCCESS; + uint16_t meta_object_id = 0; + if (replace) { + yubihsm_pkcs11_object_desc *meta_desc = + find_meta_object_by_target(slot, meta_object->target_id, + meta_object->target_type, + meta_object->target_sequence); + if (meta_desc != NULL) { + meta_object_id = meta_desc->object.id; + rc = + yh_util_delete_object(slot->device_session, meta_object_id, YH_OPAQUE); + if (rc != YHR_SUCCESS) { + DBG_INFO("Failed to delete opaque object 0x%x", meta_desc->object.id); + } else { + DBG_INFO("Removed opaque object 0x%x with label %s", + meta_desc->object.id, opaque_label); + } + memset(meta_desc, 0, sizeof(yubihsm_pkcs11_object_desc)); + } + } + yh_capabilities capabilities = {{0}}; + rc = + yh_util_import_opaque(slot->device_session, &meta_object_id, opaque_label, + 0xffff, &capabilities, YH_ALGO_OPAQUE_DATA, + opaque_value, opaque_value_len); + + if (rc != YHR_SUCCESS) { + DBG_ERR("Failed to import opaque meta object for object 0x%x", + meta_object->target_id); + return yrc_to_rv(rc); + } + DBG_INFO("Successfully imported opaque object 0x%x with label: %s", + meta_object_id, opaque_label); + + _get_object_desc(slot, meta_object_id, YH_OPAQUE, 0xffff); + + return CKR_OK; +} + +bool is_meta_object(yh_object_descriptor *object) { + return (object->type == YH_OPAQUE && + object->algorithm == YH_ALGO_OPAQUE_DATA && + strncmp(object->label, "Meta object", strlen("Meta object")) == 0); +} + +bool match_byte_array(uint8_t *a, uint16_t a_len, uint8_t *b, uint16_t b_len) { + return a_len == b_len && memcmp(a, b, a_len) == 0; +} + +CK_RV populate_cache_with_data_opaques(yubihsm_pkcs11_slot *slot) { + if (slot == NULL || slot->device_session == NULL) { + DBG_INFO("No device session available"); + return CKR_OK; + } + + if (slot->objects[0].object.id != 0) { + DBG_INFO("Cache already populated"); + return CKR_OK; + } + + yh_rc rc = YHR_SUCCESS; + yh_object_descriptor opaques[YH_MAX_ITEMS_COUNT] = {0}; + size_t n_opaques = YH_MAX_ITEMS_COUNT; + yh_capabilities capabilities = {{0}}; + + rc = + yh_util_list_objects(slot->device_session, 0, YH_OPAQUE, 0, &capabilities, + YH_ALGO_OPAQUE_DATA, NULL, opaques, &n_opaques); + if (rc != YHR_SUCCESS) { + DBG_ERR("Failed to get object list"); + return yrc_to_rv(rc); + } + for (size_t i = 0; i < n_opaques; i++) { + _get_object_desc(slot, opaques[i].id, opaques[i].type, opaques[i].sequence); + } + return CKR_OK; +} + +yubihsm_pkcs11_object_desc * +find_meta_object_by_target(yubihsm_pkcs11_slot *slot, uint16_t target_id, + uint8_t target_type, uint8_t target_sequence) { + for (int i = 0; i < YH_MAX_ITEMS_COUNT; i++) { + pkcs11_meta_object *current_meta = &slot->objects[i].meta_object; + if (current_meta->target_id == target_id && + current_meta->target_type == target_type && + current_meta->target_sequence == target_sequence) { + return &slot->objects[i]; + } + } + return NULL; +} + bool create_session(yubihsm_pkcs11_slot *slot, CK_FLAGS flags, CK_SESSION_HANDLE_PTR phSession) { @@ -639,21 +919,32 @@ bool create_session(yubihsm_pkcs11_slot *slot, CK_FLAGS flags, return list_append(&slot->pkcs11_sessions, &session); } -static void get_label_attribute(yh_object_descriptor *object, CK_VOID_PTR value, - CK_ULONG_PTR length) { - - *length = strlen(object->label); - memcpy(value, object->label, *length); - // NOTE(adma): we have seen some weird behvior with different - // PKCS#11 tools. We decided not to add '\0' for now. This *seems* - // to be a good solution ... +static void get_label_attribute(yh_object_descriptor *object, + pkcs11_meta_object *meta_object, + CK_VOID_PTR value, CK_ULONG_PTR length) { + if (meta_object != NULL && meta_object->cka_label_len > 0) { + *length = meta_object->cka_label_len; + memcpy(value, meta_object->cka_label, *length); + } else { + *length = strlen(object->label); + memcpy(value, object->label, *length); + // NOTE(adma): we have seen some weird behvior with different + // PKCS#11 tools. We decided not to add '\0' for now. This *seems* + // to be a good solution ... + } } -static void get_id_attribute(yh_object_descriptor *object, CK_VOID_PTR value, +static void get_id_attribute(yh_object_descriptor *object, + pkcs11_meta_object *meta_object, CK_VOID_PTR value, CK_ULONG_PTR length) { - uint16_t *ptr = value; - *ptr = ntohs(object->id); - *length = sizeof(uint16_t); + if (meta_object != NULL && meta_object->cka_id_len > 0) { + *length = meta_object->cka_id_len; + memcpy(value, meta_object->cka_id, *length); + } else { + uint16_t *ptr = value; + *ptr = ntohs(object->id); + *length = sizeof(uint16_t); + } } static void get_capability_attribute(yh_object_descriptor *object, @@ -675,13 +966,13 @@ static void get_capability_attribute(yh_object_descriptor *object, static CK_RV get_attribute_opaque(CK_ATTRIBUTE_TYPE type, yh_object_descriptor *object, + pkcs11_meta_object *meta_object, CK_VOID_PTR value, CK_ULONG_PTR length, - yh_session *session) { + yubihsm_pkcs11_session *session) { if (object->type != YH_OPAQUE) { return CKR_FUNCTION_FAILED; } - switch (type) { case CKA_CLASS: if (object->algorithm == YH_ALGO_OPAQUE_X509_CERTIFICATE) { @@ -709,11 +1000,11 @@ static CK_RV get_attribute_opaque(CK_ATTRIBUTE_TYPE type, break; case CKA_LABEL: - get_label_attribute(object, value, length); + get_label_attribute(object, meta_object, value, length); break; case CKA_ID: - get_id_attribute(object, value, length); + get_id_attribute(object, meta_object, value, length); break; // NOTE(adma): Data Objects attributes @@ -731,7 +1022,8 @@ static CK_RV get_attribute_opaque(CK_ATTRIBUTE_TYPE type, case CKA_VALUE: { size_t len = *length; - yh_rc yrc = yh_util_get_opaque(session, object->id, value, &len); + yh_rc yrc = yh_util_get_opaque(session->slot->device_session, object->id, + value, &len); if (yrc != YHR_SUCCESS) { return yrc_to_rv(yrc); } @@ -747,6 +1039,11 @@ static CK_RV get_attribute_opaque(CK_ATTRIBUTE_TYPE type, } break; + case CKA_SUBJECT: + case CKA_ISSUER: + case CKA_SERIAL_NUMBER: + break; + default: return CKR_ATTRIBUTE_TYPE_INVALID; } @@ -756,6 +1053,7 @@ static CK_RV get_attribute_opaque(CK_ATTRIBUTE_TYPE type, static CK_RV get_attribute_secret_key(CK_ATTRIBUTE_TYPE type, yh_object_descriptor *object, + pkcs11_meta_object *meta_object, CK_VOID_PTR value, CK_ULONG_PTR length) { yh_object_type objtype; switch (type) { @@ -781,7 +1079,7 @@ static CK_RV get_attribute_secret_key(CK_ATTRIBUTE_TYPE type, break; case CKA_LABEL: - get_label_attribute(object, value, length); + get_label_attribute(object, meta_object, value, length); break; // NOTE(adma): Key Objects attributes @@ -856,7 +1154,7 @@ static CK_RV get_attribute_secret_key(CK_ATTRIBUTE_TYPE type, break; case CKA_ID: - get_id_attribute(object, value, length); + get_id_attribute(object, meta_object, value, length); break; // case CKA_START_DATE: @@ -970,8 +1268,9 @@ static CK_RV get_attribute_secret_key(CK_ATTRIBUTE_TYPE type, static CK_RV get_attribute_private_key(CK_ATTRIBUTE_TYPE type, yh_object_descriptor *object, + pkcs11_meta_object *meta_object, CK_VOID_PTR value, CK_ULONG_PTR length, - yh_session *session) { + yubihsm_pkcs11_session *session) { switch (type) { case CKA_CLASS: *((CK_OBJECT_CLASS *) value) = CKO_PRIVATE_KEY; @@ -995,7 +1294,7 @@ static CK_RV get_attribute_private_key(CK_ATTRIBUTE_TYPE type, break; case CKA_LABEL: - get_label_attribute(object, value, length); + get_label_attribute(object, meta_object, value, length); break; // NOTE(adma): Key Objects attributes @@ -1015,7 +1314,7 @@ static CK_RV get_attribute_private_key(CK_ATTRIBUTE_TYPE type, break; case CKA_ID: - get_id_attribute(object, value, length); + get_id_attribute(object, meta_object, value, length); break; // case CKA_START_DATE: @@ -1155,9 +1454,8 @@ static CK_RV get_attribute_private_key(CK_ATTRIBUTE_TYPE type, if (yh_is_ec(object->algorithm)) { uint8_t resp[2048]; size_t resplen = sizeof(resp); - - yh_rc yrc = - yh_util_get_public_key(session, object->id, resp, &resplen, NULL); + yh_rc yrc = yh_util_get_public_key(session->slot->device_session, + object->id, resp, &resplen, NULL); if (yrc != YHR_SUCCESS) { return yrc_to_rv(yrc); } @@ -1182,8 +1480,8 @@ static CK_RV get_attribute_private_key(CK_ATTRIBUTE_TYPE type, uint8_t resp[2048]; size_t resp_len = sizeof(resp); - yh_rc yrc = - yh_util_get_public_key(session, object->id, resp, &resp_len, NULL); + yh_rc yrc = yh_util_get_public_key(session->slot->device_session, + object->id, resp, &resp_len, NULL); if (yrc != YHR_SUCCESS) { return yrc_to_rv(yrc); } @@ -1320,8 +1618,9 @@ static CK_RV load_public_key(yh_session *session, uint16_t id, EVP_PKEY *key) { static CK_RV get_attribute_public_key(CK_ATTRIBUTE_TYPE type, yh_object_descriptor *object, + pkcs11_meta_object *meta_object, CK_VOID_PTR value, CK_ULONG_PTR length, - yh_session *session) { + yubihsm_pkcs11_session *session) { switch (type) { case CKA_CLASS: *((CK_OBJECT_CLASS *) value) = CKO_PUBLIC_KEY; @@ -1383,7 +1682,7 @@ static CK_RV get_attribute_public_key(CK_ATTRIBUTE_TYPE type, break; case CKA_LABEL: - get_label_attribute(object, value, length); + get_label_attribute(object, meta_object, value, length); break; // NOTE(adma): Key Objects attributes @@ -1441,7 +1740,7 @@ static CK_RV get_attribute_public_key(CK_ATTRIBUTE_TYPE type, break; case CKA_ID: - get_id_attribute(object, value, length); + get_id_attribute(object, meta_object, value, length); break; // case CKA_START_DATE: @@ -1515,8 +1814,8 @@ static CK_RV get_attribute_public_key(CK_ATTRIBUTE_TYPE type, uint8_t resp[2048]; size_t resplen = sizeof(resp); - yh_rc yrc = - yh_util_get_public_key(session, object->id, resp, &resplen, NULL); + yh_rc yrc = yh_util_get_public_key(session->slot->device_session, + object->id, resp, &resplen, NULL); if (yrc != YHR_SUCCESS) { return yrc_to_rv(yrc); } @@ -1555,8 +1854,8 @@ static CK_RV get_attribute_public_key(CK_ATTRIBUTE_TYPE type, uint8_t resp[2048]; size_t resp_len = sizeof(resp); - yh_rc yrc = - yh_util_get_public_key(session, object->id, resp, &resp_len, NULL); + yh_rc yrc = yh_util_get_public_key(session->slot->device_session, + object->id, resp, &resp_len, NULL); if (yrc != YHR_SUCCESS) { return yrc_to_rv(yrc); } @@ -1586,7 +1885,8 @@ static CK_RV get_attribute_public_key(CK_ATTRIBUTE_TYPE type, return CKR_HOST_MEMORY; } - CK_RV rv = load_public_key(session, object->id, pkey); + CK_RV rv = + load_public_key(session->slot->device_session, object->id, pkey); if (rv != CKR_OK) { EVP_PKEY_free(pkey); return rv; @@ -1605,21 +1905,29 @@ static CK_RV get_attribute_public_key(CK_ATTRIBUTE_TYPE type, static CK_RV get_attribute(CK_ATTRIBUTE_TYPE type, yh_object_descriptor *object, CK_BYTE_PTR value, CK_ULONG_PTR length, - yh_session *session) { + yubihsm_pkcs11_session *session) { + + yubihsm_pkcs11_object_desc *meta_desc = + find_meta_object_by_target(session->slot, object->id, object->type, + object->sequence); + pkcs11_meta_object *meta_object = meta_desc ? &meta_desc->meta_object : NULL; switch (object->type) { case YH_OPAQUE: - return get_attribute_opaque(type, object, value, length, session); + return get_attribute_opaque(type, object, meta_object, value, length, + session); case YH_WRAP_KEY: case YH_HMAC_KEY: case YH_SYMMETRIC_KEY: - return get_attribute_secret_key(type, object, value, length); + return get_attribute_secret_key(type, object, meta_object, value, length); case YH_ASYMMETRIC_KEY: - return get_attribute_private_key(type, object, value, length, session); + return get_attribute_private_key(type, object, meta_object, value, length, + session); case 0x80 | YH_ASYMMETRIC_KEY: - return get_attribute_public_key(type, object, value, length, session); + return get_attribute_public_key(type, object, meta_object, value, length, + session); case YH_TEMPLATE: case YH_AUTHENTICATION_KEY: @@ -1701,78 +2009,6 @@ static CK_RV get_attribute_ecsession_key(CK_ATTRIBUTE_TYPE type, return CKR_OK; } -void delete_object_from_cache(yubihsm_pkcs11_slot *slot, - CK_OBJECT_HANDLE objHandle) { - uint16_t id = objHandle & 0xffff; - uint8_t type = objHandle >> 16; - uint8_t sequence = objHandle >> 24; - for (uint16_t i = 0; i < YH_MAX_ITEMS_COUNT; i++) { - if (slot->objects[i].object.id == id && - (slot->objects[i].object.type & 0x7f) == (type & 0x7f) && - slot->objects[i].object.sequence == sequence) { - memset(&slot->objects[i], 0, sizeof(yubihsm_pkcs11_object_desc)); - return; - } - } -} - -yubihsm_pkcs11_object_desc *get_object_desc(yubihsm_pkcs11_slot *slot, - CK_OBJECT_HANDLE objHandle) { - - yubihsm_pkcs11_object_desc *object = NULL; - uint16_t id = objHandle & 0xffff; - uint8_t type = objHandle >> 16; - uint8_t sequence = objHandle >> 24; - for (uint16_t i = 0; i < YH_MAX_ITEMS_COUNT; i++) { - if (slot->objects[i].object.id == id && - (slot->objects[i].object.type & 0x7f) == (type & 0x7f)) { - object = &slot->objects[i]; - if(object->object.sequence != sequence) { // Force refresh if cache entry has wrong sequence - memset(object, 0, sizeof(yubihsm_pkcs11_object_desc)); - } - break; - } - } - - if (!object) { - uint16_t low = 0; - struct timeval *low_time = NULL; - - for (uint16_t i = 0; i < YH_MAX_ITEMS_COUNT; i++) { - if (slot->objects[i].tv.tv_sec == 0) { - low = i; - low_time = &slot->objects[i].tv; - break; - } else { - if (!low_time || slot->objects[i].tv.tv_sec < low_time->tv_sec || - (slot->objects[i].tv.tv_sec == low_time->tv_sec && - slot->objects[i].tv.tv_usec < low_time->tv_usec)) { - - low_time = &slot->objects[i].tv; - low = i; - } - } - } - object = &slot->objects[low]; - memset(object, 0, sizeof(yubihsm_pkcs11_object_desc)); - } - - if (!object->filled) { - yh_rc yrc = yh_util_get_object_info(slot->device_session, id, type & 0x7f, - &object->object); - if (yrc != YHR_SUCCESS) { - return NULL; - } - - object->filled = true; - } - - object->object.type = type; - gettimeofday(&object->tv, NULL); - - return object->object.sequence == sequence ? object : 0; // Only return for correct sequence -} - CK_RV check_sign_mechanism(yubihsm_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism) { @@ -2442,7 +2678,8 @@ static CK_RV perform_aes_update(yh_session *session, op_info->buffer_length = next; CK_RV rv; - if ((rv = do_aes_encdec(session, op_info, out, size, out, &size, false)) != CKR_OK) { + if ((rv = do_aes_encdec(session, op_info, out, size, out, &size, false)) != + CKR_OK) { DBG_ERR("Failed to encrypt/decrypt data"); return rv; } @@ -3680,10 +3917,8 @@ CK_RV parse_rsa_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, break; case CKA_WRAP: - case CKA_UNWRAP: case CKA_DERIVE: case CKA_ENCRYPT: - case CKA_SIGN_RECOVER: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_MODIFIABLE: @@ -3694,6 +3929,16 @@ CK_RV parse_rsa_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, } break; + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: { + CK_BBOOL b_val = *(CK_BBOOL *) pTemplate[i].pValue; + if (b_val != CK_FALSE) { + DBG_ERR("Boolean false check failed for attribute 0x%lx. This will " + "be ignored", + pTemplate[i].type); + } + } break; + case CKA_MODULUS: case CKA_PRIVATE_EXPONENT: case CKA_EXPONENT_1: @@ -3733,7 +3978,6 @@ CK_RV parse_rsa_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, DBG_ERR("Iconsistent RSA Template"); return CKR_TEMPLATE_INCONSISTENT; } - return CKR_OK; } @@ -3852,19 +4096,29 @@ CK_RV parse_ec_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, case CKA_VERIFY: case CKA_WRAP: - case CKA_UNWRAP: case CKA_ENCRYPT: case CKA_DECRYPT: - case CKA_SIGN_RECOVER: case CKA_VERIFY_RECOVER: case CKA_MODIFIABLE: case CKA_COPYABLE: case CKA_ALWAYS_AUTHENTICATE: if ((rv = check_bool_attribute(pTemplate[i].pValue, false)) != CKR_OK) { + DBG_ERR("Boolean false check failed for attribute 0x%lx.", + pTemplate[i].type); return rv; } break; + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: { + CK_BBOOL b_val = *(CK_BBOOL *) pTemplate[i].pValue; + if (b_val != CK_FALSE) { + DBG_ERR("Boolean false check failed for attribute 0x%lx. This will " + "be ignored", + pTemplate[i].type); + } + } break; + case CKA_CLASS: case CKA_KEY_TYPE: case CKA_SUBJECT: @@ -4003,15 +4257,68 @@ CK_RV parse_hmac_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, } } +CK_RV parse_meta_id_template(pkcs11_meta_object *pkcs11meta, int *id, + uint8_t *value, size_t value_len) { + if (value_len != 2) { + if (pkcs11meta->cka_id_len > 0) { + if (pkcs11meta->cka_id_len != value_len || + memcmp(pkcs11meta->cka_id, value, value_len) != 0) { + DBG_ERR("CKA_ID inconsistent in template"); + return CKR_TEMPLATE_INCONSISTENT; + } + } else { + pkcs11meta->cka_id_len = value_len; + memcpy(pkcs11meta->cka_id, value, value_len); + *id = 0; + } + } else { + *id = parse_id_value(value, value_len); + if (*id == -1) { + DBG_ERR("CKA_ID invalid in template"); + return CKR_ATTRIBUTE_VALUE_INVALID; + } + } + + return CKR_OK; +} + +CK_RV parse_meta_label_template(yubihsm_pkcs11_object_template *template, + pkcs11_meta_object *pkcs11meta, bool label_set, + uint8_t *value, size_t value_len) { + if (label_set == TRUE) { + int eq = 0; + if (value_len > YH_OBJ_LABEL_LEN) { + eq = memcmp(pkcs11meta->cka_label, value, value_len); + } else { + eq = memcmp(template->label, value, value_len); + } + if (eq != 0) { + DBG_ERR("CKA_LABEL inconsistent in template"); + return CKR_TEMPLATE_INCONSISTENT; + } + } else { + if (value_len > YH_OBJ_LABEL_LEN) { + pkcs11meta->cka_label_len = value_len; + memcpy(pkcs11meta->cka_label, value, value_len); + memcpy(template->label, value, YH_OBJ_LABEL_LEN); + } else { + memcpy(template->label, value, value_len); + } + } + return CKR_OK; +} + CK_RV parse_rsa_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, - yubihsm_pkcs11_object_template *template) { + yubihsm_pkcs11_object_template *template, + pkcs11_meta_object *pkcs11meta) { uint8_t *e = NULL; bool label_set = FALSE; CK_RV rv; + int id = 0; memset(template->label, 0, sizeof(template->label)); for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++) { @@ -4032,11 +4339,12 @@ CK_RV parse_rsa_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, case CKA_ID: if (template->id == 0) { - int id = parse_id_value(pPublicKeyTemplate[i].pValue, - pPublicKeyTemplate[i].ulValueLen); - if (id == -1) { - DBG_ERR("CKA_ID invalid in PublicKeyTemplate"); - return CKR_ATTRIBUTE_VALUE_INVALID; + rv = parse_meta_id_template(pkcs11meta, &id, + pPublicKeyTemplate[i].pValue, + pPublicKeyTemplate[i].ulValueLen); + if (rv != CKR_OK) { + DBG_ERR("Failed to parse CKA_ID in PublicKeyTemplate"); + return rv; } template->id = id; } else { @@ -4083,14 +4391,13 @@ CK_RV parse_rsa_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, break; case CKA_LABEL: - if (pPublicKeyTemplate[i].ulValueLen > YH_OBJ_LABEL_LEN) { - DBG_ERR("CKA_LABEL invalid in PublicKeyTemplate"); - return CKR_ATTRIBUTE_VALUE_INVALID; + rv = parse_meta_label_template(template, pkcs11meta, label_set, + pPublicKeyTemplate[i].pValue, + pPublicKeyTemplate[i].ulValueLen); + if (rv != CKR_OK) { + DBG_ERR("CKA_LABEL inconsistent in PublicKeyTemplate"); + return rv; } - - memcpy(template->label, pPublicKeyTemplate[i].pValue, - pPublicKeyTemplate[i].ulValueLen); - label_set = TRUE; break; @@ -4128,6 +4435,13 @@ CK_RV parse_rsa_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, case CKA_UNWRAP: // pkcs11-tool sets this on public keys case CKA_VERIFY: case CKA_ENCRYPT: + /* + case CKA_EXTRACTABLE: + case CKA_PRIVATE: + case CKA_COPYABLE: + case CKA_DESTROYABLE: + case CKA_DERIVE: + */ break; default: @@ -4155,11 +4469,12 @@ CK_RV parse_rsa_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, break; case CKA_ID: { - int id = parse_id_value(pPrivateKeyTemplate[i].pValue, - pPrivateKeyTemplate[i].ulValueLen); - if (id == -1) { - DBG_ERR("CKA_ID invalid in PrivateKeyTemplate"); - return CKR_ATTRIBUTE_VALUE_INVALID; + rv = + parse_meta_id_template(pkcs11meta, &id, pPrivateKeyTemplate[i].pValue, + pPrivateKeyTemplate[i].ulValueLen); + if (rv != CKR_OK) { + DBG_ERR("Failed to parse CKA_ID in PrivateKeyTemplate"); + return rv; } if (template->id != 0 && template->id != id) { DBG_ERR("CKA_ID inconsistent in PrivateKeyTemplate"); @@ -4197,20 +4512,12 @@ CK_RV parse_rsa_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, break; case CKA_LABEL: - if (pPrivateKeyTemplate[i].ulValueLen > YH_OBJ_LABEL_LEN) { - DBG_ERR("CKA_LABEL invalid in PrivateKeyTemplate"); - return CKR_ATTRIBUTE_VALUE_INVALID; - } - - if (label_set == TRUE) { - if (memcmp(template->label, pPrivateKeyTemplate[i].pValue, - pPrivateKeyTemplate[i].ulValueLen) != 0) { - DBG_ERR("CKA_LABEL inconsistent in PrivateKeyTemplate"); - return CKR_TEMPLATE_INCONSISTENT; - } - } else { - memcpy(template->label, pPrivateKeyTemplate[i].pValue, - pPrivateKeyTemplate[i].ulValueLen); + rv = parse_meta_label_template(template, pkcs11meta, label_set, + pPrivateKeyTemplate[i].pValue, + pPrivateKeyTemplate[i].ulValueLen); + if (rv != CKR_OK) { + DBG_ERR("CKA_LABEL inconsistent in PrivateKeyTemplate"); + return rv; } break; @@ -4279,12 +4586,14 @@ CK_RV parse_ec_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, - yubihsm_pkcs11_object_template *template) { + yubihsm_pkcs11_object_template *template, + pkcs11_meta_object *pkcs11meta) { uint8_t *ecparams = NULL; uint16_t ecparams_len = 0; bool label_set = FALSE; CK_RV rv; + int id; memset(template->label, 0, sizeof(template->label)); for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++) { @@ -4305,11 +4614,12 @@ CK_RV parse_ec_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, case CKA_ID: if (template->id == 0) { - int id = parse_id_value(pPublicKeyTemplate[i].pValue, - pPublicKeyTemplate[i].ulValueLen); - if (id == -1) { - DBG_ERR("CKA_ID invalid in PublicKeyTemplate"); - return CKR_ATTRIBUTE_VALUE_INVALID; + rv = parse_meta_id_template(pkcs11meta, &id, + pPublicKeyTemplate[i].pValue, + pPublicKeyTemplate[i].ulValueLen); + if (rv != CKR_OK) { + DBG_ERR("Failed to parse CKA_ID in PublicKeyTemplate"); + return rv; } template->id = id; } else { @@ -4329,14 +4639,13 @@ CK_RV parse_ec_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, break; case CKA_LABEL: - if (pPublicKeyTemplate[i].ulValueLen > YH_OBJ_LABEL_LEN) { - DBG_ERR("CKA_LABEL invalid in PublicKeyTemplate"); - return CKR_ATTRIBUTE_VALUE_INVALID; + rv = parse_meta_label_template(template, pkcs11meta, label_set, + pPublicKeyTemplate[i].pValue, + pPublicKeyTemplate[i].ulValueLen); + if (rv != CKR_OK) { + DBG_ERR("CKA_LABEL inconsistent in PublicKeyTemplate"); + return rv; } - - memcpy(template->label, pPublicKeyTemplate[i].pValue, - pPublicKeyTemplate[i].ulValueLen); - label_set = TRUE; break; @@ -4401,11 +4710,12 @@ CK_RV parse_ec_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, break; case CKA_ID: { - int id = parse_id_value(pPrivateKeyTemplate[i].pValue, - pPrivateKeyTemplate[i].ulValueLen); - if (id == -1) { - DBG_ERR("CKA_ID invalid in PrivateKeyTemplate"); - return CKR_ATTRIBUTE_VALUE_INVALID; + rv = + parse_meta_id_template(pkcs11meta, &id, pPrivateKeyTemplate[i].pValue, + pPrivateKeyTemplate[i].ulValueLen); + if (rv != CKR_OK) { + DBG_ERR("Failed to parse CKA_ID in PrivateKeyTemplate"); + return rv; } if (template->id != 0 && template->id != id) { DBG_ERR("CKA_ID inconsistent in PrivateKeyTemplate"); @@ -4413,6 +4723,7 @@ CK_RV parse_ec_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, } else { template->id = id; } + } break; case CKA_SIGN: @@ -4443,20 +4754,12 @@ CK_RV parse_ec_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, break; case CKA_LABEL: - if (pPrivateKeyTemplate[i].ulValueLen > YH_OBJ_LABEL_LEN) { - DBG_ERR("CKA_LABEL invalid in PrivateKeyTemplate"); - return CKR_ATTRIBUTE_VALUE_INVALID; - } - - if (label_set == TRUE) { - if (memcmp(template->label, pPrivateKeyTemplate[i].pValue, - pPrivateKeyTemplate[i].ulValueLen) != 0) { - DBG_ERR("CKA_LABEL inconsistent in PrivateKeyTemplate"); - return CKR_TEMPLATE_INCONSISTENT; - } - } else { - memcpy(template->label, pPrivateKeyTemplate[i].pValue, - pPrivateKeyTemplate[i].ulValueLen); + rv = parse_meta_label_template(template, pkcs11meta, label_set, + pPrivateKeyTemplate[i].pValue, + pPrivateKeyTemplate[i].ulValueLen); + if (rv != CKR_OK) { + DBG_ERR("CKA_LABEL inconsistent in PrivateKeyTemplate"); + return rv; } break; @@ -4723,7 +5026,7 @@ CK_RV parse_aes_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, } CK_RV populate_template(int type, void *object, CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount, yh_session *session) { + CK_ULONG ulCount, yubihsm_pkcs11_session *session) { CK_RV rv = CKR_OK; CK_BYTE tmp[8192]; @@ -4838,3 +5141,38 @@ CK_RV validate_derive_key_attribute(CK_ATTRIBUTE_TYPE type, void *value) { return CKR_OK; } + +bool match_meta_attributes(yubihsm_pkcs11_session *session, + yh_object_descriptor *object, uint8_t *cka_id, + uint16_t cka_id_len, uint8_t *cka_label, + uint16_t cka_label_len) { + CK_RV rv = CKR_OK; + CK_BYTE tmp[8192] = {0}; + CK_ULONG len = sizeof(tmp); + + if (cka_id_len > 0) { + rv = get_attribute(CKA_ID, object, tmp, &len, session); + if (rv != CKR_OK) { + DBG_ERR("Failed to parse CKA_ID"); + return false; + } + + if (!match_byte_array(tmp, len, cka_id, cka_id_len)) { + return false; + } + } + + if (cka_label_len > 0) { + memset(tmp, 0, len); + len = sizeof(tmp); + rv = get_attribute(CKA_LABEL, object, tmp, &len, session); + if (rv != CKR_OK) { + DBG_ERR("Failed to parse CKA_LABEL"); + return false; + } + if (!match_byte_array(tmp, len, cka_label, cka_label_len)) { + return false; + } + } + return true; +} diff --git a/pkcs11/util_pkcs11.h b/pkcs11/util_pkcs11.h index 4e3d1aa2..64e27567 100644 --- a/pkcs11/util_pkcs11.h +++ b/pkcs11/util_pkcs11.h @@ -35,9 +35,9 @@ void destroy_session(yubihsm_pkcs11_context *ctx, CK_SESSION_HANDLE hSession); yubihsm_pkcs11_object_desc *get_object_desc(yubihsm_pkcs11_slot *slot, CK_OBJECT_HANDLE objectHandle); - -void delete_object_from_cache(yubihsm_pkcs11_slot *slot, - CK_OBJECT_HANDLE objHandle); +yubihsm_pkcs11_object_desc *_get_object_desc(yubihsm_pkcs11_slot *slot, + uint16_t id, uint8_t type, + uint16_t sequence); CK_RV check_sign_mechanism(yubihsm_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism); @@ -141,22 +141,44 @@ CK_RV parse_rsa_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, - yubihsm_pkcs11_object_template *template); + yubihsm_pkcs11_object_template *template, + pkcs11_meta_object *pkcs11meta); CK_RV parse_ec_generate_template(CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, - yubihsm_pkcs11_object_template *template); + yubihsm_pkcs11_object_template *template, + pkcs11_meta_object *pkcs11meta); int parse_id_value(void *value, CK_ULONG len); CK_RV populate_template(int type, void *object, CK_ATTRIBUTE_PTR pTemplate, - CK_ULONG ulCount, yh_session *session); + CK_ULONG ulCount, yubihsm_pkcs11_session *session); CK_RV validate_derive_key_attribute(CK_ATTRIBUTE_TYPE type, void *value); CK_RV check_bool_attribute(void *value, bool check); CK_RV yrc_to_rv(yh_rc rc); +CK_RV populate_cache_with_data_opaques(yubihsm_pkcs11_slot *slot); +CK_RV write_meta_object(yubihsm_pkcs11_slot *slot, + pkcs11_meta_object *meta_object, bool replace); + +yubihsm_pkcs11_object_desc * +find_meta_object_by_target(yubihsm_pkcs11_slot *slot, uint16_t target_id, + uint8_t target_type, uint8_t target_sequence); + +bool match_meta_attributes(yubihsm_pkcs11_session *session, + yh_object_descriptor *object, uint8_t *cka_id, + uint16_t cka_id_len, uint8_t *cka_label, + uint16_t cka_label_len); + +bool is_meta_object(yh_object_descriptor *object); +CK_RV parse_meta_id_template(pkcs11_meta_object *pkcs11meta, int *id, + uint8_t *value, size_t value_len); +CK_RV parse_meta_label_template(yubihsm_pkcs11_object_template *template, + pkcs11_meta_object *pkcs11meta, bool label_set, + uint8_t *value, size_t value_len); +bool match_byte_array(uint8_t *a, uint16_t a_len, uint8_t *b, uint16_t b_len); #endif diff --git a/pkcs11/yubihsm_pkcs11.c b/pkcs11/yubihsm_pkcs11.c index a1e8c8b4..f039df2e 100644 --- a/pkcs11/yubihsm_pkcs11.c +++ b/pkcs11/yubihsm_pkcs11.c @@ -1253,6 +1253,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login) } list_iterate(&session->slot->pkcs11_sessions, login_sessions); + populate_cache_with_data_opaques(session->slot); DOUT; @@ -1342,6 +1343,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject) CK_ULONG d; } class = {0}, key_type = {0}, id = {0}; yubihsm_pkcs11_object_template template = {0}; + pkcs11_meta_object meta_object = {0}; for (CK_ULONG i = 0; i < ulCount; i++) { switch (pTemplate[i].type) { case CKA_CLASS: @@ -1366,10 +1368,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject) case CKA_ID: if (id.set == false) { - id.d = parse_id_value(pTemplate[i].pValue, pTemplate[i].ulValueLen); - if (id.d == (CK_ULONG) -1) { - rv = CKR_ATTRIBUTE_VALUE_INVALID; - goto c_co_out; + if (pTemplate[i].ulValueLen != 2) { + meta_object.cka_id_len = pTemplate[i].ulValueLen; + memcpy(meta_object.cka_id, pTemplate[i].pValue, + pTemplate[i].ulValueLen); + id.d = 0; + } else { + id.d = parse_id_value(pTemplate[i].pValue, pTemplate[i].ulValueLen); + if (id.d == (CK_ULONG) -1) { + rv = CKR_ATTRIBUTE_VALUE_INVALID; + goto c_co_out; + } } id.set = true; } else { @@ -1380,12 +1389,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject) case CKA_LABEL: if (pTemplate[i].ulValueLen > YH_OBJ_LABEL_LEN) { - rv = CKR_ATTRIBUTE_VALUE_INVALID; - goto c_co_out; + meta_object.cka_label_len = pTemplate[i].ulValueLen; + memcpy(meta_object.cka_label, pTemplate[i].pValue, + pTemplate[i].ulValueLen); + memcpy(template.label, pTemplate[i].pValue, YH_OBJ_LABEL_LEN); + } else { + memcpy(template.label, pTemplate[i].pValue, pTemplate[i].ulValueLen); } - - memcpy(template.label, pTemplate[i].pValue, pTemplate[i].ulValueLen); - break; case CKA_EXTRACTABLE: @@ -1494,6 +1504,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject) rv = CKR_ATTRIBUTE_VALUE_INVALID; goto c_co_out; } + + if (meta_object.cka_id_len > 0 || meta_object.cka_label_len > 0) { + meta_object.target_id = template.id; + } } else if (class.d == CKO_SECRET_KEY) { if (key_type.set == false) { rv = CKR_TEMPLATE_INCOMPLETE; @@ -1632,11 +1646,16 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject) rv = CKR_ATTRIBUTE_VALUE_INVALID; goto c_co_out; } + if (meta_object.cka_id_len > 0 || meta_object.cka_label_len > 0) { + meta_object.target_id = template.id; + } } else if (class.d == CKO_CERTIFICATE || class.d == CKO_DATA) { yh_algorithm algo = YH_ALGO_OPAQUE_DATA; type = YH_OPAQUE; if (class.d == CKO_CERTIFICATE) { algo = YH_ALGO_OPAQUE_X509_CERTIFICATE; + } else { + algo = YH_ALGO_OPAQUE_DATA; } for (CK_ULONG i = 0; i < ulCount; i++) { switch (pTemplate[i].type) { @@ -1683,6 +1702,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject) case CKA_LABEL: case CKA_APPLICATION: case CKA_OBJECT_ID: + case CKA_SUBJECT: + case CKA_ISSUER: + case CKA_SERIAL_NUMBER: break; default: DBG_ERR("Invalid attribute type in key template: 0x%lx", @@ -1700,21 +1722,103 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject) rv = yrc_to_rv(rc); goto c_co_out; } + if (algo == YH_ALGO_OPAQUE_X509_CERTIFICATE && + (meta_object.cka_id_len > 0 || meta_object.cka_label_len > 0)) { + meta_object.target_id = template.id; + } + } else if (class.d == CKO_PUBLIC_KEY) { + bool pubkey_found = false; + // Read the value of the public key + for (CK_ULONG i = 0; i < ulCount; i++) { + switch (pTemplate[i].type) { + case CKA_VALUE: + if (template.obj.buf == NULL) { + template.obj.buf = (CK_BYTE_PTR) pTemplate[i].pValue; + template.objlen = pTemplate[i].ulValueLen; + DBG_INFO("Object will be stored with length %d", template.objlen); + } else { + DBG_ERR("Object buffer already set"); + rv = CKR_TEMPLATE_INCONSISTENT; + goto c_co_out; + } + break; + } + } + + // Get a list of all asym objects in the YubiHSM + yh_object_descriptor asym_keys[YH_MAX_ITEMS_COUNT] = {0}; + size_t asym_keys_len = sizeof(asym_keys); + rc = yh_util_list_objects(session->slot->device_session, 0, + YH_ASYMMETRIC_KEY, 0, &capabilities, 0, NULL, + asym_keys, &asym_keys_len); + if (rc != YHR_SUCCESS) { + DBG_ERR("Failed to get object list"); + rv = yrc_to_rv(rc); + goto c_co_out; + } + + // Check which asym public key matches the one in the request + for (size_t i = 0; i < asym_keys_len; i++) { + if (!match_meta_attributes(session, &asym_keys[i], meta_object.cka_id, + meta_object.cka_id_len, meta_object.cka_label, + meta_object.cka_label_len)) { + continue; + } + + uint8_t pubkey[2048] = {0}; + size_t pubkey_len = sizeof(pubkey); + rc = yh_util_get_public_key(session->slot->device_session, + asym_keys[i].id, pubkey, &pubkey_len, NULL); + if (rc != YHR_SUCCESS) { + DBG_ERR("Failed to get public key of object 0x%x", asym_keys[i].id); + rv = yrc_to_rv(rc); + goto c_co_out; + } + + if (match_byte_array(pubkey, pubkey_len, template.obj.buf, + template.objlen)) { + template.id = asym_keys[i].id; + pubkey_found = true; + break; + } + } + + if (pubkey_found == false) { + rv = CKR_ATTRIBUTE_VALUE_INVALID; + goto c_co_out; + } + type = YH_ASYMMETRIC_KEY; } else { rv = CKR_TEMPLATE_INCONSISTENT; goto c_co_out; } - yh_object_descriptor object = {0}; - rc = yh_util_get_object_info(session->slot->device_session, template.id, type, - &object); - if (rc != YHR_SUCCESS) { - DBG_ERR("Failed executing get object info after creating: %s", - yh_strerror(rc)); - rv = yrc_to_rv(rc); + yubihsm_pkcs11_object_desc *object_desc = + _get_object_desc(session->slot, template.id, type, 0xffff); + if (object_desc == NULL) { + DBG_ERR("Failed executing get object info after creating: id 0x%x", + template.id); + rv = CKR_OBJECT_HANDLE_INVALID; goto c_co_out; } - *phObject = object.sequence << 24 | object.type << 16 | object.id; + yh_object_descriptor *object = &object_desc->object; + + if (meta_object.target_id != 0) { + meta_object.target_type = object->type; + meta_object.target_sequence = object->sequence; + rv = write_meta_object(session->slot, &meta_object, false); + if (rv != CKR_OK) { + DBG_ERR("Failed writing meta opaque object to device"); + goto c_co_out; + } + } + + if (class.d == CKO_PUBLIC_KEY) { + *phObject = + object->sequence << 24 | (object->type | 0x80) << 16 | object->id; + } else { + *phObject = object->sequence << 24 | object->type << 16 | object->id; + } DBG_INFO("Created object %08lx", *phObject); @@ -1779,7 +1883,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject) DBG_INFO("No ECDH session key with ID %08lx was found", hObject); } } else { - if (((uint8_t) (hObject >> 16)) == YH_PUBLIC_KEY) { + if (((uint8_t)(hObject >> 16)) == YH_PUBLIC_KEY) { DBG_INFO("Trying to delete public key, returning success with noop"); goto c_do_out; } @@ -1792,16 +1896,31 @@ CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject) goto c_do_out; } - yh_rc yrc = yh_util_delete_object(session->slot->device_session, - object->object.id, object->object.type); + yh_rc yrc; + yubihsm_pkcs11_object_desc *meta_desc = + find_meta_object_by_target(session->slot, object->object.id, + object->object.type, object->object.sequence); + if (meta_desc != NULL) { + yrc = yh_util_delete_object(session->slot->device_session, + meta_desc->object.id, meta_desc->object.type); + if (yrc != YHR_SUCCESS) { + DBG_ERR("Failed to delete meta opaque object: %s", yh_strerror(yrc)); + rv = yrc_to_rv(yrc); + goto c_do_out; + } + DBG_INFO("Deleted meta object 0x%x", meta_desc->object.id); + memset(meta_desc, 0, sizeof(yubihsm_pkcs11_object_desc)); + } + + yrc = yh_util_delete_object(session->slot->device_session, + object->object.id, object->object.type); if (yrc != YHR_SUCCESS) { - DBG_ERR("Failed deleting object: %s", yh_strerror(yrc)); + DBG_ERR("Failed to delete object: %s", yh_strerror(yrc)); rv = yrc_to_rv(yrc); goto c_do_out; } - DBG_INFO("Deleted object %08lx", hObject); - delete_object_from_cache(session->slot, hObject); + memset(&object->object, 0, sizeof(yubihsm_pkcs11_object_desc)); } DOUT; @@ -1899,8 +2018,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue) "Key id: 0x%lx", hObject); ecdh_session_key *key = (ecdh_session_key *) item->data; - rv = populate_template(type, key, pTemplate, ulCount, - session->slot->device_session); + rv = populate_template(type, key, pTemplate, ulCount, session); } if ((rv == CKR_OK) && !object_found) { @@ -1921,8 +2039,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue) goto c_gav_out; } - rv = populate_template(type, object, pTemplate, ulCount, - session->slot->device_session); + rv = populate_template(type, object, pTemplate, ulCount, session); if (rv != CKR_OK) { goto c_gav_out; } @@ -1974,16 +2091,20 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue) rv = CKR_OBJECT_HANDLE_INVALID; goto c_sav_out; } + + uint8_t new_ckaid[PKCS11_ID_SIZE] = {0}; + int new_ckaid_len = 0; + uint8_t new_ckalabel[PKCS11_LABEL_SIZE] = {0}; + int new_ckalabel_len = 0; + for (CK_ULONG i = 0; i < ulCount; i++) { switch (pTemplate[i].type) { case CKA_ID: { int new_id = parse_id_value(pTemplate[i].pValue, pTemplate[i].ulValueLen); if (new_id != object->object.id) { - DBG_INFO("Refusing to change id of object (old:%x, new:%x", - object->object.id, new_id); - rv = CKR_FUNCTION_NOT_SUPPORTED; - goto c_sav_out; + new_ckaid_len = pTemplate[i].ulValueLen; + memcpy(new_ckaid, pTemplate[i].pValue, pTemplate[i].ulValueLen); } } break; @@ -1991,12 +2112,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue) if (pTemplate[i].ulValueLen != strlen(object->object.label) || memcmp(pTemplate[i].pValue, object->object.label, pTemplate[i].ulValueLen) != 0) { - DBG_INFO("Refusing to change label of object"); - rv = CKR_FUNCTION_NOT_SUPPORTED; - goto c_sav_out; + new_ckalabel_len = pTemplate[i].ulValueLen; + memcpy(new_ckalabel, pTemplate[i].pValue, pTemplate[i].ulValueLen); } break; + case CKA_SUBJECT: + break; + default: DBG_INFO("Refusing to change attribute %lx of object", pTemplate[i].type); @@ -2005,6 +2128,64 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue) } } + if (new_ckaid_len > 0 || new_ckalabel_len > 0) { + DBG_INFO("New ID or label different from existing ones. Creating metadata " + "opaque object"); + + yubihsm_pkcs11_object_desc *meta_desc = + find_meta_object_by_target(session->slot, object->object.id, + object->object.type, object->object.sequence); + if (meta_desc != NULL) { + pkcs11_meta_object *meta_object = &meta_desc->meta_object; + bool changed = FALSE; + if (!match_byte_array(new_ckaid, new_ckaid_len, meta_object->cka_id, + meta_object->cka_id_len)) { + changed = TRUE; + if (meta_object->cka_id_len > 0) { + memset(&meta_object->cka_id, 0, meta_object->cka_id_len); + } + meta_object->cka_id_len = new_ckaid_len; + memcpy(meta_object->cka_id, new_ckaid, new_ckaid_len); + } + if (!match_byte_array(new_ckalabel, new_ckalabel_len, + meta_object->cka_label, + meta_object->cka_label_len)) { + changed = TRUE; + if (meta_object->cka_label_len > 0) { + memset(&meta_object->cka_label, 0, meta_object->cka_label_len); + } + meta_object->cka_label_len = new_ckalabel_len; + memcpy(meta_object->cka_label, new_ckalabel, new_ckalabel_len); + } + if (changed) { + rv = write_meta_object(session->slot, meta_object, true); + if (rv != CKR_OK) { + DBG_ERR("Failed to update meta opaque object to update CKA_ID"); + goto c_sav_out; + } + } + } else { + // Create new opaque object and add it to the session + pkcs11_meta_object new_meta_object = {0}; + new_meta_object.target_id = object->object.id; + new_meta_object.target_type = object->object.type; + new_meta_object.target_sequence = object->object.sequence; + if (new_ckaid_len > 0) { + new_meta_object.cka_id_len = new_ckaid_len; + memcpy(new_meta_object.cka_id, new_ckaid, new_ckaid_len); + } + if (new_ckalabel_len > 0) { + new_meta_object.cka_label_len = new_ckalabel_len; + memcpy(new_meta_object.cka_label, new_ckalabel, new_ckalabel_len); + } + rv = write_meta_object(session->slot, &new_meta_object, false); + if (rv != CKR_OK) { + DBG_ERR("Failed to create a new meta opaque object to store CKA_ID"); + goto c_sav_out; + } + } + } + DOUT; c_sav_out: release_session(&g_ctx, session); @@ -2050,6 +2231,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit) } char *label = NULL; + uint8_t *template_value = NULL; if (session->operation.type != OPERATION_NOOP) { DBG_ERR("Another operation is already active %d", session->operation.type); @@ -2082,23 +2264,23 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit) bool unknown = false; bool secret_key = false; bool extractable_set = false; + size_t template_value_len = 0; + uint8_t template_id[PKCS11_ID_SIZE] = {0}; + size_t template_id_len = 0; + uint8_t template_label[PKCS11_LABEL_SIZE] = {0}; + size_t template_label_len = 0; DBG_INFO("find with %lu attributes", ulCount); if (ulCount != 0) { for (CK_ULONG i = 0; i < ulCount; i++) { switch (pTemplate[i].type) { case CKA_ID: - id = parse_id_value(pTemplate[i].pValue, pTemplate[i].ulValueLen); - if (id == -1) { - DBG_ERR("Failed to parse ID from template"); - rv = CKR_ATTRIBUTE_VALUE_INVALID; - goto c_foi_out; - } - DBG_INFO("id parsed as %x", id); + template_id_len = pTemplate[i].ulValueLen; + memcpy(template_id, pTemplate[i].pValue, template_id_len); break; case CKA_CLASS: { - uint32_t value = *((CK_ULONG_PTR) (pTemplate[i].pValue)); + uint32_t value = *((CK_ULONG_PTR)(pTemplate[i].pValue)); switch (value) { case CKO_CERTIFICATE: DBG_INFO("Filtering for certificate"); @@ -2124,30 +2306,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit) default: unknown = true; - DBG_INFO("Asking for unknown class %x, returning empty set", - (uint32_t) pTemplate[i].type); - } - } break; - - case CKA_LABEL: { - CK_ULONG len = pTemplate[i].ulValueLen; - - if (len > YH_OBJ_LABEL_LEN) { - DBG_ERR("Label value too long, found %lu, maximum is %d", len, - YH_OBJ_LABEL_LEN); - rv = CKR_ATTRIBUTE_VALUE_INVALID; - goto c_foi_out; - } - - label = calloc(len + 1, sizeof(char)); - if (label == NULL) { - DBG_ERR("Unable to allocate label memory"); - rv = CKR_HOST_MEMORY; - goto c_foi_out; + DBG_INFO("Asking for unknown class %x, returning empty set. %x", + (uint32_t) pTemplate[i].type, value); } - - memcpy(label, pTemplate[i].pValue, len); } break; + case CKA_LABEL: + template_label_len = pTemplate[i].ulValueLen; + memcpy(template_label, pTemplate[i].pValue, template_label_len); + break; case CKA_SIGN: if (*((CK_BBOOL *) pTemplate[i].pValue) == CK_TRUE) { @@ -2221,6 +2387,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit) } break; + case CKA_VALUE: + template_value_len = pTemplate[i].ulValueLen; + template_value = malloc(template_value_len * sizeof(uint8_t)); + memcpy(template_value, pTemplate[i].pValue, template_value_len); + break; + case CKA_TOKEN: case CKA_PRIVATE: case CKA_SENSITIVE: @@ -2262,43 +2434,123 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit) if (tmp_objects[i].type == YH_WRAP_KEY || tmp_objects[i].type == YH_HMAC_KEY || tmp_objects[i].type == YH_SYMMETRIC_KEY) { - memcpy(session->operation.op.find.objects + found_objects, - tmp_objects + i, sizeof(yh_object_descriptor)); - found_objects++; + yubihsm_pkcs11_object_desc *object_desc = + _get_object_desc(session->slot, tmp_objects[i].id, + tmp_objects[i].type, tmp_objects[i].sequence); + + if (match_meta_attributes(session, &object_desc->object, template_id, + template_id_len, template_label, + template_label_len)) { + memcpy(session->operation.op.find.objects + found_objects, + tmp_objects + i, sizeof(yh_object_descriptor)); + found_objects++; + } } } } else { - session->operation.op.find.n_objects = - YH_MAX_ITEMS_COUNT + MAX_ECDH_SESSION_KEYS; - rc = yh_util_list_objects(session->slot->device_session, id, type, - domains, &capabilities, algorithm, label, - session->operation.op.find.objects, - &session->operation.op.find.n_objects); - if (rc != YHR_SUCCESS) { - DBG_ERR("Failed to get object list: %s", yh_strerror(rc)); - rv = yrc_to_rv(rc); - goto c_foi_out; - } - found_objects = session->operation.op.find.n_objects; + if (template_value != NULL) { + // Find by certificate + if (algorithm != 0 && algorithm != YH_ALGO_OPAQUE_X509_CERTIFICATE) { + DBG_ERR( + "Value in template not an X509Certificate. Cannot perform search."); + rv = CKR_ATTRIBUTE_VALUE_INVALID; + goto c_foi_out; + } else { + yh_object_descriptor tmp_objects[YH_MAX_ITEMS_COUNT] = {0}; + size_t tmp_n_objects = sizeof(tmp_objects); + rc = yh_util_list_objects(session->slot->device_session, id, + YH_OPAQUE, domains, &capabilities, + YH_ALGO_OPAQUE_X509_CERTIFICATE, label, + tmp_objects, &tmp_n_objects); + if (rc != YHR_SUCCESS) { + DBG_ERR("Failed to get object list"); + rv = yrc_to_rv(rc); + goto c_foi_out; + } + + for (size_t i = 0; i < tmp_n_objects; i++) { + uint8_t cert[2048] = {0}; + size_t cert_len = sizeof(cert); + rc = yh_util_get_opaque(session->slot->device_session, + tmp_objects[i].id, cert, &cert_len); + if (rc != YHR_SUCCESS) { + DBG_ERR("Failed to get opaque object 0x%x", tmp_objects[i].id); + rv = yrc_to_rv(rc); + goto c_foi_out; + } + + if (match_byte_array(template_value, template_value_len, cert, + cert_len)) { + session->operation.op.find.objects[0].id = tmp_objects[i].id; + session->operation.op.find.objects[0].type = tmp_objects[i].type; + session->operation.op.find.objects[0].sequence = + tmp_objects[i].sequence; + found_objects = 1; + break; + } + } + } + } else { + yh_object_descriptor + tmp_objects[YH_MAX_ITEMS_COUNT + MAX_ECDH_SESSION_KEYS] = {0}; + size_t tmp_n_objects = YH_MAX_ITEMS_COUNT + MAX_ECDH_SESSION_KEYS; + rc = yh_util_list_objects(session->slot->device_session, id, type, + domains, &capabilities, algorithm, label, + tmp_objects, &tmp_n_objects); + + if (rc != YHR_SUCCESS) { + DBG_ERR("Failed to get object list"); + rv = yrc_to_rv(rc); + goto c_foi_out; + } + for (size_t i = 0; i < tmp_n_objects; i++) { + yubihsm_pkcs11_object_desc *object_desc = + _get_object_desc(session->slot, tmp_objects[i].id, + tmp_objects[i].type, tmp_objects[i].sequence); - if (pub) { - for (size_t i = 0; i < session->operation.op.find.n_objects; i++) { - if (session->operation.op.find.objects[i].type == YH_ASYMMETRIC_KEY) { - session->operation.op.find.objects[i].type |= 0x80; + if (object_desc && is_meta_object(&object_desc->object)) { + continue; + } + + if (match_meta_attributes(session, &object_desc->object, template_id, + template_id_len, template_label, + template_label_len)) { + memcpy(session->operation.op.find.objects + found_objects, + tmp_objects + i, sizeof(yh_object_descriptor)); + found_objects++; + } + } + if (pub) { + for (size_t i = 0; i < found_objects; i++) { + if (session->operation.op.find.objects[i].type == + YH_ASYMMETRIC_KEY) { + session->operation.op.find.objects[i].type |= 0x80; + } } } } } + id = parse_id_value(template_id, template_id_len); + if (id == -1) { + DBG_ERR("Failed to parse ID from template"); + rv = CKR_ATTRIBUTE_VALUE_INVALID; + goto c_foi_out; + } + DBG_INFO("id parsed as %x", id); + if (ulCount == 0 || should_include_sessionkeys(secret_key, extractable_set, session->operation.op.find.only_private, id)) { - for (ListItem *item = session->ecdh_session_keys.head; item != NULL; + + ListItem *item = NULL; + for (item = session->ecdh_session_keys.head; item != NULL; item = item->next) { ecdh_session_key *key = (ecdh_session_key *) item->data; - if (label == NULL || strcmp(label, key->label) == 0) { + if (template_label_len == 0 || + strcmp((const char *) template_label, key->label) == 0) { yh_object_descriptor desc = {0}; desc.id = key->id & 0xffff; @@ -2326,6 +2578,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit) DOUT; c_foi_out: + if (template_value != NULL) { + free(template_value); + template_value = NULL; + } if (label != NULL) { free(label); @@ -3137,8 +3393,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Decrypt) pPtr += *pulDataLen; rv = apply_decrypt_mechanism_finalize(session->slot->device_session, - &session->operation, - pPtr, &ulRemainingSize); + &session->operation, pPtr, + &ulRemainingSize); if (rv != CKR_OK) { DBG_ERR("Unable to decrypt data"); if (rv == CKR_BUFFER_TOO_SMALL) { @@ -4557,6 +4813,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey) } yubihsm_pkcs11_object_template template = {0}; + pkcs11_meta_object meta_object = {0}; memset(&template, 0, sizeof(yubihsm_pkcs11_object_template)); struct { bool set; @@ -4586,9 +4843,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey) case CKA_ID: if (id.set == false) { - id.d = parse_id_value(pTemplate[i].pValue, pTemplate[i].ulValueLen); - if (id.d == (CK_ULONG) -1) { - rv = CKR_ATTRIBUTE_VALUE_INVALID; + rv = parse_meta_id_template(&meta_object, (int *) &id.d, + pTemplate[i].pValue, + pTemplate[i].ulValueLen); + if (rv != CKR_OK) { goto c_gk_out; } id.set = true; @@ -4599,12 +4857,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey) break; case CKA_LABEL: - if (pTemplate[i].ulValueLen > YH_OBJ_LABEL_LEN) { - return CKR_ATTRIBUTE_VALUE_INVALID; - } - - memcpy(template.label, pTemplate[i].pValue, pTemplate[i].ulValueLen); - + rv = parse_meta_label_template(&template, &meta_object, FALSE, + pTemplate[i].pValue, + pTemplate[i].ulValueLen); break; case CKA_EXTRACTABLE: @@ -4781,15 +5036,27 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey) goto c_gk_out; } - yh_object_descriptor object = {0}; - rc = yh_util_get_object_info(session->slot->device_session, template.id, type, - &object); - if (rc != YHR_SUCCESS) { + yubihsm_pkcs11_object_desc *object_desc = + _get_object_desc(session->slot, template.id, type, 0xffff); + if (object_desc == NULL) { DBG_ERR("Failed getting new object %04x: %s", template.id, yh_strerror(rc)); - rv = yrc_to_rv(rc); + rv = CKR_OBJECT_HANDLE_INVALID; goto c_gk_out; } - *phKey = object.sequence << 24 | object.type << 16 | object.id; + yh_object_descriptor *object = &object_desc->object; + + *phKey = object->sequence << 24 | object->type << 16 | object->id; + + if (meta_object.cka_id_len > 0 || meta_object.cka_label_len > 0) { + meta_object.target_id = object->id; + meta_object.target_type = object->type; + meta_object.target_sequence = object->sequence; + rv = write_meta_object(session->slot, &meta_object, false); + if (rv != CKR_OK) { + DBG_ERR("Failed to import meta data object 0x%lx", rv); + goto c_gk_out; + } + } DBG_INFO("Created object %08lx", *phKey); @@ -4836,17 +5103,20 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair) } yubihsm_pkcs11_object_template template = {0}; + pkcs11_meta_object meta_object = {0}; if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN) { rv = parse_rsa_generate_template(pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, - ulPrivateKeyAttributeCount, &template); + ulPrivateKeyAttributeCount, &template, + &meta_object); } else if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN) { rv = parse_ec_generate_template(pPublicKeyTemplate, ulPublicKeyAttributeCount, pPrivateKeyTemplate, - ulPrivateKeyAttributeCount, &template); + ulPrivateKeyAttributeCount, &template, + &meta_object); } else { DBG_ERR("Invalid mechanism for key generation: %lu", pMechanism->mechanism); rv = CKR_MECHANISM_INVALID; @@ -4926,15 +5196,27 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair) } } - yh_object_descriptor object = {0}; - rc = yh_util_get_object_info(session->slot->device_session, template.id, - YH_ASYMMETRIC_KEY, &object); - if (rc != YHR_SUCCESS) { - rv = yrc_to_rv(rc); + yubihsm_pkcs11_object_desc *object_desc = + _get_object_desc(session->slot, template.id, YH_ASYMMETRIC_KEY, 0xffff); + if (object_desc == NULL) { + rv = CKR_OBJECT_HANDLE_INVALID; goto c_gkp_out; } - *phPublicKey = object.sequence << 24 | (object.type | 0x80) << 16 | object.id; - *phPrivateKey = object.sequence << 24 | object.type << 16 | object.id; + yh_object_descriptor *object = &object_desc->object; + + if (meta_object.cka_id_len > 0 || meta_object.cka_label_len > 0) { + meta_object.target_id = object->id; + meta_object.target_type = object->type; + meta_object.target_sequence = object->sequence; + rv = write_meta_object(session->slot, &meta_object, false); + if (rv != CKR_OK) { + DBG_ERR("Failed to import meta data object 0x%lx", rv); + goto c_gkp_out; + } + } + *phPublicKey = + object->sequence << 24 | (object->type | 0x80) << 16 | object->id; + *phPrivateKey = object->sequence << 24 | object->type << 16 | object->id; DOUT; @@ -5134,14 +5416,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey) goto c_uk_out; } - yh_object_descriptor object = {0}; - yrc = yh_util_get_object_info(session->slot->device_session, target_id, - target_type, &object); - if (yrc != YHR_SUCCESS) { - rv = yrc_to_rv(yrc); + yubihsm_pkcs11_object_desc *object_desc = + _get_object_desc(session->slot, target_id, target_type, 0xffff); + if (object_desc == NULL) { + DBG_ERR("Failed executing get object info after creating: id 0x%x", + target_id); + rv = CKR_OBJECT_HANDLE_INVALID; goto c_uk_out; } - *phKey = object.sequence << 24 | object.type << 16 | object.id; + yh_object_descriptor *object = &object_desc->object; + + *phKey = object->sequence << 24 | object->type << 16 | object->id; DBG_INFO("Unwrapped object %08lx", *phKey); diff --git a/pkcs11/yubihsm_pkcs11.h b/pkcs11/yubihsm_pkcs11.h index f0598667..eccfd284 100644 --- a/pkcs11/yubihsm_pkcs11.h +++ b/pkcs11/yubihsm_pkcs11.h @@ -34,6 +34,8 @@ #ifndef AES_BLOCK_SIZE #define AES_BLOCK_SIZE 16 #endif +#define PKCS11_ID_SIZE 255 +#define PKCS11_LABEL_SIZE 255 typedef enum { SESSION_RESERVED_RO = 1 << 0, @@ -46,10 +48,27 @@ typedef enum { (SESSION_AUTHENTICATED_RO | SESSION_AUTHENTICATED_RW) #define SESSION_NOT_AUTHENTICATED (SESSION_RESERVED_RO | SESSION_RESERVED_RW) +typedef struct { + /// Original objectID of the asymmetric key/certificate/symmetric key + uint16_t target_id; + /// Original object type + yh_object_type target_type; + /// Original object sequence + uint8_t target_sequence; + /// CKA_ID value + uint8_t cka_id[PKCS11_ID_SIZE]; + /// CKA_ID length + uint16_t cka_id_len; + /// CKA_LABEL value + uint8_t cka_label[PKCS11_LABEL_SIZE]; + /// CKA_LABEL length + uint16_t cka_label_len; +} pkcs11_meta_object; + typedef struct { struct timeval tv; - bool filled; yh_object_descriptor object; + pkcs11_meta_object meta_object; } yubihsm_pkcs11_object_desc; typedef enum {