pkcs11: Implement PKCS #11 3.0 Profile object and its handling in tools

This commit is contained in:
Jakub Jelen 2020-08-18 19:36:03 +02:00 committed by Frank Morgner
parent 7f9e8ba85c
commit db18a72c64
5 changed files with 160 additions and 2 deletions

View File

@ -126,6 +126,12 @@ struct pkcs15_data_object {
#define data_p15obj base.p15_object
#define is_data(obj) (__p15_type(obj) == SC_PKCS15_TYPE_DATA_OBJECT)
struct pkcs15_profile_object {
struct pkcs15_any_object base;
unsigned long profile_id;
};
struct pkcs15_skey_object {
struct pkcs15_any_object base;
@ -142,6 +148,7 @@ extern struct sc_pkcs11_object_ops pkcs15_cert_ops;
extern struct sc_pkcs11_object_ops pkcs15_prkey_ops;
extern struct sc_pkcs11_object_ops pkcs15_pubkey_ops;
extern struct sc_pkcs11_object_ops pkcs15_dobj_ops;
extern struct sc_pkcs11_object_ops pkcs15_profile_ops;
extern struct sc_pkcs11_object_ops pkcs15_skey_ops;
const CK_BYTE gostr3410_paramset_A_encoded_oid[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 };
@ -811,6 +818,32 @@ __pkcs15_create_data_object(struct pkcs15_fw_data *fw_data,
return rv;
}
/* Note, that this is not actuall PKCS #15 object, but just bogus
* structure to create PKCS #11 object. There is no corresponding
* PKCS #15 object. */
static int
__pkcs15_create_profile_object(struct pkcs15_fw_data *fw_data,
int public_certificates, struct pkcs15_any_object **profile_object)
{
struct pkcs15_profile_object *pobj = NULL;
struct sc_pkcs15_object *obj = NULL;
int rv;
obj = calloc(1, sizeof(struct sc_pkcs15_object));
rv = __pkcs15_create_object(fw_data, (struct pkcs15_any_object **) &pobj,
obj, &pkcs15_profile_ops, sizeof(struct pkcs15_profile_object));
if (rv >= 0) {
pobj->profile_id = public_certificates ? CKP_PUBLIC_CERTIFICATES_TOKEN : CKP_AUTHENTICATION_TOKEN;
}
if (profile_object != NULL)
*profile_object = (struct pkcs15_any_object *) pobj;
return rv;
}
static int
__pkcs15_create_secret_key_object(struct pkcs15_fw_data *fw_data,
@ -1430,6 +1463,10 @@ _add_pin_related_objects(struct sc_pkcs11_slot *slot, struct sc_pkcs15_object *p
static void
_add_public_objects(struct sc_pkcs11_slot *slot, struct pkcs15_fw_data *fw_data)
{
/* Public Certificates Token in PKCS #11 3.0 */
struct pkcs15_any_object *pobj = NULL;
int public_certificates = 1;
CK_RV rv;
unsigned i;
if (slot == NULL || fw_data == NULL)
@ -1446,8 +1483,15 @@ _add_public_objects(struct sc_pkcs11_slot *slot, struct pkcs15_fw_data *fw_data)
if (obj->base.flags & SC_PKCS11_OBJECT_SEEN)
continue;
/* Ignore 'private' object */
if (obj->p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE)
if (obj->p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE) {
/* If we found some non-accessible public object,
* we can no longer claim Public Ceritificate Token conformance */
if (obj->p15_object->type & SC_PKCS15_TYPE_PUBKEY ||
obj->p15_object->type & SC_PKCS15_TYPE_CERT) {
public_certificates = 0;
}
continue;
}
/* PKCS#15 4.1.3 is a little vague, but implies if not PRIVATE it is readable
* even if there is an auth_id to allow writing for example.
* See bug issue #291
@ -1456,9 +1500,20 @@ _add_public_objects(struct sc_pkcs11_slot *slot, struct pkcs15_fw_data *fw_data)
if (obj->p15_object->auth_id.len && !(is_pubkey(obj) || is_cert(obj)))
continue;
sc_log(context, "Add public object(%p,%.*s,%x)", obj, (int) sizeof obj->p15_object->label, obj->p15_object->label, obj->p15_object->type);
sc_log(context, "Add public object(%p,%.*s,%x)", obj,
(int) sizeof obj->p15_object->label, obj->p15_object->label,
obj->p15_object->type);
pkcs15_add_object(slot, obj, NULL);
}
/* If all certificates and public keys are visible, we can claim conformance
* to Public Certificate Token profile, making life easier for many applications
* saying, they do not need to login to see all keys available */
rv = __pkcs15_create_profile_object(fw_data, public_certificates, &pobj);
if (rv != CKR_OK || pobj == NULL) {
return;
}
pkcs15_add_object(slot, pobj, NULL);
}
@ -4949,6 +5004,66 @@ struct sc_pkcs11_object_ops pkcs15_dobj_ops = {
NULL /* wrap_key */
};
/* PKCS#15 Data Object*/
static void
pkcs15_profile_release(void *object)
{
__pkcs15_release_object((struct pkcs15_any_object *) object);
}
static CK_RV
pkcs15_profile_set_attribute(struct sc_pkcs11_session *session,
void *object, CK_ATTRIBUTE_PTR attr)
{
/* Profile object is not writable */
return CKR_ACTION_PROHIBITED;
}
static CK_RV
pkcs15_profile_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ATTRIBUTE_PTR attr)
{
struct pkcs15_profile_object *pobj = (struct pkcs15_profile_object*) object;
sc_log(context, "pkcs15_profile_get_attribute() called");
switch (attr->type) {
case CKA_CLASS:
check_attribute_buffer(attr, sizeof(CK_OBJECT_CLASS));
*(CK_OBJECT_CLASS*)attr->pValue = CKO_PROFILE;
break;
case CKA_PRIVATE:
/* This is needed internally for the object to be visible */
check_attribute_buffer(attr, sizeof(CK_BBOOL));
*(CK_BBOOL*)attr->pValue = CK_FALSE;
break;
case CKA_PROFILE_ID:
/* TODO */
check_attribute_buffer(attr, sizeof(CK_ULONG));
*(CK_ULONG*)attr->pValue = pobj->profile_id;
break;
default:
return CKR_ATTRIBUTE_TYPE_INVALID;
}
return CKR_OK;
}
struct sc_pkcs11_object_ops pkcs15_profile_ops = {
pkcs15_profile_release,
pkcs15_profile_set_attribute,
pkcs15_profile_get_attribute,
sc_pkcs11_any_cmp_attribute,
pkcs15_any_destroy,
NULL, /* get_size */
NULL, /* sign */
NULL, /* unwrap_key */
NULL, /* decrypt */
NULL, /* derive */
NULL, /* can_do */
NULL, /* init_params */
NULL /* wrap_key */
};
/* PKCS#15 Secret Key Objects */
/* TODO Currently only session objects */

View File

@ -250,6 +250,7 @@ static enum_specs ck_cls_s[] = {
{ CKO_PUBLIC_KEY , "CKO_PUBLIC_KEY " },
{ CKO_PRIVATE_KEY , "CKO_PRIVATE_KEY " },
{ CKO_SECRET_KEY , "CKO_SECRET_KEY " },
{ CKO_PROFILE , "CKO_PROFILE " },
{ CKO_HW_FEATURE , "CKO_HW_FEATURE " },
{ CKO_DOMAIN_PARAMETERS, "CKO_DOMAIN_PARAMETERS" },
{ CKO_NETSCAPE_CRL, "CKO_NETSCAPE_CRL " },
@ -259,6 +260,15 @@ static enum_specs ck_cls_s[] = {
{ CKO_VENDOR_DEFINED , "CKO_VENDOR_DEFINED " }
};
enum_specs ck_profile_s[] = {
{ CKP_INVALID_ID , "CKP_INVALID_ID " },
{ CKP_BASELINE_PROVIDER , "CKP_BASELINE_PROVIDER " },
{ CKP_EXTENDED_PROVIDER , "CKP_EXTENDED_PROVIDER " },
{ CKP_AUTHENTICATION_TOKEN , "CKP_AUTHENTICATION_TOKEN " },
{ CKP_PUBLIC_CERTIFICATES_TOKEN, "CKP_PUBLIC_CERTIFICATES_TOKEN" },
{ CKP_VENDOR_DEFINED , "CKP_VENDOR_DEFINED " }
};
static enum_specs ck_crt_s[] = {
{ CKC_X_509, "CKC_X_509" },
{ CKC_X_509_ATTR_CERT, "CKC_X_509_ATTR_CERT" },
@ -657,6 +667,7 @@ static enum_specs ck_ckd_s[] = {
enum_spec ck_types[] = {
{ OBJ_T, ck_cls_s, sizeof(ck_cls_s) / SZ_SPECS, "CK_OBJECT_CLASS" },
{ PROFILE_T, ck_profile_s, sizeof(ck_profile_s)/SZ_SPECS, "CK_PROFILE"},
{ KEY_T, ck_key_s, sizeof(ck_key_s) / SZ_SPECS, "CK_KEY_TYPE" },
{ CRT_T, ck_crt_s, sizeof(ck_crt_s) / SZ_SPECS, "CK_CERTIFICATE_TYPE" },
{ MEC_T, ck_mec_s, sizeof(ck_mec_s) / SZ_SPECS, "CK_MECHANISM_TYPE" },
@ -670,6 +681,7 @@ enum_spec ck_types[] = {
static enum_spec ck_key_t[] = { { KEY_T, ck_key_s, sizeof(ck_key_s) / SZ_SPECS, "CK_KEY_TYPE" } };
static enum_spec ck_cls_t[] = { { OBJ_T, ck_cls_s, sizeof(ck_cls_s) / SZ_SPECS, "CK_OBJECT_CLASS" } };
static enum_spec ck_crt_t[] = { { CRT_T, ck_crt_s, sizeof(ck_crt_s) / SZ_SPECS, "CK_CERTIFICATE_TYPE" } };
static enum_spec ck_profile_t[] = { { PROFILE_T, ck_profile_s, sizeof(ck_profile_s) / SZ_SPECS, "CK_PROFILE" } };
type_spec ck_attribute_specs[] = {
{ CKA_CLASS , "CKA_CLASS ", print_enum, ck_cls_t },
@ -781,6 +793,7 @@ type_spec ck_attribute_specs[] = {
{ CKA_ENCODING_METHODS , "CKA_ENCODING_METHODS ", print_generic, NULL },
{ CKA_MIME_TYPES , "CKA_MIME_TYPES ", print_generic, NULL },
{ CKA_MECHANISM_TYPE , "CKA_MECHANISM_TYPE ", print_generic, NULL },
{ CKA_PROFILE_ID , "CKA_PROFILE_ID ", print_enum, ck_profile_t },
{ CKA_REQUIRED_CMS_ATTRIBUTES, "CKA_REQUIRED_CMS_ATTRIBUTES ", print_generic, NULL },
{ CKA_DEFAULT_CMS_ATTRIBUTES, "CKA_DEFAULT_CMS_ATTRIBUTES ", print_generic, NULL },
{ CKA_SUPPORTED_CMS_ATTRIBUTES, "CKA_SUPPORTED_CMS_ATTRIBUTES ", print_generic, NULL },

View File

@ -53,6 +53,7 @@ typedef struct {
enum ck_type{
OBJ_T,
PROFILE_T,
KEY_T,
CRT_T,
MEC_T,

View File

@ -321,8 +321,16 @@ typedef unsigned long ck_object_class_t;
#define CKO_HW_FEATURE (5UL)
#define CKO_DOMAIN_PARAMETERS (6UL)
#define CKO_MECHANISM (7UL)
#define CKO_OTP_KEY (8UL)
#define CKO_PROFILE (9UL)
#define CKO_VENDOR_DEFINED (1UL << 31)
#define CKP_INVALID_ID (0UL)
#define CKP_BASELINE_PROVIDER (1UL)
#define CKP_EXTENDED_PROVIDER (2UL)
#define CKP_AUTHENTICATION_TOKEN (3UL)
#define CKP_PUBLIC_CERTIFICATES_TOKEN (4UL)
#define CKP_VENDOR_DEFINED (1UL << 31)
typedef unsigned long ck_hw_feature_type_t;
@ -482,6 +490,7 @@ typedef unsigned long ck_attribute_type_t;
#define CKA_OTP_COUNTER (0x22EUL)
#define CKA_OTP_TIME (0x22FUL)
#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600UL)
#define CKA_PROFILE_ID (0x601UL)
#define CKA_VENDOR_DEFINED (1UL << 31)
@ -1506,6 +1515,7 @@ struct ck_c_initialize_args
#define CKR_ATTRIBUTE_SENSITIVE (0x11UL)
#define CKR_ATTRIBUTE_TYPE_INVALID (0x12UL)
#define CKR_ATTRIBUTE_VALUE_INVALID (0x13UL)
#define CKR_ACTION_PROHIBITED (0x1BUL)
#define CKR_DATA_INVALID (0x20UL)
#define CKR_DATA_LEN_RANGE (0x21UL)
#define CKR_DEVICE_ERROR (0x30UL)

View File

@ -437,6 +437,7 @@ static void show_object(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
static void show_key(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
static void show_cert(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
static void show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj);
static void show_profile(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj);
static void sign_data(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
static void verify_signature(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
static void decrypt_data(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
@ -554,6 +555,7 @@ ATTR_METHOD(KEY_TYPE, CK_KEY_TYPE); /* getKEY_TYPE */
ATTR_METHOD(CERTIFICATE_TYPE, CK_CERTIFICATE_TYPE); /* getCERTIFICATE_TYPE */
ATTR_METHOD(MODULUS_BITS, CK_ULONG); /* getMODULUS_BITS */
ATTR_METHOD(VALUE_LEN, CK_ULONG); /* getVALUE_LEN */
ATTR_METHOD(PROFILE_ID, CK_ULONG); /* getPROFILE_ID */
VARATTR_METHOD(LABEL, char); /* getLABEL */
VARATTR_METHOD(APPLICATION, char); /* getAPPLICATION */
VARATTR_METHOD(ID, unsigned char); /* getID */
@ -3740,6 +3742,9 @@ static void show_object(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj)
case CKO_DATA:
show_dobj(sess, obj);
break;
case CKO_PROFILE:
show_profile(sess, obj);
break;
default:
printf("Object %u, type %u\n",
(unsigned int) obj,
@ -4303,6 +4308,20 @@ static void show_dobj(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj)
}
static void show_profile(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj)
{
CK_ULONG id = 0;
printf("Profile object %u\n", (unsigned int) obj);
printf(" profile_id: ");
if ((id = getPROFILE_ID(sess, obj)) != 0) {
printf("'%lu'\n", id);
} else {
printf("<empty>\n");
}
}
static void
get_token_info(CK_SLOT_ID slot, CK_TOKEN_INFO_PTR info)
{