Skip to content

Commit

Permalink
Bug 1577803, pk11wrap: set friendly flag if token implements CKP_PUBL…
Browse files Browse the repository at this point in the history
…IC_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

--HG--
extra : amend_source : 58fe6ec6aaa684b0af41843b1a46669537171f0e
  • Loading branch information
ueno committed Nov 6, 2019
1 parent 4214e57 commit c1f069a
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 17 deletions.
17 changes: 16 additions & 1 deletion gtests/pk11_gtest/pk11_module_unittest.cc
Expand Up @@ -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 {
Expand All @@ -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
97 changes: 88 additions & 9 deletions gtests/pkcs11testmodule/pkcs11testmodule.cpp
Expand Up @@ -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.
Expand All @@ -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;
Expand All @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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) {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand All @@ -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) {
Expand Down
31 changes: 31 additions & 0 deletions lib/pk11wrap/debug_module.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -202,6 +204,27 @@ get_obj_class(CK_OBJECT_CLASS objClass, char *str, int len)
PR_snprintf(str, len, "0x%p", objClass);
}

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)
{
Expand Down Expand Up @@ -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) {
Expand Down
26 changes: 19 additions & 7 deletions lib/pk11wrap/pk11obj.c
Expand Up @@ -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;
Expand All @@ -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));
Expand All @@ -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);
Expand Down

0 comments on commit c1f069a

Please sign in to comment.