diff options
Diffstat (limited to 'ta/pkcs11/src/pkcs11_attributes.c')
-rw-r--r-- | ta/pkcs11/src/pkcs11_attributes.c | 775 |
1 files changed, 775 insertions, 0 deletions
diff --git a/ta/pkcs11/src/pkcs11_attributes.c b/ta/pkcs11/src/pkcs11_attributes.c new file mode 100644 index 00000000..0f669e52 --- /dev/null +++ b/ta/pkcs11/src/pkcs11_attributes.c @@ -0,0 +1,775 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2017-2020, Linaro Limited + */ + +#include <assert.h> +#include <inttypes.h> +#include <pkcs11_ta.h> +#include <stdlib.h> +#include <string_ext.h> +#include <tee_internal_api_extensions.h> +#include <tee_internal_api.h> +#include <util.h> + +#include "attributes.h" +#include "handle.h" +#include "pkcs11_attributes.h" +#include "pkcs11_helpers.h" +#include "pkcs11_token.h" +#include "sanitize_object.h" +#include "serializer.h" +#include "token_capabilities.h" + +/* Byte size of CKA_ID attribute when generated locally */ +#define PKCS11_CKA_DEFAULT_SIZE 16 + +/* + * Object default boolean attributes as per PKCS#11 + */ +static uint8_t *pkcs11_object_default_boolprop(uint32_t attribute) +{ + static const uint8_t bool_true = 1; + static const uint8_t bool_false; + + switch (attribute) { + /* As per PKCS#11 default value */ + case PKCS11_CKA_MODIFIABLE: + case PKCS11_CKA_COPYABLE: + case PKCS11_CKA_DESTROYABLE: + return (uint8_t *)&bool_true; + case PKCS11_CKA_TOKEN: + case PKCS11_CKA_PRIVATE: + /* symkey false, privkey: token specific */ + case PKCS11_CKA_SENSITIVE: + return (uint8_t *)&bool_false; + /* Token specific default value */ + case PKCS11_CKA_SIGN: + case PKCS11_CKA_VERIFY: + return (uint8_t *)&bool_true; + case PKCS11_CKA_DERIVE: + case PKCS11_CKA_ENCRYPT: + case PKCS11_CKA_DECRYPT: + case PKCS11_CKA_SIGN_RECOVER: + case PKCS11_CKA_VERIFY_RECOVER: + case PKCS11_CKA_WRAP: + case PKCS11_CKA_UNWRAP: + case PKCS11_CKA_EXTRACTABLE: + case PKCS11_CKA_WRAP_WITH_TRUSTED: + case PKCS11_CKA_ALWAYS_AUTHENTICATE: + case PKCS11_CKA_TRUSTED: + return (uint8_t *)&bool_false; + default: + DMSG("No default for boolprop attribute %#"PRIx32, attribute); + return NULL; + } +} + +/* + * Object expects several boolean attributes to be set to a default value + * or to a validate client configuration value. This function append the input + * attribute (id/size/value) in the serialized object. + */ +static enum pkcs11_rc pkcs11_import_object_boolprop(struct obj_attrs **out, + struct obj_attrs *templ, + uint32_t attribute) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint8_t bbool = 0; + uint32_t size = sizeof(uint8_t); + void *attr = NULL; + + rc = get_attribute(templ, attribute, &bbool, &size); + if (rc) { + if (rc != PKCS11_RV_NOT_FOUND) + return rc; + attr = pkcs11_object_default_boolprop(attribute); + if (!attr) + return PKCS11_CKR_TEMPLATE_INCOMPLETE; + } else { + attr = &bbool; + } + + /* Boolean attributes are 1byte in the ABI, no alignment issue */ + return add_attribute(out, attribute, attr, sizeof(uint8_t)); +} + +static enum pkcs11_rc set_mandatory_boolprops(struct obj_attrs **out, + struct obj_attrs *temp, + uint32_t const *bp, + size_t bp_count) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + size_t n = 0; + + for (n = 0; n < bp_count; n++) { + rc = pkcs11_import_object_boolprop(out, temp, bp[n]); + if (rc) + return rc; + } + + return rc; +} + +static enum pkcs11_rc set_mandatory_attributes(struct obj_attrs **out, + struct obj_attrs *temp, + uint32_t const *bp, + size_t bp_count) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + size_t n = 0; + + for (n = 0; n < bp_count; n++) { + uint32_t size = 0; + void *value = NULL; + + if (get_attribute_ptr(temp, bp[n], &value, &size)) + return PKCS11_CKR_TEMPLATE_INCOMPLETE; + + rc = add_attribute(out, bp[n], value, size); + if (rc) + return rc; + } + + return rc; +} + +static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id, void **value, + uint32_t *size) +{ + /* should have been taken care of already */ + assert(!pkcs11_attr_is_boolean(id)); + + if (id == PKCS11_CKA_PUBLIC_KEY_INFO) { + EMSG("Cannot provide default PUBLIC_KEY_INFO"); + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + /* All other attributes have an empty default value */ + *value = NULL; + *size = 0; + return PKCS11_CKR_OK; +} + +static enum pkcs11_rc set_optional_attributes(struct obj_attrs **out, + struct obj_attrs *temp, + uint32_t const *bp, + size_t bp_count) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + size_t n = 0; + + for (n = 0; n < bp_count; n++) { + uint32_t size = 0; + void *value = NULL; + + rc = get_attribute_ptr(temp, bp[n], &value, &size); + if (rc == PKCS11_RV_NOT_FOUND) + rc = get_default_value(bp[n], &value, &size); + if (rc) + return rc; + + rc = add_attribute(out, bp[n], value, size); + if (rc) + return rc; + } + + return rc; +} + +/* + * Below are listed the mandated or optional expected attributes for + * PKCS#11 storage objects. + * + * Note: boolprops (mandated boolean attributes) PKCS11_CKA_ALWAYS_SENSITIVE, + * and PKCS11_CKA_NEVER_EXTRACTABLE are set by the token, not provided + * in the client template. + */ + +/* PKCS#11 specification for any object (session/token) of the storage */ +static const uint32_t pkcs11_any_object_boolprops[] = { + PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE, + PKCS11_CKA_MODIFIABLE, PKCS11_CKA_COPYABLE, PKCS11_CKA_DESTROYABLE, +}; + +static const uint32_t pkcs11_any_object_optional[] = { + PKCS11_CKA_LABEL, +}; + +/* PKCS#11 specification for raw data object (+pkcs11_any_object_xxx) */ +const uint32_t pkcs11_raw_data_optional[] = { + PKCS11_CKA_OBJECT_ID, PKCS11_CKA_APPLICATION, PKCS11_CKA_VALUE, +}; + +/* PKCS#11 specification for any key object (+pkcs11_any_object_xxx) */ +static const uint32_t pkcs11_any_key_boolprops[] = { + PKCS11_CKA_DERIVE, +}; + +static const uint32_t pkcs11_any_key_optional[] = { + PKCS11_CKA_ID, + PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE, + PKCS11_CKA_ALLOWED_MECHANISMS, +}; + +/* PKCS#11 specification for any symmetric key (+pkcs11_any_key_xxx) */ +static const uint32_t pkcs11_symm_key_boolprops[] = { + PKCS11_CKA_ENCRYPT, PKCS11_CKA_DECRYPT, + PKCS11_CKA_SIGN, PKCS11_CKA_VERIFY, + PKCS11_CKA_WRAP, PKCS11_CKA_UNWRAP, + PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE, + PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_TRUSTED, +}; + +static const uint32_t pkcs11_symm_key_optional[] = { + PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_UNWRAP_TEMPLATE, + PKCS11_CKA_DERIVE_TEMPLATE, + PKCS11_CKA_VALUE, PKCS11_CKA_VALUE_LEN, +}; + +/* PKCS#11 specification for any asymmetric public key (+pkcs11_any_key_xxx) */ +static const uint32_t pkcs11_public_key_boolprops[] = { + PKCS11_CKA_ENCRYPT, PKCS11_CKA_VERIFY, PKCS11_CKA_VERIFY_RECOVER, + PKCS11_CKA_WRAP, + PKCS11_CKA_TRUSTED, +}; + +static const uint32_t pkcs11_public_key_mandated[] = { + PKCS11_CKA_SUBJECT +}; + +static const uint32_t pkcs11_public_key_optional[] = { + PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_PUBLIC_KEY_INFO, +}; + +/* PKCS#11 specification for any asymmetric private key (+pkcs11_any_key_xxx) */ +static const uint32_t pkcs11_private_key_boolprops[] = { + PKCS11_CKA_DECRYPT, PKCS11_CKA_SIGN, PKCS11_CKA_SIGN_RECOVER, + PKCS11_CKA_UNWRAP, + PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE, + PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_ALWAYS_AUTHENTICATE, +}; + +static const uint32_t pkcs11_private_key_mandated[] = { + PKCS11_CKA_SUBJECT +}; + +static const uint32_t pkcs11_private_key_optional[] = { + PKCS11_CKA_UNWRAP_TEMPLATE, PKCS11_CKA_PUBLIC_KEY_INFO, +}; + +/* PKCS#11 specification for any RSA key (+pkcs11_public/private_key_xxx) */ +static const uint32_t pkcs11_rsa_public_key_mandated[] = { + PKCS11_CKA_MODULUS_BITS, +}; + +static const uint32_t pkcs11_rsa_public_key_optional[] = { + PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT, +}; + +static const uint32_t pkcs11_rsa_private_key_optional[] = { + PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT, + PKCS11_CKA_PRIVATE_EXPONENT, + PKCS11_CKA_PRIME_1, PKCS11_CKA_PRIME_2, + PKCS11_CKA_EXPONENT_1, PKCS11_CKA_EXPONENT_2, PKCS11_CKA_COEFFICIENT, +}; + +/* PKCS#11 specification for any EC key (+pkcs11_public/private_key_xxx) */ +static const uint32_t pkcs11_ec_public_key_mandated[] = { + PKCS11_CKA_EC_PARAMS, +}; + +static const uint32_t pkcs11_ec_public_key_optional[] = { + PKCS11_CKA_EC_POINT, +}; + +static const uint32_t pkcs11_ec_private_key_mandated[] = { + PKCS11_CKA_EC_PARAMS, +}; + +static const uint32_t pkcs11_ec_private_key_optional[] = { + PKCS11_CKA_VALUE, +}; + +static enum pkcs11_rc create_storage_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = init_attributes_head(out); + if (rc) + return rc; + + /* Object class is mandatory */ + class = get_class(temp); + if (class == PKCS11_CKO_UNDEFINED_ID) { + EMSG("Class attribute not found"); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + rc = add_attribute(out, PKCS11_CKA_CLASS, &class, sizeof(uint32_t)); + if (rc) + return rc; + + rc = set_mandatory_boolprops(out, temp, pkcs11_any_object_boolprops, + ARRAY_SIZE(pkcs11_any_object_boolprops)); + if (rc) + return rc; + + return set_optional_attributes(out, temp, pkcs11_any_object_optional, + ARRAY_SIZE(pkcs11_any_object_optional)); +} + +static enum pkcs11_rc create_genkey_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + uint32_t type = PKCS11_CKO_UNDEFINED_ID; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = create_storage_attributes(out, temp); + if (rc) + return rc; + + type = get_key_type(temp); + if (type == PKCS11_CKK_UNDEFINED_ID) { + EMSG("Key type attribute not found"); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + rc = add_attribute(out, PKCS11_CKA_KEY_TYPE, &type, sizeof(uint32_t)); + if (rc) + return rc; + + rc = set_mandatory_boolprops(out, temp, pkcs11_any_key_boolprops, + ARRAY_SIZE(pkcs11_any_key_boolprops)); + if (rc) + return rc; + + return set_optional_attributes(out, temp, pkcs11_any_key_optional, + ARRAY_SIZE(pkcs11_any_key_optional)); +} + +static enum pkcs11_rc create_symm_key_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(get_class(temp) == PKCS11_CKO_SECRET_KEY); + + rc = create_genkey_attributes(out, temp); + if (rc) + return rc; + + assert(get_class(*out) == PKCS11_CKO_SECRET_KEY); + + switch (get_key_type(*out)) { + case PKCS11_CKK_GENERIC_SECRET: + case PKCS11_CKK_AES: + case PKCS11_CKK_MD5_HMAC: + case PKCS11_CKK_SHA_1_HMAC: + case PKCS11_CKK_SHA256_HMAC: + case PKCS11_CKK_SHA384_HMAC: + case PKCS11_CKK_SHA512_HMAC: + case PKCS11_CKK_SHA224_HMAC: + break; + default: + EMSG("Invalid key type %#"PRIx32"/%s", + get_key_type(*out), id2str_key_type(get_key_type(*out))); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + rc = set_mandatory_boolprops(out, temp, pkcs11_symm_key_boolprops, + ARRAY_SIZE(pkcs11_symm_key_boolprops)); + if (rc) + return rc; + + return set_optional_attributes(out, temp, pkcs11_symm_key_optional, + ARRAY_SIZE(pkcs11_symm_key_optional)); +} + +static enum pkcs11_rc create_data_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(get_class(temp) == PKCS11_CKO_DATA); + + rc = create_storage_attributes(out, temp); + if (rc) + return rc; + + assert(get_class(*out) == PKCS11_CKO_DATA); + + return set_optional_attributes(out, temp, pkcs11_raw_data_optional, + ARRAY_SIZE(pkcs11_raw_data_optional)); +} + +static enum pkcs11_rc create_pub_key_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + uint32_t const *mandated = NULL; + uint32_t const *optional = NULL; + size_t mandated_count = 0; + size_t optional_count = 0; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(get_class(temp) == PKCS11_CKO_PUBLIC_KEY); + + rc = create_genkey_attributes(out, temp); + if (rc) + return rc; + + assert(get_class(*out) == PKCS11_CKO_PUBLIC_KEY); + + rc = set_mandatory_boolprops(out, temp, pkcs11_public_key_boolprops, + ARRAY_SIZE(pkcs11_public_key_boolprops)); + if (rc) + return rc; + + rc = set_mandatory_attributes(out, temp, pkcs11_public_key_mandated, + ARRAY_SIZE(pkcs11_public_key_mandated)); + if (rc) + return rc; + + rc = set_optional_attributes(out, temp, pkcs11_public_key_optional, + ARRAY_SIZE(pkcs11_public_key_optional)); + if (rc) + return rc; + + switch (get_key_type(*out)) { + case PKCS11_CKK_RSA: + mandated = pkcs11_rsa_public_key_mandated; + optional = pkcs11_rsa_public_key_optional; + mandated_count = ARRAY_SIZE(pkcs11_rsa_public_key_mandated); + optional_count = ARRAY_SIZE(pkcs11_rsa_public_key_optional); + break; + case PKCS11_CKK_EC: + mandated = pkcs11_ec_public_key_mandated; + optional = pkcs11_ec_public_key_optional; + mandated_count = ARRAY_SIZE(pkcs11_ec_public_key_mandated); + optional_count = ARRAY_SIZE(pkcs11_ec_public_key_optional); + break; + default: + EMSG("Invalid key type %#"PRIx32"/%s", + get_key_type(*out), id2str_key_type(get_key_type(*out))); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + rc = set_mandatory_attributes(out, temp, mandated, mandated_count); + if (rc) + return rc; + + return set_optional_attributes(out, temp, optional, optional_count); +} + +static enum pkcs11_rc create_priv_key_attributes(struct obj_attrs **out, + struct obj_attrs *temp) +{ + uint32_t const *mandated = NULL; + uint32_t const *optional = NULL; + size_t mandated_count = 0; + size_t optional_count = 0; + enum pkcs11_rc rc = PKCS11_CKR_OK; + + assert(get_class(temp) == PKCS11_CKO_PRIVATE_KEY); + + rc = create_genkey_attributes(out, temp); + if (rc) + return rc; + + assert(get_class(*out) == PKCS11_CKO_PRIVATE_KEY); + + rc = set_mandatory_boolprops(out, temp, pkcs11_private_key_boolprops, + ARRAY_SIZE(pkcs11_private_key_boolprops)); + if (rc) + return rc; + + rc = set_mandatory_attributes(out, temp, pkcs11_private_key_mandated, + ARRAY_SIZE(pkcs11_private_key_mandated)); + if (rc) + return rc; + + rc = set_optional_attributes(out, temp, pkcs11_private_key_optional, + ARRAY_SIZE(pkcs11_private_key_optional)); + if (rc) + return rc; + + switch (get_key_type(*out)) { + case PKCS11_CKK_RSA: + optional = pkcs11_rsa_private_key_optional; + optional_count = ARRAY_SIZE(pkcs11_rsa_private_key_optional); + break; + case PKCS11_CKK_EC: + mandated = pkcs11_ec_private_key_mandated; + optional = pkcs11_ec_private_key_optional; + mandated_count = ARRAY_SIZE(pkcs11_ec_private_key_mandated); + optional_count = ARRAY_SIZE(pkcs11_ec_private_key_optional); + break; + default: + EMSG("Invalid key type %#"PRIx32"/%s", + get_key_type(*out), id2str_key_type(get_key_type(*out))); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + rc = set_mandatory_attributes(out, temp, mandated, mandated_count); + if (rc) + return rc; + + return set_optional_attributes(out, temp, optional, optional_count); +} + +/* + * Create an attribute list for a new object from a template and a parent + * object (optional) for an object generation function (generate, copy, + * derive...). + * + * PKCS#11 directives on the supplied template and expected return value: + * - template has an invalid attribute ID: ATTRIBUTE_TYPE_INVALID + * - template has an invalid value for an attribute: ATTRIBUTE_VALID_INVALID + * - template has value for a read-only attribute: ATTRIBUTE_READ_ONLY + * - template+default+parent => still miss an attribute: TEMPLATE_INCONSISTENT + * + * INFO on PKCS11_CMD_COPY_OBJECT: + * - parent PKCS11_CKA_COPYIABLE=false => return ACTION_PROHIBITED. + * - template can specify PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE, + * PKCS11_CKA_MODIFIABLE, PKCS11_CKA_DESTROYABLE. + * - SENSITIVE can change from false to true, not from true to false. + * - LOCAL is the parent LOCAL + */ +enum pkcs11_rc +create_attributes_from_template(struct obj_attrs **out, void *template, + size_t template_size, + struct obj_attrs *parent __unused, + enum processing_func function, + enum pkcs11_mechanism_id mecha __unused) +{ + struct obj_attrs *temp = NULL; + struct obj_attrs *attrs = NULL; + enum pkcs11_rc rc = PKCS11_CKR_OK; + uint8_t local = 0; + uint8_t always_sensitive = 0; + uint8_t never_extract = 0; + uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID; + +#ifdef DEBUG /* Sanity: check function argument */ + trace_attributes_from_api_head("template", template, template_size); + switch (function) { + case PKCS11_FUNCTION_IMPORT: + break; + default: + TEE_Panic(TEE_ERROR_NOT_SUPPORTED); + } +#endif + + rc = sanitize_client_object(&temp, template, template_size); + if (rc) + goto out; + + /* If class/type not defined, match from mechanism */ + if (get_class(temp) == PKCS11_UNDEFINED_ID && + get_key_type(temp) == PKCS11_UNDEFINED_ID) { + EMSG("Unable to define class/type from mechanism"); + rc = PKCS11_CKR_TEMPLATE_INCOMPLETE; + goto out; + } + + if (!sanitize_consistent_class_and_type(temp)) { + EMSG("Inconsistent class/type"); + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + goto out; + } + + switch (get_class(temp)) { + case PKCS11_CKO_DATA: + rc = create_data_attributes(&attrs, temp); + break; + case PKCS11_CKO_SECRET_KEY: + rc = create_symm_key_attributes(&attrs, temp); + break; + case PKCS11_CKO_PUBLIC_KEY: + rc = create_pub_key_attributes(&attrs, temp); + break; + case PKCS11_CKO_PRIVATE_KEY: + rc = create_priv_key_attributes(&attrs, temp); + break; + default: + DMSG("Invalid object class %#"PRIx32"/%s", + get_class(temp), id2str_class(get_class(temp))); + + rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; + break; + } + if (rc) + goto out; + + if (get_attribute(attrs, PKCS11_CKA_LOCAL, NULL, NULL) != + PKCS11_RV_NOT_FOUND) + goto out; + + if (get_attribute(attrs, PKCS11_CKA_KEY_GEN_MECHANISM, NULL, NULL) != + PKCS11_RV_NOT_FOUND) + goto out; + + switch (function) { + case PKCS11_FUNCTION_IMPORT: + default: + local = PKCS11_FALSE; + break; + } + rc = add_attribute(&attrs, PKCS11_CKA_LOCAL, &local, sizeof(local)); + if (rc) + goto out; + + switch (get_class(attrs)) { + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_PRIVATE_KEY: + case PKCS11_CKO_PUBLIC_KEY: + always_sensitive = PKCS11_FALSE; + never_extract = PKCS11_FALSE; + + rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE, + &always_sensitive, sizeof(always_sensitive)); + if (rc) + goto out; + + rc = add_attribute(&attrs, PKCS11_CKA_NEVER_EXTRACTABLE, + &never_extract, sizeof(never_extract)); + if (rc) + goto out; + + /* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */ + mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION; + rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM, + &mechanism_id, sizeof(mechanism_id)); + if (rc) + goto out; + break; + + default: + break; + } + + *out = attrs; + +#ifdef DEBUG + trace_attributes("object", attrs); +#endif + +out: + TEE_Free(temp); + if (rc) + TEE_Free(attrs); + + return rc; +} + +static enum pkcs11_rc check_attrs_misc_integrity(struct obj_attrs *head) +{ + if (get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE) && + get_bool(head, PKCS11_CKA_EXTRACTABLE)) { + DMSG("Never/Extractable attributes mismatch %d/%d", + get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE), + get_bool(head, PKCS11_CKA_EXTRACTABLE)); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + if (get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE) && + !get_bool(head, PKCS11_CKA_SENSITIVE)) { + DMSG("Sensitive/always attributes mismatch %d/%d", + get_bool(head, PKCS11_CKA_SENSITIVE), + get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE)); + + return PKCS11_CKR_TEMPLATE_INCONSISTENT; + } + + return PKCS11_CKR_OK; +} + +/* + * Check the attributes of a to-be-created object matches the token state + */ +enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session, + struct obj_attrs *head) +{ + enum pkcs11_rc rc = PKCS11_CKR_OK; + + rc = check_attrs_misc_integrity(head); + if (rc) + return rc; + + if (get_bool(head, PKCS11_CKA_TRUSTED) && + !pkcs11_session_is_so(session)) { + DMSG("Can't create trusted object"); + + return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; + } + + if (get_bool(head, PKCS11_CKA_TOKEN) && + !pkcs11_session_is_read_write(session)) { + DMSG("Can't create persistent object"); + + return PKCS11_CKR_SESSION_READ_ONLY; + } + + /* + * TODO: START_DATE and END_DATE: complies with current time? + */ + return PKCS11_CKR_OK; +} + +#define DMSG_BAD_BBOOL(attr, proc, head) \ + do { \ + uint32_t __maybe_unused _attr = (attr); \ + uint8_t __maybe_unused _bvalue = 0; \ + enum pkcs11_rc __maybe_unused _rc = PKCS11_CKR_OK; \ + \ + _rc = get_attribute((head), _attr, &_bvalue, NULL); \ + DMSG("%s issue for %s: %sfound, value %"PRIu8, \ + id2str_attr(_attr), id2str_proc((proc)), \ + _rc ? "not " : "", _bvalue); \ + } while (0) + +static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused, + struct obj_attrs *head, + uint32_t attribute, bool val) +{ + uint8_t bbool = 0; + uint32_t sz = sizeof(bbool); + + if (!get_attribute(head, attribute, &bbool, &sz) && !!bbool == val) + return true; + + DMSG_BAD_BBOOL(attribute, proc_id, head); + return false; +} + +/* + * Check the attributes of a new secret match the processing/mechanism + * used to create it. + * + * @proc_id - PKCS11_CKM_xxx + * @head - head of the attributes of the to-be-created object. + */ +enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id, + struct obj_attrs *head) +{ + /* + * Processings that do not create secrets are not expected to call + * this function which would panic. + */ + switch (proc_id) { + case PKCS11_PROCESSING_IMPORT: + assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false)); + break; + default: + TEE_Panic(proc_id); + break; + } + + return PKCS11_CKR_OK; +} |