Skip to content

Commit

Permalink
ta: pkcs11: Add certificate object support
Browse files Browse the repository at this point in the history
Adds support for:

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

4.6 Certificate objects
4.6.3 X.509 public key certificate objects

Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
  • Loading branch information
vesajaaskelainen committed Aug 27, 2021
1 parent 9df6818 commit c72dd62
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 1 deletion.
21 changes: 21 additions & 0 deletions ta/pkcs11/include/pkcs11_ta.h
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,27 @@ enum pkcs11_key_type {
PKCS11_CKK_UNDEFINED_ID = PKCS11_UNDEFINED_ID,
};

/*
* Valid values for attribute PKCS11_CKA_CERTIFICATE_TYPE
*/
enum pkcs11_certificate_type {
PKCS11_CKC_X_509 = 0x00000000,
PKCS11_CKC_X_509_ATTR_CERT = 0x00000001,
PKCS11_CKC_WTLS = 0x00000002,
/* Vendor extension: reserved for undefined ID (~0U) */
PKCS11_CKC_UNDEFINED_ID = PKCS11_UNDEFINED_ID,
};

/*
* Valid values for attribute PKCS11_CKA_CERTIFICATE_CATEGORY
*/
enum pkcs11_certificate_category {
PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0UL,
PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1UL,
PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY = 2UL,
PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY = 3UL,
};

/*
* Valid values for mechanism IDs
* PKCS11_CKM_<x> reflects CryptoKi client API mechanism IDs CKM_<x>.
Expand Down
19 changes: 19 additions & 0 deletions ta/pkcs11/src/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,25 @@ static inline enum pkcs11_key_type get_key_type(struct obj_attrs *head)
return type;
}

/*
* get_certificate_type() - Get the certificate type of an object
* @head: Pointer to serialized attributes
*
* Returns the certificate type of an object on success or returns
* PKCS11_CKM_UNDEFINED_ID on error.
*/
static inline
enum pkcs11_certificate_type get_certificate_type(struct obj_attrs *head)
{
uint32_t type = 0;
uint32_t size = sizeof(type);

if (get_attribute(head, PKCS11_CKA_CERTIFICATE_TYPE, &type, &size))
return PKCS11_CKC_UNDEFINED_ID;

return type;
}

/*
* get_mechanism_type() - Get the mechanism type of an object
* @head: Pointer to serialized attributes
Expand Down
1 change: 1 addition & 0 deletions ta/pkcs11/src/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client,
case PKCS11_CKO_PUBLIC_KEY:
case PKCS11_CKO_PRIVATE_KEY:
case PKCS11_CKO_DATA:
case PKCS11_CKO_CERTIFICATE:
break;
default:
EMSG("Find object of class %s (%"PRIu32") is not supported",
Expand Down
187 changes: 187 additions & 0 deletions ta/pkcs11/src/pkcs11_attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,35 @@ const uint32_t raw_data_opt_or_null[] = {
PKCS11_CKA_OBJECT_ID, PKCS11_CKA_APPLICATION, PKCS11_CKA_VALUE,
};

/* PKCS#11 specification for certificate object (+pkcs11_any_object_xxx) */
static const uint32_t pkcs11_certificate_mandated[] = {
PKCS11_CKA_CERTIFICATE_TYPE,
};

static const uint32_t pkcs11_certificate_boolprops[] = {
PKCS11_CKA_TRUSTED,
};

static const uint32_t pkcs11_certificate_optional[] = {
PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_CHECK_VALUE,
PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO
};

/*
* PKCS#11 specification for X.509 certificate object (+pkcs11_certificate_xxx)
*/
static const uint32_t pkcs11_x509_certificate_mandated[] = {
PKCS11_CKA_SUBJECT,
};

static const uint32_t pkcs11_x509_certificate_optional[] = {
PKCS11_CKA_ID, PKCS11_CKA_ISSUER, PKCS11_CKA_SERIAL_NUMBER,
PKCS11_CKA_VALUE, PKCS11_CKA_URL,
PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY,
PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN, PKCS11_CKA_NAME_HASH_ALGORITHM
};

/* PKCS#11 specification for any key object (+any_object_xxx) */
static const uint32_t any_key_boolprops[] = {
PKCS11_CKA_DERIVE,
Expand Down Expand Up @@ -567,6 +596,91 @@ static enum pkcs11_rc create_data_attributes(struct obj_attrs **out,
ARRAY_SIZE(raw_data_opt_or_null));
}

static enum pkcs11_rc create_certificate_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;
uint32_t attr_size = 0;
uint32_t cert_category = PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED;
uint32_t name_hash_alg = PKCS11_CKM_SHA_1;
enum pkcs11_rc rc = PKCS11_CKR_OK;

assert(get_class(temp) == PKCS11_CKO_CERTIFICATE);

rc = create_storage_attributes(out, temp);
if (rc)
return rc;

assert(get_class(*out) == PKCS11_CKO_CERTIFICATE);

