PageRenderTime 45ms CodeModel.GetById 17ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 1ms

/security/nss/lib/ckfw/slot.c

http://github.com/zpao/v8monkey
C | 759 lines | 493 code | 94 blank | 172 comment | 101 complexity | 3b7d28434dc19db9e754e4589732d586 MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  4 * The contents of this file are subject to the Mozilla Public License Version
  5 * 1.1 (the "License"); you may not use this file except in compliance with
  6 * the License. You may obtain a copy of the License at
  7 * http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11 * for the specific language governing rights and limitations under the
 12 * License.
 13 *
 14 * The Original Code is the Netscape security libraries.
 15 *
 16 * The Initial Developer of the Original Code is
 17 * Netscape Communications Corporation.
 18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 19 * the Initial Developer. All Rights Reserved.
 20 *
 21 * Contributor(s):
 22 *
 23 * Alternatively, the contents of this file may be used under the terms of
 24 * either the GNU General Public License Version 2 or later (the "GPL"), or
 25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 26 * in which case the provisions of the GPL or the LGPL are applicable instead
 27 * of those above. If you wish to allow use of your version of this file only
 28 * under the terms of either the GPL or the LGPL, and not to allow others to
 29 * use your version of this file under the terms of the MPL, indicate your
 30 * decision by deleting the provisions above and replace them with the notice
 31 * and other provisions required by the GPL or the LGPL. If you do not delete
 32 * the provisions above, a recipient may use your version of this file under
 33 * the terms of any one of the MPL, the GPL or the LGPL.
 34 *
 35 * ***** END LICENSE BLOCK ***** */
 36
 37#ifdef DEBUG
 38static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.7 $ $Date: 2009/02/09 07:55:53 $";
 39#endif /* DEBUG */
 40
 41/*
 42 * slot.c
 43 *
 44 * This file implements the NSSCKFWSlot type and methods.
 45 */
 46
 47#ifndef CK_T
 48#include "ck.h"
 49#endif /* CK_T */
 50
 51/*
 52 * NSSCKFWSlot
 53 *
 54 *  -- create/destroy --
 55 *  nssCKFWSlot_Create
 56 *  nssCKFWSlot_Destroy
 57 *
 58 *  -- public accessors --
 59 *  NSSCKFWSlot_GetMDSlot
 60 *  NSSCKFWSlot_GetFWInstance
 61 *  NSSCKFWSlot_GetMDInstance
 62 *
 63 *  -- implement public accessors --
 64 *  nssCKFWSlot_GetMDSlot
 65 *  nssCKFWSlot_GetFWInstance
 66 *  nssCKFWSlot_GetMDInstance
 67 *
 68 *  -- private accessors --
 69 *  nssCKFWSlot_GetSlotID
 70 *  nssCKFWSlot_ClearToken
 71 *
 72 *  -- module fronts --
 73 *  nssCKFWSlot_GetSlotDescription
 74 *  nssCKFWSlot_GetManufacturerID
 75 *  nssCKFWSlot_GetTokenPresent
 76 *  nssCKFWSlot_GetRemovableDevice
 77 *  nssCKFWSlot_GetHardwareSlot
 78 *  nssCKFWSlot_GetHardwareVersion
 79 *  nssCKFWSlot_GetFirmwareVersion
 80 *  nssCKFWSlot_InitToken
 81 *  nssCKFWSlot_GetToken
 82 */
 83
 84struct NSSCKFWSlotStr {
 85  NSSCKFWMutex *mutex;
 86  NSSCKMDSlot *mdSlot;
 87  NSSCKFWInstance *fwInstance;
 88  NSSCKMDInstance *mdInstance;
 89  CK_SLOT_ID slotID;
 90
 91  /*
 92   * Everything above is set at creation time, and then not modified.
 93   * The invariants the mutex protects are:
 94   *
 95   * 1) Each of the cached descriptions (versions, etc.) are in an
 96   *    internally consistant state.
 97   *
 98   * 2) The fwToken points to the token currently in the slot, and
 99   *    it is in a consistant state.
100   *
101   * Note that the calls accessing the cached descriptions will
102   * call the NSSCKMDSlot methods with the mutex locked.  Those
103   * methods may then call the public NSSCKFWSlot routines.  Those
104   * public routines only access the constant data above, so there's
105   * no problem.  But be careful if you add to this object; mutexes
106   * are in general not reentrant, so don't create deadlock situations.
107   */
108
109  NSSUTF8 *slotDescription;
110  NSSUTF8 *manufacturerID;
111  CK_VERSION hardwareVersion;
112  CK_VERSION firmwareVersion;
113  NSSCKFWToken *fwToken;
114};
115
116#ifdef DEBUG
117/*
118 * But first, the pointer-tracking stuff.
119 *
120 * NOTE: the pointer-tracking support in NSS/base currently relies
121 * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
122 * locking, which is tied into the runtime.  We need a pointer-tracker
123 * implementation that uses the locks supplied through C_Initialize.
124 * That support, however, can be filled in later.  So for now, I'll
125 * just do this routines as no-ops.
126 */
127
128static CK_RV
129slot_add_pointer
130(
131  const NSSCKFWSlot *fwSlot
132)
133{
134  return CKR_OK;
135}
136
137static CK_RV
138slot_remove_pointer
139(
140  const NSSCKFWSlot *fwSlot
141)
142{
143  return CKR_OK;
144}
145
146NSS_IMPLEMENT CK_RV
147nssCKFWSlot_verifyPointer
148(
149  const NSSCKFWSlot *fwSlot
150)
151{
152  return CKR_OK;
153}
154
155#endif /* DEBUG */
156
157/*
158 * nssCKFWSlot_Create
159 *
160 */
161NSS_IMPLEMENT NSSCKFWSlot *
162nssCKFWSlot_Create
163(
164  NSSCKFWInstance *fwInstance,
165  NSSCKMDSlot *mdSlot,
166  CK_SLOT_ID slotID,
167  CK_RV *pError
168)
169{
170  NSSCKFWSlot *fwSlot;
171  NSSCKMDInstance *mdInstance;
172  NSSArena *arena;
173
174#ifdef NSSDEBUG
175  if (!pError) {
176    return (NSSCKFWSlot *)NULL;
177  }
178
179  *pError = nssCKFWInstance_verifyPointer(fwInstance);
180  if( CKR_OK != *pError ) {
181    return (NSSCKFWSlot *)NULL;
182  }
183#endif /* NSSDEBUG */
184
185  mdInstance = nssCKFWInstance_GetMDInstance(fwInstance);
186  if (!mdInstance) {
187    *pError = CKR_GENERAL_ERROR;
188    return (NSSCKFWSlot *)NULL;
189  }
190
191  arena = nssCKFWInstance_GetArena(fwInstance, pError);
192  if (!arena) {
193    if( CKR_OK == *pError ) {
194      *pError = CKR_GENERAL_ERROR;
195    }
196  }
197
198  fwSlot = nss_ZNEW(arena, NSSCKFWSlot);
199  if (!fwSlot) {
200    *pError = CKR_HOST_MEMORY;
201    return (NSSCKFWSlot *)NULL;
202  }
203
204  fwSlot->mdSlot = mdSlot;
205  fwSlot->fwInstance = fwInstance;
206  fwSlot->mdInstance = mdInstance;
207  fwSlot->slotID = slotID;
208
209  fwSlot->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
210  if (!fwSlot->mutex) {
211    if( CKR_OK == *pError ) {
212      *pError = CKR_GENERAL_ERROR;
213    }
214    (void)nss_ZFreeIf(fwSlot);
215    return (NSSCKFWSlot *)NULL;
216  }
217
218  if (mdSlot->Initialize) {
219    *pError = CKR_OK;
220    *pError = mdSlot->Initialize(mdSlot, fwSlot, mdInstance, fwInstance);
221    if( CKR_OK != *pError ) {
222      (void)nssCKFWMutex_Destroy(fwSlot->mutex);
223      (void)nss_ZFreeIf(fwSlot);
224      return (NSSCKFWSlot *)NULL;
225    }
226  }
227
228#ifdef DEBUG
229  *pError = slot_add_pointer(fwSlot);
230  if( CKR_OK != *pError ) {
231    if (mdSlot->Destroy) {
232      mdSlot->Destroy(mdSlot, fwSlot, mdInstance, fwInstance);
233    }
234
235    (void)nssCKFWMutex_Destroy(fwSlot->mutex);
236    (void)nss_ZFreeIf(fwSlot);
237    return (NSSCKFWSlot *)NULL;
238  }
239#endif /* DEBUG */
240
241  return fwSlot;
242}
243
244/*
245 * nssCKFWSlot_Destroy
246 *
247 */
248NSS_IMPLEMENT CK_RV
249nssCKFWSlot_Destroy
250(
251  NSSCKFWSlot *fwSlot
252)
253{
254  CK_RV error = CKR_OK;
255
256#ifdef NSSDEBUG
257  error = nssCKFWSlot_verifyPointer(fwSlot);
258  if( CKR_OK != error ) {
259    return error;
260  }
261#endif /* NSSDEBUG */
262  if (fwSlot->fwToken) {
263    nssCKFWToken_Destroy(fwSlot->fwToken);
264  }
265
266  (void)nssCKFWMutex_Destroy(fwSlot->mutex);
267
268  if (fwSlot->mdSlot->Destroy) {
269    fwSlot->mdSlot->Destroy(fwSlot->mdSlot, fwSlot, 
270      fwSlot->mdInstance, fwSlot->fwInstance);
271  }
272
273#ifdef DEBUG
274  error = slot_remove_pointer(fwSlot);
275#endif /* DEBUG */
276  (void)nss_ZFreeIf(fwSlot);
277  return error;
278}
279
280/*
281 * nssCKFWSlot_GetMDSlot
282 *
283 */
284NSS_IMPLEMENT NSSCKMDSlot *
285nssCKFWSlot_GetMDSlot
286(
287  NSSCKFWSlot *fwSlot
288)
289{
290#ifdef NSSDEBUG
291  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
292    return (NSSCKMDSlot *)NULL;
293  }
294#endif /* NSSDEBUG */
295
296  return fwSlot->mdSlot;
297}
298
299/*
300 * nssCKFWSlot_GetFWInstance
301 *
302 */
303
304NSS_IMPLEMENT NSSCKFWInstance *
305nssCKFWSlot_GetFWInstance
306(
307  NSSCKFWSlot *fwSlot
308)
309{
310#ifdef NSSDEBUG
311  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
312    return (NSSCKFWInstance *)NULL;
313  }
314#endif /* NSSDEBUG */
315
316  return fwSlot->fwInstance;
317}
318
319/*
320 * nssCKFWSlot_GetMDInstance
321 *
322 */
323
324NSS_IMPLEMENT NSSCKMDInstance *
325nssCKFWSlot_GetMDInstance
326(
327  NSSCKFWSlot *fwSlot
328)
329{
330#ifdef NSSDEBUG
331  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
332    return (NSSCKMDInstance *)NULL;
333  }
334#endif /* NSSDEBUG */
335
336  return fwSlot->mdInstance;
337}
338
339/*
340 * nssCKFWSlot_GetSlotID
341 *
342 */
343NSS_IMPLEMENT CK_SLOT_ID
344nssCKFWSlot_GetSlotID
345(
346  NSSCKFWSlot *fwSlot
347)
348{
349#ifdef NSSDEBUG
350  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
351    return (CK_SLOT_ID)0;
352  }
353#endif /* NSSDEBUG */
354
355  return fwSlot->slotID;
356}
357
358/*
359 * nssCKFWSlot_GetSlotDescription
360 *
361 */
362NSS_IMPLEMENT CK_RV
363nssCKFWSlot_GetSlotDescription
364(
365  NSSCKFWSlot *fwSlot,
366  CK_CHAR slotDescription[64]
367)
368{
369  CK_RV error = CKR_OK;
370
371#ifdef NSSDEBUG
372  if( (CK_CHAR_PTR)NULL == slotDescription ) {
373    return CKR_ARGUMENTS_BAD;
374  }
375
376  error = nssCKFWSlot_verifyPointer(fwSlot);
377  if( CKR_OK != error ) {
378    return error;
379  }
380#endif /* NSSDEBUG */
381
382  error = nssCKFWMutex_Lock(fwSlot->mutex);
383  if( CKR_OK != error ) {
384    return error;
385  }
386
387  if (!fwSlot->slotDescription) {
388    if (fwSlot->mdSlot->GetSlotDescription) {
389      fwSlot->slotDescription = fwSlot->mdSlot->GetSlotDescription(
390        fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, 
391        fwSlot->fwInstance, &error);
392      if ((!fwSlot->slotDescription) && (CKR_OK != error)) {
393        goto done;
394      }
395    } else {
396      fwSlot->slotDescription = (NSSUTF8 *) "";
397    }
398  }
399
400  (void)nssUTF8_CopyIntoFixedBuffer(fwSlot->slotDescription, (char *)slotDescription, 64, ' ');
401  error = CKR_OK;
402
403 done:
404  (void)nssCKFWMutex_Unlock(fwSlot->mutex);
405  return error;
406}
407
408/*
409 * nssCKFWSlot_GetManufacturerID
410 *
411 */
412NSS_IMPLEMENT CK_RV
413nssCKFWSlot_GetManufacturerID
414(
415  NSSCKFWSlot *fwSlot,
416  CK_CHAR manufacturerID[32]
417)
418{
419  CK_RV error = CKR_OK;
420
421#ifdef NSSDEBUG
422  if( (CK_CHAR_PTR)NULL == manufacturerID ) {
423    return CKR_ARGUMENTS_BAD;
424  }
425
426  error = nssCKFWSlot_verifyPointer(fwSlot);
427  if( CKR_OK != error ) {
428    return error;
429  }
430#endif /* NSSDEBUG */
431
432  error = nssCKFWMutex_Lock(fwSlot->mutex);
433  if( CKR_OK != error ) {
434    return error;
435  }
436
437  if (!fwSlot->manufacturerID) {
438    if (fwSlot->mdSlot->GetManufacturerID) {
439      fwSlot->manufacturerID = fwSlot->mdSlot->GetManufacturerID(
440        fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, 
441        fwSlot->fwInstance, &error);
442      if ((!fwSlot->manufacturerID) && (CKR_OK != error)) {
443        goto done;
444      }
445    } else {
446      fwSlot->manufacturerID = (NSSUTF8 *) "";
447    }
448  }
449
450  (void)nssUTF8_CopyIntoFixedBuffer(fwSlot->manufacturerID, (char *)manufacturerID, 32, ' ');
451  error = CKR_OK;
452
453 done:
454  (void)nssCKFWMutex_Unlock(fwSlot->mutex);
455  return error;
456}
457
458/*
459 * nssCKFWSlot_GetTokenPresent
460 *
461 */
462NSS_IMPLEMENT CK_BBOOL
463nssCKFWSlot_GetTokenPresent
464(
465  NSSCKFWSlot *fwSlot
466)
467{
468#ifdef NSSDEBUG
469  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
470    return CK_FALSE;
471  }
472#endif /* NSSDEBUG */
473
474  if (!fwSlot->mdSlot->GetTokenPresent) {
475    return CK_TRUE;
476  }
477
478  return fwSlot->mdSlot->GetTokenPresent(fwSlot->mdSlot, fwSlot,
479    fwSlot->mdInstance, fwSlot->fwInstance);
480}
481
482/*
483 * nssCKFWSlot_GetRemovableDevice
484 *
485 */
486NSS_IMPLEMENT CK_BBOOL
487nssCKFWSlot_GetRemovableDevice
488(
489  NSSCKFWSlot *fwSlot
490)
491{
492#ifdef NSSDEBUG
493  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
494    return CK_FALSE;
495  }
496#endif /* NSSDEBUG */
497
498  if (!fwSlot->mdSlot->GetRemovableDevice) {
499    return CK_FALSE;
500  }
501
502  return fwSlot->mdSlot->GetRemovableDevice(fwSlot->mdSlot, fwSlot,
503    fwSlot->mdInstance, fwSlot->fwInstance);
504}
505
506/*
507 * nssCKFWSlot_GetHardwareSlot
508 *
509 */
510NSS_IMPLEMENT CK_BBOOL
511nssCKFWSlot_GetHardwareSlot
512(
513  NSSCKFWSlot *fwSlot
514)
515{
516#ifdef NSSDEBUG
517  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
518    return CK_FALSE;
519  }
520#endif /* NSSDEBUG */
521
522  if (!fwSlot->mdSlot->GetHardwareSlot) {
523    return CK_FALSE;
524  }
525
526  return fwSlot->mdSlot->GetHardwareSlot(fwSlot->mdSlot, fwSlot,
527    fwSlot->mdInstance, fwSlot->fwInstance);
528}
529
530/*
531 * nssCKFWSlot_GetHardwareVersion
532 *
533 */
534NSS_IMPLEMENT CK_VERSION
535nssCKFWSlot_GetHardwareVersion
536(
537  NSSCKFWSlot *fwSlot
538)
539{
540  CK_VERSION rv;
541
542#ifdef NSSDEBUG
543  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
544    rv.major = rv.minor = 0;
545    return rv;
546  }
547#endif /* NSSDEBUG */
548
549  if( CKR_OK != nssCKFWMutex_Lock(fwSlot->mutex) ) {
550    rv.major = rv.minor = 0;
551    return rv;
552  }
553
554  if( (0 != fwSlot->hardwareVersion.major) ||
555      (0 != fwSlot->hardwareVersion.minor) ) {
556    rv = fwSlot->hardwareVersion;
557    goto done;
558  }
559
560  if (fwSlot->mdSlot->GetHardwareVersion) {
561    fwSlot->hardwareVersion = fwSlot->mdSlot->GetHardwareVersion(
562      fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, fwSlot->fwInstance);
563  } else {
564    fwSlot->hardwareVersion.major = 0;
565    fwSlot->hardwareVersion.minor = 1;
566  }
567
568  rv = fwSlot->hardwareVersion;
569 done:
570  (void)nssCKFWMutex_Unlock(fwSlot->mutex);
571  return rv;
572}
573
574/*
575 * nssCKFWSlot_GetFirmwareVersion
576 *
577 */
578NSS_IMPLEMENT CK_VERSION
579nssCKFWSlot_GetFirmwareVersion
580(
581  NSSCKFWSlot *fwSlot
582)
583{
584  CK_VERSION rv;
585
586#ifdef NSSDEBUG
587  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
588    rv.major = rv.minor = 0;
589    return rv;
590  }
591#endif /* NSSDEBUG */
592
593  if( CKR_OK != nssCKFWMutex_Lock(fwSlot->mutex) ) {
594    rv.major = rv.minor = 0;
595    return rv;
596  }
597
598  if( (0 != fwSlot->firmwareVersion.major) ||
599      (0 != fwSlot->firmwareVersion.minor) ) {
600    rv = fwSlot->firmwareVersion;
601    goto done;
602  }
603
604  if (fwSlot->mdSlot->GetFirmwareVersion) {
605    fwSlot->firmwareVersion = fwSlot->mdSlot->GetFirmwareVersion(
606      fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, fwSlot->fwInstance);
607  } else {
608    fwSlot->firmwareVersion.major = 0;
609    fwSlot->firmwareVersion.minor = 1;
610  }
611
612  rv = fwSlot->firmwareVersion;
613 done:
614  (void)nssCKFWMutex_Unlock(fwSlot->mutex);
615  return rv;
616}
617
618/*
619 * nssCKFWSlot_GetToken
620 * 
621 */
622NSS_IMPLEMENT NSSCKFWToken *
623nssCKFWSlot_GetToken
624(
625  NSSCKFWSlot *fwSlot,
626  CK_RV *pError
627)
628{
629  NSSCKMDToken *mdToken;
630  NSSCKFWToken *fwToken;
631
632#ifdef NSSDEBUG
633  if (!pError) {
634    return (NSSCKFWToken *)NULL;
635  }
636
637  *pError = nssCKFWSlot_verifyPointer(fwSlot);
638  if( CKR_OK != *pError ) {
639    return (NSSCKFWToken *)NULL;
640  }
641#endif /* NSSDEBUG */
642
643  *pError = nssCKFWMutex_Lock(fwSlot->mutex);
644  if( CKR_OK != *pError ) {
645    return (NSSCKFWToken *)NULL;
646  }
647
648  if (!fwSlot->fwToken) {
649    if (!fwSlot->mdSlot->GetToken) {
650      *pError = CKR_GENERAL_ERROR;
651      fwToken = (NSSCKFWToken *)NULL;
652      goto done;
653    }
654
655    mdToken = fwSlot->mdSlot->GetToken(fwSlot->mdSlot, fwSlot,
656      fwSlot->mdInstance, fwSlot->fwInstance, pError);
657    if (!mdToken) {
658      if( CKR_OK == *pError ) {
659        *pError = CKR_GENERAL_ERROR;
660      }
661      return (NSSCKFWToken *)NULL;
662    }
663
664    fwToken = nssCKFWToken_Create(fwSlot, mdToken, pError);
665    fwSlot->fwToken = fwToken;
666  } else {
667    fwToken = fwSlot->fwToken;
668  }
669
670 done:
671  (void)nssCKFWMutex_Unlock(fwSlot->mutex);
672  return fwToken;
673}
674
675/*
676 * nssCKFWSlot_ClearToken
677 *
678 */
679NSS_IMPLEMENT void
680nssCKFWSlot_ClearToken
681(
682  NSSCKFWSlot *fwSlot
683)
684{
685#ifdef NSSDEBUG
686  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
687    return;
688  }
689#endif /* NSSDEBUG */
690
691  if( CKR_OK != nssCKFWMutex_Lock(fwSlot->mutex) ) {
692    /* Now what? */
693    return;
694  }
695
696  fwSlot->fwToken = (NSSCKFWToken *)NULL;
697  (void)nssCKFWMutex_Unlock(fwSlot->mutex);
698  return;
699}
700
701/*
702 * NSSCKFWSlot_GetMDSlot
703 *
704 */
705
706NSS_IMPLEMENT NSSCKMDSlot *
707NSSCKFWSlot_GetMDSlot
708(
709  NSSCKFWSlot *fwSlot
710)
711{
712#ifdef DEBUG
713  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
714    return (NSSCKMDSlot *)NULL;
715  }
716#endif /* DEBUG */
717
718  return nssCKFWSlot_GetMDSlot(fwSlot);
719}
720
721/*
722 * NSSCKFWSlot_GetFWInstance
723 *
724 */
725
726NSS_IMPLEMENT NSSCKFWInstance *
727NSSCKFWSlot_GetFWInstance
728(
729  NSSCKFWSlot *fwSlot
730)
731{
732#ifdef DEBUG
733  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
734    return (NSSCKFWInstance *)NULL;
735  }
736#endif /* DEBUG */
737
738  return nssCKFWSlot_GetFWInstance(fwSlot);
739}
740
741/*
742 * NSSCKFWSlot_GetMDInstance
743 *
744 */
745
746NSS_IMPLEMENT NSSCKMDInstance *
747NSSCKFWSlot_GetMDInstance
748(
749  NSSCKFWSlot *fwSlot
750)
751{
752#ifdef DEBUG
753  if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
754    return (NSSCKMDInstance *)NULL;
755  }
756#endif /* DEBUG */
757
758  return nssCKFWSlot_GetMDInstance(fwSlot);
759}