From f017b749ea9f1586d2308504553d40bf4cc5439d Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 6 Feb 2018 11:46:26 +0100 Subject: Update NSS to 3.32.1-RTM --- security/nss/lib/pk11wrap/dev3hack.c | 4 +- security/nss/lib/pk11wrap/pk11akey.c | 4 + security/nss/lib/pk11wrap/pk11auth.c | 8 +- security/nss/lib/pk11wrap/pk11cert.c | 387 ++++++++++++++++++++++----------- security/nss/lib/pk11wrap/pk11load.c | 26 ++- security/nss/lib/pk11wrap/pk11mech.c | 4 + security/nss/lib/pk11wrap/pk11obj.c | 15 +- security/nss/lib/pk11wrap/pk11pbe.c | 58 ++++- security/nss/lib/pk11wrap/pk11pk12.c | 121 ++++++++++- security/nss/lib/pk11wrap/pk11priv.h | 13 +- security/nss/lib/pk11wrap/pk11pub.h | 8 + security/nss/lib/pk11wrap/pk11skey.c | 9 +- security/nss/lib/pk11wrap/pk11slot.c | 178 +++++++++++++-- security/nss/lib/pk11wrap/pk11util.c | 53 +++++ security/nss/lib/pk11wrap/pk11wrap.gyp | 73 ++++--- security/nss/lib/pk11wrap/secmodti.h | 2 + 16 files changed, 762 insertions(+), 201 deletions(-) (limited to 'security/nss/lib/pk11wrap') diff --git a/security/nss/lib/pk11wrap/dev3hack.c b/security/nss/lib/pk11wrap/dev3hack.c index 27325a55a..39afd6743 100644 --- a/security/nss/lib/pk11wrap/dev3hack.c +++ b/security/nss/lib/pk11wrap/dev3hack.c @@ -114,7 +114,7 @@ nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) rvSlot->base.refCount = 1; rvSlot->base.lock = PZ_NewLock(nssILockOther); rvSlot->base.arena = arena; - rvSlot->pk11slot = nss3slot; + rvSlot->pk11slot = PK11_ReferenceSlot(nss3slot); rvSlot->epv = nss3slot->functionList; rvSlot->slotID = nss3slot->slotID; /* Grab the slot name from the PKCS#11 fixed-length buffer */ @@ -150,7 +150,7 @@ nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) return NULL; } rvToken->base.arena = arena; - rvToken->pk11slot = nss3slot; + rvToken->pk11slot = PK11_ReferenceSlot(nss3slot); rvToken->epv = nss3slot->functionList; rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena, nss3slot->session, diff --git a/security/nss/lib/pk11wrap/pk11akey.c b/security/nss/lib/pk11wrap/pk11akey.c index 01d1d7fd9..c45901ec3 100644 --- a/security/nss/lib/pk11wrap/pk11akey.c +++ b/security/nss/lib/pk11wrap/pk11akey.c @@ -886,6 +886,10 @@ PK11_GetPrivateModulusLen(SECKEYPrivateKey *key) PORT_SetError(PK11_MapError(crv)); return -1; } + if (theTemplate.pValue == NULL) { + PORT_SetError(PK11_MapError(CKR_ATTRIBUTE_VALUE_INVALID)); + return -1; + } length = theTemplate.ulValueLen; if (*(unsigned char *)theTemplate.pValue == 0) { length--; diff --git a/security/nss/lib/pk11wrap/pk11auth.c b/security/nss/lib/pk11wrap/pk11auth.c index 4ccfad6f1..625fa2dc6 100644 --- a/security/nss/lib/pk11wrap/pk11auth.c +++ b/security/nss/lib/pk11wrap/pk11auth.c @@ -704,9 +704,11 @@ PRBool PK11_NeedPWInit() { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); - PRBool ret = PK11_NeedPWInitForSlot(slot); - - PK11_FreeSlot(slot); + PRBool ret = PR_FALSE; + if (slot) { + ret = PK11_NeedPWInitForSlot(slot); + PK11_FreeSlot(slot); + } return ret; } diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index 6968ae70a..c1caf5e60 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -34,6 +34,8 @@ #include "pkitm.h" #include "pkistore.h" /* to remove temp cert */ #include "devt.h" +#include "ckhelper.h" +#include "pkcs11uri.h" extern const NSSError NSS_ERROR_NOT_FOUND; extern const NSSError NSS_ERROR_INVALID_CERTIFICATE; @@ -507,15 +509,231 @@ transfer_token_certs_to_collection(nssList *certList, NSSToken *token, nss_ZFreeIf(certs); } -CERTCertificate * -PK11_FindCertFromNickname(const char *nickname, void *wincx) +static void +transfer_uri_certs_to_collection(nssList *certList, PK11URI *uri, + nssPKIObjectCollection *collection) +{ + + NSSCertificate **certs; + PRUint32 i, count; + NSSToken **tokens, **tp; + PK11SlotInfo *slot; + const char *id; + + id = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_ID); + count = nssList_Count(certList); + if (count == 0) { + return; + } + certs = nss_ZNEWARRAY(NULL, NSSCertificate *, count); + if (!certs) { + return; + } + nssList_GetArray(certList, (void **)certs, count); + for (i = 0; i < count; i++) { + /* + * Filter the subject matched certs based on the + * CKA_ID from the URI + */ + if (id && (strlen(id) != certs[i]->id.size || + memcmp(id, certs[i]->id.data, certs[i]->id.size))) + continue; + tokens = nssPKIObject_GetTokens(&certs[i]->object, NULL); + if (tokens) { + for (tp = tokens; *tp; tp++) { + const char *value; + slot = (*tp)->pk11slot; + + value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_TOKEN); + if (value && + !pk11_MatchString(value, + (char *)slot->tokenInfo.label, + sizeof(slot->tokenInfo.label))) { + continue; + } + + value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_MANUFACTURER); + if (value && + !pk11_MatchString(value, + (char *)slot->tokenInfo.manufacturerID, + sizeof(slot->tokenInfo.manufacturerID))) { + continue; + } + + value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_MODEL); + if (value && + !pk11_MatchString(value, + (char *)slot->tokenInfo.model, + sizeof(slot->tokenInfo.model))) { + continue; + } + + nssPKIObjectCollection_AddObject(collection, + (nssPKIObject *)certs[i]); + break; + } + nssTokenArray_Destroy(tokens); + } + CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(certs[i])); + } + nss_ZFreeIf(certs); +} + +static NSSCertificate ** +find_certs_from_uri(const char *uriString, void *wincx) { + PK11URI *uri = NULL; + CK_ATTRIBUTE attributes[10]; + CK_ULONG nattributes = 0; + const char *label; + PK11SlotInfo *slotinfo; + nssCryptokiObject **instances; PRStatus status; - CERTCertificate *rvCert = NULL; - NSSCertificate *cert = NULL; + nssPKIObjectCollection *collection = NULL; + NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); NSSCertificate **certs = NULL; + nssList *certList = NULL; + SECStatus rv; + CK_OBJECT_CLASS s_class = CKO_CERTIFICATE; + static const CK_BBOOL s_true = CK_TRUE; + NSSToken **tokens, **tok; + + uri = PK11URI_ParseURI(uriString); + if (uri == NULL) { + goto loser; + } + + collection = nssCertificateCollection_Create(defaultTD, NULL); + if (!collection) { + goto loser; + } + certList = nssList_Create(NULL, PR_FALSE); + if (!certList) { + goto loser; + } + + label = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_OBJECT); + if (label) { + (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, + (const char *)label, + certList); + } else { + (void)nssTrustDomain_GetCertsFromCache(defaultTD, certList); + } + + transfer_uri_certs_to_collection(certList, uri, collection); + + /* add the CKA_CLASS and CKA_TOKEN attributes manually */ + attributes[nattributes].type = CKA_CLASS; + attributes[nattributes].pValue = (void *)&s_class; + attributes[nattributes].ulValueLen = sizeof(s_class); + nattributes++; + + attributes[nattributes].type = CKA_TOKEN; + attributes[nattributes].pValue = (void *)&s_true; + attributes[nattributes].ulValueLen = sizeof(s_true); + nattributes++; + + if (label) { + attributes[nattributes].type = CKA_LABEL; + attributes[nattributes].pValue = (void *)label; + attributes[nattributes].ulValueLen = strlen(label); + nattributes++; + } + + tokens = NSSTrustDomain_FindTokensByURI(defaultTD, uri); + for (tok = tokens; tok && *tok; tok++) { + if (nssToken_IsPresent(*tok)) { + slotinfo = (*tok)->pk11slot; + + rv = pk11_AuthenticateUnfriendly(slotinfo, PR_TRUE, wincx); + if (rv != SECSuccess) { + continue; + } + instances = nssToken_FindObjectsByTemplate(*tok, NULL, + attributes, + nattributes, + 0, &status); + nssPKIObjectCollection_AddInstances(collection, instances, 0); + nss_ZFreeIf(instances); + } + nssToken_Destroy(*tok); + } + nss_ZFreeIf(tokens); + nssList_Destroy(certList); + certs = nssPKIObjectCollection_GetCertificates(collection, NULL, 0, NULL); + +loser: + if (collection) { + nssPKIObjectCollection_Destroy(collection); + } + if (uri) { + PK11URI_DestroyURI(uri); + } + return certs; +} + +CERTCertificate * +PK11_FindCertFromURI(const char *uri, void *wincx) +{ static const NSSUsage usage = { PR_TRUE /* ... */ }; - NSSToken *token; + NSSCertificate *cert = NULL; + NSSCertificate **certs = NULL; + CERTCertificate *rvCert = NULL; + + certs = find_certs_from_uri(uri, wincx); + if (certs) { + cert = nssCertificateArray_FindBestCertificate(certs, NULL, + &usage, NULL); + if (cert) { + rvCert = STAN_GetCERTCertificateOrRelease(cert); + } + nssCertificateArray_Destroy(certs); + } + return rvCert; +} + +CERTCertList * +PK11_FindCertsFromURI(const char *uri, void *wincx) +{ + int i; + CERTCertList *certList = NULL; + NSSCertificate **foundCerts; + NSSCertificate *c; + + foundCerts = find_certs_from_uri(uri, wincx); + if (foundCerts) { + PRTime now = PR_Now(); + certList = CERT_NewCertList(); + for (i = 0, c = *foundCerts; c; c = foundCerts[++i]) { + if (certList) { + CERTCertificate *certCert = STAN_GetCERTCertificateOrRelease(c); + /* c may be invalid after this, don't reference it */ + if (certCert) { + /* CERT_AddCertToListSorted adopts certCert */ + CERT_AddCertToListSorted(certList, certCert, + CERT_SortCBValidity, &now); + } + } else { + nssCertificate_Destroy(c); + } + } + if (certList && CERT_LIST_HEAD(certList) == NULL) { + CERT_DestroyCertList(certList); + certList = NULL; + } + /* all the certs have been adopted or freed, free the raw array */ + nss_ZFreeIf(foundCerts); + } + return certList; +} + +static NSSCertificate ** +find_certs_from_nickname(const char *nickname, void *wincx) +{ + PRStatus status; + NSSCertificate **certs = NULL; + NSSToken *token = NULL; NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); PK11SlotInfo *slot = NULL; SECStatus rv; @@ -523,6 +741,11 @@ PK11_FindCertFromNickname(const char *nickname, void *wincx) char *delimit = NULL; char *tokenName; + if (!strncmp(nickname, "pkcs11:", strlen("pkcs11:"))) { + certs = find_certs_from_uri(nickname, wincx); + if (certs) + return certs; + } nickCopy = PORT_Strdup(nickname); if (!nickCopy) { /* error code is set */ @@ -543,6 +766,11 @@ PK11_FindCertFromNickname(const char *nickname, void *wincx) } else { slot = PK11_GetInternalKeySlot(); token = PK11Slot_GetNSSToken(slot); + if (token) { + nssToken_AddRef(token); + } else { + PORT_SetError(SEC_ERROR_NO_TOKEN); + } } if (token) { nssList *certList; @@ -600,29 +828,38 @@ PK11_FindCertFromNickname(const char *nickname, void *wincx) certs = nssPKIObjectCollection_GetCertificates(collection, NULL, 0, NULL); nssPKIObjectCollection_Destroy(collection); - if (certs) { - cert = nssCertificateArray_FindBestCertificate(certs, NULL, - &usage, NULL); - if (cert) { - rvCert = STAN_GetCERTCertificateOrRelease(cert); - } - nssCertificateArray_Destroy(certs); - } nssList_Destroy(certList); } - if (slot) { - PK11_FreeSlot(slot); - } - if (nickCopy) - PORT_Free(nickCopy); - return rvCert; loser: + if (token) { + nssToken_Destroy(token); + } if (slot) { PK11_FreeSlot(slot); } if (nickCopy) PORT_Free(nickCopy); - return NULL; + return certs; +} + +CERTCertificate * +PK11_FindCertFromNickname(const char *nickname, void *wincx) +{ + CERTCertificate *rvCert = NULL; + NSSCertificate *cert = NULL; + NSSCertificate **certs = NULL; + static const NSSUsage usage = { PR_TRUE /* ... */ }; + + certs = find_certs_from_nickname(nickname, wincx); + if (certs) { + cert = nssCertificateArray_FindBestCertificate(certs, NULL, + &usage, NULL); + if (cert) { + rvCert = STAN_GetCERTCertificateOrRelease(cert); + } + nssCertificateArray_Destroy(certs); + } + return rvCert; } /* Traverse slots callback */ @@ -690,8 +927,7 @@ PK11_FindCertsFromEmailAddress(const char *email, void *wincx) } /* empty list? */ - if (CERT_LIST_HEAD(cbparam.certList) == NULL || - CERT_LIST_END(CERT_LIST_HEAD(cbparam.certList), cbparam.certList)) { + if (CERT_LIST_EMPTY(cbparam.certList)) { CERT_DestroyCertList(cbparam.certList); cbparam.certList = NULL; } @@ -703,111 +939,12 @@ PK11_FindCertsFromEmailAddress(const char *email, void *wincx) CERTCertList * PK11_FindCertsFromNickname(const char *nickname, void *wincx) { - char *nickCopy; - char *delimit = NULL; - char *tokenName; int i; CERTCertList *certList = NULL; - nssPKIObjectCollection *collection = NULL; NSSCertificate **foundCerts = NULL; - NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); NSSCertificate *c; - NSSToken *token; - PK11SlotInfo *slot; - SECStatus rv; - - nickCopy = PORT_Strdup(nickname); - if (!nickCopy) { - /* error code is set */ - return NULL; - } - if ((delimit = PORT_Strchr(nickCopy, ':')) != NULL) { - tokenName = nickCopy; - nickname = delimit + 1; - *delimit = '\0'; - /* find token by name */ - token = NSSTrustDomain_FindTokenByName(defaultTD, (NSSUTF8 *)tokenName); - if (token) { - slot = PK11_ReferenceSlot(token->pk11slot); - } else { - PORT_SetError(SEC_ERROR_NO_TOKEN); - slot = NULL; - } - *delimit = ':'; - } else { - slot = PK11_GetInternalKeySlot(); - token = PK11Slot_GetNSSToken(slot); - } - if (token) { - PRStatus status; - nssList *nameList; - nssCryptokiObject **instances; - nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; - rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); - if (rv != SECSuccess) { - PK11_FreeSlot(slot); - if (nickCopy) - PORT_Free(nickCopy); - return NULL; - } - collection = nssCertificateCollection_Create(defaultTD, NULL); - if (!collection) { - PK11_FreeSlot(slot); - if (nickCopy) - PORT_Free(nickCopy); - return NULL; - } - nameList = nssList_Create(NULL, PR_FALSE); - if (!nameList) { - PK11_FreeSlot(slot); - if (nickCopy) - PORT_Free(nickCopy); - return NULL; - } - (void)nssTrustDomain_GetCertsForNicknameFromCache(defaultTD, - nickname, - nameList); - transfer_token_certs_to_collection(nameList, token, collection); - instances = nssToken_FindCertificatesByNickname(token, - NULL, - nickname, - tokenOnly, - 0, - &status); - nssPKIObjectCollection_AddInstances(collection, instances, 0); - nss_ZFreeIf(instances); - - /* if it wasn't found, repeat the process for email address */ - if (nssPKIObjectCollection_Count(collection) == 0 && - PORT_Strchr(nickname, '@') != NULL) { - char *lowercaseName = CERT_FixupEmailAddr(nickname); - if (lowercaseName) { - (void)nssTrustDomain_GetCertsForEmailAddressFromCache(defaultTD, - lowercaseName, - nameList); - transfer_token_certs_to_collection(nameList, token, collection); - instances = nssToken_FindCertificatesByEmail(token, - NULL, - lowercaseName, - tokenOnly, - 0, - &status); - nssPKIObjectCollection_AddInstances(collection, instances, 0); - nss_ZFreeIf(instances); - PORT_Free(lowercaseName); - } - } - nssList_Destroy(nameList); - foundCerts = nssPKIObjectCollection_GetCertificates(collection, - NULL, 0, NULL); - nssPKIObjectCollection_Destroy(collection); - } - if (slot) { - PK11_FreeSlot(slot); - } - if (nickCopy) - PORT_Free(nickCopy); + foundCerts = find_certs_from_nickname(nickname, wincx); if (foundCerts) { PRTime now = PR_Now(); certList = CERT_NewCertList(); @@ -824,10 +961,6 @@ PK11_FindCertsFromNickname(const char *nickname, void *wincx) nssCertificate_Destroy(c); } } - if (certList && CERT_LIST_HEAD(certList) == NULL) { - CERT_DestroyCertList(certList); - certList = NULL; - } /* all the certs have been adopted or freed, free the raw array */ nss_ZFreeIf(foundCerts); } @@ -979,8 +1112,10 @@ PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, nssCertificateStore_RemoveCertLOCKED(cc->certStore, c); nssCertificateStore_Unlock(cc->certStore, &lockTrace, &unlockTrace); c->object.cryptoContext = NULL; + CERT_LockCertTempPerm(cert); cert->istemp = PR_FALSE; cert->isperm = PR_TRUE; + CERT_UnlockCertTempPerm(cert); } /* add the new instance to the cert, force an update of the diff --git a/security/nss/lib/pk11wrap/pk11load.c b/security/nss/lib/pk11wrap/pk11load.c index f12d0fd4f..91339fad8 100644 --- a/security/nss/lib/pk11wrap/pk11load.c +++ b/security/nss/lib/pk11wrap/pk11load.c @@ -17,6 +17,10 @@ #include "secerr.h" #include "prenv.h" #include "utilparst.h" +#include "prio.h" +#include "prprf.h" +#include +#include "prsystem.h" #define DEBUG_MODULE 1 @@ -350,6 +354,7 @@ SECMOD_SetRootCerts(PK11SlotInfo *slot, SECMODModule *mod) } } +#ifndef NSS_TEST_BUILD static const char *my_shlib_name = SHLIB_PREFIX "nss" SHLIB_VERSION "." SHLIB_SUFFIX; static const char *softoken_shlib_name = @@ -359,11 +364,6 @@ static PRCallOnceType loadSoftokenOnce; static PRLibrary *softokenLib; static PRInt32 softokenLoadCount; -#include "prio.h" -#include "prprf.h" -#include -#include "prsystem.h" - /* This function must be run only once. */ /* determine if hybrid platform, then actually load the DSO. */ static PRStatus @@ -380,6 +380,10 @@ softoken_LoadDSO(void) } return PR_FAILURE; } +#else +CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList); +char **NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args); +#endif /* * load a new module into our address space and initialize it. @@ -398,8 +402,11 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) if (mod->loaded) return SECSuccess; - /* intenal modules get loaded from their internal list */ + /* internal modules get loaded from their internal list */ if (mod->internal && (mod->dllName == NULL)) { +#ifdef NSS_TEST_BUILD + entry = (CK_C_GetFunctionList)NSC_GetFunctionList; +#else /* * Loads softoken as a dynamic library, * even though the rest of NSS assumes this as the "internal" module. @@ -420,10 +427,15 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) if (!entry) return SECFailure; +#endif if (mod->isModuleDB) { mod->moduleDBFunc = (CK_C_GetFunctionList) +#ifdef NSS_TEST_BUILD + NSC_ModuleDBFunc; +#else PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc"); +#endif } if (mod->moduleDBOnly) { @@ -601,6 +613,7 @@ SECMOD_UnloadModule(SECMODModule *mod) * if not, we should change this to SECFailure and move it above the * mod->loaded = PR_FALSE; */ if (mod->internal && (mod->dllName == NULL)) { +#ifndef NSS_TEST_BUILD if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) { if (softokenLib) { disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD"); @@ -616,6 +629,7 @@ SECMOD_UnloadModule(SECMODModule *mod) } loadSoftokenOnce = pristineCallOnce; } +#endif return SECSuccess; } diff --git a/security/nss/lib/pk11wrap/pk11mech.c b/security/nss/lib/pk11wrap/pk11mech.c index 4db05ff39..48e50dff4 100644 --- a/security/nss/lib/pk11wrap/pk11mech.c +++ b/security/nss/lib/pk11wrap/pk11mech.c @@ -612,6 +612,10 @@ PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size) case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: + case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN: + case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN: + case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN: + case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: diff --git a/security/nss/lib/pk11wrap/pk11obj.c b/security/nss/lib/pk11wrap/pk11obj.c index 18850b29d..47c56154d 100644 --- a/security/nss/lib/pk11wrap/pk11obj.c +++ b/security/nss/lib/pk11wrap/pk11obj.c @@ -156,8 +156,8 @@ PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, * check to see if a bool has been set. */ CK_BBOOL -PK11_HasAttributeSet(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, - CK_ATTRIBUTE_TYPE type, PRBool haslock) +pk11_HasAttributeSet_Lock(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, + CK_ATTRIBUTE_TYPE type, PRBool haslock) { CK_BBOOL ckvalue = CK_FALSE; CK_ATTRIBUTE theTemplate; @@ -181,6 +181,14 @@ PK11_HasAttributeSet(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, return ckvalue; } +CK_BBOOL +PK11_HasAttributeSet(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, + CK_ATTRIBUTE_TYPE type, PRBool haslock) +{ + PR_ASSERT(haslock == PR_FALSE); + return pk11_HasAttributeSet_Lock(slot, id, type, PR_FALSE); +} + /* * returns a full list of attributes. Allocate space for them. If an arena is * provided, allocate space out of the arena. @@ -2020,6 +2028,9 @@ PK11_FindObjectsFromNickname(char *nickname, PK11SlotInfo **slotptr, if ((delimit = PORT_Strchr(nickname, ':')) != NULL) { int len = delimit - nickname; tokenName = (char *)PORT_Alloc(len + 1); + if (!tokenName) { + return CK_INVALID_HANDLE; + } PORT_Memcpy(tokenName, nickname, len); tokenName[len] = 0; diff --git a/security/nss/lib/pk11wrap/pk11pbe.c b/security/nss/lib/pk11wrap/pk11pbe.c index 7837bfe9c..bea9333f6 100644 --- a/security/nss/lib/pk11wrap/pk11pbe.c +++ b/security/nss/lib/pk11wrap/pk11pbe.c @@ -4,6 +4,7 @@ #include "plarena.h" +#include "blapit.h" #include "seccomon.h" #include "secitem.h" #include "secport.h" @@ -301,17 +302,49 @@ SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen) return SEC_OID_UNKNOWN; } +static PRBool +sec_pkcs5_is_algorithm_v2_aes_algorithm(SECOidTag algorithm) +{ + switch (algorithm) { + case SEC_OID_AES_128_CBC: + case SEC_OID_AES_192_CBC: + case SEC_OID_AES_256_CBC: + return PR_TRUE; + default: + return PR_FALSE; + } +} + +static int +sec_pkcs5v2_aes_key_length(SECOidTag algorithm) +{ + switch (algorithm) { + /* The key length for the AES-CBC-Pad algorithms are + * determined from the undelying cipher algorithm. */ + case SEC_OID_AES_128_CBC: + return AES_128_KEY_LENGTH; + case SEC_OID_AES_192_CBC: + return AES_192_KEY_LENGTH; + case SEC_OID_AES_256_CBC: + return AES_256_KEY_LENGTH; + default: + break; + } + return 0; +} + /* * get the key length in bytes from a PKCS5 PBE */ -int -sec_pkcs5v2_key_length(SECAlgorithmID *algid) +static int +sec_pkcs5v2_key_length(SECAlgorithmID *algid, SECAlgorithmID *cipherAlgId) { SECOidTag algorithm; PLArenaPool *arena = NULL; SEC_PKCS5PBEParameter p5_param; SECStatus rv; int length = -1; + SECOidTag cipherAlg = SEC_OID_UNKNOWN; algorithm = SECOID_GetAlgorithmTag(algid); /* sanity check, they should all be PBKDF2 here */ @@ -330,8 +363,20 @@ sec_pkcs5v2_key_length(SECAlgorithmID *algid) goto loser; } - if (p5_param.keyLength.data != NULL) { + if (cipherAlgId) + cipherAlg = SECOID_GetAlgorithmTag(cipherAlgId); + + if (sec_pkcs5_is_algorithm_v2_aes_algorithm(cipherAlg)) { + length = sec_pkcs5v2_aes_key_length(cipherAlg); + } else if (p5_param.keyLength.data != NULL) { length = DER_GetInteger(&p5_param.keyLength); + } else { + CK_MECHANISM_TYPE cipherMech; + cipherMech = PK11_AlgtagToMechanism(cipherAlg); + if (cipherMech == CKM_INVALID_MECHANISM) { + goto loser; + } + length = PK11_GetMaxKeyLength(cipherMech); } loser: @@ -375,14 +420,15 @@ SEC_PKCS5GetKeyLength(SECAlgorithmID *algid) case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: return 16; case SEC_OID_PKCS5_PBKDF2: - return sec_pkcs5v2_key_length(algid); + return sec_pkcs5v2_key_length(algid, NULL); case SEC_OID_PKCS5_PBES2: case SEC_OID_PKCS5_PBMAC1: { sec_pkcs5V2Parameter *pbeV2_param; int length = -1; pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); if (pbeV2_param != NULL) { - length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId); + length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId, + &pbeV2_param->cipherAlgId); sec_pkcs5_v2_destroy_v2_param(pbeV2_param); } return length; @@ -614,6 +660,8 @@ sec_pkcs5CreateAlgorithmID(SECOidTag algorithm, SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm); if (hashAlg != SEC_OID_UNKNOWN) { keyLength = HASH_ResultLenByOidTag(hashAlg); + } else if (sec_pkcs5_is_algorithm_v2_aes_algorithm(cipherAlgorithm)) { + keyLength = sec_pkcs5v2_aes_key_length(cipherAlgorithm); } else { CK_MECHANISM_TYPE cryptoMech; cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm); diff --git a/security/nss/lib/pk11wrap/pk11pk12.c b/security/nss/lib/pk11wrap/pk11pk12.c index 1683cc564..d753b87e5 100644 --- a/security/nss/lib/pk11wrap/pk11pk12.c +++ b/security/nss/lib/pk11wrap/pk11pk12.c @@ -64,6 +64,19 @@ struct SECKEYDHPrivateKeyStr { }; typedef struct SECKEYDHPrivateKeyStr SECKEYDHPrivateKey; +/* +** Elliptic Curve Private Key structures +** +*/ +struct SECKEYECPrivateKeyStr { + PLArenaPool *arena; + SECItem version; + SECItem curveOID; /* optional/ignored */ + SECItem publicValue; /* required (for now) */ + SECItem privateValue; +}; +typedef struct SECKEYECPrivateKeyStr SECKEYECPrivateKey; + /* ** raw private key object */ @@ -74,6 +87,7 @@ struct SECKEYRawPrivateKeyStr { SECKEYRSAPrivateKey rsa; SECKEYDSAPrivateKey dsa; SECKEYDHPrivateKey dh; + SECKEYECPrivateKey ec; } u; }; typedef struct SECKEYRawPrivateKeyStr SECKEYRawPrivateKey; @@ -139,6 +153,33 @@ const SEC_ASN1Template SECKEY_DHPrivateKeyExportTemplate[] = { { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.prime) }, }; +#ifndef NSS_DISABLE_ECC +SEC_ASN1_MKSUB(SEC_BitStringTemplate) +SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) + +const SEC_ASN1Template SECKEY_ECPrivateKeyExportTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) }, + { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.ec.version) }, + { SEC_ASN1_OCTET_STRING, + offsetof(SECKEYRawPrivateKey, u.ec.privateValue) }, + /* This value will always be ignored. u.ec.curveOID will always be + * overriden with the outer AlgorithmID.parameters. */ + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_XTRN | 0, + offsetof(SECKEYRawPrivateKey, u.ec.curveOID), + SEC_ASN1_SUB(SEC_ObjectIDTemplate) }, + /* The public value is optional per RFC, but required in NSS. We + * can't do scalar mult on ECs to get a raw point with PK11 APIs. */ + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | + SEC_ASN1_XTRN | 1, + offsetof(SECKEYRawPrivateKey, u.ec.publicValue), + SEC_ASN1_SUB(SEC_BitStringTemplate) }, + { 0 } +}; +#endif /* NSS_DISABLE_ECC */ + const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) }, @@ -198,6 +239,15 @@ prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey *key) key->u.dh.base.type = siUnsignedInteger; } +static void +prepare_ec_priv_key_export_for_asn1(SECKEYRawPrivateKey *key) +{ + key->u.ec.version.type = siUnsignedInteger; + key->u.ec.curveOID.type = siUnsignedInteger; + key->u.ec.privateValue.type = siUnsignedInteger; + key->u.ec.publicValue.type = siUnsignedInteger; +} + SECStatus PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI, SECItem *nickname, SECItem *publicValue, PRBool isPerm, @@ -432,7 +482,50 @@ PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, lpk->u.dh.privateValue.len); attrs++; break; - /* what about fortezza??? */ +#ifndef NSS_DISABLE_ECC + case ecKey: + keyType = CKK_EC; + if (lpk->u.ec.publicValue.len == 0) { + goto loser; + } + if (PK11_IsInternal(slot)) { + PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, + lpk->u.ec.publicValue.data, + lpk->u.ec.publicValue.len); + attrs++; + } + PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue + : &ckfalse, + sizeof(CK_BBOOL)); + attrs++; + PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, + (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue + : &ckfalse, + sizeof(CK_BBOOL)); + attrs++; + PK11_SETATTRS(attrs, CKA_DERIVE, (keyUsage & KU_KEY_AGREEMENT) ? &cktrue + : &ckfalse, + sizeof(CK_BBOOL)); + attrs++; + ck_id = PK11_MakeIDFromPubKey(&lpk->u.ec.publicValue); + if (ck_id == NULL) { + goto loser; + } + PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len); + attrs++; + signedattr = attrs; + /* curveOID always is a copy of AlgorithmID.parameters. */ + PK11_SETATTRS(attrs, CKA_EC_PARAMS, lpk->u.ec.curveOID.data, + lpk->u.ec.curveOID.len); + attrs++; + PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.ec.privateValue.data, + lpk->u.ec.privateValue.len); + attrs++; + PK11_SETATTRS(attrs, CKA_EC_POINT, lpk->u.ec.publicValue.data, + lpk->u.ec.publicValue.len); + attrs++; + break; +#endif /* NSS_DISABLE_ECC */ default: PORT_SetError(SEC_ERROR_BAD_KEY); goto loser; @@ -513,6 +606,15 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, paramDest = NULL; lpk->keyType = dhKey; break; +#ifndef NSS_DISABLE_ECC + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + prepare_ec_priv_key_export_for_asn1(lpk); + keyTemplate = SECKEY_ECPrivateKeyExportTemplate; + paramTemplate = NULL; + paramDest = NULL; + lpk->keyType = ecKey; + break; +#endif /* NSS_DISABLE_ECC */ default: keyTemplate = NULL; @@ -526,10 +628,25 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, } /* decode the private key and any algorithm parameters */ - rv = SEC_ASN1DecodeItem(arena, lpk, keyTemplate, &pki->privateKey); + rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey); if (rv != SECSuccess) { goto loser; } + +#ifndef NSS_DISABLE_ECC + if (lpk->keyType == ecKey) { + /* Convert length in bits to length in bytes. */ + lpk->u.ec.publicValue.len >>= 3; + + /* Always override curveOID, we're ignoring any given value. */ + rv = SECITEM_CopyItem(arena, &lpk->u.ec.curveOID, + &pki->algorithm.parameters); + if (rv != SECSuccess) { + goto loser; + } + } +#endif /* NSS_DISABLE_ECC */ + if (paramDest && paramTemplate) { rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate, &(pki->algorithm.parameters)); diff --git a/security/nss/lib/pk11wrap/pk11priv.h b/security/nss/lib/pk11wrap/pk11priv.h index 45a60b42a..9281923fa 100644 --- a/security/nss/lib/pk11wrap/pk11priv.h +++ b/security/nss/lib/pk11wrap/pk11priv.h @@ -14,6 +14,7 @@ #include "seccomon.h" #include "pkcs7t.h" #include "cmsreclist.h" +#include "pkcs11uri.h" /* * These are the private NSS functions. They are not exported by nss.def, and @@ -39,12 +40,15 @@ int PK11_GetMaxKeyLength(CK_MECHANISM_TYPE type); * Generic Slot Management ************************************************************/ CK_OBJECT_HANDLE PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject); +PRBool pk11_MatchUriTokenInfo(PK11SlotInfo *slot, PK11URI *uri); SECStatus PK11_ReadAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type, PLArenaPool *arena, SECItem *result); CK_ULONG PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type); char *PK11_MakeString(PLArenaPool *arena, char *space, char *staticSring, int stringLen); +PRBool pk11_MatchString(const char *string, + const char *staticString, int staticStringLen); int PK11_MapError(CK_RV error); CK_SESSION_HANDLE PK11_GetRWSession(PK11SlotInfo *slot); void PK11_RestoreROSession(PK11SlotInfo *slot, CK_SESSION_HANDLE rwsession); @@ -106,6 +110,7 @@ CK_OBJECT_HANDLE PK11_FindObjectForCert(CERTCertificate *cert, void *wincx, PK11SlotInfo **pSlot); PK11SymKey *pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey); +unsigned int pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType); /********************************************************************** * Certs @@ -118,10 +123,10 @@ CK_OBJECT_HANDLE *PK11_FindObjectsFromNickname(char *nickname, void *wincx); CK_OBJECT_HANDLE PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE peer, CK_OBJECT_CLASS o_class); -CK_BBOOL PK11_HasAttributeSet(PK11SlotInfo *slot, - CK_OBJECT_HANDLE id, - CK_ATTRIBUTE_TYPE type, - PRBool haslock); +CK_BBOOL pk11_HasAttributeSet_Lock(PK11SlotInfo *slot, + CK_OBJECT_HANDLE id, + CK_ATTRIBUTE_TYPE type, + PRBool haslock); CK_RV PK11_GetAttributes(PLArenaPool *arena, PK11SlotInfo *slot, CK_OBJECT_HANDLE obj, CK_ATTRIBUTE *attr, int count); int PK11_NumberCertsForCertSubject(CERTCertificate *cert); diff --git a/security/nss/lib/pk11wrap/pk11pub.h b/security/nss/lib/pk11wrap/pk11pub.h index e11af86ad..edfe82f5a 100644 --- a/security/nss/lib/pk11wrap/pk11pub.h +++ b/security/nss/lib/pk11wrap/pk11pub.h @@ -76,6 +76,7 @@ PRBool PK11_IsReadOnly(PK11SlotInfo *slot); PRBool PK11_IsInternal(PK11SlotInfo *slot); PRBool PK11_IsInternalKeySlot(PK11SlotInfo *slot); char *PK11_GetTokenName(PK11SlotInfo *slot); +char *PK11_GetTokenURI(PK11SlotInfo *slot); char *PK11_GetSlotName(PK11SlotInfo *slot); PRBool PK11_NeedLogin(PK11SlotInfo *slot); PRBool PK11_IsFriendly(PK11SlotInfo *slot); @@ -135,6 +136,7 @@ PK11TokenStatus PK11_WaitForTokenEvent(PK11SlotInfo *slot, PK11TokenEvent event, PRBool PK11_NeedPWInit(void); PRBool PK11_TokenExists(CK_MECHANISM_TYPE); SECStatus PK11_GetModInfo(SECMODModule *mod, CK_INFO *info); +char *PK11_GetModuleURI(SECMODModule *mod); PRBool PK11_IsFIPS(void); SECMODModule *PK11_GetModule(PK11SlotInfo *slot); @@ -642,6 +644,8 @@ SECStatus PK11_TraverseSlotCerts( SECStatus (*callback)(CERTCertificate *, SECItem *, void *), void *arg, void *wincx); CERTCertificate *PK11_FindCertFromNickname(const char *nickname, void *wincx); +CERTCertificate *PK11_FindCertFromURI(const char *uri, void *wincx); +CERTCertList *PK11_FindCertsFromURI(const char *uri, void *wincx); CERTCertList *PK11_FindCertsFromEmailAddress(const char *email, void *wincx); CERTCertList *PK11_FindCertsFromNickname(const char *nickname, void *wincx); CERTCertificate *PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey); @@ -686,6 +690,10 @@ CERTCertList *PK11_ListCerts(PK11CertListType type, void *pwarg); CERTCertList *PK11_ListCertsInSlot(PK11SlotInfo *slot); CERTSignedCrl *PK11_ImportCRL(PK11SlotInfo *slot, SECItem *derCRL, char *url, int type, void *wincx, PRInt32 importOptions, PLArenaPool *arena, PRInt32 decodeOptions); +CK_BBOOL PK11_HasAttributeSet(PK11SlotInfo *slot, + CK_OBJECT_HANDLE id, + CK_ATTRIBUTE_TYPE type, + PRBool haslock /* must be set to PR_FALSE */); /********************************************************************** * Sign/Verify diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index e6301388e..1ef53e1d7 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -18,6 +18,8 @@ #include "secerr.h" #include "hasht.h" +static ECPointEncoding pk11_ECGetPubkeyEncoding(const SECKEYPublicKey *pubKey); + static void pk11_EnterKeyMonitor(PK11SymKey *symKey) { @@ -2005,7 +2007,7 @@ PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, /* old PKCS #11 spec was ambiguous on what needed to be passed, * try this again with and encoded public key */ - if (crv != CKR_OK) { + if (crv != CKR_OK && pk11_ECGetPubkeyEncoding(pubKey) != ECPoint_XOnly) { SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, &pubKey->u.ec.publicValue, SEC_ASN1_GET(SEC_OctetStringTemplate)); @@ -2211,6 +2213,11 @@ pk11_PubDeriveECKeyWithKDF( /* old PKCS #11 spec was ambiguous on what needed to be passed, * try this again with an encoded public key */ if (crv != CKR_OK) { + /* For curves that only use X as public value and no encoding we don't + * have to try again. (Currently only Curve25519) */ + if (pk11_ECGetPubkeyEncoding(pubKey) == ECPoint_XOnly) { + goto loser; + } SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, &pubKey->u.ec.publicValue, SEC_ASN1_GET(SEC_OctetStringTemplate)); diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index c66ae275c..0a6ed6c08 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -18,6 +18,7 @@ #include "dev3hack.h" #include "pkim.h" #include "utilpars.h" +#include "pkcs11uri.h" /************************************************************* * local static and global data @@ -409,6 +410,7 @@ PK11_NewSlotInfo(SECMODModule *mod) slot->slot_name[0] = 0; slot->token_name[0] = 0; PORT_Memset(slot->serial, ' ', sizeof(slot->serial)); + PORT_Memset(&slot->tokenInfo, 0, sizeof(slot->tokenInfo)); slot->module = NULL; slot->authTransact = 0; slot->authTime = LL_ZERO; @@ -1076,6 +1078,29 @@ PK11_MakeString(PLArenaPool *arena, char *space, return newString; } +/* + * check if a null-terminated string matches with a PKCS11 Static Label + */ +PRBool +pk11_MatchString(const char *string, + const char *staticString, int staticStringLen) +{ + int i; + + for (i = (staticStringLen - 1); i >= 0; i--) { + if (staticString[i] != ' ') + break; + } + /* move i to point to the last space */ + i++; + + if (strlen(string) == i && memcmp(string, staticString, i) == 0) { + return PR_TRUE; + } + + return PR_FALSE; +} + /* * Reads in the slots mechanism list for later use */ @@ -1140,7 +1165,6 @@ PK11_ReadMechanismList(PK11SlotInfo *slot) SECStatus PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) { - CK_TOKEN_INFO tokenInfo; CK_RV crv; SECStatus rv; PRStatus status; @@ -1148,7 +1172,7 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) /* set the slot flags to the current token values */ if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, &tokenInfo); + crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, &slot->tokenInfo); if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); if (crv != CKR_OK) { @@ -1159,13 +1183,13 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) /* set the slot flags to the current token values */ slot->series++; /* allow other objects to detect that the * slot is different */ - slot->flags = tokenInfo.flags; - slot->needLogin = ((tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE); - slot->readOnly = ((tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE); + slot->flags = slot->tokenInfo.flags; + slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE); + slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE); - slot->hasRandom = ((tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE); + slot->hasRandom = ((slot->tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE); slot->protectedAuthPath = - ((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) + ((slot->tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ? PR_TRUE : PR_FALSE); slot->lastLoginCheck = 0; @@ -1176,15 +1200,15 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) slot->protectedAuthPath = PR_FALSE; } (void)PK11_MakeString(NULL, slot->token_name, - (char *)tokenInfo.label, sizeof(tokenInfo.label)); - slot->minPassword = tokenInfo.ulMinPinLen; - slot->maxPassword = tokenInfo.ulMaxPinLen; - PORT_Memcpy(slot->serial, tokenInfo.serialNumber, sizeof(slot->serial)); + (char *)slot->tokenInfo.label, sizeof(slot->tokenInfo.label)); + slot->minPassword = slot->tokenInfo.ulMinPinLen; + slot->maxPassword = slot->tokenInfo.ulMaxPinLen; + PORT_Memcpy(slot->serial, slot->tokenInfo.serialNumber, sizeof(slot->serial)); nssToken_UpdateName(slot->nssToken); slot->defRWSession = (PRBool)((!slot->readOnly) && - (tokenInfo.ulMaxSessionCount == 1)); + (slot->tokenInfo.ulMaxSessionCount == 1)); rv = PK11_ReadMechanismList(slot); if (rv != SECSuccess) return rv; @@ -1193,13 +1217,13 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) slot->RSAInfoFlags = 0; /* initialize the maxKeyCount value */ - if (tokenInfo.ulMaxSessionCount == 0) { + if (slot->tokenInfo.ulMaxSessionCount == 0) { slot->maxKeyCount = 800; /* should be #define or a config param */ - } else if (tokenInfo.ulMaxSessionCount < 20) { + } else if (slot->tokenInfo.ulMaxSessionCount < 20) { /* don't have enough sessions to keep that many keys around */ slot->maxKeyCount = 0; } else { - slot->maxKeyCount = tokenInfo.ulMaxSessionCount / 2; + slot->maxKeyCount = slot->tokenInfo.ulMaxSessionCount / 2; } /* Make sure our session handle is valid */ @@ -1331,13 +1355,12 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) SECStatus PK11_TokenRefresh(PK11SlotInfo *slot) { - CK_TOKEN_INFO tokenInfo; CK_RV crv; /* set the slot flags to the current token values */ if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, &tokenInfo); + crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID, &slot->tokenInfo); if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); if (crv != CKR_OK) { @@ -1345,12 +1368,12 @@ PK11_TokenRefresh(PK11SlotInfo *slot) return SECFailure; } - slot->flags = tokenInfo.flags; - slot->needLogin = ((tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE); - slot->readOnly = ((tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE); - slot->hasRandom = ((tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE); + slot->flags = slot->tokenInfo.flags; + slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED) ? PR_TRUE : PR_FALSE); + slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED) ? PR_TRUE : PR_FALSE); + slot->hasRandom = ((slot->tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE); slot->protectedAuthPath = - ((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) + ((slot->tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ? PR_TRUE : PR_FALSE); /* on some platforms Active Card incorrectly sets the @@ -1665,6 +1688,63 @@ PK11_GetTokenName(PK11SlotInfo *slot) return slot->token_name; } +char * +PK11_GetTokenURI(PK11SlotInfo *slot) +{ + PK11URI *uri; + char *ret = NULL; + char label[32 + 1], manufacturer[32 + 1], serial[16 + 1], model[16 + 1]; + PK11URIAttribute attrs[4]; + size_t nattrs = 0; + + PK11_MakeString(NULL, label, (char *)slot->tokenInfo.label, + sizeof(slot->tokenInfo.label)); + if (*label != '\0') { + attrs[nattrs].name = PK11URI_PATTR_TOKEN; + attrs[nattrs].value = label; + nattrs++; + } + + PK11_MakeString(NULL, manufacturer, (char *)slot->tokenInfo.manufacturerID, + sizeof(slot->tokenInfo.manufacturerID)); + if (*manufacturer != '\0') { + attrs[nattrs].name = PK11URI_PATTR_MANUFACTURER; + attrs[nattrs].value = manufacturer; + nattrs++; + } + + PK11_MakeString(NULL, serial, (char *)slot->tokenInfo.serialNumber, + sizeof(slot->tokenInfo.serialNumber)); + if (*serial != '\0') { + attrs[nattrs].name = PK11URI_PATTR_SERIAL; + attrs[nattrs].value = serial; + nattrs++; + } + + PK11_MakeString(NULL, model, (char *)slot->tokenInfo.model, + sizeof(slot->tokenInfo.model)); + if (*model != '\0') { + attrs[nattrs].name = PK11URI_PATTR_MODEL; + attrs[nattrs].value = model; + nattrs++; + } + + uri = PK11URI_CreateURI(attrs, nattrs, NULL, 0); + if (uri == NULL) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return NULL; + } + + ret = PK11URI_FormatURI(NULL, uri); + PK11URI_DestroyURI(uri); + + if (ret == NULL) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + } + + return ret; +} + char * PK11_GetSlotName(PK11SlotInfo *slot) { @@ -1771,6 +1851,46 @@ PK11_GetTokenInfo(PK11SlotInfo *slot, CK_TOKEN_INFO *info) return SECSuccess; } +PRBool +pk11_MatchUriTokenInfo(PK11SlotInfo *slot, PK11URI *uri) +{ + const char *value; + + value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_TOKEN); + if (value) { + if (!pk11_MatchString(value, (char *)slot->tokenInfo.label, + sizeof(slot->tokenInfo.label))) { + return PR_FALSE; + } + } + + value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_MANUFACTURER); + if (value) { + if (!pk11_MatchString(value, (char *)slot->tokenInfo.manufacturerID, + sizeof(slot->tokenInfo.manufacturerID))) { + return PR_FALSE; + } + } + + value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_SERIAL); + if (value) { + if (!pk11_MatchString(value, (char *)slot->tokenInfo.serialNumber, + sizeof(slot->tokenInfo.serialNumber))) { + return PR_FALSE; + } + } + + value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_MODEL); + if (value) { + if (!pk11_MatchString(value, (char *)slot->tokenInfo.model, + sizeof(slot->tokenInfo.model))) { + return PR_FALSE; + } + } + + return PR_TRUE; +} + /* Find out if we need to initialize the user's pin */ PRBool PK11_NeedUserInit(PK11SlotInfo *slot) @@ -2291,6 +2411,14 @@ PK11_GetMaxKeyLength(CK_MECHANISM_TYPE mechanism) } } } + + /* fallback to pk11_GetPredefinedKeyLength for fixed key size algorithms */ + if (keyLength == 0) { + CK_KEY_TYPE keyType; + keyType = PK11_GetKeyType(mechanism, 0); + keyLength = pk11_GetPredefinedKeyLength(keyType); + } + if (le) PK11_FreeSlotListElement(list, le); if (freeit) @@ -2356,7 +2484,11 @@ PK11_RandomUpdate(void *data, size_t bytes) if (!bestIsInternal) { /* do internal slot, too. */ - slot = PK11_GetInternalSlot(); /* can't fail */ + slot = PK11_GetInternalSlot(); + PORT_Assert(slot); + if (!slot) { + return SECFailure; + } status = PK11_SeedRandom(slot, data, bytes); PK11_FreeSlot(slot); } diff --git a/security/nss/lib/pk11wrap/pk11util.c b/security/nss/lib/pk11wrap/pk11util.c index 9636b073c..a962e9bb3 100644 --- a/security/nss/lib/pk11wrap/pk11util.c +++ b/security/nss/lib/pk11wrap/pk11util.c @@ -14,6 +14,7 @@ #include "secerr.h" #include "dev.h" #include "utilpars.h" +#include "pkcs11uri.h" /* these are for displaying error messages */ @@ -590,6 +591,58 @@ PK11_GetModInfo(SECMODModule *mod, CK_INFO *info) return (crv == CKR_OK) ? SECSuccess : SECFailure; } +char * +PK11_GetModuleURI(SECMODModule *mod) +{ + CK_INFO info; + PK11URI *uri; + char *ret = NULL; + PK11URIAttribute attrs[3]; + size_t nattrs = 0; + char libraryManufacturer[32 + 1], libraryDescription[32 + 1], libraryVersion[8]; + + if (PK11_GetModInfo(mod, &info) == SECFailure) { + return NULL; + } + + PK11_MakeString(NULL, libraryManufacturer, (char *)info.manufacturerID, + sizeof(info.manufacturerID)); + if (*libraryManufacturer != '\0') { + attrs[nattrs].name = PK11URI_PATTR_LIBRARY_MANUFACTURER; + attrs[nattrs].value = libraryManufacturer; + nattrs++; + } + + PK11_MakeString(NULL, libraryDescription, (char *)info.libraryDescription, + sizeof(info.libraryDescription)); + if (*libraryDescription != '\0') { + attrs[nattrs].name = PK11URI_PATTR_LIBRARY_DESCRIPTION; + attrs[nattrs].value = libraryDescription; + nattrs++; + } + + PR_snprintf(libraryVersion, sizeof(libraryVersion), "%d.%d", + info.libraryVersion.major, info.libraryVersion.minor); + attrs[nattrs].name = PK11URI_PATTR_LIBRARY_VERSION; + attrs[nattrs].value = libraryVersion; + nattrs++; + + uri = PK11URI_CreateURI(attrs, nattrs, NULL, 0); + if (uri == NULL) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return NULL; + } + + ret = PK11URI_FormatURI(NULL, uri); + PK11URI_DestroyURI(uri); + if (ret == NULL) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return NULL; + } + + return ret; +} + /* Determine if we have the FIP's module loaded as the default * module to trigger other bogus FIPS requirements in PKCS #12 and * SSL diff --git a/security/nss/lib/pk11wrap/pk11wrap.gyp b/security/nss/lib/pk11wrap/pk11wrap.gyp index 2af27a052..35fdacef9 100644 --- a/security/nss/lib/pk11wrap/pk11wrap.gyp +++ b/security/nss/lib/pk11wrap/pk11wrap.gyp @@ -7,35 +7,54 @@ ], 'targets': [ { - 'target_name': 'pk11wrap', + 'target_name': 'pk11wrap_static', 'type': 'static_library', - 'sources': [ - 'dev3hack.c', - 'pk11akey.c', - 'pk11auth.c', - 'pk11cert.c', - 'pk11cxt.c', - 'pk11err.c', - 'pk11kea.c', - 'pk11list.c', - 'pk11load.c', - 'pk11mech.c', - 'pk11merge.c', - 'pk11nobj.c', - 'pk11obj.c', - 'pk11pars.c', - 'pk11pbe.c', - 'pk11pk12.c', - 'pk11pqg.c', - 'pk11sdr.c', - 'pk11skey.c', - 'pk11slot.c', - 'pk11util.c' + 'defines': [ + 'NSS_TEST_BUILD', + ], + 'dependencies': [ + 'pk11wrap_base', + '<(DEPTH)/exports.gyp:nss_exports', + '<(DEPTH)/lib/softoken/softoken.gyp:softokn_static', ], + }, + { + 'target_name': 'pk11wrap', + 'type': 'static_library', 'dependencies': [ - '<(DEPTH)/exports.gyp:nss_exports' - ] - } + 'pk11wrap_base', + '<(DEPTH)/exports.gyp:nss_exports', + ], + }, + { + 'target_name': 'pk11wrap_base', + 'type': 'none', + 'direct_dependent_settings': { + 'sources': [ + 'dev3hack.c', + 'pk11akey.c', + 'pk11auth.c', + 'pk11cert.c', + 'pk11cxt.c', + 'pk11err.c', + 'pk11kea.c', + 'pk11list.c', + 'pk11load.c', + 'pk11mech.c', + 'pk11merge.c', + 'pk11nobj.c', + 'pk11obj.c', + 'pk11pars.c', + 'pk11pbe.c', + 'pk11pk12.c', + 'pk11pqg.c', + 'pk11sdr.c', + 'pk11skey.c', + 'pk11slot.c', + 'pk11util.c' + ], + }, + }, ], 'target_defaults': { 'defines': [ @@ -48,4 +67,4 @@ 'variables': { 'module': 'nss' } -} \ No newline at end of file +} diff --git a/security/nss/lib/pk11wrap/secmodti.h b/security/nss/lib/pk11wrap/secmodti.h index 520165573..63c207929 100644 --- a/security/nss/lib/pk11wrap/secmodti.h +++ b/security/nss/lib/pk11wrap/secmodti.h @@ -107,6 +107,8 @@ struct PK11SlotInfoStr { unsigned int lastState; /* for Stan */ NSSToken *nssToken; + /* the tokeninfo struct */ + CK_TOKEN_INFO tokenInfo; /* fast mechanism lookup */ char mechanismBits[256]; }; -- cgit v1.2.3