dev3hack.c (7432B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef PKIT_H 6 #include "pkit.h" 7 #endif /* PKIT_H */ 8 9 #ifndef DEVM_H 10 #include "devm.h" 11 #endif /* DEVM_H */ 12 13 #include "pki3hack.h" 14 #include "dev3hack.h" 15 #include "pkim.h" 16 17 #ifndef BASE_H 18 #include "base.h" 19 #endif /* BASE_H */ 20 21 #include "pk11func.h" 22 #include "secmodti.h" 23 #include "secerr.h" 24 25 NSS_IMPLEMENT nssSession * 26 nssSession_ImportNSS3Session(NSSArena *arenaOpt, 27 CK_SESSION_HANDLE session, 28 PZLock *lock, PRBool rw) 29 { 30 nssSession *rvSession = NULL; 31 if (session != CK_INVALID_HANDLE) { 32 rvSession = nss_ZNEW(arenaOpt, nssSession); 33 if (rvSession) { 34 rvSession->handle = session; 35 rvSession->lock = lock; 36 rvSession->ownLock = PR_FALSE; 37 rvSession->isRW = rw; 38 } 39 } 40 return rvSession; 41 } 42 43 NSS_IMPLEMENT nssSession * 44 nssSlot_CreateSession( 45 NSSSlot *slot, 46 NSSArena *arenaOpt, 47 PRBool readWrite) 48 { 49 nssSession *rvSession; 50 51 if (!readWrite) { 52 /* nss3hack version only returns rw swssions */ 53 return NULL; 54 } 55 rvSession = nss_ZNEW(arenaOpt, nssSession); 56 if (!rvSession) { 57 return (nssSession *)NULL; 58 } 59 60 rvSession->handle = PK11_GetRWSession(slot->pk11slot); 61 if (rvSession->handle == CK_INVALID_HANDLE) { 62 nss_ZFreeIf(rvSession); 63 return NULL; 64 } 65 rvSession->isRW = PR_TRUE; 66 rvSession->slot = slot; 67 /* 68 * The session doesn't need its own lock. Here's why. 69 * 1. If we are reusing the default RW session of the slot, 70 * the slot lock is already locked to protect the session. 71 * 2. If the module is not thread safe, the slot (or rather 72 * module) lock is already locked. 73 * 3. If the module is thread safe and we are using a new 74 * session, no higher-level lock has been locked and we 75 * would need a lock for the new session. However, the 76 * current usage of the session is that it is always 77 * used and destroyed within the same function and never 78 * shared with another thread. 79 * So the session is either already protected by another 80 * lock or only used by one thread. 81 */ 82 rvSession->lock = NULL; 83 rvSession->ownLock = PR_FALSE; 84 return rvSession; 85 } 86 87 NSS_IMPLEMENT PRStatus 88 nssSession_Destroy(nssSession *s) 89 { 90 PRStatus rv = PR_SUCCESS; 91 if (s) { 92 if (s->isRW) { 93 PK11_RestoreROSession(s->slot->pk11slot, s->handle); 94 } 95 rv = nss_ZFreeIf(s); 96 } 97 return rv; 98 } 99 100 static NSSSlot * 101 nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) 102 { 103 NSSSlot *rvSlot; 104 NSSArena *arena; 105 arena = nssArena_Create(); 106 if (!arena) { 107 return NULL; 108 } 109 rvSlot = nss_ZNEW(arena, NSSSlot); 110 if (!rvSlot) { 111 nssArena_Destroy(arena); 112 return NULL; 113 } 114 rvSlot->base.refCount = 1; 115 rvSlot->base.lock = PZ_NewLock(nssILockOther); 116 rvSlot->base.arena = arena; 117 rvSlot->pk11slot = PK11_ReferenceSlot(nss3slot); 118 rvSlot->epv = nss3slot->functionList; 119 rvSlot->slotID = nss3slot->slotID; 120 /* Grab the slot name from the PKCS#11 fixed-length buffer */ 121 rvSlot->base.name = nssUTF8_Duplicate(nss3slot->slot_name, td->arena); 122 rvSlot->lock = (nss3slot->isThreadSafe) ? NULL : nss3slot->sessionLock; 123 rvSlot->isPresentLock = PZ_NewLock(nssiLockOther); 124 rvSlot->isPresentCondition = PR_NewCondVar(rvSlot->isPresentLock); 125 rvSlot->isPresentThread = NULL; 126 rvSlot->lastTokenPingState = nssSlotLastPingState_Reset; 127 return rvSlot; 128 } 129 130 NSSToken * 131 nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) 132 { 133 NSSToken *rvToken; 134 NSSArena *arena; 135 136 /* Don't create a token object for a disabled slot */ 137 if (nss3slot->disabled) { 138 PORT_SetError(SEC_ERROR_NO_TOKEN); 139 return NULL; 140 } 141 arena = nssArena_Create(); 142 if (!arena) { 143 return NULL; 144 } 145 rvToken = nss_ZNEW(arena, NSSToken); 146 if (!rvToken) { 147 nssArena_Destroy(arena); 148 return NULL; 149 } 150 rvToken->base.refCount = 1; 151 rvToken->base.lock = PZ_NewLock(nssILockOther); 152 if (!rvToken->base.lock) { 153 nssArena_Destroy(arena); 154 return NULL; 155 } 156 rvToken->base.arena = arena; 157 rvToken->pk11slot = PK11_ReferenceSlot(nss3slot); 158 rvToken->epv = nss3slot->functionList; 159 rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena, 160 nss3slot->session, 161 nss3slot->sessionLock, 162 nss3slot->defRWSession); 163 #if 0 /* we should do this instead of blindly continuing. */ 164 if (!rvToken->defaultSession) { 165 PORT_SetError(SEC_ERROR_NO_TOKEN); 166 goto loser; 167 } 168 #endif 169 if (!PK11_IsInternal(nss3slot) && PK11_IsHW(nss3slot)) { 170 rvToken->cache = nssTokenObjectCache_Create(rvToken, 171 PR_TRUE, PR_TRUE, PR_TRUE); 172 if (!rvToken->cache) 173 goto loser; 174 } 175 rvToken->trustDomain = td; 176 /* Grab the token name from the PKCS#11 fixed-length buffer */ 177 rvToken->base.name = nssUTF8_Duplicate(nss3slot->token_name, td->arena); 178 rvToken->slot = nssSlot_CreateFromPK11SlotInfo(td, nss3slot); 179 if (!rvToken->slot) { 180 goto loser; 181 } 182 if (rvToken->defaultSession) 183 rvToken->defaultSession->slot = rvToken->slot; 184 return rvToken; 185 loser: 186 PZ_DestroyLock(rvToken->base.lock); 187 nssArena_Destroy(arena); 188 return NULL; 189 } 190 191 NSS_IMPLEMENT void 192 nssToken_UpdateName(NSSToken *token) 193 { 194 if (!token) { 195 return; 196 } 197 token->base.name = nssUTF8_Duplicate(token->pk11slot->token_name, token->base.arena); 198 } 199 200 NSS_IMPLEMENT PRBool 201 nssSlot_IsPermanent(NSSSlot *slot) 202 { 203 return slot->pk11slot->isPerm; 204 } 205 206 NSS_IMPLEMENT PRBool 207 nssSlot_IsFriendly(NSSSlot *slot) 208 { 209 return PK11_IsFriendly(slot->pk11slot); 210 } 211 212 NSS_IMPLEMENT PRStatus 213 nssToken_Refresh(NSSToken *token) 214 { 215 PK11SlotInfo *nss3slot; 216 217 if (!token) { 218 return PR_SUCCESS; 219 } 220 nss3slot = token->pk11slot; 221 token->defaultSession = 222 nssSession_ImportNSS3Session(token->slot->base.arena, 223 nss3slot->session, 224 nss3slot->sessionLock, 225 nss3slot->defRWSession); 226 return token->defaultSession ? PR_SUCCESS : PR_FAILURE; 227 } 228 229 NSS_IMPLEMENT PRStatus 230 nssToken_GetTrustOrder(NSSToken *tok) 231 { 232 PK11SlotInfo *slot; 233 SECMODModule *module; 234 slot = tok->pk11slot; 235 module = PK11_GetModule(slot); 236 return module->trustOrder; 237 } 238 239 NSS_IMPLEMENT PRBool 240 nssSlot_IsLoggedIn(NSSSlot *slot) 241 { 242 if (!slot->pk11slot->needLogin) { 243 return PR_TRUE; 244 } 245 return PK11_IsLoggedIn(slot->pk11slot, NULL); 246 } 247 248 NSSTrustDomain * 249 nssToken_GetTrustDomain(NSSToken *token) 250 { 251 return token->trustDomain; 252 } 253 254 NSS_EXTERN PRStatus 255 nssTrustDomain_RemoveTokenCertsFromCache( 256 NSSTrustDomain *td, 257 NSSToken *token); 258 259 NSS_IMPLEMENT PRStatus 260 nssToken_NotifyCertsNotVisible( 261 NSSToken *tok) 262 { 263 return nssTrustDomain_RemoveTokenCertsFromCache(tok->trustDomain, tok); 264 }