[SmartcardServices-Changes] [136] trunk

source_changes at macosforge.org source_changes at macosforge.org
Tue Nov 16 12:07:03 PST 2010


Revision: 136
          http://trac.macosforge.org/projects/smartcardservices/changeset/136
Author:   geddis at apple.com
Date:     2010-11-16 12:07:01 -0800 (Tue, 16 Nov 2010)
Log Message:
-----------
Post Source Code for TokendPKCS11 for 10.5/10.6

Added Paths:
-----------
    trunk/TokendPKCS11/
    trunk/TokendPKCS11/DesignNotes.txt
    trunk/TokendPKCS11/TokendPKCS11.exp
    trunk/TokendPKCS11/TokendPKCS11.xcodeproj/
    trunk/TokendPKCS11/TokendPKCS11.xcodeproj/project.pbxproj
    trunk/TokendPKCS11/TokendPKCS11Proj.xcconfig
    trunk/TokendPKCS11/TokendPKCS11Target.xcconfig
    trunk/TokendPKCS11/TokendPKCS11_Prefix.pch
    trunk/TokendPKCS11/include/
    trunk/TokendPKCS11/include/CFUtilities.h
    trunk/TokendPKCS11/include/HandleManager.h
    trunk/TokendPKCS11/include/IteratorUtilities.h
    trunk/TokendPKCS11/include/P11Attribute.h
    trunk/TokendPKCS11/include/P11CryptoState.h
    trunk/TokendPKCS11/include/P11Identity.h
    trunk/TokendPKCS11/include/P11Mutexes.h
    trunk/TokendPKCS11/include/P11Object.h
    trunk/TokendPKCS11/include/P11Session.h
    trunk/TokendPKCS11/include/P11Slot.h
    trunk/TokendPKCS11/include/P11Slots.h
    trunk/TokendPKCS11/include/P11State.h
    trunk/TokendPKCS11/include/TLV.h
    trunk/TokendPKCS11/include/Utilities.h
    trunk/TokendPKCS11/include/byte_string.h
    trunk/TokendPKCS11/include/config-objects.h
    trunk/TokendPKCS11/include/config.h
    trunk/TokendPKCS11/include/pkcs11.h
    trunk/TokendPKCS11/src/
    trunk/TokendPKCS11/src/CFUtilities.cpp
    trunk/TokendPKCS11/src/HandleManager.inc
    trunk/TokendPKCS11/src/P11Attribute.cpp
    trunk/TokendPKCS11/src/P11CryptoState.cpp
    trunk/TokendPKCS11/src/P11Identity.cpp
    trunk/TokendPKCS11/src/P11Mutexes.cpp
    trunk/TokendPKCS11/src/P11Object.cpp
    trunk/TokendPKCS11/src/P11Session.cpp
    trunk/TokendPKCS11/src/P11Slot.cpp
    trunk/TokendPKCS11/src/P11Slots.cpp
    trunk/TokendPKCS11/src/P11State.cpp
    trunk/TokendPKCS11/src/TLV.cpp
    trunk/TokendPKCS11/src/TLV.inc
    trunk/TokendPKCS11/src/Utilities.cpp
    trunk/TokendPKCS11/src/p11-global.cpp
    trunk/TokendPKCS11/src/p11-keyops.cpp
    trunk/TokendPKCS11/src/p11-object.cpp
    trunk/TokendPKCS11/src/p11-othercrypt.cpp
    trunk/TokendPKCS11/src/p11-personalization.cpp
    trunk/TokendPKCS11/src/p11-pubkey.cpp
    trunk/TokendPKCS11/src/p11-session.cpp
    trunk/TokendPKCS11/src/p11-slot.cpp
    trunk/TokendPKCS11/src/p11-unsupported.cpp

Added: trunk/TokendPKCS11/DesignNotes.txt
===================================================================
--- trunk/TokendPKCS11/DesignNotes.txt	                        (rev 0)
+++ trunk/TokendPKCS11/DesignNotes.txt	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,12 @@
+Slots: there is a minimum number of slots that the PKCS#11 will start out w/
+	These will be empty w/ removable media
+
+	If more than the minimum # of slots exist, then the list will grow to accomodate
+	When any slot is 'removed' then it is removed only at the following condition:
+		Refresh requested (list slots) AND the # of slots is greater than the max idle
+
+	On refresh, if the slot is to be removed, but is in use, it is kept around until the next refresh
+
+Slot IDs increment from 0 -> max - 1
+
+If a slot is removed and there are active slots above it numerically, then it 'will' be present.

Added: trunk/TokendPKCS11/TokendPKCS11.exp
===================================================================
--- trunk/TokendPKCS11/TokendPKCS11.exp	                        (rev 0)
+++ trunk/TokendPKCS11/TokendPKCS11.exp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,68 @@
+_C_CancelFunction
+_C_CloseAllSessions
+_C_CloseSession
+_C_CopyObject
+_C_CreateObject
+_C_Decrypt
+_C_DecryptDigestUpdate
+_C_DecryptFinal
+_C_DecryptInit
+_C_DecryptUpdate
+_C_DecryptVerifyUpdate
+_C_DeriveKey
+_C_DestroyObject
+_C_Digest
+_C_DigestEncryptUpdate
+_C_DigestFinal
+_C_DigestInit
+_C_DigestKey
+_C_DigestUpdate
+_C_Encrypt
+_C_EncryptFinal
+_C_EncryptInit
+_C_EncryptUpdate
+_C_Finalize
+_C_FindObjects
+_C_FindObjectsFinal
+_C_FindObjectsInit
+_C_GenerateKey
+_C_GenerateKeyPair
+_C_GenerateRandom
+_C_GetAttributeValue
+_C_GetFunctionList
+_C_GetFunctionStatus
+_C_GetInfo
+_C_GetMechanismInfo
+_C_GetMechanismList
+_C_GetObjectSize
+_C_GetOperationState
+_C_GetSessionInfo
+_C_GetSlotInfo
+_C_GetSlotList
+_C_GetTokenInfo
+_C_InitPIN
+_C_InitToken
+_C_Initialize
+_C_Login
+_C_Logout
+_C_OpenSession
+_C_SeedRandom
+_C_SetAttributeValue
+_C_SetOperationState
+_C_SetPIN
+_C_Sign
+_C_SignEncryptUpdate
+_C_SignFinal
+_C_SignInit
+_C_SignRecover
+_C_SignRecoverInit
+_C_SignUpdate
+_C_UnwrapKey
+_C_Verify
+_C_VerifyFinal
+_C_VerifyInit
+_C_VerifyRecover
+_C_VerifyRecoverInit
+_C_VerifyUpdate
+_C_WaitForSlotEvent
+_C_WrapKey

