diff --git a/mozilla/security/nss/lib/dev/ckhelper.c b/mozilla/security/nss/lib/dev/ckhelper.c index 5be20f30a9d..910b97db479 100644 --- a/mozilla/security/nss/lib/dev/ckhelper.c +++ b/mozilla/security/nss/lib/dev/ckhelper.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:07 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef PKIT_H @@ -55,20 +55,25 @@ static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.1 $ $Da #include "base.h" #endif /* BASE_H */ -NSS_IMPLEMENT_DATA const CK_BBOOL -g_ck_true = CK_TRUE; +static const CK_BBOOL s_true = CK_TRUE; +NSS_IMPLEMENT_DATA const NSSItem +g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) }; -NSS_IMPLEMENT_DATA const CK_BBOOL -g_ck_false = CK_FALSE; +static const CK_BBOOL s_false = CK_FALSE; +NSS_IMPLEMENT_DATA const NSSItem +g_ck_false = { (CK_VOID_PTR)&s_false, sizeof(s_false) }; -NSS_IMPLEMENT_DATA const CK_OBJECT_CLASS -g_ck_obj_class_cert = CKO_CERTIFICATE; +static const CK_OBJECT_CLASS s_class_cert = CKO_CERTIFICATE; +NSS_IMPLEMENT_DATA const NSSItem +g_ck_class_cert = { (CK_VOID_PTR)&s_class_cert, sizeof(s_class_cert) }; -NSS_IMPLEMENT_DATA const CK_OBJECT_CLASS -g_ck_obj_class_pubkey = CKO_PUBLIC_KEY; +static const CK_OBJECT_CLASS s_class_pubkey = CKO_PUBLIC_KEY; +NSS_IMPLEMENT_DATA const NSSItem +g_ck_class_pubkey = { (CK_VOID_PTR)&s_class_pubkey, sizeof(s_class_pubkey) }; -NSS_IMPLEMENT_DATA const CK_OBJECT_CLASS -g_ck_obj_class_privkey = CKO_PRIVATE_KEY; +static const CK_OBJECT_CLASS s_class_privkey = CKO_PRIVATE_KEY; +NSS_IMPLEMENT_DATA const NSSItem +g_ck_class_privkey = { (CK_VOID_PTR)&s_class_privkey, sizeof(s_class_privkey) }; NSS_IMPLEMENT PRStatus NSSCKObject_GetAttributes @@ -77,16 +82,16 @@ NSSCKObject_GetAttributes CK_ATTRIBUTE_PTR obj_template, CK_ULONG count, NSSArena *arenaOpt, + nssSession *session, NSSSlot *slot ) { nssArenaMark *mark; - CK_SESSION_HANDLE session; + CK_SESSION_HANDLE hSession; CK_ULONG i; CK_RV ckrv; PRStatus nssrv; - /* use the default session */ - session = slot->token->session.handle; + hSession = session->handle; #ifdef arena_mark_bug_fixed if (arenaOpt) { mark = nssArenaMark(arenaOpt); @@ -96,7 +101,7 @@ NSSCKObject_GetAttributes } #endif /* Get the storage size needed for each attribute */ - ckrv = CKAPI(slot)->C_GetAttributeValue(session, + ckrv = CKAPI(slot)->C_GetAttributeValue(hSession, object, obj_template, count); if (ckrv != CKR_OK) { /* set an error here */ @@ -111,7 +116,7 @@ NSSCKObject_GetAttributes } } /* Obtain the actual attribute values. */ - ckrv = CKAPI(slot)->C_GetAttributeValue(session, + ckrv = CKAPI(slot)->C_GetAttributeValue(hSession, object, obj_template, count); if (ckrv != CKR_OK) { /* set an error here */ diff --git a/mozilla/security/nss/lib/dev/ckhelper.h b/mozilla/security/nss/lib/dev/ckhelper.h index 8479c39c15a..403fe2d18a1 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.1 $ $Date: 2001-09-13 22:06:08 $ $Name: not supported by cvs2svn $"; +static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile: ckhelper.h,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef NSSCKT_H @@ -59,120 +59,21 @@ PR_BEGIN_EXTERN_C */ /* Boolean values */ -NSS_EXTERN_DATA const CK_BBOOL g_ck_true; -NSS_EXTERN_DATA const CK_BBOOL g_ck_false; +NSS_EXTERN_DATA const NSSItem g_ck_true; +NSS_EXTERN_DATA const NSSItem g_ck_false; /* Object classes */ -NSS_EXTERN_DATA const CK_OBJECT_CLASS g_ck_obj_class_cert; -NSS_EXTERN_DATA const CK_OBJECT_CLASS g_ck_obj_class_pubkey; -NSS_EXTERN_DATA const CK_OBJECT_CLASS g_ck_obj_class_privkey; - -/* - * Helpers for building templates. - */ - -/* - * NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, i, ckattr, global_value) - * - * used to set one of the global attributes defined above. - */ -#define NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, i, ckattr, global_value) \ - (cktmpl)[i].type = ckattr; \ - (cktmpl)[i].pValue = (CK_VOID_PTR)&(global_value); \ - (cktmpl)[i].ulValueLen = (CK_ULONG)sizeof(global_value); - -/* - * NSS_SET_CK_ATTRIB_TRUE(cktmpl, i, ckattr) - * - * Set an attribute to CK_TRUE in a template - */ -#define NSS_SET_CK_ATTRIB_TRUE(cktmpl, i, ckattr) \ - NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, i, ckattr, g_ck_true) - -/* - * NSS_SET_CK_ATTRIB_FALSE(cktmpl, i, ckattr) - * - * Set an attribute to CK_FALSE in a template - */ -#define NSS_SET_CK_ATTRIB_FALSE(cktmpl, i, ckattr) \ - NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, i, ckattr, g_ck_false) - -/* - * NSS_SET_CK_ATTRIB_ITEM(cktmpl, i, ckattr, item) - * - * Set an attribute in a template to use data from an item - */ -#define NSS_SET_CK_ATTRIB_ITEM(cktmpl, i, ckattr, item) \ - (cktmpl)[i].type = ckattr; \ - (cktmpl)[i].pValue = (CK_VOID_PTR)(item)->data; \ - (cktmpl)[i].ulValueLen = (CK_ULONG)(item)->len; - -/* Create Templates */ - -/* Certificate template - * - * NSS_CK_CERTIFICATE_CREATE4(cktmpl, subject, id, der) - * - * CKA_CLASS = CKO_CERTIFICATE - * CKA_SUBJECT = subject->data - * CKA_ID = id->data - * CKA_VALUE = der->data - */ - -#define NSS_CK_CERTIFICATE_CREATE4(cktmpl, subject, id, der) \ - NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, 0, CKA_CLASS, g_ck_obj_class_cert) \ - NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_SUBJECT, subject) \ - NSS_SET_CK_ATTRIB_ITEM(cktmpl, 2, CKA_ID, id) \ - NSS_SET_CK_ATTRIB_ITEM(cktmpl, 3, CKA_VALUE, der) - -/* Search Templates */ - -/* NSS_CK_CERTIFICATE_SEARCH(cktmpl) - * - * Set up a search template for any cert object - */ -#define NSS_CK_CERTIFICATE_SEARCH(cktmpl) \ - NSS_SET_CK_ATTRIB_GLOBAL(cktmpl, 0, CKA_CLASS, g_ck_obj_class_cert) - -/* NSS_CK_CERTIFICATE_SEARCH_LABEL2(cktmpl, label) - * - * Set up a search template for a cert using label->data - */ -#define NSS_CK_CERTIFICATE_SEARCH_LABEL2(cktmpl, label) \ - NSS_CK_CERTIFICATE_SEARCH(cktmpl) \ - NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_LABEL, label) - -/* NSS_CK_CERTIFICATE_SEARCH_SUBJECT2(cktmpl, subject) - * - * Set up a search template for a cert using subject->data - */ -#define NSS_CK_CERTIFICATE_SEARCH_SUBJECT2(cktmpl, subject) \ - NSS_CK_CERTIFICATE_SEARCH(cktmpl) \ - NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_SUBJECT, subject) - -/* NSS_CK_CERTIFICATE_SEARCH_ID2(cktmpl, id) - * - * Set up a search template for a cert using id->data - */ -#define NSS_CK_CERTIFICATE_SEARCH_ID2(cktmpl, id) \ - NSS_CK_CERTIFICATE_SEARCH(cktmpl) \ - NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_ID, id) - -/* NSS_CK_CERTIFICATE_SEARCH_DER2(cktmpl, der) - * - * Set up a search template for a cert using der->data - */ -#define NSS_CK_CERTIFICATE_SEARCH_DER2(cktmpl, der) \ - NSS_CK_CERTIFICATE_SEARCH(cktmpl) \ - NSS_SET_CK_ATTRIB_ITEM(cktmpl, 1, CKA_VALUE, der) +NSS_EXTERN_DATA const NSSItem g_ck_class_cert; +NSS_EXTERN_DATA const NSSItem g_ck_class_pubkey; +NSS_EXTERN_DATA const NSSItem g_ck_class_privkey; /* NSS_CK_ATTRIBUTE_TO_ITEM(attrib, item) * * Convert a CK_ATTRIBUTE to an NSSItem. */ -#define NSS_CK_ATTRIBUTE_TO_ITEM(attrib, item) \ - (item)->data = (void *)(attrib)->pValue; \ - (item)->size = (PRUint32)(attrib)->ulValueLen; \ +#define NSS_CK_ATTRIBUTE_TO_ITEM(attrib, item) \ + (item)->data = (void *)(attrib)->pValue; \ + (item)->size = (PRUint32)(attrib)->ulValueLen; \ /* Get an array of attributes from an object. */ NSS_EXTERN PRStatus @@ -182,6 +83,7 @@ NSSCKObject_GetAttributes CK_ATTRIBUTE_PTR obj_template, CK_ULONG count, NSSArena *arenaOpt, + nssSession *session, NSSSlot *slot ); diff --git a/mozilla/security/nss/lib/dev/dev.h b/mozilla/security/nss/lib/dev/dev.h index 3b1b46d690f..07b15ba30e9 100644 --- a/mozilla/security/nss/lib/dev/dev.h +++ b/mozilla/security/nss/lib/dev/dev.h @@ -35,7 +35,7 @@ #define DEV_H #ifdef DEBUG -static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:08 $ $Name: not supported by cvs2svn $"; +static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef DEVT_H @@ -60,6 +60,11 @@ static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.1 $ $Dat * |-----------|---> NSSSlot <--> NSSToken */ +/* XXX These should probably all be "nss" not "NSS". Though the types are + * exposed, the API's should not be (with the exception of functions + * put in a friend header. + */ + #ifndef DEVT_H #include "devt.h" #endif /* DEVT_H */ @@ -162,6 +167,14 @@ NSSSlot_Logout * NSSSlot_ChangePassword */ +NSS_EXTERN nssSession * +NSSSlot_CreateSession +( + NSSSlot *slot, + NSSArena *arenaOpt, + PRBool readOnly /* so far, this is the only flag used */ +); + NSS_EXTERN NSSToken * NSSToken_Create ( @@ -184,41 +197,47 @@ NSS_EXTERN NSSCertificate * NSSToken_ImportCertificate ( NSSToken *tok, - CK_ATTRIBUTE *cktemplate + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR cktemplate ); NSS_EXTERN NSSPublicKey * NSSToken_ImportPublicKey ( NSSToken *tok, - CK_ATTRIBUTE *cktemplate + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR cktemplate ); NSS_EXTERN NSSPrivateKey * NSSToken_ImportPrivateKey ( NSSToken *tok, - CK_ATTRIBUTE *cktemplate + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR cktemplate ); NSS_EXTERN NSSSymmetricKey * NSSToken_ImportSymmetricKey ( NSSToken *tok, - CK_ATTRIBUTE *cktemplate + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR cktemplate ); NSS_EXTERN NSSPublicKey * NSSToken_GenerateKeyPair ( - NSSToken *tok + NSSToken *tok, + nssSession *sessionOpt /* algorithm and parameters */ ); NSS_EXTERN NSSSymmetricKey * NSSToken_GenerateSymmetricKey ( - NSSToken *tok + NSSToken *tok, + nssSession *sessionOpt /* algorithm and parameters */ ); @@ -227,18 +246,49 @@ NSS_EXTERN PRStatus NSSToken_DeleteStoredObject ( NSSToken *tok, + nssSession *sessionOpt, CK_OBJECT_HANDLE object ); +NSS_EXTERN NSSCertificate ** +NSSToken_FindCertificatesByTemplate +( + NSSToken *tok, + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR cktemplate, + CK_ULONG ctsize +); + /* again, a questionable function. maybe some tokens allow this? */ NSS_EXTERN PRStatus * NSSToken_TraverseCertificates ( NSSToken *tok, + nssSession *sessionOpt, PRStatus (*callback)(NSSCertificate *c, void *arg), void *arg ); +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 +); + #ifdef DEBUG void NSSModule_Debug(NSSModule *m); #endif diff --git a/mozilla/security/nss/lib/dev/devt.h b/mozilla/security/nss/lib/dev/devt.h index 532f15645fc..20468804ad4 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.1 $ $Date: 2001-09-13 22:06:09 $ $Name: not supported by cvs2svn $"; +static const char DEVT_CVS_ID[] = "@(#) $RCSfile: devt.h,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ /* @@ -64,6 +64,8 @@ typedef struct NSSSlotStr NSSSlot; typedef struct NSSTokenStr NSSToken; +typedef struct nssSessionStr nssSession; + /* The list of boolean flags used to describe properties of a * module. */ @@ -89,34 +91,34 @@ struct NSSModuleStr { struct NSSSlotStr { - NSSArena *arena; - PRInt32 refCount; - NSSModule *module; /* Parent */ - NSSToken *token; /* Child (or peer, if you will) */ - NSSUTF8 *name; - void *epv; - CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */ - PRUint32 flags; + 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 NSSTokenStr { - NSSArena *arena; - PRInt32 refCount; - NSSSlot *slot; /* Parent (or peer, if you will) */ - NSSUTF8 *name; - CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */ - PRUint32 flags; - struct { - /* according to PK11SlotInfoStr, a default session for "quick-and-dirty" - * functions - */ - CK_SESSION_HANDLE handle; - PZLock *lock; - } session; + NSSArena *arena; + PRInt32 refCount; + NSSSlot *slot; /* Parent (or peer, if you will) */ + NSSUTF8 *name; + CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */ + PRUint32 flags; + nssSession *defaultSession; }; -struct NSSTokenStr; +struct nssSessionStr +{ + PZLock *lock; + CK_SESSION_HANDLE handle; + NSSSlot *slot; +}; PR_END_EXTERN_C diff --git a/mozilla/security/nss/lib/dev/module.c b/mozilla/security/nss/lib/dev/module.c index 298c35c1025..88a9be55860 100644 --- a/mozilla/security/nss/lib/dev/module.c +++ b/mozilla/security/nss/lib/dev/module.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: module.c,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:10 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: module.c,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef DEV_H @@ -318,7 +318,8 @@ NSSModule_TraverseCertificates PRUint32 i; for (i=0; inumSlots; i++) { /* might as well skip straight to token, right? or is this slot? */ - NSSToken_TraverseCertificates(mod->slots[i]->token, callback, arg); + NSSToken_TraverseCertificates(mod->slots[i]->token, + NULL, callback, arg); } return NULL; } diff --git a/mozilla/security/nss/lib/dev/slot.c b/mozilla/security/nss/lib/dev/slot.c index 0df3a5b6ea5..fd5a1529bf9 100644 --- a/mozilla/security/nss/lib/dev/slot.c +++ b/mozilla/security/nss/lib/dev/slot.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.2 $ $Date: 2001-09-13 22:14:22 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.3 $ $Date: 2001-09-18 20:54:28 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef DEV_H @@ -55,6 +55,21 @@ static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.2 $ $Date: #include "base.h" #endif /* BASE_H */ +/* The flags needed to open a read-only session. */ +static const CK_FLAGS s_ck_readonly_flags = CKF_SERIAL_SESSION; + +/* In pk11slot.c, this was a no-op. So it is here also. */ +static CK_RV PR_CALLBACK +nss_ck_slot_notify +( + CK_SESSION_HANDLE session, + CK_NOTIFICATION event, + CK_VOID_PTR pData +) +{ + return CKR_OK; +} + /* maybe this should really inherit completely from the module... I dunno, * any uses of slots where independence is needed? */ @@ -123,6 +138,7 @@ NSSSlot_Create rvSlot->epv = parent->epv; rvSlot->module = parent; rvSlot->name = slotName; + rvSlot->slotID = slotID; rvSlot->ckFlags = slotInfo.flags; /* Initialize the token if present. */ if (slotInfo.flags & CKF_TOKEN_PRESENT) { @@ -166,3 +182,85 @@ NSSSlot_Destroy return PR_SUCCESS; } +NSS_IMPLEMENT nssSession * +NSSSlot_CreateSession +( + NSSSlot *slot, + NSSArena *arenaOpt, + PRBool readOnly /* so far, this is the only flag used */ +) +{ + CK_RV ckrv; + CK_FLAGS ckflags; + CK_SESSION_HANDLE session; + nssSession *rvSession; + ckflags = s_ck_readonly_flags; + if (!readOnly) { + 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); + if (ckrv != CKR_OK) { + /* set an error here, eh? */ + return (nssSession *)NULL; + } + rvSession = nss_ZNEW(arenaOpt, nssSession); + if (!rvSession) { + return (nssSession *)NULL; + } + if (slot->module->flags & NSSMODULE_FLAGS_NOT_THREADSAFE) { + /* If the parent module is not threadsafe, create lock to manage + * session within threads. + */ + rvSession->lock = PZ_NewLock(nssILockOther); + if (!rvSession->lock) { + /* need to translate NSPR error? */ + if (arenaOpt) { + } else { + nss_ZFreeIf(rvSession); + } + } + } + rvSession->handle = session; + rvSession->slot = slot; + return rvSession; +} + +NSS_IMPLEMENT PRStatus +nssSession_Destroy +( + nssSession *s +) +{ + if (s) { + if (s->lock) { + PZ_DestroyLock(s->lock); + } + nss_ZFreeIf(s); + } + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssSession_EnterMonitor +( + nssSession *s +) +{ + if (s->lock) PZ_Lock(s->lock); + return PR_SUCCESS; +} + +NSS_IMPLEMENT PRStatus +nssSession_ExitMonitor +( + nssSession *s +) +{ + return (s->lock) ? PZ_Unlock(s->lock) : PR_SUCCESS; +} + diff --git a/mozilla/security/nss/lib/dev/token.c b/mozilla/security/nss/lib/dev/token.c index 66ebc349afd..b50950a56af 100644 --- a/mozilla/security/nss/lib/dev/token.c +++ b/mozilla/security/nss/lib/dev/token.c @@ -32,7 +32,7 @@ */ #ifdef DEBUG -static const char CVS_ID[] = "@(#) $RCSfile: token.c,v $ $Revision: 1.1 $ $Date: 2001-09-13 22:06:10 $ $Name: not supported by cvs2svn $"; +static const char CVS_ID[] = "@(#) $RCSfile: token.c,v $ $Revision: 1.2 $ $Date: 2001-09-18 20:54:28 $ $Name: not supported by cvs2svn $"; #endif /* DEBUG */ #ifndef DEV_H @@ -59,30 +59,6 @@ static const char CVS_ID[] = "@(#) $RCSfile: token.c,v $ $Revision: 1.1 $ $Date: #include "base.h" #endif /* BASE_H */ -/* If the token cannot manage threads, we have to. The following detect - * a non-threadsafe token and lock/unlock its session handle. - */ -#define NSSTOKEN_ENTER_MONITOR(token) \ - if ((token)->session.lock) PZ_Lock((token)->session.lock) - -#define NSSTOKEN_EXIT_MONITOR(token) \ - if ((token)->session.lock) PZ_Unlock((token)->session.lock) - -/* The flags needed to open a read-only session. */ -static const CK_FLAGS s_ck_readonly_flags = CKF_SERIAL_SESSION; - -/* In pk11slot.c, this was a no-op. So it is here also. */ -CK_RV PR_CALLBACK -nss_ck_slot_notify -( - CK_SESSION_HANDLE session, - CK_NOTIFICATION event, - CK_VOID_PTR pData -) -{ - return CKR_OK; -} - /* maybe this should really inherit completely from the module... I dunno, * any uses of slots where independence is needed? */ @@ -97,12 +73,12 @@ NSSToken_Create NSSArena *arena; nssArenaMark *mark; NSSToken *rvToken; + nssSession *session; NSSUTF8 *tokenName = NULL; PRUint32 length; PRBool newArena; PRStatus nssrv; CK_TOKEN_INFO tokenInfo; - CK_SESSION_HANDLE session; CK_RV ckrv; if (arenaOpt) { arena = arenaOpt; @@ -124,16 +100,8 @@ NSSToken_Create if (!rvToken) { goto loser; } - if (parent->module->flags & NSSMODULE_FLAGS_NOT_THREADSAFE) { - /* If the parent module is not threadsafe, create lock to manage - * session within threads. - */ - rvToken->session.lock = PZ_NewLock(nssILockOther); - } /* Get token information */ - NSSTOKEN_ENTER_MONITOR(rvToken); ckrv = CKAPI(parent)->C_GetTokenInfo(slotID, &tokenInfo); - NSSTOKEN_EXIT_MONITOR(rvToken); if (ckrv != CKR_OK) { /* set an error here, eh? */ goto loser; @@ -147,13 +115,9 @@ NSSToken_Create goto loser; } } - /* Open a session handle for the token. */ - NSSTOKEN_ENTER_MONITOR(rvToken); - ckrv = CKAPI(parent)->C_OpenSession(slotID, s_ck_readonly_flags, - parent, nss_ck_slot_notify, &session); - NSSTOKEN_EXIT_MONITOR(rvToken); - if (ckrv != CKR_OK) { - /* set an error here, eh? */ + /* Open a default session handle for the token. */ + session = NSSSlot_CreateSession(parent, arena, PR_TRUE); + if (session == NULL) { goto loser; } /* TODO: seed the RNG here */ @@ -167,7 +131,7 @@ NSSToken_Create rvToken->slot = parent; rvToken->name = tokenName; rvToken->ckFlags = tokenInfo.flags; - rvToken->session.handle = session; + rvToken->defaultSession = session; #ifdef arena_mark_bug_fixed nssrv = nssArena_Unmark(arena, mark); if (nssrv != PR_SUCCESS) { @@ -176,6 +140,9 @@ NSSToken_Create #endif return rvToken; loser: + if (session) { + nssSession_Destroy(session); + } if (newArena) { nssArena_Destroy(arena); } else { @@ -185,9 +152,6 @@ loser: } #endif } - if (rvToken && rvToken->session.lock) { - PZ_DestroyLock(rvToken->session.lock); - } return (NSSToken *)NULL; } @@ -198,63 +162,164 @@ NSSToken_Destroy ) { if (--tok->refCount == 0) { + if (tok->defaultSession) { + nssSession_Destroy(tok->defaultSession); + } return NSSArena_Destroy(tok->arena); } return PR_SUCCESS; } -NSS_IMPLEMENT PRStatus * -NSSToken_TraverseCertificates +/* This is only used by the Traverse function. If we ditch traversal, + * ditch this. + */ +struct certCallbackStr { + PRStatus (*callback)(NSSCertificate *c, void *arg); + void *arg; +}; + +/* also symmKeyCallbackStr, pubKeyCallbackStr, etc. */ + +/* + * This callback examines each matching certificate by passing it to + * a higher-level callback function. + */ +static PRStatus +examine_cert_callback(NSSToken *t, nssSession *session, + CK_OBJECT_HANDLE h, void *arg) +{ + PRStatus cbrv; + NSSCertificate *cert; + struct certCallbackStr *ccb = (struct certCallbackStr *)arg; + /* maybe it should be NSSToken_CreateCertificate(token, handle); */ + cert = NSSCertificate_CreateFromHandle(h, session, t->slot); + if (!cert) { + goto loser; + } + cbrv = (*ccb->callback)(cert, ccb->arg); + if (cbrv != PR_SUCCESS) { + goto loser; + } + return PR_SUCCESS; +loser: + return PR_FAILURE; +} + +static PRStatus +collect_certs_callback(NSSToken *t, nssSession *session, + CK_OBJECT_HANDLE h, void *arg) +{ + NSSCertificate *cert; + void *certList; /* nssList soon */ + certList = (void *)arg; + cert = NSSCertificate_CreateFromHandle(h, session, t->slot); + if (!cert) { + goto loser; + } + /* XXX add cert to list */ + return PR_SUCCESS; +loser: + return PR_FAILURE; +} + +static PRStatus * +nsstoken_TraverseObjects ( NSSToken *tok, - PRStatus (*callback)(NSSCertificate *c, void *arg), + nssSession *session, + CK_ATTRIBUTE_PTR obj_template, + CK_ULONG otsize, + PRStatus (*callback)(NSSToken *t, nssSession *session, + CK_OBJECT_HANDLE h, void *arg), void *arg ) { NSSSlot *slot; - NSSCertificate *cert; - CK_OBJECT_HANDLE object; - CK_ATTRIBUTE cert_template[1]; - CK_SESSION_HANDLE session; - CK_ULONG count; - CK_RV ckrv; PRStatus cbrv; + CK_RV ckrv; + CK_ULONG count; + CK_OBJECT_HANDLE object; + CK_SESSION_HANDLE hSession; slot = tok->slot; - session = tok->session.handle; - NSS_CK_CERTIFICATE_SEARCH(cert_template); - NSSTOKEN_ENTER_MONITOR(tok); - ckrv = CKAPI(slot)->C_FindObjectsInit(session, cert_template, 1); + hSession = session->handle; + ckrv = CKAPI(slot)->C_FindObjectsInit(hSession, obj_template, otsize); if (ckrv != CKR_OK) { goto loser; } while (PR_TRUE) { - ckrv = CKAPI(slot)->C_FindObjects(session, &object, 1, &count); + /* this could be sped up by getting 5-10 at a time? */ + ckrv = CKAPI(slot)->C_FindObjects(hSession, &object, 1, &count); if (ckrv != CKR_OK) { goto loser; } if (count == 0) { break; } - /* it would be better if the next two were done outside of the - * monitor. but we don't want this function anyway, right? - */ - cert = NSSCertificate_CreateFromHandle(object, slot); - if (!cert) { - goto loser; - } - cbrv = (*callback)(cert, arg); + cbrv = (*callback)(tok, session, object, arg); if (cbrv != PR_SUCCESS) { goto loser; } } - ckrv = CKAPI(slot)->C_FindObjectsFinal(session); + ckrv = CKAPI(slot)->C_FindObjectsFinal(hSession); if (ckrv != CKR_OK) { goto loser; } - NSSTOKEN_EXIT_MONITOR(tok); - return NULL; /* for now... */ loser: - NSSTOKEN_EXIT_MONITOR(tok); return NULL; /* for now... */ } +NSS_IMPLEMENT PRStatus * +NSSToken_TraverseCertificates +( + NSSToken *tok, + nssSession *sessionOpt, + PRStatus (*callback)(NSSCertificate *c, void *arg), + void *arg +) +{ + PRStatus *rvstack; + nssSession *session; + struct certCallbackStr ccb; + CK_ATTRIBUTE cert_template[] = { + { CKA_CLASS, g_ck_class_cert.data, g_ck_class_cert.size } + }; + CK_ULONG ctsize = sizeof(cert_template) / sizeof(cert_template[0]); + session = (sessionOpt) ? sessionOpt : tok->defaultSession; + ccb.callback = callback; + ccb.arg = arg; + nssSession_EnterMonitor(session); + rvstack = nsstoken_TraverseObjects(tok, session, cert_template, ctsize, + examine_cert_callback, (void *)&ccb); + nssSession_ExitMonitor(session); + return rvstack; +} + +NSS_IMPLEMENT NSSCertificate ** +NSSToken_FindCertificatesByTemplate +( + NSSToken *tok, + nssSession *sessionOpt, + CK_ATTRIBUTE_PTR cktemplate, + CK_ULONG ctsize +) +{ + PRStatus *rvstack; + nssSession *session; + void *certList; /* nssList soon */ + session = (sessionOpt) ? sessionOpt : tok->defaultSession; + nssSession_EnterMonitor(session); + rvstack = nsstoken_TraverseObjects(tok, session, cktemplate, ctsize, + collect_certs_callback, + (void *)certList); + nssSession_ExitMonitor(session); + if (rvstack) { + /* examine the errors */ + goto loser; + } + /* XXX get an array from the list, return it */ + return (NSSCertificate **)NULL; +loser: + /* clean out the list */ + return (NSSCertificate **)NULL; +} +