summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ckfw/slot.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ckfw/slot.c')
-rw-r--r--security/nss/lib/ckfw/slot.c694
1 files changed, 694 insertions, 0 deletions
diff --git a/security/nss/lib/ckfw/slot.c b/security/nss/lib/ckfw/slot.c
new file mode 100644
index 0000000000..43d4f0d572
--- /dev/null
+++ b/security/nss/lib/ckfw/slot.c
@@ -0,0 +1,694 @@
+/* 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/. */
+
+/*
+ * 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
+ * NSSCKFWSlot_GetSlotID
+ *
+ * -- implement public accessors --
+ * nssCKFWSlot_GetMDSlot
+ * nssCKFWSlot_GetFWInstance
+ * nssCKFWSlot_GetMDInstance
+ * nssCKFWSlot_GetSlotID
+ *
+ * -- private accessors --
+ * 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 (!pError) {
+ return (NSSCKFWSlot *)NULL;
+ }
+
+ *pError = nssCKFWInstance_verifyPointer(fwInstance);
+ if (CKR_OK != *pError) {
+ return (NSSCKFWSlot *)NULL;
+ }
+#endif /* NSSDEBUG */
+
+ mdInstance = nssCKFWInstance_GetMDInstance(fwInstance);
+ if (!mdInstance) {
+ *pError = CKR_GENERAL_ERROR;
+ return (NSSCKFWSlot *)NULL;
+ }
+
+ arena = nssCKFWInstance_GetArena(fwInstance, pError);
+ if (!arena) {
+ if (CKR_OK == *pError) {
+ *pError = CKR_GENERAL_ERROR;
+ }
+ }
+
+ fwSlot = nss_ZNEW(arena, NSSCKFWSlot);
+ if (!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 (!fwSlot->mutex) {
+ if (CKR_OK == *pError) {
+ *pError = CKR_GENERAL_ERROR;
+ }
+ (void)nss_ZFreeIf(fwSlot);
+ return (NSSCKFWSlot *)NULL;
+ }
+
+ if (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 (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 (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 (!fwSlot->slotDescription) {
+ if (fwSlot->mdSlot->GetSlotDescription) {
+ fwSlot->slotDescription = fwSlot->mdSlot->GetSlotDescription(
+ fwSlot->mdSlot, fwSlot, fwSlot->mdInstance,
+ fwSlot->fwInstance, &error);
+ if ((!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 (!fwSlot->manufacturerID) {
+ if (fwSlot->mdSlot->GetManufacturerID) {
+ fwSlot->manufacturerID = fwSlot->mdSlot->GetManufacturerID(
+ fwSlot->mdSlot, fwSlot, fwSlot->mdInstance,
+ fwSlot->fwInstance, &error);
+ if ((!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 (!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 (!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 (!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 (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 (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 (!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 (!fwSlot->fwToken) {
+ if (!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 (!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);
+}
+
+/*
+ * NSSCKFWSlot_GetSlotID
+ *
+ */
+
+NSS_IMPLEMENT CK_SLOT_ID
+NSSCKFWSlot_GetSlotID(
+ NSSCKFWSlot *fwSlot)
+{
+ return nssCKFWSlot_GetSlotID(fwSlot);
+}