gecko-dev/security/nss/lib/ckfw/slot.c
2004-04-25 15:03:26 +00:00

760 lines
16 KiB
C

/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: slot.c,v $ $Revision: 1.5 $ $Date: 2004/04/25 15:03:04 $ $Name: $";
#endif /* DEBUG */
/*
* slot.c
*
* This file implements the NSSCKFWSlot type and methods.
*/
#ifndef CK_T
#include "ck.h"
#endif /* CK_T */
/*
* NSSCKFWSlot
*
* -- create/destroy --
* nssCKFWSlot_Create
* nssCKFWSlot_Destroy
*
* -- public accessors --
* NSSCKFWSlot_GetMDSlot
* NSSCKFWSlot_GetFWInstance
* NSSCKFWSlot_GetMDInstance
*
* -- implement public accessors --
* nssCKFWSlot_GetMDSlot
* nssCKFWSlot_GetFWInstance
* nssCKFWSlot_GetMDInstance
*
* -- private accessors --
* nssCKFWSlot_GetSlotID
* nssCKFWSlot_ClearToken
*
* -- module fronts --
* nssCKFWSlot_GetSlotDescription
* nssCKFWSlot_GetManufacturerID
* nssCKFWSlot_GetTokenPresent
* nssCKFWSlot_GetRemovableDevice
* nssCKFWSlot_GetHardwareSlot
* nssCKFWSlot_GetHardwareVersion
* nssCKFWSlot_GetFirmwareVersion
* nssCKFWSlot_InitToken
* nssCKFWSlot_GetToken
*/
struct NSSCKFWSlotStr {
NSSCKFWMutex *mutex;
NSSCKMDSlot *mdSlot;
NSSCKFWInstance *fwInstance;
NSSCKMDInstance *mdInstance;
CK_SLOT_ID slotID;
/*
* Everything above is set at creation time, and then not modified.
* The invariants the mutex protects are:
*
* 1) Each of the cached descriptions (versions, etc.) are in an
* internally consistant state.
*
* 2) The fwToken points to the token currently in the slot, and
* it is in a consistant state.
*
* Note that the calls accessing the cached descriptions will
* call the NSSCKMDSlot methods with the mutex locked. Those
* methods may then call the public NSSCKFWSlot routines. Those
* public routines only access the constant data above, so there's
* no problem. But be careful if you add to this object; mutexes
* are in general not reentrant, so don't create deadlock situations.
*/
NSSUTF8 *slotDescription;
NSSUTF8 *manufacturerID;
CK_VERSION hardwareVersion;
CK_VERSION firmwareVersion;
NSSCKFWToken *fwToken;
};
#ifdef DEBUG
/*
* But first, the pointer-tracking stuff.
*
* NOTE: the pointer-tracking support in NSS/base currently relies
* upon NSPR's CallOnce support. That, however, relies upon NSPR's
* locking, which is tied into the runtime. We need a pointer-tracker
* implementation that uses the locks supplied through C_Initialize.
* That support, however, can be filled in later. So for now, I'll
* just do this routines as no-ops.
*/
static CK_RV
slot_add_pointer
(
const NSSCKFWSlot *fwSlot
)
{
return CKR_OK;
}
static CK_RV
slot_remove_pointer
(
const NSSCKFWSlot *fwSlot
)
{
return CKR_OK;
}
NSS_IMPLEMENT CK_RV
nssCKFWSlot_verifyPointer
(
const NSSCKFWSlot *fwSlot
)
{
return CKR_OK;
}
#endif /* DEBUG */
/*
* nssCKFWSlot_Create
*
*/
NSS_IMPLEMENT NSSCKFWSlot *
nssCKFWSlot_Create
(
NSSCKFWInstance *fwInstance,
NSSCKMDSlot *mdSlot,
CK_SLOT_ID slotID,
CK_RV *pError
)
{
NSSCKFWSlot *fwSlot;
NSSCKMDInstance *mdInstance;
NSSArena *arena;
#ifdef NSSDEBUG
if( (CK_RV *)NULL == pError ) {
return (NSSCKFWSlot *)NULL;
}
*pError = nssCKFWInstance_verifyPointer(fwInstance);
if( CKR_OK != *pError ) {
return (NSSCKFWSlot *)NULL;
}
#endif /* NSSDEBUG */
mdInstance = nssCKFWInstance_GetMDInstance(fwInstance);
if( (NSSCKMDInstance *)NULL == mdInstance ) {
*pError = CKR_GENERAL_ERROR;
return (NSSCKFWSlot *)NULL;
}
arena = nssCKFWInstance_GetArena(fwInstance, pError);
if( (NSSArena *)NULL == arena ) {
if( CKR_OK == *pError ) {
*pError = CKR_GENERAL_ERROR;
}
}
fwSlot = nss_ZNEW(arena, NSSCKFWSlot);
if( (NSSCKFWSlot *)NULL == fwSlot ) {
*pError = CKR_HOST_MEMORY;
return (NSSCKFWSlot *)NULL;
}
fwSlot->mdSlot = mdSlot;
fwSlot->fwInstance = fwInstance;
fwSlot->mdInstance = mdInstance;
fwSlot->slotID = slotID;
fwSlot->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
if( (NSSCKFWMutex *)NULL == fwSlot->mutex ) {
if( CKR_OK == *pError ) {
*pError = CKR_GENERAL_ERROR;
}
(void)nss_ZFreeIf(fwSlot);
return (NSSCKFWSlot *)NULL;
}
if( (void *)NULL != (void *)mdSlot->Initialize ) {
*pError = CKR_OK;
*pError = mdSlot->Initialize(mdSlot, fwSlot, mdInstance, fwInstance);
if( CKR_OK != *pError ) {
(void)nssCKFWMutex_Destroy(fwSlot->mutex);
(void)nss_ZFreeIf(fwSlot);
return (NSSCKFWSlot *)NULL;
}
}
#ifdef DEBUG
*pError = slot_add_pointer(fwSlot);
if( CKR_OK != *pError ) {
if( (void *)NULL != (void *)mdSlot->Destroy ) {
mdSlot->Destroy(mdSlot, fwSlot, mdInstance, fwInstance);
}
(void)nssCKFWMutex_Destroy(fwSlot->mutex);
(void)nss_ZFreeIf(fwSlot);
return (NSSCKFWSlot *)NULL;
}
#endif /* DEBUG */
return fwSlot;
}
/*
* nssCKFWSlot_Destroy
*
*/
NSS_IMPLEMENT CK_RV
nssCKFWSlot_Destroy
(
NSSCKFWSlot *fwSlot
)
{
CK_RV error = CKR_OK;
#ifdef NSSDEBUG
error = nssCKFWSlot_verifyPointer(fwSlot);
if( CKR_OK != error ) {
return error;
}
#endif /* NSSDEBUG */
if (fwSlot->fwToken) {
nssCKFWToken_Destroy(fwSlot->fwToken);
}
(void)nssCKFWMutex_Destroy(fwSlot->mutex);
if( (void *)NULL != (void *)fwSlot->mdSlot->Destroy ) {
fwSlot->mdSlot->Destroy(fwSlot->mdSlot, fwSlot,
fwSlot->mdInstance, fwSlot->fwInstance);
}
#ifdef DEBUG
error = slot_remove_pointer(fwSlot);
#endif /* DEBUG */
(void)nss_ZFreeIf(fwSlot);
return error;
}
/*
* nssCKFWSlot_GetMDSlot
*
*/
NSS_IMPLEMENT NSSCKMDSlot *
nssCKFWSlot_GetMDSlot
(
NSSCKFWSlot *fwSlot
)
{
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return (NSSCKMDSlot *)NULL;
}
#endif /* NSSDEBUG */
return fwSlot->mdSlot;
}
/*
* nssCKFWSlot_GetFWInstance
*
*/
NSS_IMPLEMENT NSSCKFWInstance *
nssCKFWSlot_GetFWInstance
(
NSSCKFWSlot *fwSlot
)
{
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return (NSSCKFWInstance *)NULL;
}
#endif /* NSSDEBUG */
return fwSlot->fwInstance;
}
/*
* nssCKFWSlot_GetMDInstance
*
*/
NSS_IMPLEMENT NSSCKMDInstance *
nssCKFWSlot_GetMDInstance
(
NSSCKFWSlot *fwSlot
)
{
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return (NSSCKMDInstance *)NULL;
}
#endif /* NSSDEBUG */
return fwSlot->mdInstance;
}
/*
* nssCKFWSlot_GetSlotID
*
*/
NSS_IMPLEMENT CK_SLOT_ID
nssCKFWSlot_GetSlotID
(
NSSCKFWSlot *fwSlot
)
{
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return (CK_SLOT_ID)0;
}
#endif /* NSSDEBUG */
return fwSlot->slotID;
}
/*
* nssCKFWSlot_GetSlotDescription
*
*/
NSS_IMPLEMENT CK_RV
nssCKFWSlot_GetSlotDescription
(
NSSCKFWSlot *fwSlot,
CK_CHAR slotDescription[64]
)
{
CK_RV error = CKR_OK;
#ifdef NSSDEBUG
if( (CK_CHAR_PTR)NULL == slotDescription ) {
return CKR_ARGUMENTS_BAD;
}
error = nssCKFWSlot_verifyPointer(fwSlot);
if( CKR_OK != error ) {
return error;
}
#endif /* NSSDEBUG */
error = nssCKFWMutex_Lock(fwSlot->mutex);
if( CKR_OK != error ) {
return error;
}
if( (NSSUTF8 *)NULL == fwSlot->slotDescription ) {
if( (void *)NULL != (void *)fwSlot->mdSlot->GetSlotDescription ) {
fwSlot->slotDescription = fwSlot->mdSlot->GetSlotDescription(
fwSlot->mdSlot, fwSlot, fwSlot->mdInstance,
fwSlot->fwInstance, &error);
if( ((NSSUTF8 *)NULL == fwSlot->slotDescription) && (CKR_OK != error) ) {
goto done;
}
} else {
fwSlot->slotDescription = (NSSUTF8 *) "";
}
}
(void)nssUTF8_CopyIntoFixedBuffer(fwSlot->slotDescription, (char *)slotDescription, 64, ' ');
error = CKR_OK;
done:
(void)nssCKFWMutex_Unlock(fwSlot->mutex);
return error;
}
/*
* nssCKFWSlot_GetManufacturerID
*
*/
NSS_IMPLEMENT CK_RV
nssCKFWSlot_GetManufacturerID
(
NSSCKFWSlot *fwSlot,
CK_CHAR manufacturerID[32]
)
{
CK_RV error = CKR_OK;
#ifdef NSSDEBUG
if( (CK_CHAR_PTR)NULL == manufacturerID ) {
return CKR_ARGUMENTS_BAD;
}
error = nssCKFWSlot_verifyPointer(fwSlot);
if( CKR_OK != error ) {
return error;
}
#endif /* NSSDEBUG */
error = nssCKFWMutex_Lock(fwSlot->mutex);
if( CKR_OK != error ) {
return error;
}
if( (NSSUTF8 *)NULL == fwSlot->manufacturerID ) {
if( (void *)NULL != (void *)fwSlot->mdSlot->GetManufacturerID ) {
fwSlot->manufacturerID = fwSlot->mdSlot->GetManufacturerID(
fwSlot->mdSlot, fwSlot, fwSlot->mdInstance,
fwSlot->fwInstance, &error);
if( ((NSSUTF8 *)NULL == fwSlot->manufacturerID) && (CKR_OK != error) ) {
goto done;
}
} else {
fwSlot->manufacturerID = (NSSUTF8 *) "";
}
}
(void)nssUTF8_CopyIntoFixedBuffer(fwSlot->manufacturerID, (char *)manufacturerID, 32, ' ');
error = CKR_OK;
done:
(void)nssCKFWMutex_Unlock(fwSlot->mutex);
return error;
}
/*
* nssCKFWSlot_GetTokenPresent
*
*/
NSS_IMPLEMENT CK_BBOOL
nssCKFWSlot_GetTokenPresent
(
NSSCKFWSlot *fwSlot
)
{
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return CK_FALSE;
}
#endif /* NSSDEBUG */
if( (void *)NULL == (void *)fwSlot->mdSlot->GetTokenPresent ) {
return CK_TRUE;
}
return fwSlot->mdSlot->GetTokenPresent(fwSlot->mdSlot, fwSlot,
fwSlot->mdInstance, fwSlot->fwInstance);
}
/*
* nssCKFWSlot_GetRemovableDevice
*
*/
NSS_IMPLEMENT CK_BBOOL
nssCKFWSlot_GetRemovableDevice
(
NSSCKFWSlot *fwSlot
)
{
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return CK_FALSE;
}
#endif /* NSSDEBUG */
if( (void *)NULL == (void *)fwSlot->mdSlot->GetRemovableDevice ) {
return CK_FALSE;
}
return fwSlot->mdSlot->GetRemovableDevice(fwSlot->mdSlot, fwSlot,
fwSlot->mdInstance, fwSlot->fwInstance);
}
/*
* nssCKFWSlot_GetHardwareSlot
*
*/
NSS_IMPLEMENT CK_BBOOL
nssCKFWSlot_GetHardwareSlot
(
NSSCKFWSlot *fwSlot
)
{
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return CK_FALSE;
}
#endif /* NSSDEBUG */
if( (void *)NULL == (void *)fwSlot->mdSlot->GetHardwareSlot ) {
return CK_FALSE;
}
return fwSlot->mdSlot->GetHardwareSlot(fwSlot->mdSlot, fwSlot,
fwSlot->mdInstance, fwSlot->fwInstance);
}
/*
* nssCKFWSlot_GetHardwareVersion
*
*/
NSS_IMPLEMENT CK_VERSION
nssCKFWSlot_GetHardwareVersion
(
NSSCKFWSlot *fwSlot
)
{
CK_VERSION rv;
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
rv.major = rv.minor = 0;
return rv;
}
#endif /* NSSDEBUG */
if( CKR_OK != nssCKFWMutex_Lock(fwSlot->mutex) ) {
rv.major = rv.minor = 0;
return rv;
}
if( (0 != fwSlot->hardwareVersion.major) ||
(0 != fwSlot->hardwareVersion.minor) ) {
rv = fwSlot->hardwareVersion;
goto done;
}
if( (void *)NULL != (void *)fwSlot->mdSlot->GetHardwareVersion ) {
fwSlot->hardwareVersion = fwSlot->mdSlot->GetHardwareVersion(
fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, fwSlot->fwInstance);
} else {
fwSlot->hardwareVersion.major = 0;
fwSlot->hardwareVersion.minor = 1;
}
rv = fwSlot->hardwareVersion;
done:
(void)nssCKFWMutex_Unlock(fwSlot->mutex);
return rv;
}
/*
* nssCKFWSlot_GetFirmwareVersion
*
*/
NSS_IMPLEMENT CK_VERSION
nssCKFWSlot_GetFirmwareVersion
(
NSSCKFWSlot *fwSlot
)
{
CK_VERSION rv;
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
rv.major = rv.minor = 0;
return rv;
}
#endif /* NSSDEBUG */
if( CKR_OK != nssCKFWMutex_Lock(fwSlot->mutex) ) {
rv.major = rv.minor = 0;
return rv;
}
if( (0 != fwSlot->firmwareVersion.major) ||
(0 != fwSlot->firmwareVersion.minor) ) {
rv = fwSlot->firmwareVersion;
goto done;
}
if( (void *)NULL != (void *)fwSlot->mdSlot->GetFirmwareVersion ) {
fwSlot->firmwareVersion = fwSlot->mdSlot->GetFirmwareVersion(
fwSlot->mdSlot, fwSlot, fwSlot->mdInstance, fwSlot->fwInstance);
} else {
fwSlot->firmwareVersion.major = 0;
fwSlot->firmwareVersion.minor = 1;
}
rv = fwSlot->firmwareVersion;
done:
(void)nssCKFWMutex_Unlock(fwSlot->mutex);
return rv;
}
/*
* nssCKFWSlot_GetToken
*
*/
NSS_IMPLEMENT NSSCKFWToken *
nssCKFWSlot_GetToken
(
NSSCKFWSlot *fwSlot,
CK_RV *pError
)
{
NSSCKMDToken *mdToken;
NSSCKFWToken *fwToken;
#ifdef NSSDEBUG
if( (CK_RV *)NULL == pError ) {
return (NSSCKFWToken *)NULL;
}
*pError = nssCKFWSlot_verifyPointer(fwSlot);
if( CKR_OK != *pError ) {
return (NSSCKFWToken *)NULL;
}
#endif /* NSSDEBUG */
*pError = nssCKFWMutex_Lock(fwSlot->mutex);
if( CKR_OK != *pError ) {
return (NSSCKFWToken *)NULL;
}
if( (NSSCKFWToken *)NULL == fwSlot->fwToken ) {
if( (void *)NULL == (void *)fwSlot->mdSlot->GetToken ) {
*pError = CKR_GENERAL_ERROR;
fwToken = (NSSCKFWToken *)NULL;
goto done;
}
mdToken = fwSlot->mdSlot->GetToken(fwSlot->mdSlot, fwSlot,
fwSlot->mdInstance, fwSlot->fwInstance, pError);
if( (NSSCKMDToken *)NULL == mdToken ) {
if( CKR_OK == *pError ) {
*pError = CKR_GENERAL_ERROR;
}
return (NSSCKFWToken *)NULL;
}
fwToken = nssCKFWToken_Create(fwSlot, mdToken, pError);
fwSlot->fwToken = fwToken;
} else {
fwToken = fwSlot->fwToken;
}
done:
(void)nssCKFWMutex_Unlock(fwSlot->mutex);
return fwToken;
}
/*
* nssCKFWSlot_ClearToken
*
*/
NSS_IMPLEMENT void
nssCKFWSlot_ClearToken
(
NSSCKFWSlot *fwSlot
)
{
#ifdef NSSDEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return;
}
#endif /* NSSDEBUG */
if( CKR_OK != nssCKFWMutex_Lock(fwSlot->mutex) ) {
/* Now what? */
return;
}
fwSlot->fwToken = (NSSCKFWToken *)NULL;
(void)nssCKFWMutex_Unlock(fwSlot->mutex);
return;
}
/*
* NSSCKFWSlot_GetMDSlot
*
*/
NSS_IMPLEMENT NSSCKMDSlot *
NSSCKFWSlot_GetMDSlot
(
NSSCKFWSlot *fwSlot
)
{
#ifdef DEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return (NSSCKMDSlot *)NULL;
}
#endif /* DEBUG */
return nssCKFWSlot_GetMDSlot(fwSlot);
}
/*
* NSSCKFWSlot_GetFWInstance
*
*/
NSS_IMPLEMENT NSSCKFWInstance *
NSSCKFWSlot_GetFWInstance
(
NSSCKFWSlot *fwSlot
)
{
#ifdef DEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return (NSSCKFWInstance *)NULL;
}
#endif /* DEBUG */
return nssCKFWSlot_GetFWInstance(fwSlot);
}
/*
* NSSCKFWSlot_GetMDInstance
*
*/
NSS_IMPLEMENT NSSCKMDInstance *
NSSCKFWSlot_GetMDInstance
(
NSSCKFWSlot *fwSlot
)
{
#ifdef DEBUG
if( CKR_OK != nssCKFWSlot_verifyPointer(fwSlot) ) {
return (NSSCKMDInstance *)NULL;
}
#endif /* DEBUG */
return nssCKFWSlot_GetMDInstance(fwSlot);
}