Added: trunk/TokendPKCS11/TokendPKCS11.xcodeproj/project.pbxproj
===================================================================
--- trunk/TokendPKCS11/TokendPKCS11.xcodeproj/project.pbxproj	                        (rev 0)
+++ trunk/TokendPKCS11/TokendPKCS11.xcodeproj/project.pbxproj	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,391 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		46DC03860EB9FED6001E43CF /* pkcs11.h in Headers */ = {isa = PBXBuildFile; fileRef = 46DC035D0EB9FED6001E43CF /* pkcs11.h */; };
+		46DC03890EB9FED6001E43CF /* CFUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03610EB9FED6001E43CF /* CFUtilities.cpp */; };
+		46DC038B0EB9FED6001E43CF /* p11-global.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03630EB9FED6001E43CF /* p11-global.cpp */; };
+		46DC038C0EB9FED6001E43CF /* p11-keyops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03640EB9FED6001E43CF /* p11-keyops.cpp */; };
+		46DC038D0EB9FED6001E43CF /* p11-object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03650EB9FED6001E43CF /* p11-object.cpp */; };
+		46DC038E0EB9FED6001E43CF /* p11-othercrypt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03660EB9FED6001E43CF /* p11-othercrypt.cpp */; };
+		46DC038F0EB9FED6001E43CF /* p11-personalization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03670EB9FED6001E43CF /* p11-personalization.cpp */; };
+		46DC03900EB9FED6001E43CF /* p11-pubkey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03680EB9FED6001E43CF /* p11-pubkey.cpp */; };
+		46DC03910EB9FED6001E43CF /* p11-session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03690EB9FED6001E43CF /* p11-session.cpp */; };
+		46DC03920EB9FED6001E43CF /* p11-slot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC036A0EB9FED6001E43CF /* p11-slot.cpp */; };
+		46DC03930EB9FED6001E43CF /* p11-unsupported.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC036B0EB9FED6001E43CF /* p11-unsupported.cpp */; };
+		46DC03940EB9FED6001E43CF /* P11Attribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC036C0EB9FED6001E43CF /* P11Attribute.cpp */; };
+		46DC03950EB9FED6001E43CF /* P11CryptoState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC036D0EB9FED6001E43CF /* P11CryptoState.cpp */; };
+		46DC03960EB9FED6001E43CF /* P11Identity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC036E0EB9FED6001E43CF /* P11Identity.cpp */; };
+		46DC03970EB9FED6001E43CF /* P11Mutexes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC036F0EB9FED6001E43CF /* P11Mutexes.cpp */; };
+		46DC03980EB9FED6001E43CF /* P11Object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03700EB9FED6001E43CF /* P11Object.cpp */; };
+		46DC03990EB9FED6001E43CF /* P11Session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03710EB9FED6001E43CF /* P11Session.cpp */; };
+		46DC039A0EB9FED6001E43CF /* P11Slot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03720EB9FED6001E43CF /* P11Slot.cpp */; };
+		46DC039B0EB9FED6001E43CF /* P11Slots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03730EB9FED6001E43CF /* P11Slots.cpp */; };
+		46DC039C0EB9FED6001E43CF /* P11State.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03740EB9FED6001E43CF /* P11State.cpp */; };
+		46DC039D0EB9FED6001E43CF /* TLV.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03750EB9FED6001E43CF /* TLV.cpp */; };
+		46DC039F0EB9FED6001E43CF /* Utilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46DC03770EB9FED6001E43CF /* Utilities.cpp */; };
+		46DC03A50EB9FEF1001E43CF /* security_utilities.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46DC03A40EB9FEF1001E43CF /* security_utilities.framework */; };
+		46DC03E40EBA0293001E43CF /* config-objects.h in Headers */ = {isa = PBXBuildFile; fileRef = 46DC03E30EBA0293001E43CF /* config-objects.h */; };
+		52DEA5870EC2660E003D3FBA /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52DEA5860EC2660E003D3FBA /* Security.framework */; };
+		52EDC4660EC2240C00504944 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52EDC4650EC2240C00504944 /* CoreFoundation.framework */; };
+		52EDC4DC0EC25DF800504944 /* TokendPKCS11_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 52EDC4DB0EC25DF800504944 /* TokendPKCS11_Prefix.pch */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		46DC034F0EB9FED6001E43CF /* byte_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = byte_string.h; sourceTree = "<group>"; };
+		46DC03500EB9FED6001E43CF /* CFUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFUtilities.h; sourceTree = "<group>"; };
+		46DC03510EB9FED6001E43CF /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
+		46DC03520EB9FED6001E43CF /* HandleManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandleManager.h; sourceTree = "<group>"; };
+		46DC03530EB9FED6001E43CF /* IteratorUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IteratorUtilities.h; sourceTree = "<group>"; };
+		46DC03540EB9FED6001E43CF /* P11Attribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P11Attribute.h; sourceTree = "<group>"; };
+		46DC03550EB9FED6001E43CF /* P11CryptoState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P11CryptoState.h; sourceTree = "<group>"; };
+		46DC03560EB9FED6001E43CF /* P11Identity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P11Identity.h; sourceTree = "<group>"; };
+		46DC03570EB9FED6001E43CF /* P11Mutexes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P11Mutexes.h; sourceTree = "<group>"; };
+		46DC03580EB9FED6001E43CF /* P11Object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P11Object.h; sourceTree = "<group>"; };
+		46DC03590EB9FED6001E43CF /* P11Session.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P11Session.h; sourceTree = "<group>"; };
+		46DC035A0EB9FED6001E43CF /* P11Slot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P11Slot.h; sourceTree = "<group>"; };
+		46DC035B0EB9FED6001E43CF /* P11Slots.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P11Slots.h; sourceTree = "<group>"; };
+		46DC035C0EB9FED6001E43CF /* P11State.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = P11State.h; sourceTree = "<group>"; };
+		46DC035D0EB9FED6001E43CF /* pkcs11.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs11.h; sourceTree = "<group>"; };
+		46DC035E0EB9FED6001E43CF /* TLV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TLV.h; sourceTree = "<group>"; };
+		46DC035F0EB9FED6001E43CF /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = "<group>"; };
+		46DC03610EB9FED6001E43CF /* CFUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CFUtilities.cpp; sourceTree = "<group>"; };
+		46DC03620EB9FED6001E43CF /* HandleManager.inc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = HandleManager.inc; sourceTree = "<group>"; };
+		46DC03630EB9FED6001E43CF /* p11-global.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "p11-global.cpp"; sourceTree = "<group>"; };
+		46DC03640EB9FED6001E43CF /* p11-keyops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "p11-keyops.cpp"; sourceTree = "<group>"; };
+		46DC03650EB9FED6001E43CF /* p11-object.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "p11-object.cpp"; sourceTree = "<group>"; };
+		46DC03660EB9FED6001E43CF /* p11-othercrypt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "p11-othercrypt.cpp"; sourceTree = "<group>"; };
+		46DC03670EB9FED6001E43CF /* p11-personalization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "p11-personalization.cpp"; sourceTree = "<group>"; };
+		46DC03680EB9FED6001E43CF /* p11-pubkey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "p11-pubkey.cpp"; sourceTree = "<group>"; };
+		46DC03690EB9FED6001E43CF /* p11-session.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "p11-session.cpp"; sourceTree = "<group>"; };
+		46DC036A0EB9FED6001E43CF /* p11-slot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "p11-slot.cpp"; sourceTree = "<group>"; };
+		46DC036B0EB9FED6001E43CF /* p11-unsupported.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "p11-unsupported.cpp"; sourceTree = "<group>"; };
+		46DC036C0EB9FED6001E43CF /* P11Attribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = P11Attribute.cpp; sourceTree = "<group>"; };
+		46DC036D0EB9FED6001E43CF /* P11CryptoState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = P11CryptoState.cpp; sourceTree = "<group>"; };
+		46DC036E0EB9FED6001E43CF /* P11Identity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = P11Identity.cpp; sourceTree = "<group>"; };
+		46DC036F0EB9FED6001E43CF /* P11Mutexes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = P11Mutexes.cpp; sourceTree = "<group>"; };
+		46DC03700EB9FED6001E43CF /* P11Object.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = P11Object.cpp; sourceTree = "<group>"; };
+		46DC03710EB9FED6001E43CF /* P11Session.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = P11Session.cpp; sourceTree = "<group>"; };
+		46DC03720EB9FED6001E43CF /* P11Slot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = P11Slot.cpp; sourceTree = "<group>"; };
+		46DC03730EB9FED6001E43CF /* P11Slots.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = P11Slots.cpp; sourceTree = "<group>"; };
+		46DC03740EB9FED6001E43CF /* P11State.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = P11State.cpp; sourceTree = "<group>"; };
+		46DC03750EB9FED6001E43CF /* TLV.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TLV.cpp; sourceTree = "<group>"; };
+		46DC03760EB9FED6001E43CF /* TLV.inc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = TLV.inc; sourceTree = "<group>"; };
+		46DC03770EB9FED6001E43CF /* Utilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utilities.cpp; sourceTree = "<group>"; };
+		46DC03A40EB9FEF1001E43CF /* security_utilities.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = security_utilities.framework; path = /usr/local/SecurityPieces/Frameworks/security_utilities.framework; sourceTree = "<absolute>"; };
+		46DC03E30EBA0293001E43CF /* config-objects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "config-objects.h"; sourceTree = "<group>"; };
+		52DEA5860EC2660E003D3FBA /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = "<absolute>"; };
+		52DEA6020EC37001003D3FBA /* TokendPKCS11.exp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.exports; path = TokendPKCS11.exp; sourceTree = "<group>"; };
+		52EDC4650EC2240C00504944 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+		52EDC4D70EC25DA800504944 /* TokendPKCS11Proj.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = TokendPKCS11Proj.xcconfig; sourceTree = "<group>"; };
+		52EDC4D80EC25DA800504944 /* TokendPKCS11Target.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = TokendPKCS11Target.xcconfig; sourceTree = "<group>"; };
+		52EDC4DB0EC25DF800504944 /* TokendPKCS11_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TokendPKCS11_Prefix.pch; sourceTree = "<group>"; };
+		D2AAC09D05546B4700DB518D /* tokendPKCS11.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = tokendPKCS11.so; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		D2AAC09B05546B4700DB518D /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				46DC03A50EB9FEF1001E43CF /* security_utilities.framework in Frameworks */,
+				52EDC4660EC2240C00504944 /* CoreFoundation.framework in Frameworks */,
+				52DEA5870EC2660E003D3FBA /* Security.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		034768DDFF38A45A11DB9C8B /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				D2AAC09D05546B4700DB518D /* tokendPKCS11.so */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		0867D691FE84028FC02AAC07 /* tokend-pkcs11 */ = {
+			isa = PBXGroup;
+			children = (
+				52DEA6020EC37001003D3FBA /* TokendPKCS11.exp */,
+				5073E0CA09E734BC00EC74B6 /* Configuration Files */,
+				08FB77ACFE841707C02AAC07 /* Source */,
+				0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+				034768DDFF38A45A11DB9C8B /* Products */,
+			);
+			name = "tokend-pkcs11";
+			sourceTree = "<group>";
+		};
+		0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				52DEA5860EC2660E003D3FBA /* Security.framework */,
+				52EDC4650EC2240C00504944 /* CoreFoundation.framework */,
+				46DC03A40EB9FEF1001E43CF /* security_utilities.framework */,
+			);
+			name = "External Frameworks and Libraries";
+			sourceTree = "<group>";
+		};
+		08FB77ACFE841707C02AAC07 /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				52EDC4DB0EC25DF800504944 /* TokendPKCS11_Prefix.pch */,
+				46DC034E0EB9FED6001E43CF /* include */,
+				46DC03600EB9FED6001E43CF /* src */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		46DC034E0EB9FED6001E43CF /* include */ = {
+			isa = PBXGroup;
+			children = (
+				46DC034F0EB9FED6001E43CF /* byte_string.h */,
+				46DC03500EB9FED6001E43CF /* CFUtilities.h */,
+				46DC03510EB9FED6001E43CF /* config.h */,
+				46DC03E30EBA0293001E43CF /* config-objects.h */,
+				46DC03520EB9FED6001E43CF /* HandleManager.h */,
+				46DC03530EB9FED6001E43CF /* IteratorUtilities.h */,
+				46DC03540EB9FED6001E43CF /* P11Attribute.h */,
+				46DC03550EB9FED6001E43CF /* P11CryptoState.h */,
+				46DC03560EB9FED6001E43CF /* P11Identity.h */,
+				46DC03570EB9FED6001E43CF /* P11Mutexes.h */,
+				46DC03580EB9FED6001E43CF /* P11Object.h */,
+				46DC03590EB9FED6001E43CF /* P11Session.h */,
+				46DC035A0EB9FED6001E43CF /* P11Slot.h */,
+				46DC035B0EB9FED6001E43CF /* P11Slots.h */,
+				46DC035C0EB9FED6001E43CF /* P11State.h */,
+				46DC035D0EB9FED6001E43CF /* pkcs11.h */,
+				46DC035E0EB9FED6001E43CF /* TLV.h */,
+				46DC035F0EB9FED6001E43CF /* Utilities.h */,
+			);
+			path = include;
+			sourceTree = "<group>";
+		};
+		46DC03600EB9FED6001E43CF /* src */ = {
+			isa = PBXGroup;
+			children = (
+				46DC03610EB9FED6001E43CF /* CFUtilities.cpp */,
+				46DC03620EB9FED6001E43CF /* HandleManager.inc */,
+				46DC03630EB9FED6001E43CF /* p11-global.cpp */,
+				46DC03640EB9FED6001E43CF /* p11-keyops.cpp */,
+				46DC03650EB9FED6001E43CF /* p11-object.cpp */,
+				46DC03660EB9FED6001E43CF /* p11-othercrypt.cpp */,
+				46DC03670EB9FED6001E43CF /* p11-personalization.cpp */,
+				46DC03680EB9FED6001E43CF /* p11-pubkey.cpp */,
+				46DC03690EB9FED6001E43CF /* p11-session.cpp */,
+				46DC036A0EB9FED6001E43CF /* p11-slot.cpp */,
+				46DC036B0EB9FED6001E43CF /* p11-unsupported.cpp */,
+				46DC036C0EB9FED6001E43CF /* P11Attribute.cpp */,
+				46DC036D0EB9FED6001E43CF /* P11CryptoState.cpp */,
+				46DC036E0EB9FED6001E43CF /* P11Identity.cpp */,
+				46DC036F0EB9FED6001E43CF /* P11Mutexes.cpp */,
+				46DC03700EB9FED6001E43CF /* P11Object.cpp */,
+				46DC03710EB9FED6001E43CF /* P11Session.cpp */,
+				46DC03720EB9FED6001E43CF /* P11Slot.cpp */,
+				46DC03730EB9FED6001E43CF /* P11Slots.cpp */,
+				46DC03740EB9FED6001E43CF /* P11State.cpp */,
+				46DC03750EB9FED6001E43CF /* TLV.cpp */,
+				46DC03760EB9FED6001E43CF /* TLV.inc */,
+				46DC03770EB9FED6001E43CF /* Utilities.cpp */,
+			);
+			path = src;
+			sourceTree = "<group>";
+		};
+		5073E0CA09E734BC00EC74B6 /* Configuration Files */ = {
+			isa = PBXGroup;
+			children = (
+				52EDC4D70EC25DA800504944 /* TokendPKCS11Proj.xcconfig */,
+				52EDC4D80EC25DA800504944 /* TokendPKCS11Target.xcconfig */,
+			);
+			name = "Configuration Files";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		D2AAC09905546B4700DB518D /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				46DC03860EB9FED6001E43CF /* pkcs11.h in Headers */,
+				46DC03E40EBA0293001E43CF /* config-objects.h in Headers */,
+				52EDC4DC0EC25DF800504944 /* TokendPKCS11_Prefix.pch in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		D2AAC09C05546B4700DB518D /* tokendPKCS11 */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB916008733D950010E9CD /* Build configuration list for PBXNativeTarget "tokendPKCS11" */;
+			buildPhases = (
+				D2AAC09905546B4700DB518D /* Headers */,
+				D2AAC09B05546B4700DB518D /* Frameworks */,
+				D2AAC09A05546B4700DB518D /* Sources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = tokendPKCS11;
+			productName = "libtokend-pkcs11";
+			productReference = D2AAC09D05546B4700DB518D /* tokendPKCS11.so */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		0867D690FE84028FC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "TokendPKCS11" */;
+			compatibilityVersion = "Xcode 3.1";
+			hasScannedForEncodings = 1;
+			mainGroup = 0867D691FE84028FC02AAC07 /* tokend-pkcs11 */;
+			productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				D2AAC09C05546B4700DB518D /* tokendPKCS11 */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		D2AAC09A05546B4700DB518D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				46DC03890EB9FED6001E43CF /* CFUtilities.cpp in Sources */,
+				46DC038B0EB9FED6001E43CF /* p11-global.cpp in Sources */,
+				46DC038C0EB9FED6001E43CF /* p11-keyops.cpp in Sources */,
+				46DC038D0EB9FED6001E43CF /* p11-object.cpp in Sources */,
+				46DC038E0EB9FED6001E43CF /* p11-othercrypt.cpp in Sources */,
+				46DC038F0EB9FED6001E43CF /* p11-personalization.cpp in Sources */,
+				46DC03900EB9FED6001E43CF /* p11-pubkey.cpp in Sources */,
+				46DC03910EB9FED6001E43CF /* p11-session.cpp in Sources */,
+				46DC03920EB9FED6001E43CF /* p11-slot.cpp in Sources */,
+				46DC03930EB9FED6001E43CF /* p11-unsupported.cpp in Sources */,
+				46DC03940EB9FED6001E43CF /* P11Attribute.cpp in Sources */,
+				46DC03950EB9FED6001E43CF /* P11CryptoState.cpp in Sources */,
+				46DC03960EB9FED6001E43CF /* P11Identity.cpp in Sources */,
+				46DC03970EB9FED6001E43CF /* P11Mutexes.cpp in Sources */,
+				46DC03980EB9FED6001E43CF /* P11Object.cpp in Sources */,
+				46DC03990EB9FED6001E43CF /* P11Session.cpp in Sources */,
+				46DC039A0EB9FED6001E43CF /* P11Slot.cpp in Sources */,
+				46DC039B0EB9FED6001E43CF /* P11Slots.cpp in Sources */,
+				46DC039C0EB9FED6001E43CF /* P11State.cpp in Sources */,
+				46DC039D0EB9FED6001E43CF /* TLV.cpp in Sources */,
+				46DC039F0EB9FED6001E43CF /* Utilities.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB916108733D950010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = NO;
+				EXECUTABLE_EXTENSION = so;
+				EXPORTED_SYMBOLS_FILE = TokendPKCS11.exp;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					/usr/local/SecurityPieces/Frameworks,
+				);
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = TokendPKCS11_Prefix.pch;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"_GLIBCXX_DEBUG=1",
+					"_GLIBCXX_DEBUG_PEDANTIC=1",
+				);
+				INSTALL_PATH = /usr/libexec/SmartCardServices/pkcs11;
+				USER_HEADER_SEARCH_PATHS = src;
+			};
+			name = Debug;
+		};
+		1DEB916208733D950010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				EXECUTABLE_EXTENSION = so;
+				EXPORTED_SYMBOLS_FILE = TokendPKCS11.exp;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					/usr/local/SecurityPieces/Frameworks,
+				);
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = TokendPKCS11_Prefix.pch;
+				INSTALL_PATH = /usr/libexec/SmartCardServices/pkcs11;
+				STRIP_INSTALLED_PRODUCT = YES;
+				STRIP_STYLE = "non-global";
+				USER_HEADER_SEARCH_PATHS = src;
+			};
+			name = Release;
+		};
+		1DEB916508733D950010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				PREBINDING = NO;
+				PRODUCT_NAME = tokendPKCS11;
+				SDKROOT = "";
+			};
+			name = Debug;
+		};
+		1DEB916608733D950010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PREBINDING = NO;
+				PRODUCT_NAME = tokendPKCS11;
+				SDKROOT = "";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB916008733D950010E9CD /* Build configuration list for PBXNativeTarget "tokendPKCS11" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB916108733D950010E9CD /* Debug */,
+				1DEB916208733D950010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB916408733D950010E9CD /* Build configuration list for PBXProject "TokendPKCS11" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB916508733D950010E9CD /* Debug */,
+				1DEB916608733D950010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}

Added: trunk/TokendPKCS11/TokendPKCS11Proj.xcconfig
===================================================================
--- trunk/TokendPKCS11/TokendPKCS11Proj.xcconfig	                        (rev 0)
+++ trunk/TokendPKCS11/TokendPKCS11Proj.xcconfig	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,6 @@
+	PREBINDING = NO;
+	GCC_WARN_ABOUT_RETURN_TYPE = YES;
+	GCC_WARN_UNUSED_VARIABLE = YES;
+	GCC_MODEL_TUNING = G5;
+	GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES;
+	GCC_GENERATE_DEBUGGING_SYMBOLS = YES;

Added: trunk/TokendPKCS11/TokendPKCS11Target.xcconfig
===================================================================
--- trunk/TokendPKCS11/TokendPKCS11Target.xcconfig	                        (rev 0)
+++ trunk/TokendPKCS11/TokendPKCS11Target.xcconfig	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,12 @@
+	PRODUCT_NAME = 	tokendPKCS11;
+	INSTALL_PATH = /usr/libexec/SmartCardServices/pkcs11;
+	MACH_O_TYPE = mh_bundle;
+	DYLIB_COMPATIBILITY_VERSION = ;
+	DYLIB_CURRENT_VERSION = ;
+	GCC_PRECOMPILE_PREFIX_HEADER = YES;
+	GCC_PREFIX_HEADER = TokendPKCS11_Prefix.pch;
+	GCC_ENABLE_CPP_EXCEPTIONS = YES;
+	GCC_ENABLE_CPP_RTTI = YES;
+	STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = Dynamic;
+	GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+	WRAPPER_EXTENSION = so;

Added: trunk/TokendPKCS11/TokendPKCS11_Prefix.pch
===================================================================
--- trunk/TokendPKCS11/TokendPKCS11_Prefix.pch	                        (rev 0)
+++ trunk/TokendPKCS11/TokendPKCS11_Prefix.pch	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef PKCS11_ON_TOKEND_PREFIX_H
+#define PKCS11_ON_TOKEND_PREFIX_H
+
+#include <unistd.h>
+#include <stdlib.h>
+
+/* Enable GNU-style cryptoki values */
+#define CRYPTOKI_GNU 1
+
+#include "pkcs11.h"
+
+#include <Security/SecBase.h>
+#include <security_utilities/globalizer.h>
+#include <security_utilities/utilities.h>
+#include <security_utilities/threading.h> /* StLock */
+
+#include <vector>
+#include <memory>
+
+#include <tr1/memory>
+using std::tr1::shared_ptr;
+using std::tr1::weak_ptr;
+
+/* For the cases where set operations are needed */
+#include <map>
+#include <set>
+using std::map;
+using std::set;
+
+typedef unsigned long ulong;
+typedef unsigned char byte;
+
+#endif

Added: trunk/TokendPKCS11/include/CFUtilities.h
===================================================================
--- trunk/TokendPKCS11/include/CFUtilities.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/CFUtilities.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef CFUTILITIES_H
+#define CFUTILITIES_H
+
+#include <tr1/memory>
+
+class CFDeleter {
+public:
+	void operator()(const void* ref) const { call(ref); }
+	static void call(const void* ref);
+};
+
+/* Ref for any CF Type */
+typedef std::tr1::shared_ptr<const void> CFTypeRef_Ref;
+
+inline CFTypeRef_Ref wrapCFRef(const void* ref) {
+	return CFTypeRef_Ref(ref, CFDeleter());
+}
+
+/** Wrapper class around CFTypeRefs that deletes the value on destruction */
+template<typename T, typename D = CFDeleter>
+class ScopedCF {
+	NOCOPY(ScopedCF);
+public:
+	ScopedCF() : ref(NULL) {}
+	ScopedCF(T ref) : ref(ref) {}
+	~ScopedCF() {
+		if(ref) D::call(ref);
+	}
+	/* Get's a pointer to ref - permits usage in functions that want a CF as input™ */
+	T* operator &() { return &ref; }
+	//operator T() { return ref; }
+	T get() const { return ref; }
+	template<typename X>
+	operator X() const { return static_cast<X> (ref); }
+	T release() {
+		T ret = ref;
+		ref = NULL;
+		return ret;
+	}
+private:
+	T ref;
+};
+
+#endif
+

Added: trunk/TokendPKCS11/include/HandleManager.h
===================================================================
--- trunk/TokendPKCS11/include/HandleManager.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/HandleManager.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,215 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef HANDLE_MANAGER_H
+#define HANDLE_MANAGER_H
+
+template<typename T>
+class HandleManager;
+
+static const int INVALID_HANDLE_VALUE = -1;
+
+template<typename T>
+class HandledObject {
+	NOCOPY(HandledObject);
+public:
+	HandledObject() : handle(INVALID_HANDLE_VALUE) {}
+	virtual ~HandledObject() {}
+	int getHandle() const {
+		return handle;
+	}
+	bool isValid() const {
+		return handle != INVALID_HANDLE_VALUE;
+	}
+protected:
+	void invalidate() {
+		this->handle = INVALID_HANDLE_VALUE;
+	}
+
+private:
+	friend class HandleManager<T>;
+	void setHandle(int handle) {
+		this->handle = handle;
+	}
+	int handle;
+};
+
+template<typename T>
+class LockableHandledObject : public HandledObject<T> {
+	NOCOPY(LockableHandledObject);
+public:
+	LockableHandledObject(UserMutex *mutex) : mutex(mutex) {}
+
+	UserMutex &getLock() const { return *mutex; }
+protected:
+	friend class HandleManager<T>;
+	UserMutex *releaseLock() { return mutex.release(); }
+private:
+	mutable auto_ptr<UserMutex> mutex;
+};
+template<typename RefType>
+class Filter {
+public:
+	virtual ~Filter() {}
+	typedef const RefType argument_type;
+	typedef bool return_type; /* If return true, keep value */
+};
+
+template<typename RefType>
+class FilterKeepAll : public Filter<RefType> {
+public:
+	bool operator() (const RefType &value) const {
+		return true;
+	}
+};
+
+template<typename RefType>
+class FilterKeepValid : public Filter<RefType> {
+public:
+	bool operator() (const RefType &value) const {
+		return value.get() && value->isValid();
+	}
+};
+
+/**
+ * Class to handle (zero or custom)-based object-handles in a unified way
+ */
+template<typename T>
+class HandleManager {
+	NOCOPY(HandleManager);
+public:
+	typedef shared_ptr<T> ref_type;
+	typedef std::vector<ref_type> value_collection;
+	typedef HandledObject<T> handled_type;
+	value_collection values;
+
+	typedef typename value_collection::reverse_iterator reverse_iterator;
+	typedef typename value_collection::iterator iterator;
+	typedef typename value_collection::const_iterator const_iterator;
+public:
+	/**
+	 * Initialize the HandleManager with a given base reference
+	 * @param base Value to add to handles returned (for handlespace unification)
+	 */
+	HandleManager(int base = 0);
+
+	/**
+	 * Add a new reference value to the handle manager into an empty slot
+	 * @param ref New value to add
+	 * @param notEmpty Filter that returns success on a non-empty slot (negated during search)
+	 */
+	template<typename Filter>
+	iterator add(ref_type ref, Filter notEmpty);
+
+	/**
+	 * Replace a given iterator's value, updating the new value's handle ref
+	 * @param iter Location to update
+	 * @param ref New value (which has it's location updated
+	 */
+	void replace_value(iterator iter, ref_type ref) {
+		*iter = ref;
+		refresh_active_reference(iter);
+	}
+
+	/**
+	 * Copy out the handles that pass the given filter.
+	 * Example use: dumping out available P11Object handles
+	 *
+	 * @param result Output iterator to dump the results
+	 * @param filter The filter that must 'pass'
+	 */
+	template<typename OutputIterator, typename Filter>
+	void copy_handles(OutputIterator result, Filter filter);
+
+	/**
+	 * Remove from the end everything until the last non 'filter-success' value or there's only size units left
+	 *
+	 * @param min_size Size at which to stop removing values
+	 * @param filter Filter to use in determining whether a value should be a candidate for removal
+	 */
+	template<typename Filter>
+	void remove_after_last_match(size_t min_size, Filter filter);
+
+	/**
+	 * Returns whether `handle` is a valid handle for this pool or not
+	 */
+	bool valid_handle(int handle) const;
+
+	/**
+	 * Find the given `handle` and return it or the `end` marker
+	 */
+	iterator find(int handle) {
+		return !valid_handle(handle) ? values.end() : values.begin() + (handle - base);
+	}
+	/**
+	 * Find the given `handle` and return it or the `end` marker
+	 */
+	const_iterator find(int handle) const {
+		return !valid_handle(handle) ? values.end() : values.begin() + (handle - base);
+	}
+	/**
+	 * Invalidate and release the reference at the given reference location
+	 */
+	void erase(const iterator &iter);
+
+	/**
+	 * Get a lock and 'erase' the value
+	 */
+	void kill_lockable_value(const iterator &iter);
+
+	/**
+	 * Return an iterator pointing to the beginning of the object collection.
+	 * Facilitates manual searching through object values.
+	 */
+	iterator begin() {
+		return values.begin();
+	}
+
+	/**
+	 * Returns an iterator pointing just beyond the end of the object collection.
+	 */
+	iterator end() {
+		return values.end();
+	}
+
+	/**
+	 * Returns an iterator pointing just beyond the end of the object collection.
+	 */
+	const_iterator end() const {
+		return values.end();
+	}
+private:
+	/**
+	 * Refereshes the handle for a given value reference.
+	 * Calculates the correct handle value and assigns it to the contained value.
+	 *
+	 * @param iter Value reference to alter
+	 */
+	void refresh_active_reference(iterator iter);
+	
+	const int base;
+};
+
+#include "HandleManager.inc"
+
+#endif

Added: trunk/TokendPKCS11/include/IteratorUtilities.h
===================================================================
--- trunk/TokendPKCS11/include/IteratorUtilities.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/IteratorUtilities.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,110 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef ITERATOR_UTILITIES_H
+#define ITERATOR_UTILITIES_H
+
+template<typename T>
+const T *dereference(const shared_ptr<T> &value) {
+	return value->get();
+}
+template<typename T, typename T2>
+const T *dereference_key(const std::pair<shared_ptr<T>, T2> &value) {
+	return value.first->get();
+}
+template<typename T>
+const typename T::first_type &get_key(const T &pair) {
+	return pair.first;
+}
+
+template<typename T, typename TList, typename F>
+class TransformCopier {
+public:
+	TransformCopier(F func) : func(func) {}
+	void operator() (T *to, const TList &from) {
+		transform(from.begin(), from.end(), to, func);
+	}
+private:
+	F func;
+};
+
+template<typename T, typename TList>
+class SimpleCopier {
+public:
+	void operator() (T *to, const TList &from) {
+		copy(from.begin(), from.end(), to);
+	}
+};	
+
+template<typename T, typename TList, typename CopyOp>
+ck_rv_t generic_copy_checked(T *to, const TList &from, size_t &size, CopyOp copier) {
+	if(!to) {
+		size = from.size();
+		return CKR_OK;
+	}
+	if(size < from.size()) {
+		size = from.size();
+		return CKR_BUFFER_TOO_SMALL;
+	}
+	size = from.size();
+	copier(to, from);
+	return CKR_OK;
+}
+
+
+template<typename T, typename TList, typename F>
+ck_rv_t copy_transformed_list(T *to, const TList &from, size_t &size, F func) {
+	return generic_copy_checked(to, from, size, TransformCopier<T,TList,F>(func));
+}
+
+template<typename T, typename TList>
+ck_rv_t copy_list(T *to, const TList &from, size_t &size) {
+	return generic_copy_checked(to, from, size, SimpleCopier<T,TList>());	
+}
+
+template<typename T, typename TList>
+ck_rv_t copy_list_of_refs(T *to, const TList &from, size_t &size) {
+	return copy_transformed_list(to, from, size, dereference<T>);
+}
+template<typename T, typename TMap>
+ck_rv_t copy_list_of_key_refs(T *to, const TMap &from, size_t &size) {
+	return copy_transformed_list(to, from, size, dereference_key<T, typename TMap::mapped_type>);
+}
+
+template<typename T, typename TMap>
+ck_rv_t copy_list_of_keys(T *to, const TMap &from, size_t &size) {
+	return copy_transformed_list(to, from, size, get_key<typename TMap::value_type>);
+}
+
+template<typename InputIterator, typename OutputIterator, typename Predicate>
+OutputIterator copy_if(InputIterator first, InputIterator last, OutputIterator result, Predicate pred) {
+	for(; first != last; ++first) {
+		if(pred(*first)) {
+			*result = *first;
+			++result;
+		}
+	}
+	return result;
+}
+
+#endif

Added: trunk/TokendPKCS11/include/P11Attribute.h
===================================================================
--- trunk/TokendPKCS11/include/P11Attribute.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/P11Attribute.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,127 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef P11ATTRIBUTE_H
+#define P11ATTRIBUTE_H
+
+
+/**
+ * PKCS#11 Attribute wrapper object
+ */
+class P11Attribute : public ck_attribute {
+	NOCOPY(P11Attribute);
+public:
+	/** Construct an attribute from the given type and data */
+	P11Attribute(ck_attribute_type_t type, const void *data, size_t data_len);
+
+	/**
+	 * Initializes the attribute with a PKCS#11 spec attribute
+	 */
+	P11Attribute(const struct ck_attribute &ckattr);
+	/** Releases the internally held 'value' ptr */
+	~P11Attribute();
+
+	/**
+	 * Returns boolean value of attribute
+	 * @pre Attribute must be an integer size (1,2,4,8 on 64-bit)
+	 */
+	bool getBool() const;
+	/**
+	 * Returns native integer value of attribute
+	 * @pre Attribute must be an integer size (1,2,4,8 on 64-bit)
+	 */
+	long getLong() const;
+
+	/** Compare two P11Attributes for equality in type and value */
+	bool operator ==(const P11Attribute& comparand) const;
+private:
+	/** Initializes the object with the given type and data */
+	void init(ck_attribute_type_t type, const void *data, size_t data_len);
+};
+
+typedef shared_ptr<P11Attribute> P11Attribute_Ref;
+typedef map<ck_attribute_type_t,P11Attribute_Ref> P11AttributeMap;
+
+/**
+ * Object attribute container, used for both searches and data retreival
+ */
+class P11Attributes {
+public:
+	/** Construct an empty attribute container */
+	P11Attributes();
+	/** Construct an attribute container pre-populated with values */
+	P11Attributes(struct ck_attribute *templates, ulong count);
+
+	/** Obtain the CKA_CLASS value in ck_object_class_t form */
+	ck_object_class_t oclass() const;
+
+	/**
+	 * Adds a long integer attribute (native byte-order)
+	 * @param type Type of attribute
+	 * @param value Value of attribute
+	 */
+	void addLong(ck_attribute_type_t type, long value) {
+		add(type, &value, sizeof(value));
+	}
+	/**
+	 * Adds a boolean attribute
+	 * @param type Type of attribute
+	 * @param value Value of attribute
+	 */
+	void addBool(ck_attribute_type_t type, bool value) {
+		unsigned char bool_char = value ? 1 : 0;
+		add(type, &bool_char, sizeof(bool_char));
+	}
+	/**
+	 * Adds a single-byte attribute
+	 * @param type Type of attribute
+	 * @param value Value of attribute
+	 */
+	void addByte(ck_attribute_type_t type, byte value) {
+		add(type, &value, sizeof(value));
+	}
+	/**
+	 * Adds an arbitrary attribute
+	 * @param type Type of attribute
+	 * @param data Attribute value
+	 * @param data_len Length of attribute
+	 */
+	void add(ck_attribute_type_t type, const void *data, size_t data_len);
+	/**
+	 * Pull attributes out in PKCS#11 form
+	 * @param templates In/Out array of attributes to populate
+	 * @param count Number of attributes
+	 * @return CKR_* compliant with PKCS#11 specification for C_GetAttributeValue
+	 */
+	ck_rv_t get(struct ck_attribute *templates, ulong count) const;
+
+	/**
+	 * Return whether this attribute collection contains at least each search element
+	 * @param search The attribute collection to match against
+	 */
+	bool match(const P11Attributes &search) const;
+private:
+	P11AttributeMap attributes;
+};
+
+#endif

Added: trunk/TokendPKCS11/include/P11CryptoState.h
===================================================================
--- trunk/TokendPKCS11/include/P11CryptoState.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/P11CryptoState.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef P11CRYPTOSTATE_H
+#define P11CRYPTOSTATE_H
+
+#include "P11Object.h"
+
+class P11CryptoState {
+public:
+	/** Construct a crypto state w/ a given key and mechanism
+	 * If they are incompatible/invalid, throw an exception
+	 */
+	P11CryptoState(P11Object_Ref key, const struct ck_mechanism &mechanism);
+	virtual ~P11CryptoState();
+
+	/** Perform decryption using the given key and mechanism
+	 * May cause authentication prompts
+	 */
+	ck_rv_t decrypt(const byte *input, ulong input_len, byte *output, ulong &output_len);
+	/** Perform signature using the given key and mechanism
+	 * May cause authentication prompts
+	 * XXX: Currently uses raw decryption, should use actual signature algorithms
+	 */
+	ck_rv_t sign(const byte *input, ulong input_len, byte *output, ulong &output_len);
+
+private:
+	P11Object_Ref key;
+	struct ck_mechanism mechanism;
+
+	SecIdentityRef getIdentityRef() const;
+};
+
+
+#endif

Added: trunk/TokendPKCS11/include/P11Identity.h
===================================================================
--- trunk/TokendPKCS11/include/P11Identity.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/P11Identity.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef P11IDENTITY_H
+#define P11IDENTITY_H
+
+#include "P11Object.h"
+#include "HandleManager.h"
+
+class P11Identity;
+typedef shared_ptr<P11Identity> P11Identity_Ref;
+
+/* Represents a set of Private, Public, Cert */
+class P11Identity : public HandledObject<P11Identity> {
+	NOCOPY(P11Identity);
+public:
+	virtual ~P11Identity();
+	
+	SecIdentityRef getIdentity() { return identity; }
+protected:
+	friend class P11Identities;
+	P11Identity(SecIdentityRef identity);
+
+private:
+	bool createObjects(P11Objects_Ref objectContainer, P11Identity_Ref &identity_reference);
+	/* Weak references since P11Objects is the lifetime maintainer */
+	P11Object_WeakRef privateKey;
+	P11Object_WeakRef publicKey;
+	P11Object_WeakRef certificate;
+
+	SecIdentityRef identity;
+};
+
+class P11Identities {
+	NOCOPY(P11Identities);
+public:
+	P11Identities();
+	void createIdentity(P11Objects_Ref objectContainer, SecIdentityRef identity);
+private:
+	typedef HandleManager<P11Identity> IdentityManager;
+	IdentityManager identities;
+};
+
+#endif
+

Added: trunk/TokendPKCS11/include/P11Mutexes.h
===================================================================
--- trunk/TokendPKCS11/include/P11Mutexes.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/P11Mutexes.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef P11MUTEXES_H
+#define P11MUTEXES_H
+
+#include "Utilities.h"
+
+class SystemMutexFactory : public Factory<UserMutex> {
+	NOCOPY(SystemMutexFactory);
+public:
+	SystemMutexFactory() {}
+	UserMutex *create();
+};
+
+class NullMutexFactory : public Factory<UserMutex> {
+	NOCOPY(NullMutexFactory);
+public:
+	NullMutexFactory() {}
+	UserMutex *create();
+};
+
+class AppMutexFactory : public Factory<UserMutex> {
+	NOCOPY(AppMutexFactory);
+public:
+	AppMutexFactory(const void *init_args)
+	: init_args(init_args) {
+	}
+	UserMutex *create();
+private:
+	const void *init_args;
+};
+
+#endif

Added: trunk/TokendPKCS11/include/P11Object.h
===================================================================
--- trunk/TokendPKCS11/include/P11Object.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/P11Object.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,131 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef P11OBJECT_H
+#define P11OBJECT_H
+
+#include "Utilities.h"
+#include "P11Mutexes.h"
+#include "P11Attribute.h"
+
+#include "HandleManager.h"
+
+class P11Identity;
+typedef weak_ptr<P11Identity> P11Identity_WeakRef;
+
+
+class P11Objects;
+typedef shared_ptr<P11Objects> P11Objects_Ref;
+typedef weak_ptr<P11Objects> P11Objects_WeakRef;
+
+/* A PKCS #11 object (session or on-card) */
+class P11Object : public LockableHandledObject<P11Object> {
+	NOCOPY(P11Object);
+private:
+	friend class P11ObjectCreator;
+	P11Object(P11Objects_WeakRef parent, ck_object_class_t objectClass, const P11Attributes &attrTemplate);
+public:
+	virtual ~P11Object();
+
+	void setIdentity(P11Identity_WeakRef identity) { this->identity = identity; }
+
+	/* Shortcut attribute */
+	ck_object_class_t oclass() const;
+
+	const P11Attributes &getAttributes() const;
+
+	ck_object_handle_t getHandle() const {
+		return HandledObject<P11Object>::getHandle();
+	}
+
+	P11Objects_WeakRef getParent() const { return parent; }
+	/* Return the associated identity if it exists */
+	P11Identity_WeakRef getIdentity() const { return identity; }
+protected:
+	auto_ptr<P11Attributes> attributes;
+	P11Objects_WeakRef parent;
+	P11Identity_WeakRef identity;
+};
+
+typedef shared_ptr<P11Object> P11Object_Ref;
+typedef weak_ptr<P11Object> P11Object_WeakRef;
+typedef std::vector<ck_object_handle_t> P11ObjectHandleList;
+
+class P11ObjectCreator {
+private:
+	friend class P11Identity;
+	friend class P11Objects;
+	static P11Object_Ref create(P11Objects_WeakRef parent, ck_object_class_t objectClass, const P11Attributes &attributes) {
+		return P11Object_Ref(new P11Object(parent, objectClass, attributes));
+	}
+};
+
+class P11Objects;
+typedef shared_ptr<P11Objects> P11Objects_Ref;
+typedef weak_ptr<P11Objects> P11Objects_WeakRef;
+
+class P11Objects {
+	NOCOPY(P11Objects);
+public:
+	P11Objects(int handle_base = 0);
+	P11Objects(bool read_only, ck_rv_t read_only_error, int handle_base = 0);
+
+	static P11Object_Ref addNew(P11Objects_Ref container, ck_object_class_t objectClass, const P11Attributes &attributes);
+
+	void search(const P11Attributes &search, P11ObjectHandleList &output);
+
+	P11Object_Ref getObject(ck_object_handle_t handle);
+	bool destroyObject(ck_object_handle_t handle);
+private:
+	int refresh();
+
+	typedef HandleManager<P11Object> ObjectManager;
+	ObjectManager objects;
+	bool read_only;
+	ck_rv_t read_only_error;
+
+	mutable auto_ptr<UserMutex> lock;
+protected:
+	/* Locked object support */
+	typedef P11Object_Ref ref_type;
+	typedef ck_object_handle_t handle_type;
+	
+	friend class LockedContainedObject<P11Objects>;
+	ref_type handleToValue(handle_type handle) const;
+public:	
+	UserMutex &getLock() const { return *lock; }
+};
+
+class LockedSession;
+
+/* Handles obtaining the necessary persistent lock for session handling */
+class LockedObject : public LockedContainedObject<P11Objects> {
+public:
+	LockedObject(const P11Objects &container, ck_object_handle_t handle, bool readWrite = false)
+	:LockedContainedObject<P11Objects>(container, handle, readWrite) {}
+	/* Since Objects can be in two places, a utility function to get ahold of a locked version exists.. */
+	static LockedObject *get_locked_object(const LockedSession &session, ck_object_handle_t handle, bool readWrite = false);
+};
+
+
+#endif

Added: trunk/TokendPKCS11/include/P11Session.h
===================================================================
--- trunk/TokendPKCS11/include/P11Session.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/P11Session.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,146 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef P11SESSION_H
+#define P11SESSION_H
+
+#include "P11Mutexes.h"
+#include "P11Object.h"
+#include "P11Attribute.h"
+#include "P11Slot.h"
+#include "P11CryptoState.h"
+
+#include "HandleManager.h"
+
+class P11Session;
+
+typedef shared_ptr<P11Session> P11Session_Ref;
+typedef weak_ptr<P11Session> P11Session_WeakRef;
+
+
+/* P11Session can only be pulled after a lock on the P11Sessions object
+ * No 'disabled' P11Session object will be accessible, so no extra checks needed
+ */
+class P11Session : public LockableHandledObject<P11Session> {
+	NOCOPY(P11Session);
+protected:
+	friend class P11SessionCreator;
+	P11Session(const LockedSlot &slot, ck_flags_t flags, ck_notify_t notify, void *app_data);
+
+public:
+	~P11Session();
+
+	void information(struct ck_session_info &info, const LockedSlot &lockedSlot);
+
+	/* CRYPTO APIs */
+	auto_ptr<P11CryptoState> decryptState;
+	auto_ptr<P11CryptoState> signState;
+
+	P11Objects &getObjects() { return *objects; }
+	ck_slot_id_t getSlotID() { return slotID; }
+
+	/* Object APIs */
+	void initializeSearch();
+	void lock_and_load_search(P11Objects &objects, const P11Attributes &attributes);
+	auto_ptr<P11ObjectHandleList> activeSearch;
+
+	/* Notify */
+	ck_rv_t notify(ck_notification_t event) {
+		return notifyCallback(getHandle(), event, applicationData);
+	}
+	ck_session_handle_t getHandle() const { return HandledObject<P11Session>::getHandle(); }
+
+protected:
+	ck_flags_t	mFlags;				/* see below */
+
+	ck_slot_id_t slotID;
+	/* Session-specific objects */
+	P11Objects_Ref objects;
+
+	/* NOTIFY CALLBACK DATA */
+	ck_notify_t notifyCallback;
+	void *applicationData;
+};
+
+class P11SessionCreator {
+public:
+	/** Allow P11Sessions to create/destory slots */
+	friend class P11Sessions;
+private:
+	static P11Session_Ref create(const LockedSlot &slot, ck_flags_t flags, ck_notify_t notify, void *app_data) {
+		return P11Session_Ref(new P11Session(slot, flags, notify, app_data));
+	}
+};
+
+
+class P11Sessions {
+	NOCOPY(P11Sessions);
+private:
+	/** Permit P11SessionsCreator to manage session manager creation */
+	friend class P11SessionsCreator;
+	P11Sessions();
+public:
+	~P11Sessions();
+
+	typedef map<ck_session_handle_t,P11Session_Ref> P11SessionMap;
+	typedef multimap<ck_slot_id_t,P11Session_WeakRef> P11SlotSessionMap;
+
+	void create(const LockedSlot &slot, ck_flags_t flags, ck_notify_t notify, void *app_data, ck_session_handle_t &session);
+
+	void close(ck_session_handle_t hSession);
+	void closeAll(ck_slot_id_t slotID);
+
+	UserMutex &getLock() const { return *lock; }
+protected:
+	typedef HandleManager<P11Session> SessionManager;
+	SessionManager sessions;
+	P11SlotSessionMap slotsToSessions;
+
+	mutable auto_ptr<UserMutex> lock;
+
+	void refresh();
+protected:
+	/* Locked object support */
+	typedef P11Session_Ref ref_type;
+	typedef ck_session_handle_t handle_type;
+	static const P11Sessions &getContainer();
+
+	friend class LockedSession;
+	friend class LockedContainedObject<P11Sessions>;
+	ref_type handleToValue(handle_type handle) const;
+};
+
+class P11SessionsCreator {
+private:
+	friend class P11State;
+	static P11Sessions *create() { return new P11Sessions; }
+};
+
+/* Handles obtaining the necessary persistent lock for session handling */
+class LockedSession : public LockedContainedObject<P11Sessions> {
+public:
+	LockedSession(ck_session_handle_t session, bool readWrite = false)
+	:LockedContainedObject<P11Sessions>(P11Sessions::getContainer(), session, readWrite) {}
+};
+
+#endif

Added: trunk/TokendPKCS11/include/P11Slot.h
===================================================================
--- trunk/TokendPKCS11/include/P11Slot.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/P11Slot.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,156 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef P11SLOT_H
+#define P11SLOT_H
+
+#include "pkcs11.h"
+
+#include "P11Object.h"
+#include "P11Mutexes.h"
+#include "HandleManager.h"
+#include "P11Identity.h"
+
+#include "CFUtilities.h"
+
+class P11Mechanism;
+typedef shared_ptr<P11Mechanism> P11Mechanism_Ref;
+
+/**
+ * Utility PKCS11 class to convey cryptographic mechanism information
+ */
+class P11Mechanism {
+	NOCOPY(P11Mechanism);
+public:
+	/** Construct the P11Mechanism object with given mechanism and info */
+	P11Mechanism(const struct ck_mechanism &mech, const struct ck_mechanism_info &info);
+
+	/** Return the mechanism's type */
+	ck_mechanism_type_t getType() const { return mechanismType; }
+	/** Accessor to the mechanism parameter */
+	const vector<byte> &getParameter() const { return parameter; }
+	/** Accessor to the mechanism information */
+	const struct ck_mechanism_info &getInfo() { return info; }
+
+protected:
+	ck_mechanism_type_t mechanismType;
+	vector<byte> parameter;
+	struct ck_mechanism_info info;
+};
+typedef map<ck_mechanism_type_t,P11Mechanism_Ref> P11MechanismMap;
+
+class P11Slot;
+typedef shared_ptr<P11Slot> P11Slot_Ref;
+typedef weak_ptr<P11Slot> P11Slot_WeakRef;
+
+/**
+ * P11 Slot interface
+ */
+class P11Slot : public LockableHandledObject<P11Slot> {
+	NOCOPY(P11Slot);
+private:
+	/** Permit P11SlotCreator to manage slot creation */
+	friend class P11SlotCreator;
+	/* Create a dummy empty slot */
+	P11Slot();
+	/* Create an active slot */
+	P11Slot(SecKeychainRef keychain);
+public:
+	/** Accessor to the slot's handle */
+	ck_slot_id_t getSlotID() const {
+		return getHandle();
+	}
+
+	/** Load slot information into ck_slot_info */
+	void getInformation(struct ck_slot_info &info);
+	/**
+	 * Load token information
+	 * @param info Structure to load data into
+	 * @param active_count Number of active slot uses to supply
+	 */
+	void getTokenInformation(struct ck_token_info &info, int active_count);
+
+	/** Obtain mechanism information of a given type */
+	P11Mechanism_Ref getMechanism(ck_mechanism_type_t type);
+
+	/** Log into the slot with the given pin
+	 * @param user_type User type to login as, ignored since only 'user-login' is permitted
+	 * @param pin PIN to use, if NULL, use 'Token Specific Login' aka Keychain login
+	 * @param pin_len Length of the PIN to use
+	 */
+	ck_rv_t login(ck_user_type_t userType, const byte *pin, ulong pin_len);
+	/** Log out of the slot */
+	ck_rv_t logout();
+
+	/** Check the login status of the user */
+	bool isLoggedIn() const;
+	/** Check if the token is present */
+	bool isPresent() const;
+
+	/** Get a reference to the contained slot objects */
+	P11Objects &getObjects() { return *objects; }
+
+	/** Check if the slot is still present, throw if not */
+	void assertPresent() const;
+protected:
+	/** Loads the included mechanisms as objects into the object container */
+	void loadMechanisms();
+	/** Loads the associated public/private keys and certificates into the object container */
+	void loadKeypairs();
+
+	/** Reference to the keychain used */
+	ScopedCF<SecKeychainRef> keychain;
+
+	/** Reference to the slot's object manager */
+	P11Objects_Ref objects;
+	/** Reference to the slot's identity manager */
+	P11Identities identityValues;
+	/** Map of available mechanisms
+	 * Note the mechanism availability management is partly spread out due to implementation
+	 * challenges.
+	 */
+	P11MechanismMap mechanisms;
+public:
+	/** Accessor to available mechanism map */
+	const P11MechanismMap &getMechanisms() const {
+		assertPresent();
+		return mechanisms;
+	}
+};
+
+
+class P11SlotCreator {
+public:
+	/** Allow ApplySlotChanges and P11Slots to create/destory slots */
+	friend class ApplySlotChanges;
+	friend class P11Slots;
+private:
+	static P11Slot_Ref DummySlot() {
+		return P11Slot_Ref(new P11Slot);
+	}
+	static P11Slot_Ref ActiveSlot(SecKeychainRef keychain) {
+		return P11Slot_Ref(new P11Slot(keychain));
+	}
+};
+
+#endif

Added: trunk/TokendPKCS11/include/P11Slots.h
===================================================================
--- trunk/TokendPKCS11/include/P11Slots.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/P11Slots.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,94 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef P11SLOTS_H
+#define P11SLOTS_H
+
+#include "pkcs11.h"
+
+#include "P11Object.h"
+#include "P11Mutexes.h"
+#include "P11Slot.h"
+#include "HandleManager.h"
+
+class EmptySlot;
+
+/* Class to manage what slots exist */
+class P11Slots {
+	NOCOPY(P11Slots);
+private:
+	/** Permit P11SlotsCreator to manage slot creation */
+	friend class P11SlotsCreator;
+	P11Slots();
+
+public:
+	/** Obtain a list of slots active/inactive, based on presentOnly flag */
+	ck_rv_t list(ck_slot_id_t *slotList, ulong &slotCount, bool presentOnly);
+
+	typedef map<SecKeychainRef,ck_slot_id_t> KeychainToSlotMap;
+	typedef vector<P11Slot_Ref> P11SlotList;
+
+	/** Accessor to the container lock */
+	UserMutex &getLock() const { return *lock; }
+protected:
+	/** Permit access to ApplySlotChanges (access to slots, keychainToSlot, and loadEmptySlot */
+	friend class ApplySlotChanges;
+	typedef HandleManager<P11Slot> SlotHandleManager;
+	SlotHandleManager slots;
+	/** Mapping of keychains to slots to know what to kill on token removal */
+	KeychainToSlotMap keychainToSlot;
+
+	/** Get a reference to an slot to use w/ 'keychain' */
+	P11Slot_Ref loadEmptySlot(SecKeychainRef keychain);
+private:
+	void refresh();
+	mutable auto_ptr<UserMutex> lock;
+protected:
+	/* Locked object support */
+	typedef P11Slot_Ref ref_type;
+	typedef ck_slot_id_t handle_type;
+	static const P11Slots &getContainer();
+
+	friend class LockedSlot;
+	friend class LockedContainedObject<P11Slots>;
+	ref_type handleToValue(handle_type handle) const;
+};
+
+
+class P11SlotsCreator {
+private:
+	/** Permit only the P11State to create a slot manager */
+	friend class P11State;
+	static P11Slots *create() {
+		return new P11Slots;
+	}
+};
+
+/* Handles obtaining the necessary persistent lock for session handling */
+class LockedSlot : public LockedContainedObject<P11Slots> {
+public:
+	LockedSlot(ck_slot_id_t handle, bool readWrite = false)
+	:LockedContainedObject<P11Slots>(P11Slots::getContainer(), handle, readWrite) {}
+};
+
+#endif

Added: trunk/TokendPKCS11/include/P11State.h
===================================================================
--- trunk/TokendPKCS11/include/P11State.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/P11State.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,104 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "Utilities.h"
+
+#include "P11Slot.h"
+#include "P11Slots.h"
+#include "P11Session.h"
+
+/**
+ * Class managing global state.
+ */
+class P11State {
+	NOCOPY(P11State);
+private:
+	friend class ModuleNexus<P11State>;
+	/**
+	 * Constructs the P11State, private to prevent construction
+	 * by anything other than ModuleNexus which manages the global state
+	 */
+	P11State();
+public:
+	/**
+	 * Performs the work of C_Initialize.
+	 * Sets up the mutex factory and global lock
+	 */
+	ck_rv_t initialize(const struct ck_c_initialize_args *args);
+
+	/** If the state is not initialized, throw a P11Exception */
+	void assertInitialized();
+
+	/** Make sure the state is initialized and lock it before killing everything */
+	ck_rv_t finalize();
+
+	/** Accessor to the slot manager */
+	P11Slots &getSlots() { return *slots; }
+
+	/** Accessor to the session manager */
+	P11Sessions& getSessions() { return *sessions; }
+
+	/** Obtain the global lock */
+	UserMutex &getLock() { return *mutex; }
+	/** Obtain a new mutex instance */
+	UserMutex *newMutex() { return mutexFactory->create(); }
+protected:
+	auto_ptr<P11Sessions> sessions;
+	auto_ptr<P11Slots> slots;
+private:
+	mutable auto_ptr<UserMutex> mutex;
+	auto_ptr<Factory<UserMutex> > mutexFactory;
+	bool isInitialized;
+
+	/** Saved arguments from initialization */
+	struct ck_c_initialize_args current_args;
+};
+
+/** Globally accessible state */
+extern ModuleNexus<P11State> globalState;
+
+/** Class to obtain a hold on the global state
+ * If the P11 client does not permit OS primitives,
+ * this will force all users of the P11 to be fully serialized.
+ * Potential fix would be to use some sort of semaphore-type emulation mechanism...
+ */
+class GlobalLockCheck {
+public:
+	GlobalLockCheck(bool readWrite = false);
+private:
+	friend class P11State;
+	auto_ptr<StLock<UserMutex> > lock;
+};
+
+/** Method to process errors for actual returns and session killing
+ * If the token was removed.
+ */
+ck_rv_t processSlotError(const P11Exception &e, ck_slot_id_t slot);
+
+/** Method to process errors for actual returns and session killing
+ * If the token was removed.
+ */
+ck_rv_t processSessionError(const P11Exception &e, ck_session_handle_t session);
+
+/** Method to process return values for actual returns and session killing */
+ck_rv_t processSessionReturn(ck_rv_t rv, ck_session_handle_t session);

Added: trunk/TokendPKCS11/include/TLV.h
===================================================================
--- trunk/TokendPKCS11/include/TLV.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/TLV.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,143 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef TLV_H
+#define TLV_H
+
+#include <tr1/memory>
+
+#include <stdexcept>
+
+#include <sstream>
+#include <vector>
+
+#ifndef NOCOPY
+#define NOCOPY(Type)    private: Type(const Type &); void operator = (const Type &);
+#endif
+
+#include "byte_string.h"
+
+class TLV;
+typedef std::tr1::shared_ptr<TLV> TLV_ref;
+typedef std::vector<TLV_ref> TLVList;
+
+/** Utility class to simplify TLV parsing and encoding
+ *  Condition of proper behavior (assume sizeof(size_t) => ptr size):
+ *  32-bit: Total data < 4GB
+ *  64-bit: Total data < 4GB * 4GB
+ */
+class TLV {
+	NOCOPY(TLV);
+public:
+	TLV() throw();
+	TLV(uint8_t tag) throw();
+	TLV(const byte_string &tag) throw();
+	TLV(uint8_t tag, const byte_string &value) throw();
+	TLV(const byte_string &tag, const byte_string &value) throw();
+	TLV(const byte_string &tag, const TLVList &tlv) throw();
+	TLV(uint8_t tag, const TLVList &tlv) throw();
+
+	/* Parses a byte_string as a TLV value - ignores trailing bytes
+	 * Throws an error if the encoding is invalid
+	 */
+	static TLV_ref parse(const byte_string &data) throw(std::runtime_error);
+
+	/* Parses an entire sequence of bytes as a TLV value
+	 * - ignores trailing bytes, iter points to byte after TLV
+	 * Can accept forward iterators to bytes or pointers to bytes for the range
+	 * Ex: byte_string::iterator, unsigned char *
+	 * Throws an error if the encoding is invalid
+	 */
+	template<typename ForwardIterator>
+	static TLV_ref parse(ForwardIterator &iter, const ForwardIterator &end) throw(std::runtime_error);
+
+	/* Obtains the tag of this TLV */
+	const byte_string &getTag() const throw() { return tag; }
+
+	/* Encodes this TLV into a new byte_string */
+	byte_string encode() const throw();
+	/* Encodes this TLV, appending the data to 'out' */
+	void encode(byte_string &out) const throw();
+	/* Decodes the value of this TLV as a sequence of TLVs */
+	const TLVList &getInnerValues() const throw(std::runtime_error);
+	/* Obtains the value of this TLV */
+	const byte_string &getValue() const throw();
+
+	/* Calculates the length of this TLV */
+	size_t length() const throw();
+
+private:
+	byte_string tag;
+	/* cached/assigned value as a string */
+	mutable std::auto_ptr<byte_string> value;
+	/* cached/assigned value as a TLV sequence */
+	mutable std::auto_ptr<TLVList> innerValues;
+
+	/* Parses an entire sequence of bytes as a sequence of TLV values, appending them to tlv
+	 * Can accept forward iterators to bytes or pointers to bytes for the range
+	 * Ex: byte_string::iterator, unsigned char *
+	 * Throws an error if the encoding is invalid
+	 */
+	template<typename ForwardIterator>
+	static void parseSequence(ForwardIterator &iter, const ForwardIterator &end, TLVList &tlv) throw(std::runtime_error);
+
+	/* Parses the ber-encoded length from a sequence of bytes
+	 * Can accept forward iterators to bytes or pointers to bytes for the range
+	 * Ex: byte_string::iterator, unsigned char *
+	 * Throws an error if the encoding is invalid
+	 */
+	template<typename ForwardIterator>
+	static size_t parseLength(ForwardIterator &iter, const ForwardIterator &end) throw(std::runtime_error);
+
+	/* ber-encodes an integer and writes it's output to 'out' */
+	static void encodeLength(size_t value, byte_string &out) throw();
+public:
+	/* Obtains the length of a ber-encoded integer that would contain the value */
+	static size_t encodedLength(size_t value) throw();
+private:
+	/* Encodes a sequence of TLVs, writing the to 'out' */
+	static void encodeSequence(const TLVList &tlv, byte_string &out) throw();
+
+	/* Calculates the total length of the value */
+	size_t valueLength() const throw();
+};
+
+class TagPredicate {
+public:
+	TagPredicate(uint8_t tag) throw()
+	:tag(1, tag) {
+	}
+	TagPredicate(const byte_string &tag) throw()
+	:tag(tag) {
+	}
+	bool operator() (const TLV_ref &tlv) throw() {
+		return this->tag == tlv->getTag();
+	}
+private:
+	byte_string tag;
+};
+
+/* TEMPLATE DEFINITIONS */
+#include "TLV.inc"
+
+#endif

Added: trunk/TokendPKCS11/include/Utilities.h
===================================================================
--- trunk/TokendPKCS11/include/Utilities.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/Utilities.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef UTILITIES_H
+#define UTILITIES_H
+
+/* Mark a class as non-copyable, compile-error will occur on copy-attept */
+#ifndef NOCOPY
+#define NOCOPY(Type)    private: Type(const Type &); void operator = (const Type &);
+#endif
+
+/**
+ * PKCS#11 Exception class which propogates a PKCS#11 ck_rv_t to the
+ * calling application on loop-exit
+ */
+class P11Exception {
+public:
+	P11Exception(ck_rv_t ret) : ret(ret) {}
+
+	const ck_rv_t ret;
+};
+
+/**
+ * Wrapper class around a lockable object
+ * - by default, this is a read lock
+ * - a write-lock is accessible
+ * NOTE: Some implementations may use a basic mutex
+ * in which case read-lock == write-lock
+ */
+class UserMutex {
+	NOCOPY(UserMutex);
+public:
+	UserMutex() {}
+	virtual ~UserMutex() {}
+	virtual void lock() = 0;
+	virtual void unlock() = 0;
+	virtual UserMutex &writeMutex() = 0;
+};
+
+/* Handles obtaining the necessary persistent lock for object handling */
+template<typename ContainerType>
+class LockedContainedObject {
+	NOCOPY(LockedContainedObject);
+private:
+	typedef typename ContainerType::handle_type handle_type;
+	typedef typename ContainerType::ref_type ref_type;
+	typedef ContainerType container_type;
+public:
+	/**
+	 * Obtains a LockedContainedObject from a container
+	 * Obtains a reader lock on the container, then the given lock on the object itself
+	 *
+	 * @param container Container to pull the object from
+	 * @param handle Handle identifier of the object to retreive
+	 * @param readWrite Whether to obtain a read/write lock on the object itself
+ 	 * @throw P11Exception if the object doesn't exist at retreival-time
+	 */
+	LockedContainedObject(const container_type &container, handle_type handle, bool readWrite = false)
+	:containerLock(container.getLock()),refLock(NULL),ref() {
+		ref = container.handleToValue(handle);
+		refLock.reset(new StLock<UserMutex>(readWrite ? ref->getLock().writeMutex() : ref->getLock())); /* VALIDATED */
+	}
+	virtual ~LockedContainedObject() {}
+	/** Returns the contained reference to the locked object */
+	const ref_type &get() const {
+		return ref;
+	}
+private:
+	StLock<UserMutex> containerLock; /* VALIDATED */
+	/* Since the session mutex will only be revealed after construction */
+	auto_ptr<StLock<UserMutex> > refLock;
+	ref_type ref;
+};
+
+/** Template class for a generic create-only factory (object should be 'deleted') */
+template<typename T>
+class Factory {
+public:
+	virtual ~Factory() {}
+	virtual T *create() = 0;
+};
+
+/** Writes out a space-padded string to the destination
+ * Up to `size` bytes from `from` are copied to `to` and then padded with spaces up to `size`
+ *
+ * @param to Output byte buffer of 'size' bytes
+ * @param from Null-terminated string that 'should' be less than 'size' bytes
+ * @param size Size of the output buffer
+ */
+void pad_string_set(byte *to, const char *from, size_t size);
+
+#endif

Added: trunk/TokendPKCS11/include/byte_string.h
===================================================================
--- trunk/TokendPKCS11/include/byte_string.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/byte_string.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef BYTE_STRING
+#define BYTE_STRING
+#include <vector>
+
+/** Utility definition and additional operators to make working with
+ * sequences of bytes more easy and less error/leak-prone
+ */
+typedef std::vector<uint8_t> byte_string;
+
+inline bool operator==(const byte_string &l, const byte_string::value_type &value) {
+	return l.size() == 1 && l.at(0) == value;
+}
+
+inline byte_string &operator+=(byte_string &l, const byte_string::value_type &value) {
+	l.push_back(value);
+	return l;
+}
+inline byte_string &operator+=(byte_string &l, const char &value) {
+	l.push_back(value);
+	return l;
+}
+
+inline byte_string &operator+=(byte_string &l, const byte_string::value_type *value) {
+	l.insert(l.end(), value, value + strlen((char*)value));
+	return l;
+}
+
+inline byte_string &operator+=(byte_string &l, const byte_string &r) {
+	l.insert(l.end(), r.begin(), r.end());
+	return l;
+}
+
+/* RHS must be null-terminated */
+inline bool operator==(const byte_string& l, const byte_string::value_type* r) {
+	byte_string::size_type lSize = l.size();
+	byte_string::size_type rSize = strlen((const char*)r);
+	if(lSize != rSize)
+		return false;
+	return equal(l.begin(), l.end(), r);
+}
+
+inline bool operator!=(const byte_string& l, const byte_string::value_type* r) {
+	return !(l == r);
+}
+
+inline unsigned char *malloc_copy(const byte_string &l) {
+	unsigned char *output = (unsigned char*)malloc(l.size());
+	if(!output)
+		return NULL;
+	memcpy(output, &l[0], l.size());
+	return output;
+}
+#endif

Added: trunk/TokendPKCS11/include/config-objects.h
===================================================================
--- trunk/TokendPKCS11/include/config-objects.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/config-objects.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef CONFIG_OBJECTS_H
+#define CONFIG_OBJECTS_H
+
+//#define MAX_IDLE_OBJECTS 8
+//#define MIN_OBJECTS 0
+// Currently setup to have no objects by default and never totally erase all objects
+
+/* If ID contains an element of this null terminated list, don't include it
+ * Digital Signature not included due to PIN authentication issues
+ */
+static const char *SKIP_OBJECT_MATCH[] = { "Digital Signature", 0 };
+
+#endif

Added: trunk/TokendPKCS11/include/config.h
===================================================================
--- trunk/TokendPKCS11/include/config.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/config.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#define PKCS11_MANUFACTURER "Apple"
+#define PKCS11_DESCRIPTION "Apple PKCS #11 module"
+#define PKCS11_SLOT_DESCRIPTION "Apple Tokend"
+#define PKCS11_LIBRARY_MAJOR 0
+#define PKCS11_LIBRARY_MINOR 1
+
+/* #define USE_PROTECTED_PATH */
+/* #define USE_PIN_AUTH */
+#define USE_ALWAYS_AUTH_SESSION
+
+#define MAX_IDLE_SLOTS 8
+#define MIN_SLOTS 4
+
+#endif

Added: trunk/TokendPKCS11/include/pkcs11.h
===================================================================
--- trunk/TokendPKCS11/include/pkcs11.h	                        (rev 0)
+++ trunk/TokendPKCS11/include/pkcs11.h	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,1358 @@
+/* pkcs11.h
+   Copyright 2006, 2007 g10 Code GmbH
+   Copyright 2006 Andreas Jellinghaus
+
+   This file is free software; as a special exception the author gives
+   unlimited permission to copy and/or distribute it, with or without
+   modifications, as long as this notice is preserved.
+
+   This file is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY, to the extent permitted by law; without even
+   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+   PURPOSE.  */
+
+/* Please submit changes back to the Scute project at
+   http://www.scute.org/ (or send them to marcus at g10code.com), so that
+   they can be picked up by other projects from there as well.  */
+
+/* This file is a modified implementation of the PKCS #11 standard by
+   RSA Security Inc.  It is mostly a drop-in replacement, with the
+   following change:
+
+   This header file does not require any macro definitions by the user
+   (like CK_DEFINE_FUNCTION etc).  In fact, it defines those macros
+   for you (if useful, some are missing, let me know if you need
+   more).
+
+   There is an additional API available that does comply better to the
+   GNU coding standard.  It can be switched on by defining
+   CRYPTOKI_GNU before including this header file.  For this, the
+   following changes are made to the specification:
+
+   All structure types are changed to a "struct ck_foo" where CK_FOO
+   is the type name in PKCS #11.
+
+   All non-structure types are changed to ck_foo_t where CK_FOO is the
+   lowercase version of the type name in PKCS #11.  The basic types
+   (CK_ULONG et al.) are removed without substitute.
+
+   All members of structures are modified in the following way: Type
+   indication prefixes are removed, and underscore characters are
+   inserted before words.  Then the result is lowercased.
+
+   Note that function names are still in the original case, as they
+   need for ABI compatibility.
+
+   CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute.  Use
+   <stdbool.h>.
+
+   If CRYPTOKI_COMPAT is defined before including this header file,
+   then none of the API changes above take place, and the API is the
+   one defined by the PKCS #11 standard.  */
+
+#ifndef PKCS11_H
+#define PKCS11_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* The version of cryptoki we implement.  The revision is changed with
+   each modification of this file.  If you do not use the "official"
+   version of this file, please consider deleting the revision macro
+   (you may use a macro with a different name to keep track of your
+   versions).  */
+#define CRYPTOKI_VERSION_MAJOR		2
+#define CRYPTOKI_VERSION_MINOR		20
+#define CRYPTOKI_VERSION_REVISION	6
+
+
+/* Compatibility interface is default, unless CRYPTOKI_GNU is
+   given.  */
+#ifndef CRYPTOKI_GNU
+#ifndef CRYPTOKI_COMPAT
+#define CRYPTOKI_COMPAT 1
+#endif
+#endif
+
+/* System dependencies.  */
+
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+
+/* There is a matching pop below.  */
+#pragma pack(push, cryptoki, 1)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_SPEC __declspec(dllexport)
+#else
+#define CK_SPEC __declspec(dllimport)
+#endif
+
+#else
+
+/* Make all CK functions visible */
+#define CK_SPEC __attribute__ ((visibility("default")))
+
+#endif
+
+
+#ifdef CRYPTOKI_COMPAT
+  /* If we are in compatibility mode, switch all exposed names to the
+     PKCS #11 variant.  There are corresponding #undefs below.  */
+
+#define ck_flags_t CK_FLAGS
+#define ck_version _CK_VERSION
+
+#define ck_info _CK_INFO
+#define cryptoki_version cryptokiVersion
+#define manufacturer_id manufacturerID
+#define library_description libraryDescription
+#define library_version libraryVersion
+
+#define ck_notification_t CK_NOTIFICATION
+#define ck_slot_id_t CK_SLOT_ID
+
+#define ck_slot_info _CK_SLOT_INFO
+#define slot_description slotDescription
+#define hardware_version hardwareVersion
+#define firmware_version firmwareVersion
+
+#define ck_token_info _CK_TOKEN_INFO
+#define serial_number serialNumber
+#define max_session_count ulMaxSessionCount
+#define session_count ulSessionCount
+#define max_rw_session_count ulMaxRwSessionCount
+#define rw_session_count ulRwSessionCount
+#define max_pin_len ulMaxPinLen
+#define min_pin_len ulMinPinLen
+#define total_public_memory ulTotalPublicMemory
+#define free_public_memory ulFreePublicMemory
+#define total_private_memory ulTotalPrivateMemory
+#define free_private_memory ulFreePrivateMemory
+#define utc_time utcTime
+
+#define ck_session_handle_t CK_SESSION_HANDLE
+#define ck_user_type_t CK_USER_TYPE
+#define ck_state_t CK_STATE
+
+#define ck_session_info _CK_SESSION_INFO
+#define slot_id slotID
+#define device_error ulDeviceError
+
+#define ck_object_handle_t CK_OBJECT_HANDLE
+#define ck_object_class_t CK_OBJECT_CLASS
+#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE
+#define ck_key_type_t CK_KEY_TYPE
+#define ck_certificate_type_t CK_CERTIFICATE_TYPE
+#define ck_attribute_type_t CK_ATTRIBUTE_TYPE
+
+#define ck_attribute _CK_ATTRIBUTE
+#define value pValue
+#define value_len ulValueLen
+
+#define ck_date _CK_DATE
+
+#define ck_mechanism_type_t CK_MECHANISM_TYPE
+
+#define ck_mechanism _CK_MECHANISM
+#define parameter pParameter
+#define parameter_len ulParameterLen
+
+#define ck_mechanism_info _CK_MECHANISM_INFO
+#define min_key_size ulMinKeySize
+#define max_key_size ulMaxKeySize
+
+#define ck_rv_t CK_RV
+#define ck_notify_t CK_NOTIFY
+
+#define ck_function_list _CK_FUNCTION_LIST
+
+#define ck_createmutex_t CK_CREATEMUTEX
+#define ck_destroymutex_t CK_DESTROYMUTEX
+#define ck_lockmutex_t CK_LOCKMUTEX
+#define ck_unlockmutex_t CK_UNLOCKMUTEX
+
+#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS
+#define create_mutex CreateMutex
+#define destroy_mutex DestroyMutex
+#define lock_mutex LockMutex
+#define unlock_mutex UnlockMutex
+#define reserved pReserved
+
+#endif	/* CRYPTOKI_COMPAT */
+
+
+
+typedef unsigned long ck_flags_t;
+
+struct ck_version
+{
+  unsigned char major;
+  unsigned char minor;
+};
+
+
+struct ck_info
+{
+  struct ck_version cryptoki_version;
+  unsigned char manufacturer_id[32];
+  ck_flags_t flags;
+  unsigned char library_description[32];
+  struct ck_version library_version;
+};
+
+
+typedef unsigned long ck_notification_t;
+
+#define CKN_SURRENDER	(0)
+
+
+typedef unsigned long ck_slot_id_t;
+
+
+struct ck_slot_info
+{
+  unsigned char slot_description[64];
+  unsigned char manufacturer_id[32];
+  ck_flags_t flags;
+  struct ck_version hardware_version;
+  struct ck_version firmware_version;
+};
+
+
+#define CKF_TOKEN_PRESENT	(1 << 0)
+#define CKF_REMOVABLE_DEVICE	(1 << 1)
+#define CKF_HW_SLOT		(1 << 2)
+#define CKF_ARRAY_ATTRIBUTE	(1 << 30)
+
+
+struct ck_token_info
+{
+  unsigned char label[32];
+  unsigned char manufacturer_id[32];
+  unsigned char model[16];
+  unsigned char serial_number[16];
+  ck_flags_t flags;
+  unsigned long max_session_count;
+  unsigned long session_count;
+  unsigned long max_rw_session_count;
+  unsigned long rw_session_count;
+  unsigned long max_pin_len;
+  unsigned long min_pin_len;
+  unsigned long total_public_memory;
+  unsigned long free_public_memory;
+  unsigned long total_private_memory;
+  unsigned long free_private_memory;
+  struct ck_version hardware_version;
+  struct ck_version firmware_version;
+  unsigned char utc_time[16];
+};
+
+
+#define CKF_RNG					(1 << 0)
+#define CKF_WRITE_PROTECTED			(1 << 1)
+#define CKF_LOGIN_REQUIRED			(1 << 2)
+#define CKF_USER_PIN_INITIALIZED		(1 << 3)
+#define CKF_RESTORE_KEY_NOT_NEEDED		(1 << 5)
+#define CKF_CLOCK_ON_TOKEN			(1 << 6)
+#define CKF_PROTECTED_AUTHENTICATION_PATH	(1 << 8)
+#define CKF_DUAL_CRYPTO_OPERATIONS		(1 << 9)
+#define CKF_TOKEN_INITIALIZED			(1 << 10)
+#define CKF_SECONDARY_AUTHENTICATION		(1 << 11)
+#define CKF_USER_PIN_COUNT_LOW			(1 << 16)
+#define CKF_USER_PIN_FINAL_TRY			(1 << 17)
+#define CKF_USER_PIN_LOCKED			(1 << 18)
+#define CKF_USER_PIN_TO_BE_CHANGED		(1 << 19)
+#define CKF_SO_PIN_COUNT_LOW			(1 << 20)
+#define CKF_SO_PIN_FINAL_TRY			(1 << 21)
+#define CKF_SO_PIN_LOCKED			(1 << 22)
+#define CKF_SO_PIN_TO_BE_CHANGED		(1 << 23)
+
+#define CK_UNAVAILABLE_INFORMATION	((unsigned long) -1)
+#define CK_EFFECTIVELY_INFINITE		(0)
+
+
+typedef unsigned long ck_session_handle_t;
+
+#define CK_INVALID_HANDLE	(0)
+
+
+typedef unsigned long ck_user_type_t;
+
+#define CKU_SO			(0)
+#define CKU_USER		(1)
+#define CKU_CONTEXT_SPECIFIC	(2)
+
+
+typedef unsigned long ck_state_t;
+
+#define CKS_RO_PUBLIC_SESSION	(0)
+#define CKS_RO_USER_FUNCTIONS	(1)
+#define CKS_RW_PUBLIC_SESSION	(2)
+#define CKS_RW_USER_FUNCTIONS	(3)
+#define CKS_RW_SO_FUNCTIONS	(4)
+
+
+struct ck_session_info
+{
+  ck_slot_id_t slot_id;
+  ck_state_t state;
+  ck_flags_t flags;
+  unsigned long device_error;
+};
+
+#define CKF_RW_SESSION		(1 << 1)
+#define CKF_SERIAL_SESSION	(1 << 2)
+
+
+typedef unsigned long ck_object_handle_t;
+
+
+typedef unsigned long ck_object_class_t;
+
+#define CKO_DATA		(0)
+#define CKO_CERTIFICATE		(1)
+#define CKO_PUBLIC_KEY		(2)
+#define CKO_PRIVATE_KEY		(3)
+#define CKO_SECRET_KEY		(4)
+#define CKO_HW_FEATURE		(5)
+#define CKO_DOMAIN_PARAMETERS	(6)
+#define CKO_MECHANISM		(7)
+#define CKO_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_hw_feature_type_t;
+
+#define CKH_MONOTONIC_COUNTER	(1)
+#define CKH_CLOCK		(2)
+#define CKH_USER_INTERFACE	(3)
+#define CKH_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_key_type_t;
+
+#define CKK_RSA			(0)
+#define CKK_DSA			(1)
+#define CKK_DH			(2)
+#define CKK_ECDSA		(3)
+#define CKK_EC			(3)
+#define CKK_X9_42_DH		(4)
+#define CKK_KEA			(5)
+#define CKK_GENERIC_SECRET	(0x10)
+#define CKK_RC2			(0x11)
+#define CKK_RC4			(0x12)
+#define CKK_DES			(0x13)
+#define CKK_DES2		(0x14)
+#define CKK_DES3		(0x15)
+#define CKK_CAST		(0x16)
+#define CKK_CAST3		(0x17)
+#define CKK_CAST128		(0x18)
+#define CKK_RC5			(0x19)
+#define CKK_IDEA		(0x1a)
+#define CKK_SKIPJACK		(0x1b)
+#define CKK_BATON		(0x1c)
+#define CKK_JUNIPER		(0x1d)
+#define CKK_CDMF		(0x1e)
+#define CKK_AES			(0x1f)
+#define CKK_BLOWFISH		(0x20)
+#define CKK_TWOFISH		(0x21)
+#define CKK_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_certificate_type_t;
+
+#define CKC_X_509		(0)
+#define CKC_X_509_ATTR_CERT	(1)
+#define CKC_WTLS		(2)
+#define CKC_VENDOR_DEFINED	((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_attribute_type_t;
+
+#define CKA_CLASS			(0)
+#define CKA_TOKEN			(1)
+#define CKA_PRIVATE			(2)
+#define CKA_LABEL			(3)
+#define CKA_APPLICATION			(0x10)
+#define CKA_VALUE			(0x11)
+#define CKA_OBJECT_ID			(0x12)
+#define CKA_CERTIFICATE_TYPE		(0x80)
+#define CKA_ISSUER			(0x81)
+#define CKA_SERIAL_NUMBER		(0x82)
+#define CKA_AC_ISSUER			(0x83)
+#define CKA_OWNER			(0x84)
+#define CKA_ATTR_TYPES			(0x85)
+#define CKA_TRUSTED			(0x86)
+#define CKA_CERTIFICATE_CATEGORY	(0x87)
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN	(0x88)
+#define CKA_URL				(0x89)
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY	(0x8a)
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY	(0x8b)
+#define CKA_CHECK_VALUE			(0x90)
+#define CKA_KEY_TYPE			(0x100)
+#define CKA_SUBJECT			(0x101)
+#define CKA_ID				(0x102)
+#define CKA_SENSITIVE			(0x103)
+#define CKA_ENCRYPT			(0x104)
+#define CKA_DECRYPT			(0x105)
+#define CKA_WRAP			(0x106)
+#define CKA_UNWRAP			(0x107)
+#define CKA_SIGN			(0x108)
+#define CKA_SIGN_RECOVER		(0x109)
+#define CKA_VERIFY			(0x10a)
+#define CKA_VERIFY_RECOVER		(0x10b)
+#define CKA_DERIVE			(0x10c)
+#define CKA_START_DATE			(0x110)
+#define CKA_END_DATE			(0x111)
+#define CKA_MODULUS			(0x120)
+#define CKA_MODULUS_BITS		(0x121)
+#define CKA_PUBLIC_EXPONENT		(0x122)
+#define CKA_PRIVATE_EXPONENT		(0x123)
+#define CKA_PRIME_1			(0x124)
+#define CKA_PRIME_2			(0x125)
+#define CKA_EXPONENT_1			(0x126)
+#define CKA_EXPONENT_2			(0x127)
+#define CKA_COEFFICIENT			(0x128)
+#define CKA_PRIME			(0x130)
+#define CKA_SUBPRIME			(0x131)
+#define CKA_BASE			(0x132)
+#define CKA_PRIME_BITS			(0x133)
+#define CKA_SUB_PRIME_BITS		(0x134)
+#define CKA_VALUE_BITS			(0x160)
+#define CKA_VALUE_LEN			(0x161)
+#define CKA_EXTRACTABLE			(0x162)
+#define CKA_LOCAL			(0x163)
+#define CKA_NEVER_EXTRACTABLE		(0x164)
+#define CKA_ALWAYS_SENSITIVE		(0x165)
+#define CKA_KEY_GEN_MECHANISM		(0x166)
+#define CKA_MODIFIABLE			(0x170)
+#define CKA_ECDSA_PARAMS		(0x180)
+#define CKA_EC_PARAMS			(0x180)
+#define CKA_EC_POINT			(0x181)
+#define CKA_SECONDARY_AUTH		(0x200)
+#define CKA_AUTH_PIN_FLAGS		(0x201)
+#define CKA_ALWAYS_AUTHENTICATE		(0x202)
+#define CKA_WRAP_WITH_TRUSTED		(0x210)
+#define CKA_HW_FEATURE_TYPE		(0x300)
+#define CKA_RESET_ON_INIT		(0x301)
+#define CKA_HAS_RESET			(0x302)
+#define CKA_PIXEL_X			(0x400)
+#define CKA_PIXEL_Y			(0x401)
+#define CKA_RESOLUTION			(0x402)
+#define CKA_CHAR_ROWS			(0x403)
+#define CKA_CHAR_COLUMNS		(0x404)
+#define CKA_COLOR			(0x405)
+#define CKA_BITS_PER_PIXEL		(0x406)
+#define CKA_CHAR_SETS			(0x480)
+#define CKA_ENCODING_METHODS		(0x481)
+#define CKA_MIME_TYPES			(0x482)
+#define CKA_MECHANISM_TYPE		(0x500)
+#define CKA_REQUIRED_CMS_ATTRIBUTES	(0x501)
+#define CKA_DEFAULT_CMS_ATTRIBUTES	(0x502)
+#define CKA_SUPPORTED_CMS_ATTRIBUTES	(0x503)
+#define CKA_WRAP_TEMPLATE		(CKF_ARRAY_ATTRIBUTE | 0x211)
+#define CKA_UNWRAP_TEMPLATE		(CKF_ARRAY_ATTRIBUTE | 0x212)
+#define CKA_ALLOWED_MECHANISMS		(CKF_ARRAY_ATTRIBUTE | 0x600)
+#define CKA_VENDOR_DEFINED		((unsigned long) (1 << 31))
+
+
+struct ck_attribute
+{
+  ck_attribute_type_t type;
+  void *value;
+  unsigned long value_len;
+};
+
+
+struct ck_date
+{
+  unsigned char year[4];
+  unsigned char month[2];
+  unsigned char day[2];
+};
+
+
+typedef unsigned long ck_mechanism_type_t;
+
+#define CKM_RSA_PKCS_KEY_PAIR_GEN	(0)
+#define CKM_RSA_PKCS			(1)
+#define CKM_RSA_9796			(2)
+#define CKM_RSA_X_509			(3)
+#define CKM_MD2_RSA_PKCS		(4)
+#define CKM_MD5_RSA_PKCS		(5)
+#define CKM_SHA1_RSA_PKCS		(6)
+#define CKM_RIPEMD128_RSA_PKCS		(7)
+#define CKM_RIPEMD160_RSA_PKCS		(8)
+#define CKM_RSA_PKCS_OAEP		(9)
+#define CKM_RSA_X9_31_KEY_PAIR_GEN	(0xa)
+#define CKM_RSA_X9_31			(0xb)
+#define CKM_SHA1_RSA_X9_31		(0xc)
+#define CKM_RSA_PKCS_PSS		(0xd)
+#define CKM_SHA1_RSA_PKCS_PSS		(0xe)
+#define CKM_DSA_KEY_PAIR_GEN		(0x10)
+#define	CKM_DSA				(0x11)
+#define CKM_DSA_SHA1			(0x12)
+#define CKM_DH_PKCS_KEY_PAIR_GEN	(0x20)
+#define CKM_DH_PKCS_DERIVE		(0x21)
+#define	CKM_X9_42_DH_KEY_PAIR_GEN	(0x30)
+#define CKM_X9_42_DH_DERIVE		(0x31)
+#define CKM_X9_42_DH_HYBRID_DERIVE	(0x32)
+#define CKM_X9_42_MQV_DERIVE		(0x33)
+#define CKM_SHA256_RSA_PKCS		(0x40)
+#define CKM_SHA384_RSA_PKCS		(0x41)
+#define CKM_SHA512_RSA_PKCS		(0x42)
+#define CKM_SHA256_RSA_PKCS_PSS		(0x43)
+#define CKM_SHA384_RSA_PKCS_PSS		(0x44)
+#define CKM_SHA512_RSA_PKCS_PSS		(0x45)
+#define CKM_RC2_KEY_GEN			(0x100)
+#define CKM_RC2_ECB			(0x101)
+#define	CKM_RC2_CBC			(0x102)
+#define	CKM_RC2_MAC			(0x103)
+#define CKM_RC2_MAC_GENERAL		(0x104)
+#define CKM_RC2_CBC_PAD			(0x105)
+#define CKM_RC4_KEY_GEN			(0x110)
+#define CKM_RC4				(0x111)
+#define CKM_DES_KEY_GEN			(0x120)
+#define CKM_DES_ECB			(0x121)
+#define CKM_DES_CBC			(0x122)
+#define CKM_DES_MAC			(0x123)
+#define CKM_DES_MAC_GENERAL		(0x124)
+#define CKM_DES_CBC_PAD			(0x125)
+#define CKM_DES2_KEY_GEN		(0x130)
+#define CKM_DES3_KEY_GEN		(0x131)
+#define CKM_DES3_ECB			(0x132)
+#define CKM_DES3_CBC			(0x133)
+#define CKM_DES3_MAC			(0x134)
+#define CKM_DES3_MAC_GENERAL		(0x135)
+#define CKM_DES3_CBC_PAD		(0x136)
+#define CKM_CDMF_KEY_GEN		(0x140)
+#define CKM_CDMF_ECB			(0x141)
+#define CKM_CDMF_CBC			(0x142)
+#define CKM_CDMF_MAC			(0x143)
+#define CKM_CDMF_MAC_GENERAL		(0x144)
+#define CKM_CDMF_CBC_PAD		(0x145)
+#define CKM_MD2				(0x200)
+#define CKM_MD2_HMAC			(0x201)
+#define CKM_MD2_HMAC_GENERAL		(0x202)
+#define CKM_MD5				(0x210)
+#define CKM_MD5_HMAC			(0x211)
+#define CKM_MD5_HMAC_GENERAL		(0x212)
+#define CKM_SHA_1			(0x220)
+#define CKM_SHA_1_HMAC			(0x221)
+#define CKM_SHA_1_HMAC_GENERAL		(0x222)
+#define CKM_RIPEMD128			(0x230)
+#define CKM_RIPEMD128_HMAC		(0x231)
+#define CKM_RIPEMD128_HMAC_GENERAL	(0x232)
+#define CKM_RIPEMD160			(0x240)
+#define CKM_RIPEMD160_HMAC		(0x241)
+#define CKM_RIPEMD160_HMAC_GENERAL	(0x242)
+#define CKM_SHA256			(0x250)
+#define CKM_SHA256_HMAC			(0x251)
+#define CKM_SHA256_HMAC_GENERAL		(0x252)
+#define CKM_SHA384			(0x260)
+#define CKM_SHA384_HMAC			(0x261)
+#define CKM_SHA384_HMAC_GENERAL		(0x262)
+#define CKM_SHA512			(0x270)
+#define CKM_SHA512_HMAC			(0x271)
+#define CKM_SHA512_HMAC_GENERAL		(0x272)
+#define CKM_CAST_KEY_GEN		(0x300)
+#define CKM_CAST_ECB			(0x301)
+#define CKM_CAST_CBC			(0x302)
+#define CKM_CAST_MAC			(0x303)
+#define CKM_CAST_MAC_GENERAL		(0x304)
+#define CKM_CAST_CBC_PAD		(0x305)
+#define CKM_CAST3_KEY_GEN		(0x310)
+#define CKM_CAST3_ECB			(0x311)
+#define CKM_CAST3_CBC			(0x312)
+#define CKM_CAST3_MAC			(0x313)
+#define CKM_CAST3_MAC_GENERAL		(0x314)
+#define CKM_CAST3_CBC_PAD		(0x315)
+#define CKM_CAST5_KEY_GEN		(0x320)
+#define CKM_CAST128_KEY_GEN		(0x320)
+#define CKM_CAST5_ECB			(0x321)
+#define CKM_CAST128_ECB			(0x321)
+#define CKM_CAST5_CBC			(0x322)
+#define CKM_CAST128_CBC			(0x322)
+#define CKM_CAST5_MAC			(0x323)
+#define	CKM_CAST128_MAC			(0x323)
+#define CKM_CAST5_MAC_GENERAL		(0x324)
+#define CKM_CAST128_MAC_GENERAL		(0x324)
+#define CKM_CAST5_CBC_PAD		(0x325)
+#define CKM_CAST128_CBC_PAD		(0x325)
+#define CKM_RC5_KEY_GEN			(0x330)
+#define CKM_RC5_ECB			(0x331)
+#define CKM_RC5_CBC			(0x332)
+#define CKM_RC5_MAC			(0x333)
+#define CKM_RC5_MAC_GENERAL		(0x334)
+#define CKM_RC5_CBC_PAD			(0x335)
+#define CKM_IDEA_KEY_GEN		(0x340)
+#define CKM_IDEA_ECB			(0x341)
+#define	CKM_IDEA_CBC			(0x342)
+#define CKM_IDEA_MAC			(0x343)
+#define CKM_IDEA_MAC_GENERAL		(0x344)
+#define CKM_IDEA_CBC_PAD		(0x345)
+#define CKM_GENERIC_SECRET_KEY_GEN	(0x350)
+#define CKM_CONCATENATE_BASE_AND_KEY	(0x360)
+#define CKM_CONCATENATE_BASE_AND_DATA	(0x362)
+#define CKM_CONCATENATE_DATA_AND_BASE	(0x363)
+#define CKM_XOR_BASE_AND_DATA		(0x364)
+#define CKM_EXTRACT_KEY_FROM_KEY	(0x365)
+#define CKM_SSL3_PRE_MASTER_KEY_GEN	(0x370)
+#define CKM_SSL3_MASTER_KEY_DERIVE	(0x371)
+#define CKM_SSL3_KEY_AND_MAC_DERIVE	(0x372)
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH	(0x373)
+#define CKM_TLS_PRE_MASTER_KEY_GEN	(0x374)
+#define CKM_TLS_MASTER_KEY_DERIVE	(0x375)
+#define CKM_TLS_KEY_AND_MAC_DERIVE	(0x376)
+#define CKM_TLS_MASTER_KEY_DERIVE_DH	(0x377)
+#define CKM_SSL3_MD5_MAC		(0x380)
+#define CKM_SSL3_SHA1_MAC		(0x381)
+#define CKM_MD5_KEY_DERIVATION		(0x390)
+#define CKM_MD2_KEY_DERIVATION		(0x391)
+#define CKM_SHA1_KEY_DERIVATION		(0x392)
+#define CKM_PBE_MD2_DES_CBC		(0x3a0)
+#define CKM_PBE_MD5_DES_CBC		(0x3a1)
+#define CKM_PBE_MD5_CAST_CBC		(0x3a2)
+#define CKM_PBE_MD5_CAST3_CBC		(0x3a3)
+#define CKM_PBE_MD5_CAST5_CBC		(0x3a4)
+#define CKM_PBE_MD5_CAST128_CBC		(0x3a4)
+#define CKM_PBE_SHA1_CAST5_CBC		(0x3a5)
+#define CKM_PBE_SHA1_CAST128_CBC	(0x3a5)
+#define CKM_PBE_SHA1_RC4_128		(0x3a6)
+#define CKM_PBE_SHA1_RC4_40		(0x3a7)
+#define CKM_PBE_SHA1_DES3_EDE_CBC	(0x3a8)
+#define CKM_PBE_SHA1_DES2_EDE_CBC	(0x3a9)
+#define CKM_PBE_SHA1_RC2_128_CBC	(0x3aa)
+#define CKM_PBE_SHA1_RC2_40_CBC		(0x3ab)
+#define CKM_PKCS5_PBKD2			(0x3b0)
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC	(0x3c0)
+#define CKM_KEY_WRAP_LYNKS		(0x400)
+#define CKM_KEY_WRAP_SET_OAEP		(0x401)
+#define CKM_SKIPJACK_KEY_GEN		(0x1000)
+#define CKM_SKIPJACK_ECB64		(0x1001)
+#define CKM_SKIPJACK_CBC64		(0x1002)
+#define CKM_SKIPJACK_OFB64		(0x1003)
+#define CKM_SKIPJACK_CFB64		(0x1004)
+#define CKM_SKIPJACK_CFB32		(0x1005)
+#define CKM_SKIPJACK_CFB16		(0x1006)
+#define CKM_SKIPJACK_CFB8		(0x1007)
+#define CKM_SKIPJACK_WRAP		(0x1008)
+#define CKM_SKIPJACK_PRIVATE_WRAP	(0x1009)
+#define CKM_SKIPJACK_RELAYX		(0x100a)
+#define CKM_KEA_KEY_PAIR_GEN		(0x1010)
+#define CKM_KEA_KEY_DERIVE		(0x1011)
+#define CKM_FORTEZZA_TIMESTAMP		(0x1020)
+#define CKM_BATON_KEY_GEN		(0x1030)
+#define CKM_BATON_ECB128		(0x1031)
+#define CKM_BATON_ECB96			(0x1032)
+#define CKM_BATON_CBC128		(0x1033)
+#define CKM_BATON_COUNTER		(0x1034)
+#define CKM_BATON_SHUFFLE		(0x1035)
+#define CKM_BATON_WRAP			(0x1036)
+#define CKM_ECDSA_KEY_PAIR_GEN		(0x1040)
+#define CKM_EC_KEY_PAIR_GEN		(0x1040)
+#define CKM_ECDSA			(0x1041)
+#define CKM_ECDSA_SHA1			(0x1042)
+#define CKM_ECDH1_DERIVE		(0x1050)
+#define CKM_ECDH1_COFACTOR_DERIVE	(0x1051)
+#define CKM_ECMQV_DERIVE		(0x1052)
+#define CKM_JUNIPER_KEY_GEN		(0x1060)
+#define CKM_JUNIPER_ECB128		(0x1061)
+#define CKM_JUNIPER_CBC128		(0x1062)
+#define CKM_JUNIPER_COUNTER		(0x1063)
+#define CKM_JUNIPER_SHUFFLE		(0x1064)
+#define CKM_JUNIPER_WRAP		(0x1065)
+#define CKM_FASTHASH			(0x1070)
+#define CKM_AES_KEY_GEN			(0x1080)
+#define CKM_AES_ECB			(0x1081)
+#define CKM_AES_CBC			(0x1082)
+#define CKM_AES_MAC			(0x1083)
+#define CKM_AES_MAC_GENERAL		(0x1084)
+#define CKM_AES_CBC_PAD			(0x1085)
+#define CKM_DSA_PARAMETER_GEN		(0x2000)
+#define CKM_DH_PKCS_PARAMETER_GEN	(0x2001)
+#define CKM_X9_42_DH_PARAMETER_GEN	(0x2002)
+#define CKM_VENDOR_DEFINED		((unsigned long) (1 << 31))
+
+
+struct ck_mechanism
+{
+  ck_mechanism_type_t mechanism;
+  void *parameter;
+  unsigned long parameter_len;
+};
+
+
+struct ck_mechanism_info
+{
+  unsigned long min_key_size;
+  unsigned long max_key_size;
+  ck_flags_t flags;
+};
+
+#define CKF_HW			(1 << 0)
+#define CKF_ENCRYPT		(1 << 8)
+#define CKF_DECRYPT		(1 << 9)
+#define CKF_DIGEST		(1 << 10)
+#define CKF_SIGN		(1 << 11)
+#define CKF_SIGN_RECOVER	(1 << 12)
+#define CKF_VERIFY		(1 << 13)
+#define CKF_VERIFY_RECOVER	(1 << 14)
+#define CKF_GENERATE		(1 << 15)
+#define CKF_GENERATE_KEY_PAIR	(1 << 16)
+#define CKF_WRAP		(1 << 17)
+#define CKF_UNWRAP		(1 << 18)
+#define CKF_DERIVE		(1 << 19)
+#define CKF_EXTENSION		((unsigned long) (1 << 31))
+
+
+/* Flags for C_WaitForSlotEvent.  */
+#define CKF_DONT_BLOCK				(1)
+
+
+typedef unsigned long ck_rv_t;
+
+
+typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session,
+				ck_notification_t event, void *application);
+
+/* Forward reference.  */
+struct ck_function_list;
+
+#define _CK_DECLARE_FUNCTION(name, args)	\
+typedef ck_rv_t (*CK_ ## name) args;		\
+ck_rv_t CK_SPEC name args
+
+_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args));
+_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved));
+_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info));
+_CK_DECLARE_FUNCTION (C_GetFunctionList,
+		      (struct ck_function_list **function_list));
+
+_CK_DECLARE_FUNCTION (C_GetSlotList,
+		      (unsigned char token_present, ck_slot_id_t *slot_list,
+		       unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetSlotInfo,
+		      (ck_slot_id_t slot_id, struct ck_slot_info *info));
+_CK_DECLARE_FUNCTION (C_GetTokenInfo,
+		      (ck_slot_id_t slot_id, struct ck_token_info *info));
+_CK_DECLARE_FUNCTION (C_WaitForSlotEvent,
+		      (ck_flags_t flags, ck_slot_id_t *slot, void *reserved));
+_CK_DECLARE_FUNCTION (C_GetMechanismList,
+		      (ck_slot_id_t slot_id,
+		       ck_mechanism_type_t *mechanism_list,
+		       unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetMechanismInfo,
+		      (ck_slot_id_t slot_id, ck_mechanism_type_t type,
+		       struct ck_mechanism_info *info));
+_CK_DECLARE_FUNCTION (C_InitToken,
+		      (ck_slot_id_t slot_id, unsigned char *pin,
+		       unsigned long pin_len, unsigned char *label));
+_CK_DECLARE_FUNCTION (C_InitPIN,
+		      (ck_session_handle_t session, unsigned char *pin,
+		       unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_SetPIN,
+		      (ck_session_handle_t session, unsigned char *old_pin,
+		       unsigned long old_len, unsigned char *new_pin,
+		       unsigned long new_len));
+
+_CK_DECLARE_FUNCTION (C_OpenSession,
+		      (ck_slot_id_t slot_id, ck_flags_t flags,
+		       void *application, ck_notify_t notify,
+		       ck_session_handle_t *session));
+_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id));
+_CK_DECLARE_FUNCTION (C_GetSessionInfo,
+		      (ck_session_handle_t session,
+		       struct ck_session_info *info));
+_CK_DECLARE_FUNCTION (C_GetOperationState,
+		      (ck_session_handle_t session,
+		       unsigned char *operation_state,
+		       unsigned long *operation_state_len));
+_CK_DECLARE_FUNCTION (C_SetOperationState,
+		      (ck_session_handle_t session,
+		       unsigned char *operation_state,
+		       unsigned long operation_state_len,
+		       ck_object_handle_t encryption_key,
+		       ck_object_handle_t authentiation_key));
+_CK_DECLARE_FUNCTION (C_Login,
+		      (ck_session_handle_t session, ck_user_type_t user_type,
+		       unsigned char *pin, unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_CreateObject,
+		      (ck_session_handle_t session,
+		       struct ck_attribute *templ,
+		       unsigned long count, ck_object_handle_t *object));
+_CK_DECLARE_FUNCTION (C_CopyObject,
+		      (ck_session_handle_t session, ck_object_handle_t object,
+		       struct ck_attribute *templ, unsigned long count,
+		       ck_object_handle_t *new_object));
+_CK_DECLARE_FUNCTION (C_DestroyObject,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object));
+_CK_DECLARE_FUNCTION (C_GetObjectSize,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object,
+		       unsigned long *size));
+_CK_DECLARE_FUNCTION (C_GetAttributeValue,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object,
+		       struct ck_attribute *templ,
+		       unsigned long count));
+_CK_DECLARE_FUNCTION (C_SetAttributeValue,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t object,
+		       struct ck_attribute *templ,
+		       unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjectsInit,
+		      (ck_session_handle_t session,
+		       struct ck_attribute *templ,
+		       unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjects,
+		      (ck_session_handle_t session,
+		       ck_object_handle_t *object,
+		       unsigned long max_object_count,
+		       unsigned long *object_count));
+_CK_DECLARE_FUNCTION (C_FindObjectsFinal,
+		      (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_EncryptInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Encrypt,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *encrypted_data,
+		       unsigned long *encrypted_data_len));
+_CK_DECLARE_FUNCTION (C_EncryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len,
+		       unsigned char *encrypted_part,
+		       unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_EncryptFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *last_encrypted_part,
+		       unsigned long *last_encrypted_part_len));
+
+_CK_DECLARE_FUNCTION (C_DecryptInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Decrypt,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_data,
+		       unsigned long encrypted_data_len,
+		       unsigned char *data, unsigned long *data_len));
+_CK_DECLARE_FUNCTION (C_DecryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_part,
+		       unsigned long encrypted_part_len,
+		       unsigned char *part, unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_DecryptFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *last_part,
+		       unsigned long *last_part_len));
+
+_CK_DECLARE_FUNCTION (C_DigestInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism));
+_CK_DECLARE_FUNCTION (C_Digest,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *digest,
+		       unsigned long *digest_len));
+_CK_DECLARE_FUNCTION (C_DigestUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_DigestKey,
+		      (ck_session_handle_t session, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_DigestFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *digest,
+		       unsigned long *digest_len));
+
+_CK_DECLARE_FUNCTION (C_SignInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Sign,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *signature,
+		       unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_SignFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *signature,
+		       unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignRecoverInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_SignRecover,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *signature,
+		       unsigned long *signature_len));
+
+_CK_DECLARE_FUNCTION (C_VerifyInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Verify,
+		      (ck_session_handle_t session,
+		       unsigned char *data, unsigned long data_len,
+		       unsigned char *signature,
+		       unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_VerifyFinal,
+		      (ck_session_handle_t session,
+		       unsigned char *signature,
+		       unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyRecoverInit,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_VerifyRecover,
+		      (ck_session_handle_t session,
+		       unsigned char *signature,
+		       unsigned long signature_len,
+		       unsigned char *data,
+		       unsigned long *data_len));
+
+_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len,
+		       unsigned char *encrypted_part,
+		       unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_part,
+		       unsigned long encrypted_part_len,
+		       unsigned char *part,
+		       unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_SignEncryptUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *part, unsigned long part_len,
+		       unsigned char *encrypted_part,
+		       unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate,
+		      (ck_session_handle_t session,
+		       unsigned char *encrypted_part,
+		       unsigned long encrypted_part_len,
+		       unsigned char *part,
+		       unsigned long *part_len));
+
+_CK_DECLARE_FUNCTION (C_GenerateKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       struct ck_attribute *templ,
+		       unsigned long count,
+		       ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_GenerateKeyPair,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       struct ck_attribute *public_key_template,
+		       unsigned long public_key_attribute_count,
+		       struct ck_attribute *private_key_template,
+		       unsigned long private_key_attribute_count,
+		       ck_object_handle_t *public_key,
+		       ck_object_handle_t *private_key));
+_CK_DECLARE_FUNCTION (C_WrapKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t wrapping_key,
+		       ck_object_handle_t key,
+		       unsigned char *wrapped_key,
+		       unsigned long *wrapped_key_len));
+_CK_DECLARE_FUNCTION (C_UnwrapKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t unwrapping_key,
+		       unsigned char *wrapped_key,
+		       unsigned long wrapped_key_len,
+		       struct ck_attribute *templ,
+		       unsigned long attribute_count,
+		       ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_DeriveKey,
+		      (ck_session_handle_t session,
+		       struct ck_mechanism *mechanism,
+		       ck_object_handle_t base_key,
+		       struct ck_attribute *templ,
+		       unsigned long attribute_count,
+		       ck_object_handle_t *key));
+
+_CK_DECLARE_FUNCTION (C_SeedRandom,
+		      (ck_session_handle_t session, unsigned char *seed,
+		       unsigned long seed_len));
+_CK_DECLARE_FUNCTION (C_GenerateRandom,
+		      (ck_session_handle_t session,
+		       unsigned char *random_data,
+		       unsigned long random_len));
+
+_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session));
+
+
+struct ck_function_list
+{
+  struct ck_version version;
+  CK_C_Initialize C_Initialize;
+  CK_C_Finalize C_Finalize;
+  CK_C_GetInfo C_GetInfo;
+  CK_C_GetFunctionList C_GetFunctionList;
+  CK_C_GetSlotList C_GetSlotList;
+  CK_C_GetSlotInfo C_GetSlotInfo;
+  CK_C_GetTokenInfo C_GetTokenInfo;
+  CK_C_GetMechanismList C_GetMechanismList;
+  CK_C_GetMechanismInfo C_GetMechanismInfo;
+  CK_C_InitToken C_InitToken;
+  CK_C_InitPIN C_InitPIN;
+  CK_C_SetPIN C_SetPIN;
+  CK_C_OpenSession C_OpenSession;
+  CK_C_CloseSession C_CloseSession;
+  CK_C_CloseAllSessions C_CloseAllSessions;
+  CK_C_GetSessionInfo C_GetSessionInfo;
+  CK_C_GetOperationState C_GetOperationState;
+  CK_C_SetOperationState C_SetOperationState;
+  CK_C_Login C_Login;
+  CK_C_Logout C_Logout;
+  CK_C_CreateObject C_CreateObject;
+  CK_C_CopyObject C_CopyObject;
+  CK_C_DestroyObject C_DestroyObject;
+  CK_C_GetObjectSize C_GetObjectSize;
+  CK_C_GetAttributeValue C_GetAttributeValue;
+  CK_C_SetAttributeValue C_SetAttributeValue;
+  CK_C_FindObjectsInit C_FindObjectsInit;
+  CK_C_FindObjects C_FindObjects;
+  CK_C_FindObjectsFinal C_FindObjectsFinal;
+  CK_C_EncryptInit C_EncryptInit;
+  CK_C_Encrypt C_Encrypt;
+  CK_C_EncryptUpdate C_EncryptUpdate;
+  CK_C_EncryptFinal C_EncryptFinal;
+  CK_C_DecryptInit C_DecryptInit;
+  CK_C_Decrypt C_Decrypt;
+  CK_C_DecryptUpdate C_DecryptUpdate;
+  CK_C_DecryptFinal C_DecryptFinal;
+  CK_C_DigestInit C_DigestInit;
+  CK_C_Digest C_Digest;
+  CK_C_DigestUpdate C_DigestUpdate;
+  CK_C_DigestKey C_DigestKey;
+  CK_C_DigestFinal C_DigestFinal;
+  CK_C_SignInit C_SignInit;
+  CK_C_Sign C_Sign;
+  CK_C_SignUpdate C_SignUpdate;
+  CK_C_SignFinal C_SignFinal;
+  CK_C_SignRecoverInit C_SignRecoverInit;
+  CK_C_SignRecover C_SignRecover;
+  CK_C_VerifyInit C_VerifyInit;
+  CK_C_Verify C_Verify;
+  CK_C_VerifyUpdate C_VerifyUpdate;
+  CK_C_VerifyFinal C_VerifyFinal;
+  CK_C_VerifyRecoverInit C_VerifyRecoverInit;
+  CK_C_VerifyRecover C_VerifyRecover;
+  CK_C_DigestEncryptUpdate C_DigestEncryptUpdate;
+  CK_C_DecryptDigestUpdate C_DecryptDigestUpdate;
+  CK_C_SignEncryptUpdate C_SignEncryptUpdate;
+  CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate;
+  CK_C_GenerateKey C_GenerateKey;
+  CK_C_GenerateKeyPair C_GenerateKeyPair;
+  CK_C_WrapKey C_WrapKey;
+  CK_C_UnwrapKey C_UnwrapKey;
+  CK_C_DeriveKey C_DeriveKey;
+  CK_C_SeedRandom C_SeedRandom;
+  CK_C_GenerateRandom C_GenerateRandom;
+  CK_C_GetFunctionStatus C_GetFunctionStatus;
+  CK_C_CancelFunction C_CancelFunction;
+  CK_C_WaitForSlotEvent C_WaitForSlotEvent;
+};
+
+
+typedef ck_rv_t (*ck_createmutex_t) (void **mutex);
+typedef ck_rv_t (*ck_destroymutex_t) (void *mutex);
+typedef ck_rv_t (*ck_lockmutex_t) (void *mutex);
+typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex);
+
+
+struct ck_c_initialize_args
+{
+  ck_createmutex_t create_mutex;
+  ck_destroymutex_t destroy_mutex;
+  ck_lockmutex_t lock_mutex;
+  ck_unlockmutex_t unlock_mutex;
+  ck_flags_t flags;
+  void *reserved;
+};
+
+
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS	(1 << 0)
+#define CKF_OS_LOCKING_OK			(1 << 1)
+
+#define CKR_OK					(0)
+#define CKR_CANCEL				(1)
+#define CKR_HOST_MEMORY				(2)
+#define CKR_SLOT_ID_INVALID			(3)
+#define CKR_GENERAL_ERROR			(5)
+#define CKR_FUNCTION_FAILED			(6)
+#define CKR_ARGUMENTS_BAD			(7)
+#define CKR_NO_EVENT				(8)
+#define CKR_NEED_TO_CREATE_THREADS		(9)
+#define CKR_CANT_LOCK				(0xa)
+#define CKR_ATTRIBUTE_READ_ONLY			(0x10)
+#define CKR_ATTRIBUTE_SENSITIVE			(0x11)
+#define CKR_ATTRIBUTE_TYPE_INVALID		(0x12)
+#define CKR_ATTRIBUTE_VALUE_INVALID		(0x13)
+#define CKR_DATA_INVALID			(0x20)
+#define CKR_DATA_LEN_RANGE			(0x21)
+#define CKR_DEVICE_ERROR			(0x30)
+#define CKR_DEVICE_MEMORY			(0x31)
+#define CKR_DEVICE_REMOVED			(0x32)
+#define CKR_ENCRYPTED_DATA_INVALID		(0x40)
+#define CKR_ENCRYPTED_DATA_LEN_RANGE		(0x41)
+#define CKR_FUNCTION_CANCELED			(0x50)
+#define CKR_FUNCTION_NOT_PARALLEL		(0x51)
+#define CKR_FUNCTION_NOT_SUPPORTED		(0x54)
+#define CKR_KEY_HANDLE_INVALID			(0x60)
+#define CKR_KEY_SIZE_RANGE			(0x62)
+#define CKR_KEY_TYPE_INCONSISTENT		(0x63)
+#define CKR_KEY_NOT_NEEDED			(0x64)
+#define CKR_KEY_CHANGED				(0x65)
+#define CKR_KEY_NEEDED				(0x66)
+#define CKR_KEY_INDIGESTIBLE			(0x67)
+#define CKR_KEY_FUNCTION_NOT_PERMITTED		(0x68)
+#define CKR_KEY_NOT_WRAPPABLE			(0x69)
+#define CKR_KEY_UNEXTRACTABLE			(0x6a)
+#define CKR_MECHANISM_INVALID			(0x70)
+#define CKR_MECHANISM_PARAM_INVALID		(0x71)
+#define CKR_OBJECT_HANDLE_INVALID		(0x82)
+#define CKR_OPERATION_ACTIVE			(0x90)
+#define CKR_OPERATION_NOT_INITIALIZED		(0x91)
+#define CKR_PIN_INCORRECT			(0xa0)
+#define CKR_PIN_INVALID				(0xa1)
+#define CKR_PIN_LEN_RANGE			(0xa2)
+#define CKR_PIN_EXPIRED				(0xa3)
+#define CKR_PIN_LOCKED				(0xa4)
+#define CKR_SESSION_CLOSED			(0xb0)
+#define CKR_SESSION_COUNT			(0xb1)
+#define CKR_SESSION_HANDLE_INVALID		(0xb3)
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED	(0xb4)
+#define CKR_SESSION_READ_ONLY			(0xb5)
+#define CKR_SESSION_EXISTS			(0xb6)
+#define CKR_SESSION_READ_ONLY_EXISTS		(0xb7)
+#define CKR_SESSION_READ_WRITE_SO_EXISTS	(0xb8)
+#define CKR_SIGNATURE_INVALID			(0xc0)
+#define CKR_SIGNATURE_LEN_RANGE			(0xc1)
+#define CKR_TEMPLATE_INCOMPLETE			(0xd0)
+#define CKR_TEMPLATE_INCONSISTENT		(0xd1)
+#define CKR_TOKEN_NOT_PRESENT			(0xe0)
+#define CKR_TOKEN_NOT_RECOGNIZED		(0xe1)
+#define CKR_TOKEN_WRITE_PROTECTED		(0xe2)
+#define	CKR_UNWRAPPING_KEY_HANDLE_INVALID	(0xf0)
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE		(0xf1)
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT	(0xf2)
+#define CKR_USER_ALREADY_LOGGED_IN		(0x100)
+#define CKR_USER_NOT_LOGGED_IN			(0x101)
+#define CKR_USER_PIN_NOT_INITIALIZED		(0x102)
+#define CKR_USER_TYPE_INVALID			(0x103)
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN	(0x104)
+#define CKR_USER_TOO_MANY_TYPES			(0x105)
+#define CKR_WRAPPED_KEY_INVALID			(0x110)
+#define CKR_WRAPPED_KEY_LEN_RANGE		(0x112)
+#define CKR_WRAPPING_KEY_HANDLE_INVALID		(0x113)
+#define CKR_WRAPPING_KEY_SIZE_RANGE		(0x114)
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT	(0x115)
+#define CKR_RANDOM_SEED_NOT_SUPPORTED		(0x120)
+#define CKR_RANDOM_NO_RNG			(0x121)
+#define CKR_DOMAIN_PARAMS_INVALID		(0x130)
+#define CKR_BUFFER_TOO_SMALL			(0x150)
+#define CKR_SAVED_STATE_INVALID			(0x160)
+#define CKR_INFORMATION_SENSITIVE		(0x170)
+#define CKR_STATE_UNSAVEABLE			(0x180)
+#define CKR_CRYPTOKI_NOT_INITIALIZED		(0x190)
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED	(0x191)
+#define CKR_MUTEX_BAD				(0x1a0)
+#define CKR_MUTEX_NOT_LOCKED			(0x1a1)
+#define CKR_FUNCTION_REJECTED			(0x200)
+#define CKR_VENDOR_DEFINED			((unsigned long) (1 << 31))
+
+
+
+/* Compatibility layer.  */
+
+#ifdef CRYPTOKI_COMPAT
+
+#undef CK_DEFINE_FUNCTION
+#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name
+
+/* For NULL.  */
+#include <stddef.h>
+
+typedef unsigned char CK_BYTE;
+typedef unsigned char CK_CHAR;
+typedef unsigned char CK_UTF8CHAR;
+typedef unsigned char CK_BBOOL;
+typedef unsigned long int CK_ULONG;
+typedef long int CK_LONG;
+typedef CK_BYTE *CK_BYTE_PTR;
+typedef CK_CHAR *CK_CHAR_PTR;
+typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR;
+typedef CK_ULONG *CK_ULONG_PTR;
+typedef void *CK_VOID_PTR;
+typedef void **CK_VOID_PTR_PTR;
+#define CK_FALSE 0
+#define CK_TRUE 1
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#endif
+
+typedef struct ck_version CK_VERSION;
+typedef struct ck_version *CK_VERSION_PTR;
+
+typedef struct ck_info CK_INFO;
+typedef struct ck_info *CK_INFO_PTR;
+
+typedef ck_slot_id_t *CK_SLOT_ID_PTR;
+
+typedef struct ck_slot_info CK_SLOT_INFO;
+typedef struct ck_slot_info *CK_SLOT_INFO_PTR;
+
+typedef struct ck_token_info CK_TOKEN_INFO;
+typedef struct ck_token_info *CK_TOKEN_INFO_PTR;
+
+typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR;
+
+typedef struct ck_session_info CK_SESSION_INFO;
+typedef struct ck_session_info *CK_SESSION_INFO_PTR;
+
+typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR;
+
+typedef ck_object_class_t *CK_OBJECT_CLASS_PTR;
+
+typedef struct ck_attribute CK_ATTRIBUTE;
+typedef struct ck_attribute *CK_ATTRIBUTE_PTR;
+
+typedef struct ck_date CK_DATE;
+typedef struct ck_date *CK_DATE_PTR;
+
+typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR;
+
+typedef struct ck_mechanism CK_MECHANISM;
+typedef struct ck_mechanism *CK_MECHANISM_PTR;
+
+typedef struct ck_mechanism_info CK_MECHANISM_INFO;
+typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR;
+
+typedef struct ck_function_list CK_FUNCTION_LIST;
+typedef struct ck_function_list *CK_FUNCTION_LIST_PTR;
+typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR;
+
+typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS;
+typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR;
+
+#define NULL_PTR NULL
+
+/* Delete the helper macros defined at the top of the file.  */
+#undef ck_flags_t
+#undef ck_version
+
+#undef ck_info
+#undef cryptoki_version
+#undef manufacturer_id
+#undef library_description
+#undef library_version
+
+#undef ck_notification_t
+#undef ck_slot_id_t
+
+#undef ck_slot_info
+#undef slot_description
+#undef hardware_version
+#undef firmware_version
+
+#undef ck_token_info
+#undef serial_number
+#undef max_session_count
+#undef session_count
+#undef max_rw_session_count
+#undef rw_session_count
+#undef max_pin_len
+#undef min_pin_len
+#undef total_public_memory
+#undef free_public_memory
+#undef total_private_memory
+#undef free_private_memory
+#undef utc_time
+
+#undef ck_session_handle_t
+#undef ck_user_type_t
+#undef ck_state_t
+
+#undef ck_session_info
+#undef slot_id
+#undef device_error
+
+#undef ck_object_handle_t
+#undef ck_object_class_t
+#undef ck_hw_feature_type_t
+#undef ck_key_type_t
+#undef ck_certificate_type_t
+#undef ck_attribute_type_t
+
+#undef ck_attribute
+#undef value
+#undef value_len
+
+#undef ck_date
+
+#undef ck_mechanism_type_t
+
+#undef ck_mechanism
+#undef parameter
+#undef parameter_len
+
+#undef ck_mechanism_info
+#undef min_key_size
+#undef max_key_size
+
+#undef ck_rv_t
+#undef ck_notify_t
+
+#undef ck_function_list
+
+#undef ck_createmutex_t
+#undef ck_destroymutex_t
+#undef ck_lockmutex_t
+#undef ck_unlockmutex_t
+
+#undef ck_c_initialize_args
+#undef create_mutex
+#undef destroy_mutex
+#undef lock_mutex
+#undef unlock_mutex
+#undef reserved
+
+#endif	/* CRYPTOKI_COMPAT */
+
+
+/* System dependencies.  */
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+#pragma pack(pop, cryptoki)
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif	/* PKCS11_H */

