diff options
-rw-r--r-- | pkcs11.c | 1264 |
1 files changed, 641 insertions, 623 deletions
@@ -155,8 +155,11 @@ typedef struct p11_session { CK_STATE state; /* State (CKS_*) of this session */ CK_NOTIFY notify; /* Notification callback */ CK_VOID_PTR application; /* Application data */ - hal_rpc_pkey_attribute *find_query; /* FindObject*() query state */ - int find_query_done; /* find_query has terminated */ + hal_rpc_pkey_attribute_t *find_query; /* FindObject*() query state */ + unsigned find_query_token : 1; /* Find query for token objects in progress */ + unsigned find_query_session : 1; /* Find query for session objects in progress */ + unsigned find_query_n : 30; /* Number of entries in find_query */ + hal_uuid_t find_query_previous_uuid; /* Previous UUID for find queries */ hal_digest_algorithm_t digest_algorithm, /* Hash algorithm for C_Digest*() */ sign_digest_algorithm, /* Hash algorithm for C_Sign*() */ @@ -222,11 +225,11 @@ static enum { * PKCS #11 sessions and object handles for this application. */ -static p11_session_t p11_sessions[P11_MAX_SESSION_HANDLES]; -static p11_object_t p11_objects [P11_MAX_OBJECT_HANDLES]; +static p11_session_t p11_sessions [P11_MAX_SESSION_HANDLES]; +static p11_object_t p11_objects [P11_MAX_OBJECT_HANDLES]; +static unsigned p11_object_uuids [P11_MAX_OBJECT_HANDLES]; -static unsigned p11_sessions_in_use, p11_session_next; -static unsigned p11_objects_in_use, p11_object_next; +static unsigned p11_sessions_in_use, p11_objects_in_use; /* * Mutex callbacks. @@ -660,7 +663,7 @@ static inline CK_ULONG handle_compose(const handle_flavor_t flavor, { return (mask_dpb(HANDLE_MASK_FLAVOR, flavor) | mask_dpb(HANDLE_MASK_NONCE, nonce) | - mask_dbp(HANDLE_MASK_INDEX, index)); + mask_dpb(HANDLE_MASK_INDEX, index)); } static inline handle_flavor_t handle_flavor(const CK_ULONG handle) @@ -670,7 +673,7 @@ static inline handle_flavor_t handle_flavor(const CK_ULONG handle) static inline unsigned handle_index(const CK_ULONG handle) { - return mask_ldb(HANDLE_INDEX, handle); + return mask_ldb(HANDLE_MASK_INDEX, handle); } // Backwards compatability, probably phase this out @@ -679,79 +682,64 @@ static inline unsigned handle_index(const CK_ULONG handle) /* - * Attribute methods. + * Descriptor methods. Descriptors are generated at compile time by + * an auxiliary Python script, see attributes.* for details. */ /* - * Set an attribute for a given object. - * - * It would be trivial to generalize this to take a CK_ATTRIBUTE_PTR - * template instead of a single attribute, at the cost of losing the - * const specifiers (CK_ATTRIBUTE_PTR has an internal non-const void*). + * Return the descriptor associated with a particular object class and + * key type. */ -static int p11_attribute_set(const hal_pkey_handle_t pkey, - const CK_ATTRIBUTE_TYPE type, - const void * const value, - const CK_ULONG length) +static const p11_descriptor_t *p11_descriptor_from_key_type(const CK_OBJECT_CLASS object_class, + const CK_KEY_TYPE key_type) { - const hal_rpc_pkey_attribute_t attribute = {.type = type, .length = length, .value = value}; - return hal_check(hal_rpc_pkey_set_attributes(pkey, &attribute, 1)); + int i; + + for (i = 0; i < sizeof(p11_descriptor_keyclass_map)/sizeof(*p11_descriptor_keyclass_map); i++) { + const p11_descriptor_keyclass_map_t * const m = &p11_descriptor_keyclass_map[i]; + if (m->object_class == object_class && m->key_type == key_type) + return m->descriptor; + } + + return NULL; } /* - * Get a single attribute from a given object. - * - * This could easily be generalized to take a CK_ATTRIBUTE_PTR, at the - * cost of more complicated error semantics. + * Find the entry for a particular attribute in a descriptor. */ -static int p11_attribute_get(const hal_pkey_handle_t pkey, - const CK_ATTRIBUTE_TYPE type, - void *value, - CK_ULONG *length, - const CK_ULONG maxlength) +static const p11_attribute_descriptor_t *p11_find_attribute_in_descriptor(const p11_descriptor_t *descriptor, + const CK_ATTRIBUTE_TYPE type) { - hal_rpc_pkey_attribute_t attribute = {.type = type}; - - if (!hal_check(hal_rpc_pkey_get_attributes(pkey, &attribute, 1, value, maxlength))) - return 0; + int i; - if (length != NULL) - *length = attribute.length; + if (descriptor != NULL && descriptor->attributes != NULL) + for (i = 0; i < descriptor->n_attributes; i++) + if (descriptor->attributes[i].type == type) + return &descriptor->attributes[i]; - return 1; + return NULL; } /* - * Wrappers to set and get CK_BBOOL and CK_ULONG values. + * Check whether an attribute is marked as sensitive. If we don't + * recognize the attribute, report it as sensitive (safer than the + * alternative). */ -static int p11_attribute_set_bbool(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, const CK_BBOOL value) -{ - return p11_attribute_set(pkey, type, &value, sizeof(value)); -} - -#if 0 - -static int p11_attribute_set_ulong(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, const CK_ULONG value) +static int p11_attribute_is_sensitive(const p11_descriptor_t *descriptor, + const CK_ATTRIBUTE_TYPE type) { - return p11_attribute_set(pkey, type, &value, sizeof(value)); + const p11_attribute_descriptor_t *a = p11_find_attribute_in_descriptor(descriptor, type); + return a == NULL || (a->flags & P11_DESCRIPTOR_SENSITIVE) != 0; } -#endif - -static int p11_attribute_get_bbool(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, CK_BBOOL *value) -{ - CK_ULONG length; - return p11_attribute_get(pkey, type, value, &length, sizeof(*value)) && length == sizeof(*value); -} + -static int p11_attribute_get_ulong(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, CK_ULONG *value) -{ - CK_ULONG length; - return p11_attribute_get(pkey, type, value, &length, sizeof(*value)) && length == sizeof(*value); -} +/* + * Attribute methods. + */ /* * Find an attribute in a CK_ATTRIBUTE_PTR template. Returns index @@ -784,6 +772,104 @@ static void *p11_attribute_find_value_in_template(const CK_ATTRIBUTE_TYPE type, } /* + * Set attributes for a newly-created or newly-uploaded HSM key. + */ + +static int p11_attributes_set(const hal_pkey_handle_t pkey, + const CK_ATTRIBUTE_PTR template, + const CK_ULONG template_length, + const p11_descriptor_t * const descriptor, + const hal_rpc_pkey_attribute_t *extra, + const unsigned extra_length) +{ + assert(template != NULL && descriptor != NULL && (extra_length == 0 || extra != NULL)); + + /* + * Populate attributes, starting with the application's template, + * which we assume has already been blessed by the API function that + * called this method. + * + * If the attribute is flagged as sensitive in the descriptor, we + * don't store it as an attribute. Generally, this only arises for + * private key components of objects created with C_CreateObject(), + * but in theory there are some corner cases in which a user could + * choose to mark a private key as extractable and not sensitive, so + * we might have to back-fill missing values in those cases if + * anyone ever thinks up a sane reason for supporting them. For + * now, assume that private keys are bloody well supposed to be + * private. + */ + + hal_rpc_pkey_attribute_t attributes[template_length + descriptor->n_attributes + extra_length]; + unsigned n = 0; + + for (int i = 0; i < template_length; i++) { + const CK_ATTRIBUTE_TYPE type = template[i].type; + const void * val = template[i].pValue; + const int len = template[i].ulValueLen; + + if (p11_attribute_is_sensitive(descriptor, type)) + continue; + + if (n >= sizeof(attributes) / sizeof(*attributes)) + return 0; + + attributes[n].type = type; + attributes[n].value = val; + attributes[n].length = len; + n++; + } + + /* + * Next, add defaults from the descriptor. + */ + + for (int i = 0; i < descriptor->n_attributes; i++) { + const CK_ATTRIBUTE_TYPE type = descriptor->attributes[i].type; + const void * val = descriptor->attributes[i].value; + const int len = descriptor->attributes[i].length; + const unsigned flags = descriptor->attributes[i].flags; + + if (val == NULL && (flags & P11_DESCRIPTOR_DEFAULT_VALUE) != 0) + val = ""; + + if (val == NULL || p11_attribute_find_in_template(type, template, template_length) >= 0) + continue; + + if (n >= sizeof(attributes) / sizeof(*attributes)) + return 0; + + attributes[n].type = type; + attributes[n].value = val; + attributes[n].length = len; + n++; + } + + /* + * Finally, add any attributes provided by the calling function itself. + */ + + for (int i = 0; i < extra_length; i++) { + if (n >= sizeof(attributes) / sizeof(*attributes)) + return 0; + + attributes[n].type = extra[i].type; + attributes[n].value = extra[i].value; + attributes[n].length = extra[i].length; + n++; + } + + /* + * Set all those attributes. + */ + + if (!hal_check(hal_rpc_pkey_set_attributes(pkey, attributes, n))) + return 0; + + return 1; +} + +/* * Map a keyusage-related attribute to a keyusage bit flag. * * Assumes that calling code has already checked whether this @@ -832,65 +918,42 @@ static void p11_attribute_apply_keyusage(hal_key_flags_t *keyusage, const CK_ATT /* - * Descriptor methods. Descriptors are generated at compile time by - * an auxiliary Python script, see attributes.* for details. + * Object methods. */ /* - * Return the descriptor associated with a particular object class and - * key type. - */ - -static const p11_descriptor_t *p11_descriptor_from_key_type(const CK_OBJECT_CLASS object_class, - const CK_KEY_TYPE key_type) -{ - int i; - - for (i = 0; i < sizeof(p11_descriptor_keyclass_map)/sizeof(*p11_descriptor_keyclass_map); i++) { - const p11_descriptor_keyclass_map_t * const m = &p11_descriptor_keyclass_map[i]; - if (m->object_class == object_class && m->key_type == key_type) - return m->descriptor; - } - - return NULL; -} - -/* - * Find the entry for a particular attribute in a descriptor. + * Look up an object's UUID in the object index table, return + * indication of whether it's present or not and the position it + * should occupy within the index table in either case. + * + * NB: *where is a position in p11_object_uuids[], not p11_objects[]. */ -static const p11_attribute_descriptor_t *p11_find_attribute_in_descriptor(const p11_descriptor_t *descriptor, - const CK_ATTRIBUTE_TYPE type) +static int p11_object_uuid_bsearch(const hal_uuid_t * const uuid, int *where) { - int i; - - if (descriptor != NULL && descriptor->attributes != NULL) - for (i = 0; i < descriptor->n_attributes; i++) - if (descriptor->attributes[i].type == type) - return &descriptor->attributes[i]; + assert(uuid != NULL && where != NULL); - return NULL; -} + int lo = -1; + int hi = p11_objects_in_use; -/* - * Check whether an attribute is marked as sensitive. If we don't - * recognize the attribute, report it as sensitive (safer than the - * alternative). - */ - -static int p11_attribute_is_sensitive(const p11_descriptor_t *descriptor, - const CK_ATTRIBUTE_TYPE type) -{ - const p11_attribute_descriptor_t *a = p11_find_attribute_in_descriptor(descriptor, type); - return a == NULL || (a->flags & P11_DESCRIPTOR_SENSITIVE) != 0; + for (;;) { + int m = (lo + hi) / 2; + if (hi == 0 || m == lo) { + *where = hi; + return 0; + } + const int cmp = hal_uuid_cmp(uuid, &p11_objects[p11_object_uuids[m]].uuid); + if (cmp < 0) + hi = m; + else if (cmp > 0) + lo = m; + else { + *where = m; + return 1; + } + } } - - -/* - * Object methods. - */ - /* * Allocate a new object. */ @@ -905,6 +968,17 @@ static CK_OBJECT_HANDLE p11_object_allocate(const handle_flavor_t flavor, if (flavor != handle_flavor_token_object && flavor != handle_flavor_session_object) return CK_INVALID_HANDLE; + int where; + + if (p11_object_uuid_bsearch(uuid, &where)) { + assert(where >= 0 && where < p11_objects_in_use); + const CK_OBJECT_HANDLE handle = p11_objects[p11_object_uuids[where]].handle; + return handle_flavor(handle) == flavor ? handle : CK_INVALID_HANDLE; + } + + if (p11_objects_in_use >= sizeof(p11_objects) / sizeof(*p11_objects)) + return CK_INVALID_HANDLE; + static unsigned next_index, nonce; const unsigned last_index = next_index; p11_object_t *object = NULL; @@ -919,13 +993,22 @@ static CK_OBJECT_HANDLE p11_object_allocate(const handle_flavor_t flavor, if (next_index == 0) ++nonce; - object = p11_objects[next_index]; + object = &p11_objects[next_index]; - } while (object.handle == CK_INVALID_HANDLE); + } while (object->handle != CK_INVALID_HANDLE); - object->handle = handle_compose(flavor, nonce, next_handle); + object->handle = handle_compose(flavor, nonce, next_index); object->uuid = *uuid; object->session = flavor == handle_flavor_session_object ? session->handle : CK_INVALID_HANDLE; + + if (where < p11_objects_in_use) + memmove(&p11_object_uuids[where + 1], &p11_object_uuids[where], + (p11_objects_in_use - where) * sizeof(*p11_object_uuids)); + + p11_object_uuids[where] = next_index; + + p11_objects_in_use++; + return object->handle; } @@ -938,16 +1021,44 @@ static void p11_object_free(p11_object_t *object) if (object == NULL) return; -#warning Should we delete session objects here? + int where; + + if (p11_objects_in_use > 0 && + p11_object_uuid_bsearch(&object->uuid, &where) && + --p11_objects_in_use > where) + memmove(&p11_object_uuids[where], &p11_object_uuids[where + 1], + (p11_objects_in_use - where) * sizeof(*p11_object_uuids)); memset(object, 0, sizeof(*object)); } /* - * Find an object. + * Find an object given its UUID. */ -static p11_object_t *p11_object_find(const CK_OBJECT_HANDLE object_handle) +static p11_object_t *p11_object_by_uuid(const hal_uuid_t * const uuid) +{ + int where; + + if (uuid == NULL || !p11_object_uuid_bsearch(uuid, &where)) + return NULL; + + assert(where >= 0 && where < p11_objects_in_use); + + p11_object_t *object = &p11_objects[p11_object_uuids[where]]; + + if (handle_flavor(object->handle) != handle_flavor_session_object && + handle_flavor(object->handle) != handle_flavor_token_object) + return NULL; + + return object; +} + +/* + * Find an object given its handle. + */ + +static p11_object_t *p11_object_by_handle(const CK_OBJECT_HANDLE object_handle) { if (handle_flavor(object_handle) != handle_flavor_session_object && handle_flavor(object_handle) != handle_flavor_token_object) @@ -966,25 +1077,27 @@ static p11_object_t *p11_object_find(const CK_OBJECT_HANDLE object_handle) return object; } +#if 0 + /* * Iterate over object handles. Start with CK_INVALID_HANDLE, * returns CK_INVALID_HANDLE when done. */ -static CK_BJECT_HANDLE p11_object_handle_iterate(const CK_OBJECT_HANDLE object_handle) +static CK_OBJECT_HANDLE p11_object_handle_iterate(const CK_OBJECT_HANDLE object_handle) { if (handle_flavor(object_handle) != handle_flavor_session_object && handle_flavor(object_handle) != handle_flavor_token_object) - return CK_HANDLE_INVALID; + return CK_INVALID_HANDLE; - for (unsigned index = session_handle == CK_INVALID_HANDLE ? 0 : handle_index(session_handle) + 1; + for (unsigned index = object_handle == CK_INVALID_HANDLE ? 0 : handle_index(object_handle) + 1; index < sizeof(p11_sessions) / sizeof(*p11_sessions); index++) if (handle_flavor(p11_sessions[index].handle) == handle_flavor_session_object || handle_flavor(p11_sessions[index].handle) == handle_flavor_token_object) return p11_sessions[index].handle; - return CK_HANDLE_INVALID; + return CK_INVALID_HANDLE; } /* @@ -996,9 +1109,11 @@ static p11_object_t *p11_object_iterate(p11_object_t *object) if (object == NULL) return NULL; - return p11_object_find(p11_object_handle_iterate(object->handle)); + return p11_object_by_handle(p11_object_handle_iterate(object->handle)); } +#endif + /* * Translate CKA_TOKEN value to handle flavor. */ @@ -1008,6 +1123,12 @@ static inline handle_flavor_t p11_object_flavor_from_cka_token(const CK_BBOOL *b return (bbool != NULL && *bbool) ? handle_flavor_token_object : handle_flavor_session_object; } +static inline hal_key_flags_t p11_object_hal_flags(const CK_OBJECT_HANDLE handle) +{ + return handle_flavor(handle) == handle_flavor_token_object ? HAL_KEY_FLAG_TOKEN : 0; +} + + /* * Open the HSM pkey object (if any) corresponding to the PKCS #11 handle. */ @@ -1016,12 +1137,13 @@ static int p11_object_pkey_open(const p11_session_t *session, const CK_OBJECT_HANDLE object_handle, hal_pkey_handle_t *pkey) { - return (session != NULL && pkey != NULL && + const p11_object_t *object = p11_object_by_handle(object_handle); + + return (session != NULL && pkey != NULL && object != NULL && hal_check(hal_rpc_pkey_open(p11_session_hal_client(session), p11_session_hal_session(session), - pkey, - p11_object_get_uuid(object_handle), - p11_object_get_hal_flags(object_handle)))); + pkey, &object->uuid, + p11_object_hal_flags(object_handle)))); } /* @@ -1032,25 +1154,15 @@ typedef enum { p11_object_access_read, p11_object_access_write } p11_object_acce static CK_RV p11_object_check_rights(const p11_session_t *session, const CK_OBJECT_HANDLE object_handle, - const p11_object_access_t rights) + const p11_object_access_t rights, + const CK_BBOOL cka_private, + const CK_BBOOL cka_token) { - hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; - CK_BBOOL cka_private; - CK_BBOOL cka_token; CK_RV rv; if (session == NULL) lose(CKR_SESSION_HANDLE_INVALID); - if (!p11_object_pkey_open(session, object_handle, &pkey)) - lose(CKR_OBJECT_HANDLE_INVALID); - - if (!p11_attribute_get_bbool(pkey, CKA_PRIVATE, &cka_private)) - cka_private = CK_TRUE; - - if (!p11_attribute_get_bbool(pkey, CKA_TOKEN, &cka_token)) - cka_token = CK_FALSE; - /* * Read-only sessions are, um, read-only. Well, except, in PKCS #11, * read-only only sort of means what you might expect. @@ -1091,122 +1203,10 @@ static CK_RV p11_object_check_rights(const p11_session_t *session, rv = CKR_OK; fail: - (void) hal_check(hal_rpc_pkey_close(pkey)); return rv; } /* - * Given a pkey handle and UUID for a newly created HSM key, attach - * attributes and create an object handle. - */ - -static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session, - const hal_pkey_handle_t pkey, - const hal_uuid_t *uuid, - const handle_flavor_t flavor, - const CK_ATTRIBUTE_PTR template, - const CK_ULONG template_length, - const p11_descriptor_t * const descriptor, - const hal_rpc_pkey_attribute_t *extra, - const unsigned extra_length) -{ - assert(session != NULL && template != NULL && descriptor != NULL && uuid != NULL && - (extra_length == 0 || extra != NULL) && - (flavor == handle_flavor_token_object || flavor == handle_flavor_session_object)); - - /* - * Populate attributes, starting with the application's template, - * which we assume has already been blessed by the API function that - * called this method. - * - * If the attribute is flagged as sensitive in the descriptor, we - * don't store it as an attribute. Generally, this only arises for - * private key components of objects created with C_CreateObject(), - * but in theory there are some corner cases in which a user could - * choose to mark a private key as extractable and not sensitive, so - * we might have to back-fill missing values in those cases if - * anyone ever thinks up a sane reason for supporting them. For - * now, assume that private keys are bloody well supposed to be - * private. - */ - - hal_rpc_pkey_attribute_t attributes[template_length + descriptor->n_attributes + extra_length]; - unsigned n = 0; - - for (int i = 0; i < template_length; i++) { - const CK_ATTRIBUTE_TYPE type = template[i].type; - const void * val = template[i].pValue; - const int len = template[i].ulValueLen; - - if (p11_attribute_is_sensitive(descriptor, type)) - continue; - - if (n >= sizeof(attributes) / sizeof(*attributes)) - lose(CKR_FUNCTION_FAILED); - - attributes[n].type = type; - attributes[n].value = val; - attributes[n].length = len; - n++; - } - - /* - * Next, add defaults from the descriptor. - */ - - for (int i = 0; i < descriptor->n_attributes; i++) { - const CK_ATTRIBUTE_TYPE type = descriptor->attributes[i].type; - const void * val = descriptor->attributes[i].value; - const int len = descriptor->attributes[i].length; - const unsigned flags = descriptor->attributes[i].flags; - - if (val == NULL && (flags & P11_DESCRIPTOR_DEFAULT_VALUE) != 0) - val = ""; - - if (val == NULL || p11_attribute_find_in_template(type, template, template_length) >= 0) - continue; - - if (n >= sizeof(attributes) / sizeof(*attributes)) - lose(CKR_FUNCTION_FAILED); - - attributes[n].type = type; - attributes[n].value = val; - attributes[n].length = len; - n++; - } - - /* - * Finally, add any attributes provided by the calling function itself. - */ - - for (int i = 0; i < extra_length; i++) { - if (n >= sizeof(attributes) / sizeof(*attributes)) - lose(CKR_FUNCTION_FAILED); - - attributes[n].type = extra[i].type; - attributes[n].value = extra[i].value; - attributes[n].length = extra[i].length; - n++; - } - - /* - * Set all those attributes. - */ - - if (!hal_check(hal_rpc_pkey_set_attributes(pkey, attributes, n))) - lose(CKR_FUNCTION_FAILED); - - /* - * Create the object handle, then we're done. - */ - - return p11_object_allocate(flavor, uuid, session); - - fail: - return CK_INVALID_HANDLE; -} - -/* * Create pkeys to go with PKCS #11 key objects loaded by C_CreateObject(). */ @@ -1218,13 +1218,14 @@ static int p11_object_create_rsa_public_key(const p11_session_t * const session, CK_OBJECT_HANDLE_PTR phObject, const hal_key_flags_t flags) { - const hal_rpc_pkey_attributes extra[] = { - {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)} + const hal_rpc_pkey_attribute_t extra[] = { + {.type = CKA_LOCAL, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)} }; hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; uint8_t keybuf[hal_rsa_key_t_size]; hal_rsa_key_t *key = NULL; + hal_uuid_t uuid; const uint8_t *cka_modulus = NULL; size_t cka_modulus_len = 0; @@ -1246,7 +1247,6 @@ static int p11_object_create_rsa_public_key(const p11_session_t * const session, if (ok) { uint8_t der[hal_rsa_public_key_to_der_len(key)]; - hal_uuid_t uuid; ok = (hal_check(hal_rsa_public_key_to_der(key, der, NULL, sizeof(der))) && hal_check(hal_rpc_pkey_load(p11_session_hal_client(session), p11_session_hal_session(session), @@ -1254,9 +1254,12 @@ static int p11_object_create_rsa_public_key(const p11_session_t * const session, &uuid, der, sizeof(der), flags))); } + if (ok) + ok = p11_attributes_set(pkey, template, template_len, descriptor, + extra, sizeof(extra)/sizeof(*extra)); + if (ok) { - *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len, - descriptor, extra, sizeof(extra)/sizeof(*extra)); + *phObject = p11_object_allocate(flavor, &uuid, session); ok = *phObject != CK_INVALID_HANDLE; } @@ -1276,14 +1279,15 @@ static int p11_object_create_ec_public_key(const p11_session_t * const session, CK_OBJECT_HANDLE_PTR phObject, const hal_key_flags_t flags) { - const hal_rpc_pkey_attributes extra[] = { - {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)} + const hal_rpc_pkey_attribute_t extra[] = { + {.type = CKA_LOCAL, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)} }; hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; uint8_t keybuf[hal_ecdsa_key_t_size]; hal_ecdsa_key_t *key = NULL; hal_curve_name_t curve; + hal_uuid_t uuid; const uint8_t *cka_ec_point = NULL; size_t cka_ec_point_len = 0; const uint8_t *cka_ec_params = NULL; size_t cka_ec_params_len = 0; @@ -1305,7 +1309,6 @@ static int p11_object_create_ec_public_key(const p11_session_t * const session, if (ok) { uint8_t der[hal_ecdsa_public_key_to_der_len(key)]; - hal_uuid_t uuid; ok = (hal_check(hal_ecdsa_public_key_to_der(key, der, NULL, sizeof(der))) && hal_check(hal_rpc_pkey_load(p11_session_hal_client(session), p11_session_hal_session(session), @@ -1313,9 +1316,12 @@ static int p11_object_create_ec_public_key(const p11_session_t * const session, &uuid, der, sizeof(der), flags))); } + if (ok) + ok = p11_attributes_set(pkey, template, template_len, descriptor, + extra, sizeof(extra)/sizeof(*extra)); + if (ok) { - *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len, - descriptor, extra, sizeof(extra)/sizeof(*extra)); + *phObject = p11_object_allocate(flavor, &uuid, session); ok = *phObject != CK_INVALID_HANDLE; } @@ -1335,10 +1341,10 @@ static int p11_object_create_rsa_private_key(const p11_session_t * const session CK_OBJECT_HANDLE_PTR phObject, const hal_key_flags_t flags) { - const hal_rpc_pkey_attributes extra[] = { - {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}, - {.type = CKA_ALWAYS_SENSITIVE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}, - {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)} + const hal_rpc_pkey_attribute_t extra[] = { + {.type = CKA_LOCAL, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)}, + {.type = CKA_ALWAYS_SENSITIVE, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)}, + {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)} }; hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; @@ -1394,9 +1400,12 @@ static int p11_object_create_rsa_private_key(const p11_session_t * const session memset(keybuf, 0, sizeof(keybuf)); + if (ok) + ok = p11_attributes_set(pkey, template, template_len, descriptor, + extra, sizeof(extra)/sizeof(*extra)); + if (ok) { - *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len, - descriptor, extra, sizeof(extra)/sizeof(*extra)); + *phObject = p11_object_allocate(flavor, &uuid, session); ok = *phObject != CK_INVALID_HANDLE; } @@ -1416,16 +1425,17 @@ static int p11_object_create_ec_private_key(const p11_session_t * const session, CK_OBJECT_HANDLE_PTR phObject, const hal_key_flags_t flags) { - const hal_rpc_pkey_attributes extra[] = { - {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}, - {.type = CKA_ALWAYS_SENSITIVE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}, - {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)} + const hal_rpc_pkey_attribute_t extra[] = { + {.type = CKA_LOCAL, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)}, + {.type = CKA_ALWAYS_SENSITIVE, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)}, + {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)} }; hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; uint8_t keybuf[hal_ecdsa_key_t_size]; hal_ecdsa_key_t *key = NULL; hal_curve_name_t curve; + hal_uuid_t uuid; const uint8_t *cka_value = NULL; size_t cka_value_len = 0; const uint8_t *cka_ec_point = NULL; size_t cka_ec_point_len = 0; @@ -1453,7 +1463,6 @@ static int p11_object_create_ec_private_key(const p11_session_t * const session, if (ok) { uint8_t der[hal_ecdsa_private_key_to_der_len(key)]; - hal_uuid_t uuid; ok = (hal_check(hal_ecdsa_private_key_to_der(key, der, NULL, sizeof(der))) && hal_check(hal_rpc_pkey_load(p11_session_hal_client(session), p11_session_hal_session(session), @@ -1464,9 +1473,12 @@ static int p11_object_create_ec_private_key(const p11_session_t * const session, memset(keybuf, 0, sizeof(keybuf)); + if (ok) + ok = p11_attributes_set(pkey, template, template_len, descriptor, + extra, sizeof(extra)/sizeof(*extra)); + if (ok) { - *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len, - descriptor, extra, sizeof(extra)/sizeof(*extra)); + *phObject = p11_object_allocate(flavor, &uuid, session); ok = *phObject != CK_INVALID_HANDLE; } @@ -1507,12 +1519,12 @@ static p11_session_t *p11_session_allocate(void) if (next_index == 0) ++nonce; - session = p11_sessions[next_index]; + session = &p11_sessions[next_index]; - } while (session.handle == CK_INVALID_HANDLE); + } while (session->handle != CK_INVALID_HANDLE); memset(session, 0, sizeof(*session)); - session.handle = handle_compose(handle_flavor_session, nonce, next_handle); + session->handle = handle_compose(handle_flavor_session, nonce, next_index); p11_sessions_in_use++; return session; } @@ -1576,7 +1588,7 @@ static p11_session_t *p11_session_find(const CK_SESSION_HANDLE session_handle) static CK_SESSION_HANDLE p11_session_handle_iterate(const CK_SESSION_HANDLE session_handle) { if (handle_flavor(session_handle) != handle_flavor_session) - return CK_HANDLE_INVALID; + return CK_INVALID_HANDLE; for (unsigned index = session_handle == CK_INVALID_HANDLE ? 0 : handle_index(session_handle) + 1; index < sizeof(p11_sessions) / sizeof(*p11_sessions); @@ -1584,7 +1596,7 @@ static CK_SESSION_HANDLE p11_session_handle_iterate(const CK_SESSION_HANDLE sess if (handle_flavor(p11_sessions[index].handle) == handle_flavor_session) return p11_sessions[index].handle; - return CK_HANDLE_INVALID; + return CK_INVALID_HANDLE; } /* @@ -1995,21 +2007,22 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session, lose(CKR_FUNCTION_FAILED); const hal_rpc_pkey_attribute_t extra[] = { - {.type = CKA_LOCAL, - .value = &const_CK_TRUE, .length = sizeof(const_CK_TRUE)}, - {.type = CKA_KEY_GEN_MECHANISM, - .value = &mechanism->mechanism, .length = sizeof(mechanism->mechanism)}, - {.type = CKA_MODULUS, - value = modulus, .length = modulus_len} + {.type = CKA_LOCAL, + .value = &const_CK_TRUE, .length = sizeof(const_CK_TRUE)}, + {.type = CKA_KEY_GEN_MECHANISM, + .value = &pMechanism->mechanism, .length = sizeof(pMechanism->mechanism)}, + {.type = CKA_MODULUS, + .value = modulus, .length = modulus_len} }; - *phPrivateKey = p11_object_create(session, private_pkey, &private_uuid, private_handle_flavor, - pPrivateKeyTemplate, ulPrivateKeyAttributeCount, - private_descriptor, extra, sizeof(extra)/sizeof(*extra)); + if (!p11_attributes_set(private_pkey, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, + private_descriptor, extra, sizeof(extra)/sizeof(*extra)) || + !p11_attributes_set(public_pkey, pPublicKeyTemplate, ulPublicKeyAttributeCount, + public_descriptor, extra, sizeof(extra)/sizeof(*extra))) + lose(CKR_FUNCTION_FAILED); - *phPublicKey = p11_object_create(session, public_handle_flavor, - pPublicKeyTemplate, ulPublicKeyAttributeCount, - public_descriptor, extra, sizeof(extra)/sizeof(*extra)); + *phPrivateKey = p11_object_allocate(private_handle_flavor, &private_uuid, session); + *phPublicKey = p11_object_allocate(public_handle_flavor, &public_uuid, session); if (*phPrivateKey == CK_INVALID_HANDLE || *phPublicKey == CK_INVALID_HANDLE) lose(CKR_FUNCTION_FAILED); @@ -2094,23 +2107,24 @@ static CK_RV generate_keypair_ec(p11_session_t *session, lose(CKR_FUNCTION_FAILED); const hal_rpc_pkey_attribute_t extra[] = { - {.type = CKA_LOCAL, - .value = &const_CK_TRUE, .length = sizeof(const_CK_TRUE)}, - {.type = CKA_KEY_GEN_MECHANISM, - .value = &mechanism->mechanism, .length = sizeof(mechanism->mechanism)}, - {.type = CKA_EC_PARAMS, - value = params, .length = params_len}, - {.type = CKA_EC_POINT, - value = point, .length = sizeof(point)} + {.type = CKA_LOCAL, + .value = &const_CK_TRUE, .length = sizeof(const_CK_TRUE)}, + {.type = CKA_KEY_GEN_MECHANISM, + .value = &pMechanism->mechanism, .length = sizeof(pMechanism->mechanism)}, + {.type = CKA_EC_PARAMS, + .value = params, .length = params_len}, + {.type = CKA_EC_POINT, + .value = point, .length = sizeof(point)} }; - *phPrivateKey = p11_object_create(session, private_pkey, &private_uuid, private_handle_flavor, - pPrivateKeyTemplate, ulPrivateKeyAttributeCount, - private_descriptor, extra, sizeof(extra)/sizeof(*extra) - 1); + if (!p11_attributes_set(private_pkey, pPrivateKeyTemplate, ulPrivateKeyAttributeCount, + private_descriptor, extra, sizeof(extra)/sizeof(*extra) - 1) || + !p11_attributes_set(public_pkey, pPublicKeyTemplate, ulPublicKeyAttributeCount, + public_descriptor, extra, sizeof(extra)/sizeof(*extra))) + lose(CKR_FUNCTION_FAILED); - *phPublicKey = p11_object_create(session, public_handle_flavor, - pPublicKeyTemplate, ulPublicKeyAttributeCount, - public_descriptor, extra, sizeof(extra)/sizeof(*extra)); + *phPrivateKey = p11_object_allocate(private_handle_flavor, &private_uuid, session); + *phPublicKey = p11_object_allocate(public_handle_flavor, &public_uuid, session); if (*phPrivateKey == CK_INVALID_HANDLE || *phPublicKey == CK_INVALID_HANDLE) lose(CKR_FUNCTION_FAILED); @@ -2318,36 +2332,37 @@ static void digest_cleanup(hal_hash_handle_t *handle) } /* - * Compute the length of a signature based on the key. We could get - * this via the RPC API, but its probably faster to look in the local - * attribute database. Rewrite this later if this proves incorrect. + * Compute the length of a signature based on the key. */ -static int get_signature_len(const CK_OBJECT_HANDLE object_handle, - const hal_pkey_handle_t pkey, +static int get_signature_len(const hal_pkey_handle_t pkey, size_t *signature_len) { assert(signature_len != NULL); - CK_KEY_TYPE cka_key_type; + hal_rpc_pkey_attribute_t attribute; + uint8_t attribute_buffer[sizeof(CK_KEY_TYPE)]; hal_curve_name_t curve; CK_BYTE oid[20]; - CK_ULONG len; - if (!p11_attribute_get_ulong(session, object_handle, CKA_KEY_TYPE, &cka_key_type)) + attribute.type = CKA_KEY_TYPE; + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, &attribute, 1, + attribute_buffer, sizeof(attribute_buffer)))) return 0; - switch (cka_key_type) { + switch (*(CK_KEY_TYPE*)attribute.value) { case CKK_RSA: - if (!p11_attribute_get(session, object_handle, CKA_MODULUS, NULL, &len, 0)) + attribute.type = CKA_MODULUS; + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, &attribute, 1, NULL, 0))) return 0; - *signature_len = len; + *signature_len = attribute.length; return 1; case CKK_EC: - if (!p11_attribute_get(session, object_handle, CKA_EC_PARAMS, oid, &len, sizeof(oid)) || - !ec_curve_oid_to_name(oid, len, &curve)) + attribute.type = CKA_EC_PARAMS; + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, &attribute, 1, oid, sizeof(oid))) || + !ec_curve_oid_to_name(attribute.value, attribute.length, &curve)) return 0; switch (curve) { case HAL_CURVE_P256: *signature_len = 64; return 1; @@ -2379,7 +2394,7 @@ static CK_RV sign_hal_rpc(p11_session_t *session, if (!p11_object_pkey_open(session, session->sign_key_handle, &pkey)) lose(CKR_FUNCTION_FAILED); - if (!get_signature_len(session->sign_key_handle, pkey, &signature_len)) + if (!get_signature_len(pkey, &signature_len)) lose(CKR_FUNCTION_FAILED); rv = pSignature != NULL && signature_len > *pulSignatureLen ? CKR_BUFFER_TOO_SMALL : CKR_OK; @@ -2560,7 +2575,7 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved) * Destroy all current sessions. */ - p11_session_delete_all(); + p11_session_free_all(); /* * At this point we're pretty well committed to shutting down, so @@ -2795,12 +2810,17 @@ CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) { ENTER_PUBLIC_FUNCTION(C_CloseSession); - CK_RV rv; + p11_session_t *session; + CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); - rv = p11_session_delete(hSession); + if ((session = p11_session_find(hSession)) == NULL) + lose(CKR_SESSION_HANDLE_INVALID); + + p11_session_free(session); + fail: mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -2813,7 +2833,7 @@ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) mutex_lock_or_return_failure(p11_global_mutex); - p11_session_delete_all(); + p11_session_free_all(); return mutex_unlock(p11_global_mutex); } @@ -2924,6 +2944,7 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) ENTER_PUBLIC_FUNCTION(C_Logout); const hal_client_handle_t client = {HAL_HANDLE_NONE}; + p11_session_t *session = NULL; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -2934,7 +2955,7 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) * anything special for "this" session. */ - if (p11_session_find(hSession) == NULL) + if ((session = p11_session_find(hSession)) == NULL) lose(CKR_SESSION_HANDLE_INVALID); if (logged_in_as == not_logged_in) @@ -2950,7 +2971,7 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) const hal_session_handle_t session_handle_none = {HAL_HANDLE_NONE}; - const hal_rpc_pkey_attribute attrs[] = { + const hal_rpc_pkey_attribute_t attrs[] = { {.type = CKA_PRIVATE, .value = &const_CK_TRUE, .length = sizeof(const_CK_TRUE)} }; @@ -2965,12 +2986,13 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, 0, attrs, sizeof(attrs)/sizeof(*attrs), - uuids, &n, sizeof(uuids)/sizeof(*uuuids), - &uuids[sizeof(uuids)/sizeof(*uuuids) - 1])); + uuids, &n, sizeof(uuids)/sizeof(*uuids), + &uuids[sizeof(uuids)/sizeof(*uuids) - 1])); if (rv != CKR_OK) goto fail; for (int i = 0; i < n; i++) { + p11_object_free(p11_object_by_uuid(&uuids[i])); hal_pkey_handle_t pkey; rv = p11_whine_from_hal(hal_rpc_pkey_open(p11_session_hal_client(session), session_handle_none, &pkey, &uuids[i], 0)); @@ -2982,17 +3004,7 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) } } - if (n > 0) { - for (CK_OBJECT_HANDLE handle = p11_object_handle_iterate(CK_INVALID_HANDLE); - handle != CK_INVALID_HANDLE; handle = p11_object_handle_iterate(handle)) { - p11_object_t *object = p11_object_find(handle); - assert(object != NULL); - if (bsearch(&object->uuid, uuids, n, sizeof(*uuids), hal_uuid_cmp) != NULL) - p11_object_free(object); - } - } - - } while (n == sizeof(uuids)/sizeof(*uuuids)); + } while (n == sizeof(uuids)/sizeof(*uuids)); memset(uuids, 0, sizeof(uuids)); do { @@ -3002,22 +3014,15 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, HAL_KEY_FLAG_TOKEN, attrs, sizeof(attrs)/sizeof(*attrs), - uuids, &n, sizeof(uuids)/sizeof(*uuuids), - &uuids[sizeof(uuids)/sizeof(*uuuids) - 1])); + uuids, &n, sizeof(uuids)/sizeof(*uuids), + &uuids[sizeof(uuids)/sizeof(*uuids) - 1])); if (rv != CKR_OK) goto fail; - if (n > 0) { - for (CK_OBJECT_HANDLE handle = p11_object_handle_iterate(CK_INVALID_HANDLE); - handle != CK_INVALID_HANDLE; handle = p11_object_handle_iterate(handle)) { - p11_object_t *object = p11_object_find(handle); - assert(object != NULL); - if (bsearch(&object->uuid, uuids, n, sizeof(*uuids), hal_uuid_cmp) != NULL) - p11_object_free(object); - } - } + for (int i = 0; i < n; i++) + p11_object_free(p11_object_by_uuid(&uuids[i])); - } while (n == sizeof(uuids)/sizeof(*uuuids)); + } while (n == sizeof(uuids)/sizeof(*uuids)); for (p11_session_t *session = p11_session_iterate(NULL); session != NULL; session = p11_session_iterate(session)) { @@ -3054,7 +3059,6 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, { ENTER_PUBLIC_FUNCTION(C_CreateObject); - CK_OBJECT_HANDLE handle = CK_INVALID_HANDLE; p11_session_t *session; CK_RV rv; @@ -3145,7 +3149,14 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, { ENTER_PUBLIC_FUNCTION(C_DestroyObject); + uint8_t attributes_buffer[2 * sizeof(CK_BBOOL)]; hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; + hal_rpc_pkey_attribute_t attributes[] = { + [0].type = CKA_PRIVATE, + [1].type = CKA_TOKEN + }; + CK_BBOOL cka_private; + CK_BBOOL cka_token; p11_session_t *session; CK_RV rv = CKR_OK; @@ -3153,20 +3164,29 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, session = p11_session_find(hSession); - if ((rv = p11_object_check_rights(session, hObject, p11_object_access_write)) != CKR_OK) - goto fail; - if (!p11_object_pkey_open(session, hObject, &pkey)) lose(CKR_FUNCTION_FAILED); - if (!hal_check(hal_rpc_pkey_delete(pkey))) { - (void) hal_rpc_pkey_close(pkey); + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, attributes, sizeof(attributes)/sizeof(*attributes), + attributes_buffer, sizeof(attributes_buffer)))) + lose(CKR_KEY_HANDLE_INVALID); + + cka_private = *(CK_BBOOL*) attributes[0].value; + cka_token = *(CK_BBOOL*) attributes[1].value; + + rv = p11_object_check_rights(session, hObject, p11_object_access_write, cka_private, cka_token); + + if (rv != CKR_OK) + goto fail; + + if (!hal_check(hal_rpc_pkey_delete(pkey))) lose(CKR_FUNCTION_FAILED); - } - p11_object_free(p11_object_find(hObject)); + p11_object_free(p11_object_by_handle(hObject)); fail: + if (pkey.handle != HAL_HANDLE_NONE) + (void) hal_rpc_pkey_close(pkey); mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -3177,12 +3197,14 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, { ENTER_PUBLIC_FUNCTION(C_GetAttributeValue); - p11_session_t *session; + hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; const p11_descriptor_t *descriptor = NULL; - CK_BBOOL cka_sensitive, cka_extractable; + CK_BBOOL cka_extractable, cka_sensitive; CK_OBJECT_CLASS cka_class; - CK_KEY_TYPE cka_key_type; + CK_BBOOL cka_private; + CK_BBOOL cka_token; int sensitive_object = 0; + p11_session_t *session; CK_RV rv; mutex_lock_or_return_failure(p11_global_mutex); @@ -3192,70 +3214,122 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, session = p11_session_find(hSession); - if ((rv = p11_object_check_rights(session, hObject, p11_object_access_read)) != CKR_OK) - goto fail; - - if (!p11_attribute_get_ulong(session, hObject, CKA_CLASS, &cka_class)) + if (!p11_object_pkey_open(session, hObject, &pkey)) lose(CKR_OBJECT_HANDLE_INVALID); - switch (cka_class) { + { + hal_rpc_pkey_attribute_t attributes[] = { + [0].type = CKA_CLASS, + [1].type = CKA_PRIVATE, + [2].type = CKA_TOKEN + }; + uint8_t attributes_buffer[sizeof(CK_OBJECT_CLASS) + 2 * sizeof(CK_BBOOL)]; - case CKO_PRIVATE_KEY: - case CKO_SECRET_KEY: - if (!p11_attribute_get_bbool(session, hObject, CKA_EXTRACTABLE, &cka_extractable) || - !p11_attribute_get_bbool(session, hObject, CKA_SENSITIVE, &cka_sensitive)) + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, + attributes, sizeof(attributes)/sizeof(*attributes), + attributes_buffer, sizeof(attributes_buffer)))) lose(CKR_OBJECT_HANDLE_INVALID); - sensitive_object = cka_sensitive || !cka_extractable; + cka_class = *(CK_OBJECT_CLASS*) attributes[0].value; + cka_private = *(CK_BBOOL*) attributes[1].value; + cka_token = *(CK_BBOOL*) attributes[2].value; - /* Fall through */ + rv = p11_object_check_rights(session, hObject, p11_object_access_read, cka_private, cka_token); - case CKO_PUBLIC_KEY: - if (!p11_attribute_get_ulong(session, hObject, CKA_KEY_TYPE, &cka_key_type)) + if (rv != CKR_OK) + goto fail; + } + + if (cka_class == CKO_PRIVATE_KEY || cka_class == CKO_SECRET_KEY) { + hal_rpc_pkey_attribute_t attributes[] = { + [0].type = CKA_EXTRACTABLE, + [1].type = CKA_SENSITIVE + }; + uint8_t attributes_buffer[sizeof(CK_OBJECT_CLASS) + sizeof(CK_KEY_TYPE)]; + + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, + attributes, sizeof(attributes)/sizeof(*attributes), + attributes_buffer, sizeof(attributes_buffer)))) lose(CKR_OBJECT_HANDLE_INVALID); - descriptor = p11_descriptor_from_key_type(cka_class, cka_key_type); + + cka_extractable = *(CK_BBOOL*) attributes[0].value; + cka_sensitive = *(CK_BBOOL*) attributes[1].value; + + sensitive_object = cka_sensitive || !cka_extractable; } - if (!sql_check_ok(sql_prepare(&q, select_format, flavor)) || - !sql_check_ok(sqlite3_bind_int64(q, 1, hObject))) - lose(CKR_FUNCTION_FAILED); + { + hal_rpc_pkey_attribute_t attributes[ulCount]; - rv = CKR_OK; + memset(attributes, 0, sizeof(attributes)); - for (int i = 0; i < ulCount; i++) { + for (int i = 0; i < ulCount; i++) + attributes[i].type = pTemplate[i].type; - if (sensitive_object && p11_attribute_is_sensitive(descriptor, pTemplate[i].type)) { - pTemplate[i].ulValueLen = -1; - rv = CKR_ATTRIBUTE_SENSITIVE; - } + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, + attributes, sizeof(attributes)/sizeof(*attributes), + NULL, 0))) + lose(CKR_OBJECT_HANDLE_INVALID); - else if (!sql_check_ok(sqlite3_reset(q)) || - !sql_check_ok(sqlite3_bind_int64(q, 2, pTemplate[i].type)) || - (ret = sqlite3_step(q)) != SQLITE_ROW) { - if (ret != SQLITE_DONE) - sql_whine_step(); - pTemplate[i].ulValueLen = -1; - rv = CKR_ATTRIBUTE_TYPE_INVALID; - } + rv = CKR_OK; - else if (pTemplate[i].pValue == NULL) { - pTemplate[i].ulValueLen = sqlite3_column_bytes(q, 0); - } + size_t attributes_buffer_len = 0; - else if (pTemplate[i].ulValueLen >= sqlite3_column_bytes(q, 0)) { - pTemplate[i].ulValueLen = sqlite3_column_bytes(q, 0); - memcpy(pTemplate[i].pValue, sqlite3_column_blob(q, 0), pTemplate[i].ulValueLen); + for (int i = 0; i < ulCount; i++) { + if (sensitive_object && p11_attribute_is_sensitive(descriptor, pTemplate[i].type)) { + pTemplate[i].ulValueLen = -1; + rv = CKR_ATTRIBUTE_SENSITIVE; + continue; + } + if (attributes[i].length == 0) { + pTemplate[i].ulValueLen = -1; + rv = CKR_ATTRIBUTE_TYPE_INVALID; + continue; + } + if (pTemplate[i].pValue == NULL) { + pTemplate[i].ulValueLen = attributes[i].length; + continue; + } + if (pTemplate[i].ulValueLen < attributes[i].length) { + pTemplate[i].ulValueLen = -1; + rv = CKR_BUFFER_TOO_SMALL; + continue; + } + attributes_buffer_len += attributes[i].length; } - else { - pTemplate[i].ulValueLen = -1; - rv = CKR_BUFFER_TOO_SMALL; - } + if (attributes_buffer_len == 0) + goto fail; + + uint8_t attributes_buffer[attributes_buffer_len]; + unsigned n = 0; + + for (int i = 0; i < ulCount; i++) + if (pTemplate[i].pValue != NULL && pTemplate[i].ulValueLen != -1) + attributes[n++].type = pTemplate[i].type; + + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, attributes, n, + attributes_buffer, sizeof(attributes_buffer)))) + lose(CKR_OBJECT_HANDLE_INVALID); + + for (int i = 0; i < n; i++) { + int j = p11_attribute_find_in_template(attributes[i].type, pTemplate, ulCount); + + if (j < 0 || pTemplate[j].ulValueLen == -1 || pTemplate[j].ulValueLen < attributes[i].length) + lose(CKR_FUNCTION_FAILED); + memcpy(pTemplate[j].pValue, attributes[i].value, attributes[i].length); + pTemplate[j].ulValueLen = attributes[i].length; + } } fail: - sqlite3_finalize(q); + if (pkey.handle != HAL_HANDLE_NONE) { + if (rv == CKR_OK) + rv = p11_whine_from_hal(hal_rpc_pkey_close(pkey)); + else + (void) hal_rpc_pkey_close(pkey); + } mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -3265,139 +3339,76 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, { ENTER_PUBLIC_FUNCTION(C_FindObjectsInit); - static const char select_missing[] = - " WITH" - " known AS (SELECT token_object_id FROM object WHERE token_object_id IS NOT NULL)" - " SELECT token_object_id FROM token_object WHERE token_object_id NOT IN known"; - - static const char insert_missing[] = - " INSERT INTO object (object_handle, token_object_id) VALUES (?1, ?2)"; - - static const char create_format[] = - " CREATE TEMPORARY TABLE findobjects_%lu AS" - " SELECT object_id FROM object NATURAL LEFT JOIN session" - " WHERE session_handle IS NULL OR session_handle = ?1"; - - static const char drop_format[] = - " DROP TABLE IF EXISTS findobjects_%lu"; - - static const char delete_format[] = - " WITH" - " matches AS (SELECT object_id" - " FROM object NATURAL JOIN session_attribute" - " WHERE type = ?1 AND value = ?2" - " UNION" - " SELECT object_id" - " FROM object NATURAL JOIN token_attribute" - " WHERE type = ?1 AND value = ?2)" - " DELETE FROM findobjects_%lu WHERE object_id NOT IN matches"; - - static const char select_format[] = - " SELECT object_handle FROM findobjects_%lu NATURAL JOIN object ORDER BY object_id"; - + const size_t attributes_len = sizeof(hal_rpc_pkey_attribute_t) * (ulCount + 1); + size_t len = attributes_len; + CK_BBOOL *cka_private = NULL; + CK_BBOOL *cka_token = NULL; p11_session_t *session; - sqlite3_stmt *q1 = NULL, *q2 = NULL; CK_RV rv = CKR_OK; - int i, ret; + uint8_t *mem; mutex_lock_or_return_failure(p11_global_mutex); if ((session = p11_session_find(hSession)) == NULL) lose(CKR_SESSION_HANDLE_INVALID); - if (ulCount > 0 && pTemplate == NULL) + if (ulCount > 0 && pTemplate == NULL) lose(CKR_ARGUMENTS_BAD); if (session->find_query != NULL) lose(CKR_OPERATION_ACTIVE); - /* - * Assign handles to any token objects that don't have them yet. - */ + assert(!session->find_query_token && !session->find_query_session); - if (!sql_check_ok(sql_prepare(&q1, select_missing)) || - !sql_check_ok(sql_prepare(&q2, insert_missing))) - lose(CKR_FUNCTION_FAILED); + for (int i = 0; i < ulCount; i++) { + if (pTemplate[i].pValue == NULL || pTemplate[i].ulValueLen == 0) + lose(CKR_ARGUMENTS_BAD); + len += pTemplate[i].ulValueLen; + } - while ((ret = sqlite3_step(q1)) == SQLITE_ROW) { - sqlite3_int64 token_object_id = sqlite3_column_int64(q1, 0); - CK_OBJECT_HANDLE object_handle = p11_allocate_unused_handle(handle_flavor_token_object); + if ((mem = malloc(len)) == NULL) + lose(CKR_HOST_MEMORY); - if (!sql_check_ok(sqlite3_reset(q2)) || - !sql_check_ok(sqlite3_bind_int64(q2, 1, object_handle)) || - !sql_check_ok(sqlite3_bind_int64(q2, 2, token_object_id)) || - !sql_check_done(sqlite3_step(q2))) - lose(CKR_FUNCTION_FAILED); - } + session->find_query = (hal_rpc_pkey_attribute_t *) mem; + mem += attributes_len; - if (ret != SQLITE_DONE) { - sql_whine_step(); - lose(CKR_FUNCTION_FAILED); + for (int i = 0; i < ulCount; i++) { + len = pTemplate[i].ulValueLen; + session->find_query[i].type = pTemplate[i].type; + session->find_query[i].value = mem; + session->find_query[i].length = len; + memcpy(mem, pTemplate[i].pValue, len); + mem += len; } - /* - * Create a temporary table to hold this session's FindObjects - * state. Populate this with every object this session knows about, - * then prune based on login status and whatever filter attributes - * the caller supplied. - */ + cka_private = p11_attribute_find_value_in_template(CKA_PRIVATE, pTemplate, ulCount); + cka_token = p11_attribute_find_value_in_template(CKA_TOKEN, pTemplate, ulCount); - if (!sql_check_ok(sql_finalize_and_clear(&q1)) || - !sql_check_ok(sql_finalize_and_clear(&q2)) || - !sql_check_ok(sql_prepare(&q1, drop_format, hSession)) || - !sql_check_done(sqlite3_step(q1)) || - !sql_check_ok(sql_prepare(&q2, create_format, hSession)) || - !sql_check_ok(sqlite3_bind_int64(q2, 1, hSession)) || - !sql_check_done(sqlite3_step(q2)) || - !sql_check_ok(sql_finalize_and_clear(&q1)) || - !sql_check_ok(sql_finalize_and_clear(&q2)) || - !sql_check_ok(sql_prepare(&q1, delete_format, hSession))) - lose(CKR_FUNCTION_FAILED); + session->find_query_n = ulCount; + session->find_query_token = cka_token == NULL || *cka_token; + session->find_query_session = cka_token == NULL || !*cka_token; + memset(&session->find_query_previous_uuid, 0, sizeof(session->find_query_previous_uuid)); /* - * If we're not logged in as the regular user, run an extra filter - * cycle to remove all private objects before we get to the - * caller-supplied template. + * Quietly enforce object privacy even if template tries to bypass, + * per PCKS #11 specification. */ - if (logged_in_as != logged_in_as_user) { - if (!sql_check_ok(sqlite3_bind_int64(q1, 1, CKA_PRIVATE)) || - !sql_check_ok(sqlite3_bind_blob( q1, 2, - &const_CK_FALSE, - sizeof(const_CK_FALSE), - NULL)) || - !sql_check_done(sqlite3_step(q1))) - lose(CKR_FUNCTION_FAILED); + if (logged_in_as != logged_in_as_user && cka_private == NULL) { + session->find_query[ulCount].type = CKA_PRIVATE; + session->find_query[ulCount].value = &const_CK_FALSE; + session->find_query[ulCount].length = sizeof(const_CK_FALSE); + session->find_query_n++; } - /* - * Filter through the caller-supplied template. - * - * NB: This doesn't support some of the more obscure searches, such - * as searches for sessions or hardware features. Too much rope - * already, worry about those if we ever really need them. - */ - - for (i = 0; i < ulCount; i++) - if (!sql_check_ok(sqlite3_reset(q1)) || - !sql_check_ok(sqlite3_bind_int64(q1, 1, pTemplate[i].type)) || - !sql_check_ok(sqlite3_bind_blob( q1, 2, pTemplate[i].pValue, - pTemplate[i].ulValueLen, NULL)) || - !sql_check_done(sqlite3_step(q1))) - lose(CKR_FUNCTION_FAILED); - - /* - * Stash a prepared query in the session object which will return - * whatever object handles survived all that filtering. - */ - - if (!sql_check_ok(sql_prepare(&session->find_query, select_format, hSession))) - lose(CKR_FUNCTION_FAILED); - session->find_query_done = 0; + if (logged_in_as != logged_in_as_user && cka_private != NULL && *cka_private) { + int i = p11_attribute_find_in_template(CKA_PRIVATE, pTemplate, ulCount); + assert(i >= 0 && i < ulCount); + session->find_query[i].value = &const_CK_FALSE; + session->find_query[i].length = sizeof(const_CK_FALSE); + } fail: - sqlite3_finalize(q1); - sqlite3_finalize(q2); mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -3408,8 +3419,8 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, { ENTER_PUBLIC_FUNCTION(C_FindObjects); + hal_uuid_t previous_uuid = {{0}}; p11_session_t *session; - int i, ret = SQLITE_OK; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3423,35 +3434,55 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, if (phObject == NULL || pulObjectCount == NULL) lose(CKR_ARGUMENTS_BAD); - /* - * C_FindObjectsInit() did all the heavy lifting, we just have to - * return the resulting handles. - */ + *pulObjectCount = 0; - i = 0; + while (*pulObjectCount < ulMaxObjectCount && + (session->find_query_token || session->find_query_session)) { + hal_uuid_t uuids[ulMaxObjectCount - *pulObjectCount]; + handle_flavor_t flavor; + hal_key_flags_t flags; + unsigned n; - if (!session->find_query_done) - while (i < ulMaxObjectCount && (ret = sqlite3_step(session->find_query)) == SQLITE_ROW) - phObject[i++] = (CK_OBJECT_HANDLE) sqlite3_column_int64(session->find_query, 0); + if (session->find_query_token) { + flavor = handle_flavor_token_object; + flags = HAL_KEY_FLAG_TOKEN; + } + else { + flavor = handle_flavor_session_object; + flags = 0; + } - switch (ret) { + rv = p11_whine_from_hal(hal_rpc_pkey_match(p11_session_hal_client(session), + p11_session_hal_session(session), + HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, flags, + session->find_query, session->find_query_n, + uuids, &n, sizeof(uuids)/sizeof(*uuids), + &previous_uuid)); + if (rv != CKR_OK) + goto fail; - case SQLITE_DONE: - session->find_query_done = 1; - break; + for (int i = 0; i < n; i++) { + phObject[*pulObjectCount] = p11_object_allocate(flavor, &uuids[i], session); + if (phObject[*pulObjectCount] == CK_INVALID_HANDLE) + lose(CKR_FUNCTION_FAILED); + ++*pulObjectCount; + } - case SQLITE_OK: - case SQLITE_ROW: - break; + if (n == sizeof(uuids)/sizeof(*uuids)) { + memcpy(&session->find_query_previous_uuid, &uuids[n - 1], + sizeof(session->find_query_previous_uuid)); + } - default: - sql_whine_step(); - lose(CKR_FUNCTION_FAILED); + else { + memset(&session->find_query_previous_uuid, 0, sizeof(session->find_query_previous_uuid)); + if (session->find_query_token) + session->find_query_token = 0; + else + session->find_query_session = 0; + } } - *pulObjectCount = i; - fail: mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -3460,11 +3491,7 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) { ENTER_PUBLIC_FUNCTION(C_FindObjectsFinal); - static const char drop_format[] = - " DROP TABLE IF EXISTS findobjects_%lu"; - p11_session_t *session; - sqlite3_stmt *q = NULL; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3475,17 +3502,15 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) if (session->find_query == NULL) lose(CKR_OPERATION_NOT_INITIALIZED); - /* - * Clean up result query and temporary table. - */ + free(session->find_query); - if (!sql_check_ok(sql_finalize_and_clear(&session->find_query)) || - !sql_check_ok(sql_prepare(&q, drop_format, hSession)) || - !sql_check_done(sqlite3_step(q))) - lose(CKR_FUNCTION_FAILED); + session->find_query = NULL; + session->find_query_n = 0; + session->find_query_token = 0; + session->find_query_session = 0; + memset(&session->find_query_previous_uuid, 0, sizeof(session->find_query_previous_uuid)); fail: - sqlite3_finalize(q); mutex_unlock_return_with_rv(rv, p11_global_mutex); } @@ -3662,10 +3687,19 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, { ENTER_PUBLIC_FUNCTION(C_SignInit); + uint8_t attributes_buffer[sizeof(CK_OBJECT_CLASS) + sizeof(CK_KEY_TYPE) + 3 * sizeof(CK_BBOOL)]; + hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; + hal_rpc_pkey_attribute_t attributes[] = { + [0].type = CKA_KEY_TYPE, + [1].type = CKA_SIGN, + [2].type = CKA_PRIVATE, + [3].type = CKA_TOKEN + }; + CK_KEY_TYPE cka_key_type; + CK_BBOOL cka_sign; + CK_BBOOL cka_private; + CK_BBOOL cka_token; p11_session_t *session; - CK_OBJECT_CLASS key_class; - CK_KEY_TYPE key_type; - CK_BBOOL key_sign; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3676,19 +3710,28 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, if (pMechanism == NULL) lose(CKR_ARGUMENTS_BAD); - if (session->sign_key_handle != CK_INVALID_HANDLE || session->sign_digest_algorithm != HAL_DIGEST_ALGORITHM_NONE) + if (session->sign_key_handle != CK_INVALID_HANDLE || + session->sign_digest_algorithm != HAL_DIGEST_ALGORITHM_NONE) lose(CKR_OPERATION_ACTIVE); - if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK) - goto fail; + if (!p11_object_pkey_open(session, hKey, &pkey)) + lose(CKR_KEY_HANDLE_INVALID); - if (!p11_attribute_get_ulong(session, hKey, CKA_CLASS, &key_class) || - !p11_attribute_get_ulong(session, hKey, CKA_KEY_TYPE, &key_type) || - !p11_attribute_get_bbool(session, hKey, CKA_SIGN, &key_sign) || - key_class != CKO_PRIVATE_KEY) + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, attributes, sizeof(attributes)/sizeof(*attributes), + attributes_buffer, sizeof(attributes_buffer)))) lose(CKR_KEY_HANDLE_INVALID); - if (!key_sign) + cka_key_type = *(CK_KEY_TYPE*) attributes[0].value; + cka_sign = *(CK_BBOOL*) attributes[1].value; + cka_private = *(CK_BBOOL*) attributes[2].value; + cka_token = *(CK_BBOOL*) attributes[3].value; + + rv = p11_object_check_rights(session, hKey, p11_object_access_read, cka_private, cka_token); + + if (rv != CKR_OK) + goto fail; + + if (!cka_sign) lose(CKR_KEY_FUNCTION_NOT_PERMITTED); switch (pMechanism->mechanism) { @@ -3698,7 +3741,7 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: - if (key_type != CKK_RSA) + if (cka_key_type != CKK_RSA) lose(CKR_KEY_TYPE_INCONSISTENT); break; case CKM_ECDSA: @@ -3706,7 +3749,7 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, case CKM_ECDSA_SHA256: case CKM_ECDSA_SHA384: case CKM_ECDSA_SHA512: - if (key_type != CKK_EC) + if (cka_key_type != CKK_EC) lose(CKR_KEY_TYPE_INCONSISTENT); break; default: @@ -3743,10 +3786,12 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, return CKR_MECHANISM_INVALID; } - return mutex_unlock(p11_global_mutex); + rv = CKR_OK; fail: - if (session != NULL) { + if (pkey.handle != HAL_HANDLE_NONE) + (void) hal_rpc_pkey_close(pkey); + if (rv != CKR_OK && session != NULL) { session->sign_key_handle = CK_INVALID_HANDLE; session->sign_digest_algorithm = HAL_DIGEST_ALGORITHM_NONE; } @@ -3762,7 +3807,6 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, ENTER_PUBLIC_FUNCTION(C_Sign); p11_session_t *session; - CK_KEY_TYPE key_type; CK_RV rv; mutex_lock_or_return_failure(p11_global_mutex); @@ -3779,9 +3823,6 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, if (session->sign_digest_handle.handle != HAL_HANDLE_NONE) lose(CKR_OPERATION_ACTIVE); - if (!p11_attribute_get_ulong(session, session->sign_key_handle, CKA_KEY_TYPE, &key_type)) - lose(CKR_FUNCTION_FAILED); - if (session->sign_digest_algorithm != HAL_DIGEST_ALGORITHM_NONE && pSignature != NULL) { if ((rv = digest_update(session, session->sign_digest_algorithm, &session->sign_digest_handle, pData, ulDataLen)) != CKR_OK) @@ -3790,16 +3831,8 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, ulDataLen = 0; } - switch (key_type) { + rv = sign_hal_rpc(session, pData, ulDataLen, pSignature, pulSignatureLen); - case CKK_RSA: - case CKK_EC: - rv = sign_hal_rpc(session, pData, ulDataLen, pSignature, pulSignatureLen); - break; - - default: - lose(CKR_FUNCTION_FAILED); - } /* Fall through */ fail: if (session != NULL && pSignature != NULL && rv != CKR_BUFFER_TOO_SMALL) { @@ -3857,7 +3890,6 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, ENTER_PUBLIC_FUNCTION(C_SignFinal); p11_session_t *session; - CK_KEY_TYPE key_type; CK_RV rv; mutex_lock_or_return_failure(p11_global_mutex); @@ -3868,22 +3900,12 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, if (pulSignatureLen == NULL) lose(CKR_ARGUMENTS_BAD); - if (session->sign_key_handle == CK_INVALID_HANDLE || session->sign_digest_handle.handle == HAL_HANDLE_NONE) + if (session->sign_key_handle == CK_INVALID_HANDLE || + session->sign_digest_handle.handle == HAL_HANDLE_NONE) lose(CKR_OPERATION_NOT_INITIALIZED); - if (!p11_attribute_get_ulong(session, session->sign_key_handle, CKA_KEY_TYPE, &key_type)) - lose(CKR_FUNCTION_FAILED); - - switch (key_type) { + rv = sign_hal_rpc(session, NULL, 0, pSignature, pulSignatureLen); - case CKK_RSA: - case CKK_EC: - rv = sign_hal_rpc(session, NULL, 0, pSignature, pulSignatureLen); - break; - - default: - lose(CKR_FUNCTION_FAILED); - } /* Fall through */ fail: if (session != NULL && pSignature != NULL && rv != CKR_BUFFER_TOO_SMALL) { @@ -3901,10 +3923,20 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, { ENTER_PUBLIC_FUNCTION(C_VerifyInit); + uint8_t attributes_buffer[sizeof(CK_OBJECT_CLASS) + sizeof(CK_KEY_TYPE) + 3 * sizeof(CK_BBOOL)]; + hal_pkey_handle_t pkey = {HAL_HANDLE_NONE}; + hal_rpc_pkey_attribute_t attributes[] = { + [0].type = CKA_KEY_TYPE, + [1].type = CKA_VERIFY, + [2].type = CKA_PRIVATE, + [3].type = CKA_TOKEN + }; + CK_KEY_TYPE cka_key_type; + CK_BBOOL cka_verify; + CK_BBOOL cka_private; + CK_BBOOL cka_token; + p11_session_t *session; - CK_OBJECT_CLASS key_class; - CK_KEY_TYPE key_type; - CK_BBOOL key_verify; CK_RV rv = CKR_OK; mutex_lock_or_return_failure(p11_global_mutex); @@ -3915,19 +3947,28 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, if (pMechanism == NULL) lose(CKR_ARGUMENTS_BAD); - if (session->verify_key_handle != CK_INVALID_HANDLE || session->verify_digest_algorithm != HAL_DIGEST_ALGORITHM_NONE) + if (session->verify_key_handle != CK_INVALID_HANDLE || + session->verify_digest_algorithm != HAL_DIGEST_ALGORITHM_NONE) lose(CKR_OPERATION_ACTIVE); - if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK) - goto fail; + if (!p11_object_pkey_open(session, hKey, &pkey)) + lose(CKR_KEY_HANDLE_INVALID); - if (!p11_attribute_get_ulong(session, hKey, CKA_CLASS, &key_class) || - !p11_attribute_get_ulong(session, hKey, CKA_KEY_TYPE, &key_type) || - !p11_attribute_get_bbool(session, hKey, CKA_VERIFY, &key_verify) || - key_class != CKO_PUBLIC_KEY) + if (!hal_check(hal_rpc_pkey_get_attributes(pkey, attributes, sizeof(attributes)/sizeof(*attributes), + attributes_buffer, sizeof(attributes_buffer)))) lose(CKR_KEY_HANDLE_INVALID); - if (!key_verify) + cka_key_type = *(CK_KEY_TYPE*) attributes[0].value; + cka_verify = *(CK_BBOOL*) attributes[1].value; + cka_private = *(CK_BBOOL*) attributes[2].value; + cka_token = *(CK_BBOOL*) attributes[3].value; + + rv = p11_object_check_rights(session, hKey, p11_object_access_read, cka_private, cka_token); + + if (rv != CKR_OK) + goto fail; + + if (!cka_verify) lose(CKR_KEY_FUNCTION_NOT_PERMITTED); switch (pMechanism->mechanism) { @@ -3937,7 +3978,7 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: - if (key_type != CKK_RSA) + if (cka_key_type != CKK_RSA) lose(CKR_KEY_TYPE_INCONSISTENT); break; case CKM_ECDSA: @@ -3945,7 +3986,7 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, case CKM_ECDSA_SHA256: case CKM_ECDSA_SHA384: case CKM_ECDSA_SHA512: - if (key_type != CKK_EC) + if (cka_key_type != CKK_EC) lose(CKR_KEY_TYPE_INCONSISTENT); break; default: @@ -3982,10 +4023,12 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, return CKR_MECHANISM_INVALID; } - return mutex_unlock(p11_global_mutex); + rv = CKR_OK; fail: - if (session != NULL) { + if (pkey.handle != HAL_HANDLE_NONE) + (void) hal_rpc_pkey_close(pkey); + if (rv != CKR_OK && session != NULL) { session->verify_key_handle = CK_INVALID_HANDLE; session->verify_digest_algorithm = HAL_DIGEST_ALGORITHM_NONE; } @@ -4001,7 +4044,6 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, ENTER_PUBLIC_FUNCTION(C_Verify); p11_session_t *session; - CK_KEY_TYPE key_type; CK_RV rv; mutex_lock_or_return_failure(p11_global_mutex); @@ -4023,19 +4065,7 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession, ulDataLen = 0; } - if (!p11_attribute_get_ulong(session, session->verify_key_handle, CKA_KEY_TYPE, &key_type)) - lose(CKR_FUNCTION_FAILED); - - switch (key_type) { - - case CKK_RSA: - case CKK_EC: - rv = verify_hal_rpc(session, pData, ulDataLen, pSignature, ulSignatureLen); - break; - - default: - lose(CKR_FUNCTION_FAILED); - } + rv = verify_hal_rpc(session, pData, ulDataLen, pSignature, ulSignatureLen); fail: /* Fall through */ @@ -4094,7 +4124,6 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, ENTER_PUBLIC_FUNCTION(C_VerifyFinal); p11_session_t *session; - CK_KEY_TYPE key_type; CK_RV rv; mutex_lock_or_return_failure(p11_global_mutex); @@ -4105,22 +4134,11 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, if (pSignature == NULL) lose(CKR_ARGUMENTS_BAD); - if (session->verify_key_handle == CK_INVALID_HANDLE || session->verify_digest_handle.handle == HAL_HANDLE_NONE) + if (session->verify_key_handle == CK_INVALID_HANDLE || + session->verify_digest_handle.handle == HAL_HANDLE_NONE) lose(CKR_OPERATION_NOT_INITIALIZED); - if (!p11_attribute_get_ulong(session, session->verify_key_handle, CKA_KEY_TYPE, &key_type)) - lose(CKR_FUNCTION_FAILED); - - switch (key_type) { - - case CKK_RSA: - case CKK_EC: - rv = verify_hal_rpc(session, NULL, 0, pSignature, ulSignatureLen); - break; - - default: - lose(CKR_FUNCTION_FAILED); - } + rv = verify_hal_rpc(session, NULL, 0, pSignature, ulSignatureLen); fail: /* Fall through */ |