1 /* pkcs11.h
2  * Copyright (c) OASIS Open 2016. All Rights Reserved./
3  * Copyright (C) 2017  for the binding: Carsten Blüggel <carblue@geekmail.de>
4  * /Distributed under the terms of the OASIS IPR Policy,
5  * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
6  * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
7  * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
8  */
9 
10 /* Latest version of the specification:
11  * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
12  */
13 /*
14 Written in the D programming language.
15 See also https://github.com/jpf91/systemd/wiki/Deimos-git-branch-structure
16 For git maintenance (ensure at least one congruent line with originating C header):
17 #define _PKCS11_H_ 1
18 
19 Different from the C source which unrolls all #include of pkcs11t.h and pkcs11f.h in pkcs11.h,
20 the extern function decls ("extern" form of all the entry points) and
21 function pointer decls (typedef form of all the entry points) from pkcs11f.h are in pkcs11f.d,
22 the struct CK_FUNCTION_LIST is in pkcs11t.d as well as all content from pkcs11t.h.
23 */
24 
25 module pkcs11;
26 
27 
28 public import pkcs11.pkcs11t;
29 public import pkcs11.pkcs11f;
30 
31 // PKCS11_DYNAMIC_BINDING_ONE / PKCS11_DYNAMIC_BINDING_MULTIPLE are mutual exclusive !
32 version(     PKCS11_DYNAMIC_BINDING_ONE)
33 	version=PKCS11_DYNAMIC_BINDING;
34 else version(PKCS11_DYNAMIC_BINDING_MULTIPLE)
35 	version=PKCS11_DYNAMIC_BINDING;
36 
37 // only version(PKCS11_DYNAMIC_BINDING) needs compiling
38 version(PKCS11_DYNAMIC_BINDING) {
39 
40 	version(PKCS11_OPENSC_SPY) enum PKCS11_OPENSC_SPY = true;
41 	else                       enum PKCS11_OPENSC_SPY = false;
42 
43 	private {
44 		import std.exception : enforce;
45 		import derelict.util.exception,
46 					 derelict.util.loader,
47 					 derelict.util.system;
48 
49 		version(P11KIT) { // use highest priority pkcs#11 module as configured by p11-kit
50 			static if (Derelict_OS_Windows)
51 				enum libNames = "libp11-kit.dll";
52 			else static if( Derelict_OS_Mac )
53 				enum libNames = "libp11-kit.dylib";
54 			else static if( Derelict_OS_Posix )
55 				enum libNames = "libp11-kit.so";
56 			else
57 				static assert( 0, "Need to implement PKCS11 libNames for this operating system." );
58 		}
59 		else {
60 			static if (Derelict_OS_Windows) {
61 				static if (PKCS11_OPENSC_SPY)
62 					enum libNames = "pkcs11-spy.dll";
63 				else
64 					enum libNames = "opensc-pkcs11.dll";
65 			}
66 			else static if( Derelict_OS_Mac ) {
67 				static if (PKCS11_OPENSC_SPY)
68 					enum libNames = "pkcs11-spy.dylib";
69 				else
70 					enum libNames = "opensc-pkcs11.dylib";
71 			}
72 			else static if( Derelict_OS_Posix ) {
73 				static if (PKCS11_OPENSC_SPY)
74 					enum libNames = "pkcs11-spy.so";
75 				else
76 					enum libNames = "opensc-pkcs11.so"; // onepin-opensc-pkcs11.so ?
77 			}
78 			else
79 				static assert( 0, "Need to implement PKCS11 libNames for this operating system." );
80 		}
81 	} // private
82 
83 	class PKCS11Loader : SharedLibLoader {
84 
85 		public this() {
86 			super( libNames );
87 		}
88 
89 		protected override void loadSymbols() {
90 			bindFunc( cast(void**)&C_GetFunctionList,   "C_GetFunctionList");
91 
92 		// Try to use C_GetFunctionList; an error implies, the library is not usable
93 			CK_FUNCTION_LIST_PTR  pFunctionList;
94 			enforce(C_GetFunctionList(&pFunctionList) == CKR_OK);
95 version(PKCS11_DYNAMIC_BINDING_ONE)
96 			m_function_list_ptr    = pFunctionList;
97 
98 			C_Initialize           = pFunctionList.C_Initialize;
99 			C_Finalize             = pFunctionList.C_Finalize;
100 			C_GetInfo              = pFunctionList.C_GetInfo;
101 //		C_GetFunctionList      = pFunctionList.C_GetFunctionList;
102 			C_GetSlotList          = pFunctionList.C_GetSlotList;
103 			C_GetSlotInfo          = pFunctionList.C_GetSlotInfo;
104 			C_GetTokenInfo         = pFunctionList.C_GetTokenInfo;
105 			C_GetMechanismList     = pFunctionList.C_GetMechanismList;
106 			C_GetMechanismInfo     = pFunctionList.C_GetMechanismInfo;
107 			C_InitToken            = pFunctionList.C_InitToken;
108 			C_InitPIN              = pFunctionList.C_InitPIN;
109 			C_SetPIN               = pFunctionList.C_SetPIN;
110 			C_OpenSession          = pFunctionList.C_OpenSession;
111 			C_CloseSession         = pFunctionList.C_CloseSession;
112 			C_CloseAllSessions     = pFunctionList.C_CloseAllSessions;
113 			C_GetSessionInfo       = pFunctionList.C_GetSessionInfo;
114 			C_GetOperationState    = pFunctionList.C_GetOperationState;
115 			C_SetOperationState    = pFunctionList.C_SetOperationState;
116 			C_Login                = pFunctionList.C_Login;
117 			C_Logout               = pFunctionList.C_Logout;
118 			C_CreateObject         = pFunctionList.C_CreateObject;
119 			C_CopyObject           = pFunctionList.C_CopyObject;
120 			C_DestroyObject        = pFunctionList.C_DestroyObject;
121 			C_GetObjectSize        = pFunctionList.C_GetObjectSize;
122 			C_GetAttributeValue    = pFunctionList.C_GetAttributeValue;
123 			C_SetAttributeValue    = pFunctionList.C_SetAttributeValue;
124 			C_FindObjectsInit      = pFunctionList.C_FindObjectsInit;
125 			C_FindObjects          = pFunctionList.C_FindObjects;
126 			C_FindObjectsFinal     = pFunctionList.C_FindObjectsFinal;
127 			C_EncryptInit          = pFunctionList.C_EncryptInit;
128 			C_Encrypt              = pFunctionList.C_Encrypt;
129 			C_EncryptUpdate        = pFunctionList.C_EncryptUpdate;
130 			C_EncryptFinal         = pFunctionList.C_EncryptFinal;
131 			C_DecryptInit          = pFunctionList.C_DecryptInit;
132 			C_Decrypt              = pFunctionList.C_Decrypt;
133 			C_DecryptUpdate        = pFunctionList.C_DecryptUpdate;
134 			C_DecryptFinal         = pFunctionList.C_DecryptFinal;
135 			C_DigestInit           = pFunctionList.C_DigestInit;
136 			C_Digest               = pFunctionList.C_Digest;
137 			C_DigestUpdate         = pFunctionList.C_DigestUpdate;
138 			C_DigestKey            = pFunctionList.C_DigestKey;
139 			C_DigestFinal          = pFunctionList.C_DigestFinal;
140 			C_SignInit             = pFunctionList.C_SignInit;
141 			C_Sign                 = pFunctionList.C_Sign;
142 			C_SignUpdate           = pFunctionList.C_SignUpdate;
143 			C_SignFinal            = pFunctionList.C_SignFinal;
144 			C_SignRecoverInit      = pFunctionList.C_SignRecoverInit;
145 			C_SignRecover          = pFunctionList.C_SignRecover;
146 			C_VerifyInit           = pFunctionList.C_VerifyInit;
147 			C_Verify               = pFunctionList.C_Verify;
148 			C_VerifyUpdate         = pFunctionList.C_VerifyUpdate;
149 			C_VerifyFinal          = pFunctionList.C_VerifyFinal;
150 			C_VerifyRecoverInit    = pFunctionList.C_VerifyRecoverInit;
151 			C_VerifyRecover        = pFunctionList.C_VerifyRecover;
152 			C_DigestEncryptUpdate  = pFunctionList.C_DigestEncryptUpdate;
153 			C_DecryptDigestUpdate  = pFunctionList.C_DecryptDigestUpdate;
154 			C_SignEncryptUpdate    = pFunctionList.C_SignEncryptUpdate;
155 			C_DecryptVerifyUpdate  = pFunctionList.C_DecryptVerifyUpdate;
156 			C_GenerateKey          = pFunctionList.C_GenerateKey;
157 			C_GenerateKeyPair      = pFunctionList.C_GenerateKeyPair;
158 			C_WrapKey              = pFunctionList.C_WrapKey;
159 			C_UnwrapKey            = pFunctionList.C_UnwrapKey;
160 			C_DeriveKey            = pFunctionList.C_DeriveKey;
161 			C_SeedRandom           = pFunctionList.C_SeedRandom;
162 			C_GenerateRandom       = pFunctionList.C_GenerateRandom;
163 			C_GetFunctionStatus    = pFunctionList.C_GetFunctionStatus;
164 			C_CancelFunction       = pFunctionList.C_CancelFunction;
165 			C_WaitForSlotEvent     = pFunctionList.C_WaitForSlotEvent;
166 		}
167 
168 version(PKCS11_DYNAMIC_BINDING_ONE) {
169 	__gshared CK_FUNCTION_LIST_PTR  m_function_list_ptr;
170 
171 		// for (rare) cases, when it's required to pass the access to Cryptoki-functions
172 		@property __gshared CK_FUNCTION_LIST_PTR function_list_ptr() {
173 			return m_function_list_ptr;
174 		}
175 }
176 version(PKCS11_DYNAMIC_BINDING_MULTIPLE)
177 		mixin CK_FUNCTION_LIST_FENTRIES;
178 	} // class PKCS11Loader
179 
180 version(PKCS11_DYNAMIC_BINDING_ONE) {
181 	__gshared PKCS11Loader          PKCS11;
182 
183 	shared static this() {
184 		PKCS11 = new PKCS11Loader();
185 	}
186 
187 	__gshared {
188 		mixin CK_FUNCTION_LIST_FENTRIES;
189 	}
190 } // version(PKCS11_DYNAMIC_BINDING_ONE)
191 
192 
193 	unittest {
194 		PKCS11.load("opensc-pkcs11.so");
195 version(PKCS11_DYNAMIC_BINDING_ONE) {
196 		// the following usage of function_list_ptr is not necessary in regular use cases; here only for testing purpose of @property function
197 		auto  p = PKCS11.function_list_ptr;
198 		p.C_Initialize(null);
199 		p.C_Finalize(null);
200 }
201 	}
202 
203 } // version(PKCS11_DYNAMIC_BINDING)