Added: trunk/TokendPKCS11/src/CFUtilities.cpp
===================================================================
--- trunk/TokendPKCS11/src/CFUtilities.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/CFUtilities.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "CFUtilities.h"
+#include <CoreFoundation/CFBase.h>
+
+void CFDeleter::call(const void *ref) {
+	CFRelease((CFTypeRef)ref);
+}

Added: trunk/TokendPKCS11/src/HandleManager.inc
===================================================================
--- trunk/TokendPKCS11/src/HandleManager.inc	                        (rev 0)
+++ trunk/TokendPKCS11/src/HandleManager.inc	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,101 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+template<typename T>
+HandleManager<T>::HandleManager(int base /* = 0 */)
+:values(), base(base) {
+}
+
+template<typename T>
+void HandleManager<T>::refresh_active_reference(iterator iter) {
+	int handle = iter - values.begin() + base;
+	(*iter)->setHandle(handle);
+}
+
+template<typename T>
+template<typename OutputIterator, typename Filter>
+void HandleManager<T>::copy_handles(OutputIterator result, Filter filter) {
+	for(int i = 0; i < values.size(); i++) {
+		if(filter(values[i])) {
+			*result = i + base;
+			++result;
+		}
+	}
+}
+
+
+template<typename T>
+template<typename Filter>
+typename HandleManager<T>::iterator HandleManager<T>::add(ref_type ref, Filter notEmpty) {
+	iterator iter = find_if(values.begin(), values.end(), not1(notEmpty));
+	if(iter == values.end()) {
+		values.push_back(ref);
+		ref->setHandle(values.size() - 1 + base);
+		return values.end() - 1;
+	}
+	*iter = ref;
+	refresh_active_reference(iter);
+	return iter;
+}
+
+/* Remove from the end everything until the last non 'filter-success' value or there's only size units left */
+template<typename T>
+template<typename Filter>
+void HandleManager<T>::remove_after_last_match(size_t min_size, Filter filter) {
+	if(values.size() <= min_size) return;
+	reverse_iterator erase_begin = values.rbegin();
+	reverse_iterator erase_end(values.begin() + min_size);
+	erase_end = find_if(erase_begin, erase_end, filter);
+	values.erase(erase_end.base(),erase_begin.base());
+}
+
+template<typename T>
+bool HandleManager<T>::valid_handle(int handle) const {
+	handle -= base;
+	return handle < values.size() && handle >= 0 && handle != INVALID_HANDLE_VALUE;
+}
+
+
+template<typename T>
+void HandleManager<T>::erase(const iterator &iter) {
+	if(iter == end()) return;
+	/* Reset handle to INVALID_HANDLE_VALUE in case anything's holding on */
+	(*iter)->invalidate();
+	(*iter).reset((T*)NULL);
+	/* Cleanup is responsibility of client */
+}
+
+template<typename T>
+void HandleManager<T>::kill_lockable_value(const iterator &iter) {
+	if(iter == end()) return;
+	/* C++ spec states that `sessionLock` will get collected before `saved_mutex` will at closeout, thus safety ensues */
+	ref_type value = *iter;
+	LockableHandledObject<T> &lockable = *value;
+	StLock<UserMutex> valueLock(lockable.getLock().writeMutex()); /* VALIDATED */
+	/* Pull out the lock for safety */
+	auto_ptr<UserMutex> saved_mutex(lockable.releaseLock());
+	erase(iter);
+	/* Force early unlock before the mutex is destroyed */
+	valueLock.unlock();
+}
+

