summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2019-11-06 11:33:14 +0100
committerDaiki Ueno <dueno@redhat.com>2019-11-06 11:33:14 +0100
commit0e52897da7438eae158b1e4b6637116302cb0bf2 (patch)
treeabcdc0f20cc7109477a7519787f53cde40f09ddd
parent34813d0525df1d7976e57c25cdaccb1865ef3668 (diff)
downloadnss-hg-0e52897da7438eae158b1e4b6637116302cb0bf2.tar.gz
Bug 1577803, pk11wrap: set friendly flag if token implements CKP_PUBLIC_CERTIFICATES_TOKEN, r=rrelyea
Summary: This makes NSS look for CKO_PROFILE object at token initialization time to check if it implements the [[ https://docs.oasis-open.org/pkcs11/pkcs11-profiles/v3.0/pkcs11-profiles-v3.0.pdf | Public Certificates Token profile ]] as defined in PKCS #11 v3.0. If it is found, the token is automatically marked as friendly so no authentication attempts will be made when accessing certificates. Reviewers: rrelyea Reviewed By: rrelyea Subscribers: reviewbot Bug #: 1577803 Differential Revision: https://phabricator.services.mozilla.com/D45669
-rw-r--r--gtests/pk11_gtest/pk11_module_unittest.cc17
-rw-r--r--gtests/pkcs11testmodule/pkcs11testmodule.cpp97
-rw-r--r--lib/pk11wrap/debug_module.c31
-rw-r--r--lib/pk11wrap/pk11obj.c26
-rw-r--r--lib/pk11wrap/pk11slot.c81
-rw-r--r--lib/pk11wrap/secmodti.h2
-rw-r--r--lib/util/pkcs11t.h15
7 files changed, 252 insertions, 17 deletions
diff --git a/gtests/pk11_gtest/pk11_module_unittest.cc b/gtests/pk11_gtest/pk11_module_unittest.cc
index 508e1387a..1cc1df06e 100644
--- a/gtests/pk11_gtest/pk11_module_unittest.cc
+++ b/gtests/pk11_gtest/pk11_module_unittest.cc
@@ -51,7 +51,9 @@ TEST_F(Pkcs11ModuleTest, ListSlots) {
// These tokens are always present.
const std::vector<std::string> kSlotsWithToken = {
"NSS Internal Cryptographic Services",
- "NSS User Private Key and Certificate Services", "Test PKCS11 Slot 二"};
+ "NSS User Private Key and Certificate Services",
+ "Test PKCS11 Public Certs Slot",
+ "Test PKCS11 Slot 二"};
std::vector<std::string> foundSlots;
do {
@@ -66,4 +68,17 @@ TEST_F(Pkcs11ModuleTest, ListSlots) {
foundSlots.begin()));
}
+TEST_F(Pkcs11ModuleTest, PublicCertificatesToken) {
+ const std::string kRegularToken = "Test PKCS11 Tokeñ 2 Label";
+ const std::string kPublicCertificatesToken = "Test PKCS11 Public Certs Token";
+
+ ScopedPK11SlotInfo slot1(PK11_FindSlotByName(kRegularToken.c_str()));
+ EXPECT_NE(nullptr, slot1);
+ EXPECT_FALSE(PK11_IsFriendly(slot1.get()));
+
+ ScopedPK11SlotInfo slot2(PK11_FindSlotByName(kPublicCertificatesToken.c_str()));
+ EXPECT_NE(nullptr, slot2);
+ EXPECT_TRUE(PK11_IsFriendly(slot2.get()));
+}
+
} // namespace nss_test
diff --git a/gtests/pkcs11testmodule/pkcs11testmodule.cpp b/gtests/pkcs11testmodule/pkcs11testmodule.cpp
index ea5a0201f..dbb574442 100644
--- a/gtests/pkcs11testmodule/pkcs11testmodule.cpp
+++ b/gtests/pkcs11testmodule/pkcs11testmodule.cpp
@@ -76,17 +76,25 @@ CK_RV Test_C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR) { return CKR_OK; }
static int tokenPresent = 0;
+// The token in slot 4 has 2 objects. Both of them are profile object
+// and identified by object ID 1 or 2.
+static bool readingProfile = false;
+static const CK_PROFILE_ID profiles[] = {CKP_PUBLIC_CERTIFICATES_TOKEN,
+ CKP_BASELINE_PROVIDER};
+static int profileIndex = 0;
+
CK_RV Test_C_GetSlotList(CK_BBOOL limitToTokensPresent,
CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
if (!pulCount) {
return CKR_ARGUMENTS_BAD;
}
- CK_SLOT_ID slots[3];
+ CK_SLOT_ID slots[4];
CK_ULONG slotCount = 0;
- // We always return slot 2.
+ // We always return slot 2 and 4.
slots[slotCount++] = 2;
+ slots[slotCount++] = 4;
// Slot 1 is a removable slot where a token is present if
// tokenPresent = CK_TRUE.
@@ -103,7 +111,7 @@ CK_RV Test_C_GetSlotList(CK_BBOOL limitToTokensPresent,
if (*pulCount < slotCount) {
return CKR_BUFFER_TOO_SMALL;
}
- memcpy(pSlotList, slots, sizeof(CK_ULONG) * slotCount);
+ memcpy(pSlotList, slots, sizeof(CK_SLOT_ID) * slotCount);
}
*pulCount = slotCount;
@@ -113,6 +121,7 @@ CK_RV Test_C_GetSlotList(CK_BBOOL limitToTokensPresent,
static const char TestSlotDescription[] = "Test PKCS11 Slot";
static const char TestSlot2Description[] = "Test PKCS11 Slot 二";
static const char TestSlot3Description[] = "Empty PKCS11 Slot";
+static const char TestSlot4Description[] = "Test PKCS11 Public Certs Slot";
CK_RV Test_C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
if (!pInfo) {
@@ -133,6 +142,10 @@ CK_RV Test_C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
CopyString(pInfo->slotDescription, TestSlot3Description);
pInfo->flags = CKF_REMOVABLE_DEVICE;
break;
+ case 4:
+ CopyString(pInfo->slotDescription, TestSlot4Description);
+ pInfo->flags = CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE;
+ break;
default:
return CKR_ARGUMENTS_BAD;
}
@@ -148,6 +161,7 @@ CK_RV Test_C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
// as UTF-8.
static const char TestTokenLabel[] = "Test PKCS11 Tokeñ Label";
static const char TestToken2Label[] = "Test PKCS11 Tokeñ 2 Label";
+static const char TestToken4Label[] = "Test PKCS11 Public Certs Token";
static const char TestTokenModel[] = "Test Model";
CK_RV Test_C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) {
@@ -162,6 +176,9 @@ CK_RV Test_C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) {
case 2:
CopyString(pInfo->label, TestToken2Label);
break;
+ case 4:
+ CopyString(pInfo->label, TestToken4Label);
+ break;
default:
return CKR_ARGUMENTS_BAD;
}
@@ -223,6 +240,9 @@ CK_RV Test_C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS, CK_VOID_PTR, CK_NOTIFY,
case 2:
*phSession = 2;
break;
+ case 4:
+ *phSession = 4;
+ break;
default:
return CKR_ARGUMENTS_BAD;
}
@@ -247,6 +267,9 @@ CK_RV Test_C_GetSessionInfo(CK_SESSION_HANDLE hSession,
case 2:
pInfo->slotID = 2;
break;
+ case 4:
+ pInfo->slotID = 4;
+ break;
default:
return CKR_ARGUMENTS_BAD;
}
@@ -289,8 +312,27 @@ CK_RV Test_C_GetObjectSize(CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ULONG_PTR) {
return CKR_FUNCTION_NOT_SUPPORTED;
}
-CK_RV Test_C_GetAttributeValue(CK_SESSION_HANDLE, CK_OBJECT_HANDLE,
- CK_ATTRIBUTE_PTR, CK_ULONG) {
+CK_RV Test_C_GetAttributeValue(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE hObject,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) {
+ if (hSession == 4) {
+ assert(hObject >= 1 &&
+ hObject - 1 < sizeof(profiles) / sizeof(profiles[0]));
+ for (CK_ULONG count = 0; count < ulCount; count++) {
+ if (pTemplate[count].type == CKA_PROFILE_ID) {
+ if (pTemplate[count].pValue) {
+ assert(pTemplate[count].ulValueLen == sizeof(CK_ULONG));
+ CK_ULONG value = profiles[hObject - 1];
+ memcpy(pTemplate[count].pValue, &value, sizeof(value));
+ } else {
+ pTemplate[count].ulValueLen = sizeof(CK_ULONG);
+ }
+ } else {
+ pTemplate[count].ulValueLen = (CK_ULONG)-1;
+ }
+ }
+ return CKR_OK;
+ }
return CKR_FUNCTION_NOT_SUPPORTED;
}
@@ -299,17 +341,54 @@ CK_RV Test_C_SetAttributeValue(CK_SESSION_HANDLE, CK_OBJECT_HANDLE,
return CKR_FUNCTION_NOT_SUPPORTED;
}
-CK_RV Test_C_FindObjectsInit(CK_SESSION_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG) {
+CK_RV Test_C_FindObjectsInit(CK_SESSION_HANDLE hSession,
+ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) {
+ // Slot 4
+ if (hSession == 4) {
+ for (CK_ULONG count = 0; count < ulCount; count++) {
+ CK_ATTRIBUTE attribute = pTemplate[count];
+ if (attribute.type == CKA_CLASS) {
+ assert(attribute.ulValueLen == sizeof(CK_ULONG));
+
+ CK_ULONG value;
+ memcpy(&value, attribute.pValue, attribute.ulValueLen);
+ if (value == CKO_PROFILE) {
+ readingProfile = true;
+ profileIndex = 0;
+ break;
+ }
+ }
+ }
+ }
return CKR_OK;
}
-CK_RV Test_C_FindObjects(CK_SESSION_HANDLE, CK_OBJECT_HANDLE_PTR, CK_ULONG,
+CK_RV Test_C_FindObjects(CK_SESSION_HANDLE hSession,
+ CK_OBJECT_HANDLE_PTR phObject,
+ CK_ULONG ulMaxObjectCount,
CK_ULONG_PTR pulObjectCount) {
- *pulObjectCount = 0;
+ if (readingProfile) {
+ assert(hSession == 4);
+ CK_ULONG count = ulMaxObjectCount;
+ size_t remaining = sizeof(profiles) / sizeof(profiles[0]) - profileIndex;
+ if (count > remaining) {
+ count = remaining;
+ }
+ for (CK_ULONG i = 0; i < count; i++) {
+ phObject[i] = i + 1;
+ }
+ profileIndex += count;
+ *pulObjectCount = count;
+ } else {
+ *pulObjectCount = 0;
+ }
return CKR_OK;
}
-CK_RV Test_C_FindObjectsFinal(CK_SESSION_HANDLE) { return CKR_OK; }
+CK_RV Test_C_FindObjectsFinal(CK_SESSION_HANDLE hSession) {
+ readingProfile = false;
+ return CKR_OK;
+}
CK_RV Test_C_EncryptInit(CK_SESSION_HANDLE, CK_MECHANISM_PTR,
CK_OBJECT_HANDLE) {
diff --git a/lib/pk11wrap/debug_module.c b/lib/pk11wrap/debug_module.c
index 59b89c37a..6dddb24b4 100644
--- a/lib/pk11wrap/debug_module.c
+++ b/lib/pk11wrap/debug_module.c
@@ -134,6 +134,7 @@ get_attr_type_str(CK_ATTRIBUTE_TYPE atype, char *str, int len)
CASE(CKA_RESET_ON_INIT);
CASE(CKA_HAS_RESET);
CASE(CKA_VENDOR_DEFINED);
+ CASE(CKA_PROFILE_ID);
CASE(CKA_NSS_URL);
CASE(CKA_NSS_EMAIL);
CASE(CKA_NSS_SMIME_INFO);
@@ -189,6 +190,7 @@ get_obj_class(CK_OBJECT_CLASS objClass, char *str, int len)
CASE(CKO_SECRET_KEY);
CASE(CKO_HW_FEATURE);
CASE(CKO_DOMAIN_PARAMETERS);
+ CASE(CKO_PROFILE);
CASE(CKO_NSS_CRL);
CASE(CKO_NSS_SMIME);
CASE(CKO_NSS_TRUST);
@@ -203,6 +205,27 @@ get_obj_class(CK_OBJECT_CLASS objClass, char *str, int len)
}
static void
+get_profile_val(CK_PROFILE_ID profile, char *str, int len)
+{
+
+ const char *a = NULL;
+
+ switch (profile) {
+ CASE(CKP_INVALID_ID);
+ CASE(CKP_BASELINE_PROVIDER);
+ CASE(CKP_EXTENDED_PROVIDER);
+ CASE(CKP_AUTHENTICATION_TOKEN);
+ CASE(CKP_PUBLIC_CERTIFICATES_TOKEN);
+ default:
+ break;
+ }
+ if (a)
+ PR_snprintf(str, len, "%s", a);
+ else
+ PR_snprintf(str, len, "0x%p", profile);
+}
+
+static void
get_trust_val(CK_TRUST trust, char *str, int len)
{
const char *a = NULL;
@@ -688,6 +711,14 @@ print_attr_value(CK_ATTRIBUTE_PTR attr)
atype, valstr, attr->ulValueLen));
break;
}
+ case CKA_PROFILE_ID:
+ if (attr->ulValueLen > 0 && attr->pValue) {
+ CK_PROFILE_ID profile = *((CK_PROFILE_ID *)attr->pValue);
+ get_profile_val(profile, valstr, sizeof valstr);
+ PR_LOG(modlog, 4, (fmt_s_s_d,
+ atype, valstr, attr->ulValueLen));
+ break;
+ }
case CKA_ISSUER:
case CKA_SUBJECT:
if (attr->ulValueLen > 0 && attr->pValue) {
diff --git a/lib/pk11wrap/pk11obj.c b/lib/pk11wrap/pk11obj.c
index 16ff15a80..bc9e93454 100644
--- a/lib/pk11wrap/pk11obj.c
+++ b/lib/pk11wrap/pk11obj.c
@@ -1830,15 +1830,24 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
{
CK_OBJECT_HANDLE *objID = NULL;
CK_ULONG returned_count = 0;
+ PRBool owner = PR_TRUE;
+ CK_SESSION_HANDLE session;
+ PRBool haslock = PR_FALSE;
CK_RV crv = CKR_SESSION_HANDLE_INVALID;
- PK11_EnterSlotMonitor(slot);
- if (slot->session != CK_INVALID_SESSION) {
- crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,
+ session = pk11_GetNewSession(slot, &owner);
+ haslock = (!owner || !(slot->isThreadSafe));
+ if (haslock) {
+ PK11_EnterSlotMonitor(slot);
+ }
+ if (session != CK_INVALID_SESSION) {
+ crv = PK11_GETTAB(slot)->C_FindObjectsInit(session,
findTemplate, templCount);
}
if (crv != CKR_OK) {
- PK11_ExitSlotMonitor(slot);
+ if (haslock)
+ PK11_ExitSlotMonitor(slot);
+ pk11_CloseSession(slot, session, owner);
PORT_SetError(PK11_MapError(crv));
*object_count = -1;
return NULL;
@@ -1863,7 +1872,7 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
PORT_Free(oldObjID);
break;
}
- crv = PK11_GETTAB(slot)->C_FindObjects(slot->session,
+ crv = PK11_GETTAB(slot)->C_FindObjects(session,
&objID[*object_count], PK11_SEARCH_CHUNKSIZE, &returned_count);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
@@ -1874,8 +1883,11 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
*object_count += returned_count;
} while (returned_count == PK11_SEARCH_CHUNKSIZE);
- PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
- PK11_ExitSlotMonitor(slot);
+ PK11_GETTAB(slot)->C_FindObjectsFinal(session);
+ if (haslock) {
+ PK11_ExitSlotMonitor(slot);
+ }
+ pk11_CloseSession(slot, session, owner);
if (objID && (*object_count == 0)) {
PORT_Free(objID);
diff --git a/lib/pk11wrap/pk11slot.c b/lib/pk11wrap/pk11slot.c
index 12aeddc8a..072294056 100644
--- a/lib/pk11wrap/pk11slot.c
+++ b/lib/pk11wrap/pk11slot.c
@@ -419,6 +419,8 @@ PK11_NewSlotInfo(SECMODModule *mod)
slot->hasRootCerts = PR_FALSE;
slot->hasRootTrust = PR_FALSE;
slot->nssToken = NULL;
+ slot->profileList = NULL;
+ slot->profileCount = 0;
return slot;
}
@@ -446,6 +448,9 @@ PK11_DestroySlot(PK11SlotInfo *slot)
if (slot->mechanismList) {
PORT_Free(slot->mechanismList);
}
+ if (slot->profileList) {
+ PORT_Free(slot->profileList);
+ }
if (slot->isThreadSafe && slot->sessionLock) {
PZ_DestroyLock(slot->sessionLock);
}
@@ -1170,6 +1175,76 @@ PK11_ReadMechanismList(PK11SlotInfo *slot)
return SECSuccess;
}
+static SECStatus
+pk11_ReadProfileList(PK11SlotInfo *slot)
+{
+ CK_ATTRIBUTE findTemp[2];
+ CK_ATTRIBUTE *attrs;
+ CK_BBOOL cktrue = CK_TRUE;
+ CK_OBJECT_CLASS oclass = CKO_PROFILE;
+ int tsize;
+ int objCount;
+ CK_OBJECT_HANDLE *handles = NULL;
+ int i;
+
+ attrs = findTemp;
+ PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue));
+ attrs++;
+ PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass));
+ attrs++;
+ tsize = attrs - findTemp;
+ PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE));
+
+ if (slot->profileList) {
+ PORT_Free(slot->profileList);
+ slot->profileList = NULL;
+ }
+ slot->profileCount = 0;
+
+ objCount = 0;
+ handles = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount);
+ if (handles == NULL) {
+ if (objCount < 0) {
+ return SECFailure; /* error code is set */
+ }
+ PORT_Assert(objCount == 0);
+ return SECSuccess;
+ }
+
+ slot->profileList = (CK_PROFILE_ID *)
+ PORT_Alloc(objCount * sizeof(CK_PROFILE_ID));
+ if (slot->profileList == NULL) {
+ PORT_Free(handles);
+ return SECFailure; /* error code is set */
+ }
+
+ for (i = 0; i < objCount; i++) {
+ CK_ULONG value;
+
+ value = PK11_ReadULongAttribute(slot, handles[i], CKA_PROFILE_ID);
+ if (value == CK_UNAVAILABLE_INFORMATION) {
+ continue;
+ }
+ slot->profileList[slot->profileCount++] = value;
+ }
+
+ PORT_Free(handles);
+ return SECSuccess;
+}
+
+static PRBool
+pk11_HasProfile(PK11SlotInfo *slot, CK_PROFILE_ID id)
+{
+ int i;
+
+ for (i = 0; i < slot->profileCount; i++) {
+ if (slot->profileList[i] == id) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
/*
* initialize a new token
* unlike initialize slot, this can be called multiple times in the lifetime
@@ -1291,6 +1366,11 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts)
if (status != PR_SUCCESS)
return SECFailure;
+ rv = pk11_ReadProfileList(slot);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
if (!(slot->isInternal) && (slot->hasRandom)) {
/* if this slot has a random number generater, use it to add entropy
* to the internal slot. */
@@ -1695,6 +1775,7 @@ PK11_IsFriendly(PK11SlotInfo *slot)
{
/* internal slot always has public readable certs */
return (PRBool)(slot->isInternal ||
+ pk11_HasProfile(slot, CKP_PUBLIC_CERTIFICATES_TOKEN) ||
((slot->defaultFlags & SECMOD_FRIENDLY_FLAG) ==
SECMOD_FRIENDLY_FLAG));
}
diff --git a/lib/pk11wrap/secmodti.h b/lib/pk11wrap/secmodti.h
index 260e6387d..4af20100d 100644
--- a/lib/pk11wrap/secmodti.h
+++ b/lib/pk11wrap/secmodti.h
@@ -111,6 +111,8 @@ struct PK11SlotInfoStr {
CK_TOKEN_INFO tokenInfo;
/* fast mechanism lookup */
char mechanismBits[256];
+ CK_PROFILE_ID *profileList;
+ int profileCount;
};
/* Symetric Key structure. Reference Counted */
diff --git a/lib/util/pkcs11t.h b/lib/util/pkcs11t.h
index 6ee6609a9..d57da409a 100644
--- a/lib/util/pkcs11t.h
+++ b/lib/util/pkcs11t.h
@@ -313,6 +313,7 @@ typedef CK_ULONG CK_OBJECT_CLASS;
/* CKO_HW_FEATURE is new for v2.10 */
/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
/* CKO_MECHANISM is new for v2.20 */
+/* CKO_PROFILE is new for v3.00 */
#define CKO_DATA 0x00000000
#define CKO_CERTIFICATE 0x00000001
#define CKO_PUBLIC_KEY 0x00000002
@@ -321,10 +322,23 @@ typedef CK_ULONG CK_OBJECT_CLASS;
#define CKO_HW_FEATURE 0x00000005
#define CKO_DOMAIN_PARAMETERS 0x00000006
#define CKO_MECHANISM 0x00000007
+#define CKO_PROFILE 0x00000009
#define CKO_VENDOR_DEFINED 0x80000000
typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
+/* CK_PROFILE_ID is new for v3.00. CK_PROFILE_ID is a value that
+ * identifies the profile that the token supports. */
+typedef CK_ULONG CK_PROFILE_ID;
+
+/* Profile ID's */
+#define CKP_INVALID_ID 0x00000000UL
+#define CKP_BASELINE_PROVIDER 0x00000001UL
+#define CKP_EXTENDED_PROVIDER 0x00000002UL
+#define CKP_AUTHENTICATION_TOKEN 0x00000003UL
+#define CKP_PUBLIC_CERTIFICATES_TOKEN 0x00000004UL
+#define CKP_VENDOR_DEFINED 0x80000000UL
+
/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
* value that identifies the hardware feature type of an object
* with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
@@ -536,6 +550,7 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE;
#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x00000600)
+#define CKA_PROFILE_ID 0x00000601UL
#define CKA_VENDOR_DEFINED 0x80000000