diff --git a/mozilla/security/nss/lib/dev/ckhelper.c b/mozilla/security/nss/lib/dev/ckhelper.c index 3ec3acb4b64..2110af43e21 100644 --- a/mozilla/security/nss/lib/dev/ckhelper.c +++ b/mozilla/security/nss/lib/dev/ckhelper.c @@ -32,29 +32,21 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.17 $ $Date: 2002-03-15 19:51:27 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.18 $ $Date: 2002-04-04 20:00:21 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ - -#ifdef NSS_3_4_CODE -#include "pkcs11.h" -#else #ifndef NSSCKEPV_H #include "nssckepv.h" #endif /* NSSCKEPV_H */ -#endif /* NSS_3_4_CODE */ + +#ifndef DEVM_H +#include "devm.h" +#endif /* DEVM_H */ #ifndef CKHELPER_H #include "ckhelper.h" #endif /* CKHELPER_H */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ - static const CK_BBOOL s_true = CK_TRUE; NSS_IMPLEMENT_DATA const NSSItem g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) }; @@ -111,6 +103,7 @@ nssCKObject_GetAttributes CK_RV ckrv; PRStatus nssrv; PRBool alloced = PR_FALSE; + void *epv = nssSlot_GetCryptokiEPV(slot); hSession = session->handle; if (arenaOpt) { mark = nssArena_Mark(arenaOpt); @@ -124,8 +117,8 @@ nssCKObject_GetAttributes */ if (obj_template[0].ulValueLen == 0) { /* Get the storage size needed for each attribute */ - ckrv = CKAPI(slot)->C_GetAttributeValue(hSession, - object, obj_template, count); + ckrv = CKAPI(epv)->C_GetAttributeValue(hSession, + object, obj_template, count); if (ckrv != CKR_OK && ckrv != CKR_ATTRIBUTE_TYPE_INVALID && ckrv != CKR_ATTRIBUTE_SENSITIVE) @@ -154,8 +147,8 @@ nssCKObject_GetAttributes alloced = PR_TRUE; } /* Obtain the actual attribute values. */ - ckrv = CKAPI(slot)->C_GetAttributeValue(hSession, - object, obj_template, count); + ckrv = CKAPI(epv)->C_GetAttributeValue(hSession, + object, obj_template, count); nssSession_ExitMonitor(session); if (ckrv != CKR_OK && ckrv != CKR_ATTRIBUTE_TYPE_INVALID && @@ -238,11 +231,12 @@ nssCKObject_IsAttributeTrue CK_ATTRIBUTE_PTR attr; CK_ATTRIBUTE atemplate = { 0, NULL, 0 }; CK_RV ckrv; + void *epv = nssSlot_GetCryptokiEPV(slot); attr = &atemplate; NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool); nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_GetAttributeValue(session->handle, object, - &atemplate, 1); + ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object, + &atemplate, 1); nssSession_ExitMonitor(session); if (ckrv != CKR_OK) { *rvStatus = PR_FAILURE; @@ -263,9 +257,10 @@ nssCKObject_SetAttributes ) { CK_RV ckrv; + void *epv = nssSlot_GetCryptokiEPV(slot); nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_SetAttributeValue(session->handle, object, - obj_template, count); + ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object, + obj_template, count); nssSession_ExitMonitor(session); if (ckrv == CKR_OK) { return PR_SUCCESS; @@ -290,3 +285,366 @@ nssCKObject_IsTokenObjectTemplate return PR_FALSE; } +#ifdef PURE_STAN_BUILD +static NSSCertificateType +nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib) +{ + CK_CERTIFICATE_TYPE ckCertType; + if (!attrib->pValue) { + /* default to PKIX */ + return NSSCertificateType_PKIX; + } + ckCertType = *((CK_ULONG *)attrib->pValue); + switch (ckCertType) { + case CKC_X_509: + return NSSCertificateType_PKIX; + default: + break; + } + return NSSCertificateType_Unknown; +} + +/* incoming pointers must be valid */ +NSS_IMPLEMENT PRStatus +nssCryptokiCertificate_GetAttributes +( + nssCryptokiObject *certObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSCertificateType *certTypeOpt, + NSSItem *idOpt, + NSSDER *encodingOpt, + NSSDER *issuerOpt, + NSSDER *serialOpt, + NSSDER *subjectOpt, + NSSASCII7 **emailOpt +) +{ + PRStatus status; + PRUint32 i; + nssSession *session; + NSSSlot *slot; + CK_ULONG template_size; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_template[7]; + /* Set up a template of all options chosen by caller */ + NSS_CK_TEMPLATE_START(cert_template, attr, template_size); + if (certTypeOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CERTIFICATE_TYPE); + } + if (idOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID); + } + if (encodingOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); + } + if (issuerOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ISSUER); + } + if (serialOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SERIAL_NUMBER); + } + if (subjectOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT); + } + if (emailOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_EMAIL); + } + NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size); + if (template_size == 0) { + /* caller didn't want anything */ + return PR_SUCCESS; + } + + status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt, + certObject, CKO_CERTIFICATE, + cert_template, template_size); + if (status != PR_SUCCESS) { + + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(certObject->token); + + slot = nssToken_GetSlot(certObject->token); + status = nssCKObject_GetAttributes(certObject->handle, + cert_template, template_size, + arenaOpt, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + } + + i=0; + if (certTypeOpt) { + *certTypeOpt = nss_cert_type_from_ck_attrib(&cert_template[i]); i++; + } + if (idOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], idOpt); i++; + } + if (encodingOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], encodingOpt); i++; + } + if (issuerOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], issuerOpt); i++; + } + if (serialOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], serialOpt); i++; + } + if (subjectOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt); i++; + } + if (emailOpt) { + NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[i], *emailOpt); i++; + } + return PR_SUCCESS; +} + +static NSSKeyPairType +nss_key_pair_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib) +{ + CK_KEY_TYPE ckKeyType; + PR_ASSERT(attrib->pValue); + ckKeyType = *((CK_ULONG *)attrib->pValue); + switch (ckKeyType) { + case CKK_RSA: return NSSKeyPairType_RSA; + case CKK_DSA: return NSSKeyPairType_DSA; + default: break; + } + return NSSKeyPairType_Unknown; +} + +NSS_IMPLEMENT PRStatus +nssCryptokiPrivateKey_GetAttributes +( + nssCryptokiObject *keyObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSKeyPairType *keyTypeOpt, + NSSItem *idOpt +) +{ + PRStatus status; + PRUint32 i; + nssSession *session; + NSSSlot *slot; + CK_ULONG template_size; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[2]; + /* Set up a template of all options chosen by caller */ + NSS_CK_TEMPLATE_START(key_template, attr, template_size); + if (keyTypeOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_KEY_TYPE); + } + if (idOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID); + } + NSS_CK_TEMPLATE_FINISH(key_template, attr, template_size); + if (template_size == 0) { + /* caller didn't want anything */ + return PR_SUCCESS; + } + + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(keyObject->token); + + slot = nssToken_GetSlot(keyObject->token); + status = nssCKObject_GetAttributes(keyObject->handle, + key_template, template_size, + arenaOpt, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + + i=0; + if (keyTypeOpt) { + *keyTypeOpt = nss_key_pair_type_from_ck_attrib(&key_template[i]); i++; + } + if (idOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&key_template[i], idOpt); i++; + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssCryptokiPublicKey_GetAttributes +( + nssCryptokiObject *keyObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSKeyPairType *keyTypeOpt, + NSSItem *idOpt +) +{ + PRStatus status; + PRUint32 i; + nssSession *session; + NSSSlot *slot; + CK_ULONG template_size; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[2]; + /* Set up a template of all options chosen by caller */ + NSS_CK_TEMPLATE_START(key_template, attr, template_size); + if (keyTypeOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_KEY_TYPE); + } + if (idOpt) { + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID); + } + NSS_CK_TEMPLATE_FINISH(key_template, attr, template_size); + if (template_size == 0) { + /* caller didn't want anything */ + return PR_SUCCESS; + } + + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(keyObject->token); + + slot = nssToken_GetSlot(keyObject->token); + status = nssCKObject_GetAttributes(keyObject->handle, + key_template, template_size, + arenaOpt, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + + i=0; + if (keyTypeOpt) { + *keyTypeOpt = nss_key_pair_type_from_ck_attrib(&key_template[i]); i++; + } + if (idOpt) { + NSS_CK_ATTRIBUTE_TO_ITEM(&key_template[i], idOpt); i++; + } + return PR_SUCCESS; +} + +static nssTrustLevel +get_nss_trust +( + CK_TRUST ckt +) +{ + nssTrustLevel t; + switch (ckt) { + case CKT_NETSCAPE_TRUST_UNKNOWN: t = nssTrustLevel_Unknown; break; + case CKT_NETSCAPE_UNTRUSTED: t = nssTrustLevel_NotTrusted; break; + case CKT_NETSCAPE_TRUSTED_DELEGATOR: t = nssTrustLevel_TrustedDelegator; + break; + case CKT_NETSCAPE_VALID_DELEGATOR: t = nssTrustLevel_ValidDelegator; break; + case CKT_NETSCAPE_TRUSTED: t = nssTrustLevel_Trusted; break; + case CKT_NETSCAPE_VALID: t = nssTrustLevel_Valid; break; + } + return t; +} + +NSS_IMPLEMENT PRStatus +nssCryptokiTrust_GetAttributes +( + nssCryptokiObject *trustObject, + nssSession *sessionOpt, + nssTrustLevel *serverAuth, + nssTrustLevel *clientAuth, + nssTrustLevel *codeSigning, + nssTrustLevel *emailProtection +) +{ + PRStatus status; + NSSSlot *slot; + nssSession *session; + CK_BBOOL isToken; + CK_TRUST saTrust, caTrust, epTrust, csTrust; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE trust_template[5]; + CK_ULONG trust_size; + + /* Use the trust object to find the trust settings */ + NSS_CK_TEMPLATE_START(trust_template, attr, trust_size); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust); + NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size); + + status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL, + trustObject, + CKO_NETSCAPE_TRUST, + trust_template, trust_size); + if (status != PR_SUCCESS) { + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(trustObject->token); + + slot = nssToken_GetSlot(trustObject->token); + status = nssCKObject_GetAttributes(trustObject->handle, + trust_template, trust_size, + NULL, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + } + + *serverAuth = get_nss_trust(saTrust); + *clientAuth = get_nss_trust(caTrust); + *emailProtection = get_nss_trust(epTrust); + *codeSigning = get_nss_trust(csTrust); + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssCryptokiCRL_GetAttributes +( + nssCryptokiObject *crlObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSItem *crl, + NSSItem *krl, + NSSItem *url +) +{ + PRStatus status; + NSSSlot *slot; + nssSession *session; + CK_BBOOL isToken; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE crl_template[5]; + CK_ULONG crl_size; + + NSS_CK_TEMPLATE_START(crl_template, attr, crl_size); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken); + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE); + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_KRL); + NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_URL); + NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size); + + status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL, + crlObject, + CKO_NETSCAPE_CRL, + crl_template, crl_size); + if (status != PR_SUCCESS) { + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(crlObject->token); + + slot = nssToken_GetSlot(crlObject->token); + status = nssCKObject_GetAttributes(crlObject->handle, + crl_template, crl_size, + arenaOpt, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + return status; + } + } + + NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[0], crl); + NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[1], krl); + NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[2], url); + return PR_SUCCESS; +} +#endif /* PURE_STAN_BUILD */ + diff --git a/mozilla/security/nss/lib/dev/ckhelper.h b/mozilla/security/nss/lib/dev/ckhelper.h index 9ed320e7b26..91a1fad6439 100644 --- a/mozilla/security/nss/lib/dev/ckhelper.h +++ b/mozilla/security/nss/lib/dev/ckhelper.h @@ -41,7 +41,7 @@ #define CKHELPER_H #ifdef DEBUG -static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile: ckhelper.h,v $ $Revision: 1.13 $ $Date: 2002-01-23 01:20:32 $ $Name: not supported by cvs2svn $"; +static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile: ckhelper.h,v $ $Revision: 1.14 $ $Date: 2002-04-04 20:00:21 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef NSSCKT_H @@ -50,10 +50,6 @@ static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile: ckhelper.h,v $ $Revision: PR_BEGIN_EXTERN_C -/* Shortcut to cryptoki API functions. */ -#define CKAPI(x) \ - ((CK_FUNCTION_LIST_PTR)((x)->epv)) - /* Some globals to keep from constantly redeclaring common cryptoki * attribute types on the stack. */ diff --git a/mozilla/security/nss/lib/dev/dev.h b/mozilla/security/nss/lib/dev/dev.h index 6018415650c..a1894b9eae5 100644 --- a/mozilla/security/nss/lib/dev/dev.h +++ b/mozilla/security/nss/lib/dev/dev.h @@ -34,53 +34,142 @@ #ifndef DEV_H #define DEV_H -#ifdef DEBUG -static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.21 $ $Date: 2002-03-07 23:21:32 $ $Name: not supported by cvs2svn $"; -#endif /* DEBUG */ +/* + * dev.h + * + * Low-level methods for interaction with cryptoki devices + */ -#ifndef DEVT_H -#include "devt.h" -#endif /* DEVT_H */ +#ifdef DEBUG +static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.22 $ $Date: 2002-04-04 20:00:21 $ $Name: not supported by cvs2svn $"; +#endif /* DEBUG */ #ifndef NSSCKT_H #include "nssckt.h" #endif /* NSSCKT_H */ -#ifndef NSSPKIT_H -#include "nsspkit.h" -#endif /* NSSPKIT_H */ +#ifndef NSSDEV_H +#include "nssdev.h" +#endif /* NSSDEV_H */ -#ifndef BASET_H -#include "baset.h" -#endif /* BASET_H */ - -/* - * nssdev.h - * - * This file prototypes the methods of the low-level cryptoki devices. - * - * |-----------|---> NSSSlot <--> NSSToken - * | NSSModule |---> NSSSlot <--> NSSToken - * |-----------|---> NSSSlot <--> NSSToken - */ +#ifndef DEVT_H +#include "devt.h" +#endif /* DEVT_H */ PR_BEGIN_EXTERN_C +/* the global module list + * + * These functions are for managing the global set of modules. Trust Domains, + * etc., will draw from this set. These functions are completely internal + * and only invoked when there are changes to the global module state + * (load or unload). + * + * nss_InitializeGlobalModuleList + * nss_DestroyGlobalModuleList + * nss_GetLoadedModules + * + * nssGlobalModuleList_Add + * nssGlobalModuleList_Remove + * nssGlobalModuleList_FindModuleByName + * nssGlobalModuleList_FindSlotByName + * nssGlobalModuleList_FindTokenByName + */ + +NSS_EXTERN PRStatus +nss_InitializeGlobalModuleList +( + void +); + +NSS_EXTERN PRStatus +nss_DestroyGlobalModuleList +( + void +); + +NSS_EXTERN NSSModule ** +nss_GetLoadedModules +( + void +); + +NSS_EXTERN PRStatus +nssGlobalModuleList_Add +( + NSSModule *module +); + +NSS_EXTERN PRStatus +nssGlobalModuleList_Remove +( + NSSModule *module +); + +NSS_EXTERN NSSModule * +nssGlobalModuleList_FindModuleByName +( + NSSUTF8 *moduleName +); + +NSS_EXTERN NSSSlot * +nssGlobalModuleList_FindSlotByName +( + NSSUTF8 *slotName +); + +NSS_EXTERN NSSToken * +nssGlobalModuleList_FindTokenByName +( + NSSUTF8 *tokenName +); + +NSS_EXTERN NSSToken * +nss_GetDefaultCryptoToken +( + void +); + +NSS_EXTERN NSSToken * +nss_GetDefaultDatabaseToken +( + void +); + +/* + * |-----------|<---> NSSSlot <--> NSSToken + * | NSSModule |<---> NSSSlot <--> NSSToken + * |-----------|<---> NSSSlot <--> NSSToken + */ + +/* NSSModule + * + * nssModule_Create + * nssModule_CreateFromSpec + * nssModule_AddRef + * nssModule_GetName + * nssModule_GetSlots + * nssModule_FindSlotByName + * nssModule_FindTokenByName + * nssModule_GetCertOrder + */ + NSS_EXTERN NSSModule * nssModule_Create ( NSSUTF8 *moduleOpt, NSSUTF8 *uriOpt, - NSSUTF8 *opaqueOpt, /* XXX is this where the mech flags go??? */ + NSSUTF8 *opaqueOpt, void *reserved - /* XXX more? */ ); /* This is to use the new loading mechanism. */ NSS_EXTERN NSSModule * nssModule_CreateFromSpec ( - NSSUTF8 *moduleSpec + NSSUTF8 *moduleSpec, + NSSModule *parent, + PRBool loadSubModules ); NSS_EXTERN PRStatus @@ -95,20 +184,8 @@ nssModule_AddRef NSSModule *mod ); -NSS_EXTERN PRStatus -nssModule_Load -( - NSSModule *mod -); - -NSS_EXTERN PRStatus -nssModule_Unload -( - NSSModule *mod -); - -NSS_EXTERN PRStatus -nssModule_LogoutAllSlots +NSS_EXTERN NSSUTF8 * +nssModule_GetName ( NSSModule *mod ); @@ -133,24 +210,30 @@ nssModule_FindTokenByName NSSUTF8 *tokenName ); -/* This descends from NSSTrustDomain_TraverseCertificates, a questionable - * function. Do we want NSS to have access to this at the module level? - */ -NSS_EXTERN PRStatus * -nssModule_TraverseCertificates +NSS_EXTERN PRInt32 +nssModule_GetCertOrder ( - NSSModule *mod, - PRStatus (*callback)(NSSCertificate *c, void *arg), - void *arg + NSSModule *module ); -NSS_EXTERN NSSSlot * -nssSlot_Create -( - NSSArena *arenaOpt, - CK_SLOT_ID slotId, - NSSModule *parent -); +/* NSSSlot + * + * nssSlot_Destroy + * nssSlot_AddRef + * nssSlot_GetName + * nssSlot_GetTokenName + * nssSlot_IsTokenPresent + * nssSlot_IsPermanent + * nssSlot_IsFriendly + * nssSlot_IsHardware + * nssSlot_Refresh + * nssSlot_GetModule + * nssSlot_GetToken + * nssSlot_Login + * nssSlot_Logout + * nssSlot_SetPassword + * nssSlot_CreateSession + */ NSS_EXTERN PRStatus nssSlot_Destroy @@ -158,18 +241,6 @@ nssSlot_Destroy NSSSlot *slot ); -NSS_EXTERN PRBool -nssSlot_IsPermanent -( - NSSSlot *slot -); - -NSS_EXTERN PRStatus -nssSlot_Refresh -( - NSSSlot *slot -); - NSS_EXTERN NSSSlot * nssSlot_AddRef ( @@ -179,15 +250,67 @@ nssSlot_AddRef NSS_EXTERN NSSUTF8 * nssSlot_GetName ( - NSSSlot *slot, - NSSArena *arenaOpt + NSSSlot *slot +); + +NSS_EXTERN NSSUTF8 * +nssSlot_GetTokenName +( + NSSSlot *slot +); + +NSS_EXTERN NSSModule * +nssSlot_GetModule +( + NSSSlot *slot +); + +NSS_EXTERN NSSToken * +nssSlot_GetToken +( + NSSSlot *slot +); + +NSS_EXTERN PRBool +nssSlot_IsTokenPresent +( + NSSSlot *slot +); + +NSS_EXTERN PRBool +nssSlot_IsPermanent +( + NSSSlot *slot +); + +NSS_EXTERN PRBool +nssSlot_IsFriendly +( + NSSSlot *slot +); + +NSS_EXTERN PRBool +nssSlot_IsHardware +( + NSSSlot *slot +); + +NSS_EXTERN PRBool +nssSlot_IsLoggedIn +( + NSSSlot *slot +); + +NSS_EXTERN PRStatus +nssSlot_Refresh +( + NSSSlot *slot ); NSS_EXTERN PRStatus nssSlot_Login ( NSSSlot *slot, - PRBool asSO, NSSCallback *pwcb ); extern const NSSError NSS_ERROR_INVALID_PASSWORD; @@ -213,7 +336,8 @@ NSS_EXTERN PRStatus nssSlot_SetPassword ( NSSSlot *slot, - NSSCallback *pwcb + NSSUTF8 *oldPasswordOpt, + NSSUTF8 *newPassword ); extern const NSSError NSS_ERROR_INVALID_PASSWORD; extern const NSSError NSS_ERROR_USER_CANCELED; @@ -230,13 +354,36 @@ nssSlot_CreateSession PRBool readWrite /* so far, this is the only flag used */ ); -NSS_EXTERN NSSToken * -nssToken_Create -( - NSSArena *arenaOpt, - CK_SLOT_ID slotID, - NSSSlot *parent -); +/* NSSToken + * + * nssToken_Destroy + * nssToken_AddRef + * nssToken_GetName + * nssToken_GetModule + * nssToken_GetSlot + * nssToken_NeedsPINInitialization + * nssToken_ImportCertificate + * nssToken_ImportTrust + * nssToken_ImportCRL + * nssToken_GenerateKeyPair + * nssToken_GenerateSymmetricKey + * nssToken_DeleteStoredObject + * nssToken_FindCertificates + * nssToken_FindCertificatesBySubject + * nssToken_FindCertificatesByNickname + * nssToken_FindCertificatesByEmail + * nssToken_FindCertificateByIssuerAndSerialNumber + * nssToken_FindCertificateByEncodedCertificate + * nssToken_FindTrustObjects + * nssToken_FindTrustForCertificate + * nssToken_FindCRLs + * nssToken_FindPrivateKeys + * nssToken_FindPrivateKeyByID + * nssToken_Digest + * nssToken_BeginDigest + * nssToken_ContinueDigest + * nssToken_FinishDigest + */ NSS_EXTERN PRStatus nssToken_Destroy @@ -244,12 +391,6 @@ nssToken_Destroy NSSToken *tok ); -NSS_EXTERN PRBool -nssToken_IsPresent -( - NSSToken *token -); - NSS_EXTERN NSSToken * nssToken_AddRef ( @@ -262,6 +403,509 @@ nssToken_GetName NSSToken *tok ); +NSS_EXTERN NSSModule * +nssToken_GetModule +( + NSSToken *token +); + +NSS_EXTERN NSSSlot * +nssToken_GetSlot +( + NSSToken *tok +); + +NSS_EXTERN PRBool +nssToken_NeedsPINInitialization +( + NSSToken *token +); + +#ifdef PURE_STAN_BUILD +NSS_EXTERN nssCryptokiObject * +nssToken_ImportCertificate +( + NSSToken *tok, + nssSession *sessionOpt, + NSSCertificateType certType, + NSSItem *id, + NSSUTF8 *nickname, + NSSDER *encoding, + NSSDER *issuer, + NSSDER *subject, + NSSDER *serial, + PRBool asTokenObject +); + +NSS_EXTERN nssCryptokiObject * +nssToken_ImportTrust +( + NSSToken *tok, + nssSession *sessionOpt, + NSSDER *certEncoding, + NSSDER *certIssuer, + NSSDER *certSerial, + nssTrustLevel serverAuth, + nssTrustLevel clientAuth, + nssTrustLevel codeSigning, + nssTrustLevel emailProtection, + PRBool asTokenObject +); + +NSS_EXTERN nssCryptokiObject * +nssToken_ImportCRL +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *subject, + NSSDER *encoding, + PRBool isKRL, + NSSUTF8 *url, + PRBool asTokenObject +); + +/* Permanently remove an object from the token. */ +NSS_EXTERN PRStatus +nssToken_DeleteStoredObject +( + nssCryptokiObject *instance +); + +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificates +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificatesBySubject +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *subject, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificatesByNickname +( + NSSToken *token, + nssSession *sessionOpt, + NSSUTF8 *name, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificatesByEmail +( + NSSToken *token, + nssSession *sessionOpt, + NSSASCII7 *email, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCertificatesByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *id, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject * +nssToken_FindCertificateByIssuerAndSerialNumber +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *issuer, + NSSDER *serial, + nssTokenSearchType searchType, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject * +nssToken_FindCertificateByEncodedCertificate +( + NSSToken *token, + nssSession *sessionOpt, + NSSBER *encodedCertificate, + nssTokenSearchType searchType, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject ** +nssToken_FindTrustObjects +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject * +nssToken_FindTrustForCertificate +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *certEncoding, + NSSDER *certIssuer, + NSSDER *certSerial, + nssTokenSearchType searchType +); + +NSS_EXTERN nssCryptokiObject ** +nssToken_FindCRLs +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject ** +nssToken_FindPrivateKeys +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +); + +NSS_EXTERN nssCryptokiObject * +nssToken_FindPrivateKeyByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *keyID +); + +NSS_EXTERN nssCryptokiObject * +nssToken_FindPublicKeyByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *keyID +); + +#endif /* PURE_STAN_BUILD */ + +NSS_EXTERN NSSItem * +nssToken_Digest +( + NSSToken *tok, + nssSession *sessionOpt, + NSSAlgorithmAndParameters *ap, + NSSItem *data, + NSSItem *rvOpt, + NSSArena *arenaOpt +); + +NSS_EXTERN PRStatus +nssToken_BeginDigest +( + NSSToken *tok, + nssSession *sessionOpt, + NSSAlgorithmAndParameters *ap +); + +NSS_EXTERN PRStatus +nssToken_ContinueDigest +( + NSSToken *tok, + nssSession *sessionOpt, + NSSItem *item +); + +NSS_EXTERN NSSItem * +nssToken_FinishDigest +( + NSSToken *tok, + nssSession *sessionOpt, + NSSItem *rvOpt, + NSSArena *arenaOpt +); + +/* nssSession + * + * nssSession_Destroy + * nssSession_EnterMonitor + * nssSession_ExitMonitor + * nssSession_IsReadWrite + */ + +NSS_EXTERN PRStatus +nssSession_Destroy +( + nssSession *s +); + +/* would like to inline */ +NSS_EXTERN PRStatus +nssSession_EnterMonitor +( + nssSession *s +); + +/* would like to inline */ +NSS_EXTERN PRStatus +nssSession_ExitMonitor +( + nssSession *s +); + +/* would like to inline */ +NSS_EXTERN PRBool +nssSession_IsReadWrite +( + nssSession *s +); + +/* nssCryptokiObject + * + * An object living on a cryptoki token. + * Not really proper to mix up the object types just because + * nssCryptokiObject itself is generic, but doing so anyway. + * + * nssCryptokiObject_Destroy + * nssCryptokiObject_Equal + * nssCryptokiObject_Clone + * nssCryptokiCertificate_GetAttributes + * nssCryptokiPrivateKey_GetAttributes + * nssCryptokiPublicKey_GetAttributes + * nssCryptokiTrust_GetAttributes + * nssCryptokiCRL_GetAttributes + */ + +NSS_EXTERN void +nssCryptokiObject_Destroy +( + nssCryptokiObject *object +); + +NSS_EXTERN PRBool +nssCryptokiObject_Equal +( + nssCryptokiObject *object1, + nssCryptokiObject *object2 +); + +NSS_EXTERN nssCryptokiObject * +nssCryptokiObject_Clone +( + nssCryptokiObject *object +); + +NSS_EXTERN PRStatus +nssCryptokiCertificate_GetAttributes +( + nssCryptokiObject *object, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSCertificateType *certTypeOpt, + NSSItem *idOpt, + NSSDER *encodingOpt, + NSSDER *issuerOpt, + NSSDER *serialOpt, + NSSDER *subjectOpt, + NSSASCII7 **emailOpt +); + +NSS_EXTERN PRStatus +nssCryptokiTrust_GetAttributes +( + nssCryptokiObject *trustObject, + nssSession *sessionOpt, + nssTrustLevel *serverAuth, + nssTrustLevel *clientAuth, + nssTrustLevel *codeSigning, + nssTrustLevel *emailProtection +); + +NSS_EXTERN PRStatus +nssCryptokiCRL_GetAttributes +( + nssCryptokiObject *crlObject, + nssSession *sessionOpt, + NSSArena *arenaOpt, + NSSItem *crl, + NSSItem *krl, + NSSItem *url +); + +NSS_EXTERN void +nssModuleArray_Destroy +( + NSSModule **modules +); + +/* nssSlotArray + * + * nssSlotArray_Destroy + */ + +NSS_EXTERN void +nssSlotArray_Destroy +( + NSSSlot **slots +); + +/* nssTokenArray + * + * nssTokenArray_Destroy + */ + +NSS_EXTERN void +nssTokenArray_Destroy +( + NSSToken **tokens +); + +/* nssCryptokiObjectArray + * + * nssCryptokiObjectArray_Destroy + */ +NSS_EXTERN void +nssCryptokiObjectArray_Destroy +( + nssCryptokiObject **object +); + +/* nssSlotList +* + * An ordered list of slots. The order can be anything, it is set in the + * Add methods. Perhaps it should be CreateInCertOrder, ...? + * + * nssSlotList_Create + * nssSlotList_Destroy + * nssSlotList_Add + * nssSlotList_AddModuleSlots + * nssSlotList_GetSlots + * nssSlotList_FindSlotByName + * nssSlotList_FindTokenByName + * nssSlotList_GetBestSlot + * nssSlotList_GetBestSlotForAlgorithmAndParameters + * nssSlotList_GetBestSlotForAlgorithmsAndParameters + */ + +/* nssSlotList_Create + */ +NSS_EXTERN nssSlotList * +nssSlotList_Create +( + NSSArena *arenaOpt +); + +/* nssSlotList_Destroy + */ +NSS_EXTERN void +nssSlotList_Destroy +( + nssSlotList *slotList +); + +/* nssSlotList_Add + * + * Add the given slot in the given order. + */ +NSS_EXTERN PRStatus +nssSlotList_Add +( + nssSlotList *slotList, + NSSSlot *slot, + PRUint32 order +); + +/* nssSlotList_AddModuleSlots + * + * Add all slots in the module, in the given order (the slots will have + * equal weight). + */ +NSS_EXTERN PRStatus +nssSlotList_AddModuleSlots +( + nssSlotList *slotList, + NSSModule *module, + PRUint32 order +); + +/* nssSlotList_GetSlots + */ +NSS_EXTERN NSSSlot ** +nssSlotList_GetSlots +( + nssSlotList *slotList +); + +/* nssSlotList_FindSlotByName + */ +NSS_EXTERN NSSSlot * +nssSlotList_FindSlotByName +( + nssSlotList *slotList, + NSSUTF8 *slotName +); + +/* nssSlotList_FindTokenByName + */ +NSS_EXTERN NSSToken * +nssSlotList_FindTokenByName +( + nssSlotList *slotList, + NSSUTF8 *tokenName +); + +/* nssSlotList_GetBestSlot + * + * The best slot is the highest ranking in order, i.e., the first in the + * list. + */ +NSS_EXTERN NSSSlot * +nssSlotList_GetBestSlot +( + nssSlotList *slotList +); + +/* nssSlotList_GetBestSlotForAlgorithmAndParameters + * + * Highest-ranking slot than can handle algorithm/parameters. + */ +NSS_EXTERN NSSSlot * +nssSlotList_GetBestSlotForAlgorithmAndParameters +( + nssSlotList *slotList, + NSSAlgorithmAndParameters *ap +); + +/* nssSlotList_GetBestSlotForAlgorithmsAndParameters + * + * Highest-ranking slot than can handle all algorithms/parameters. + */ +NSS_EXTERN NSSSlot * +nssSlotList_GetBestSlotForAlgorithmsAndParameters +( + nssSlotList *slotList, + NSSAlgorithmAndParameters **ap +); + +#ifndef PURE_STAN_BUILD +/* XXX the following remain while merging new work */ + NSS_EXTERN PRStatus nssToken_ImportCertificate ( @@ -305,22 +949,6 @@ nssToken_SetHasCrls NSSToken *tok ); -NSS_EXTERN NSSPublicKey * -nssToken_GenerateKeyPair -( - NSSToken *tok, - nssSession *sessionOpt - /* algorithm and parameters */ -); - -NSS_EXTERN NSSSymmetricKey * -nssToken_GenerateSymmetricKey -( - NSSToken *tok, - nssSession *sessionOpt - /* algorithm and parameters */ -); - /* Permanently remove an object from the token. */ NSS_EXTERN PRStatus nssToken_DeleteStoredObject @@ -400,82 +1028,6 @@ nssToken_FindTrustForCert nssTokenSearchType searchType ); -NSS_EXTERN NSSItem * -nssToken_Digest -( - NSSToken *tok, - nssSession *sessionOpt, - NSSAlgorithmAndParameters *ap, - NSSItem *data, - NSSItem *rvOpt, - NSSArena *arenaOpt -); - -NSS_EXTERN PRStatus -nssToken_BeginDigest -( - NSSToken *tok, - nssSession *sessionOpt, - NSSAlgorithmAndParameters *ap -); - -NSS_EXTERN PRStatus -nssToken_ContinueDigest -( - NSSToken *tok, - nssSession *sessionOpt, - NSSItem *item -); - -NSS_EXTERN NSSItem * -nssToken_FinishDigest -( - NSSToken *tok, - nssSession *sessionOpt, - NSSItem *rvOpt, - NSSArena *arenaOpt -); - -NSS_EXTERN PRStatus -nssSession_Destroy -( - nssSession *s -); - -/* would like to inline */ -NSS_EXTERN PRStatus -nssSession_EnterMonitor -( - nssSession *s -); - -/* would like to inline */ -NSS_EXTERN PRStatus -nssSession_ExitMonitor -( - nssSession *s -); - -/* would like to inline */ -NSS_EXTERN PRBool -nssSession_IsReadWrite -( - nssSession *s -); - -NSS_EXTERN NSSAlgorithmAndParameters * -NSSAlgorithmAndParameters_CreateSHA1Digest -( - NSSArena *arenaOpt -); - -NSS_EXTERN NSSAlgorithmAndParameters * -NSSAlgorithmAndParameters_CreateMD5Digest -( - NSSArena *arenaOpt -); - -#ifdef NSS_3_4_CODE /* exposing this for the smart card cache code */ NSS_EXTERN nssCryptokiInstance * nssCryptokiInstance_Create @@ -485,7 +1037,8 @@ nssCryptokiInstance_Create CK_OBJECT_HANDLE h, PRBool isTokenObject ); -#endif + +#endif /* !PURE_STAN_BUILD */ PR_END_EXTERN_C diff --git a/mozilla/security/nss/lib/dev/devm.h b/mozilla/security/nss/lib/dev/devm.h index c3e31d9374d..9547cb16115 100644 --- a/mozilla/security/nss/lib/dev/devm.h +++ b/mozilla/security/nss/lib/dev/devm.h @@ -35,28 +35,119 @@ #define DEVM_H #ifdef DEBUG -static const char DEVM_CVS_ID[] = "@(#) $RCSfile: devm.h,v $ $Revision: 1.4 $ $Date: 2001-11-08 00:14:52 $ $Name: not supported by cvs2svn $"; +static const char DEVM_CVS_ID[] = "@(#) $RCSfile: devm.h,v $ $Revision: 1.5 $ $Date: 2002-04-04 20:00:21 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ -#ifndef DEVT_H -#include "devt.h" -#endif /* DEVT_H */ - -#ifndef NSSCKT_H -#include "nssckt.h" -#endif /* NSSCKT_H */ - #ifndef BASE_H #include "base.h" #endif /* BASE_H */ +#ifndef NSSCKT_H +#include "nssckt.h" +#endif /* NSSCKT_H */ + +#ifndef DEV_H +#include "dev.h" +#endif /* DEV_H */ + +#ifndef DEVTM_H +#include "devtm.h" +#endif /* DEVTM_H */ + PR_BEGIN_EXTERN_C +/* Shortcut to cryptoki API functions. */ +#define CKAPI(epv) \ + ((CK_FUNCTION_LIST_PTR)(epv)) + +NSS_EXTERN void +nssDevice_AddRef +( + struct nssDeviceBaseStr *device +); + +NSS_EXTERN PRBool +nssDevice_Destroy +( + struct nssDeviceBaseStr *device +); + +NSS_EXTERN PRBool +nssModule_IsThreadSafe +( + NSSModule *module +); + +NSS_EXTERN PRBool +nssModule_IsInternal +( + NSSModule *mod +); + +NSS_EXTERN PRBool +nssModule_IsModuleDBOnly +( + NSSModule *mod +); + +NSS_EXTERN void * +nssModule_GetCryptokiEPV +( + NSSModule *mod +); + +NSS_EXTERN NSSSlot * +nssSlot_Create +( + CK_SLOT_ID slotId, + NSSModule *parent +); + +NSS_EXTERN void * +nssSlot_GetCryptokiEPV +( + NSSSlot *slot +); + +NSS_EXTERN NSSToken * +nssToken_Create +( + CK_SLOT_ID slotID, + NSSSlot *peer +); + +NSS_EXTERN void * +nssToken_GetCryptokiEPV +( + NSSToken *token +); + +NSS_EXTERN nssSession * +nssToken_GetDefaultSession +( + NSSToken *token +); + +NSS_EXTERN PRBool +nssToken_IsLoginRequired +( + NSSToken *token +); + +NSS_EXTERN nssCryptokiObject * +nssCryptokiObject_Create +( + NSSToken *t, + nssSession *session, + CK_OBJECT_HANDLE h +); + /* PKCS#11 stores strings in a fixed-length buffer padded with spaces. This * function gets the length of the actual string. */ NSS_EXTERN PRUint32 -nssPKCS11StringLength( +nssPKCS11String_Length +( CK_CHAR *pkcs11str, PRUint32 bufLen ); diff --git a/mozilla/security/nss/lib/dev/devmod.c b/mozilla/security/nss/lib/dev/devmod.c index dc0f24a9392..76b6bc9949f 100644 --- a/mozilla/security/nss/lib/dev/devmod.c +++ b/mozilla/security/nss/lib/dev/devmod.c @@ -32,30 +32,72 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: devmod.c,v $ $Revision: 1.2 $ $Date: 2001-11-28 16:23:39 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: devmod.c,v $ $Revision: 1.3 $ $Date: 2002-04-04 20:00:21 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ -#include "nspr.h" - -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ - -#ifndef DEVM_H -#include "devm.h" -#endif /* DEVM_H */ - #ifndef NSSCKEPV_H #include "nssckepv.h" #endif /* NSSCKEPV_H */ +#ifndef DEVM_H +#include "devm.h" +#endif /* DEVM_H */ + #ifndef CKHELPER_H #include "ckhelper.h" #endif /* CKHELPER_H */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ +#ifdef PURE_STAN_CODE + +extern void FC_GetFunctionList(void); +extern void NSC_GetFunctionList(void); +extern void NSC_ModuleDBFunc(void); + +/* The list of boolean flags used to describe properties of a + * module. + */ +#define NSSMODULE_FLAGS_NOT_THREADSAFE 0x0001 /* isThreadSafe */ +#define NSSMODULE_FLAGS_INTERNAL 0x0002 /* isInternal */ +#define NSSMODULE_FLAGS_FIPS 0x0004 /* isFIPS */ +#define NSSMODULE_FLAGS_MODULE_DB 0x0008 /* isModuleDB */ +#define NSSMODULE_FLAGS_MODULE_DB_ONLY 0x0010 /* moduleDBOnly */ +#define NSSMODULE_FLAGS_CRITICAL 0x0020 /* isCritical */ + +struct NSSModuleStr { + struct nssDeviceBaseStr base; + NSSUTF8 *libraryName; + PRLibrary *library; + char *libraryParams; + void *moduleDBFunc; + void *epv; + CK_INFO info; + NSSSlot **slots; + PRUint32 numSlots; + PRBool isLoaded; + struct { + PRInt32 trust; + PRInt32 cipher; + PRInt32 certStorage; + } order; +}; + +#define NSSMODULE_IS_THREADSAFE(module) \ + (!(module->base.flags & NSSMODULE_FLAGS_NOT_THREADSAFE)) + +#define NSSMODULE_IS_INTERNAL(module) \ + (module->base.flags & NSSMODULE_FLAGS_INTERNAL) + +#define NSSMODULE_IS_FIPS(module) \ + (module->base.flags & NSSMODULE_FLAGS_FIPS) + +#define NSSMODULE_IS_MODULE_DB(module) \ + (module->base.flags & NSSMODULE_FLAGS_MODULE_DB) + +#define NSSMODULE_IS_MODULE_DB_ONLY(module) \ + (module->base.flags & NSSMODULE_FLAGS_MODULE_DB_ONLY) + +#define NSSMODULE_IS_CRITICAL(module) \ + (module->base.flags & NSSMODULE_FLAGS_CRITICAL) /* Threading callbacks for C_Initialize. Use NSPR threads. */ @@ -92,6 +134,9 @@ nss_ck_UnlockMutex(CK_VOID_PTR mutex) } /* Default callback args to C_Initialize */ +/* XXX not const because we are modifying the pReserved argument in order + * to use the libraryParams extension. + */ static CK_C_INITIALIZE_ARGS s_ck_initialize_args = { nss_ck_CreateMutex, /* CreateMutex */ @@ -103,6 +148,171 @@ s_ck_initialize_args = { NULL /* pReserved */ }; +/* load all slots in a module. */ +static PRStatus +module_load_slots(NSSModule *mod) +{ + CK_ULONG i, ulNumSlots; + CK_SLOT_ID *slotIDs; + nssArenaMark *mark = NULL; + NSSSlot **slots; + PRStatus nssrv; + CK_RV ckrv; + /* Get the number of slots */ + ckrv = CKAPI(mod->epv)->C_GetSlotList(CK_FALSE, NULL, &ulNumSlots); + if (ckrv != CKR_OK) { + /* what is the error? */ + return PR_FAILURE; + } + /* Alloc memory for the array of slot ID's */ + slotIDs = nss_ZNEWARRAY(NULL, CK_SLOT_ID, ulNumSlots); + if (!slotIDs) { + goto loser; + } + /* Get the actual slot list */ + ckrv = CKAPI(mod->epv)->C_GetSlotList(CK_FALSE, slotIDs, &ulNumSlots); + if (ckrv != CKR_OK) { + /* what is the error? */ + goto loser; + } + /* Alloc memory for the array of slots, in the module's arena */ + mark = nssArena_Mark(mod->base.arena); /* why mark? it'll be destroyed */ + if (!mark) { + return PR_FAILURE; + } + slots = nss_ZNEWARRAY(mod->base.arena, NSSSlot *, ulNumSlots); + if (!slots) { + goto loser; + } + /* Initialize each slot */ + for (i=0; ibase.arena, mark); + if (nssrv != PR_SUCCESS) { + goto loser; + } + mod->slots = slots; + mod->numSlots = ulNumSlots; + return PR_SUCCESS; +loser: + if (mark) { + nssArena_Release(mod->base.arena, mark); + } + nss_ZFreeIf(slotIDs); + return PR_FAILURE; +} + +NSS_IMPLEMENT PRStatus +nssModule_Load +( + NSSModule *mod +) +{ + PRLibrary *library = NULL; + CK_C_GetFunctionList epv; + CK_RV ckrv; + if (NSSMODULE_IS_INTERNAL(mod)) { + /* internal, statically get the C_GetFunctionList function */ + if (NSSMODULE_IS_FIPS(mod)) { + epv = (CK_C_GetFunctionList) FC_GetFunctionList; + } else { + epv = (CK_C_GetFunctionList) NSC_GetFunctionList; + } + if (NSSMODULE_IS_MODULE_DB(mod)) { + mod->moduleDBFunc = (void *) NSC_ModuleDBFunc; + } + if (NSSMODULE_IS_MODULE_DB_ONLY(mod)) { + mod->isLoaded = PR_TRUE; /* XXX needed? */ + return PR_SUCCESS; + } + } else { + /* Use NSPR to load the library */ + library = PR_LoadLibrary(mod->libraryName); + if (!library) { + /* what's the error to set? */ + return PR_FAILURE; + } + mod->library = library; + /* Skip if only getting the db loader function */ + if (!NSSMODULE_IS_MODULE_DB_ONLY(mod)) { + /* Load the cryptoki entry point function */ + epv = (CK_C_GetFunctionList)PR_FindSymbol(library, + "C_GetFunctionList"); + } + /* Load the module database loader function */ + if (NSSMODULE_IS_MODULE_DB(mod)) { + mod->moduleDBFunc = (void *)PR_FindSymbol(library, + "NSS_ReturnModuleSpecData"); + } + } + if (epv == NULL) { + goto loser; + } + /* Load the cryptoki entry point vector (function list) */ + ckrv = (*epv)((CK_FUNCTION_LIST_PTR *)&mod->epv); + if (ckrv != CKR_OK) { + goto loser; + } + /* Initialize the module */ + if (mod->libraryParams) { + s_ck_initialize_args.LibraryParameters = (void *)mod->libraryParams; + } else { + s_ck_initialize_args.LibraryParameters = NULL; + } + ckrv = CKAPI(mod->epv)->C_Initialize(&s_ck_initialize_args); + if (ckrv != CKR_OK) { + /* Apparently the token is not thread safe. Retry without + * threading parameters. + */ + mod->base.flags |= NSSMODULE_FLAGS_NOT_THREADSAFE; + ckrv = CKAPI(mod->epv)->C_Initialize((CK_VOID_PTR)NULL); + if (ckrv != CKR_OK) { + goto loser; + } + } + /* TODO: check the version # using C_GetInfo */ + ckrv = CKAPI(mod->epv)->C_GetInfo(&mod->info); + if (ckrv != CKR_OK) { + goto loser; + } + /* TODO: if the name is not set, get it from info.libraryDescription */ + /* Now load the slots */ + if (module_load_slots(mod) != PR_SUCCESS) { + goto loser; + } + /* Module has successfully loaded */ + mod->isLoaded = PR_TRUE; + return PR_SUCCESS; +loser: + if (library) { + PR_UnloadLibrary(library); + } + /* clear all values set above, they are invalid now */ + mod->library = NULL; + mod->epv = NULL; + return PR_FAILURE; +} + +NSS_IMPLEMENT PRStatus +nssModule_Unload +( + NSSModule *mod +) +{ + PRStatus nssrv = PR_SUCCESS; + if (mod->library) { + (void)CKAPI(mod->epv)->C_Finalize(NULL); + nssrv = PR_UnloadLibrary(mod->library); + } + /* Free the slots, yes? */ + mod->library = NULL; + mod->epv = NULL; + mod->isLoaded = PR_FALSE; + return nssrv; +} + /* Alloc memory for a module. Copy in the module name and library path * if provided. XXX use the opaque arg also, right? */ @@ -130,21 +340,25 @@ nssModule_Create /* if the name is a duplicate, should that be tested here? or * wait for Load? */ - rvMod->name = nssUTF8_Duplicate(moduleOpt, arena); - if (!rvMod->name) { + rvMod->base.name = nssUTF8_Duplicate(moduleOpt, arena); + if (!rvMod->base.name) { goto loser; } } if (uriOpt) { /* Load the module from a URI. */ /* XXX at this time - only file URI (even worse, no file:// for now) */ - rvMod->libraryPath = nssUTF8_Duplicate(uriOpt, arena); - if (!rvMod->libraryPath) { + rvMod->libraryName = nssUTF8_Duplicate(uriOpt, arena); + if (!rvMod->libraryName) { goto loser; } } - rvMod->arena = arena; - rvMod->refCount = 1; + rvMod->base.arena = arena; + rvMod->base.refCount = 1; + rvMod->base.lock = PZ_NewLock(nssNSSILockOther); + if (!rvMod->base.lock) { + goto loser; + } /* everything else is 0/NULL at this point. */ return rvMod; loser: @@ -152,80 +366,401 @@ loser: return (NSSModule *)NULL; } -/* load all slots in a module. */ +NSS_EXTERN PRStatus +nssCryptokiArgs_ParseNextPair +( + NSSUTF8 *start, + NSSUTF8 **attrib, + NSSUTF8 **value, + NSSUTF8 **remainder, + NSSArena *arenaOpt +); + static PRStatus -module_load_slots(NSSModule *mod) +parse_slot_flags +( + NSSSlot *slot, + NSSUTF8 *slotFlags +) +{ + PRStatus nssrv = PR_SUCCESS; +#if 0 + PRBool done = PR_FALSE; + NSSUTF8 *mark, *last; + last = mark = slotFlags; + while (PR_TRUE) { + while (*mark && *mark != ',') ++mark; + if (!*mark) done = PR_TRUE; + *mark = '\0'; + if (nssUTF8_Equal(last, "RANDOM", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_HAS_RANDOM; + } else if (nssUTF8_Equal(last, "RSA", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_RSA; + } else if (nssUTF8_Equal(last, "DSA", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_DSA; + } else if (nssUTF8_Equal(last, "DH", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_DH; + } else if (nssUTF8_Equal(last, "RC2", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_RC2; + } else if (nssUTF8_Equal(last, "RC4", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_RC4; + } else if (nssUTF8_Equal(last, "RC5", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_RC5; + } else if (nssUTF8_Equal(last, "DES", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_DES; + } else if (nssUTF8_Equal(last, "AES", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_AES; + } else if (nssUTF8_Equal(last, "SHA1", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_SHA1; + } else if (nssUTF8_Equal(last, "MD2", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_MD2; + } else if (nssUTF8_Equal(last, "MD5", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_MD5; + } else if (nssUTF8_Equal(last, "SSL", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_SSL; + } else if (nssUTF8_Equal(last, "TLS", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_TLS; + } else if (nssUTF8_Equal(last, "PublicCerts", &nssrv)) { + slot->base.flags |= NSSSLOT_FLAGS_FRIENDLY; + } else { + return PR_FAILURE; + } + if (done) break; + last = ++mark; + } +#endif + return nssrv; +} + +static PRStatus +parse_slot_parameters +( + NSSSlot *slot, + NSSUTF8 *slotParams, + NSSArena *tmparena +) +{ + PRStatus nssrv = PR_SUCCESS; + NSSUTF8 *current, *remainder; + NSSUTF8 *attrib, *value; + current = slotParams; + while (nssrv == PR_SUCCESS) { + nssrv = nssCryptokiArgs_ParseNextPair(current, + &attrib, &value, + &remainder, tmparena); + if (nssrv != PR_SUCCESS) break; + if (value) { + if (nssUTF8_Equal(attrib, "slotFlags", &nssrv)) { + nssrv = parse_slot_flags(slot, value); + } else if (nssUTF8_Equal(attrib, "askpw", &nssrv)) { + } else if (nssUTF8_Equal(attrib, "timeout", &nssrv)) { + } + } + if (*remainder == '\0') break; + current = remainder; + } + return nssrv; +} + +/* softoken seems to use "0x0000001", but no standard yet... perhaps this + * should store the number as an ID, in case the input isn't 1,2,3,...? + */ +static PRIntn +get_slot_number(NSSUTF8* snString) +{ + /* XXX super big hack */ + return atoi(&snString[strlen(snString)-1]); +} + +static PRStatus +parse_module_slot_parameters +( + NSSModule *mod, + NSSUTF8 *slotParams +) +{ + PRStatus nssrv = PR_SUCCESS; + NSSUTF8 *current, *remainder; + NSSUTF8 *attrib, *value; + NSSArena *tmparena; + PRIntn slotNum; + tmparena = nssArena_Create(); + if (!tmparena) { + return PR_FAILURE; + } + current = slotParams; + while (nssrv == PR_SUCCESS) { + nssrv = nssCryptokiArgs_ParseNextPair(current, + &attrib, &value, + &remainder, tmparena); + if (nssrv != PR_SUCCESS) break; + if (value) { + slotNum = get_slot_number(attrib); + if (slotNum < 0 || slotNum > mod->numSlots) { + return PR_FAILURE; + } + nssrv = parse_slot_parameters(mod->slots[slotNum], + value, tmparena); + if (nssrv != PR_SUCCESS) break; + } + if (*remainder == '\0') break; + current = remainder; + } + return nssrv; +} + +static PRStatus +parse_nss_flags +( + NSSModule *mod, + NSSUTF8 *nssFlags +) +{ + PRStatus nssrv = PR_SUCCESS; + PRBool done = PR_FALSE; + NSSUTF8 *mark, *last; + last = mark = nssFlags; + while (PR_TRUE) { + while (*mark && *mark != ',') ++mark; + if (!*mark) done = PR_TRUE; + *mark = '\0'; + if (nssUTF8_Equal(last, "internal", &nssrv)) { + mod->base.flags |= NSSMODULE_FLAGS_INTERNAL; + } else if (nssUTF8_Equal(last, "moduleDB", &nssrv)) { + mod->base.flags |= NSSMODULE_FLAGS_MODULE_DB; + } else if (nssUTF8_Equal(last, "moduleDBOnly", &nssrv)) { + mod->base.flags |= NSSMODULE_FLAGS_MODULE_DB_ONLY; + } else if (nssUTF8_Equal(last, "critical", &nssrv)) { + mod->base.flags |= NSSMODULE_FLAGS_CRITICAL; + } else { + return PR_FAILURE; + } + if (done) break; + last = ++mark; + } + return nssrv; +} + +static PRStatus +parse_nss_parameters +( + NSSModule *mod, + NSSUTF8 *nssParams, + NSSArena *tmparena, + NSSUTF8 **slotParams +) +{ + PRStatus nssrv = PR_SUCCESS; + NSSUTF8 *current, *remainder; + NSSUTF8 *attrib, *value; + current = nssParams; + while (nssrv == PR_SUCCESS) { + nssrv = nssCryptokiArgs_ParseNextPair(current, + &attrib, &value, + &remainder, tmparena); + if (nssrv != PR_SUCCESS) break; + if (value) { + if (nssUTF8_Equal(attrib, "flags", &nssrv) || + nssUTF8_Equal(attrib, "Flags", &nssrv)) { + nssrv = parse_nss_flags(mod, value); + } else if (nssUTF8_Equal(attrib, "trustOrder", &nssrv)) { + mod->order.trust = atoi(value); + } else if (nssUTF8_Equal(attrib, "cipherOrder", &nssrv)) { + mod->order.cipher = atoi(value); + } else if (nssUTF8_Equal(attrib, "ciphers", &nssrv)) { + } else if (nssUTF8_Equal(attrib, "slotParams", &nssrv)) { + /* slotParams doesn't get an arena, it is handled separately */ + *slotParams = nssUTF8_Duplicate(value, NULL); + } + } + if (*remainder == '\0') break; + current = remainder; + } + return nssrv; +} + +static PRStatus +parse_module_parameters +( + NSSModule *mod, + NSSUTF8 *moduleParams, + NSSUTF8 **slotParams +) +{ + PRStatus nssrv = PR_SUCCESS; + NSSUTF8 *current, *remainder; + NSSUTF8 *attrib, *value; + NSSArena *arena = mod->base.arena; + NSSArena *tmparena; + current = moduleParams; + tmparena = nssArena_Create(); + if (!tmparena) { + return PR_FAILURE; + } + while (nssrv == PR_SUCCESS) { + nssrv = nssCryptokiArgs_ParseNextPair(current, + &attrib, &value, + &remainder, tmparena); + if (nssrv != PR_SUCCESS) break; + if (value) { + if (nssUTF8_Equal(attrib, "name", &nssrv)) { + mod->base.name = nssUTF8_Duplicate(value, arena); + } else if (nssUTF8_Equal(attrib, "library", &nssrv)) { + mod->libraryName = nssUTF8_Duplicate(value, arena); + } else if (nssUTF8_Equal(attrib, "parameters", &nssrv)) { + mod->libraryParams = nssUTF8_Duplicate(value, arena); + } else if (nssUTF8_Equal(attrib, "NSS", &nssrv)) { + parse_nss_parameters(mod, value, tmparena, slotParams); + } + } + if (*remainder == '\0') break; + current = remainder; + } + nssArena_Destroy(tmparena); + return nssrv; +} + +static NSSUTF8 ** +get_module_specs +( + NSSModule *mod +) +{ + SECMODModuleDBFunc func = (SECMODModuleDBFunc)mod->moduleDBFunc; + if (func) { + return (*func)(SECMOD_MODULE_DB_FUNCTION_FIND, + mod->libraryParams, + NULL); + } + return NULL; +} + +/* XXX continue working on */ +NSS_IMPLEMENT NSSModule * +nssModule_CreateFromSpec +( + NSSUTF8 *moduleSpec, + NSSModule *parent, + PRBool loadSubModules +) { - CK_ULONG i, ulNumSlots; - CK_SLOT_ID *slotIDs; - nssArenaMark *mark = NULL; - NSSSlot **slots; PRStatus nssrv; - CK_RV ckrv; - /* Get the number of slots */ - ckrv = CKAPI(mod)->C_GetSlotList(CK_FALSE, NULL, &ulNumSlots); - if (ckrv != CKR_OK) { - /* what is the error? */ - return PR_FAILURE; + NSSModule *thisModule; + NSSArena *arena; + NSSUTF8 *slotParams = NULL; + arena = nssArena_Create(); + if (!arena) { + return NULL; } - /* Alloc memory for the array of slot ID's */ - slotIDs = nss_ZNEWARRAY(NULL, CK_SLOT_ID, ulNumSlots); - if (!slotIDs) { + thisModule = nss_ZNEW(arena, NSSModule); + if (!thisModule) { goto loser; } - /* Get the actual slot list */ - ckrv = CKAPI(mod)->C_GetSlotList(CK_FALSE, slotIDs, &ulNumSlots); - if (ckrv != CKR_OK) { - /* what is the error? */ + thisModule->base.lock = PZ_NewLock(nssILockOther); + if (!thisModule->base.lock) { goto loser; } - /* Alloc memory for the array of slots, in the module's arena */ - mark = nssArena_Mark(mod->arena); - if (!mark) { - return PR_FAILURE; - } - slots = nss_ZNEWARRAY(mod->arena, NSSSlot *, ulNumSlots); - if (!slots) { + PR_AtomicIncrement(&thisModule->base.refCount); + thisModule->base.arena = arena; + thisModule->base.lock = PZ_NewLock(nssNSSILockOther); + if (!thisModule->base.lock) { goto loser; } - /* Initialize each slot */ - for (i=0; iarena, slotIDs[i], mod); - } - nss_ZFreeIf(slotIDs); - nssrv = nssArena_Unmark(mod->arena, mark); + nssrv = parse_module_parameters(thisModule, moduleSpec, &slotParams); if (nssrv != PR_SUCCESS) { goto loser; } - mod->slots = slots; - mod->numSlots = ulNumSlots; - return PR_SUCCESS; -loser: - if (mark) { - nssArena_Release(mod->arena, mark); + nssrv = nssModule_Load(thisModule); + if (nssrv != PR_SUCCESS) { + goto loser; } - nss_ZFreeIf(slotIDs); - return PR_FAILURE; + if (slotParams) { + nssrv = parse_module_slot_parameters(thisModule, slotParams); + nss_ZFreeIf(slotParams); + if (nssrv != PR_SUCCESS) { + goto loser; + } + } + if (loadSubModules && NSSMODULE_IS_MODULE_DB(thisModule)) { + NSSUTF8 **moduleSpecs; + NSSUTF8 **index; + /* get the array of sub modules one level below this module */ + moduleSpecs = get_module_specs(thisModule); + /* iterate over the array */ + for (index = moduleSpecs; index && *index; index++) { + NSSModule *child; + /* load the child recursively */ + child = nssModule_CreateFromSpec(*index, thisModule, PR_TRUE); + if (!child) { + /* when children fail, does the parent? */ + nssrv = PR_FAILURE; + break; + } + if (NSSMODULE_IS_CRITICAL(child) && !child->isLoaded) { + nssrv = PR_FAILURE; + nssModule_Destroy(child); + break; + } + nssModule_Destroy(child); + /*nss_ZFreeIf(*index);*/ + } + /*nss_ZFreeIf(moduleSpecs);*/ + } + /* The global list inherits the reference */ + nssrv = nssGlobalModuleList_Add(thisModule); + if (nssrv != PR_SUCCESS) { + goto loser; + } + return thisModule; +loser: + if (thisModule->base.lock) { + PZ_DestroyLock(thisModule->base.lock); + } + nssArena_Destroy(arena); + return (NSSModule *)NULL; } -/* This is going to take much more thought. The module has a list of slots, - * each of which points to a token. Presumably, all are ref counted. Some - * kind of consistency check is needed here, or perhaps at a higher level. - */ NSS_IMPLEMENT PRStatus nssModule_Destroy ( NSSModule *mod ) { - PRUint32 i; - if (--mod->refCount == 0) { - /* Ignore any failure here. */ - for (i=0; inumSlots; i++) { - nssSlot_Destroy(mod->slots[i]); + PRUint32 i, numSlots; + PR_AtomicDecrement(&mod->base.refCount); + if (mod->base.refCount == 0) { + if (mod->numSlots == 0) { + (void)nssModule_Unload(mod); + return nssArena_Destroy(mod->base.arena); + } else { + numSlots = mod->numSlots; + for (i=0; islots[i]); + } } + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssModule_DestroyFromSlot +( + NSSModule *mod, + NSSSlot *slot +) +{ + PRUint32 i, numSlots = 0; + PR_ASSERT(mod->base.refCount == 0); + for (i=0; inumSlots; i++) { + if (mod->slots[i] == slot) { + mod->slots[i] = NULL; + } else if (mod->slots[i]) { + numSlots++; + } + } + if (numSlots == 0) { (void)nssModule_Unload(mod); - return NSSArena_Destroy(mod->arena); + return nssArena_Destroy(mod->base.arena); } return PR_SUCCESS; } @@ -236,85 +771,70 @@ nssModule_AddRef NSSModule *mod ) { - ++mod->refCount; + PR_AtomicIncrement(&mod->base.refCount); return mod; } -NSS_IMPLEMENT PRStatus -nssModule_Load +NSS_IMPLEMENT NSSUTF8 * +nssModule_GetName ( NSSModule *mod ) { - PRLibrary *library = NULL; - CK_C_GetFunctionList ep; - CK_RV ckrv; - /* Use NSPR to load the library */ - library = PR_LoadLibrary((char *)mod->libraryPath); - if (!library) { - /* what's the error to set? */ - return PR_FAILURE; - } - mod->library = library; - /* TODO: semantics here in SECMOD_LoadModule about module db */ - /* Load the cryptoki entry point function */ - ep = (CK_C_GetFunctionList)PR_FindSymbol(library, "C_GetFunctionList"); - if (ep == NULL) { - goto loser; - } - /* Load the cryptoki entry point vector (function list) */ - ckrv = (*ep)((CK_FUNCTION_LIST_PTR *)&mod->epv); - if (ckrv != CKR_OK) { - goto loser; - } - /* Initialize the module */ - /* XXX This is where some additional parameters may need to come in, - * SECMOD_LoadModule has LibraryParameters - */ - ckrv = CKAPI(mod)->C_Initialize(&s_ck_initialize_args); - if (ckrv != CKR_OK) { - /* Apparently the token is not thread safe. Retry without - * threading parameters. - */ - mod->flags |= NSSMODULE_FLAGS_NOT_THREADSAFE; - ckrv = CKAPI(mod)->C_Initialize((CK_VOID_PTR)NULL); - if (ckrv != CKR_OK) { - goto loser; - } - } - /* TODO: check the version # using C_GetInfo */ - /* TODO: if the name is not set, get it from info.libraryDescription */ - /* Now load the slots */ - if (module_load_slots(mod) != PR_SUCCESS) { - goto loser; - } - /* Module has successfully loaded */ - return PR_SUCCESS; -loser: - if (library) { - PR_UnloadLibrary(library); - } - /* clear all values set above, they are invalid now */ - mod->library = NULL; - mod->epv = NULL; - return PR_FAILURE; + return mod->base.name; } -NSS_IMPLEMENT PRStatus -nssModule_Unload +NSS_IMPLEMENT PRBool +nssModule_IsThreadSafe +( + NSSModule *module +) +{ + return NSSMODULE_IS_THREADSAFE(module); +} + +NSS_IMPLEMENT PRBool +nssModule_IsInternal ( NSSModule *mod ) { - PRStatus nssrv = PR_SUCCESS; - if (mod->library) { - (void)CKAPI(mod)->C_Finalize(NULL); - nssrv = PR_UnloadLibrary(mod->library); + return NSSMODULE_IS_INTERNAL(mod); +} + +NSS_IMPLEMENT PRBool +nssModule_IsModuleDBOnly +( + NSSModule *mod +) +{ + return NSSMODULE_IS_MODULE_DB_ONLY(mod); +} + +NSS_IMPLEMENT void * +nssModule_GetCryptokiEPV +( + NSSModule *mod +) +{ + return mod->epv; +} + +NSS_IMPLEMENT NSSSlot ** +nssModule_GetSlots +( + NSSModule *mod +) +{ + PRUint32 i; + NSSSlot **rvSlots; + rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, mod->numSlots + 1); + if (rvSlots) { + for (i=0; inumSlots; i++) { + rvSlots[i] = nssSlot_AddRef(mod->slots[i]); + } } - /* Free the slots, yes? */ - mod->library = NULL; - mod->epv = NULL; - return nssrv; + return rvSlots; } NSS_IMPLEMENT NSSSlot * @@ -326,9 +846,13 @@ nssModule_FindSlotByName { PRUint32 i; PRStatus nssrv; + NSSSlot *slot; + NSSUTF8 *name; for (i=0; inumSlots; i++) { - if (nssUTF8_Equal(mod->slots[i]->name, slotName, &nssrv)) { - return nssSlot_AddRef(mod->slots[i]); + slot = mod->slots[i]; + name = nssSlot_GetName(slot); + if (nssUTF8_Equal(name, slotName, &nssrv)) { + return nssSlot_AddRef(slot); } if (nssrv != PR_SUCCESS) { break; @@ -337,7 +861,7 @@ nssModule_FindSlotByName return (NSSSlot *)NULL; } -NSS_EXTERN NSSToken * +NSS_IMPLEMENT NSSToken * nssModule_FindTokenByName ( NSSModule *mod, @@ -347,50 +871,30 @@ nssModule_FindTokenByName PRUint32 i; PRStatus nssrv; NSSToken *tok; + NSSUTF8 *name; for (i=0; inumSlots; i++) { - tok = mod->slots[i]->token; - if (nssUTF8_Equal(tok->name, tokenName, &nssrv)) { - return nssToken_AddRef(tok); - } - if (nssrv != PR_SUCCESS) { - break; + tok = nssSlot_GetToken(mod->slots[i]); + if (tok) { + name = nssToken_GetName(tok); + if (nssUTF8_Equal(name, tokenName, &nssrv)) { + return tok; + } + if (nssrv != PR_SUCCESS) { + break; + } } } return (NSSToken *)NULL; } -NSS_IMPLEMENT PRStatus * -nssModule_TraverseCertificates +NSS_IMPLEMENT PRInt32 +nssModule_GetCertOrder ( - NSSModule *mod, - PRStatus (*callback)(NSSCertificate *c, void *arg), - void *arg + NSSModule *module ) { - return NULL; + return 1; /* XXX */ } -#ifdef DEBUG -void -nssModule_Debug(NSSModule *m) -{ - PRUint32 i; - printf("\n"); - printf("Module Name: %s\n", m->name); - printf("Module Path: %s\n", m->libraryPath); - printf("Number of Slots in Module: %d\n\n", m->numSlots); - for (i=0; inumSlots; i++) { - printf("\tSlot #%d\n", i); - if (m->slots[i]->name) { - printf("\tSlot Name: %s\n", m->slots[i]->name); - } else { - printf("\tSlot Name: \n"); - } - if (m->slots[i]->token) { - printf("\tToken Name: %s\n", m->slots[i]->token->name); - } else { - printf("\tToken: \n"); - } - } -} -#endif +#endif /* PURE_STAN_BUILD */ + diff --git a/mozilla/security/nss/lib/dev/devobject.c b/mozilla/security/nss/lib/dev/devobject.c index d433a3a56ed..502f33b85c3 100644 --- a/mozilla/security/nss/lib/dev/devobject.c +++ b/mozilla/security/nss/lib/dev/devobject.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: devobject.c,v $ $Revision: 1.22 $ $Date: 2002-04-03 19:22:11 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: devobject.c,v $ $Revision: 1.23 $ $Date: 2002-04-04 20:00:22 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef DEV_H @@ -84,6 +84,7 @@ nssToken_DeleteStoredObject PRStatus nssrv; PRBool createdSession = PR_FALSE; NSSToken *token = instance->token; + void *epv = token->epv; nssSession *session = NULL; if (nssCKObject_IsAttributeTrue(instance->handle, CKA_TOKEN, token->defaultSession, @@ -99,7 +100,7 @@ nssToken_DeleteStoredObject return PR_FAILURE; } nssSession_EnterMonitor(session); - ckrv = CKAPI(token)->C_DestroyObject(session->handle, instance->handle); + ckrv = CKAPI(epv)->C_DestroyObject(session->handle, instance->handle); nssSession_ExitMonitor(session); if (createdSession) { nssSession_Destroy(session); @@ -121,6 +122,7 @@ import_object { nssSession *session = NULL; PRBool createdSession = PR_FALSE; + void *epv = tok->epv; CK_OBJECT_HANDLE object; CK_RV ckrv; if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) { @@ -143,7 +145,7 @@ import_object return CK_INVALID_HANDLE; } nssSession_EnterMonitor(session); - ckrv = CKAPI(tok->slot)->C_CreateObject(session->handle, + ckrv = CKAPI(epv)->C_CreateObject(session->handle, objectTemplate, otsize, &object); nssSession_ExitMonitor(session); @@ -169,21 +171,22 @@ find_object_by_template CK_OBJECT_HANDLE rvObject = CK_INVALID_HANDLE; CK_ULONG count = 0; CK_RV ckrv; + void *epv = tok->epv; nssSession *session; session = (sessionOpt) ? sessionOpt : tok->defaultSession; hSession = session->handle; nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_FindObjectsInit(hSession, cktemplate, ctsize); + ckrv = CKAPI(epv)->C_FindObjectsInit(hSession, cktemplate, ctsize); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); return CK_INVALID_HANDLE; } - ckrv = CKAPI(tok)->C_FindObjects(hSession, &rvObject, 1, &count); + ckrv = CKAPI(epv)->C_FindObjects(hSession, &rvObject, 1, &count); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); return CK_INVALID_HANDLE; } - ckrv = CKAPI(tok)->C_FindObjectsFinal(hSession); + ckrv = CKAPI(epv)->C_FindObjectsFinal(hSession); nssSession_ExitMonitor(session); if (ckrv != CKR_OK) { return CK_INVALID_HANDLE; @@ -215,18 +218,19 @@ traverse_objects_by_template nssSession *session; nssList *objectList = NULL; int objectStackSize = OBJECT_STACK_SIZE; + void *epv = tok->epv; slot = tok->slot; objectStack = startOS; session = (sessionOpt) ? sessionOpt : tok->defaultSession; hSession = session->handle; nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_FindObjectsInit(hSession, obj_template, otsize); + ckrv = CKAPI(epv)->C_FindObjectsInit(hSession, obj_template, otsize); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); goto loser; } while (PR_TRUE) { - ckrv = CKAPI(slot)->C_FindObjects(hSession, objectStack, + ckrv = CKAPI(epv)->C_FindObjects(hSession, objectStack, objectStackSize, &count); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); @@ -250,7 +254,7 @@ traverse_objects_by_template break; } } - ckrv = CKAPI(slot)->C_FindObjectsFinal(hSession); + ckrv = CKAPI(epv)->C_FindObjectsFinal(hSession); nssSession_ExitMonitor(session); if (ckrv != CKR_OK) { goto loser; @@ -1100,3 +1104,31 @@ loser: return (NSSTrust *)NULL; } +NSS_IMPLEMENT PRBool +nssToken_HasCrls +( + NSSToken *tok +) +{ + return !tok->hasNoCrls; +} + +NSS_IMPLEMENT PRStatus +nssToken_SetHasCrls +( + NSSToken *tok +) +{ + tok->hasNoCrls = PR_FALSE; + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRBool +nssToken_IsPresent +( + NSSToken *token +) +{ + return nssSlot_IsTokenPresent(token->slot); +} + diff --git a/mozilla/security/nss/lib/dev/devslot.c b/mozilla/security/nss/lib/dev/devslot.c index f0697a34385..d109e18f8a7 100644 --- a/mozilla/security/nss/lib/dev/devslot.c +++ b/mozilla/security/nss/lib/dev/devslot.c @@ -32,37 +32,65 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: devslot.c,v $ $Revision: 1.2 $ $Date: 2001-12-07 01:35:53 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: devslot.c,v $ $Revision: 1.3 $ $Date: 2002-04-04 20:00:22 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ +#ifndef NSSCKEPV_H +#include "nssckepv.h" +#endif /* NSSCKEPV_H */ #ifndef DEVM_H #include "devm.h" #endif /* DEVM_H */ -#ifdef NSS_3_4_CODE -#include "pkcs11.h" -#else -#ifndef NSSCKEPV_H -#include "nssckepv.h" -#endif /* NSSCKEPV_H */ -#endif /* NSS_3_4_CODE */ - #ifndef CKHELPER_H #include "ckhelper.h" #endif /* CKHELPER_H */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ +/* measured in seconds */ +#define NSSSLOT_TOKEN_DELAY_TIME 10 + +/* this should track global and per-transaction login information */ + +#ifdef PURE_STAN_CODE +typedef enum { + nssSlotAskPasswordTimes_FirstTime = 0, + nssSlotAskPasswordTimes_EveryTime = 1, + nssSlotAskPasswordTimes_Timeout = 2 +} +nssSlotAskPasswordTimes; + +struct nssSlotAuthInfoStr +{ + PRTime lastLogin; + nssSlotAskPasswordTimes askTimes; + PRIntervalTime askPasswordTimeout; +}; + +struct NSSSlotStr +{ + struct nssDeviceBaseStr base; + NSSModule *module; /* Parent */ + NSSToken *token; /* Peer */ + CK_SLOT_ID slotID; + CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */ + struct nssSlotAuthInfoStr authInfo; + PRIntervalTime lastTokenPing; +#ifdef NSS_3_4_CODE + PK11SlotInfo *pk11slot; +#endif +}; +#endif /* PURE_STAN_CODE */ + +#define NSSSLOT_IS_FRIENDLY(slot) \ + (slot->base.flags & NSSSLOT_FLAGS_FRIENDLY) + +/* measured as interval */ +static PRIntervalTime s_token_delay_time = 0; /* The flags needed to open a read-only session. */ static const CK_FLAGS s_ck_readonly_flags = CKF_SERIAL_SESSION; -#ifdef PURE_STAN /* In pk11slot.c, this was a no-op. So it is here also. */ static CK_RV PR_CALLBACK nss_ck_slot_notify @@ -74,56 +102,41 @@ nss_ck_slot_notify { return CKR_OK; } -#endif -/* maybe this should really inherit completely from the module... I dunno, - * any uses of slots where independence is needed? - */ +#ifdef PURE_STAN_BUILD NSS_IMPLEMENT NSSSlot * nssSlot_Create ( - NSSArena *arenaOpt, CK_SLOT_ID slotID, NSSModule *parent ) { NSSArena *arena = NULL; - nssArenaMark *mark = NULL; NSSSlot *rvSlot; NSSToken *token = NULL; NSSUTF8 *slotName = NULL; PRUint32 length; - PRBool newArena; - PRStatus nssrv; CK_SLOT_INFO slotInfo; CK_RV ckrv; - if (arenaOpt) { - arena = arenaOpt; - mark = nssArena_Mark(arena); - if (!mark) { - return (NSSSlot *)NULL; - } - newArena = PR_FALSE; - } else { - arena = NSSArena_Create(); - if(!arena) { - return (NSSSlot *)NULL; - } - newArena = PR_TRUE; + void *epv; + arena = NSSArena_Create(); + if(!arena) { + return (NSSSlot *)NULL; } rvSlot = nss_ZNEW(arena, NSSSlot); if (!rvSlot) { goto loser; } /* Get slot information */ - ckrv = CKAPI(parent)->C_GetSlotInfo(slotID, &slotInfo); + epv = nssModule_GetCryptokiEPV(parent); + ckrv = CKAPI(epv)->C_GetSlotInfo(slotID, &slotInfo); if (ckrv != CKR_OK) { /* set an error here, eh? */ goto loser; } /* Grab the slot description from the PKCS#11 fixed-length buffer */ - length = nssPKCS11StringLength(slotInfo.slotDescription, - sizeof(slotInfo.slotDescription)); + length = nssPKCS11String_Length(slotInfo.slotDescription, + sizeof(slotInfo.slotDescription)); if (length > 0) { slotName = nssUTF8_Create(arena, nssStringType_UTF8String, (void *)slotInfo.slotDescription, length); @@ -131,45 +144,31 @@ nssSlot_Create goto loser; } } - if (!arenaOpt) { - /* Avoid confusion now - only set the slot's arena to a non-NULL value - * if a new arena is created. Otherwise, depend on the caller (having - * passed arenaOpt) to free the arena. - */ - rvSlot->arena = arena; + rvSlot->base.arena = arena; + rvSlot->base.refCount = 1; + rvSlot->base.name = slotName; + rvSlot->base.lock = PZ_NewLock(nssNSSILockOther); /* XXX */ + if (!rvSlot->base.lock) { + goto loser; } - rvSlot->refCount = 1; - rvSlot->epv = parent->epv; - rvSlot->module = parent; - rvSlot->name = slotName; + rvSlot->module = parent; /* refs go from module to slots */ rvSlot->slotID = slotID; rvSlot->ckFlags = slotInfo.flags; /* Initialize the token if present. */ if (slotInfo.flags & CKF_TOKEN_PRESENT) { - token = nssToken_Create(arena, slotID, rvSlot); + token = nssToken_Create(slotID, rvSlot); if (!token) { goto loser; } } rvSlot->token = token; - if (mark) { - nssrv = nssArena_Unmark(arena, mark); - if (nssrv != PR_SUCCESS) { - goto loser; - } - } return rvSlot; loser: - if (newArena) { - nssArena_Destroy(arena); - } else { - if (mark) { - nssArena_Release(arena, mark); - } - } + nssArena_Destroy(arena); /* everything was created in the arena, nothing to see here, move along */ return (NSSSlot *)NULL; } +#endif /* PURE_STAN_BUILD */ NSS_IMPLEMENT PRStatus nssSlot_Destroy @@ -177,46 +176,304 @@ nssSlot_Destroy NSSSlot *slot ) { - if (--slot->refCount == 0) { -#ifndef NSS_3_4_CODE - /* Not going to do this in 3.4, maybe never */ +#ifdef PURE_STAN_BUILD + PR_AtomicDecrement(&slot->base.refCount); + if (slot->base.refCount == 0) { nssToken_Destroy(slot->token); -#endif - if (slot->arena) { - return NSSArena_Destroy(slot->arena); - } else { - nss_ZFreeIf(slot); - } + nssModule_DestroyFromSlot(slot->module, slot); + return nssArena_Destroy(slot->base.arena); } +#endif return PR_SUCCESS; } +NSS_IMPLEMENT void +NSSSlot_Destroy +( + NSSSlot *slot +) +{ + (void)nssSlot_Destroy(slot); +} + NSS_IMPLEMENT NSSSlot * nssSlot_AddRef ( NSSSlot *slot ) { - ++slot->refCount; + PR_AtomicIncrement(&slot->base.refCount); return slot; } NSS_IMPLEMENT NSSUTF8 * nssSlot_GetName ( - NSSSlot *slot, - NSSArena *arenaOpt + NSSSlot *slot ) { - if (slot->name) { - return nssUTF8_Duplicate(slot->name, arenaOpt); + return slot->base.name; +} + +NSS_IMPLEMENT NSSUTF8 * +nssSlot_GetTokenName +( + NSSSlot *slot +) +{ + return nssToken_GetName(slot->token); +} + +static PRBool +within_token_delay_period(NSSSlot *slot) +{ + PRIntervalTime time, lastTime; + /* Set the delay time for checking the token presence */ + if (s_token_delay_time == 0) { + s_token_delay_time = PR_SecondsToInterval(NSSSLOT_TOKEN_DELAY_TIME); } - return (NSSUTF8 *)NULL; + time = PR_IntervalNow(); + lastTime = slot->lastTokenPing; + if ((time > lastTime) && ((time - lastTime) < s_token_delay_time)) { + return PR_TRUE; + } + slot->lastTokenPing = time; + return PR_FALSE; +} + +NSS_IMPLEMENT PRBool +nssSlot_IsTokenPresent +( + NSSSlot *slot +) +{ + CK_RV ckrv; + PRStatus nssrv; + /* XXX */ + nssSession *session; + CK_SLOT_INFO slotInfo; + void *epv; + /* permanent slots are always present */ + if (nssSlot_IsPermanent(slot)) { + return PR_TRUE; + } + /* avoid repeated calls to check token status within set interval */ + if (within_token_delay_period(slot)) { + return (PRBool)((slot->ckFlags & CKF_TOKEN_PRESENT) != 0); + } + /* First obtain the slot info */ +#ifdef PURE_STAN_BUILD + epv = nssModule_GetCryptokiEPV(slot->module); +#else + epv = slot->epv; +#endif + if (!epv) { + return PR_FALSE; + } + ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo); + if (ckrv != CKR_OK) { + slot->token->base.name[0] = 0; /* XXX */ + return PR_FALSE; + } + slot->ckFlags = slotInfo.flags; + /* check for the presence of the token */ + if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) { + if (!slot->token) { + /* token was ne'er present */ + return PR_FALSE; + } + session = nssToken_GetDefaultSession(slot->token); + nssSession_EnterMonitor(session); + /* token is not present */ + if (session->handle != CK_INVALID_SESSION) { + /* session is valid, close and invalidate it */ + CKAPI(epv)->C_CloseSession(session->handle); + session->handle = CK_INVALID_SESSION; + } + nssSession_ExitMonitor(session); + slot->token->base.name[0] = 0; /* XXX */ + return PR_FALSE; +#ifdef PURE_STAN_CODE + } else if (!slot->token) { + /* token was not present at boot time, is now */ + slot->token = nssToken_Create(slot->slotID, slot); + return (slot->token != NULL); +#endif + } + /* token is present, use the session info to determine if the card + * has been removed and reinserted. + */ + session = nssToken_GetDefaultSession(slot->token); + nssSession_EnterMonitor(session); + if (session->handle != CK_INVALID_SESSION) { + CK_SESSION_INFO sessionInfo; + ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo); + if (ckrv != CKR_OK) { + /* session is screwy, close and invalidate it */ + CKAPI(epv)->C_CloseSession(session->handle); + session->handle = CK_INVALID_SESSION; + } + } + nssSession_ExitMonitor(session); + /* token not removed, finished */ + if (session->handle != CK_INVALID_SESSION) { + return PR_TRUE; + } else { + /* token has been removed, need to refresh with new session */ + nssrv = nssSlot_Refresh(slot); + if (nssrv != PR_SUCCESS) { + slot->token->base.name[0] = 0; /* XXX */ + return PR_FALSE; + } + return PR_TRUE; + } +} + +#ifdef PURE_STAN_BUILD +NSS_IMPLEMENT NSSModule * +nssSlot_GetModule +( + NSSSlot *slot +) +{ + return nssModule_AddRef(slot->module); +} +#endif /* PURE_STAN_BUILD */ + +NSS_IMPLEMENT void * +nssSlot_GetCryptokiEPV +( + NSSSlot *slot +) +{ +#ifdef PURE_STAN_BUILD + return nssModule_GetCryptokiEPV(slot->module); +#else + return slot->epv; +#endif +} + +NSS_IMPLEMENT NSSToken * +nssSlot_GetToken +( + NSSSlot *slot +) +{ + if (nssSlot_IsTokenPresent(slot)) { + return nssToken_AddRef(slot->token); + } + return (NSSToken *)NULL; +} + +#ifdef PURE_STAN_BUILD +NSS_IMPLEMENT PRBool +nssSlot_IsPermanent +( + NSSSlot *slot +) +{ + return (!(slot->ckFlags & CKF_REMOVABLE_DEVICE)); +} + +NSS_IMPLEMENT PRBool +nssSlot_IsFriendly +( + NSSSlot *slot +) +{ + return PR_TRUE /* XXX NSSSLOT_IS_FRIENDLY(slot)*/; +} + +NSS_IMPLEMENT PRBool +nssSlot_IsHardware +( + NSSSlot *slot +) +{ + return (slot->ckFlags & CKF_HW_SLOT); +} + +NSS_IMPLEMENT PRStatus +nssSlot_Refresh +( + NSSSlot *slot +) +{ + /* XXX */ +#if 0 + nssToken_Destroy(slot->token); + if (slotInfo.flags & CKF_TOKEN_PRESENT) { + slot->token = nssToken_Create(NULL, slotID, slot); + } +#endif + return PR_SUCCESS; +} + +static PRBool +slot_needs_login +( + NSSSlot *slot, + nssSession *session +) +{ + PRBool needsLogin, logout; + struct nssSlotAuthInfoStr *authInfo = &slot->authInfo; + void *epv = nssModule_GetCryptokiEPV(slot->module); + if (!nssToken_IsLoginRequired(slot->token)) { + return PR_FALSE; + } + if (authInfo->askTimes == nssSlotAskPasswordTimes_EveryTime) { + logout = PR_TRUE; + } else if (authInfo->askTimes == nssSlotAskPasswordTimes_Timeout) { + PRIntervalTime currentTime = PR_IntervalNow(); + if (authInfo->lastLogin - currentTime < authInfo->askPasswordTimeout) { + logout = PR_FALSE; + } else { + logout = PR_TRUE; + } + } else { /* nssSlotAskPasswordTimes_FirstTime */ + logout = PR_FALSE; + } + if (logout) { + /* The login has expired, timeout */ + nssSession_EnterMonitor(session); + CKAPI(epv)->C_Logout(session->handle); + nssSession_ExitMonitor(session); + needsLogin = PR_TRUE; + } else { + CK_RV ckrv; + CK_SESSION_INFO sessionInfo; + nssSession_EnterMonitor(session); + ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo); + nssSession_ExitMonitor(session); + if (ckrv != CKR_OK) { + /* XXX error -- invalidate session */ + return PR_FALSE; + } + switch (sessionInfo.state) { + case CKS_RW_PUBLIC_SESSION: + case CKS_RO_PUBLIC_SESSION: + default: + needsLogin = PR_TRUE; + break; + case CKS_RW_USER_FUNCTIONS: + case CKS_RW_SO_FUNCTIONS: + case CKS_RO_USER_FUNCTIONS: + needsLogin = PR_FALSE; + break; + } + } + return needsLogin; } static PRStatus -nssslot_login(NSSSlot *slot, nssSession *session, - CK_USER_TYPE userType, NSSCallback *pwcb) +slot_login +( + NSSSlot *slot, + nssSession *session, + CK_USER_TYPE userType, + NSSCallback *pwcb +) { PRStatus nssrv; PRUint32 attempts; @@ -224,15 +481,19 @@ nssslot_login(NSSSlot *slot, nssSession *session, NSSUTF8 *password = NULL; CK_ULONG pwLen; CK_RV ckrv; + void *epv; if (!pwcb->getPW) { /* set error INVALID_ARG */ return PR_FAILURE; } + epv = nssModule_GetCryptokiEPV(slot->module); keepTrying = PR_TRUE; nssrv = PR_FAILURE; attempts = 0; while (keepTrying) { - nssrv = pwcb->getPW(slot->name, &attempts, pwcb->arg, &password); + /* use the token name, since it is present */ + NSSUTF8 *tokenName = nssToken_GetName(slot->token); + nssrv = pwcb->getPW(tokenName, attempts, pwcb->arg, &password); if (nssrv != PR_SUCCESS) { nss_SetError(NSS_ERROR_USER_CANCELED); break; @@ -242,8 +503,8 @@ nssslot_login(NSSSlot *slot, nssSession *session, break; } nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_Login(session->handle, userType, - (CK_CHAR_PTR)password, pwLen); + ckrv = CKAPI(epv)->C_Login(session->handle, userType, + (CK_CHAR_PTR)password, pwLen); nssSession_ExitMonitor(session); switch (ckrv) { case CKR_OK: @@ -265,129 +526,130 @@ nssslot_login(NSSSlot *slot, nssSession *session, password = NULL; ++attempts; } - nss_ZFreeIf(password); return nssrv; } static PRStatus -nssslot_init_password(NSSSlot *slot, nssSession *rwSession, NSSCallback *pwcb) +init_slot_password +( + NSSSlot *slot, + nssSession *rwSession, + NSSUTF8 *password +) { - NSSUTF8 *userPW = NULL; - NSSUTF8 *ssoPW = NULL; - PRStatus nssrv; + PRStatus status; + NSSUTF8 *ssoPW = ""; CK_ULONG userPWLen, ssoPWLen; CK_RV ckrv; - if (!pwcb->getInitPW) { - /* set error INVALID_ARG */ - return PR_FAILURE; - } + void *epv = nssModule_GetCryptokiEPV(slot->module); /* Get the SO and user passwords */ - nssrv = pwcb->getInitPW(slot->name, pwcb->arg, &ssoPW, &userPW); - if (nssrv != PR_SUCCESS) goto loser; - userPWLen = (CK_ULONG)nssUTF8_Length(userPW, &nssrv); - if (nssrv != PR_SUCCESS) goto loser; - ssoPWLen = (CK_ULONG)nssUTF8_Length(ssoPW, &nssrv); - if (nssrv != PR_SUCCESS) goto loser; + userPWLen = (CK_ULONG)nssUTF8_Length(password, &status); + if (status != PR_SUCCESS) { + goto loser; + } + ssoPWLen = (CK_ULONG)nssUTF8_Length(ssoPW, &status); + if (status != PR_SUCCESS) { + goto loser; + } /* First log in as SO */ - ckrv = CKAPI(slot)->C_Login(rwSession->handle, CKU_SO, - (CK_CHAR_PTR)ssoPW, ssoPWLen); + ckrv = CKAPI(epv)->C_Login(rwSession->handle, CKU_SO, + (CK_CHAR_PTR)ssoPW, ssoPWLen); if (ckrv != CKR_OK) { /* set error ...SO_LOGIN_FAILED */ goto loser; } /* Now change the user PIN */ - ckrv = CKAPI(slot)->C_InitPIN(rwSession->handle, - (CK_CHAR_PTR)userPW, userPWLen); + ckrv = CKAPI(epv)->C_InitPIN(rwSession->handle, + (CK_CHAR_PTR)password, userPWLen); if (ckrv != CKR_OK) { /* set error */ goto loser; } - nss_ZFreeIf(ssoPW); - nss_ZFreeIf(userPW); return PR_SUCCESS; loser: - nss_ZFreeIf(ssoPW); - nss_ZFreeIf(userPW); return PR_FAILURE; } static PRStatus -nssslot_change_password(NSSSlot *slot, nssSession *rwSession, NSSCallback *pwcb) +change_slot_password +( + NSSSlot *slot, + nssSession *rwSession, + NSSUTF8 *oldPassword, + NSSUTF8 *newPassword +) { - NSSUTF8 *userPW = NULL; - NSSUTF8 *newPW = NULL; - PRUint32 attempts; - PRStatus nssrv; - PRBool keepTrying = PR_TRUE; + PRStatus status; CK_ULONG userPWLen, newPWLen; CK_RV ckrv; - if (!pwcb->getNewPW) { - /* set error INVALID_ARG */ - return PR_FAILURE; + void *epv = nssModule_GetCryptokiEPV(slot->module); + userPWLen = (CK_ULONG)nssUTF8_Length(oldPassword, &status); + if (status != PR_SUCCESS) { + return status; } - attempts = 0; - while (keepTrying) { - nssrv = pwcb->getNewPW(slot->name, &attempts, pwcb->arg, - &userPW, &newPW); - if (nssrv != PR_SUCCESS) { - nss_SetError(NSS_ERROR_USER_CANCELED); - break; - } - userPWLen = (CK_ULONG)nssUTF8_Length(userPW, &nssrv); - if (nssrv != PR_SUCCESS) return nssrv; - newPWLen = (CK_ULONG)nssUTF8_Length(newPW, &nssrv); - if (nssrv != PR_SUCCESS) return nssrv; - nssSession_EnterMonitor(rwSession); - ckrv = CKAPI(slot)->C_SetPIN(rwSession->handle, - (CK_CHAR_PTR)userPW, userPWLen, - (CK_CHAR_PTR)newPW, newPWLen); - nssSession_ExitMonitor(rwSession); - switch (ckrv) { - case CKR_OK: - slot->authInfo.lastLogin = PR_Now(); - nssrv = PR_SUCCESS; - keepTrying = PR_FALSE; - break; - case CKR_PIN_INCORRECT: - nss_SetError(NSS_ERROR_INVALID_PASSWORD); - keepTrying = PR_TRUE; /* received bad pw, keep going */ - break; - default: - nssrv = PR_FAILURE; - keepTrying = PR_FALSE; - break; - } - nss_ZFreeIf(userPW); - nss_ZFreeIf(newPW); - userPW = NULL; - newPW = NULL; - ++attempts; + newPWLen = (CK_ULONG)nssUTF8_Length(newPassword, &status); + if (status != PR_SUCCESS) { + return status; } - nss_ZFreeIf(userPW); - nss_ZFreeIf(newPW); - return nssrv; + nssSession_EnterMonitor(rwSession); + ckrv = CKAPI(epv)->C_SetPIN(rwSession->handle, + (CK_CHAR_PTR)oldPassword, userPWLen, + (CK_CHAR_PTR)newPassword, newPWLen); + nssSession_ExitMonitor(rwSession); + switch (ckrv) { + case CKR_OK: + slot->authInfo.lastLogin = PR_Now(); + status = PR_SUCCESS; + break; + case CKR_PIN_INCORRECT: + nss_SetError(NSS_ERROR_INVALID_PASSWORD); + status = PR_FAILURE; + break; + default: + status = PR_FAILURE; + break; + } + return status; } NSS_IMPLEMENT PRStatus nssSlot_Login ( NSSSlot *slot, - PRBool asSO, NSSCallback *pwcb ) { - PRBool needsLogin, needsInit; - CK_USER_TYPE userType; - userType = (asSO) ? CKU_SO : CKU_USER; - needsInit = PR_FALSE; /* XXX */ - needsLogin = PR_TRUE; /* XXX */ - if (needsInit) { - return nssSlot_SetPassword(slot, pwcb); - } else if (needsLogin) { - return nssslot_login(slot, slot->token->defaultSession, - userType, pwcb); + PRStatus status; + CK_USER_TYPE userType = CKU_USER; + NSSToken *token = nssSlot_GetToken(slot); + nssSession *session; + if (!token) { + return PR_FAILURE; } - return PR_SUCCESS; /* login not required */ + if (!nssToken_IsLoginRequired(token)) { + nssToken_Destroy(token); + return PR_SUCCESS; + } + session = nssToken_GetDefaultSession(slot->token); + if (nssToken_NeedsPINInitialization(token)) { + NSSUTF8 *password = NULL; + if (!pwcb->getInitPW) { + nssToken_Destroy(token); + return PR_FAILURE; /* don't know how to get initial password */ + } + status = (*pwcb->getInitPW)(slot->base.name, pwcb->arg, &password); + if (status == PR_SUCCESS) { + session = nssSlot_CreateSession(slot, NULL, PR_TRUE); + status = init_slot_password(slot, session, password); + nssSession_Destroy(session); + } + } else if (slot_needs_login(slot, session)) { + status = slot_login(slot, session, userType, pwcb); + } else { + status = PR_SUCCESS; + } + nssToken_Destroy(token); + return status; } NSS_IMPLEMENT PRStatus @@ -397,12 +659,15 @@ nssSlot_Logout nssSession *sessionOpt ) { - nssSession *session; PRStatus nssrv = PR_SUCCESS; + nssSession *session; CK_RV ckrv; - session = (sessionOpt) ? sessionOpt : slot->token->defaultSession; + void *epv = nssModule_GetCryptokiEPV(slot->module); + session = sessionOpt ? + sessionOpt : + nssToken_GetDefaultSession(slot->token); nssSession_EnterMonitor(session); - ckrv = CKAPI(slot)->C_Logout(session->handle); + ckrv = CKAPI(epv)->C_Logout(session->handle); nssSession_ExitMonitor(session); if (ckrv != CKR_OK) { /* translate the error */ @@ -411,6 +676,16 @@ nssSlot_Logout return nssrv; } +NSS_IMPLEMENT PRBool +nssSlot_IsLoggedIn +( + NSSSlot *slot +) +{ + nssSession *session = nssToken_GetDefaultSession(slot->token); + return !slot_needs_login(slot, session); +} + NSS_IMPLEMENT void nssSlot_SetPasswordDefaults ( @@ -421,28 +696,36 @@ nssSlot_SetPasswordDefaults slot->authInfo.askPasswordTimeout = askPasswordTimeout; } + NSS_IMPLEMENT PRStatus nssSlot_SetPassword ( NSSSlot *slot, - NSSCallback *pwcb + NSSUTF8 *oldPasswordOpt, + NSSUTF8 *newPassword ) { - PRStatus nssrv; + PRStatus status; nssSession *rwSession; - PRBool needsInit; - needsInit = PR_FALSE; /* XXX */ + NSSToken *token = nssSlot_GetToken(slot); + if (!token) { + return PR_FAILURE; + } rwSession = nssSlot_CreateSession(slot, NULL, PR_TRUE); - if (needsInit) { - nssrv = nssslot_init_password(slot, rwSession, pwcb); + if (nssToken_NeedsPINInitialization(token)) { + status = init_slot_password(slot, rwSession, newPassword); + } else if (oldPasswordOpt) { + status = change_slot_password(slot, rwSession, + oldPasswordOpt, newPassword); } else { - nssrv = nssslot_change_password(slot, rwSession, pwcb); + /* old password must be given in order to change */ + status = PR_FAILURE; } nssSession_Destroy(rwSession); - return nssrv; + nssToken_Destroy(token); + return status; } -#ifdef PURE_STAN NSS_IMPLEMENT nssSession * nssSlot_CreateSession ( @@ -453,18 +736,15 @@ nssSlot_CreateSession { CK_RV ckrv; CK_FLAGS ckflags; - CK_SESSION_HANDLE session; + CK_SESSION_HANDLE handle; + void *epv = nssModule_GetCryptokiEPV(slot->module); nssSession *rvSession; ckflags = s_ck_readonly_flags; if (readWrite) { ckflags |= CKF_RW_SESSION; } - /* does the opening and closing of sessions need to be done in a - * threadsafe manner? should there be a "meta-lock" controlling - * calls like this? - */ - ckrv = CKAPI(slot)->C_OpenSession(slot->slotID, ckflags, - slot, nss_ck_slot_notify, &session); + ckrv = CKAPI(epv)->C_OpenSession(slot->slotID, ckflags, + slot, nss_ck_slot_notify, &handle); if (ckrv != CKR_OK) { /* set an error here, eh? */ return (nssSession *)NULL; @@ -473,7 +753,7 @@ nssSlot_CreateSession if (!rvSession) { return (nssSession *)NULL; } - if (slot->module->flags & NSSMODULE_FLAGS_NOT_THREADSAFE) { + if (!nssModule_IsThreadSafe(slot->module)) { /* If the parent module is not threadsafe, create lock to manage * session within threads. */ @@ -487,7 +767,7 @@ nssSlot_CreateSession return (nssSession *)NULL; } } - rvSession->handle = session; + rvSession->handle = handle; rvSession->slot = slot; rvSession->isRW = readWrite; return rvSession; @@ -501,7 +781,8 @@ nssSession_Destroy { CK_RV ckrv = CKR_OK; if (s) { - ckrv = CKAPI(s->slot)->C_CloseSession(s->handle); + void *epv = s->slot->epv; + ckrv = CKAPI(epv)->C_CloseSession(s->handle); if (s->lock) { PZ_DestroyLock(s->lock); } @@ -509,7 +790,7 @@ nssSession_Destroy } return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; } -#endif +#endif /* PURE_STAN_BUILD */ NSS_IMPLEMENT PRStatus nssSession_EnterMonitor diff --git a/mozilla/security/nss/lib/dev/devt.h b/mozilla/security/nss/lib/dev/devt.h index 99c5ea10b59..c9fe3626c45 100644 --- a/mozilla/security/nss/lib/dev/devt.h +++ b/mozilla/security/nss/lib/dev/devt.h @@ -35,7 +35,7 @@ #define DEVT_H #ifdef DEBUG -static const char DEVT_CVS_ID[] = "@(#) $RCSfile: devt.h,v $ $Revision: 1.13 $ $Date: 2002-03-07 23:21:33 $ $Name: not supported by cvs2svn $"; +static const char DEVT_CVS_ID[] = "@(#) $RCSfile: devt.h,v $ $Revision: 1.14 $ $Date: 2002-04-04 20:00:22 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ /* @@ -72,60 +72,21 @@ PR_BEGIN_EXTERN_C typedef struct nssSessionStr nssSession; -/* The list of boolean flags used to describe properties of a - * module. - */ -#define NSSMODULE_FLAGS_NOT_THREADSAFE 0x0001 /* isThreadSafe */ - -struct NSSModuleStr { - NSSArena *arena; - PRInt32 refCount; - NSSUTF8 *name; - NSSUTF8 *libraryPath; - PRLibrary *library; - void *epv; - NSSSlot **slots; - PRUint32 numSlots; - PRUint32 flags; -}; - -/* The list of boolean flags used to describe properties of a - * slot. - */ -#define NSSSLOT_FLAGS_LOGIN_REQUIRED 0x0001 /* needLogin */ -/*#define NSSSLOT_FLAGS_READONLY 0x0002*/ /* readOnly */ - -/* this should track global and per-transaction login information */ -struct nssSlotAuthInfoStr +/* XXX until NSSTokenStr is moved */ +struct nssDeviceBaseStr { - PRTime lastLogin; - PRInt32 askPasswordTimeout; -}; - -struct NSSSlotStr -{ - NSSArena *arena; - PRInt32 refCount; - NSSModule *module; /* Parent */ - NSSToken *token; /* Child (or peer, if you will) */ - NSSUTF8 *name; - CK_SLOT_ID slotID; - void *epv; - CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */ - PRUint32 flags; - struct nssSlotAuthInfoStr authInfo; - NSSTrustDomain *trustDomain; -#ifdef NSS_3_4_CODE - PK11SlotInfo *pk11slot; -#endif + NSSArena *arena; + PZLock *lock; + PRInt32 refCount; + NSSUTF8 *name; + PRUint32 flags; }; +/* XXX until devobject.c goes away */ struct NSSTokenStr { - NSSArena *arena; - PRInt32 refCount; + struct nssDeviceBaseStr base; NSSSlot *slot; /* Parent (or peer, if you will) */ - NSSUTF8 *name; CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */ PRUint32 flags; void *epv; @@ -141,12 +102,41 @@ struct NSSTokenStr #endif }; +typedef enum { + nssSlotAskPasswordTimes_FirstTime = 0, + nssSlotAskPasswordTimes_EveryTime = 1, + nssSlotAskPasswordTimes_Timeout = 2 +} +nssSlotAskPasswordTimes; + +struct nssSlotAuthInfoStr +{ + PRTime lastLogin; + nssSlotAskPasswordTimes askTimes; + PRIntervalTime askPasswordTimeout; +}; + +struct NSSSlotStr +{ + struct nssDeviceBaseStr base; + NSSModule *module; /* Parent */ + NSSToken *token; /* Peer */ + CK_SLOT_ID slotID; + CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */ + struct nssSlotAuthInfoStr authInfo; + PRIntervalTime lastTokenPing; +#ifdef NSS_3_4_CODE + void *epv; + PK11SlotInfo *pk11slot; +#endif +}; + struct nssSessionStr { - PZLock *lock; - CK_SESSION_HANDLE handle; - NSSSlot *slot; - PRBool isRW; + PZLock *lock; + CK_SESSION_HANDLE handle; + NSSSlot *slot; + PRBool isRW; }; typedef enum { @@ -154,17 +144,14 @@ typedef enum { NSSCertificateType_PKIX = 1 } NSSCertificateType; -#ifdef nodef typedef enum { nssTrustLevel_Unknown = 0, nssTrustLevel_NotTrusted = 1, nssTrustLevel_Trusted = 2, nssTrustLevel_TrustedDelegator = 3, - nssTrustLevel_Valid = 4 + nssTrustLevel_Valid = 4, + nssTrustLevel_ValidDelegator = 5 } nssTrustLevel; -#else -typedef CK_ULONG nssTrustLevel; /* for now */ -#endif typedef struct nssCryptokiInstanceStr nssCryptokiInstance; @@ -176,6 +163,8 @@ struct nssCryptokiInstanceStr NSSUTF8 *label; }; +typedef struct nssCryptokiInstanceStr nssCryptokiObject; + typedef struct nssTokenCertSearchStr nssTokenCertSearch; typedef enum { @@ -195,6 +184,9 @@ struct nssTokenCertSearchStr */ }; +struct nssSlotListStr; +typedef struct nssSlotListStr nssSlotList; + struct NSSAlgorithmAndParametersStr { CK_MECHANISM mechanism; diff --git a/mozilla/security/nss/lib/dev/devtm.h b/mozilla/security/nss/lib/dev/devtm.h new file mode 100644 index 00000000000..3abc2097ee4 --- /dev/null +++ b/mozilla/security/nss/lib/dev/devtm.h @@ -0,0 +1,60 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifndef DEVTM_H +#define DEVTM_H + +#ifdef DEBUG +static const char DEVTM_CVS_ID[] = "@(#) $RCSfile: devtm.h,v $ $Revision: 1.1 $ $Date: 2002-04-04 20:00:22 $ $Name: not supported by cvs2svn $"; +#endif /* DEBUG */ + +/* + * devtm.h + * + * This file contains module-private definitions for the low-level + * cryptoki devices. + */ + +#ifndef DEVT_H +#include "devt.h" +#endif /* DEVT_H */ + +PR_BEGIN_EXTERN_C + +#define MAX_LOCAL_CACHE_OBJECTS 10 + +typedef struct nssTokenObjectCacheStr nssTokenObjectCache; + +PR_END_EXTERN_C + +#endif /* DEVTM_H */ diff --git a/mozilla/security/nss/lib/dev/devtoken.c b/mozilla/security/nss/lib/dev/devtoken.c index c0ce7c3489a..abbb9201cdc 100644 --- a/mozilla/security/nss/lib/dev/devtoken.c +++ b/mozilla/security/nss/lib/dev/devtoken.c @@ -32,77 +32,69 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.10 $ $Date: 2002-03-07 23:21:33 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.11 $ $Date: 2002-04-04 20:00:22 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ -#ifndef DEV_H -#include "dev.h" -#endif /* DEV_H */ - -#ifndef DEVM_H -#include "devm.h" -#endif /* DEVM_H */ - #ifndef NSSCKEPV_H #include "nssckepv.h" #endif /* NSSCKEPV_H */ +#ifndef DEVM_H +#include "devm.h" +#endif /* DEVM_H */ + #ifndef CKHELPER_H #include "ckhelper.h" #endif /* CKHELPER_H */ -#ifndef BASE_H -#include "base.h" -#endif /* BASE_H */ +#ifdef NSS_3_4_CODE +#endif + +/* The number of object handles to grab during each call to C_FindObjects */ +#define OBJECT_STACK_SIZE 16 + +#ifdef PURE_STAN_BUILD +struct NSSTokenStr +{ + struct nssDeviceBaseStr base; + NSSSlot *slot; /* Peer */ + CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */ + nssSession *defaultSession; + nssTokenObjectCache *cache; +}; -/* maybe this should really inherit completely from the module... I dunno, - * any uses of slots where independence is needed? - */ NSS_IMPLEMENT NSSToken * nssToken_Create ( - NSSArena *arenaOpt, CK_SLOT_ID slotID, - NSSSlot *parent + NSSSlot *peer ) { NSSArena *arena; - nssArenaMark *mark = NULL; NSSToken *rvToken; nssSession *session = NULL; NSSUTF8 *tokenName = NULL; PRUint32 length; - PRBool newArena; PRBool readWrite; - PRStatus nssrv; CK_TOKEN_INFO tokenInfo; CK_RV ckrv; - if (arenaOpt) { - arena = arenaOpt; - mark = nssArena_Mark(arena); - if (!mark) { - return (NSSToken *)NULL; - } - newArena = PR_FALSE; - } else { - arena = NSSArena_Create(); - if(!arena) { - return (NSSToken *)NULL; - } - newArena = PR_TRUE; + void *epv = nssSlot_GetCryptokiEPV(peer); + arena = NSSArena_Create(); + if(!arena) { + return (NSSToken *)NULL; } rvToken = nss_ZNEW(arena, NSSToken); if (!rvToken) { goto loser; } /* Get token information */ - ckrv = CKAPI(parent)->C_GetTokenInfo(slotID, &tokenInfo); + ckrv = CKAPI(epv)->C_GetTokenInfo(slotID, &tokenInfo); if (ckrv != CKR_OK) { /* set an error here, eh? */ goto loser; } /* Grab the slot description from the PKCS#11 fixed-length buffer */ - length = nssPKCS11StringLength(tokenInfo.label, sizeof(tokenInfo.label)); + length = nssPKCS11String_Length(tokenInfo.label, sizeof(tokenInfo.label)); if (length > 0) { tokenName = nssUTF8_Create(arena, nssStringType_UTF8String, (void *)tokenInfo.label, length); @@ -117,28 +109,26 @@ nssToken_Create } else { readWrite = PR_FALSE; } - session = nssSlot_CreateSession(parent, arena, readWrite); + session = nssSlot_CreateSession(peer, arena, readWrite); if (session == NULL) { goto loser; } /* TODO: seed the RNG here */ - if (!arenaOpt) { - /* Avoid confusion now - only set the token's arena to a non-NULL value - * if a new arena is created. Otherwise, depend on the caller (having - * passed arenaOpt) to free the arena. - */ - rvToken->arena = arena; + rvToken->base.arena = arena; + rvToken->base.refCount = 1; + rvToken->base.name = tokenName; + rvToken->base.lock = PZ_NewLock(nssNSSILockOther); /* XXX */ + if (!rvToken->base.lock) { + goto loser; } - rvToken->refCount = 1; - rvToken->slot = parent; - rvToken->name = tokenName; + rvToken->slot = peer; /* slot owns ref to token */ rvToken->ckFlags = tokenInfo.flags; rvToken->defaultSession = session; - rvToken->hasNoTrust = PR_FALSE; - rvToken->hasNoCrls = PR_FALSE; - if (mark) { - nssrv = nssArena_Unmark(arena, mark); - if (nssrv != PR_SUCCESS) { + if (nssSlot_IsHardware(peer)) { + rvToken->cache = nssTokenObjectCache_Create(rvToken, + PR_TRUE, PR_TRUE, PR_TRUE); + if (!rvToken->cache) { + nssSlot_Destroy(peer); goto loser; } } @@ -147,15 +137,10 @@ loser: if (session) { nssSession_Destroy(session); } - if (newArena) { - nssArena_Destroy(arena); - } else { - if (mark) { - nssArena_Release(arena, mark); - } - } + nssArena_Destroy(arena); return (NSSToken *)NULL; } +#endif /* PURE_STAN_BUILD */ NSS_IMPLEMENT PRStatus nssToken_Destroy @@ -163,142 +148,1068 @@ nssToken_Destroy NSSToken *tok ) { - if (--tok->refCount == 0) { -#ifndef NSS_3_4_CODE - /* don't do this in 3.4 -- let PK11SlotInfo handle it */ - if (tok->defaultSession) { - nssSession_Destroy(tok->defaultSession); - } - if (tok->arena) { - return NSSArena_Destroy(tok->arena); - } else { - nss_ZFreeIf(tok); - } -#else - nss_ZFreeIf(tok); -#endif +#ifdef PURE_STAN_BUILD + PR_AtomicDecrement(&tok->base.refCount); + if (tok->base.refCount == 0) { + nssTokenObjectCache_Destroy(tok->cache); + return nssArena_Destroy(tok->base.arena); } +#endif return PR_SUCCESS; } +NSS_IMPLEMENT void +NSSToken_Destroy +( + NSSToken *tok +) +{ + (void)nssToken_Destroy(tok); +} + NSS_IMPLEMENT NSSToken * nssToken_AddRef ( NSSToken *tok ) { - ++tok->refCount; + PR_AtomicIncrement(&tok->base.refCount); return tok; } +NSS_IMPLEMENT NSSSlot * +nssToken_GetSlot +( + NSSToken *tok +) +{ + return nssSlot_AddRef(tok->slot); +} + +#ifdef PURE_STAN_BUILD +NSS_IMPLEMENT NSSModule * +nssToken_GetModule +( + NSSToken *token +) +{ + return nssSlot_GetModule(token->slot); +} +#endif + +NSS_IMPLEMENT void * +nssToken_GetCryptokiEPV +( + NSSToken *token +) +{ + return nssSlot_GetCryptokiEPV(token->slot); +} + +NSS_IMPLEMENT nssSession * +nssToken_GetDefaultSession +( + NSSToken *token +) +{ + return token->defaultSession; +} + NSS_IMPLEMENT NSSUTF8 * nssToken_GetName ( NSSToken *tok ) { - if (tok->name[0] == 0) { - (void) nssToken_IsPresent(tok); + if (tok->base.name[0] == 0) { + (void) nssSlot_IsTokenPresent(tok->slot); } - return tok->name; + return tok->base.name; } -NSS_IMPLEMENT PRBool -nssToken_IsPresent +NSS_IMPLEMENT NSSUTF8 * +NSSToken_GetName ( NSSToken *token ) { - CK_RV ckrv; - PRStatus nssrv; - nssSession *session; - CK_SLOT_INFO slotInfo; - NSSSlot *slot = token->slot; - PRIntervalTime time,lastTime; - static PRIntervalTime delayTime = 0; - - session = token->defaultSession; - /* permanent slots are always present */ - if (nssSlot_IsPermanent(slot) && session != CK_INVALID_SESSION) { - return PR_TRUE; - } - - if (delayTime == 0) { - delayTime = PR_SecondsToInterval(10); - } - - time = PR_IntervalNow(); - lastTime = token->lastTime; - if ((time > lastTime) && ((time - lastTime) < delayTime)) { - return (PRBool) ((slot->ckFlags & CKF_TOKEN_PRESENT) != 0); - } - token->lastTime = time; - nssSession_EnterMonitor(session); - /* First obtain the slot info */ - ckrv = CKAPI(slot)->C_GetSlotInfo(slot->slotID, &slotInfo); - if (ckrv != CKR_OK) { - nssSession_ExitMonitor(session); - token->name[0] = 0; - return PR_FALSE; - } - slot->ckFlags = slotInfo.flags; - /* check for the presence of the token */ - if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) { - /* token is not present */ - if (session->handle != CK_INVALID_SESSION) { - /* session is valid, close and invalidate it */ - CKAPI(slot)->C_CloseSession(session->handle); - session->handle = CK_INVALID_SESSION; - } - nssSession_ExitMonitor(session); - token->name[0] = 0; - return PR_FALSE; - } - /* token is present, use the session info to determine if the card - * has been removed and reinserted. - */ - if (session != CK_INVALID_SESSION) { - CK_SESSION_INFO sessionInfo; - ckrv = CKAPI(slot)->C_GetSessionInfo(session->handle, &sessionInfo); - if (ckrv != CKR_OK) { - /* session is screwy, close and invalidate it */ - CKAPI(slot)->C_CloseSession(session->handle); - session->handle = CK_INVALID_SESSION; - } - } - nssSession_ExitMonitor(session); - /* token not removed, finished */ - if (session->handle != CK_INVALID_SESSION) { - return PR_TRUE; - } else { - /* token has been removed, need to refresh with new session */ - nssrv = nssSlot_Refresh(slot); - if (nssrv != PR_SUCCESS) { - token->name[0] = 0; - return PR_FALSE; - } - return PR_TRUE; - } + return nssToken_GetName(token); } NSS_IMPLEMENT PRBool -nssToken_HasCrls +nssToken_IsLoginRequired ( - NSSToken *tok + NSSToken *token ) { - return !tok->hasNoCrls; + return (token->ckFlags & CKF_LOGIN_REQUIRED); +} + +NSS_IMPLEMENT PRBool +nssToken_NeedsPINInitialization +( + NSSToken *token +) +{ + return (!(token->ckFlags & CKF_USER_PIN_INITIALIZED)); +} + +#ifdef PURE_STAN_BUILD +NSS_IMPLEMENT PRStatus +nssToken_DeleteStoredObject +( + nssCryptokiObject *instance +) +{ + CK_RV ckrv; + PRStatus status; + PRBool createdSession = PR_FALSE; + NSSToken *token = instance->token; + nssSession *session = NULL; + void *epv = nssToken_GetCryptokiEPV(instance->token); + if (token->cache) { + status = nssTokenObjectCache_RemoveObject(token->cache, instance); + } + if (instance->isTokenObject) { + if (nssSession_IsReadWrite(token->defaultSession)) { + session = token->defaultSession; + } else { + session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE); + createdSession = PR_TRUE; + } + } + if (session == NULL) { + return PR_FAILURE; + } + nssSession_EnterMonitor(session); + ckrv = CKAPI(epv)->C_DestroyObject(session->handle, instance->handle); + nssSession_ExitMonitor(session); + if (createdSession) { + nssSession_Destroy(session); + } + if (ckrv != CKR_OK) { + return PR_FAILURE; + } + return status; +} + +static nssCryptokiObject * +import_object +( + NSSToken *tok, + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR objectTemplate, + CK_ULONG otsize +) +{ + nssSession *session = NULL; + PRBool createdSession = PR_FALSE; + CK_OBJECT_HANDLE handle; + CK_RV ckrv; + void *epv = nssToken_GetCryptokiEPV(tok); + if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) { + if (sessionOpt) { + if (!nssSession_IsReadWrite(sessionOpt)) { + return CK_INVALID_HANDLE; + } else { + session = sessionOpt; + } + } else if (nssSession_IsReadWrite(tok->defaultSession)) { + session = tok->defaultSession; + } else { + session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE); + createdSession = PR_TRUE; + } + } else { + session = (sessionOpt) ? sessionOpt : tok->defaultSession; + } + if (session == NULL) { + return CK_INVALID_HANDLE; + } + nssSession_EnterMonitor(session); + ckrv = CKAPI(epv)->C_CreateObject(session->handle, + objectTemplate, otsize, + &handle); + nssSession_ExitMonitor(session); + if (createdSession) { + nssSession_Destroy(session); + } + if (ckrv != CKR_OK) { + return CK_INVALID_HANDLE; + } + return nssCryptokiObject_Create(tok, session, handle); +} + +static nssCryptokiObject ** +create_objects_from_handles +( + NSSToken *tok, + nssSession *session, + CK_OBJECT_HANDLE *handles, + PRUint32 numH +) +{ + nssCryptokiObject **objects; + objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numH + 1); + if (objects) { + PRInt32 i; + for (i=0; i0; --i) { + nssCryptokiObject_Destroy(objects[i]); + } + return (nssCryptokiObject **)NULL; + } + } + } + return objects; +} + +static nssCryptokiObject ** +find_objects +( + NSSToken *tok, + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR obj_template, + CK_ULONG otsize, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_RV ckrv; + CK_ULONG count; + CK_OBJECT_HANDLE *objectHandles; + PRUint32 arraySize, numHandles; + void *epv = nssToken_GetCryptokiEPV(tok); + nssCryptokiObject **objects; + NSSArena *arena; + nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession; + /* the arena is only for the array of object handles */ + arena = nssArena_Create(); + if (!arena) { + if (statusOpt) *statusOpt = PR_FAILURE; + return (nssCryptokiObject **)NULL; + } + if (maximumOpt > 0) { + arraySize = maximumOpt; + } else { + arraySize = OBJECT_STACK_SIZE; + } + numHandles = 0; + objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize); + if (!objectHandles) { + goto loser; + } + nssSession_EnterMonitor(session); /* ==== session lock === */ + /* Initialize the find with the template */ + ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, + obj_template, otsize); + if (ckrv != CKR_OK) { + nssSession_ExitMonitor(session); + goto loser; + } + while (PR_TRUE) { + /* Issue the find for up to arraySize - numHandles objects */ + ckrv = CKAPI(epv)->C_FindObjects(session->handle, + objectHandles + numHandles, + arraySize - numHandles, + &count); + if (ckrv != CKR_OK) { + nssSession_ExitMonitor(session); + goto loser; + } + /* bump the number of found objects */ + numHandles += count; + if (maximumOpt == 0 || numHandles < arraySize) { + /* either reached maximum, or no more objects to get */ + break; + } + /* the array is filled, double it and continue */ + arraySize *= 2; + objectHandles = nss_ZREALLOCARRAY(objectHandles, + CK_OBJECT_HANDLE, + arraySize); + if (!objectHandles) { + nssSession_ExitMonitor(session); + goto loser; + } + } + ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle); + nssSession_ExitMonitor(session); /* ==== end session lock === */ + if (ckrv != CKR_OK) { + goto loser; + } + if (numHandles > 0) { + objects = create_objects_from_handles(tok, session, + objectHandles, numHandles); + } else { + objects = NULL; + } + nssArena_Destroy(arena); + if (statusOpt) *statusOpt = PR_SUCCESS; + return objects; +loser: + nssArena_Destroy(arena); + if (statusOpt) *statusOpt = PR_FAILURE; + return (nssCryptokiObject **)NULL; +} + +static nssCryptokiObject ** +find_objects_by_template +( + NSSToken *token, + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR obj_template, + CK_ULONG otsize, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_OBJECT_CLASS objclass; + nssCryptokiObject **objects = NULL; + PRUint32 i; + for (i=0; icache && + nssTokenObjectCache_HaveObjectClass(token->cache, objclass)) + { + objects = nssTokenObjectCache_FindObjectsByTemplate(token->cache, + objclass, + obj_template, + otsize, + maximumOpt); + if (statusOpt) *statusOpt = PR_SUCCESS; + } + /* Either they are not cached, or cache failed; look on token. */ + if (!objects) { + objects = find_objects(token, sessionOpt, + obj_template, otsize, + maximumOpt, statusOpt); + } + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_ImportCertificate +( + NSSToken *tok, + nssSession *sessionOpt, + NSSCertificateType certType, + NSSItem *id, + NSSUTF8 *nickname, + NSSDER *encoding, + NSSDER *issuer, + NSSDER *subject, + NSSDER *serial, + PRBool asTokenObject +) +{ + CK_CERTIFICATE_TYPE cert_type; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_tmpl[9]; + CK_ULONG ctsize; + nssCryptokiObject *rvObject = NULL; + if (certType == NSSCertificateType_PKIX) { + cert_type = CKC_X_509; + } else { + return (nssCryptokiObject *)NULL; + } + NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize); + if (asTokenObject) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } else { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CERTIFICATE_TYPE, cert_type); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); + NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize); + /* Import the certificate onto the token */ + rvObject = import_object(tok, sessionOpt, cert_tmpl, ctsize); + if (rvObject && tok->cache) { + nssTokenObjectCache_ImportObject(tok->cache, rvObject, + CKO_CERTIFICATE, + cert_tmpl, ctsize); + } + return rvObject; +} + +/* traverse all certificates - this should only happen if the token + * has been marked as "traversable" + */ +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificates +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_template[2]; + CK_ULONG ctsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly || + searchType == nssTokenSearchType_TokenForced) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); + + if (searchType == nssTokenSearchType_TokenForced) { + objects = find_objects(token, sessionOpt, + cert_template, ctsize, + maximumOpt, statusOpt); + } else { + objects = find_objects_by_template(token, sessionOpt, + cert_template, ctsize, + maximumOpt, statusOpt); + } + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificatesBySubject +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *subject, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE subj_template[3]; + CK_ULONG stsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(subj_template, attr, stsize); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); + NSS_CK_TEMPLATE_FINISH(subj_template, attr, stsize); + /* now locate the token certs matching this template */ + objects = find_objects_by_template(token, sessionOpt, + subj_template, stsize, + maximumOpt, statusOpt); + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificatesByNickname +( + NSSToken *token, + nssSession *sessionOpt, + NSSUTF8 *name, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE nick_template[3]; + CK_ULONG ntsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(nick_template, attr, ntsize); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, name); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_TEMPLATE_FINISH(nick_template, attr, ntsize); + /* now locate the token certs matching this template */ + objects = find_objects_by_template(token, sessionOpt, + nick_template, ntsize, + maximumOpt, statusOpt); + if (!objects) { + /* This is to workaround the fact that PKCS#11 doesn't specify + * whether the '\0' should be included. XXX Is that still true? + * im - this is not needed by the current softoken. However, I'm + * leaving it in until I have surveyed more tokens to see if it needed. + * well, its needed by the builtin token... + */ + nick_template[0].ulValueLen++; + objects = find_objects_by_template(token, sessionOpt, + nick_template, ntsize, + maximumOpt, statusOpt); + } + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificatesByEmail +( + NSSToken *token, + nssSession *sessionOpt, + NSSASCII7 *email, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE email_template[3]; + CK_ULONG etsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(email_template, attr, etsize); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NETSCAPE_EMAIL, email); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_TEMPLATE_FINISH(email_template, attr, etsize); + /* now locate the token certs matching this template */ + objects = find_objects_by_template(token, sessionOpt, + email_template, etsize, + maximumOpt, statusOpt); + if (!objects) { + /* This is to workaround the fact that PKCS#11 doesn't specify + * whether the '\0' should be included. XXX Is that still true? + * im - this is not needed by the current softoken. However, I'm + * leaving it in until I have surveyed more tokens to see if it needed. + * well, its needed by the builtin token... + */ + email_template[0].ulValueLen++; + objects = find_objects_by_template(token, sessionOpt, + email_template, etsize, + maximumOpt, statusOpt); + } + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCertificatesByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *id, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE id_template[3]; + CK_ULONG idtsize; + nssCryptokiObject **objects; + NSS_CK_TEMPLATE_START(id_template, attr, idtsize); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_TEMPLATE_FINISH(id_template, attr, idtsize); + /* now locate the token certs matching this template */ + objects = find_objects_by_template(token, sessionOpt, + id_template, idtsize, + maximumOpt, statusOpt); + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindCertificateByIssuerAndSerialNumber +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *issuer, + NSSDER *serial, + nssTokenSearchType searchType, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_template[4]; + CK_ULONG ctsize; + nssCryptokiObject **objects; + nssCryptokiObject *rvObject = NULL; + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + /* Set the unique id */ + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, issuer); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, serial); + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); + /* get the object handle */ + objects = find_objects_by_template(token, sessionOpt, + cert_template, ctsize, + 1, statusOpt); + if (objects) { + rvObject = objects[0]; + nss_ZFreeIf(objects); + } + return rvObject; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindCertificateByEncodedCertificate +( + NSSToken *token, + nssSession *sessionOpt, + NSSBER *encodedCertificate, + nssTokenSearchType searchType, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE cert_template[3]; + CK_ULONG ctsize; + nssCryptokiObject **objects; + nssCryptokiObject *rvObject = NULL; + NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); + /* Set the search to token/session only if provided */ + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encodedCertificate); + NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); + /* get the object handle */ + objects = find_objects_by_template(token, sessionOpt, + cert_template, ctsize, + 1, statusOpt); + if (objects) { + rvObject = objects[0]; + nss_ZFreeIf(objects); + } + return rvObject; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindPrivateKeys +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[2]; + CK_ULONG ktsize; + nssCryptokiObject **objects; + + NSS_CK_TEMPLATE_START(key_template, attr, ktsize); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); + + objects = find_objects_by_template(token, sessionOpt, + key_template, ktsize, + maximumOpt, statusOpt); + return objects; +} + +/* XXX ?there are no session cert objects, so only search token objects */ +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindPrivateKeyByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *keyID +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[3]; + CK_ULONG ktsize; + nssCryptokiObject **objects; + nssCryptokiObject *rvKey = NULL; + + NSS_CK_TEMPLATE_START(key_template, attr, ktsize); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); + NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); + + objects = find_objects_by_template(token, sessionOpt, + key_template, ktsize, + 1, NULL); + if (objects) { + rvKey = objects[0]; + nss_ZFreeIf(objects); + } + return rvKey; +} + +/* XXX ?there are no session cert objects, so only search token objects */ +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindPublicKeyByID +( + NSSToken *token, + nssSession *sessionOpt, + NSSItem *keyID +) +{ + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE key_template[3]; + CK_ULONG ktsize; + nssCryptokiObject **objects; + nssCryptokiObject *rvKey = NULL; + + NSS_CK_TEMPLATE_START(key_template, attr, ktsize); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_pubkey); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID); + NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize); + + objects = find_objects_by_template(token, sessionOpt, + key_template, ktsize, + 1, NULL); + if (objects) { + rvKey = objects[0]; + nss_ZFreeIf(objects); + } + return rvKey; +} + +static void +sha1_hash(NSSItem *input, NSSItem *output) +{ + NSSAlgorithmAndParameters *ap; + NSSToken *token = nss_GetDefaultCryptoToken(); + ap = NSSAlgorithmAndParameters_CreateSHA1Digest(NULL); + (void)nssToken_Digest(token, NULL, ap, input, output, NULL); +#ifdef NSS_3_4_CODE + PK11_FreeSlot(token->pk11slot); +#endif + nss_ZFreeIf(ap); +} + +static void +md5_hash(NSSItem *input, NSSItem *output) +{ + NSSAlgorithmAndParameters *ap; + NSSToken *token = nss_GetDefaultCryptoToken(); + ap = NSSAlgorithmAndParameters_CreateMD5Digest(NULL); + (void)nssToken_Digest(token, NULL, ap, input, output, NULL); +#ifdef NSS_3_4_CODE + PK11_FreeSlot(token->pk11slot); +#endif + nss_ZFreeIf(ap); +} + +static CK_TRUST +get_ck_trust +( + nssTrustLevel nssTrust +) +{ + CK_TRUST t; + switch (nssTrust) { + case nssTrustLevel_Unknown: t = CKT_NETSCAPE_TRUST_UNKNOWN; break; + case nssTrustLevel_NotTrusted: t = CKT_NETSCAPE_UNTRUSTED; break; + case nssTrustLevel_TrustedDelegator: t = CKT_NETSCAPE_TRUSTED_DELEGATOR; + break; + case nssTrustLevel_ValidDelegator: t = CKT_NETSCAPE_VALID_DELEGATOR; break; + case nssTrustLevel_Trusted: t = CKT_NETSCAPE_TRUSTED; break; + case nssTrustLevel_Valid: t = CKT_NETSCAPE_VALID; break; + } + return t; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_ImportTrust +( + NSSToken *tok, + nssSession *sessionOpt, + NSSDER *certEncoding, + NSSDER *certIssuer, + NSSDER *certSerial, + nssTrustLevel serverAuth, + nssTrustLevel clientAuth, + nssTrustLevel codeSigning, + nssTrustLevel emailProtection, + PRBool asTokenObject +) +{ + nssCryptokiObject *object; + CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; + CK_TRUST ckSA, ckCA, ckCS, ckEP; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE trust_tmpl[10]; + CK_ULONG tsize; + PRUint8 sha1[20]; /* this is cheating... */ + PRUint8 md5[16]; + NSSItem sha1_result, md5_result; + sha1_result.data = sha1; sha1_result.size = sizeof sha1; + md5_result.data = md5; md5_result.size = sizeof md5; + sha1_hash(certEncoding, &sha1_result); + md5_hash(certEncoding, &md5_result); + ckSA = get_ck_trust(serverAuth); + ckCA = get_ck_trust(clientAuth); + ckCS = get_ck_trust(codeSigning); + ckEP = get_ck_trust(emailProtection); + NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize); + if (asTokenObject) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } else { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER, certSerial); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_MD5_HASH, &md5_result); + /* now set the trust values */ + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, ckSA); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, ckCA); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, ckCS); + NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, ckEP); + NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize); + /* import the trust object onto the token */ + object = import_object(tok, sessionOpt, trust_tmpl, tsize); + if (object && tok->cache) { + nssTokenObjectCache_ImportObject(tok->cache, object, + CKO_CERTIFICATE, + trust_tmpl, tsize); + } + /* XXX + if (object) { + tok->hasNoTrust = PR_FALSE; + } + */ + return object; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindTrustObjects +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE tobj_template[2]; + CK_ULONG tobj_size; + nssCryptokiObject **objects; + nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; + + NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly || + searchType == nssTokenSearchType_TokenForced) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); + NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); + + if (searchType == nssTokenSearchType_TokenForced) { + objects = find_objects(token, session, + tobj_template, tobj_size, + maximumOpt, statusOpt); + } else { + objects = find_objects_by_template(token, session, + tobj_template, tobj_size, + maximumOpt, statusOpt); + } + return objects; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_FindTrustForCertificate +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *certEncoding, + NSSDER *certIssuer, + NSSDER *certSerial, + nssTokenSearchType searchType +) +{ + CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE tobj_template[5]; + CK_ULONG tobj_size; + PRUint8 sha1[20]; /* this is cheating... */ + NSSItem sha1_result; + nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; + nssCryptokiObject *object, **objects; + + sha1_result.data = sha1; sha1_result.size = sizeof sha1; + sha1_hash(certEncoding, &sha1_result); + NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result); +#ifdef NSS_3_4_CODE + if (!PK11_HasRootCerts(token->pk11slot)) { +#endif + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , certSerial); +#ifdef NSS_3_4_CODE + } + /* + * we need to arrange for the built-in token to lose the bottom 2 + * attributes so that old built-in tokens will continue to work. + */ +#endif + NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size); + object = NULL; + objects = find_objects_by_template(token, session, + tobj_template, tobj_size, + 1, NULL); + if (objects) { + object = objects[0]; + nss_ZFreeIf(objects); + } + return object; +} + +NSS_IMPLEMENT nssCryptokiObject * +nssToken_ImportCRL +( + NSSToken *token, + nssSession *sessionOpt, + NSSDER *subject, + NSSDER *encoding, + PRBool isKRL, + NSSUTF8 *url, + PRBool asTokenObject +) +{ + nssCryptokiObject *object; + CK_OBJECT_CLASS crlobjc = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE crl_tmpl[6]; + CK_ULONG crlsize; + + NSS_CK_TEMPLATE_START(crl_tmpl, attr, crlsize); + if (asTokenObject) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } else { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject); + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encoding); + NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NETSCAPE_URL, url); + if (isKRL) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NETSCAPE_KRL, &g_ck_true); + } else { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NETSCAPE_KRL, &g_ck_false); + } + NSS_CK_TEMPLATE_FINISH(crl_tmpl, attr, crlsize); + + /* import the crl object onto the token */ + object = import_object(token, sessionOpt, crl_tmpl, crlsize); + if (object && token->cache) { + nssTokenObjectCache_ImportObject(token->cache, object, + CKO_CERTIFICATE, + crl_tmpl, crlsize); + } + return object; +} + +NSS_IMPLEMENT nssCryptokiObject ** +nssToken_FindCRLs +( + NSSToken *token, + nssSession *sessionOpt, + nssTokenSearchType searchType, + PRUint32 maximumOpt, + PRStatus *statusOpt +) +{ + CK_OBJECT_CLASS crlobjc = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE_PTR attr; + CK_ATTRIBUTE crlobj_template[2]; + CK_ULONG crlobj_size; + nssCryptokiObject **objects; + nssSession *session = sessionOpt ? sessionOpt : token->defaultSession; + + NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size); + if (searchType == nssTokenSearchType_SessionOnly) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); + } else if (searchType == nssTokenSearchType_TokenOnly || + searchType == nssTokenSearchType_TokenForced) { + NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); + } + NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc); + NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size); + + if (searchType == nssTokenSearchType_TokenForced) { + objects = find_objects(token, session, + crlobj_template, crlobj_size, + maximumOpt, statusOpt); + } else { + objects = find_objects_by_template(token, session, + crlobj_template, crlobj_size, + maximumOpt, statusOpt); + } + return objects; } NSS_IMPLEMENT PRStatus -nssToken_SetHasCrls +nssToken_GetCachedObjectAttributes ( - NSSToken *tok + NSSToken *token, + NSSArena *arenaOpt, + nssCryptokiObject *object, + CK_OBJECT_CLASS objclass, + CK_ATTRIBUTE_PTR atemplate, + CK_ULONG atlen ) { - tok->hasNoCrls = PR_FALSE; - return PR_SUCCESS; + if (!token->cache) { + return PR_FAILURE; + } + return nssTokenObjectCache_GetObjectAttributes(token->cache, arenaOpt, + object, objclass, + atemplate, atlen); } +#endif /* PURE_STAN_BUILD */ NSS_IMPLEMENT NSSItem * nssToken_Digest @@ -315,17 +1226,18 @@ nssToken_Digest CK_ULONG digestLen; CK_BYTE_PTR digest; NSSItem *rvItem = NULL; + void *epv = nssToken_GetCryptokiEPV(tok); nssSession *session; session = (sessionOpt) ? sessionOpt : tok->defaultSession; nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_DigestInit(session->handle, &ap->mechanism); + ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); return NULL; } #if 0 /* XXX the standard says this should work, but it doesn't */ - ckrv = CKAPI(tok)->C_Digest(session->handle, NULL, 0, NULL, &digestLen); + ckrv = CKAPI(epv)->C_Digest(session->handle, NULL, 0, NULL, &digestLen); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); return NULL; @@ -351,7 +1263,7 @@ nssToken_Digest return NULL; } } - ckrv = CKAPI(tok)->C_Digest(session->handle, + ckrv = CKAPI(epv)->C_Digest(session->handle, (CK_BYTE_PTR)data->data, (CK_ULONG)data->size, (CK_BYTE_PTR)digest, @@ -377,9 +1289,10 @@ nssToken_BeginDigest { CK_RV ckrv; nssSession *session; + void *epv = nssToken_GetCryptokiEPV(tok); session = (sessionOpt) ? sessionOpt : tok->defaultSession; nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_DigestInit(session->handle, &ap->mechanism); + ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism); nssSession_ExitMonitor(session); return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE; } @@ -394,9 +1307,10 @@ nssToken_ContinueDigest { CK_RV ckrv; nssSession *session; + void *epv = nssToken_GetCryptokiEPV(tok); session = (sessionOpt) ? sessionOpt : tok->defaultSession; nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_DigestUpdate(session->handle, + ckrv = CKAPI(epv)->C_DigestUpdate(session->handle, (CK_BYTE_PTR)item->data, (CK_ULONG)item->size); nssSession_ExitMonitor(session); @@ -416,10 +1330,11 @@ nssToken_FinishDigest CK_ULONG digestLen; CK_BYTE_PTR digest; NSSItem *rvItem = NULL; + void *epv = nssToken_GetCryptokiEPV(tok); nssSession *session; session = (sessionOpt) ? sessionOpt : tok->defaultSession; nssSession_EnterMonitor(session); - ckrv = CKAPI(tok)->C_DigestFinal(session->handle, NULL, &digestLen); + ckrv = CKAPI(epv)->C_DigestFinal(session->handle, NULL, &digestLen); if (ckrv != CKR_OK || digestLen == 0) { nssSession_ExitMonitor(session); return NULL; @@ -443,7 +1358,7 @@ nssToken_FinishDigest return NULL; } } - ckrv = CKAPI(tok)->C_DigestFinal(session->handle, digest, &digestLen); + ckrv = CKAPI(epv)->C_DigestFinal(session->handle, digest, &digestLen); nssSession_ExitMonitor(session); if (ckrv != CKR_OK) { nss_ZFreeIf(digest); @@ -455,36 +1370,3 @@ nssToken_FinishDigest return rvItem; } -/* XXX of course this doesn't belong here */ -NSS_IMPLEMENT NSSAlgorithmAndParameters * -NSSAlgorithmAndParameters_CreateSHA1Digest -( - NSSArena *arenaOpt -) -{ - NSSAlgorithmAndParameters *rvAP = NULL; - rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters); - if (rvAP) { - rvAP->mechanism.mechanism = CKM_SHA_1; - rvAP->mechanism.pParameter = NULL; - rvAP->mechanism.ulParameterLen = 0; - } - return rvAP; -} - -NSS_IMPLEMENT NSSAlgorithmAndParameters * -NSSAlgorithmAndParameters_CreateMD5Digest -( - NSSArena *arenaOpt -) -{ - NSSAlgorithmAndParameters *rvAP = NULL; - rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters); - if (rvAP) { - rvAP->mechanism.mechanism = CKM_MD5; - rvAP->mechanism.pParameter = NULL; - rvAP->mechanism.ulParameterLen = 0; - } - return rvAP; -} - diff --git a/mozilla/security/nss/lib/dev/devutil.c b/mozilla/security/nss/lib/dev/devutil.c index a0c2bfa7637..5c7efdbe677 100644 --- a/mozilla/security/nss/lib/dev/devutil.c +++ b/mozilla/security/nss/lib/dev/devutil.c @@ -32,21 +32,544 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: devutil.c,v $ $Revision: 1.1 $ $Date: 2001-11-08 00:14:53 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: devutil.c,v $ $Revision: 1.2 $ $Date: 2002-04-04 20:00:23 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef DEVM_H #include "devm.h" #endif /* DEVM_H */ +#ifndef CKHELPER_H +#include "ckhelper.h" +#endif /* CKHELPER_H */ + +#ifdef PURE_STAN_BUILD +NSS_IMPLEMENT nssCryptokiObject * +nssCryptokiObject_Create +( + NSSToken *t, + nssSession *session, + CK_OBJECT_HANDLE h +) +{ + PRStatus status; + NSSSlot *slot; + nssCryptokiObject *object; + CK_BBOOL *isTokenObject; + CK_ATTRIBUTE cert_template[] = { + { CKA_TOKEN, NULL, 0 }, + { CKA_LABEL, NULL, 0 } + }; + slot = nssToken_GetSlot(t); + status = nssCKObject_GetAttributes(h, cert_template, 2, + NULL, session, slot); + nssSlot_Destroy(slot); + if (status != PR_SUCCESS) { + /* a failure here indicates a device error */ + return (nssCryptokiObject *)NULL; + } + object = nss_ZNEW(NULL, nssCryptokiObject); + if (!object) { + return (nssCryptokiObject *)NULL; + } + object->handle = h; + object->token = nssToken_AddRef(t); + isTokenObject = (CK_BBOOL *)cert_template[0].pValue; + object->isTokenObject = *isTokenObject; + nss_ZFreeIf(isTokenObject); + NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[1], object->label); + return object; +} + +NSS_IMPLEMENT void +nssCryptokiObject_Destroy +( + nssCryptokiObject *object +) +{ + if (object) { + nssToken_Destroy(object->token); + nss_ZFreeIf(object->label); + nss_ZFreeIf(object); + } +} + +NSS_IMPLEMENT nssCryptokiObject * +nssCryptokiObject_Clone +( + nssCryptokiObject *object +) +{ + nssCryptokiObject *rvObject; + rvObject = nss_ZNEW(NULL, nssCryptokiObject); + if (rvObject) { + rvObject->handle = object->handle; + rvObject->token = nssToken_AddRef(object->token); + rvObject->isTokenObject = object->isTokenObject; + if (object->label) { + rvObject->label = nssUTF8_Duplicate(object->label, NULL); + } + } + return rvObject; +} + +NSS_EXTERN PRBool +nssCryptokiObject_Equal +( + nssCryptokiObject *o1, + nssCryptokiObject *o2 +) +{ + return (o1->token == o2->token && o1->handle == o2->handle); +} + NSS_IMPLEMENT PRUint32 -nssPKCS11StringLength(CK_CHAR *pkcs11Str, PRUint32 bufLen) +nssPKCS11String_Length(CK_CHAR *pkcs11Str, PRUint32 bufLen) { PRInt32 i; for (i = bufLen - 1; i>=0; ) { - if (pkcs11Str[i] != ' ') break; + if (pkcs11Str[i] != ' ' && pkcs11Str[i] != '\0') break; --i; } return (PRUint32)(i + 1); } +/* + * Slot arrays + */ + +NSS_IMPLEMENT NSSSlot ** +nssSlotArray_Clone +( + NSSSlot **slots +) +{ + NSSSlot **rvSlots = NULL; + NSSSlot **sp = slots; + PRUint32 count = 0; + while (sp && *sp) count++; + if (count > 0) { + rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1); + if (rvSlots) { + sp = slots; + count = 0; + for (sp = slots; *sp; sp++) { + rvSlots[count++] = nssSlot_AddRef(*sp); + } + } + } + return rvSlots; +} + +NSS_IMPLEMENT void +nssModuleArray_Destroy +( + NSSModule **modules +) +{ + if (modules) { + NSSModule **mp; + for (mp = modules; *mp; mp++) { + nssModule_Destroy(*mp); + } + nss_ZFreeIf(modules); + } +} + +NSS_IMPLEMENT void +nssSlotArray_Destroy +( + NSSSlot **slots +) +{ + if (slots) { + NSSSlot **slotp; + for (slotp = slots; *slotp; slotp++) { + nssSlot_Destroy(*slotp); + } + nss_ZFreeIf(slots); + } +} + +NSS_IMPLEMENT void +NSSSlotArray_Destroy +( + NSSSlot **slots +) +{ + nssSlotArray_Destroy(slots); +} + +NSS_IMPLEMENT void +nssTokenArray_Destroy +( + NSSToken **tokens +) +{ + if (tokens) { + NSSToken **tokenp; + for (tokenp = tokens; *tokenp; tokenp++) { + nssToken_Destroy(*tokenp); + } + nss_ZFreeIf(tokens); + } +} + +NSS_IMPLEMENT void +NSSTokenArray_Destroy +( + NSSToken **tokens +) +{ + return nssTokenArray_Destroy(tokens); +} + +NSS_IMPLEMENT void +nssCryptokiObjectArray_Destroy +( + nssCryptokiObject **objects +) +{ + if (objects) { + nssCryptokiObject **op; + for (op = objects; *op; op++) { + nssCryptokiObject_Destroy(*op); + } + nss_ZFreeIf(objects); + } +} + +/* + * Slot lists + */ + +struct nssSlotListNodeStr +{ + PRCList link; + NSSSlot *slot; + PRUint32 order; +}; + +/* XXX separate slots with non-present tokens? */ +struct nssSlotListStr +{ + NSSArena *arena; + PRBool i_allocated_arena; + PZLock *lock; + PRCList head; + PRUint32 count; +}; + +NSS_IMPLEMENT nssSlotList * +nssSlotList_Create +( + NSSArena *arenaOpt +) +{ + nssSlotList *rvList; + NSSArena *arena; + nssArenaMark *mark; + if (arenaOpt) { + arena = arenaOpt; + mark = nssArena_Mark(arena); + if (!mark) { + return (nssSlotList *)NULL; + } + } else { + arena = nssArena_Create(); + if (!arena) { + return (nssSlotList *)NULL; + } + } + rvList = nss_ZNEW(arena, nssSlotList); + if (!rvList) { + goto loser; + } + rvList->lock = PZ_NewLock(nssILockOther); /* XXX */ + if (!rvList->lock) { + goto loser; + } + PR_INIT_CLIST(&rvList->head); + rvList->arena = arena; + rvList->i_allocated_arena = (arenaOpt == NULL); + nssArena_Unmark(arena, mark); + return rvList; +loser: + if (arenaOpt) { + nssArena_Release(arena, mark); + } else { + nssArena_Destroy(arena); + } + return (nssSlotList *)NULL; +} + +NSS_IMPLEMENT void +nssSlotList_Destroy +( + nssSlotList *slotList +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + if (slotList) { + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + nssSlot_Destroy(node->slot); + link = PR_NEXT_LINK(link); + } + if (slotList->i_allocated_arena) { + nssArena_Destroy(slotList->arena); + } + } +} + +/* XXX should do allocs outside of lock */ +NSS_IMPLEMENT PRStatus +nssSlotList_Add +( + nssSlotList *slotList, + NSSSlot *slot, + PRUint32 order +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + if (order < node->order) { + break; + } + link = PR_NEXT_LINK(link); + } + node = nss_ZNEW(slotList->arena, struct nssSlotListNodeStr); + if (!node) { + return PR_FAILURE; + } + PR_INIT_CLIST(&node->link); + node->slot = nssSlot_AddRef(slot); + node->order = order; + PR_INSERT_AFTER(&node->link, link); + slotList->count++; + PZ_Unlock(slotList->lock); + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssSlotList_AddModuleSlots +( + nssSlotList *slotList, + NSSModule *module, + PRUint32 order +) +{ + nssArenaMark *mark = NULL; + NSSSlot **sp, **slots = NULL; + PRCList *link; + struct nssSlotListNodeStr *node; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + if (order < node->order) { + break; + } + link = PR_NEXT_LINK(link); + } + slots = nssModule_GetSlots(module); + if (!slots) { + PZ_Unlock(slotList->lock); + return PR_SUCCESS; + } + mark = nssArena_Mark(slotList->arena); + if (!mark) { + goto loser; + } + for (sp = slots; *sp; sp++) { + node = nss_ZNEW(slotList->arena, struct nssSlotListNodeStr); + if (!node) { + goto loser; + } + PR_INIT_CLIST(&node->link); + node->slot = *sp; /* have ref from nssModule_GetSlots */ + node->order = order; + PR_INSERT_AFTER(&node->link, link); + slotList->count++; + } + PZ_Unlock(slotList->lock); + nssArena_Unmark(slotList->arena, mark); + return PR_SUCCESS; +loser: + PZ_Unlock(slotList->lock); + if (mark) { + nssArena_Release(slotList->arena, mark); + } + if (slots) { + nssSlotArray_Destroy(slots); + } + return PR_FAILURE; +} + +NSS_IMPLEMENT NSSSlot ** +nssSlotList_GetSlots +( + nssSlotList *slotList +) +{ + PRUint32 i; + PRCList *link; + struct nssSlotListNodeStr *node; + NSSSlot **rvSlots = NULL; + PZ_Lock(slotList->lock); + rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, slotList->count + 1); + if (!rvSlots) { + PZ_Unlock(slotList->lock); + return (NSSSlot **)NULL; + } + i = 0; + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + rvSlots[i] = nssSlot_AddRef(node->slot); + link = PR_NEXT_LINK(link); + i++; + } + PZ_Unlock(slotList->lock); + return rvSlots; +} + +#if 0 +NSS_IMPLEMENT NSSSlot * +nssSlotList_GetBestSlotForAlgorithmAndParameters +( + nssSlotList *slotList, + NSSAlgorithmAndParameters *ap +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + NSSSlot *rvSlot = NULL; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + node = (struct nssSlotListNodeStr *)link; + if (nssSlot_DoesAlgorithmAndParameters(ap)) { + rvSlot = nssSlot_AddRef(node->slot); /* XXX check isPresent? */ + } + link = PR_NEXT_LINK(link); + } + PZ_Unlock(slotList->lock); + return rvSlot; +} +#endif + +NSS_IMPLEMENT NSSSlot * +nssSlotList_GetBestSlot +( + nssSlotList *slotList +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + NSSSlot *rvSlot = NULL; + PZ_Lock(slotList->lock); + if (PR_CLIST_IS_EMPTY(&slotList->head)) { + PZ_Unlock(slotList->lock); + return (NSSSlot *)NULL; + } + link = PR_NEXT_LINK(&slotList->head); + node = (struct nssSlotListNodeStr *)link; + rvSlot = nssSlot_AddRef(node->slot); /* XXX check isPresent? */ + PZ_Unlock(slotList->lock); + return rvSlot; +} + +NSS_IMPLEMENT NSSSlot * +nssSlotList_FindSlotByName +( + nssSlotList *slotList, + NSSUTF8 *slotName +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + NSSSlot *rvSlot = NULL; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + NSSUTF8 *sName; + node = (struct nssSlotListNodeStr *)link; + sName = nssSlot_GetName(node->slot); + if (nssUTF8_Equal(sName, slotName, NULL)) { + rvSlot = nssSlot_AddRef(node->slot); + break; + } + link = PR_NEXT_LINK(link); + } + PZ_Unlock(slotList->lock); + return rvSlot; +} + +NSS_IMPLEMENT NSSToken * +nssSlotList_FindTokenByName +( + nssSlotList *slotList, + NSSUTF8 *tokenName +) +{ + PRCList *link; + struct nssSlotListNodeStr *node; + NSSToken *rvToken = NULL; + PZ_Lock(slotList->lock); + link = PR_NEXT_LINK(&slotList->head); + while (link != &slotList->head) { + NSSUTF8 *tName; + node = (struct nssSlotListNodeStr *)link; + tName = nssSlot_GetTokenName(node->slot); + if (nssUTF8_Equal(tName, tokenName, NULL)) { + rvToken = nssSlot_GetToken(node->slot); + break; + } + link = PR_NEXT_LINK(link); + } + PZ_Unlock(slotList->lock); + return rvToken; +} + +#endif /* PURE_STAN_BUILD */ + +/* XXX of course this doesn't belong here */ +NSS_IMPLEMENT NSSAlgorithmAndParameters * +NSSAlgorithmAndParameters_CreateSHA1Digest +( + NSSArena *arenaOpt +) +{ + NSSAlgorithmAndParameters *rvAP = NULL; + rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters); + if (rvAP) { + rvAP->mechanism.mechanism = CKM_SHA_1; + rvAP->mechanism.pParameter = NULL; + rvAP->mechanism.ulParameterLen = 0; + } + return rvAP; +} + +NSS_IMPLEMENT NSSAlgorithmAndParameters * +NSSAlgorithmAndParameters_CreateMD5Digest +( + NSSArena *arenaOpt +) +{ + NSSAlgorithmAndParameters *rvAP = NULL; + rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters); + if (rvAP) { + rvAP->mechanism.mechanism = CKM_MD5; + rvAP->mechanism.pParameter = NULL; + rvAP->mechanism.ulParameterLen = 0; + } + return rvAP; +} + diff --git a/mozilla/security/nss/lib/dev/manifest.mn b/mozilla/security/nss/lib/dev/manifest.mn index 2fc8b88f256..2ad8fa13279 100644 --- a/mozilla/security/nss/lib/dev/manifest.mn +++ b/mozilla/security/nss/lib/dev/manifest.mn @@ -30,7 +30,7 @@ # may use your version of this file under either the MPL or the # GPL. # -MANIFEST_CVS_ID = "@(#) $RCSfile: manifest.mn,v $ $Revision: 1.5 $ $Date: 2002-03-14 04:12:15 $ $Name: not supported by cvs2svn $" +MANIFEST_CVS_ID = "@(#) $RCSfile: manifest.mn,v $ $Revision: 1.6 $ $Date: 2002-04-04 20:00:23 $ $Name: not supported by cvs2svn $" CORE_DEPTH = ../../.. @@ -39,6 +39,7 @@ PRIVATE_EXPORTS = \ devt.h \ dev.h \ nssdevt.h \ + nssdev.h \ $(NULL) EXPORTS = \ diff --git a/mozilla/security/nss/lib/dev/nssdev.h b/mozilla/security/nss/lib/dev/nssdev.h new file mode 100644 index 00000000000..120eefc93a3 --- /dev/null +++ b/mozilla/security/nss/lib/dev/nssdev.h @@ -0,0 +1,72 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#ifndef NSSDEV_H +#define NSSDEV_H + +#ifdef DEBUG +static const char NSSDEV_CVS_ID[] = "@(#) $RCSfile: nssdev.h,v $ $Revision: 1.1 $ $Date: 2002-04-04 20:00:23 $ $Name: not supported by cvs2svn $"; +#endif /* DEBUG */ +/* + * nssdev.h + * + * High-level methods for interaction with cryptoki devices + */ + +#ifndef NSSDEVT_H +#include "nssdevt.h" +#endif /* NSSDEVT_H */ + +PR_BEGIN_EXTERN_C + +/* NSSAlgorithmAndParameters + * + * NSSAlgorithmAndParameters_CreateSHA1Digest + * NSSAlgorithmAndParameters_CreateMD5Digest + */ + +NSS_EXTERN NSSAlgorithmAndParameters * +NSSAlgorithmAndParameters_CreateSHA1Digest +( + NSSArena *arenaOpt +); + +NSS_EXTERN NSSAlgorithmAndParameters * +NSSAlgorithmAndParameters_CreateMD5Digest +( + NSSArena *arenaOpt +); + +PR_END_EXTERN_C + +#endif /* DEV_H */ diff --git a/mozilla/security/nss/lib/pk11wrap/dev3hack.c b/mozilla/security/nss/lib/pk11wrap/dev3hack.c index 6b76aaef126..b8aa77b34b4 100644 --- a/mozilla/security/nss/lib/pk11wrap/dev3hack.c +++ b/mozilla/security/nss/lib/pk11wrap/dev3hack.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: dev3hack.c,v $ $Revision: 1.9 $ $Date: 2002-03-14 04:12:20 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: dev3hack.c,v $ $Revision: 1.10 $ $Date: 2002-04-04 20:00:26 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef NSS_3_4_CODE @@ -121,13 +121,12 @@ nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) if (!rvSlot) { return NULL; } - rvSlot->refCount = 1; + rvSlot->base.refCount = 1; rvSlot->pk11slot = nss3slot; rvSlot->epv = nss3slot->functionList; rvSlot->slotID = nss3slot->slotID; - rvSlot->trustDomain = td; /* Grab the slot name from the PKCS#11 fixed-length buffer */ - rvSlot->name = nssUTF8_Duplicate(nss3slot->slot_name,td->arena); + rvSlot->base.name = nssUTF8_Duplicate(nss3slot->slot_name,td->arena); return rvSlot; } @@ -139,7 +138,7 @@ nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) if (!rvToken) { return NULL; } - rvToken->refCount = 1; + rvToken->base.refCount = 1; rvToken->pk11slot = nss3slot; rvToken->epv = nss3slot->functionList; rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena, @@ -148,11 +147,11 @@ nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) nss3slot->defRWSession); rvToken->trustDomain = td; /* Grab the token name from the PKCS#11 fixed-length buffer */ - rvToken->name = nssUTF8_Duplicate(nss3slot->token_name,td->arena); + rvToken->base.name = nssUTF8_Duplicate(nss3slot->token_name,td->arena); rvToken->slot = nssSlot_CreateFromPK11SlotInfo(td, nss3slot); rvToken->slot->token = rvToken; rvToken->defaultSession->slot = rvToken->slot; - rvToken->arena = td->arena; + rvToken->base.arena = td->arena; return rvToken; } @@ -162,7 +161,7 @@ nssToken_UpdateName(NSSToken *token) if (!token) { return; } - token->name = nssUTF8_Duplicate(token->pk11slot->token_name,token->arena); + token->base.name = nssUTF8_Duplicate(token->pk11slot->token_name,token->base.arena); } NSS_IMPLEMENT PRBool @@ -183,7 +182,7 @@ nssToken_Refresh(NSSToken *token) return PR_SUCCESS; } nss3slot = token->pk11slot; - token->defaultSession = nssSession_ImportNSS3Session(token->slot->arena, + token->defaultSession = nssSession_ImportNSS3Session(token->slot->base.arena, nss3slot->session, nss3slot->sessionLock, nss3slot->defRWSession); diff --git a/mozilla/security/nss/lib/pki/pki3hack.c b/mozilla/security/nss/lib/pki/pki3hack.c index 47e10ace26a..252d25ef6f4 100644 --- a/mozilla/security/nss/lib/pki/pki3hack.c +++ b/mozilla/security/nss/lib/pki/pki3hack.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.46 $ $Date: 2002-04-03 19:22:14 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: pki3hack.c,v $ $Revision: 1.47 $ $Date: 2002-04-04 20:00:28 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ /* @@ -254,7 +254,7 @@ nssToken_LoadCerts(NSSToken *token) search.cached = NULL; search.searchType = nssTokenSearchType_TokenOnly; if (!token->certList) { - token->certList = nssList_Create(token->arena, PR_FALSE); + token->certList = nssList_Create(token->base.arena, PR_FALSE); if (!token->certList) { return PR_FAILURE; }