Added: trunk/TokendPKCS11/src/P11Attribute.cpp
===================================================================
--- trunk/TokendPKCS11/src/P11Attribute.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/P11Attribute.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,137 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11Attribute.h"
+#include "Utilities.h"
+
+P11Attribute::P11Attribute(ck_attribute_type_t type, const void *data, size_t data_len) {
+	init(type, data, data_len);
+}
+
+P11Attribute::P11Attribute(const struct ck_attribute &attr) {
+	init(attr.type, attr.value, attr.value_len);
+}
+
+P11Attribute::~P11Attribute() {
+	if(value)
+		free(value);
+}
+
+void P11Attribute::init(ck_attribute_type_t type, const void *data, size_t data_len) {
+	this->type = type;
+	this->value_len = data_len;
+	this->value = malloc(data_len);
+	if(!this->value)
+		throw P11Exception(CKR_HOST_MEMORY);
+	memcpy(this->value, data, data_len);
+}
+
+bool P11Attribute::getBool() const {
+	return 0 != getLong();
+}
+
+long P11Attribute::getLong() const {
+	/* Try to be accomodating to diff sizes.. */
+	switch(value_len) {
+#if LONG_MAX != INT_MAX
+	case sizeof(long):
+		return *(long*)(value);
+#endif
+	case sizeof(int):
+		return *(int*)(value);
+	case sizeof(short):
+		return *(short*)(value);
+	case sizeof(char):
+		return *(char*)(value);
+	default:
+		throw P11Exception(CKR_ATTRIBUTE_VALUE_INVALID);
+	}
+}
+
+bool P11Attribute::operator ==(const P11Attribute &comparand) const {
+	return type == comparand.type
+		&& value_len == comparand.value_len
+		&& (value && comparand.value)
+		&& 0 == memcmp(value, comparand.value, value_len);
+}
+
+P11Attributes::P11Attributes() : attributes() {
+}
+
+P11Attributes::P11Attributes(struct ck_attribute *attrs, ulong count) : attributes() {
+	for(int i = 0; i < count; i++) {
+		attributes[attrs[i].type] = P11Attribute_Ref(new P11Attribute(attrs[i]));
+	}
+}
+
+void P11Attributes::add(ck_attribute_type_t type, const void *data, size_t data_len) {
+	P11Attribute_Ref attr(new P11Attribute(type, data, data_len));
+	attributes.insert(P11AttributeMap::value_type(type, attr));
+}
+
+ck_object_class_t P11Attributes::oclass() const {
+	P11AttributeMap::const_iterator iter = attributes.find(CKA_CLASS);
+	if(iter == attributes.end())
+		return CKO_VENDOR_DEFINED; /* Should we err out? */
+	return iter->second->getLong();
+}
+
+ck_rv_t P11Attributes::get(struct ck_attribute *attrs, ulong count) const {
+	ck_rv_t ret = CKR_OK;
+	/* FIRST: Check for permissions -- not so applicable here...
+	 * SECOND: Check for all values existing
+	 * THIRD: Check that there's enough space to hold the individual value
+	 * -NOTE-: Even if there is such an error, do not return immediately, process all values
+	 * Multiple errors lead to undefined error returned
+	 */
+	for(;count > 0; count--, attrs++) {
+		const P11AttributeMap::const_iterator iter = attributes.find(attrs->type);
+		/* NOOP: Permission check */
+		if(iter == attributes.end()) {
+			attrs->value_len = -1;
+			ret = CKR_ATTRIBUTE_TYPE_INVALID;
+		} else if(!attrs->value) {
+			attrs->value_len = iter->second->value_len;
+		} else if(attrs->value_len < iter->second->value_len) {
+			attrs->value_len = -1;
+			ret = CKR_BUFFER_TOO_SMALL;
+		} else {
+			attrs->value_len = iter->second->value_len;
+			if(attrs->value)
+				memcpy(attrs->value, iter->second->value, attrs->value_len);
+		}
+	}
+	return ret;
+}
+
+/* Return true if this attribute object matches each element in search */
+bool P11Attributes::match(const P11Attributes &search) const {
+	P11AttributeMap::const_iterator iter, endIter = search.attributes.end();
+	for(iter = search.attributes.begin(); iter != endIter; ++iter) {
+		const P11AttributeMap::const_iterator matchIter = attributes.find(iter->first);
+		/* Attribute missing */
+		if(matchIter == attributes.end()) return false;
+		if(!(*matchIter->second == *iter->second)) return false;
+	}
+	return true;
+}