rc = set_mandatory_boolprops(out, temp, pkcs11_certificate_boolprops,
ARRAY_SIZE(pkcs11_certificate_boolprops));
if (rc)
return rc;

rc = set_mandatory_attributes(out, temp, pkcs11_certificate_mandated,
ARRAY_SIZE(pkcs11_certificate_mandated));
if (rc)
return rc;

rc = set_optional_attributes(out, temp, pkcs11_certificate_optional,
ARRAY_SIZE(pkcs11_certificate_optional));
if (rc)
return rc;

switch (get_certificate_type(*out)) {
case PKCS11_CKC_X_509:
mandated = pkcs11_x509_certificate_mandated;
optional = pkcs11_x509_certificate_optional;
mandated_count = ARRAY_SIZE(pkcs11_x509_certificate_mandated);
optional_count = ARRAY_SIZE(pkcs11_x509_certificate_optional);
break;
default:
EMSG("Invalid certificate type %#"PRIx32"/%s",
get_certificate_type(*out),
id2str_certificate_type(get_certificate_type(*out)));

return PKCS11_CKR_TEMPLATE_INCONSISTENT;
}

rc = set_mandatory_attributes(out, temp, mandated, mandated_count);
if (rc)
return rc;

rc = set_optional_attributes(out, temp, optional, optional_count);
if (rc)
return rc;

attr_size = 0;
rc = get_attribute_ptr(*out, PKCS11_CKA_CERTIFICATE_CATEGORY, NULL,
&attr_size);
if ((rc == PKCS11_CKR_OK && attr_size == 0) ||
rc == PKCS11_RV_NOT_FOUND) {
rc = set_attribute(out, PKCS11_CKA_CERTIFICATE_CATEGORY,
&cert_category,
sizeof(cert_category));
if (rc)
return rc;
}

attr_size = 0;
rc = get_attribute_ptr(*out, PKCS11_CKA_NAME_HASH_ALGORITHM, NULL,
&attr_size);
if ((rc == PKCS11_CKR_OK && attr_size == 0) ||
rc == PKCS11_RV_NOT_FOUND) {
rc = set_attribute(out, PKCS11_CKA_NAME_HASH_ALGORITHM,
&name_hash_alg,
sizeof(name_hash_alg));
if (rc)
return rc;
}

return rc;
}

static enum pkcs11_rc create_pub_key_attributes(struct obj_attrs **out,
struct obj_attrs *temp,
enum processing_func function)
Expand Down Expand Up @@ -940,6 +1054,9 @@ create_attributes_from_template(struct obj_attrs **out, void *template,
case PKCS11_CKO_DATA:
rc = create_data_attributes(&attrs, temp);
break;
case PKCS11_CKO_CERTIFICATE:
rc = create_certificate_attributes(&attrs, temp);
break;
case PKCS11_CKO_SECRET_KEY:
rc = sanitize_symm_key_attributes(&temp, function);
if (rc)
Expand Down Expand Up @@ -1134,6 +1251,7 @@ enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session,
case PKCS11_CKO_PRIVATE_KEY:
case PKCS11_CKO_PUBLIC_KEY:
case PKCS11_CKO_DATA:
case PKCS11_CKO_CERTIFICATE:
private = object_is_private(head);
break;
default:
Expand Down Expand Up @@ -1780,6 +1898,73 @@ static bool attr_is_modifiable_private_key(struct pkcs11_attribute_head *attr,
}
}

static bool attr_is_modifiable_certificate(struct pkcs11_attribute_head *attr,
struct pkcs11_session *session,
struct pkcs11_object *obj)
{
uint8_t boolval = 0;
uint32_t boolsize = 0;
enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;

/* Trusted certificates cannot be modified. */
rc = get_attribute(obj->attributes, PKCS11_CKA_TRUSTED,
&boolval, &boolsize);
if (rc || boolval == PKCS11_TRUE)
return false;

/* Common certificate attributes */
switch (attr->id) {
case PKCS11_CKA_TRUSTED:
/*
* The CKA_TRUSTED attribute cannot be set to CK_TRUE by an
* application. It MUST be set by a token initialization
* application or by the token’s SO.
*/
return pkcs11_session_is_so(session);

case PKCS11_CKA_CERTIFICATE_TYPE:
case PKCS11_CKA_CERTIFICATE_CATEGORY:
return false;

default:
break;
}

/* Certificate type specific attributes */
switch (get_certificate_type(obj->attributes)) {
case PKCS11_CKC_X_509:
/*
* Only the CKA_ID, CKA_ISSUER, and CKA_SERIAL_NUMBER
* attributes may be modified after the object is created.
*/
switch (attr->id) {
case PKCS11_CKA_ID:
case PKCS11_CKA_ISSUER:
case PKCS11_CKA_SERIAL_NUMBER:
return true;

case PKCS11_CKA_SUBJECT:
case PKCS11_CKA_VALUE:
case PKCS11_CKA_URL:
case PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
case PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY:
case PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN:
case PKCS11_CKA_NAME_HASH_ALGORITHM:
return false;

default:
break;
}
break;

default:
/* Unsupported certificate type */
return false;
}

return true;
}

