Skip to content

Commit

Permalink
pkcs11: Initial C_SetAttributeValue support
Browse files Browse the repository at this point in the history
Specified in:

PKCS OP-TEE#11 Cryptographic Token Interface Base Specification Version 2.40
Plus Errata 01

C_SetAttributeValue

Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
  • Loading branch information
vesajaaskelainen committed Dec 17, 2020
1 parent ba788ab commit a08e263
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 0 deletions.
16 changes: 16 additions & 0 deletions ta/pkcs11/src/attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,22 @@ enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute,
return PKCS11_CKR_OK;
}

enum pkcs11_rc set_attribute(struct obj_attrs **head, uint32_t attribute,
void *data, size_t size)
{
enum pkcs11_rc rc = PKCS11_CKR_OK;

rc = remove_attribute_check(head, attribute, 1);
if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
return rc;

rc = add_attribute(head, attribute, data, size);
if (rc)
return rc;

return PKCS11_CKR_OK;
}

bool get_bool(struct obj_attrs *head, uint32_t attribute)
{
enum pkcs11_rc rc = PKCS11_CKR_OK;
Expand Down
14 changes: 14 additions & 0 deletions ta/pkcs11/src/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,20 @@ enum pkcs11_rc get_attribute_ptr(struct obj_attrs *head, uint32_t attribute,
enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute,
void *attr, uint32_t *attr_size);

/*
* set_attribute() - Set serialized attributes.
*
* @head: *@head points to serialized attributes,
* can be reallocated as attributes are added
* @attribute: Attribute ID to set
* @data: Opaque data of attribute
* @size: Size of data
*
* Return PKCS11_CKR_OK on success or a PKCS11 return code.
*/
enum pkcs11_rc set_attribute(struct obj_attrs **head, uint32_t attribute,
void *data, size_t size);

/*
* get_u32_attribute() - Copy out the 32-bit attribute value of a given ID
* @head: Pointer to serialized attributes
Expand Down
3 changes: 3 additions & 0 deletions ta/pkcs11/src/entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd,
case PKCS11_CMD_GET_ATTRIBUTE_VALUE:
rc = entry_get_attribute_value(client, ptypes, params);
break;
case PKCS11_CMD_SET_ATTRIBUTE_VALUE:
rc = entry_set_attribute_value(client, ptypes, params);
break;
case PKCS11_CMD_GET_OBJECT_SIZE:
rc = entry_get_object_size(client, ptypes, params);
break;
Expand Down
128 changes: 128 additions & 0 deletions ta/pkcs11/src/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,134 @@ uint32_t entry_get_attribute_value(struct pkcs11_client *client,
return rc;
}

uint32_t entry_set_attribute_value(struct pkcs11_client *client,
uint32_t ptypes, TEE_Param *params)
{
const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE,
TEE_PARAM_TYPE_NONE);
TEE_Param *ctrl = params;
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
struct serialargs ctrlargs = { };
struct pkcs11_session *session = NULL;
struct pkcs11_object_head *template = NULL;
struct pkcs11_object *obj = NULL;
uint32_t object_handle = 0;
char *cur = NULL;
size_t len = 0;
char *end = NULL;
bool modifiable = 0;

if (!client || ptypes != exp_pt)
return PKCS11_CKR_ARGUMENTS_BAD;

serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);

rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
if (rc)
return rc;

rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t));
if (rc)
return rc;

rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
if (rc)
return rc;

if (serialargs_remaining_bytes(&ctrlargs)) {
rc = PKCS11_CKR_ARGUMENTS_BAD;
goto out;
}

obj = pkcs11_handle2object(object_handle, session);
if (!obj) {
rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
goto out;
}

/*
* 1. Modifications to object with secret details from public session
* is denied. On failure returns PKCS11_CKR_OBJECT_HANDLE_INVALID
* (to hide presence of object)
*
* 2. If object is not modifiable then access is denied. On failure
* returns CKR_ACTION_PROHIBITED
*
* 3. Perform rule check for common variables to verify if value can be
* changed. On failure returns CKR_TEMPLATE_INCONSISTENT.
*
* 4. Depending on object type additional mechanisms consistency checks
* need to be performed. On failure returns
* CKR_TEMPLATE_INCONSISTENT.
*/

/* 1. Verify that proper session is used for accessing the object */
rc = check_access_attrs_against_token(session, obj->attributes);
if (rc) {
rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
goto out;
}

/* 2. Verify that object can be modified. */
modifiable = object_is_modifiable(obj->attributes);
if (!modifiable) {
rc = PKCS11_CKR_ACTION_PROHIBITED;
goto out;
}

/* 3. iterate over attributes and check if we can set their values */
cur = (char *)template + sizeof(struct pkcs11_object_head);
end = cur + template->attrs_size;

for (; cur < end; cur += len) {
struct pkcs11_attribute_head *cli_ref =
(struct pkcs11_attribute_head *)cur;

len = sizeof(*cli_ref) + cli_ref->size;

if (!attribute_is_settable(cli_ref, obj)) {
rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
goto out;
}
}

/* 4. TODO: mechanism consistency checks */

/* Everything is OK perform set operations */

/* iterate over attributes and set their values */
cur = (char *)template + sizeof(struct pkcs11_object_head);
end = cur + template->attrs_size;

for (; cur < end; cur += len) {
struct pkcs11_attribute_head *cli_ref =
(struct pkcs11_attribute_head *)cur;

len = sizeof(*cli_ref) + cli_ref->size;

/*
* We assume that if size is 0, pValue was NULL, so we return
* the size of the required buffer for it (3., 4.)
*/
rc = set_attribute(&obj->attributes, cli_ref->id,
cli_ref->size ? cli_ref->data : NULL,
cli_ref->size);
if (rc)
goto out;
}

DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32,
session->handle, object_handle);