Added: trunk/TokendPKCS11/src/P11CryptoState.cpp
===================================================================
--- trunk/TokendPKCS11/src/P11CryptoState.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/P11CryptoState.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,205 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11CryptoState.h"
+#include "P11Identity.h"
+
+#include "CFUtilities.h"
+#include <Security/Security.h>
+
+P11CryptoState::P11CryptoState(P11Object_Ref key, const struct ck_mechanism &mechanism)
+: key(key), mechanism(mechanism) {
+	if(key->oclass() != CKO_PRIVATE_KEY)
+		throw P11Exception(CKR_KEY_HANDLE_INVALID);
+	/* CURRENTLY ONLY SUPPORT CKM_RSA_PKCS */
+	/* MUST SUPPORT CKM_RSA_X_509 for SSL */
+	if(mechanism.mechanism != CKM_RSA_PKCS && mechanism.mechanism != CKM_RSA_X_509)
+		throw P11Exception(CKR_MECHANISM_INVALID);
+	/* CKM_RSA_PKCS takes no params */
+//	if(mechanism.parameter_len != 0)
+//		throw P11Exception(CKR_MECHANISM_PARAM_INVALID);
+	/* Null out the ptr since it wont be copied to use */
+	this->mechanism.parameter = NULL;
+}
+
+P11CryptoState::~P11CryptoState() {
+	if(mechanism.parameter)
+		free(mechanism.parameter);
+}
+
+static void check(OSStatus status, ck_rv_t errorValue = CKR_FUNCTION_FAILED) {
+	if(noErr != status)
+		throw P11Exception(errorValue);
+}
+
+static int getKeySize(SecKeyRef keyRef) {
+	const CSSM_KEY *cssmKey;
+	check(SecKeyGetCSSMKey(keyRef, &cssmKey));
+	return cssmKey->KeyHeader.LogicalKeySizeInBits / 8;
+}
+
+
+class CSSM_Context_Deleter {
+public:
+	static void call(CSSM_CC_HANDLE handle) {
+		if(handle) CSSM_DeleteContext(handle);
+	}
+};
+
+/* Expects input and output to handle full keysize of data */
+static void rawCrypt(SecKeyRef keyRef, const byte *input, ulong input_len, byte *output, ulong &output_len) {
+	ScopedCF<CSSM_CC_HANDLE,CSSM_Context_Deleter> cc;
+	const CSSM_KEY *cssmKey;
+	CSSM_CSP_HANDLE csp;
+	const CSSM_ACCESS_CREDENTIALS *accessCred;
+	CSSM_ALGORITHMS encrPad = CSSM_PADDING_NONE;
+	CSSM_ALGORITHMS encrAlg = CSSM_ALGID_RSA;
+
+	check(SecKeyGetCSSMKey(keyRef, &cssmKey));
+	check(SecKeyGetCSPHandle(keyRef, &csp));
+	check(SecKeyGetCredentials(keyRef, CSSM_ACL_AUTHORIZATION_DECRYPT, kSecCredentialTypeWithUI, &accessCred));
+	check(CSSM_CSP_CreateAsymmetricContext(csp, encrAlg, accessCred, cssmKey, encrPad, &cc));
+
+	CSSM_DATA dataBuf = { input_len, (byte*)input};
+	CSSM_DATA result = { output_len, output };
+
+	byte remainBuffer[1024];
+	memset(remainBuffer, 0, sizeof(remainBuffer));
+	memset(output, 0, output_len);
+	CSSM_DATA remData = {sizeof(remainBuffer), remainBuffer};
+	check(CSSM_DecryptData(cc, &dataBuf, 1, &result, 1, &output_len, &remData));
+}
+
+/* PKCS1 padding for signature */
+static void pkcs_pad(const byte *input, ulong input_len, byte *output, ulong output_len) {
+	int data_start = output_len - input_len;
+	if(data_start < 11) /* Min 8-bytes of padding, w/ 3 bytes extra */
+		throw P11Exception(CKR_DATA_LEN_RANGE);
+	output[0] = 0;
+	output[1] = 1;
+	memset(&output[2], 0xFF, data_start - 3);
+	output[data_start - 1] = 0;
+	memcpy(&output[data_start], input, input_len);
+}
+
+static ck_rv_t pkcs_strip(const byte *input, ulong input_len, const byte **data_begin) {
+	int i;
+	if(input[0] != 0 || input[1] != 2)
+		return CKR_ENCRYPTED_DATA_INVALID;
+	for(i = 3; i < input_len; i++) {
+		if(0 == input[i])
+			goto found_end;
+	}
+	return CKR_ENCRYPTED_DATA_INVALID;
+found_end:
+	i++;
+	*data_begin = &input[i];
+	return CKR_OK;
+}
+
+ck_rv_t P11CryptoState::sign(const byte *input, ulong input_len, byte *output, ulong &output_len) {
+	/* GET THE KEYCHAIN OBJECT */
+	SecIdentityRef identityRef = getIdentityRef();
+	ScopedCF<SecKeyRef> keyRef;
+	OSStatus status = SecIdentityCopyPrivateKey(identityRef, &keyRef);
+	if(noErr != status) /* TODO: Enhance error return */
+		return CKR_FUNCTION_FAILED;
+	if(!input)
+		return CKR_ARGUMENTS_BAD;
+	int key_size = getKeySize(keyRef);
+	if(!output) {
+		output_len = key_size;
+		return CKR_OK;
+	}
+	if(output_len < key_size)
+		return CKR_BUFFER_TOO_SMALL;
+	byte dataToSign[key_size];
+	switch(mechanism.mechanism) {
+	case CKM_RSA_PKCS:
+		pkcs_pad(input, input_len, dataToSign, key_size);
+		break;
+	case CKM_RSA_X_509:
+		if(input_len != key_size)
+			return CKR_SIGNATURE_LEN_RANGE;
+		memcpy(dataToSign, input, key_size);
+		break;
+	default:
+		/* Init must catch this case */
+		return CKR_GENERAL_ERROR;
+	}
+	rawCrypt(keyRef, dataToSign, key_size, output, output_len);
+	return CKR_OK;
+}
+
+ck_rv_t P11CryptoState::decrypt(const byte *input, ulong input_len, byte *output, ulong &output_len) {
+	/* GET THE KEYCHAIN OBJECT */
+	SecIdentityRef identityRef = getIdentityRef();
+	ScopedCF<SecKeyRef> keyRef;
+	OSStatus status = SecIdentityCopyPrivateKey(identityRef, &keyRef);
+	if(noErr != status) /* TODO: Enhance error return */
+		return CKR_FUNCTION_FAILED;
+	if(!input)
+		return CKR_ARGUMENTS_BAD;
+	ulong key_size = getKeySize(keyRef);
+	if(!output) { /* max size is keysize */
+		output_len = key_size;
+		return CKR_OK;
+	}
+	byte decryptedData[key_size];
+	const byte *unpadded_data;
+	rawCrypt(keyRef, input, input_len, decryptedData, key_size);
+	switch(mechanism.mechanism) {
+	case CKM_RSA_PKCS:
+		{
+			ck_rv_t ret = pkcs_strip(decryptedData, key_size, &unpadded_data);
+			if(ret != CKR_OK)
+				return ret;
+		}
+		break;
+	case CKM_RSA_X_509:
+		unpadded_data = decryptedData;
+		break;
+	default:
+		/* Init must catch this case */
+		return CKR_GENERAL_ERROR;
+	}
+	int unpadded_data_size = decryptedData + key_size - unpadded_data;
+	if(!output) {
+		output_len = unpadded_data_size;
+		return CKR_OK;
+	}
+	if(output_len < unpadded_data_size) {
+		output_len = unpadded_data_size;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+	output_len = unpadded_data_size;
+	memcpy(output, unpadded_data, unpadded_data_size);
+	return CKR_OK;
+}
+
+SecIdentityRef P11CryptoState::getIdentityRef() const {
+	P11Identity_Ref identity = key->getIdentity().lock();
+	if(!identity.get())
+		throw P11Exception(CKR_ATTRIBUTE_VALUE_INVALID);
+	return identity->getIdentity();
+}

Added: trunk/TokendPKCS11/src/P11Identity.cpp
===================================================================
--- trunk/TokendPKCS11/src/P11Identity.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/P11Identity.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,315 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11Identity.h"
+#include "CFUtilities.h"
+#include <Security/Security.h>
+
+#include "TLV.h"
+
+#include "config-objects.h"
+
+P11Identity::P11Identity(SecIdentityRef identity)
+: identity(identity), privateKey(), publicKey(), certificate() {
+	CFRetain(identity);
+}
+
+P11Identity::~P11Identity() {
+	CFRelease(identity);
+}
+
+
+typedef struct bool_attr {
+	ck_attribute_type_t type;
+	byte value;
+} bool_attr;
+typedef struct long_attr {
+	ck_attribute_type_t type;
+	long value;
+} long_attr;
+typedef struct raw_attr {
+	ck_attribute_type_t type;
+	const void *value;
+	ulong size;
+} raw_attr;
+
+static void check(OSStatus status, ck_rv_t errorValue = CKR_FUNCTION_FAILED) {
+	if(noErr != status)
+		throw P11Exception(errorValue);
+}
+
+static void checkAssert(bool value, ck_rv_t errorValue = CKR_FUNCTION_FAILED) {
+	if(!value)
+		throw P11Exception(errorValue);
+}
+
+
+class SKIPKEY {
+};
+
+static const std::string getLabel(SecKeychainItemRef item) {
+	SecKeychainAttribute attr = {
+		kSecLabelItemAttr, 0, NULL
+	};
+	SecKeychainAttributeList list = {
+		1, &attr
+	};
+	check(SecKeychainItemCopyContent(item, NULL, &list, NULL, NULL));
+	const std::string ret((char*)attr.data, attr.length);
+	SecKeychainItemFreeContent(&list, NULL);
+	return ret;
+}
+
+bool operator==(const CSSM_OID &a, const CSSM_OID &b) {
+	return a.Length == b.Length && 0 == memcmp(a.Data, b.Data, a.Length);
+}
+
+bool operator!=(const CSSM_OID &a, const CSSM_OID &b) {
+	return !(a == b);
+}
+
+static const std::string getPrivateKeyLabel(SecIdentityRef identity) {
+	ScopedCF<SecKeyRef> keyRef;
+	check(SecIdentityCopyPrivateKey(identity, &keyRef));
+	return getLabel((SecKeychainItemRef)keyRef.get());
+}
+
+static void getCertData(SecIdentityRef identity, P11Attributes &certAttributes, P11Attributes &pubKeyAttributes, P11Attributes &keyAttributes) {
+	ScopedCF<SecCertificateRef> certRef;
+	check(SecIdentityCopyCertificate(identity, &certRef));
+	
+	const std::string &label = getLabel((SecKeychainItemRef)certRef.get());
+	certAttributes.add(CKA_LABEL, label.data(), label.size());
+	pubKeyAttributes.add(CKA_LABEL, label.data(), label.size());
+	
+	CSSM_DATA cert_data;
+	check(SecCertificateGetData(certRef, &cert_data));
+	certAttributes.add(CKA_VALUE, cert_data.Data, cert_data.Length);
+	
+	CSSM_CL_HANDLE cl;
+	check(SecCertificateGetCLHandle(certRef, &cl));
+	
+	uint32 fieldCount = 0;
+	CSSM_FIELD_PTR fields;
+	CSSM_RETURN ret = CSSM_CL_CertGetAllFields(cl, &cert_data, &fieldCount, &fields);
+	checkAssert(ret == CSSM_OK);
+	try {
+		for(int i = 0; i < fieldCount; i++) {
+			/* Handle field */
+			const CSSM_OID &oid = fields[i].FieldOid;
+			const CSSM_DATA &data = fields[i].FieldValue;
+			if(oid == CSSMOID_X509V1SerialNumber) {
+				certAttributes.add(CKA_SERIAL_NUMBER, data.Data, data.Length);
+			} else if(oid == CSSMOID_X509V1IssuerNameStd) {
+				certAttributes.add(CKA_ISSUER, data.Data, data.Length);
+			} else if(oid == CSSMOID_X509V1SubjectNameStd) {
+				certAttributes.add(CKA_SUBJECT, data.Data, data.Length);
+				keyAttributes.add(CKA_SUBJECT, data.Data, data.Length);
+				pubKeyAttributes.add(CKA_SUBJECT, data.Data, data.Length);
+			} else if(oid == CSSMOID_X509V1SubjectPublicKeyCStruct) {
+				CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *pubKeyInfo =
+				(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)data.Data;
+				/* REQUIRE RSA */
+				if(pubKeyInfo->algorithm.algorithm != CSSMOID_RSA)
+					throw P11Exception(CKR_FUNCTION_FAILED);
+				byte *begin = pubKeyInfo->subjectPublicKey.Data;
+				byte *end = begin + pubKeyInfo->subjectPublicKey.Length;
+				byte *ptr = begin;
+				try {
+					TLV_ref keyData = TLV::parse(ptr, end);
+					checkAssert(keyData->getTag() == 0x30);
+					const TLVList &values = keyData->getInnerValues();
+					checkAssert(values.size() == 2);
+					const byte_string &modulus = values[0]->getValue();
+					const byte_string &exponent = values[1]->getValue();
+					int modulusDataBegin = 0;
+					/* Trim off extra zeroes in modulus encoding */
+					while(!modulus[modulusDataBegin])
+						modulusDataBegin++;
+					pubKeyAttributes.add(CKA_MODULUS, &modulus[0], modulus.size());
+					pubKeyAttributes.add(CKA_PUBLIC_EXPONENT, &exponent[0], exponent.size());
+					pubKeyAttributes.addLong(CKA_MODULUS_BITS, (modulus.size() - modulusDataBegin) * 8);
+					keyAttributes.add(CKA_MODULUS, &modulus[0], modulus.size());
+					keyAttributes.add(CKA_PUBLIC_EXPONENT, &exponent[0], exponent.size());
+					pubKeyAttributes.add(CKA_VALUE, begin, end - begin);
+				} catch(runtime_error &e) {
+					throw P11Exception(CKR_FUNCTION_FAILED);
+				}
+			}
+		}
+		CSSM_CL_FreeFields(cl, fieldCount, &fields);
+	} catch(P11Exception &e) {
+		CSSM_CL_FreeFields(cl, fieldCount, &fields);
+		throw e;
+	}
+}
+
+static int should_skip(const std::string &label) {
+	for(const char **p = SKIP_OBJECT_MATCH; p && *p; p++) {
+		if(-1 != label.find(*p))
+			return 1;
+	}
+	return 0;
+}
+
+static void getKeyData(SecIdentityRef identity, P11Attributes &keyAttributes) {
+	const std::string &label = getPrivateKeyLabel(identity);
+	if(should_skip(label))
+		throw SKIPKEY();
+	keyAttributes.add(CKA_LABEL, label.data(), label.size());
+}
+
+#define SET_BOOL_ATTRIBUTES(store,attrs) do {\
+for(int i = 0; i < sizeof(attrs) / sizeof(attrs[0]); i++) \
+store.addBool(attrs[i].type, attrs[i].value); \
+} while(0)
+#define SET_LONG_ATTRIBUTES(store,attrs) do {\
+for(int i = 0; i < sizeof(attrs) / sizeof(attrs[0]); i++) \
+store.addLong(attrs[i].type, attrs[i].value); \
+} while(0)
+#define SET_RAW_ATTRIBUTES(store,attrs) do {\
+for(int i = 0; i < sizeof(attrs) / sizeof(attrs[0]); i++) \
+store.add(attrs[i].type, attrs[i].value, attrs[i].size); \
+} while(0)
+
+bool P11Identity::createObjects(P11Objects_Ref objects, P11Identity_Ref &identity_reference) {
+	static const long_attr keyLongs[] = {
+		{ CKA_KEY_TYPE, CKK_RSA }
+	};
+	static const bool_attr keyBools[] = {
+		/* Stored-object specific */
+		{ CKA_MODIFIABLE, 0 },
+		{ CKA_TOKEN, 1 },
+		/* Key Specific */
+		{ CKA_EXTRACTABLE, 0 },
+		{ CKA_SENSITIVE, 1 },
+		{ CKA_DECRYPT, 1 },
+		{ CKA_SIGN, 1 },
+		{ CKA_SIGN_RECOVER, 0 },
+		{ CKA_UNWRAP, 0 }, /* CURRENTLY NO KEY UNWRAPPING */
+		{ CKA_ALWAYS_AUTHENTICATE, 0 },
+		{ CKA_WRAP_WITH_TRUSTED, 0 },
+		{ CKA_ALWAYS_SENSITIVE, 1 },
+		{ CKA_NEVER_EXTRACTABLE, 1 },
+		{ CKA_LOCAL, 0 } /* NOTHING ASSUMED ABOUT KEY */
+	};
+	static const long mech_array[] = {
+		CKM_RSA_PKCS,
+		CKM_RSA_X_509
+	};
+	static const raw_attr keyRaws[] = {
+		{ CKA_START_DATE, NULL, 0 },
+		{ CKA_END_DATE, NULL, 0 },
+		{ CKA_ALLOWED_MECHANISMS, mech_array, sizeof(mech_array) },
+/* { CKA_KEY_GEN_MECHANISM, -- unavailable, not empty } */
+		{ CKA_UNWRAP_TEMPLATE, NULL, 0 }
+	};
+	static const long_attr pubKeyLongs[] = {
+		{ CKA_KEY_TYPE, CKK_RSA }
+	};
+	static const bool_attr pubKeyBools[] = {
+		{ CKA_MODIFIABLE, 0 },
+		{ CKA_TOKEN, 1 },
+		{ CKA_ENCRYPT, 0 },
+		{ CKA_VERIFY, 0 },
+		{ CKA_VERIFY_RECOVER, 0 },
+		{ CKA_WRAP, 0 },
+		{ CKA_TRUSTED, 0 }
+	};
+	static const raw_attr pubKeyRaws[] = {
+		{ CKA_START_DATE, NULL, 0 },
+		{ CKA_END_DATE, NULL, 0 },
+		{ CKA_WRAP_TEMPLATE, NULL, 0 }
+	};
+	static const bool_attr certBools[] = {
+		/* Stored-object specific */
+		{ CKA_MODIFIABLE, 0 },
+		{ CKA_TOKEN, 1 },
+		{ CKA_PRIVATE, 0 },
+		{ CKA_TRUSTED, 0 }, /* Not a root */
+	};
+	static const long_attr certLongs[] = {
+		{ CKA_CERTIFICATE_TYPE, CKC_X_509 },
+		{ CKA_CERTIFICATE_CATEGORY, 1 }, // Token user cert
+		{ CKA_JAVA_MIDP_SECURITY_DOMAIN, 0 } // Unspecified
+	};
+	static const raw_attr certRaws[] = {
+		{ CKA_APPLICATION, NULL, 0 },
+		{ CKA_OBJECT_ID, NULL, 0 },
+		{ CKA_URL, NULL, 0 },
+		{ CKA_HASH_OF_ISSUER_PUBLIC_KEY, NULL, 0 },
+		{ CKA_HASH_OF_SUBJECT_PUBLIC_KEY, NULL, 0 },
+		{ CKA_START_DATE, NULL, 0 },
+		{ CKA_END_DATE, NULL, 0 }
+	};
+	
+	/* FOR EACH KEYPAIR */
+	/* CKA_ID - all == generate based on identity value
+	 * CKA_LABEL - all
+	 */
+	P11Attributes keyAttributes;
+	P11Attributes pubKeyAttributes;
+	P11Attributes certAttributes;
+	SET_LONG_ATTRIBUTES(keyAttributes, keyLongs);
+	SET_LONG_ATTRIBUTES(pubKeyAttributes, pubKeyLongs);
+	SET_LONG_ATTRIBUTES(certAttributes, certLongs);
+	SET_BOOL_ATTRIBUTES(keyAttributes, keyBools);
+	SET_BOOL_ATTRIBUTES(pubKeyAttributes, pubKeyBools);
+	SET_BOOL_ATTRIBUTES(certAttributes, certBools);
+	SET_RAW_ATTRIBUTES(keyAttributes, keyRaws);
+	SET_RAW_ATTRIBUTES(pubKeyAttributes, pubKeyRaws);
+	SET_RAW_ATTRIBUTES(certAttributes, certRaws);
+
+	certAttributes.addByte(CKA_ID, getHandle());
+	keyAttributes.addByte(CKA_ID, getHandle());
+	pubKeyAttributes.addByte(CKA_ID, getHandle());
+	/* GET CERTIFICATE DATA */
+	try {
+		getCertData(identity, certAttributes, pubKeyAttributes, keyAttributes);
+	} catch(P11Exception &e) {
+		throw e;
+	}
+	/* END GET CERT DATA */
+	try {
+		getKeyData(identity, keyAttributes);
+	} catch(P11Exception &e) {
+		throw e;
+	} catch(SKIPKEY &e) {
+		return false;
+	}
+
+	P11Objects::addNew(objects, CKO_PUBLIC_KEY, pubKeyAttributes)->setIdentity(identity_reference);
+	P11Objects::addNew(objects, CKO_PRIVATE_KEY, keyAttributes)  ->setIdentity(identity_reference);
+	P11Objects::addNew(objects, CKO_CERTIFICATE, certAttributes) ->setIdentity(identity_reference);
+	return true;
+}
+
+P11Identities::P11Identities() : identities() {
+}
+
+void P11Identities::createIdentity(P11Objects_Ref objects, SecIdentityRef identity) {
+	P11Identity_Ref new_identity(new P11Identity(identity));
+	IdentityManager::iterator iter = identities.add(new_identity, FilterKeepValid<P11Identity_Ref>());
+	if(!new_identity->createObjects(objects, new_identity))
+		identities.erase(iter);
+}

