summaryrefslogtreecommitdiff
path: root/nss/lib/pk11wrap
diff options
context:
space:
mode:
Diffstat (limited to 'nss/lib/pk11wrap')
-rw-r--r--nss/lib/pk11wrap/dev3hack.c4
-rw-r--r--nss/lib/pk11wrap/pk11akey.c8
-rw-r--r--nss/lib/pk11wrap/pk11cert.c387
-rw-r--r--nss/lib/pk11wrap/pk11load.c26
-rw-r--r--nss/lib/pk11wrap/pk11mech.c4
-rw-r--r--nss/lib/pk11wrap/pk11obj.c12
-rw-r--r--nss/lib/pk11wrap/pk11pbe.c58
-rw-r--r--nss/lib/pk11wrap/pk11pk12.c121
-rw-r--r--nss/lib/pk11wrap/pk11priv.h13
-rw-r--r--nss/lib/pk11wrap/pk11pub.h8
-rw-r--r--nss/lib/pk11wrap/pk11skey.c48
-rw-r--r--nss/lib/pk11wrap/pk11slot.c172
-rw-r--r--nss/lib/pk11wrap/pk11util.c53
-rw-r--r--nss/lib/pk11wrap/pk11wrap.gyp73
-rw-r--r--nss/lib/pk11wrap/secmodti.h2
15 files changed, 787 insertions, 202 deletions
diff --git a/nss/lib/pk11wrap/dev3hack.c b/nss/lib/pk11wrap/dev3hack.c
index 27325a5..39afd67 100644
--- a/nss/lib/pk11wrap/dev3hack.c
+++ b/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/nss/lib/pk11wrap/pk11akey.c b/nss/lib/pk11wrap/pk11akey.c
index d086ed4..c45901e 100644
--- a/nss/lib/pk11wrap/pk11akey.c
+++ b/nss/lib/pk11wrap/pk11akey.c
@@ -765,12 +765,10 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot, KeyType keyType, CK_OBJECT_HANDLE id)
&pubKey->u.ec.DEREncodedParams);
if (crv != CKR_OK)
break;
+ pubKey->u.ec.encoding = ECPoint_Undefined;
crv = pk11_get_Decoded_ECPoint(arena,
&pubKey->u.ec.DEREncodedParams, value,
&pubKey->u.ec.publicValue);
- if (seckey_SetPointEncoding(arena, pubKey) != SECSuccess) {
- crv |= CKR_GENERAL_ERROR;
- }
break;
case fortezzaKey:
case nullKey:
@@ -888,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/nss/lib/pk11wrap/pk11cert.c b/nss/lib/pk11wrap/pk11cert.c
index 6968ae7..c1caf5e 100644
--- a/nss/lib/pk11wrap/pk11cert.c
+++ b/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/nss/lib/pk11wrap/pk11load.c b/nss/lib/pk11wrap/pk11load.c
index f12d0fd..91339fa 100644
--- a/nss/lib/pk11wrap/pk11load.c
+++ b/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 <stdio.h>
+#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 <stdio.h>
-#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/nss/lib/pk11wrap/pk11mech.c b/nss/lib/pk11wrap/pk11mech.c
index 4db05ff..48e50df 100644
--- a/nss/lib/pk11wrap/pk11mech.c
+++ b/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/nss/lib/pk11wrap/pk11obj.c b/nss/lib/pk11wrap/pk11obj.c
index 18850b2..4046c1f 100644
--- a/nss/lib/pk11wrap/pk11obj.c
+++ b/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.
diff --git a/nss/lib/pk11wrap/pk11pbe.c b/nss/lib/pk11wrap/pk11pbe.c
index 7837bfe..bea9333 100644
--- a/nss/lib/pk11wrap/pk11pbe.c
+++ b/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/nss/lib/pk11wrap/pk11pk12.c b/nss/lib/pk11wrap/pk11pk12.c
index 1683cc5..d753b87 100644
--- a/nss/lib/pk11wrap/pk11pk12.c
+++ b/nss/lib/pk11wrap/pk11pk12.c
@@ -65,6 +65,19 @@ struct SECKEYDHPrivateKeyStr {
typedef struct SECKEYDHPrivateKeyStr SECKEYDHPrivateKey;
/*
+** Elliptic Curve Private Key structures
+** <https://tools.ietf.org/html/rfc5915#section-3>
+*/
+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
*/
struct SECKEYRawPrivateKeyStr {
@@ -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/nss/lib/pk11wrap/pk11priv.h b/nss/lib/pk11wrap/pk11priv.h
index 45a60b4..9281923 100644
--- a/nss/lib/pk11wrap/pk11priv.h
+++ b/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/nss/lib/pk11wrap/pk11pub.h b/nss/lib/pk11wrap/pk11pub.h
index e11af86..edfe82f 100644
--- a/nss/lib/pk11wrap/pk11pub.h
+++ b/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/nss/lib/pk11wrap/pk11skey.c b/nss/lib/pk11wrap/pk11skey.c
index 850ec02..1ef53e1 100644
--- a/nss/lib/pk11wrap/pk11skey.c
+++ b/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));
@@ -2037,6 +2039,40 @@ PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
return NULL;
}
+/* Test for curves that are known to use a special encoding.
+ * Extend this function when additional curves are added. */
+static ECPointEncoding
+pk11_ECGetPubkeyEncoding(const SECKEYPublicKey *pubKey)
+{
+ SECItem oid;
+ SECStatus rv;
+ PORTCheapArenaPool tmpArena;
+ ECPointEncoding encoding = ECPoint_Undefined;
+
+ PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
+
+ /* decode the OID tag */
+ rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &oid,
+ SEC_ASN1_GET(SEC_ObjectIDTemplate),
+ &pubKey->u.ec.DEREncodedParams);
+ if (rv == SECSuccess) {
+ SECOidTag tag = SECOID_FindOIDTag(&oid);
+ switch (tag) {
+ case SEC_OID_CURVE25519:
+ encoding = ECPoint_XOnly;
+ break;
+ case SEC_OID_SECG_EC_SECP256R1:
+ case SEC_OID_SECG_EC_SECP384R1:
+ case SEC_OID_SECG_EC_SECP521R1:
+ default:
+ /* unknown curve, default to uncompressed */
+ encoding = ECPoint_Uncompressed;
+ }
+ }
+ PORT_DestroyCheapArena(&tmpArena);
+ return encoding;
+}
+
/* Returns the size of the public key, or 0 if there
* is an error. */
static CK_ULONG
@@ -2044,10 +2080,11 @@ pk11_ECPubKeySize(SECKEYPublicKey *pubKey)
{
SECItem *publicValue = &pubKey->u.ec.publicValue;
- if (pubKey->u.ec.encoding == ECPoint_XOnly) {
+ ECPointEncoding encoding = pk11_ECGetPubkeyEncoding(pubKey);
+ if (encoding == ECPoint_XOnly) {
return publicValue->len;
}
- if (publicValue->data[0] == 0x04) {
+ if (encoding == ECPoint_Uncompressed) {
/* key encoded in uncompressed form */
return ((publicValue->len - 1) / 2);
}
@@ -2176,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/nss/lib/pk11wrap/pk11slot.c b/nss/lib/pk11wrap/pk11slot.c
index c66ae27..db805c1 100644
--- a/nss/lib/pk11wrap/pk11slot.c
+++ b/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;
@@ -1077,6 +1079,29 @@ PK11_MakeString(PLArenaPool *arena, char *space,
}
/*
+ * 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
*/
SECStatus
@@ -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
@@ -1666,6 +1689,63 @@ PK11_GetTokenName(PK11SlotInfo *slot)
}
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)
{
return slot->slot_name;
@@ -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)
diff --git a/nss/lib/pk11wrap/pk11util.c b/nss/lib/pk11wrap/pk11util.c
index 9636b07..a962e9b 100644
--- a/nss/lib/pk11wrap/pk11util.c
+++ b/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/nss/lib/pk11wrap/pk11wrap.gyp b/nss/lib/pk11wrap/pk11wrap.gyp
index 2af27a0..35fdace 100644
--- a/nss/lib/pk11wrap/pk11wrap.gyp
+++ b/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/nss/lib/pk11wrap/secmodti.h b/nss/lib/pk11wrap/secmodti.h
index 5201655..63c2079 100644
--- a/nss/lib/pk11wrap/secmodti.h
+++ b/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];
};