From 804e6ff53969911514384a8aa3ced0bb32b044e7 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Mon, 23 Jul 2018 10:08:31 +0200 Subject: [PATCH] Bug 1475274, Provide a way to specify tokens by PKCS #11 URI, r=rrelyea Summary: This patch allows client applications to specify tokens unambiguously with PKCS #11 URI, instead of token name. It also includes a minor fixes to PKCS #11 URI handling that previously treated the scheme case sensitively. Reviewers: kaie, rrelyea Bug #: 1475274 Differential Revision: https://phabricator.services.mozilla.com/D2099 --HG-- extra : amend_source : 2c523bef26f62206b178c9ba04833c85cf5492cb --- gtests/util_gtest/util_pkcs11uri_unittest.cc | 1 + lib/pk11wrap/pk11cert.c | 2 +- lib/pk11wrap/pk11slot.c | 86 ++++++++++++-------- lib/util/pkcs11uri.c | 2 +- tests/cert/cert.sh | 18 ++++ 5 files changed, 71 insertions(+), 38 deletions(-) diff --git a/gtests/util_gtest/util_pkcs11uri_unittest.cc b/gtests/util_gtest/util_pkcs11uri_unittest.cc index 5f1d94acf2..680e2f4a2b 100644 --- a/gtests/util_gtest/util_pkcs11uri_unittest.cc +++ b/gtests/util_gtest/util_pkcs11uri_unittest.cc @@ -160,6 +160,7 @@ TEST_F(PK11URITest, ParseRetrieveTest) { TEST_F(PK11URITest, ParseFormatTest) { TestParseFormat("pkcs11:", "pkcs11:"); + TestParseFormat("PKCS11:", "pkcs11:"); TestParseFormat("pkcs11:token=aaa", "pkcs11:token=aaa"); TestParseFormat("pkcs11:token=aaa;manufacturer=bbb", "pkcs11:token=aaa;manufacturer=bbb"); diff --git a/lib/pk11wrap/pk11cert.c b/lib/pk11wrap/pk11cert.c index c1caf5e60b..66d6c40df6 100644 --- a/lib/pk11wrap/pk11cert.c +++ b/lib/pk11wrap/pk11cert.c @@ -741,7 +741,7 @@ find_certs_from_nickname(const char *nickname, void *wincx) char *delimit = NULL; char *tokenName; - if (!strncmp(nickname, "pkcs11:", strlen("pkcs11:"))) { + if (!PORT_Strncasecmp(nickname, "pkcs11:", strlen("pkcs11:"))) { certs = find_certs_from_uri(nickname, wincx); if (certs) return certs; diff --git a/lib/pk11wrap/pk11slot.c b/lib/pk11wrap/pk11slot.c index c39abe17e6..ebe54d4956 100644 --- a/lib/pk11wrap/pk11slot.c +++ b/lib/pk11wrap/pk11slot.c @@ -607,12 +607,32 @@ PK11_FindSlotsByNames(const char *dllName, const char *slotName, return slotList; } -PK11SlotInfo * -PK11_FindSlotByName(const char *name) +typedef PRBool (*PK11SlotMatchFunc)(PK11SlotInfo *slot, const void *arg); + +static PRBool +pk11_MatchSlotByTokenName(PK11SlotInfo *slot, const void *arg) +{ + return PORT_Strcmp(slot->token_name, arg) == 0; +} + +static PRBool +pk11_MatchSlotBySerial(PK11SlotInfo *slot, const void *arg) { + return PORT_Memcmp(slot->serial, arg, sizeof(slot->serial)) == 0; +} + +static PRBool +pk11_MatchSlotByTokenURI(PK11SlotInfo *slot, const void *arg) +{ + return pk11_MatchUriTokenInfo(slot, (PK11URI *)arg); +} + +static PK11SlotInfo * +pk11_FindSlot(const void *arg, PK11SlotMatchFunc func) +{ + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); SECMODModuleList *mlp; SECMODModuleList *modules; - SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); int i; PK11SlotInfo *slot = NULL; @@ -620,10 +640,6 @@ PK11_FindSlotByName(const char *name) PORT_SetError(SEC_ERROR_NOT_INITIALIZED); return slot; } - if ((name == NULL) || (*name == 0)) { - return PK11_GetInternalKeySlot(); - } - /* work through all the slots */ SECMOD_GetReadLock(moduleLock); modules = SECMOD_GetDefaultModuleList(); @@ -631,7 +647,7 @@ PK11_FindSlotByName(const char *name) for (i = 0; i < mlp->module->slotCount; i++) { PK11SlotInfo *tmpSlot = mlp->module->slots[i]; if (PK11_IsPresent(tmpSlot)) { - if (PORT_Strcmp(tmpSlot->token_name, name) == 0) { + if (func(tmpSlot, arg)) { slot = PK11_ReferenceSlot(tmpSlot); break; } @@ -649,43 +665,41 @@ PK11_FindSlotByName(const char *name) return slot; } -PK11SlotInfo * -PK11_FindSlotBySerial(char *serial) +static PK11SlotInfo * +pk11_FindSlotByTokenURI(const char *uriString) { - SECMODModuleList *mlp; - SECMODModuleList *modules; - SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); - int i; PK11SlotInfo *slot = NULL; + PK11URI *uri; - if (!moduleLock) { - PORT_SetError(SEC_ERROR_NOT_INITIALIZED); + uri = PK11URI_ParseURI(uriString); + if (!uri) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); return slot; } - /* work through all the slots */ - SECMOD_GetReadLock(moduleLock); - modules = SECMOD_GetDefaultModuleList(); - for (mlp = modules; mlp != NULL; mlp = mlp->next) { - for (i = 0; i < mlp->module->slotCount; i++) { - PK11SlotInfo *tmpSlot = mlp->module->slots[i]; - if (PK11_IsPresent(tmpSlot)) { - if (PORT_Memcmp(tmpSlot->serial, serial, - sizeof(tmpSlot->serial)) == 0) { - slot = PK11_ReferenceSlot(tmpSlot); - break; - } - } - } - if (slot != NULL) - break; + + slot = pk11_FindSlot(uri, pk11_MatchSlotByTokenURI); + PK11URI_DestroyURI(uri); + return slot; +} + +PK11SlotInfo * +PK11_FindSlotByName(const char *name) +{ + if ((name == NULL) || (*name == 0)) { + return PK11_GetInternalKeySlot(); } - SECMOD_ReleaseReadLock(moduleLock); - if (slot == NULL) { - PORT_SetError(SEC_ERROR_NO_TOKEN); + if (!PORT_Strncasecmp(name, "pkcs11:", strlen("pkcs11:"))) { + return pk11_FindSlotByTokenURI(name); } - return slot; + return pk11_FindSlot(name, pk11_MatchSlotByTokenName); +} + +PK11SlotInfo * +PK11_FindSlotBySerial(char *serial) +{ + return pk11_FindSlot(serial, pk11_MatchSlotBySerial); } /* diff --git a/lib/util/pkcs11uri.c b/lib/util/pkcs11uri.c index 94b00171e9..c29521080b 100644 --- a/lib/util/pkcs11uri.c +++ b/lib/util/pkcs11uri.c @@ -674,7 +674,7 @@ PK11URI_ParseURI(const char *string) const char *p = string; SECStatus ret; - if (strncmp("pkcs11:", p, 7) != 0) { + if (PORT_Strncasecmp("pkcs11:", p, 7) != 0) { return NULL; } p += 7; diff --git a/tests/cert/cert.sh b/tests/cert/cert.sh index 6da2a0be5e..6d0547c9b6 100755 --- a/tests/cert/cert.sh +++ b/tests/cert/cert.sh @@ -2124,6 +2124,23 @@ cert_test_implicit_db_init() certu -A -n ca -t 'C,C,C' -d ${P_R_IMPLICIT_INIT_DIR} -i "${SERVER_CADIR}/serverCA.ca.cert" } +cert_test_token_uri() +{ + echo "$SCRIPTNAME: specify token with PKCS#11 URI" + + CERTIFICATE_DB_URI=`${BINDIR}/certutil -U -f "${R_PWFILE}" -d ${P_R_SERVERDIR} | sed -n 's/^ *uri: \(.*NSS%20Certificate%20DB.*\)/\1/p'` + BUILTIN_OBJECTS_URI=`${BINDIR}/certutil -U -f "${R_PWFILE}" -d ${P_R_SERVERDIR} | sed -n 's/^ *uri: \(.*Builtin%20Object%20Token.*\)/\1/p'` + + CU_ACTION="List keys in NSS Certificate DB" + certu -K -f "${R_PWFILE}" -d ${P_R_SERVERDIR} -h ${CERTIFICATE_DB_URI} + + # This token shouldn't have any keys + CU_ACTION="List keys in NSS Builtin Objects" + RETEXPECTED=255 + certu -K -f "${R_PWFILE}" -d ${P_R_SERVERDIR} -h ${BUILTIN_OBJECTS_URI} + RETEXPECTED=0 +} + check_sign_algo() { certu -L -n "$CERTNAME" -d "${PROFILEDIR}" -f "${R_PWFILE}" | \ @@ -2579,6 +2596,7 @@ cert_test_password cert_test_distrust cert_test_ocspresp cert_test_rsapss +cert_test_token_uri if [ -z "$NSS_TEST_DISABLE_CRL" ] ; then cert_crl_ssl