Added: trunk/TokendPKCS11/src/P11Mutexes.cpp
===================================================================
--- trunk/TokendPKCS11/src/P11Mutexes.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/P11Mutexes.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,122 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11Mutexes.h"
+#include <pthread.h>
+
+class SystemWriteMutex : public UserMutex {
+	NOCOPY(SystemWriteMutex);
+public:
+	SystemWriteMutex(pthread_rwlock_t &rwlock) : rwlock(rwlock) {
+	}
+	virtual ~SystemWriteMutex() {}
+	void lock() {
+		if(0 != pthread_rwlock_wrlock(&rwlock))
+			throw P11Exception(CKR_GENERAL_ERROR);
+	}
+	void unlock() {
+		if(0 != pthread_rwlock_unlock(&rwlock))
+			throw P11Exception(CKR_GENERAL_ERROR);
+	}
+	UserMutex &writeMutex() { return *this; }
+private:
+	pthread_rwlock_t &rwlock;
+};
+
+class SystemMutex : public UserMutex {
+	NOCOPY(SystemMutex);
+public:
+	SystemMutex() : rwlock(), writeLock(rwlock) {
+		pthread_rwlock_init(&rwlock, NULL);
+	}
+	virtual ~SystemMutex() {
+		pthread_rwlock_destroy(&rwlock);
+	}
+	void lock() {
+		if(0 != pthread_rwlock_rdlock(&rwlock))
+			throw P11Exception(CKR_GENERAL_ERROR);
+	}
+	void unlock() {
+		if(0 != pthread_rwlock_unlock(&rwlock))
+			throw P11Exception(CKR_GENERAL_ERROR);
+	}
+	UserMutex &writeMutex() {
+		return writeLock;
+	}
+private:
+	pthread_rwlock_t rwlock;
+	SystemWriteMutex writeLock;
+};
+
+class NullMutex : public UserMutex {
+	NOCOPY(NullMutex);
+public:
+	NullMutex() {}
+	void lock() {
+	}
+	void unlock() {
+	}
+	UserMutex &writeMutex() {
+		return *this;
+	}
+};
+
+class AppMutex : public UserMutex {
+	NOCOPY(AppMutex);
+public:
+	AppMutex(const struct ck_c_initialize_args &init_args)
+	: init_args(init_args), mutex(NULL) {
+		checkResult(init_args.create_mutex(&mutex));
+	}
+	virtual ~AppMutex() {
+		init_args.destroy_mutex(mutex);
+	}
+	void lock() {
+		checkResult(init_args.lock_mutex(mutex));
+	}
+	void unlock() {
+		checkResult(init_args.unlock_mutex(mutex));
+	}
+	UserMutex &writeMutex() {
+		return *this;
+	}
+private:
+	const struct ck_c_initialize_args &init_args;
+	void *mutex;
+	static void checkResult(ck_rv_t ret) {
+		if(CKR_OK != ret)
+			throw P11Exception(ret);
+	}
+};
+
+UserMutex *SystemMutexFactory::create() {
+	return new SystemMutex();
+}
+
+UserMutex *NullMutexFactory::create() {
+	return new NullMutex();
+}
+
+UserMutex *AppMutexFactory::create() {
+	return new AppMutex(*(struct ck_c_initialize_args*)init_args);
+}

Added: trunk/TokendPKCS11/src/P11Object.cpp
===================================================================
--- trunk/TokendPKCS11/src/P11Object.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/P11Object.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11Object.h"
+//#include "P11Slot.h"
+#include "P11State.h"
+
+P11Object::P11Object(P11Objects_WeakRef parent, ck_object_class_t objectClass, const P11Attributes &attributes)
+:LockableHandledObject<P11Object>(globalState().newMutex()),
+	attributes(new P11Attributes(attributes)), parent(parent) {
+	this->attributes->addLong(CKA_CLASS, objectClass);
+}
+P11Object::~P11Object() {
+}
+
+ck_object_class_t P11Object::oclass() const {
+	return getAttributes().oclass();
+}
+
+const P11Attributes &P11Object::getAttributes() const {
+	/* Prepare attributes if not setup yet */
+	return *attributes;
+}
+
+P11Objects::P11Objects(int handle_base /* = 0 */)
+:objects(handle_base), read_only(false), read_only_error(CKR_OK), lock(globalState().newMutex()) {
+}
+
+P11Objects::P11Objects(bool read_only, ck_rv_t read_only_error, int handle_base /* = 0 */)
+:objects(handle_base), read_only(read_only), read_only_error(read_only_error), lock(globalState().newMutex()) {
+}
+
+P11Object_Ref P11Objects::addNew(P11Objects_Ref container, ck_object_class_t objectClass, const P11Attributes &attributes) {
+	P11Object_Ref ref = P11ObjectCreator::create(container, objectClass, attributes);
+	container->objects.add(ref, FilterKeepValid<P11Object_Ref>());
+	return ref;
+}
+
+P11Object_Ref P11Objects::handleToValue(ck_object_handle_t handle) const {
+	ObjectManager::const_iterator iter = objects.find(handle);
+	if(iter == objects.end() || !iter->get())
+		throw P11Exception(CKR_OBJECT_HANDLE_INVALID);
+	return *iter;
+}
+
+bool P11Objects::destroyObject(ck_object_handle_t handle) {
+	if(read_only)
+		throw P11Exception(read_only_error);
+	ObjectManager::iterator iter = objects.find(handle);
+	if(iter != objects.end() && (*iter)->isValid()) {
+		objects.kill_lockable_value(iter);
+		return true;
+	}
+	return false;
+}
+
+/* Protected attribute types
+ CKO_MECHANISM
+ CKO_HW_FEATURE
+ */
+
+class P11AttributeLoader {
+public:
+	P11AttributeLoader(const P11Attributes &search, P11ObjectHandleList &output) : search(search), output(output) {
+		returnRestrictedObject = search.oclass() == CKO_MECHANISM || search.oclass() == CKO_HW_FEATURE;
+	}
+	void operator () (const P11Object_Ref &ref) {
+		/* Double check that the object exists in the case of a deleted one */
+		if(!ref.get() || !ref->isValid()) return;
+		/* Check that the object's attributes match the search pattern */
+		if(!ref->getAttributes().match(search)) return;
+
+		/* Gotcha in the spec, if CKA_CLASS does not contain CKO_MECHANISM or CKO_HW_FEATURE
+		 * explicitly do not include CKO_MECHANISM or CKO_HW_FEATURE objects
+		 */
+		if(!returnRestrictedObject && (ref->oclass() == CKO_MECHANISM || ref->oclass() == CKO_HW_FEATURE))
+			return;
+		output.push_back(ref->getHandle());
+	}
+private:
+	const P11Attributes &search;
+	P11ObjectHandleList &output;
+	bool returnRestrictedObject;
+};
+
+void P11Objects::search(const P11Attributes &search, P11ObjectHandleList &output) {
+	for_each(objects.begin(), objects.end(), P11AttributeLoader(search, output));
+}
+
+/* Since Objects can be in two places, a utility function to get ahold of a locked version exists.. */
+LockedObject *LockedObject::get_locked_object(const LockedSession &session, ck_object_handle_t handle, bool readWrite /* = false */) {
+	P11Session_Ref sessionRef = session.get();
+	auto_ptr<LockedObject> obj;
+	try {
+		obj.reset(new LockedObject(sessionRef->getObjects(), handle));
+	} catch(P11Exception &e) {
+		if(e.ret != CKR_OBJECT_HANDLE_INVALID)
+			throw e;
+	}
+	if(!obj.get()) {
+		/* Lock the slot and get the object */
+		LockedSlot lockedSlot(sessionRef->getSlotID(), false);
+		obj.reset(new LockedObject(lockedSlot.get()->getObjects(), handle));
+	}
+	if(!obj.get())
+		throw P11Exception(CKR_OBJECT_HANDLE_INVALID);
+	return obj.release();
+}