out:
TEE_Free(template);
template = NULL;

return rc;
}

uint32_t entry_get_object_size(struct pkcs11_client *client,
uint32_t ptypes, TEE_Param *params)
{
Expand Down
3 changes: 3 additions & 0 deletions ta/pkcs11/src/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client,
enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client,
uint32_t ptypes, TEE_Param *params);

enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client,
uint32_t ptypes, TEE_Param *params);

enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client,
uint32_t ptypes, TEE_Param *params);

Expand Down
36 changes: 36 additions & 0 deletions ta/pkcs11/src/pkcs11_attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,11 @@ bool object_is_private(struct obj_attrs *head)
return false;
}

bool object_is_modifiable(struct obj_attrs *head)
{
return get_bool(head, PKCS11_CKA_MODIFIABLE);
}

/*
* Add a CKA ID attribute to an object or paired object if missing.
* If 2 objects are provided and at least 1 does not have a CKA_ID,
Expand Down Expand Up @@ -1541,3 +1546,34 @@ bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr,

return true;
}

bool attribute_is_settable(struct pkcs11_attribute_head *req_attr,
struct pkcs11_object *obj)
{
uint8_t boolval = 0;
uint32_t boolsize = 0;
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;

switch (req_attr->id) {
case PKCS11_CKA_SENSITIVE:
/* Only allow change from CK_FALSE -> CK_TRUE */
boolsize = sizeof(boolval);
rc = get_attribute(obj->attributes, PKCS11_CKA_SENSITIVE,
&boolval, &boolsize);
if (rc || boolval == PKCS11_TRUE)
return false;
break;

case PKCS11_CKA_EXTRACTABLE:
/* Only allow change from CK_TRUE -> CK_FALSE */
boolsize = sizeof(boolval);
rc = get_attribute(obj->attributes, PKCS11_CKA_EXTRACTABLE,
&boolval, &boolsize);
if (rc || boolval == PKCS11_FALSE)
return false;
break;
default:
break;
}
return true;
}
5 changes: 5 additions & 0 deletions ta/pkcs11/src/pkcs11_attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,14 @@ check_mechanism_against_processing(struct pkcs11_session *session,

bool object_is_private(struct obj_attrs *head);

bool object_is_modifiable(struct obj_attrs *head);

bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr,
struct pkcs11_object *obj);

bool attribute_is_settable(struct pkcs11_attribute_head *req_attr,
struct pkcs11_object *obj);

enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **attrs1,
struct obj_attrs **attrs2);

Expand Down

0 comments on commit a08e263

Please sign in to comment.