static bool attribute_is_modifiable(struct pkcs11_session *session,
struct pkcs11_attribute_head *req_attr,
struct pkcs11_object *obj,
Expand Down Expand Up @@ -1828,6 +2013,8 @@ static bool attribute_is_modifiable(struct pkcs11_session *session,
case PKCS11_CKO_DATA:
/* None of the data object attributes are modifiable */
return false;
case PKCS11_CKO_CERTIFICATE:
return attr_is_modifiable_certificate(req_attr, session, obj);
default:
break;
}
Expand Down
22 changes: 22 additions & 0 deletions ta/pkcs11/src/pkcs11_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ static const struct attr_size attr_ids[] = {
PKCS11_ID_SZ(PKCS11_CKA_VALUE_LEN, 4),
PKCS11_ID_SZ(PKCS11_CKA_KEY_GEN_MECHANISM, 4),
PKCS11_ID_SZ(PKCS11_CKA_LABEL, 0),
PKCS11_ID_SZ(PKCS11_CKA_CERTIFICATE_TYPE, 4),
PKCS11_ID_SZ(PKCS11_CKA_ISSUER, 0),
PKCS11_ID_SZ(PKCS11_CKA_SERIAL_NUMBER, 0),
PKCS11_ID_SZ(PKCS11_CKA_CERTIFICATE_CATEGORY, 4),
PKCS11_ID_SZ(PKCS11_CKA_URL, 0),
PKCS11_ID_SZ(PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY, 0),
PKCS11_ID_SZ(PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY, 0),
PKCS11_ID_SZ(PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN, 4),
PKCS11_ID_SZ(PKCS11_CKA_NAME_HASH_ALGORITHM, 4),
PKCS11_ID_SZ(PKCS11_CKA_CHECK_VALUE, 0),
PKCS11_ID_SZ(PKCS11_CKA_WRAP_TEMPLATE, 0),
PKCS11_ID_SZ(PKCS11_CKA_UNWRAP_TEMPLATE, 0),
PKCS11_ID_SZ(PKCS11_CKA_DERIVE_TEMPLATE, 0),
Expand Down Expand Up @@ -330,6 +340,13 @@ static const struct any_id __maybe_unused string_key_type[] = {
PKCS11_ID(PKCS11_CKK_UNDEFINED_ID)
};

static const struct any_id __maybe_unused string_certificate_type[] = {
PKCS11_ID(PKCS11_CKC_X_509),
PKCS11_ID(PKCS11_CKC_X_509_ATTR_CERT),
PKCS11_ID(PKCS11_CKC_WTLS),
PKCS11_ID(PKCS11_CKC_UNDEFINED_ID)
};

/*
* Processing IDs not exported in the TA API.
* PKCS11_CKM_* mechanism IDs are looked up from mechanism_string_id().
Expand Down Expand Up @@ -760,6 +777,11 @@ const char *id2str_key_type(uint32_t id)
return ID2STR(id, string_key_type, "PKCS11_CKK_");
}

const char *id2str_certificate_type(uint32_t id)
{
return ID2STR(id, string_certificate_type, "PKCS11_CKC_");
}

const char *id2str_attr_value(uint32_t id, size_t size, void *value)
{
static const char str_true[] = "TRUE";
Expand Down
1 change: 1 addition & 0 deletions ta/pkcs11/src/pkcs11_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ const char *id2str_attr(uint32_t id);
const char *id2str_class(uint32_t id);
const char *id2str_type(uint32_t id, uint32_t class);
const char *id2str_key_type(uint32_t id);
const char *id2str_certificate_type(uint32_t id);
const char *id2str_attr_value(uint32_t id, size_t size, void *value);
const char *id2str_proc(uint32_t id);
const char *id2str_function(uint32_t id);
Expand Down
2 changes: 1 addition & 1 deletion ta/pkcs11/src/sanitize_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ bool sanitize_consistent_class_and_type(struct obj_attrs *attrs)
{
switch (get_class(attrs)) {
case PKCS11_CKO_DATA:
case PKCS11_CKO_CERTIFICATE:
return true;
case PKCS11_CKO_SECRET_KEY:
return key_type_is_symm_key(get_key_type(attrs));
Expand All @@ -37,7 +38,6 @@ bool sanitize_consistent_class_and_type(struct obj_attrs *attrs)
case PKCS11_CKO_PRIVATE_KEY:
return key_type_is_asymm_key(get_key_type(attrs));
case PKCS11_CKO_OTP_KEY:
case PKCS11_CKO_CERTIFICATE:
case PKCS11_CKO_DOMAIN_PARAMETERS:
case PKCS11_CKO_HW_FEATURE:
default:
Expand Down

0 comments on commit c72dd62

Please sign in to comment.