Added: trunk/TokendPKCS11/src/P11Session.cpp
===================================================================
--- trunk/TokendPKCS11/src/P11Session.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/P11Session.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,107 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11State.h"
+#include "P11Session.h"
+#include "P11Slot.h"
+
+/* Must offset due to shared namespace */
+#define SESSION_OBJECT_BASE 0x08000000
+
+P11Session::P11Session(const LockedSlot &slot, ck_flags_t flags, ck_notify_t notify, void *app_data)
+:LockableHandledObject<P11Session>(globalState().newMutex()),
+	decryptState(), signState(), activeSearch(),
+	mFlags(flags), slotID(slot.get()->getSlotID()), objects(new P11Objects(SESSION_OBJECT_BASE)),
+	notifyCallback(notify), applicationData(app_data) {
+}
+
+P11Session::~P11Session() {
+}
+
+void P11Session::information(struct ck_session_info &info, const LockedSlot &lockedSlot) {
+	memset(&info, 0, sizeof(info));
+	info.device_error = 0;
+	info.slot_id = slotID;
+	info.flags = CKF_SERIAL_SESSION; /* backwards compatibility requires */
+	info.state = lockedSlot.get()->isLoggedIn() ? CKS_RO_USER_FUNCTIONS : CKS_RO_PUBLIC_SESSION;
+}
+
+void P11Session::initializeSearch() {
+	activeSearch.reset(new P11ObjectHandleList);
+}
+
+void P11Session::lock_and_load_search(P11Objects &objects, const P11Attributes &search) {
+	StLock<UserMutex> lockedObjects(objects.getLock()); /* VALIDATED */
+	/* Load session-local objects */
+	objects.search(search, *activeSearch);
+}
+
+P11Sessions::P11Sessions()
+:sessions(), slotsToSessions(), lock(globalState().newMutex()) {
+}
+
+P11Sessions::~P11Sessions() {
+}
+
+void P11Sessions::create(const LockedSlot &slot, ck_flags_t flags, ck_notify_t notify, void *app_data, ck_session_handle_t &session) {
+	P11Session_Ref newSession(P11SessionCreator::create(slot, flags, notify, app_data));
+	sessions.add(newSession, FilterKeepValid<P11Session_Ref>());
+	slotsToSessions.insert(P11SlotSessionMap::value_type(slot.get()->getSlotID(), newSession));
+	session = newSession->getHandle();
+}
+
+P11Session_Ref P11Sessions::handleToValue(ck_session_handle_t handle) const {
+	SessionManager::const_iterator iter = sessions.find(handle);
+	if(iter == sessions.end() || !(*iter).get()) // Invalid or dead session
+		throw P11Exception(CKR_SESSION_HANDLE_INVALID);
+	return *iter;
+}
+
+void P11Sessions::close(ck_session_handle_t handle) {
+	SessionManager::iterator iter = sessions.find(handle);
+	if(iter == sessions.end() || !(*iter).get()) // Invalid or dead session
+		throw P11Exception(CKR_SESSION_HANDLE_INVALID);
+	sessions.kill_lockable_value(iter);
+}
+
+void P11Sessions::closeAll(ck_slot_id_t slot) {
+	std::pair<P11SlotSessionMap::iterator,P11SlotSessionMap::iterator> slots = slotsToSessions.equal_range(slot);
+	std::vector<P11Session_WeakRef> sessionsToDestroy;
+	for(P11SlotSessionMap::iterator iter = slots.first; iter != slots.second; ++iter) {
+		sessionsToDestroy.push_back(iter->second);
+	}
+	/* Kill the sessions from the mapping location */
+	slotsToSessions.erase(slots.first, slots.second);
+	/* Remove what should be the last reference to the sessions, after obtaining a lock for safety */
+	for(int i = 0, len = sessionsToDestroy.size(); i < len; i++) {
+		P11Session_Ref session = sessionsToDestroy[i].lock();
+		if(!session.get()) continue;
+		sessions.kill_lockable_value(sessions.find(session->getHandle()));
+	}
+	/* Until the max idle, trim off any dead sessions */
+	sessions.remove_after_last_match(0, FilterKeepValid<P11Session_Ref>());
+}
+
+const P11Sessions &P11Sessions::getContainer() {
+	return globalState().getSessions();
+}

Added: trunk/TokendPKCS11/src/P11Slot.cpp
===================================================================
--- trunk/TokendPKCS11/src/P11Slot.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/P11Slot.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,186 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11State.h"
+#include "P11Slot.h"
+#include "CFUtilities.h"
+#include <Security/Security.h>
+
+#include "config.h"
+
+P11Mechanism::P11Mechanism(const struct ck_mechanism &mech, const struct ck_mechanism_info &info)
+: mechanismType(mech.mechanism), parameter(0), info(info) {
+	if(mech.parameter_len > 0)
+		parameter.assign((byte*)mech.parameter, (byte*)mech.parameter + mech.parameter_len);
+}
+
+P11Slot::P11Slot()
+:LockableHandledObject<P11Slot>(globalState().newMutex()),
+	keychain(NULL), objects(new P11Objects(true, CKR_TOKEN_WRITE_PROTECTED)),
+	identityValues(), mechanisms() {
+}
+
+P11Slot::P11Slot(SecKeychainRef keychain)
+:LockableHandledObject<P11Slot>(globalState().newMutex()),
+	keychain(keychain), objects(new P11Objects(true, CKR_TOKEN_WRITE_PROTECTED)),
+	identityValues(), mechanisms() {
+	CFRetain(keychain);
+
+	/* Add mechanism objects */
+	loadMechanisms();
+	loadKeypairs();
+}
+
+void P11Slot::getInformation(struct ck_slot_info &info) {
+	memset(&info, 0, sizeof(info));
+	pad_string_set(info.slot_description, PKCS11_SLOT_DESCRIPTION, sizeof(info.slot_description));
+	pad_string_set(info.manufacturer_id, PKCS11_MANUFACTURER, sizeof(info.manufacturer_id));
+	info.flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
+	if(isPresent()) {
+		info.flags |= CKF_TOKEN_PRESENT;
+	}
+}
+
+void P11Slot::getTokenInformation(struct ck_token_info &info, int active_count) {
+	assertPresent();
+	memset(&info, 0, sizeof(info));
+	char pathName[PATH_MAX];
+	UInt32 ioPathLength = sizeof(pathName) - 1;
+	if (noErr != SecKeychainGetPath(keychain, &ioPathLength, pathName))
+		pad_string_set(info.label, "unknown", sizeof(info.label));// XXX
+	else {
+		pathName[ioPathLength] = 0;
+		pad_string_set(info.label, pathName, sizeof(info.label));
+	}
+	pad_string_set(info.manufacturer_id, "unknown", sizeof(info.manufacturer_id));
+	pad_string_set(info.model, "unknown", sizeof(info.model));
+	pad_string_set(info.serial_number, "0", sizeof(info.serial_number));
+
+	info.flags =
+		CKF_WRITE_PROTECTED /* No personalization, so no write ops can be permitted */
+		| CKF_TOKEN_INITIALIZED; /* No personalization permitted, assume token initialized */
+#ifdef USE_PROTECTED_PATH
+	info.flags |= CKF_PROTECTED_AUTHENTICATION_PATH; /* To allow for keychain prompts rather than require UI from PKCS11 app */
+#endif
+#if defined(USE_PROTECTED_PATH) || defined(USE_PIN_AUTH)
+		/* Tokend will perform it's own auth... this is to help protect against problems such as
+		 * Firefox 3's CKF_PROTECTED_AUTHENTICATION_PATH problem while
+		 * providing the best usability... note that
+		 * all pkcs11 clients must have console access for this to work... */
+	info.flags |= CKF_USER_PIN_INITIALIZED | CKF_LOGIN_REQUIRED; /* Login is required for certain ops (crypto) .... */
+#endif
+	info.max_session_count = CK_EFFECTIVELY_INFINITE;
+	info.max_rw_session_count = 0;
+	info.rw_session_count = 0;
+	info.total_public_memory = CK_UNAVAILABLE_INFORMATION;
+	info.total_private_memory = CK_UNAVAILABLE_INFORMATION;
+	info.free_public_memory = CK_UNAVAILABLE_INFORMATION;
+	info.free_private_memory = CK_UNAVAILABLE_INFORMATION;
+
+	info.session_count = active_count;
+}
+
+P11Mechanism_Ref P11Slot::getMechanism(ck_mechanism_type_t mech) {
+	P11MechanismMap::const_iterator iter = mechanisms.find(mech);
+	if(iter == mechanisms.end())
+		throw P11Exception(CKR_MECHANISM_INVALID);
+	return iter->second;
+}
+
+ck_rv_t P11Slot::login(ck_user_type_t user_type, const byte *pin, ulong pin_len) {
+	assertPresent();
+	/* To handle keychain auth using popup, no pin passed */
+	OSStatus status = SecKeychainUnlock(keychain, pin_len, pin, pin != NULL); /* Use password options? */
+	switch(status) {
+	case noErr:
+		return CKR_OK;
+	default:
+		return CKR_PIN_INCORRECT;
+	}
+}
+
+ck_rv_t P11Slot::logout() {
+	assertPresent();
+	SecKeychainLock(keychain);
+	return CKR_OK;
+}
+
+bool P11Slot::isLoggedIn() const {
+	assertPresent();
+#ifdef USE_ALWAYS_AUTH_SESSION
+	return true;
+#else
+	SecKeychainStatus status;
+	OSStatus ret = SecKeychainGetStatus(keychain, &status);
+	return ret == noErr && status & kSecUnlockStateStatus;
+#endif
+}
+
+void P11Slot::assertPresent() const {
+	if(!isPresent())
+		throw P11Exception(CKR_TOKEN_NOT_PRESENT);
+}
+
+bool P11Slot::isPresent() const {
+	/* Useful for tracking down a slot removed during usage */
+	if(!keychain.get())
+		return false;
+	SecKeychainStatus status;
+	OSStatus ret = SecKeychainGetStatus(keychain, &status);
+	/* Should we return ok if no error? */
+	return ret == noErr;
+}
+
+void P11Slot::loadMechanisms() {
+	ck_mechanism_type_t mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };
+	struct ck_mechanism mechData = { 0, NULL, 0 };
+	/* Same support for each */
+	struct ck_mechanism_info mechInfo = {
+		1024,
+		4096, /* Current max == 4096 .... */
+		CKF_HW | CKF_DECRYPT | CKF_SIGN /* | CKF_UNWRAP */
+	};
+	int idx;
+	for(idx = 0; idx < sizeof(mechs) / sizeof(mechs[0]); idx++) {
+		mechData.mechanism = mechs[idx];
+		P11Mechanism_Ref mech(new P11Mechanism(mechData, mechInfo));
+		mechanisms.insert(P11MechanismMap::value_type(mechData.mechanism, mech));
+	}
+	/* Add objects */
+	P11Attributes mechAttributes;
+	mechAttributes.add(CKA_MECHANISM_TYPE, mechs, sizeof(mechs));
+	P11Objects::addNew(objects, CKO_MECHANISM, mechAttributes);
+}
+
+void P11Slot::loadKeypairs() {
+	ScopedCF<SecIdentitySearchRef> searchRef;
+	OSStatus status = SecIdentitySearchCreate(keychain, NULL, &searchRef);
+	if(status != noErr)
+		throw P11Exception(CKR_GENERAL_ERROR);
+	while(true) {
+		SecIdentityRef itemRef = NULL;
+		status = SecIdentitySearchCopyNext(searchRef, &itemRef);
+		if(status || !itemRef) break;
+		identityValues.createIdentity(objects, itemRef);
+	}
+}

Added: trunk/TokendPKCS11/src/P11Slots.cpp
===================================================================
--- trunk/TokendPKCS11/src/P11Slots.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/P11Slots.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,160 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11Slots.h"
+
+#include "P11State.h"
+#include "IteratorUtilities.h"
+#include "CFUtilities.h"
+#include <Security/Security.h>
+#include "config.h"
+
+class FilterKeepOccupiedSlot : public Filter<P11Slot_Ref> {
+public:
+	inline bool operator() (const P11Slot_Ref &slot) const {
+		return slot.get() && slot->isPresent();
+	}
+};
+
+class FilterKeepUsedSlot : public Filter<P11Slot_Ref> {
+public:
+	inline bool operator() (const P11Slot_Ref &slot) const {
+		return slot.get() && (!slot.unique() || slot->isPresent());
+	}
+};
+
+class GetSlotID {
+public:
+	ck_slot_id_t operator() (const P11Slot_Ref &slot) {
+		return slot.get() ? slot->getSlotID() : (ck_slot_id_t)-1;
+	}
+};
+
+class ApplySlotChanges {
+public:
+	ApplySlotChanges(P11Slots &slots) : slots(slots) {
+	}
+	void operator() (const P11Slots::KeychainToSlotMap::value_type &value) {
+		if(value.second != INVALID_HANDLE_VALUE) { /* Slot exists and must be deleted */
+			P11Slots::SlotHandleManager::iterator iter = slots.slots.find(value.second);
+			if(iter != slots.slots.end()) {
+				/* Kill all sessions w/ this slot */
+				{
+					/* RW Lock - state alteration */
+					P11Sessions &sessions = globalState().getSessions();
+					StLock<UserMutex> sessionsLock(sessions.getLock().writeMutex()); /* VALIDATED */
+					sessions.closeAll(iter->get()->getHandle());
+				}
+				slots.slots.kill_lockable_value(iter);
+				/* Fill in the slot w/ dummy data */
+				slots.slots.replace_value(iter, P11SlotCreator::DummySlot());
+			}
+			slots.keychainToSlot.erase(value.first);
+		} else { /* New slot and must be instantiated */
+			P11Slot_Ref ref = slots.loadEmptySlot(value.first);
+			P11Slots::KeychainToSlotMap::value_type new_value(value.first,ref->getSlotID());
+			slots.keychainToSlot.insert(new_value);
+		}
+	}
+private:
+	P11Slots &slots;
+};
+
+P11Slots::P11Slots() : slots(), keychainToSlot(), lock(globalState().newMutex()) {
+	/* Create 'empty' slots until the minimum, ignoring slot emptiness */
+	for(int i = 0; i < MIN_SLOTS; i++) {
+		slots.add(P11SlotCreator::DummySlot(), FilterKeepAll<P11Slot_Ref>());
+	}
+}
+
+ck_rv_t P11Slots::list(ck_slot_id_t *slotList, ulong &slotCount, bool presentOnly) {
+	refresh();
+	/* ck_slot_id is an unsigned long, assumes unsigned longs are sizeof ptr */
+	std::vector<ck_slot_id_t> slotsToReturn;
+	if(presentOnly)
+		slots.copy_handles(back_insert_iterator<std::vector<ck_slot_id_t> >(slotsToReturn), FilterKeepOccupiedSlot());
+	else
+		slots.copy_handles(back_insert_iterator<std::vector<ck_slot_id_t> >(slotsToReturn), FilterKeepValid<P11Slot_Ref>());
+	return copy_list(slotList, slotsToReturn, slotCount);
+}
+P11Slot_Ref P11Slots::handleToValue(ck_slot_id_t slotID) const {
+	SlotHandleManager::const_iterator iter = slots.find(slotID);
+	if(iter == slots.end())
+		throw P11Exception(CKR_SLOT_ID_INVALID);
+	return *iter;
+}
+
+const P11Slots &P11Slots::getContainer() {
+	return globalState().getSlots();
+}
+
+static void LoadIntoMap(const void *value, void *context) {
+	SecKeychainRef keychainRef = (SecKeychainRef)value;
+	P11Slots::KeychainToSlotMap &set = *(P11Slots::KeychainToSlotMap*)context;
+	set.insert(P11Slots::KeychainToSlotMap::value_type(keychainRef, INVALID_HANDLE_VALUE));
+}
+
+P11Slot_Ref P11Slots::loadEmptySlot(SecKeychainRef keychain) {
+	return *slots.add(P11SlotCreator::ActiveSlot(keychain), FilterKeepOccupiedSlot());
+}
+
+/* T EXPECTED TO BE OF PAIR TYPE */
+template<typename T>
+bool KeyComparer(const T &first, const T &second) {
+	return (intptr_t)(void*)first.first < (intptr_t)(void*)second.first;
+}
+
+void P11Slots::refresh() {
+	// if we want to support soft tokens, must iterate over domains; see cacheKeychainLists
+	OSStatus status = noErr;
+	CFArrayRef searchList = NULL;
+	
+	status = SecKeychainCopyDomainSearchList(kSecPreferencesDomainDynamic, &searchList);
+	if (status) {
+		//??
+		keychainToSlot.clear();
+		return;
+	}
+	
+	uint32_t count = searchList ? CFArrayGetCount(searchList) : 0;
+	
+	// Create new slots if not in list already
+	KeychainToSlotMap activeKeychains;
+	CFRange range = CFRangeMake(0, count);
+	CFArrayApplyFunction(searchList, range, LoadIntoMap, &activeKeychains);
+	
+	/* Couldn't used existing typedef in the map due to const issues */
+	typedef vector<std::pair<SecKeychainRef,ck_slot_id_t> > P11SlotMapIterList;
+	P11SlotMapIterList slotDifference;
+	set_symmetric_difference(keychainToSlot.begin(), keychainToSlot.end(), activeKeychains.begin(), activeKeychains.end(), back_insert_iterator<P11SlotMapIterList>(slotDifference), KeyComparer<KeychainToSlotMap::value_type>);
+	
+	/* Any slots in the difference list require an update of some kind
+	 * If the slot iter contains an active slot, then it must be deleted
+	 * else the slot is from the 'fresh' list and must be created */
+	for_each(slotDifference.begin(), slotDifference.end(), ApplySlotChanges(*this));
+	
+	/* Until the max idle, trim off any dead slots */
+	slots.remove_after_last_match(MAX_IDLE_SLOTS, FilterKeepUsedSlot());
+	if (searchList)
+		CFRelease(searchList);
+}

Added: trunk/TokendPKCS11/src/P11State.cpp
===================================================================
--- trunk/TokendPKCS11/src/P11State.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/P11State.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,110 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11State.h"
+#include "P11Mutexes.h"
+
+ModuleNexus<P11State> globalState;
+
+P11State::P11State()
+:slots(), sessions(), mutex(), mutexFactory(), isInitialized(false), current_args() {
+}
+
+void P11State::assertInitialized() {
+	if(!isInitialized)
+		throw P11Exception(CKR_CRYPTOKI_NOT_INITIALIZED);
+}
+
+ck_rv_t P11State::initialize(const struct ck_c_initialize_args *init_args) {
+	if (isInitialized)
+		return CKR_CRYPTOKI_ALREADY_INITIALIZED;
+	if (init_args->reserved)
+		return CKR_ARGUMENTS_BAD;
+	current_args = *init_args;
+	/* OS locking preferred */
+	if(current_args.flags & CKF_OS_LOCKING_OK) {
+		mutexFactory.reset(new SystemMutexFactory());
+	} else if (current_args.create_mutex && current_args.destroy_mutex && current_args.lock_mutex && current_args.unlock_mutex) {
+		mutexFactory.reset(new AppMutexFactory(&current_args));
+	} else {
+		mutexFactory.reset(new NullMutexFactory());
+	}
+	mutex.reset(mutexFactory->create());
+	/* Hook up globals */
+	slots.reset(P11SlotsCreator::create());
+	sessions.reset(P11SessionsCreator::create());
+	isInitialized = true;
+	return CKR_OK;
+}
+
+ck_rv_t P11State::finalize() {
+	GlobalLockCheck globalLock;
+	isInitialized = false;
+	memset(&current_args, 0, sizeof(current_args));
+	mutexFactory.reset();
+	/* Swap out mutex to release after unlocking */
+	auto_ptr<UserMutex> preserved(mutex);
+	globalLock.lock->unlock();
+	return CKR_OK;
+}
+
+void AssertGlobalInitialized() {
+	globalState().assertInitialized();
+}
+
+GlobalLockCheck::GlobalLockCheck(bool readWrite) : lock() {
+	globalState().assertInitialized();
+	/* Warning, weak uninitialization safety... */
+	lock.reset(new StLock<UserMutex>(globalState().getLock())); /* VALIDATED */
+	globalState().assertInitialized();
+}
+
+ck_rv_t processSlotError(const P11Exception &e, ck_slot_id_t slot) {
+	ck_rv_t rv = e.ret;
+	if(rv != CKR_TOKEN_NOT_PRESENT)
+		return rv;
+	/* Kill all associated sessions */
+	C_CloseAllSessions(slot);
+	return rv;
+}
+
+ck_rv_t processSessionReturn(ck_rv_t rv, ck_session_handle_t session) {
+	if(rv != CKR_TOKEN_NOT_PRESENT)
+		return rv;
+	rv = CKR_SESSION_HANDLE_INVALID;
+	ck_slot_id_t slot;
+	/* Get slot */
+	{
+		GlobalLockCheck globalLock;
+		/* R Lock: Getting attributes performs no alterations */
+		LockedSession lockedSession(session);
+		slot = lockedSession.get()->getSlotID();
+	}
+	/* Kill all associated sessions */
+	C_CloseAllSessions(slot);
+	return rv;
+}
+
+ck_rv_t processSessionError(const P11Exception &e, ck_session_handle_t session) {
+	return processSessionReturn(e.ret, session);
+}

Added: trunk/TokendPKCS11/src/TLV.cpp
===================================================================
--- trunk/TokendPKCS11/src/TLV.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/TLV.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,183 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "TLV.h"
+
+#include <limits>
+
+using namespace std;
+
+TLV::TLV() throw()
+:tag(), value(NULL), innerValues(NULL) {
+}
+
+TLV::TLV(unsigned char tag) throw()
+:tag(1, tag), value(NULL), innerValues(NULL) {
+}
+
+TLV::TLV(const byte_string& tag) throw()
+:tag(tag), value(NULL), innerValues(NULL) {
+}
+
+TLV::TLV(unsigned char tag, const byte_string& value) throw()
+:tag(1, tag), value(new byte_string(value)), innerValues(NULL) {
+}
+
+TLV::TLV(const byte_string& tag, const byte_string& value) throw()
+:tag(tag), value(new byte_string(value)), innerValues(NULL) {
+}
+
+TLV::TLV(uint8_t tag, const TLVList &tlv) throw()
+:tag(1, tag), value(NULL), innerValues(new TLVList(tlv)) {
+}
+
+TLV::TLV(const byte_string &tag, const TLVList &tlv) throw()
+:tag(tag), value(NULL), innerValues(new TLVList(tlv)) {
+}
+
+TLV_ref TLV::parse(const byte_string &in) throw(std::runtime_error) {
+	byte_string::const_iterator begin = in.begin();
+	return parse(begin, in.end());
+}
+
+byte_string TLV::encode() const throw() {
+	byte_string out;
+	encode(out);
+	return out;
+}
+
+void TLV::encode(byte_string &out) const throw() {
+	const byte_string &tag = getTag();
+	// Puts the tag
+	out += tag;
+	// Puts the length
+	encodeLength(valueLength(), out);
+
+#if 1
+	// Non-caching version since the TLV is expected to be
+	// thrown away after encoding
+	// If there is a value, put that
+	if(value.get()) {
+		out += *value;
+		return;
+	}
+	if(!innerValues.get())
+		return;
+	// Else if there are innerValues, encode those out
+	encodeSequence(*innerValues, out);
+#else
+	// Obtain the value in a cached manner
+	const byte_string &value = getValue();
+	out += value;
+#endif
+}
+
+const TLVList &TLV::getInnerValues() const throw(std::runtime_error) {
+	/* If there is a cached innervalues version, output it
+	 * else parse any existing TLV data and use that */
+	if(innerValues.get()) return *innerValues;
+	if(!value.get()) {
+		innerValues.reset(new TLVList());
+		return *innerValues;
+	}
+	innerValues.reset(new TLVList());
+	byte_string::const_iterator begin = value->begin();
+	parseSequence(begin, (byte_string::const_iterator)value->end(), *innerValues);
+
+	return *innerValues;
+}
+
+const byte_string &TLV::getValue() const throw() {
+	/* If there is a cached value version, output it
+	 * else encode any existing TLV data and use that */
+	if(value.get()) return *value;
+	if(!innerValues.get()) {
+		value.reset(new byte_string());
+		return *value;
+	}
+	value.reset(new byte_string());
+	encodeSequence(*innerValues, *value);
+	return *value;
+}
+
+size_t TLV::length() const throw() {
+	size_t innerLength = valueLength();
+	return tag.size() + encodedLength(innerLength) + innerLength;
+}
+
+void TLV::encodeLength(size_t value, byte_string &out) throw() {
+	/* Encode and output the length according to BER-TLV encoding rules */
+	static const size_t MAX_VALUE = std::numeric_limits<size_t>::max();
+	static const size_t highbyte = (MAX_VALUE ^ (MAX_VALUE >> 8));
+	static const size_t shiftbyte = (sizeof(size_t) - 1) * 8;
+	if (value < 0x80) {
+		out += (unsigned char)(value & 0x7F);
+		return;
+	}
+	size_t size = sizeof(value), i;
+	while(0 == (value & highbyte) && size > 0) {
+		value <<= 8;
+		size--;
+	}
+	out += (unsigned char)(0x80 | size);
+	for(i = 0; i < size; i++) {
+		out += (unsigned char)((value >> shiftbyte) & 0xFF);
+		value <<= 8;
+	}
+}
+
+size_t TLV::encodedLength(size_t value) throw() {
+	if(value < 0x80)
+		return 1;
+	/* Values larger than 0x7F must be encoded in the form (Length-Bytes) (Length) */
+	static const size_t MAX_VALUE = std::numeric_limits<size_t>::max();
+	/* EX: 0xFF000000 - for size_t == 32-bit */
+	static const size_t highbyte = (MAX_VALUE ^ (MAX_VALUE >> 8));
+	size_t size = sizeof(value);
+	/* Check for the highest byte that contains a value */
+	while(0 == (value & highbyte) && size > 0) {
+		value <<= 8;
+		size--;
+	}
+	/* + 1 for byte-size byte
+	 * Size encoded as (0x80 + N) [N-bytes]
+	 * Max size-bytes == 127
+	 */
+	return size + 1;
+}
+
+void TLV::encodeSequence(const TLVList &tlv, byte_string &out) throw() {
+	for(TLVList::const_iterator iter = tlv.begin(); iter < tlv.end(); iter++)
+		(*iter)->encode(out);
+}
+
+size_t TLV::valueLength() const throw() {
+	/* Calculate the length of a value, either by its actual value length
+	 * or calculated length based on contained TLV values */
+	if(value.get()) return value->size();
+	if(!innerValues.get()) return 0;
+	size_t retValue = 0;
+	for(TLVList::const_iterator iter = innerValues->begin(); iter < innerValues->end(); iter++)
+		retValue += (*iter)->length();
+	return retValue;
+}

Added: trunk/TokendPKCS11/src/TLV.inc
===================================================================
--- trunk/TokendPKCS11/src/TLV.inc	                        (rev 0)
+++ trunk/TokendPKCS11/src/TLV.inc	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,104 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+template<typename ForwardIterator>
+void TLV::parseSequence(ForwardIterator &iter, const ForwardIterator &end, TLVList &tlv) throw(std::runtime_error) {
+	/* While there is still data inbetween the iterators */
+	while(iter < end) {
+		/* parse TLV structures and append them to the list */
+		TLV_ref ref = TLV::parse(iter, end);
+		tlv.push_back(ref);
+	}
+}
+
+template<typename ForwardIterator>
+TLV_ref TLV::parse(ForwardIterator &iter, const ForwardIterator &end) throw(std::runtime_error) {
+	byte_string tag;
+	uint8_t ch;
+	if(iter >= end) throw std::runtime_error("Invalid TLV-encoding");
+	/* Read the first byte as the tag */
+	ch = *iter++;
+	tag += ch;
+	if(iter >= end) throw std::runtime_error("Invalid TLV-encoding");
+	/* If the tag is flagged as a multibyte tag */
+	if((ch & 0x1F) == 0x1F) { /* Multibyte tag */
+		do {
+			ch = *iter++;
+			tag += ch;
+			if(iter >= end) throw std::runtime_error("Invalid TLV-encoding");
+			/* Read more until there are no more bytes w/o the high-bit set */
+		} while((ch & 0x80) != 0);
+	}
+	/* Parse the length of the contained value */
+	size_t length = parseLength(iter, end);
+	ForwardIterator begin = iter;
+	iter += length;
+	/* The iterator is permitted to be at the very and at this point */
+	if(iter > end) throw std::runtime_error("Invalid TLV-encoding");
+	/* Return a new TLV with the calculated tag and value */
+	return TLV_ref(new TLV(tag, byte_string(begin, iter)));
+}
+
+/*
+	BER-TLV
+	Reference: http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816-4_annex-d.aspx
+
+	In short form, the length field consists of a single byte where the bit B8 shall be set to 0 and
+	the bits B7-B1 shall encode an integer equal to the number of bytes in the value field. Any length
+	from 0-127 can thus be encoded by 1 byte.
+
+	In long form, the length field consists of a leading byte where the bit B8 shall be set to 1 and
+	the B7-B1 shall not be all equal, thus encoding a positive integer equal to the number of subsequent
+	bytes in the length field. Those subsequent bytes shall encode an integer equal to the number of bytes
+	in the value field. Any length within the APDU limit (up to 65535) can thus be encoded by 3 bytes.
+
+	NOTE - ISO/IEC 7816 does not use the indefinite lengths specified by the basic encoding rules of
+	ASN.1 (see ISO/IEC 8825).
+
+	Sample data (from a certficate GET DATA):
+
+	00000000  53 82 04 84 70 82 04 78  78 da 33 68 62 db 61 d0
+	00000010  c4 ba 60 01 33 13 23 13  13 97 e2 dc 88 f7 0c 40
+	00000020  20 da 63 c0 cb c6 a9 d5  e6 d1 f6 9d 97 91 91 95
+	....
+	00000460  1f 22 27 83 ef fe ed 5e  7a f3 e8 b6 dc 6b 3f dc
+	00000470  4c be bc f5 bf f2 70 7e  6b d0 4c 00 80 0d 3f 1f
+	00000480  71 01 80 72 03 49 44 41
+
+*/
+template<typename ForwardIterator>
+size_t TLV::parseLength(ForwardIterator &iter, const ForwardIterator &end) throw(std::runtime_error) {
+	// Parse a BER length field. Returns the value of the length
+	uint8_t ch = *iter++;
+	if (!(ch & 0x80))	// single byte
+		return static_cast<uint32_t>(ch);
+	size_t result = 0;
+	uint8_t byteLen = ch & 0x7F;
+	for(;byteLen > 0; byteLen--) {
+		if(iter == end)
+			throw std::runtime_error("Invalid BER-encoded length");
+		ch = *iter++;
+		result = (result << 8) | static_cast<uint8_t>(ch);
+	}
+	return result;
+}

