/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef PKIT_H #include "pkit.h" #endif /* PKIT_H */ #ifndef DEVM_H #include "devm.h" #endif /* DEVM_H */ #include "pki3hack.h" #include "dev3hack.h" #include "pkim.h" #ifndef BASE_H #include "base.h" #endif /* BASE_H */ #include "pk11func.h" #include "secmodti.h" #include "secerr.h" NSS_IMPLEMENT nssSession * nssSession_ImportNSS3Session(NSSArena *arenaOpt, CK_SESSION_HANDLE session, PZLock *lock, PRBool rw) { nssSession *rvSession = NULL; if (session != CK_INVALID_HANDLE) { rvSession = nss_ZNEW(arenaOpt, nssSession); if (rvSession) { rvSession->handle = session; rvSession->lock = lock; rvSession->ownLock = PR_FALSE; rvSession->isRW = rw; } } return rvSession; } NSS_IMPLEMENT nssSession * nssSlot_CreateSession( NSSSlot *slot, NSSArena *arenaOpt, PRBool readWrite) { nssSession *rvSession; if (!readWrite) { /* nss3hack version only returns rw swssions */ return NULL; } rvSession = nss_ZNEW(arenaOpt, nssSession); if (!rvSession) { return (nssSession *)NULL; } rvSession->handle = PK11_GetRWSession(slot->pk11slot); if (rvSession->handle == CK_INVALID_HANDLE) { nss_ZFreeIf(rvSession); return NULL; } rvSession->isRW = PR_TRUE; rvSession->slot = slot; /* * The session doesn't need its own lock. Here's why. * 1. If we are reusing the default RW session of the slot, * the slot lock is already locked to protect the session. * 2. If the module is not thread safe, the slot (or rather * module) lock is already locked. * 3. If the module is thread safe and we are using a new * session, no higher-level lock has been locked and we * would need a lock for the new session. However, the * current usage of the session is that it is always * used and destroyed within the same function and never * shared with another thread. * So the session is either already protected by another * lock or only used by one thread. */ rvSession->lock = NULL; rvSession->ownLock = PR_FALSE; return rvSession; } NSS_IMPLEMENT PRStatus nssSession_Destroy(nssSession *s) { PRStatus rv = PR_SUCCESS; if (s) { if (s->isRW) { PK11_RestoreROSession(s->slot->pk11slot, s->handle); } rv = nss_ZFreeIf(s); } return rv; } static NSSSlot * nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) { NSSSlot *rvSlot; NSSArena *arena; arena = nssArena_Create(); if (!arena) { return NULL; } rvSlot = nss_ZNEW(arena, NSSSlot); if (!rvSlot) { nssArena_Destroy(arena); return NULL; } rvSlot->base.refCount = 1; rvSlot->base.lock = PZ_NewLock(nssILockOther); rvSlot->base.arena = arena; rvSlot->pk11slot = PK11_ReferenceSlot(nss3slot); rvSlot->epv = nss3slot->functionList; rvSlot->slotID = nss3slot->slotID; /* Grab the slot name from the PKCS#11 fixed-length buffer */ rvSlot->base.name = nssUTF8_Duplicate(nss3slot->slot_name, td->arena); rvSlot->lock = (nss3slot->isThreadSafe) ? NULL : nss3slot->sessionLock; rvSlot->isPresentLock = PZ_NewLock(nssiLockOther); rvSlot->isPresentCondition = PR_NewCondVar(rvSlot->isPresentLock); rvSlot->isPresentThread = NULL; rvSlot->lastTokenPingState = nssSlotLastPingState_Reset; return rvSlot; } NSSToken * nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) { NSSToken *rvToken; NSSArena *arena; /* Don't create a token object for a disabled slot */ if (nss3slot->disabled) { PORT_SetError(SEC_ERROR_NO_TOKEN); return NULL; } arena = nssArena_Create(); if (!arena) { return NULL; } rvToken = nss_ZNEW(arena, NSSToken); if (!rvToken) { nssArena_Destroy(arena); return NULL; } rvToken->base.refCount = 1; rvToken->base.lock = PZ_NewLock(nssILockOther); if (!rvToken->base.lock) { nssArena_Destroy(arena); return NULL; } rvToken->base.arena = arena; rvToken->pk11slot = PK11_ReferenceSlot(nss3slot); rvToken->epv = nss3slot->functionList; rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena, nss3slot->session, nss3slot->sessionLock, nss3slot->defRWSession); #if 0 /* we should do this instead of blindly continuing. */ if (!rvToken->defaultSession) { PORT_SetError(SEC_ERROR_NO_TOKEN); goto loser; } #endif if (!PK11_IsInternal(nss3slot) && PK11_IsHW(nss3slot)) { rvToken->cache = nssTokenObjectCache_Create(rvToken, PR_TRUE, PR_TRUE, PR_TRUE); if (!rvToken->cache) goto loser; } rvToken->trustDomain = td; /* Grab the token name from the PKCS#11 fixed-length buffer */ rvToken->base.name = nssUTF8_Duplicate(nss3slot->token_name, td->arena); rvToken->slot = nssSlot_CreateFromPK11SlotInfo(td, nss3slot); if (!rvToken->slot) { goto loser; } if (rvToken->defaultSession) rvToken->defaultSession->slot = rvToken->slot; return rvToken; loser: PZ_DestroyLock(rvToken->base.lock); nssArena_Destroy(arena); return NULL; } NSS_IMPLEMENT void nssToken_UpdateName(NSSToken *token) { if (!token) { return; } token->base.name = nssUTF8_Duplicate(token->pk11slot->token_name, token->base.arena); } NSS_IMPLEMENT PRBool nssSlot_IsPermanent(NSSSlot *slot) { return slot->pk11slot->isPerm; } NSS_IMPLEMENT PRBool nssSlot_IsFriendly(NSSSlot *slot) { return PK11_IsFriendly(slot->pk11slot); } NSS_IMPLEMENT PRStatus nssToken_Refresh(NSSToken *token) { PK11SlotInfo *nss3slot; if (!token) { return PR_SUCCESS; } nss3slot = token->pk11slot; token->defaultSession = nssSession_ImportNSS3Session(token->slot->base.arena, nss3slot->session, nss3slot->sessionLock, nss3slot->defRWSession); return token->defaultSession ? PR_SUCCESS : PR_FAILURE; } NSS_IMPLEMENT PRStatus nssToken_GetTrustOrder(NSSToken *tok) { PK11SlotInfo *slot; SECMODModule *module; slot = tok->pk11slot; module = PK11_GetModule(slot); return module->trustOrder; } NSS_IMPLEMENT PRBool nssSlot_IsLoggedIn(NSSSlot *slot) { if (!slot->pk11slot->needLogin) { return PR_TRUE; } return PK11_IsLoggedIn(slot->pk11slot, NULL); } NSSTrustDomain * nssToken_GetTrustDomain(NSSToken *token) { return token->trustDomain; } NSS_EXTERN PRStatus nssTrustDomain_RemoveTokenCertsFromCache( NSSTrustDomain *td, NSSToken *token); NSS_IMPLEMENT PRStatus nssToken_NotifyCertsNotVisible( NSSToken *tok) { return nssTrustDomain_RemoveTokenCertsFromCache(tok->trustDomain, tok); }