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 /*
6  * instance.c
7  *
8  * This file implements the NSSCKFWInstance type and methods.
9  */
10 
11 #ifndef CK_T
12 #include "ck.h"
13 #endif /* CK_T */
14 
15 /*
16  * NSSCKFWInstance
17  *
18  *  -- create/destroy --
19  *  nssCKFWInstance_Create
20  *  nssCKFWInstance_Destroy
21  *
22  *  -- public accessors --
23  *  NSSCKFWInstance_GetMDInstance
24  *  NSSCKFWInstance_GetArena
25  *  NSSCKFWInstance_MayCreatePthreads
26  *  NSSCKFWInstance_CreateMutex
27  *  NSSCKFWInstance_GetConfigurationData
28  *  NSSCKFWInstance_GetInitArgs
29  *  NSSCKFWInstance_DestroySessionHandle
30  *  NSSCKFWInstance_FindSessionHandle
31  *
32  *  -- implement public accessors --
33  *  nssCKFWInstance_GetMDInstance
34  *  nssCKFWInstance_GetArena
35  *  nssCKFWInstance_MayCreatePthreads
36  *  nssCKFWInstance_CreateMutex
37  *  nssCKFWInstance_GetConfigurationData
38  *  nssCKFWInstance_GetInitArgs
39  *  nssCKFWInstance_DestroySessionHandle
40  *  nssCKFWInstance_FindSessionHandle
41  *
42  *  -- private accessors --
43  *  nssCKFWInstance_CreateSessionHandle
44  *  nssCKFWInstance_ResolveSessionHandle
45  *  nssCKFWInstance_CreateObjectHandle
46  *  nssCKFWInstance_ResolveObjectHandle
47  *  nssCKFWInstance_DestroyObjectHandle
48  *
49  *  -- module fronts --
50  *  nssCKFWInstance_GetNSlots
51  *  nssCKFWInstance_GetCryptokiVersion
52  *  nssCKFWInstance_GetManufacturerID
53  *  nssCKFWInstance_GetFlags
54  *  nssCKFWInstance_GetLibraryDescription
55  *  nssCKFWInstance_GetLibraryVersion
56  *  nssCKFWInstance_GetModuleHandlesSessionObjects
57  *  nssCKFWInstance_GetSlots
58  *  nssCKFWInstance_WaitForSlotEvent
59  *
60  *  -- debugging versions only --
61  *  nssCKFWInstance_verifyPointer
62  */
63 
64 struct NSSCKFWInstanceStr {
65     NSSCKFWMutex *mutex;
66     NSSArena *arena;
67     NSSCKMDInstance *mdInstance;
68     CK_C_INITIALIZE_ARGS_PTR pInitArgs;
69     CK_C_INITIALIZE_ARGS initArgs;
70     CryptokiLockingState LockingState;
71     CK_BBOOL mayCreatePthreads;
72     NSSUTF8 *configurationData;
73     CK_ULONG nSlots;
74     NSSCKFWSlot **fwSlotList;
75     NSSCKMDSlot **mdSlotList;
76     CK_BBOOL moduleHandlesSessionObjects;
77 
78     /*
79      * Everything above is set at creation time, and then not modified.
80      * The invariants the mutex protects are:
81      *
82      *  1) Each of the cached descriptions (versions, etc.) are in an
83      *     internally consistant state.
84      *
85      *  2) The session handle hashes and count are consistant
86      *
87      *  3) The object handle hashes and count are consistant.
88      *
89      * I could use multiple locks, but let's wait to see if that's
90      * really necessary.
91      *
92      * Note that the calls accessing the cached descriptions will
93      * call the NSSCKMDInstance methods with the mutex locked.  Those
94      * methods may then call the public NSSCKFWInstance routines.
95      * Those public routines only access the constant data above, so
96      * there's no problem.  But be careful if you add to this object;
97      * mutexes are in general not reentrant, so don't create deadlock
98      * situations.
99      */
100 
101     CK_VERSION cryptokiVersion;
102     NSSUTF8 *manufacturerID;
103     NSSUTF8 *libraryDescription;
104     CK_VERSION libraryVersion;
105 
106     CK_ULONG lastSessionHandle;
107     nssCKFWHash *sessionHandleHash;
108 
109     CK_ULONG lastObjectHandle;
110     nssCKFWHash *objectHandleHash;
111 };
112 
113 #ifdef DEBUG
114 /*
115  * But first, the pointer-tracking stuff.
116  *
117  * NOTE: the pointer-tracking support in NSS/base currently relies
118  * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
119  * locking, which is tied into the runtime.  We need a pointer-tracker
120  * implementation that uses the locks supplied through C_Initialize.
121  * That support, however, can be filled in later.  So for now, I'll
122  * just do this routines as no-ops.
123  */
124 
125 static CK_RV
instance_add_pointer(const NSSCKFWInstance * fwInstance)126 instance_add_pointer(
127     const NSSCKFWInstance *fwInstance)
128 {
129     return CKR_OK;
130 }
131 
132 static CK_RV
instance_remove_pointer(const NSSCKFWInstance * fwInstance)133 instance_remove_pointer(
134     const NSSCKFWInstance *fwInstance)
135 {
136     return CKR_OK;
137 }
138 
139 NSS_IMPLEMENT CK_RV
nssCKFWInstance_verifyPointer(const NSSCKFWInstance * fwInstance)140 nssCKFWInstance_verifyPointer(
141     const NSSCKFWInstance *fwInstance)
142 {
143     return CKR_OK;
144 }
145 
146 #endif /* DEBUG */
147 
148 /*
149  * nssCKFWInstance_Create
150  *
151  */
152 NSS_IMPLEMENT NSSCKFWInstance *
nssCKFWInstance_Create(CK_C_INITIALIZE_ARGS_PTR pInitArgs,CryptokiLockingState LockingState,NSSCKMDInstance * mdInstance,CK_RV * pError)153 nssCKFWInstance_Create(
154     CK_C_INITIALIZE_ARGS_PTR pInitArgs,
155     CryptokiLockingState LockingState,
156     NSSCKMDInstance *mdInstance,
157     CK_RV *pError)
158 {
159     NSSCKFWInstance *fwInstance;
160     NSSArena *arena = (NSSArena *)NULL;
161     CK_ULONG i;
162     CK_BBOOL called_Initialize = CK_FALSE;
163 
164 #ifdef NSSDEBUG
165     if ((CK_RV)NULL == pError) {
166         return (NSSCKFWInstance *)NULL;
167     }
168 
169     if (!mdInstance) {
170         *pError = CKR_ARGUMENTS_BAD;
171         return (NSSCKFWInstance *)NULL;
172     }
173 #endif /* NSSDEBUG */
174 
175     arena = NSSArena_Create();
176     if (!arena) {
177         *pError = CKR_HOST_MEMORY;
178         return (NSSCKFWInstance *)NULL;
179     }
180 
181     fwInstance = nss_ZNEW(arena, NSSCKFWInstance);
182     if (!fwInstance) {
183         goto nomem;
184     }
185 
186     fwInstance->arena = arena;
187     fwInstance->mdInstance = mdInstance;
188 
189     fwInstance->LockingState = LockingState;
190     if ((CK_C_INITIALIZE_ARGS_PTR)NULL != pInitArgs) {
191         fwInstance->initArgs = *pInitArgs;
192         fwInstance->pInitArgs = &fwInstance->initArgs;
193         if (pInitArgs->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) {
194             fwInstance->mayCreatePthreads = CK_FALSE;
195         } else {
196             fwInstance->mayCreatePthreads = CK_TRUE;
197         }
198         fwInstance->configurationData = (NSSUTF8 *)(pInitArgs->pReserved);
199     } else {
200         fwInstance->mayCreatePthreads = CK_TRUE;
201     }
202 
203     fwInstance->mutex = nssCKFWMutex_Create(pInitArgs, LockingState, arena,
204                                             pError);
205     if (!fwInstance->mutex) {
206         if (CKR_OK == *pError) {
207             *pError = CKR_GENERAL_ERROR;
208         }
209         goto loser;
210     }
211 
212     if (mdInstance->Initialize) {
213         *pError = mdInstance->Initialize(mdInstance, fwInstance, fwInstance->configurationData);
214         if (CKR_OK != *pError) {
215             goto loser;
216         }
217 
218         called_Initialize = CK_TRUE;
219     }
220 
221     if (mdInstance->ModuleHandlesSessionObjects) {
222         fwInstance->moduleHandlesSessionObjects =
223             mdInstance->ModuleHandlesSessionObjects(mdInstance, fwInstance);
224     } else {
225         fwInstance->moduleHandlesSessionObjects = CK_FALSE;
226     }
227 
228     if (!mdInstance->GetNSlots) {
229         /* That routine is required */
230         *pError = CKR_GENERAL_ERROR;
231         goto loser;
232     }
233 
234     fwInstance->nSlots = mdInstance->GetNSlots(mdInstance, fwInstance, pError);
235     if ((CK_ULONG)0 == fwInstance->nSlots) {
236         if (CKR_OK == *pError) {
237             /* Zero is not a legitimate answer */
238             *pError = CKR_GENERAL_ERROR;
239         }
240         goto loser;
241     }
242 
243     fwInstance->fwSlotList = nss_ZNEWARRAY(arena, NSSCKFWSlot *, fwInstance->nSlots);
244     if ((NSSCKFWSlot **)NULL == fwInstance->fwSlotList) {
245         goto nomem;
246     }
247 
248     fwInstance->mdSlotList = nss_ZNEWARRAY(arena, NSSCKMDSlot *, fwInstance->nSlots);
249     if ((NSSCKMDSlot **)NULL == fwInstance->mdSlotList) {
250         goto nomem;
251     }
252 
253     fwInstance->sessionHandleHash = nssCKFWHash_Create(fwInstance,
254                                                        fwInstance->arena, pError);
255     if (!fwInstance->sessionHandleHash) {
256         goto loser;
257     }
258 
259     fwInstance->objectHandleHash = nssCKFWHash_Create(fwInstance,
260                                                       fwInstance->arena, pError);
261     if (!fwInstance->objectHandleHash) {
262         goto loser;
263     }
264 
265     if (!mdInstance->GetSlots) {
266         /* That routine is required */
267         *pError = CKR_GENERAL_ERROR;
268         goto loser;
269     }
270 
271     *pError = mdInstance->GetSlots(mdInstance, fwInstance, fwInstance->mdSlotList);
272     if (CKR_OK != *pError) {
273         goto loser;
274     }
275 
276     for (i = 0; i < fwInstance->nSlots; i++) {
277         NSSCKMDSlot *mdSlot = fwInstance->mdSlotList[i];
278 
279         if (!mdSlot) {
280             *pError = CKR_GENERAL_ERROR;
281             goto loser;
282         }
283 
284         fwInstance->fwSlotList[i] = nssCKFWSlot_Create(fwInstance, mdSlot, i, pError);
285         if (CKR_OK != *pError) {
286             CK_ULONG j;
287 
288             for (j = 0; j < i; j++) {
289                 (void)nssCKFWSlot_Destroy(fwInstance->fwSlotList[j]);
290             }
291 
292             for (j = i; j < fwInstance->nSlots; j++) {
293                 NSSCKMDSlot *mds = fwInstance->mdSlotList[j];
294                 if (mds->Destroy) {
295                     mds->Destroy(mds, (NSSCKFWSlot *)NULL, mdInstance, fwInstance);
296                 }
297             }
298 
299             goto loser;
300         }
301     }
302 
303 #ifdef DEBUG
304     *pError = instance_add_pointer(fwInstance);
305     if (CKR_OK != *pError) {
306         for (i = 0; i < fwInstance->nSlots; i++) {
307             (void)nssCKFWSlot_Destroy(fwInstance->fwSlotList[i]);
308         }
309 
310         goto loser;
311     }
312 #endif /* DEBUG */
313 
314     *pError = CKR_OK;
315     return fwInstance;
316 
317 nomem:
318     *pError = CKR_HOST_MEMORY;
319 /*FALLTHROUGH*/
320 loser:
321 
322     if (CK_TRUE == called_Initialize) {
323         if (mdInstance->Finalize) {
324             mdInstance->Finalize(mdInstance, fwInstance);
325         }
326     }
327 
328     if (fwInstance && fwInstance->mutex) {
329         nssCKFWMutex_Destroy(fwInstance->mutex);
330     }
331 
332     if (arena) {
333         (void)NSSArena_Destroy(arena);
334     }
335     return (NSSCKFWInstance *)NULL;
336 }
337 
338 /*
339  * nssCKFWInstance_Destroy
340  *
341  */
342 NSS_IMPLEMENT CK_RV
nssCKFWInstance_Destroy(NSSCKFWInstance * fwInstance)343 nssCKFWInstance_Destroy(
344     NSSCKFWInstance *fwInstance)
345 {
346 #ifdef NSSDEBUG
347     CK_RV error = CKR_OK;
348 #endif /* NSSDEBUG */
349     CK_ULONG i;
350 
351 #ifdef NSSDEBUG
352     error = nssCKFWInstance_verifyPointer(fwInstance);
353     if (CKR_OK != error) {
354         return error;
355     }
356 #endif /* NSSDEBUG */
357 
358     nssCKFWMutex_Destroy(fwInstance->mutex);
359 
360     for (i = 0; i < fwInstance->nSlots; i++) {
361         (void)nssCKFWSlot_Destroy(fwInstance->fwSlotList[i]);
362     }
363 
364     if (fwInstance->mdInstance->Finalize) {
365         fwInstance->mdInstance->Finalize(fwInstance->mdInstance, fwInstance);
366     }
367 
368     if (fwInstance->sessionHandleHash) {
369         nssCKFWHash_Destroy(fwInstance->sessionHandleHash);
370     }
371 
372     if (fwInstance->objectHandleHash) {
373         nssCKFWHash_Destroy(fwInstance->objectHandleHash);
374     }
375 
376 #ifdef DEBUG
377     (void)instance_remove_pointer(fwInstance);
378 #endif /* DEBUG */
379 
380     (void)NSSArena_Destroy(fwInstance->arena);
381     return CKR_OK;
382 }
383 
384 /*
385  * nssCKFWInstance_GetMDInstance
386  *
387  */
388 NSS_IMPLEMENT NSSCKMDInstance *
nssCKFWInstance_GetMDInstance(NSSCKFWInstance * fwInstance)389 nssCKFWInstance_GetMDInstance(
390     NSSCKFWInstance *fwInstance)
391 {
392 #ifdef NSSDEBUG
393     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
394         return (NSSCKMDInstance *)NULL;
395     }
396 #endif /* NSSDEBUG */
397 
398     return fwInstance->mdInstance;
399 }
400 
401 /*
402  * nssCKFWInstance_GetArena
403  *
404  */
405 NSS_IMPLEMENT NSSArena *
nssCKFWInstance_GetArena(NSSCKFWInstance * fwInstance,CK_RV * pError)406 nssCKFWInstance_GetArena(
407     NSSCKFWInstance *fwInstance,
408     CK_RV *pError)
409 {
410 #ifdef NSSDEBUG
411     if (!pError) {
412         return (NSSArena *)NULL;
413     }
414 
415     *pError = nssCKFWInstance_verifyPointer(fwInstance);
416     if (CKR_OK != *pError) {
417         return (NSSArena *)NULL;
418     }
419 #endif /* NSSDEBUG */
420 
421     *pError = CKR_OK;
422     return fwInstance->arena;
423 }
424 
425 /*
426  * nssCKFWInstance_MayCreatePthreads
427  *
428  */
429 NSS_IMPLEMENT CK_BBOOL
nssCKFWInstance_MayCreatePthreads(NSSCKFWInstance * fwInstance)430 nssCKFWInstance_MayCreatePthreads(
431     NSSCKFWInstance *fwInstance)
432 {
433 #ifdef NSSDEBUG
434     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
435         return CK_FALSE;
436     }
437 #endif /* NSSDEBUG */
438 
439     return fwInstance->mayCreatePthreads;
440 }
441 
442 /*
443  * nssCKFWInstance_CreateMutex
444  *
445  */
446 NSS_IMPLEMENT NSSCKFWMutex *
nssCKFWInstance_CreateMutex(NSSCKFWInstance * fwInstance,NSSArena * arena,CK_RV * pError)447 nssCKFWInstance_CreateMutex(
448     NSSCKFWInstance *fwInstance,
449     NSSArena *arena,
450     CK_RV *pError)
451 {
452     NSSCKFWMutex *mutex;
453 
454 #ifdef NSSDEBUG
455     if (!pError) {
456         return (NSSCKFWMutex *)NULL;
457     }
458 
459     *pError = nssCKFWInstance_verifyPointer(fwInstance);
460     if (CKR_OK != *pError) {
461         return (NSSCKFWMutex *)NULL;
462     }
463 #endif /* NSSDEBUG */
464 
465     mutex = nssCKFWMutex_Create(fwInstance->pInitArgs, fwInstance->LockingState,
466                                 arena, pError);
467     if (!mutex) {
468         if (CKR_OK == *pError) {
469             *pError = CKR_GENERAL_ERROR;
470         }
471 
472         return (NSSCKFWMutex *)NULL;
473     }
474 
475     return mutex;
476 }
477 
478 /*
479  * nssCKFWInstance_GetConfigurationData
480  *
481  */
482 NSS_IMPLEMENT NSSUTF8 *
nssCKFWInstance_GetConfigurationData(NSSCKFWInstance * fwInstance)483 nssCKFWInstance_GetConfigurationData(
484     NSSCKFWInstance *fwInstance)
485 {
486 #ifdef NSSDEBUG
487     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
488         return (NSSUTF8 *)NULL;
489     }
490 #endif /* NSSDEBUG */
491 
492     return fwInstance->configurationData;
493 }
494 
495 /*
496  * nssCKFWInstance_GetInitArgs
497  *
498  */
499 CK_C_INITIALIZE_ARGS_PTR
nssCKFWInstance_GetInitArgs(NSSCKFWInstance * fwInstance)500 nssCKFWInstance_GetInitArgs(
501     NSSCKFWInstance *fwInstance)
502 {
503 #ifdef NSSDEBUG
504     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
505         return (CK_C_INITIALIZE_ARGS_PTR)NULL;
506     }
507 #endif /* NSSDEBUG */
508 
509     return fwInstance->pInitArgs;
510 }
511 
512 /*
513  * nssCKFWInstance_CreateSessionHandle
514  *
515  */
516 NSS_IMPLEMENT CK_SESSION_HANDLE
nssCKFWInstance_CreateSessionHandle(NSSCKFWInstance * fwInstance,NSSCKFWSession * fwSession,CK_RV * pError)517 nssCKFWInstance_CreateSessionHandle(
518     NSSCKFWInstance *fwInstance,
519     NSSCKFWSession *fwSession,
520     CK_RV *pError)
521 {
522     CK_SESSION_HANDLE hSession;
523 
524 #ifdef NSSDEBUG
525     if (!pError) {
526         return (CK_SESSION_HANDLE)0;
527     }
528 
529     *pError = nssCKFWInstance_verifyPointer(fwInstance);
530     if (CKR_OK != *pError) {
531         return (CK_SESSION_HANDLE)0;
532     }
533 #endif /* NSSDEBUG */
534 
535     *pError = nssCKFWMutex_Lock(fwInstance->mutex);
536     if (CKR_OK != *pError) {
537         return (CK_SESSION_HANDLE)0;
538     }
539 
540     hSession = ++(fwInstance->lastSessionHandle);
541 
542     /* Alan would say I should unlock for this call. */
543 
544     *pError = nssCKFWSession_SetHandle(fwSession, hSession);
545     if (CKR_OK != *pError) {
546         goto done;
547     }
548 
549     *pError = nssCKFWHash_Add(fwInstance->sessionHandleHash,
550                               (const void *)hSession, (const void *)fwSession);
551     if (CKR_OK != *pError) {
552         hSession = (CK_SESSION_HANDLE)0;
553         goto done;
554     }
555 
556 done:
557     nssCKFWMutex_Unlock(fwInstance->mutex);
558     return hSession;
559 }
560 
561 /*
562  * nssCKFWInstance_ResolveSessionHandle
563  *
564  */
565 NSS_IMPLEMENT NSSCKFWSession *
nssCKFWInstance_ResolveSessionHandle(NSSCKFWInstance * fwInstance,CK_SESSION_HANDLE hSession)566 nssCKFWInstance_ResolveSessionHandle(
567     NSSCKFWInstance *fwInstance,
568     CK_SESSION_HANDLE hSession)
569 {
570     NSSCKFWSession *fwSession;
571 
572 #ifdef NSSDEBUG
573     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
574         return (NSSCKFWSession *)NULL;
575     }
576 #endif /* NSSDEBUG */
577 
578     if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
579         return (NSSCKFWSession *)NULL;
580     }
581 
582     fwSession = (NSSCKFWSession *)nssCKFWHash_Lookup(
583         fwInstance->sessionHandleHash, (const void *)hSession);
584 
585     /* Assert(hSession == nssCKFWSession_GetHandle(fwSession)) */
586 
587     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
588 
589     return fwSession;
590 }
591 
592 /*
593  * nssCKFWInstance_DestroySessionHandle
594  *
595  */
596 NSS_IMPLEMENT void
nssCKFWInstance_DestroySessionHandle(NSSCKFWInstance * fwInstance,CK_SESSION_HANDLE hSession)597 nssCKFWInstance_DestroySessionHandle(
598     NSSCKFWInstance *fwInstance,
599     CK_SESSION_HANDLE hSession)
600 {
601     NSSCKFWSession *fwSession;
602 
603 #ifdef NSSDEBUG
604     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
605         return;
606     }
607 #endif /* NSSDEBUG */
608 
609     if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
610         return;
611     }
612 
613     fwSession = (NSSCKFWSession *)nssCKFWHash_Lookup(
614         fwInstance->sessionHandleHash, (const void *)hSession);
615     if (fwSession) {
616         nssCKFWHash_Remove(fwInstance->sessionHandleHash, (const void *)hSession);
617         nssCKFWSession_SetHandle(fwSession, (CK_SESSION_HANDLE)0);
618     }
619 
620     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
621 
622     return;
623 }
624 
625 /*
626  * nssCKFWInstance_FindSessionHandle
627  *
628  */
629 NSS_IMPLEMENT CK_SESSION_HANDLE
nssCKFWInstance_FindSessionHandle(NSSCKFWInstance * fwInstance,NSSCKFWSession * fwSession)630 nssCKFWInstance_FindSessionHandle(
631     NSSCKFWInstance *fwInstance,
632     NSSCKFWSession *fwSession)
633 {
634 #ifdef NSSDEBUG
635     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
636         return (CK_SESSION_HANDLE)0;
637     }
638 
639     if (CKR_OK != nssCKFWSession_verifyPointer(fwSession)) {
640         return (CK_SESSION_HANDLE)0;
641     }
642 #endif /* NSSDEBUG */
643 
644     return nssCKFWSession_GetHandle(fwSession);
645     /* look it up and assert? */
646 }
647 
648 /*
649  * nssCKFWInstance_CreateObjectHandle
650  *
651  */
652 NSS_IMPLEMENT CK_OBJECT_HANDLE
nssCKFWInstance_CreateObjectHandle(NSSCKFWInstance * fwInstance,NSSCKFWObject * fwObject,CK_RV * pError)653 nssCKFWInstance_CreateObjectHandle(
654     NSSCKFWInstance *fwInstance,
655     NSSCKFWObject *fwObject,
656     CK_RV *pError)
657 {
658     CK_OBJECT_HANDLE hObject;
659 
660 #ifdef NSSDEBUG
661     if (!pError) {
662         return (CK_OBJECT_HANDLE)0;
663     }
664 
665     *pError = nssCKFWInstance_verifyPointer(fwInstance);
666     if (CKR_OK != *pError) {
667         return (CK_OBJECT_HANDLE)0;
668     }
669 #endif /* NSSDEBUG */
670 
671     *pError = nssCKFWMutex_Lock(fwInstance->mutex);
672     if (CKR_OK != *pError) {
673         return (CK_OBJECT_HANDLE)0;
674     }
675 
676     hObject = ++(fwInstance->lastObjectHandle);
677 
678     *pError = nssCKFWObject_SetHandle(fwObject, hObject);
679     if (CKR_OK != *pError) {
680         hObject = (CK_OBJECT_HANDLE)0;
681         goto done;
682     }
683 
684     *pError = nssCKFWHash_Add(fwInstance->objectHandleHash,
685                               (const void *)hObject, (const void *)fwObject);
686     if (CKR_OK != *pError) {
687         hObject = (CK_OBJECT_HANDLE)0;
688         goto done;
689     }
690 
691 done:
692     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
693     return hObject;
694 }
695 
696 /*
697  * nssCKFWInstance_ResolveObjectHandle
698  *
699  */
700 NSS_IMPLEMENT NSSCKFWObject *
nssCKFWInstance_ResolveObjectHandle(NSSCKFWInstance * fwInstance,CK_OBJECT_HANDLE hObject)701 nssCKFWInstance_ResolveObjectHandle(
702     NSSCKFWInstance *fwInstance,
703     CK_OBJECT_HANDLE hObject)
704 {
705     NSSCKFWObject *fwObject;
706 
707 #ifdef NSSDEBUG
708     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
709         return (NSSCKFWObject *)NULL;
710     }
711 #endif /* NSSDEBUG */
712 
713     if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
714         return (NSSCKFWObject *)NULL;
715     }
716 
717     fwObject = (NSSCKFWObject *)nssCKFWHash_Lookup(
718         fwInstance->objectHandleHash, (const void *)hObject);
719 
720     /* Assert(hObject == nssCKFWObject_GetHandle(fwObject)) */
721 
722     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
723     return fwObject;
724 }
725 
726 /*
727  * nssCKFWInstance_ReassignObjectHandle
728  *
729  */
730 NSS_IMPLEMENT CK_RV
nssCKFWInstance_ReassignObjectHandle(NSSCKFWInstance * fwInstance,CK_OBJECT_HANDLE hObject,NSSCKFWObject * fwObject)731 nssCKFWInstance_ReassignObjectHandle(
732     NSSCKFWInstance *fwInstance,
733     CK_OBJECT_HANDLE hObject,
734     NSSCKFWObject *fwObject)
735 {
736     CK_RV error = CKR_OK;
737     NSSCKFWObject *oldObject;
738 
739 #ifdef NSSDEBUG
740     error = nssCKFWInstance_verifyPointer(fwInstance);
741     if (CKR_OK != error) {
742         return error;
743     }
744 #endif /* NSSDEBUG */
745 
746     error = nssCKFWMutex_Lock(fwInstance->mutex);
747     if (CKR_OK != error) {
748         return error;
749     }
750 
751     oldObject = (NSSCKFWObject *)nssCKFWHash_Lookup(
752         fwInstance->objectHandleHash, (const void *)hObject);
753     if (oldObject) {
754         /* Assert(hObject == nssCKFWObject_GetHandle(oldObject) */
755         (void)nssCKFWObject_SetHandle(oldObject, (CK_SESSION_HANDLE)0);
756         nssCKFWHash_Remove(fwInstance->objectHandleHash, (const void *)hObject);
757     }
758 
759     error = nssCKFWObject_SetHandle(fwObject, hObject);
760     if (CKR_OK != error) {
761         goto done;
762     }
763     error = nssCKFWHash_Add(fwInstance->objectHandleHash,
764                             (const void *)hObject, (const void *)fwObject);
765 
766 done:
767     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
768     return error;
769 }
770 
771 /*
772  * nssCKFWInstance_DestroyObjectHandle
773  *
774  */
775 NSS_IMPLEMENT void
nssCKFWInstance_DestroyObjectHandle(NSSCKFWInstance * fwInstance,CK_OBJECT_HANDLE hObject)776 nssCKFWInstance_DestroyObjectHandle(
777     NSSCKFWInstance *fwInstance,
778     CK_OBJECT_HANDLE hObject)
779 {
780     NSSCKFWObject *fwObject;
781 
782 #ifdef NSSDEBUG
783     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
784         return;
785     }
786 #endif /* NSSDEBUG */
787 
788     if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
789         return;
790     }
791 
792     fwObject = (NSSCKFWObject *)nssCKFWHash_Lookup(
793         fwInstance->objectHandleHash, (const void *)hObject);
794     if (fwObject) {
795         /* Assert(hObject = nssCKFWObject_GetHandle(fwObject)) */
796         nssCKFWHash_Remove(fwInstance->objectHandleHash, (const void *)hObject);
797         (void)nssCKFWObject_SetHandle(fwObject, (CK_SESSION_HANDLE)0);
798     }
799 
800     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
801     return;
802 }
803 
804 /*
805  * nssCKFWInstance_FindObjectHandle
806  *
807  */
808 NSS_IMPLEMENT CK_OBJECT_HANDLE
nssCKFWInstance_FindObjectHandle(NSSCKFWInstance * fwInstance,NSSCKFWObject * fwObject)809 nssCKFWInstance_FindObjectHandle(
810     NSSCKFWInstance *fwInstance,
811     NSSCKFWObject *fwObject)
812 {
813 #ifdef NSSDEBUG
814     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
815         return (CK_OBJECT_HANDLE)0;
816     }
817 
818     if (CKR_OK != nssCKFWObject_verifyPointer(fwObject)) {
819         return (CK_OBJECT_HANDLE)0;
820     }
821 #endif /* NSSDEBUG */
822 
823     return nssCKFWObject_GetHandle(fwObject);
824 }
825 
826 /*
827  * nssCKFWInstance_GetNSlots
828  *
829  */
830 NSS_IMPLEMENT CK_ULONG
nssCKFWInstance_GetNSlots(NSSCKFWInstance * fwInstance,CK_RV * pError)831 nssCKFWInstance_GetNSlots(
832     NSSCKFWInstance *fwInstance,
833     CK_RV *pError)
834 {
835 #ifdef NSSDEBUG
836     if (!pError) {
837         return (CK_ULONG)0;
838     }
839 
840     *pError = nssCKFWInstance_verifyPointer(fwInstance);
841     if (CKR_OK != *pError) {
842         return (CK_ULONG)0;
843     }
844 #endif /* NSSDEBUG */
845 
846     *pError = CKR_OK;
847     return fwInstance->nSlots;
848 }
849 
850 /*
851  * nssCKFWInstance_GetCryptokiVersion
852  *
853  */
854 NSS_IMPLEMENT CK_VERSION
nssCKFWInstance_GetCryptokiVersion(NSSCKFWInstance * fwInstance)855 nssCKFWInstance_GetCryptokiVersion(
856     NSSCKFWInstance *fwInstance)
857 {
858     CK_VERSION rv;
859 
860 #ifdef NSSDEBUG
861     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
862         rv.major = rv.minor = 0;
863         return rv;
864     }
865 #endif /* NSSDEBUG */
866 
867     if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
868         rv.major = rv.minor = 0;
869         return rv;
870     }
871 
872     if ((0 != fwInstance->cryptokiVersion.major) ||
873         (0 != fwInstance->cryptokiVersion.minor)) {
874         rv = fwInstance->cryptokiVersion;
875         goto done;
876     }
877 
878     if (fwInstance->mdInstance->GetCryptokiVersion) {
879         fwInstance->cryptokiVersion = fwInstance->mdInstance->GetCryptokiVersion(
880             fwInstance->mdInstance, fwInstance);
881     } else {
882         fwInstance->cryptokiVersion.major = 2;
883         fwInstance->cryptokiVersion.minor = 1;
884     }
885 
886     rv = fwInstance->cryptokiVersion;
887 
888 done:
889     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
890     return rv;
891 }
892 
893 /*
894  * nssCKFWInstance_GetManufacturerID
895  *
896  */
897 NSS_IMPLEMENT CK_RV
nssCKFWInstance_GetManufacturerID(NSSCKFWInstance * fwInstance,CK_CHAR manufacturerID[32])898 nssCKFWInstance_GetManufacturerID(
899     NSSCKFWInstance *fwInstance,
900     CK_CHAR manufacturerID[32])
901 {
902     CK_RV error = CKR_OK;
903 
904 #ifdef NSSDEBUG
905     if ((CK_CHAR_PTR)NULL == manufacturerID) {
906         return CKR_ARGUMENTS_BAD;
907     }
908 
909     error = nssCKFWInstance_verifyPointer(fwInstance);
910     if (CKR_OK != error) {
911         return error;
912     }
913 #endif /* NSSDEBUG */
914 
915     error = nssCKFWMutex_Lock(fwInstance->mutex);
916     if (CKR_OK != error) {
917         return error;
918     }
919 
920     if (!fwInstance->manufacturerID) {
921         if (fwInstance->mdInstance->GetManufacturerID) {
922             fwInstance->manufacturerID = fwInstance->mdInstance->GetManufacturerID(
923                 fwInstance->mdInstance, fwInstance, &error);
924             if ((!fwInstance->manufacturerID) && (CKR_OK != error)) {
925                 goto done;
926             }
927         } else {
928             fwInstance->manufacturerID = (NSSUTF8 *)"";
929         }
930     }
931 
932     (void)nssUTF8_CopyIntoFixedBuffer(fwInstance->manufacturerID, (char *)manufacturerID, 32, ' ');
933     error = CKR_OK;
934 
935 done:
936     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
937     return error;
938 }
939 
940 /*
941  * nssCKFWInstance_GetFlags
942  *
943  */
944 NSS_IMPLEMENT CK_ULONG
nssCKFWInstance_GetFlags(NSSCKFWInstance * fwInstance)945 nssCKFWInstance_GetFlags(
946     NSSCKFWInstance *fwInstance)
947 {
948 #ifdef NSSDEBUG
949     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
950         return (CK_ULONG)0;
951     }
952 #endif /* NSSDEBUG */
953 
954     /* No "instance flags" are yet defined by Cryptoki. */
955     return (CK_ULONG)0;
956 }
957 
958 /*
959  * nssCKFWInstance_GetLibraryDescription
960  *
961  */
962 NSS_IMPLEMENT CK_RV
nssCKFWInstance_GetLibraryDescription(NSSCKFWInstance * fwInstance,CK_CHAR libraryDescription[32])963 nssCKFWInstance_GetLibraryDescription(
964     NSSCKFWInstance *fwInstance,
965     CK_CHAR libraryDescription[32])
966 {
967     CK_RV error = CKR_OK;
968 
969 #ifdef NSSDEBUG
970     if ((CK_CHAR_PTR)NULL == libraryDescription) {
971         return CKR_ARGUMENTS_BAD;
972     }
973 
974     error = nssCKFWInstance_verifyPointer(fwInstance);
975     if (CKR_OK != error) {
976         return error;
977     }
978 #endif /* NSSDEBUG */
979 
980     error = nssCKFWMutex_Lock(fwInstance->mutex);
981     if (CKR_OK != error) {
982         return error;
983     }
984 
985     if (!fwInstance->libraryDescription) {
986         if (fwInstance->mdInstance->GetLibraryDescription) {
987             fwInstance->libraryDescription = fwInstance->mdInstance->GetLibraryDescription(
988                 fwInstance->mdInstance, fwInstance, &error);
989             if ((!fwInstance->libraryDescription) && (CKR_OK != error)) {
990                 goto done;
991             }
992         } else {
993             fwInstance->libraryDescription = (NSSUTF8 *)"";
994         }
995     }
996 
997     (void)nssUTF8_CopyIntoFixedBuffer(fwInstance->libraryDescription, (char *)libraryDescription, 32, ' ');
998     error = CKR_OK;
999 
1000 done:
1001     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
1002     return error;
1003 }
1004 
1005 /*
1006  * nssCKFWInstance_GetLibraryVersion
1007  *
1008  */
1009 NSS_IMPLEMENT CK_VERSION
nssCKFWInstance_GetLibraryVersion(NSSCKFWInstance * fwInstance)1010 nssCKFWInstance_GetLibraryVersion(
1011     NSSCKFWInstance *fwInstance)
1012 {
1013     CK_VERSION rv;
1014 
1015 #ifdef NSSDEBUG
1016     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
1017         rv.major = rv.minor = 0;
1018         return rv;
1019     }
1020 #endif /* NSSDEBUG */
1021 
1022     if (CKR_OK != nssCKFWMutex_Lock(fwInstance->mutex)) {
1023         rv.major = rv.minor = 0;
1024         return rv;
1025     }
1026 
1027     if ((0 != fwInstance->libraryVersion.major) ||
1028         (0 != fwInstance->libraryVersion.minor)) {
1029         rv = fwInstance->libraryVersion;
1030         goto done;
1031     }
1032 
1033     if (fwInstance->mdInstance->GetLibraryVersion) {
1034         fwInstance->libraryVersion = fwInstance->mdInstance->GetLibraryVersion(
1035             fwInstance->mdInstance, fwInstance);
1036     } else {
1037         fwInstance->libraryVersion.major = 0;
1038         fwInstance->libraryVersion.minor = 3;
1039     }
1040 
1041     rv = fwInstance->libraryVersion;
1042 done:
1043     (void)nssCKFWMutex_Unlock(fwInstance->mutex);
1044     return rv;
1045 }
1046 
1047 /*
1048  * nssCKFWInstance_GetModuleHandlesSessionObjects
1049  *
1050  */
1051 NSS_IMPLEMENT CK_BBOOL
nssCKFWInstance_GetModuleHandlesSessionObjects(NSSCKFWInstance * fwInstance)1052 nssCKFWInstance_GetModuleHandlesSessionObjects(
1053     NSSCKFWInstance *fwInstance)
1054 {
1055 #ifdef NSSDEBUG
1056     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
1057         return CK_FALSE;
1058     }
1059 #endif /* NSSDEBUG */
1060 
1061     return fwInstance->moduleHandlesSessionObjects;
1062 }
1063 
1064 /*
1065  * nssCKFWInstance_GetSlots
1066  *
1067  */
1068 NSS_IMPLEMENT NSSCKFWSlot **
nssCKFWInstance_GetSlots(NSSCKFWInstance * fwInstance,CK_RV * pError)1069 nssCKFWInstance_GetSlots(
1070     NSSCKFWInstance *fwInstance,
1071     CK_RV *pError)
1072 {
1073 #ifdef NSSDEBUG
1074     if (!pError) {
1075         return (NSSCKFWSlot **)NULL;
1076     }
1077 
1078     *pError = nssCKFWInstance_verifyPointer(fwInstance);
1079     if (CKR_OK != *pError) {
1080         return (NSSCKFWSlot **)NULL;
1081     }
1082 #endif /* NSSDEBUG */
1083 
1084     return fwInstance->fwSlotList;
1085 }
1086 
1087 /*
1088  * nssCKFWInstance_WaitForSlotEvent
1089  *
1090  */
1091 NSS_IMPLEMENT NSSCKFWSlot *
nssCKFWInstance_WaitForSlotEvent(NSSCKFWInstance * fwInstance,CK_BBOOL block,CK_RV * pError)1092 nssCKFWInstance_WaitForSlotEvent(
1093     NSSCKFWInstance *fwInstance,
1094     CK_BBOOL block,
1095     CK_RV *pError)
1096 {
1097     NSSCKFWSlot *fwSlot = (NSSCKFWSlot *)NULL;
1098     NSSCKMDSlot *mdSlot;
1099     CK_ULONG i, n;
1100 
1101 #ifdef NSSDEBUG
1102     if (!pError) {
1103         return (NSSCKFWSlot *)NULL;
1104     }
1105 
1106     *pError = nssCKFWInstance_verifyPointer(fwInstance);
1107     if (CKR_OK != *pError) {
1108         return (NSSCKFWSlot *)NULL;
1109     }
1110 
1111     switch (block) {
1112         case CK_TRUE:
1113         case CK_FALSE:
1114             break;
1115         default:
1116             *pError = CKR_ARGUMENTS_BAD;
1117             return (NSSCKFWSlot *)NULL;
1118     }
1119 #endif /* NSSDEBUG */
1120 
1121     if (!fwInstance->mdInstance->WaitForSlotEvent) {
1122         *pError = CKR_NO_EVENT;
1123         return (NSSCKFWSlot *)NULL;
1124     }
1125 
1126     mdSlot = fwInstance->mdInstance->WaitForSlotEvent(
1127         fwInstance->mdInstance,
1128         fwInstance,
1129         block,
1130         pError);
1131 
1132     if (!mdSlot) {
1133         return (NSSCKFWSlot *)NULL;
1134     }
1135 
1136     n = nssCKFWInstance_GetNSlots(fwInstance, pError);
1137     if (((CK_ULONG)0 == n) && (CKR_OK != *pError)) {
1138         return (NSSCKFWSlot *)NULL;
1139     }
1140 
1141     for (i = 0; i < n; i++) {
1142         if (fwInstance->mdSlotList[i] == mdSlot) {
1143             fwSlot = fwInstance->fwSlotList[i];
1144             break;
1145         }
1146     }
1147 
1148     if (!fwSlot) {
1149         /* Internal error */
1150         *pError = CKR_GENERAL_ERROR;
1151         return (NSSCKFWSlot *)NULL;
1152     }
1153 
1154     return fwSlot;
1155 }
1156 
1157 /*
1158  * NSSCKFWInstance_GetMDInstance
1159  *
1160  */
1161 NSS_IMPLEMENT NSSCKMDInstance *
NSSCKFWInstance_GetMDInstance(NSSCKFWInstance * fwInstance)1162 NSSCKFWInstance_GetMDInstance(
1163     NSSCKFWInstance *fwInstance)
1164 {
1165 #ifdef DEBUG
1166     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
1167         return (NSSCKMDInstance *)NULL;
1168     }
1169 #endif /* DEBUG */
1170 
1171     return nssCKFWInstance_GetMDInstance(fwInstance);
1172 }
1173 
1174 /*
1175  * NSSCKFWInstance_GetArena
1176  *
1177  */
1178 NSS_IMPLEMENT NSSArena *
NSSCKFWInstance_GetArena(NSSCKFWInstance * fwInstance,CK_RV * pError)1179 NSSCKFWInstance_GetArena(
1180     NSSCKFWInstance *fwInstance,
1181     CK_RV *pError)
1182 {
1183 #ifdef DEBUG
1184     if (!pError) {
1185         return (NSSArena *)NULL;
1186     }
1187 
1188     *pError = nssCKFWInstance_verifyPointer(fwInstance);
1189     if (CKR_OK != *pError) {
1190         return (NSSArena *)NULL;
1191     }
1192 #endif /* DEBUG */
1193 
1194     return nssCKFWInstance_GetArena(fwInstance, pError);
1195 }
1196 
1197 /*
1198  * NSSCKFWInstance_MayCreatePthreads
1199  *
1200  */
1201 NSS_IMPLEMENT CK_BBOOL
NSSCKFWInstance_MayCreatePthreads(NSSCKFWInstance * fwInstance)1202 NSSCKFWInstance_MayCreatePthreads(
1203     NSSCKFWInstance *fwInstance)
1204 {
1205 #ifdef DEBUG
1206     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
1207         return CK_FALSE;
1208     }
1209 #endif /* DEBUG */
1210 
1211     return nssCKFWInstance_MayCreatePthreads(fwInstance);
1212 }
1213 
1214 /*
1215  * NSSCKFWInstance_CreateMutex
1216  *
1217  */
1218 NSS_IMPLEMENT NSSCKFWMutex *
NSSCKFWInstance_CreateMutex(NSSCKFWInstance * fwInstance,NSSArena * arena,CK_RV * pError)1219 NSSCKFWInstance_CreateMutex(
1220     NSSCKFWInstance *fwInstance,
1221     NSSArena *arena,
1222     CK_RV *pError)
1223 {
1224 #ifdef DEBUG
1225     if (!pError) {
1226         return (NSSCKFWMutex *)NULL;
1227     }
1228 
1229     *pError = nssCKFWInstance_verifyPointer(fwInstance);
1230     if (CKR_OK != *pError) {
1231         return (NSSCKFWMutex *)NULL;
1232     }
1233 #endif /* DEBUG */
1234 
1235     return nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
1236 }
1237 
1238 /*
1239  * NSSCKFWInstance_GetConfigurationData
1240  *
1241  */
1242 NSS_IMPLEMENT NSSUTF8 *
NSSCKFWInstance_GetConfigurationData(NSSCKFWInstance * fwInstance)1243 NSSCKFWInstance_GetConfigurationData(
1244     NSSCKFWInstance *fwInstance)
1245 {
1246 #ifdef DEBUG
1247     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
1248         return (NSSUTF8 *)NULL;
1249     }
1250 #endif /* DEBUG */
1251 
1252     return nssCKFWInstance_GetConfigurationData(fwInstance);
1253 }
1254 
1255 /*
1256  * NSSCKFWInstance_GetInitArgs
1257  *
1258  */
1259 NSS_IMPLEMENT CK_C_INITIALIZE_ARGS_PTR
NSSCKFWInstance_GetInitArgs(NSSCKFWInstance * fwInstance)1260 NSSCKFWInstance_GetInitArgs(
1261     NSSCKFWInstance *fwInstance)
1262 {
1263 #ifdef DEBUG
1264     if (CKR_OK != nssCKFWInstance_verifyPointer(fwInstance)) {
1265         return (CK_C_INITIALIZE_ARGS_PTR)NULL;
1266     }
1267 #endif /* DEBUG */
1268 
1269     return nssCKFWInstance_GetInitArgs(fwInstance);
1270 }
1271 
1272 /*
1273  * nssCKFWInstance_DestroySessionHandle
1274  *
1275  */
1276 NSS_IMPLEMENT void
NSSCKFWInstance_DestroySessionHandle(NSSCKFWInstance * fwInstance,CK_SESSION_HANDLE hSession)1277 NSSCKFWInstance_DestroySessionHandle(
1278     NSSCKFWInstance *fwInstance,
1279     CK_SESSION_HANDLE hSession)
1280 {
1281     nssCKFWInstance_DestroySessionHandle(fwInstance, hSession);
1282 }
1283 
1284 /*
1285  * nssCKFWInstance_FindSessionHandle
1286  *
1287  */
1288 NSS_IMPLEMENT CK_SESSION_HANDLE
NSSCKFWInstance_FindSessionHandle(NSSCKFWInstance * fwInstance,NSSCKFWSession * fwSession)1289 NSSCKFWInstance_FindSessionHandle(
1290     NSSCKFWInstance *fwInstance,
1291     NSSCKFWSession *fwSession)
1292 {
1293     return nssCKFWInstance_FindSessionHandle(fwInstance, fwSession);
1294 }
1295