Added: trunk/TokendPKCS11/src/Utilities.cpp
===================================================================
--- trunk/TokendPKCS11/src/Utilities.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/Utilities.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,46 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "Utilities.h"
+
+#include <string.h>
+
+/******************************************************************************
+ ** Function: strnlen
+ **
+ ** Limited length strlen function (normally included with GNU compiler)
+ *******************************************************************************/
+size_t strnlen(const char *__string, size_t __maxlen)
+{
+    size_t i;
+
+    for (i = 0; i < __maxlen; i++)
+        if (__string[i] == 0x00) break;
+
+    return i;
+}
+
+void pad_string_set(byte *to, const char *from, size_t size) {
+	memset(to, 0x20, size);
+	memcpy(to, from, strnlen(from, size));
+}

Added: trunk/TokendPKCS11/src/p11-global.cpp
===================================================================
--- trunk/TokendPKCS11/src/p11-global.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/p11-global.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,154 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+
+#include "Utilities.h"
+
+#include <assert.h>
+
+#include "P11State.h"
+
+#include "config.h"
+
+/* WARNING - not thread safe per spec */
+ck_rv_t C_Initialize(void *init_args) {
+	try {
+		struct ck_c_initialize_args blank_init_args;
+		if(!init_args) {
+			init_args = &blank_init_args;
+			memset(&blank_init_args, 0, sizeof(blank_init_args));
+		}
+
+		return globalState().initialize((struct ck_c_initialize_args*)init_args);
+	} catch(P11Exception &e) {
+		return e.ret;
+	}
+}
+
+/* WARNING - not completely thread safe per spec WRT duplicate calls */
+ck_rv_t C_Finalize(void *reserved) {
+	try {
+		return globalState().finalize();
+	} catch(P11Exception &e) {
+		return e.ret;
+	}
+}
+
+ck_rv_t C_GetInfo(struct ck_info *info) {
+	try {
+		memset(info, 0, sizeof(*info));
+
+		info->cryptoki_version.major = CRYPTOKI_VERSION_MAJOR;
+		info->cryptoki_version.minor = CRYPTOKI_VERSION_MINOR;
+		pad_string_set(info->manufacturer_id, PKCS11_MANUFACTURER, sizeof(info->manufacturer_id));
+		pad_string_set(info->library_description, PKCS11_DESCRIPTION, sizeof(info->library_description));
+		info->library_version.major = PKCS11_LIBRARY_MAJOR;
+		info->library_version.minor = PKCS11_LIBRARY_MINOR;
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return e.ret;
+	}
+}
+
+static struct ck_function_list pkcs11_functions = {
+	{ CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
+	C_Initialize,
+	C_Finalize,
+	C_GetInfo,
+	C_GetFunctionList,
+	C_GetSlotList,
+	C_GetSlotInfo,
+	C_GetTokenInfo,
+	C_GetMechanismList,
+	C_GetMechanismInfo,
+	C_InitToken,
+	C_InitPIN,
+	C_SetPIN,
+	C_OpenSession,
+	C_CloseSession,
+	C_CloseAllSessions,
+	C_GetSessionInfo,
+	C_GetOperationState,
+	C_SetOperationState,
+	C_Login,
+	C_Logout,
+	C_CreateObject,
+	C_CopyObject,
+	C_DestroyObject,
+	C_GetObjectSize,
+	C_GetAttributeValue,
+	C_SetAttributeValue,
+	C_FindObjectsInit,
+	C_FindObjects,
+	C_FindObjectsFinal,
+	C_EncryptInit,
+	C_Encrypt,
+	C_EncryptUpdate,
+	C_EncryptFinal,
+	C_DecryptInit,
+	C_Decrypt,
+	C_DecryptUpdate,
+	C_DecryptFinal,
+	C_DigestInit,
+	C_Digest,
+	C_DigestUpdate,
+	C_DigestKey,
+	C_DigestFinal,
+	C_SignInit,
+	C_Sign,
+	C_SignUpdate,
+	C_SignFinal,
+	C_SignRecoverInit,
+	C_SignRecover,
+	C_VerifyInit,
+	C_Verify,
+	C_VerifyUpdate,
+	C_VerifyFinal,
+	C_VerifyRecoverInit,
+	C_VerifyRecover,
+	C_DigestEncryptUpdate,
+	C_DecryptDigestUpdate,
+	C_SignEncryptUpdate,
+	C_DecryptVerifyUpdate,
+	C_GenerateKey,
+	C_GenerateKeyPair,
+	C_WrapKey,
+	C_UnwrapKey,
+	C_DeriveKey,
+	C_SeedRandom,
+	C_GenerateRandom,
+	C_GetFunctionStatus,
+	C_CancelFunction,
+	C_WaitForSlotEvent
+};
+
+ck_rv_t C_GetFunctionList(struct ck_function_list **function_list) {
+	try {
+		if(!function_list)
+			return CKR_ARGUMENTS_BAD;
+		*function_list = (struct ck_function_list*)&pkcs11_functions;
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return e.ret;
+	}
+}

Added: trunk/TokendPKCS11/src/p11-keyops.cpp
===================================================================
--- trunk/TokendPKCS11/src/p11-keyops.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/p11-keyops.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,173 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "Utilities.h"
+#include "P11State.h"
+
+using std::tr1::dynamic_pointer_cast;
+
+/* Supported algs
+ * CKM_RSA_PKCS   Sign/Decrypt
+ * CKM_RSA_X_X509 Sign/Decrypt
+ */
+
+ck_rv_t C_DecryptInit(ck_session_handle_t session, struct ck_mechanism *mech, ck_object_handle_t key) {
+	try {
+		GlobalLockCheck globalLock;
+		/* RW LOCK: Crypto ops alter the session */
+		LockedSession lockedSession(session, true);
+		P11Session_Ref sessionRef = lockedSession.get();
+		/* R LOCK: Nab the slot, crypto ops don't alter slot -- checks existence */
+		LockedSlot lockedSlot(sessionRef->getSlotID());
+		lockedSlot.get()->assertPresent();
+		if(sessionRef->decryptState.get())
+			throw P11Exception(CKR_OPERATION_ACTIVE);		
+		auto_ptr<LockedObject> obj(LockedObject::get_locked_object(lockedSession, key));
+		/* May throw if invalid mechanism/keyobject pair */
+		/* Release a reference into the cryptostate */
+		sessionRef->decryptState.reset(new P11CryptoState(obj->get(), *mech));
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_Decrypt(ck_session_handle_t session, byte *encrypted_data, ulong encrypted_data_len, byte *data, ulong *data_len) {
+	try {
+		GlobalLockCheck globalLock;
+		if(!encrypted_data || !encrypted_data_len || !data_len)
+			return CKR_ARGUMENTS_BAD;
+		/* RW LOCK: Crypto ops alter the session */
+		LockedSession lockedSession(session, true);
+		P11Session_Ref sessionRef = lockedSession.get();
+		/* R LOCK: Nab the slot, crypto ops don't alter slot -- checks existence */
+		LockedSlot lockedSlot(sessionRef->getSlotID());
+		lockedSlot.get()->assertPresent();
+		if(!sessionRef->decryptState.get())
+			return CKR_OPERATION_NOT_INITIALIZED;
+		ck_rv_t ret;
+		try {
+			ret = sessionRef->decryptState->decrypt(encrypted_data, encrypted_data_len, data, *data_len);
+		} catch(P11Exception &e) {
+			ret = e.ret;
+		}
+		/* size-obtaining funcs (CKR_OK and CKR_BUFFER_TOO_SMALL) do not kill the state */
+		if(!(CKR_OK == ret && !data || CKR_BUFFER_TOO_SMALL == ret))
+			sessionRef->decryptState.reset();
+		return processSessionReturn(ret, session);
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DecryptUpdate(ck_session_handle_t session, byte *encrypted_part, ulong encrypted_part_len, byte *part, ulong *part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DecryptFinal(ck_session_handle_t session, byte *last_part, ulong *last_part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_SignInit(ck_session_handle_t session, struct ck_mechanism *mech, ck_object_handle_t key) {
+	try {
+		GlobalLockCheck globalLock;
+		/* RW LOCK: Crypto ops alter the session */
+		LockedSession lockedSession(session, true);
+		P11Session_Ref sessionRef = lockedSession.get();
+		/* R LOCK: Nab the slot, crypto ops don't alter slot -- checks existence */
+		LockedSlot lockedSlot(sessionRef->getSlotID());
+		lockedSlot.get()->assertPresent();
+		if(sessionRef->signState.get())
+			throw P11Exception(CKR_OPERATION_ACTIVE);
+		auto_ptr<LockedObject> obj(LockedObject::get_locked_object(lockedSession, key));
+		sessionRef->signState.reset(new P11CryptoState(obj->get(), *mech));
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_Sign(ck_session_handle_t session, byte *data, ulong data_len, byte *signature, ulong *signature_len) {
+	try {
+		GlobalLockCheck globalLock;
+		if(!data || !data_len || !signature_len)
+			return CKR_ARGUMENTS_BAD;
+		/* RW LOCK: Crypto ops alter the session */
+		LockedSession lockedSession(session, true);
+		P11Session_Ref sessionRef = lockedSession.get();
+		/* R LOCK: Nab the slot, crypto ops don't alter slot -- checks existence */
+		LockedSlot lockedSlot(sessionRef->getSlotID());
+		lockedSlot.get()->assertPresent();
+		if(!sessionRef->signState.get())
+			return CKR_OPERATION_NOT_INITIALIZED;
+		ck_rv_t ret;
+		try {
+			ret = sessionRef->signState->sign(data, data_len, signature, *signature_len);
+		} catch(P11Exception &e) {
+			ret = e.ret;
+		}
+		/* size-obtaining funcs (CKR_OK and CKR_BUFFER_TOO_SMALL) do not kill the state */
+		if(!(CKR_OK == ret && !signature || CKR_BUFFER_TOO_SMALL == ret))
+			sessionRef->signState.reset();
+		return processSessionReturn(ret, session);
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_SignUpdate(ck_session_handle_t session, byte *part, ulong part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_SignFinal(ck_session_handle_t session, byte *signature, ulong *signature_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_UnwrapKey(ck_session_handle_t session, struct ck_mechanism *mech, ck_object_handle_t unwrapping_key, byte *wrapped_key, ulong wrapped_key_len, struct ck_attribute *templ, ulong attr_count, ck_object_handle_t *key) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}

Added: trunk/TokendPKCS11/src/p11-object.cpp
===================================================================
--- trunk/TokendPKCS11/src/p11-object.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/p11-object.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,142 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "Utilities.h"
+#include "P11State.h"
+
+ck_rv_t C_GetObjectSize(ck_session_handle_t session, ck_object_handle_t object, ulong *size) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_GetAttributeValue(ck_session_handle_t session, ck_object_handle_t object, struct ck_attribute *templ, ulong count) {
+	try {
+		GlobalLockCheck globalLock;
+		if(!templ)
+			return CKR_ARGUMENTS_BAD;
+		/* R Lock: Getting attributes performs no alterations */
+		LockedSession lockedSession(session);
+		/* Obtain the object (or throw bad object handle) and return attributes */
+		auto_ptr<LockedObject> obj(LockedObject::get_locked_object(lockedSession, object, false));
+		return obj->get()->getAttributes().get(templ, count);
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_FindObjectsInit(ck_session_handle_t session, struct ck_attribute *templ, ulong count) {
+	try {
+		GlobalLockCheck globalLock;
+		if(!templ && count != 0)
+			return CKR_ARGUMENTS_BAD;
+		/* RW Lock: Beginning a search initializes search variables in the session */
+		LockedSession lockedSession(session, true);
+		/* Construct the search */
+		P11Attributes search(templ, count);
+
+		P11Session_Ref sessionRef = lockedSession.get();
+		lockedSession.get()->initializeSearch();
+		/* Load up session objects */
+		sessionRef->lock_and_load_search(sessionRef->getObjects(), search);
+		/* Lock the slot and load it */
+		LockedSlot lockedSlot(sessionRef->getSlotID());
+		sessionRef->lock_and_load_search(lockedSlot.get()->getObjects(), search);
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_FindObjects(ck_session_handle_t session, ck_object_handle_t *object, ulong max_object_count, ulong *object_count) {
+	try {
+		GlobalLockCheck globalLock;
+		/* RW Lock: Pulling objects from the search alters the session */
+		LockedSession lockedSession(session, true);
+		P11Session_Ref sessionRef = lockedSession.get();
+		if(!sessionRef->activeSearch.get())
+			return CKR_OPERATION_NOT_INITIALIZED;
+		if(!object_count || !object)
+			return CKR_ARGUMENTS_BAD;
+		/* Pull out some of the values in the active search and return them */
+		*object_count = min(max_object_count, sessionRef->activeSearch->size());
+		P11ObjectHandleList::iterator begin = sessionRef->activeSearch->begin();
+		P11ObjectHandleList::iterator endOfCopy = begin + *object_count;
+		copy(begin, endOfCopy, object);
+		sessionRef->activeSearch->erase(begin, endOfCopy);
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_FindObjectsFinal(ck_session_handle_t session) {
+	try {
+		GlobalLockCheck globalLock;
+		/* RW Lock: Completion of search alters the session by removing the active search */
+		LockedSession lockedSession(session, true);
+		P11Session_Ref sessionRef = lockedSession.get();
+		if(!sessionRef->activeSearch.get())
+			return CKR_OPERATION_NOT_INITIALIZED;
+		sessionRef->activeSearch.reset(NULL);
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_CopyObject(ck_session_handle_t session, ck_object_handle_t object, struct ck_attribute *templ, ulong count, ck_object_handle_t *new_object) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DestroyObject(ck_session_handle_t session, ck_object_handle_t object) {
+	try {
+		GlobalLockCheck globalLock;
+		/* RW Lock: Deletion alters the session, object-container, and object */
+		/* NOTE: Slot objects are not deletable and will throw */
+		LockedSession lockedSession(session, true);
+		P11Session_Ref sessionRef = lockedSession.get();
+		P11Objects_Ref objectContainer;
+		{
+			/* Located the object and find its parent */
+			auto_ptr<LockedObject> obj(LockedObject::get_locked_object(lockedSession, object, false));
+			objectContainer = obj->get()->getParent().lock();
+		}
+		/* Container is gone... forget about it */
+		if(!objectContainer.get())
+			return CKR_OK;
+		StLock<UserMutex> containerLock(objectContainer->getLock().writeMutex()); /* VALIDATED */
+		objectContainer->destroyObject(object);
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}

Added: trunk/TokendPKCS11/src/p11-othercrypt.cpp
===================================================================
--- trunk/TokendPKCS11/src/p11-othercrypt.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/p11-othercrypt.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "Utilities.h"
+#include "P11State.h"
+
+ck_rv_t C_SignRecoverInit(ck_session_handle_t session, struct ck_mechanism *mech, ck_object_handle_t key) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_SignRecover(ck_session_handle_t session, byte *data, ulong data_len, byte *signature, ulong *signature_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+/* Dual-operation crypto-digest/verify - user should split ops */
+ck_rv_t C_DigestEncryptUpdate(ck_session_handle_t session, byte *part, ulong part_len, byte *encrypted_part, ulong *encrypted_part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DecryptDigestUpdate(ck_session_handle_t session, byte *encrypted_part, ulong encrypted_part_len, byte *part, ulong *part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_SignEncryptUpdate(ck_session_handle_t session, byte *part, ulong part_len, byte *encrypted_part, ulong *encrypted_part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DecryptVerifyUpdate(ck_session_handle_t session, byte *encrypted_part, ulong encrypted_part_len, byte *part, ulong *part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_WrapKey(ck_session_handle_t session, struct ck_mechanism *mech, ck_object_handle_t wrapping_key, ck_object_handle_t key, byte *wrapped_key, ulong *wrapped_key_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DeriveKey(ck_session_handle_t session, struct ck_mechanism *mech, ck_object_handle_t base_key, struct ck_attribute *templ, ulong attr_count, ck_object_handle_t *key) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_SeedRandom(ck_session_handle_t session, byte *seed, ulong seed_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_GenerateRandom(ck_session_handle_t session, byte *random_data, ulong random_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}

Added: trunk/TokendPKCS11/src/p11-personalization.cpp
===================================================================
--- trunk/TokendPKCS11/src/p11-personalization.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/p11-personalization.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "Utilities.h"
+#include "P11State.h"
+
+ck_rv_t C_InitPIN(ck_session_handle_t session, byte *pin, ulong pin_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_SetPIN(ck_session_handle_t session, byte *old_pin, ulong old_len, byte *new_pin, ulong new_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_CreateObject(ck_session_handle_t session, struct ck_attribute *templ, ulong count, ck_object_handle_t *object) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_SetAttributeValue(ck_session_handle_t session, ck_object_handle_t object, struct ck_attribute *templ, ulong count) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_GenerateKey(ck_session_handle_t session, struct ck_mechanism *mech, struct ck_attribute *templ, ulong count, ck_object_handle_t *key) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_GenerateKeyPair(ck_session_handle_t session, struct ck_mechanism *mech, struct ck_attribute *pubkey_template, ulong pubkey_attr_count, struct ck_attribute *privkey_template, ulong privkey_attr_count, ck_object_handle_t *pubkey, ck_object_handle_t *privkey) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}

Added: trunk/TokendPKCS11/src/p11-pubkey.cpp
===================================================================
--- trunk/TokendPKCS11/src/p11-pubkey.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/p11-pubkey.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,160 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "Utilities.h"
+#include "P11State.h"
+
+ck_rv_t C_EncryptInit(ck_session_handle_t session, struct ck_mechanism *mech, ck_object_handle_t key) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_Encrypt(ck_session_handle_t session, byte *data, ulong data_len, byte *encrypted_data, ulong *encrypted_data_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_EncryptUpdate(ck_session_handle_t session, byte *part, ulong part_len, byte *encrypted_part, ulong *encrypted_part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_EncryptFinal(ck_session_handle_t session, byte *last_encrypted_part, ulong *last_encrypted_part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DigestInit(ck_session_handle_t session, struct ck_mechanism *mech) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_Digest(ck_session_handle_t session, byte *data, ulong data_len, byte *digest, ulong *digest_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DigestUpdate(ck_session_handle_t session, byte *part, ulong part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DigestKey(ck_session_handle_t session, ck_object_handle_t key) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_DigestFinal(ck_session_handle_t session, byte *digest, ulong *digest_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_VerifyInit(ck_session_handle_t session, struct ck_mechanism *mech, ck_object_handle_t key) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_Verify(ck_session_handle_t session, byte *data, ulong data_len, byte *signature, ulong signature_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_VerifyUpdate(ck_session_handle_t session, byte *part, ulong part_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_VerifyFinal(ck_session_handle_t session, byte *signature, ulong signature_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_VerifyRecoverInit(ck_session_handle_t session, struct ck_mechanism *mech, ck_object_handle_t key) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_VerifyRecover(ck_session_handle_t session, byte *signature, ulong signature_len, byte *data, ulong *data_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}

Added: trunk/TokendPKCS11/src/p11-session.cpp
===================================================================
--- trunk/TokendPKCS11/src/p11-session.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/p11-session.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,104 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "Utilities.h"
+#include "P11State.h"
+
+ck_rv_t C_OpenSession(ck_slot_id_t slot_id, ck_flags_t flags, void *application, ck_notify_t notify, ck_session_handle_t *session) {
+	try {
+		GlobalLockCheck globalLock;
+		if(!session)
+			return CKR_ARGUMENTS_BAD;
+		/* RW Lock - state alteration */
+		P11Sessions &sessions = globalState().getSessions();
+		StLock<UserMutex> sessionsLock(sessions.getLock().writeMutex()); /* VALIDATED */
+		sessions.create(slot_id, flags, notify, application, *session);
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSlotError(e, slot_id);
+	}
+}
+
+ck_rv_t C_CloseSession(ck_session_handle_t session) {
+	try {
+		GlobalLockCheck globalLock;
+		/* RW Lock - state alteration */
+		P11Sessions &sessions = globalState().getSessions();
+		StLock<UserMutex> sessionsLock(sessions.getLock().writeMutex()); /* VALIDATED */
+		sessions.close(session);
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_CloseAllSessions(ck_slot_id_t slot_id) {
+	try {
+		GlobalLockCheck globalLock;
+		/* RW Lock - state alteration */
+		P11Sessions &sessions = globalState().getSessions();
+		StLock<UserMutex> sessionsLock(sessions.getLock().writeMutex()); /* VALIDATED */
+		sessions.closeAll(slot_id);
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		/* Exempt from error processing since it is in response to error processing */
+		return e.ret;
+	}
+}
+
+ck_rv_t C_GetSessionInfo(ck_session_handle_t session, struct ck_session_info *info) {
+	try {
+		GlobalLockCheck globalLock;
+		/* R Lock: Get Session Info == no change, need slot... */
+		LockedSession sessionRef(session);
+		LockedSlot lockedSlot(sessionRef.get()->getSlotID());
+		sessionRef.get()->information(*info, lockedSlot);
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_Login(ck_session_handle_t session, ck_user_type_t user_type, byte *pin, ulong pin_len) {
+	try {
+		GlobalLockCheck globalLock;
+		/* RW Lock: Login changes slot state - not session state as pkcs11 wants... */
+		LockedSession sessionRef(session, true);
+		LockedSlot lockedSlot(sessionRef.get()->getSlotID(), true);
+		return lockedSlot.get()->login(user_type, pin, pin_len);
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_Logout(ck_session_handle_t session) {
+	try {
+		GlobalLockCheck globalLock;
+		/* RW Lock: Logout changes state */
+		LockedSession sessionRef(session, true);
+		LockedSlot lockedSlot(sessionRef.get()->getSlotID(), true);
+		return lockedSlot.get()->logout();
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}

Added: trunk/TokendPKCS11/src/p11-slot.cpp
===================================================================
--- trunk/TokendPKCS11/src/p11-slot.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/p11-slot.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+
+#include "P11State.h"
+#include "IteratorUtilities.h"
+#include "Utilities.h"
+
+ck_rv_t C_GetSlotList(byte token_present, ck_slot_id_t *slot_list, ulong *count) {
+	try {
+		GlobalLockCheck globalLock;
+		/* token_present ignored */
+		if(!count)
+			return CKR_ARGUMENTS_BAD;
+		P11Slots &slots = globalState().getSlots();
+		/* RW Lock : Listing slots causes a refresh */
+		StLock<UserMutex> slotsLock(slots.getLock().writeMutex()); /* VALIDATED */
+		return slots.list(slot_list, *count, token_present != 0);
+	} catch(P11Exception &e) {
+		return e.ret;
+	}
+}
+
+ck_rv_t C_GetSlotInfo(ck_slot_id_t slot_id, struct ck_slot_info *info) {
+	bool slotIsPresent;
+	try {
+		GlobalLockCheck globalLock;
+		if(!info)
+			return CKR_ARGUMENTS_BAD;
+		/* R Lock: Just pulling slot data */
+		LockedSlot lockedSlot(slot_id);
+		P11Slot_Ref slot = lockedSlot.get();
+		slotIsPresent = slot->isPresent();
+		slot->getInformation(*info);
+	} catch(P11Exception &e) {
+		return e.ret;
+	}
+	if(!slotIsPresent) {
+		/* Try to close all sessions */
+		C_CloseAllSessions(slot_id);
+	}
+	return CKR_OK;
+}
+
+ck_rv_t C_GetTokenInfo(ck_slot_id_t slot_id, struct ck_token_info *info) {
+	try {
+		GlobalLockCheck globalLock;
+		if(!info)
+			return CKR_ARGUMENTS_BAD;
+		/* R Lock: Just pulling slot data */
+		LockedSlot lockedSlot(slot_id);
+		P11Slot_Ref slot = lockedSlot.get();
+		/* Global use and current use need to not be counted */
+		slot->getTokenInformation(*info, slot.use_count() - 2);
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSlotError(e, slot_id);
+	}
+}
+
+ck_rv_t C_WaitForSlotEvent(ck_flags_t flags, ck_slot_id_t *slot, void *reserved) {
+	try {
+		GlobalLockCheck globalLock;
+		/* NOTE: Existing apple impl does not impl */
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return e.ret;
+	}
+}
+
+ck_rv_t C_GetMechanismList(ck_slot_id_t slot_id, ck_mechanism_type_t *mech_list, ulong *count) {
+	try {
+		GlobalLockCheck globalLock;
+		if(!count)
+			return CKR_ARGUMENTS_BAD;
+		/* R Lock: Just pulling mechanism list */
+		LockedSlot lockedSlot(slot_id);
+		P11Slot_Ref slot = lockedSlot.get();
+		return copy_list_of_keys(mech_list, slot->getMechanisms(), *count);
+	} catch(P11Exception &e) {
+		return processSlotError(e, slot_id);
+	}
+}
+
+ck_rv_t C_GetMechanismInfo(ck_slot_id_t slot_id, ck_mechanism_type_t type, struct ck_mechanism_info *info) {
+	try {
+		GlobalLockCheck globalLock;
+		if(!info)
+			return CKR_ARGUMENTS_BAD;
+		/* R Lock: Just pulling mechanism info */
+		LockedSlot lockedSlot(slot_id);
+		P11Slot_Ref slot = lockedSlot.get();
+		P11Mechanism_Ref mech = slot->getMechanism(type);
+		*info = mech->getInfo();
+		return CKR_OK;
+	} catch(P11Exception &e) {
+		return processSlotError(e, slot_id);
+	}
+}
+
+ck_rv_t C_InitToken(ck_slot_id_t slot_id, byte *pin, ulong pin_len, byte *label) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSlotError(e, slot_id);
+	}
+}

Added: trunk/TokendPKCS11/src/p11-unsupported.cpp
===================================================================
--- trunk/TokendPKCS11/src/p11-unsupported.cpp	                        (rev 0)
+++ trunk/TokendPKCS11/src/p11-unsupported.cpp	2010-11-16 20:07:01 UTC (rev 136)
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2008 Apple Inc. All Rights Reserved.
+ *
+ *  @APPLE_LICENSE_HEADER_START@
+ *
+ *  This file contains Original Code and/or Modifications of Original Code
+ *  as defined in and that are subject to the Apple Public Source License
+ *  Version 2.0 (the 'License'). You may not use this file except in
+ *  compliance with the License. Please obtain a copy of the License at
+ *  http://www.opensource.apple.com/apsl/ and read it before using this
+ *  file.
+ *
+ *  The Original Code and all software distributed under the License are
+ *  distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ *  EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ *  INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ *  Please see the License for the specific language governing rights and
+ *  limitations under the License.
+ *
+ *  @APPLE_LICENSE_HEADER_END@
+ */
+
+#include "P11State.h"
+
+
+ck_rv_t C_GetFunctionStatus(ck_session_handle_t session) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_CancelFunction(ck_session_handle_t session) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_GetOperationState(ck_session_handle_t session, byte *op_state, ulong *op_state_len) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+ck_rv_t C_SetOperationState(ck_session_handle_t session, byte *op_state, ulong op_state_len, ck_object_handle_t enc_key, ck_object_handle_t auth_key) {
+	try {
+		GlobalLockCheck globalLock;
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	} catch(P11Exception &e) {
+		return processSessionError(e, session);
+	}
+}
+
+// MAX LINE LENGTH: 	268
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/smartcardservices-changes/attachments/20101116/629046f7/attachment-0001.html>


More information about the SmartcardServices-Changes mailing list