]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/pkcs11/pkcs11_library.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libstrongswan / plugins / pkcs11 / pkcs11_library.c
CommitLineData
34454dc3 1/*
4aab3153 2 * Copyright (C) 2011-2015 Tobias Brunner
34454dc3 3 * Copyright (C) 2010 Martin Willi
19ef2aec
TB
4 *
5 * Copyright (C) secunet Security Networks AG
34454dc3
MW
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18#include "pkcs11_library.h"
19
f30187d4 20#ifndef WIN32
34454dc3 21#include <dlfcn.h>
f30187d4
MS
22#else
23/* macro defined by synchapi.h that maps to CreateMutexA/W */
24#undef CreateMutex
25#endif
34454dc3
MW
26
27#include <library.h>
4aab3153 28#include <asn1/asn1.h>
f05b4272 29#include <utils/debug.h>
50e1a710 30#include <threading/mutex.h>
12642a68 31#include <collections/linked_list.h>
34454dc3
MW
32
33typedef struct private_pkcs11_library_t private_pkcs11_library_t;
34
a6456dd6
MW
35
36ENUM_BEGIN(ck_rv_names, CKR_OK, CKR_CANT_LOCK,
37 "OK",
38 "CANCEL",
39 "HOST_MEMORY",
40 "SLOT_ID_INVALID",
41 "(0x04)",
42 "GENERAL_ERROR",
43 "FUNCTION_FAILED",
44 "ARGUMENTS_BAD",
45 "NO_EVENT",
46 "NEED_TO_CREATE_THREADS",
47 "CANT_LOCK");
48ENUM_NEXT(ck_rv_names, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID,
49 CKR_CANT_LOCK,
50 "ATTRIBUTE_READ_ONLY",
51 "ATTRIBUTE_SENSITIVE",
52 "ATTRIBUTE_TYPE_INVALID",
53 "ATTRIBUTE_VALUE_INVALID");
54ENUM_NEXT(ck_rv_names, CKR_DATA_INVALID, CKR_DATA_LEN_RANGE,
55 CKR_ATTRIBUTE_VALUE_INVALID,
45c8399d 56 "DATA_INVALID",
a6456dd6
MW
57 "DATA_LEN_RANGE");
58ENUM_NEXT(ck_rv_names, CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED,
59 CKR_DATA_LEN_RANGE,
60 "DEVICE_ERROR",
61 "DEVICE_MEMORY",
62 "DEVICE_REMOVED");
63ENUM_NEXT(ck_rv_names, CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE,
64 CKR_DEVICE_REMOVED,
65 "ENCRYPTED_DATA_INVALID",
66 "ENCRYPTED_DATA_LEN_RANGE");
67ENUM_NEXT(ck_rv_names, CKR_FUNCTION_CANCELED, CKR_FUNCTION_NOT_SUPPORTED,
68 CKR_ENCRYPTED_DATA_LEN_RANGE,
69 "FUNCTION_CANCELED",
70 "FUNCTION_NOT_PARALLEL",
71 "(0x52)",
72 "(0x53)",
73 "FUNCTION_NOT_SUPPORTED");
74ENUM_NEXT(ck_rv_names, CKR_KEY_HANDLE_INVALID, CKR_KEY_UNEXTRACTABLE,
75 CKR_FUNCTION_NOT_SUPPORTED,
76 "KEY_HANDLE_INVALID",
77 "(0x61)",
78 "KEY_SIZE_RANGE",
79 "KEY_TYPE_INCONSISTENT",
80 "KEY_NOT_NEEDED",
81 "KEY_CHANGED",
82 "KEY_NEEDED",
83 "KEY_INDIGESTIBLE",
84 "KEY_FUNCTION_NOT_PERMITTED",
85 "KEY_NOT_WRAPPABLE",
86 "KEY_UNEXTRACTABLE");
87ENUM_NEXT(ck_rv_names, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID,
88 CKR_KEY_UNEXTRACTABLE,
89 "MECHANISM_INVALID",
90 "MECHANISM_PARAM_INVALID");
91ENUM_NEXT(ck_rv_names, CKR_OBJECT_HANDLE_INVALID, CKR_OBJECT_HANDLE_INVALID,
92 CKR_MECHANISM_PARAM_INVALID,
93 "OBJECT_HANDLE_INVALID");
94ENUM_NEXT(ck_rv_names, CKR_OPERATION_ACTIVE, CKR_OPERATION_NOT_INITIALIZED,
95 CKR_OBJECT_HANDLE_INVALID,
96 "OPERATION_ACTIVE",
97 "OPERATION_NOT_INITIALIZED");
98ENUM_NEXT(ck_rv_names, CKR_PIN_INCORRECT, CKR_PIN_LOCKED,
99 CKR_OPERATION_NOT_INITIALIZED,
100 "PIN_INCORRECT",
101 "PIN_INVALID",
102 "PIN_LEN_RANGE",
103 "PIN_EXPIRED",
104 "PIN_LOCKED");
105ENUM_NEXT(ck_rv_names, CKR_SESSION_CLOSED, CKR_SESSION_READ_WRITE_SO_EXISTS,
106 CKR_PIN_LOCKED,
107 "SESSION_CLOSED",
108 "SESSION_COUNT",
109 "(0xb2)",
110 "SESSION_HANDLE_INVALID",
111 "SESSION_PARALLEL_NOT_SUPPORTED",
112 "SESSION_READ_ONLY",
113 "SESSION_EXISTS",
114 "SESSION_READ_ONLY_EXISTS",
115 "SESSION_READ_WRITE_SO_EXISTS");
116ENUM_NEXT(ck_rv_names, CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE,
117 CKR_SESSION_READ_WRITE_SO_EXISTS,
118 "SIGNATURE_INVALID",
119 "SIGNATURE_LEN_RANGE");
120ENUM_NEXT(ck_rv_names, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT,
121 CKR_SIGNATURE_LEN_RANGE,
122 "TEMPLATE_INCOMPLETE",
123 "TEMPLATE_INCONSISTENT",
124);
125ENUM_NEXT(ck_rv_names, CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_WRITE_PROTECTED,
126 CKR_TEMPLATE_INCONSISTENT,
127 "TOKEN_NOT_PRESENT",
128 "TOKEN_NOT_RECOGNIZED",
129 "TOKEN_WRITE_PROTECTED");
130ENUM_NEXT(ck_rv_names, CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,
131 CKR_TOKEN_WRITE_PROTECTED,
132 "UNWRAPPING_KEY_HANDLE_INVALID",
133 "UNWRAPPING_KEY_SIZE_RANGE",
134 "UNWRAPPING_KEY_TYPE_INCONSISTENT");
135ENUM_NEXT(ck_rv_names, CKR_USER_ALREADY_LOGGED_IN, CKR_USER_TOO_MANY_TYPES,
136 CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,
137 "USER_ALREADY_LOGGED_IN",
138 "USER_NOT_LOGGED_IN",
139 "USER_PIN_NOT_INITIALIZED",
140 "USER_TYPE_INVALID",
141 "USER_ANOTHER_ALREADY_LOGGED_IN",
142 "USER_TOO_MANY_TYPES");
143ENUM_NEXT(ck_rv_names, CKR_WRAPPED_KEY_INVALID, CKR_WRAPPING_KEY_TYPE_INCONSISTENT,
144 CKR_USER_TOO_MANY_TYPES,
145 "WRAPPED_KEY_INVALID",
146 "(0x111)",
147 "WRAPPED_KEY_LEN_RANGE",
148 "WRAPPING_KEY_HANDLE_INVALID",
149 "WRAPPING_KEY_SIZE_RANGE",
150 "WRAPPING_KEY_TYPE_INCONSISTENT");
151ENUM_NEXT(ck_rv_names, CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG,
152 CKR_WRAPPING_KEY_TYPE_INCONSISTENT,
153 "RANDOM_SEED_NOT_SUPPORTED",
154 "RANDOM_NO_RNG");
155ENUM_NEXT(ck_rv_names, CKR_DOMAIN_PARAMS_INVALID, CKR_DOMAIN_PARAMS_INVALID,
156 CKR_RANDOM_NO_RNG,
157 "DOMAIN_PARAMS_INVALID");
158ENUM_NEXT(ck_rv_names, CKR_BUFFER_TOO_SMALL, CKR_BUFFER_TOO_SMALL,
159 CKR_DOMAIN_PARAMS_INVALID,
160 "BUFFER_TOO_SMALL");
161ENUM_NEXT(ck_rv_names, CKR_SAVED_STATE_INVALID, CKR_SAVED_STATE_INVALID,
162 CKR_BUFFER_TOO_SMALL,
163 "SAVED_STATE_INVALID");
164ENUM_NEXT(ck_rv_names, CKR_INFORMATION_SENSITIVE, CKR_INFORMATION_SENSITIVE,
165 CKR_SAVED_STATE_INVALID,
166 "INFORMATION_SENSITIVE");
167ENUM_NEXT(ck_rv_names, CKR_STATE_UNSAVEABLE, CKR_STATE_UNSAVEABLE,
168 CKR_INFORMATION_SENSITIVE,
169 "STATE_UNSAVEABLE");
170ENUM_NEXT(ck_rv_names, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CRYPTOKI_ALREADY_INITIALIZED,
171 CKR_STATE_UNSAVEABLE,
172 "CRYPTOKI_NOT_INITIALIZED",
173 "CRYPTOKI_ALREADY_INITIALIZED");
174ENUM_NEXT(ck_rv_names, CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED,
175 CKR_CRYPTOKI_ALREADY_INITIALIZED,
176 "MUTEX_BAD",
177 "MUTEX_NOT_LOCKED");
178ENUM_NEXT(ck_rv_names, CKR_FUNCTION_REJECTED, CKR_FUNCTION_REJECTED,
179 CKR_MUTEX_NOT_LOCKED,
180 "FUNCTION_REJECTED");
181ENUM_END(ck_rv_names, CKR_FUNCTION_REJECTED);
182
183
75451ac8
MW
184ENUM_BEGIN(ck_mech_names, CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_DSA_SHA1,
185 "RSA_PKCS_KEY_PAIR_GEN",
186 "RSA_PKCS",
187 "RSA_9796",
188 "RSA_X_509",
189 "MD2_RSA_PKCS",
190 "MD5_RSA_PKCS",
191 "SHA1_RSA_PKCS",
192 "RIPEMD128_RSA_PKCS",
193 "RIPEMD160_RSA_PKCS",
194 "RSA_PKCS_OAEP",
195 "RSA_X9_31_KEY_PAIR_GEN",
196 "RSA_X9_31",
197 "SHA1_RSA_X9_31",
198 "RSA_PKCS_PSS",
199 "SHA1_RSA_PKCS_PSS",
200 "(0xf)",
201 "DSA_KEY_PAIR_GEN",
202 "DSA",
203 "DSA_SHA1");
204ENUM_NEXT(ck_mech_names, CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE,
205 CKM_DSA_SHA1,
206 "DH_PKCS_KEY_PAIR_GEN",
207 "DH_PKCS_DERIVE");
208ENUM_NEXT(ck_mech_names, CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_MQV_DERIVE,
209 CKM_DH_PKCS_DERIVE,
210 "X9_42_DH_KEY_PAIR_GEN",
211 "X9_42_DH_DERIVE",
212 "X9_42_DH_HYBRID_DERIVE",
213 "X9_42_MQV_DERIVE");
214ENUM_NEXT(ck_mech_names, CKM_SHA256_RSA_PKCS, CKM_SHA512_RSA_PKCS_PSS,
215 CKM_X9_42_MQV_DERIVE,
216 "SHA256_RSA_PKCS",
217 "SHA384_RSA_PKCS",
218 "SHA512_RSA_PKCS",
219 "SHA256_RSA_PKCS_PSS",
220 "SHA384_RSA_PKCS_PSS",
221 "SHA512_RSA_PKCS_PSS");
222ENUM_NEXT(ck_mech_names, CKM_RC2_KEY_GEN, CKM_RC2_CBC_PAD,
223 CKM_SHA512_RSA_PKCS_PSS,
224 "RC2_KEY_GEN",
225 "RC2_ECB",
226 "RC2_CBC",
227 "RC2_MAC",
228 "RC2_MAC_GENERAL",
229 "RC2_CBC_PAD");
230ENUM_NEXT(ck_mech_names, CKM_RC4_KEY_GEN, CKM_RC4,
231 CKM_RC2_CBC_PAD,
232 "RC4_KEY_GEN",
233 "RC4");
234ENUM_NEXT(ck_mech_names, CKM_DES_KEY_GEN, CKM_DES_CBC_PAD,
235 CKM_RC4,
236 "DES_KEY_GEN",
237 "DES_ECB",
238 "DES_CBC",
239 "DES_MAC",
240 "DES_MAC_GENERAL",
241 "DES_CBC_PAD");
242ENUM_NEXT(ck_mech_names, CKM_DES2_KEY_GEN, CKM_DES3_CBC_PAD,
243 CKM_DES_CBC_PAD,
244 "DES2_KEY_GEN",
245 "DES3_KEY_GEN",
246 "DES3_ECB",
247 "DES3_CBC",
248 "DES3_MAC",
249 "DES3_MAC_GENERAL",
250 "DES3_CBC_PAD");
251ENUM_NEXT(ck_mech_names, CKM_CDMF_KEY_GEN, CKM_CDMF_CBC_PAD,
252 CKM_DES3_CBC_PAD,
253 "CDMF_KEY_GEN",
254 "CDMF_ECB",
255 "CDMF_CBC",
256 "CDMF_MAC",
257 "CDMF_MAC_GENERAL",
258 "CDMF_CBC_PAD");
259ENUM_NEXT(ck_mech_names, CKM_MD2, CKM_MD2_HMAC_GENERAL,
260 CKM_CDMF_CBC_PAD,
261 "MD2",
262 "MD2_HMAC",
263 "MD2_HMAC_GENERAL");
264ENUM_NEXT(ck_mech_names, CKM_MD5, CKM_MD5_HMAC_GENERAL,
265 CKM_MD2_HMAC_GENERAL,
266 "MD5",
267 "MD5_HMAC",
268 "MD5_HMAC_GENERAL");
269ENUM_NEXT(ck_mech_names, CKM_SHA_1, CKM_SHA_1_HMAC_GENERAL,
270 CKM_MD5_HMAC_GENERAL,
271 "SHA_1",
272 "SHA_1_HMAC",
273 "SHA_1_HMAC_GENERAL");
274ENUM_NEXT(ck_mech_names, CKM_RIPEMD128, CKM_RIPEMD128_HMAC_GENERAL,
275 CKM_SHA_1_HMAC_GENERAL,
276 "RIPEMD128",
277 "RIPEMD128_HMAC",
278 "RIPEMD128_HMAC_GENERAL");
279ENUM_NEXT(ck_mech_names, CKM_RIPEMD160, CKM_RIPEMD160_HMAC_GENERAL,
280 CKM_RIPEMD128_HMAC_GENERAL,
281 "RIPEMD160",
282 "RIPEMD160_HMAC",
283 "RIPEMD160_HMAC_GENERAL");
284ENUM_NEXT(ck_mech_names, CKM_SHA256, CKM_SHA256_HMAC_GENERAL,
285 CKM_RIPEMD160_HMAC_GENERAL,
286 "SHA256",
287 "SHA256_HMAC",
288 "SHA256_HMAC_GENERAL");
289ENUM_NEXT(ck_mech_names, CKM_SHA384, CKM_SHA384_HMAC_GENERAL,
290 CKM_SHA256_HMAC_GENERAL,
291 "SHA384",
292 "SHA384_HMAC",
293 "SHA384_HMAC_GENERAL");
294ENUM_NEXT(ck_mech_names, CKM_SHA512, CKM_SHA512_HMAC_GENERAL,
295 CKM_SHA384_HMAC_GENERAL ,
296 "SHA512",
297 "SHA512_HMAC",
298 "SHA512_HMAC_GENERAL");
299ENUM_NEXT(ck_mech_names, CKM_CAST_KEY_GEN, CKM_CAST_CBC_PAD,
300 CKM_SHA512_HMAC_GENERAL,
301 "CAST_KEY_GEN",
302 "CAST_ECB",
303 "CAST_CBC",
304 "CAST_MAC",
305 "CAST_MAC_GENERAL",
306 "CAST_CBC_PAD");
307ENUM_NEXT(ck_mech_names, CKM_CAST3_KEY_GEN, CKM_CAST3_CBC_PAD,
308 CKM_CAST_CBC_PAD,
309 "CAST3_KEY_GEN",
310 "CAST3_ECB",
311 "CAST3_CBC",
312 "CAST3_MAC",
313 "CAST3_MAC_GENERAL",
314 "CAST3_CBC_PAD");
315ENUM_NEXT(ck_mech_names, CKM_CAST128_KEY_GEN, CKM_CAST128_CBC_PAD,
316 CKM_CAST3_CBC_PAD,
317 "CAST128_KEY_GEN",
318 "CAST128_ECB",
319 "CAST128_CBC",
320 "CAST128_MAC",
321 "CAST128_MAC_GENERAL",
322 "CAST128_CBC_PAD");
323ENUM_NEXT(ck_mech_names, CKM_RC5_KEY_GEN, CKM_RC5_CBC_PAD,
324 CKM_CAST128_CBC_PAD,
325 "RC5_KEY_GEN",
326 "RC5_ECB",
327 "RC5_CBC",
328 "RC5_MAC",
329 "RC5_MAC_GENERAL",
330 "RC5_CBC_PAD");
331ENUM_NEXT(ck_mech_names, CKM_IDEA_KEY_GEN, CKM_IDEA_CBC_PAD,
332 CKM_RC5_CBC_PAD,
333 "IDEA_KEY_GEN",
334 "IDEA_ECB",
335 "IDEA_CBC",
336 "IDEA_MAC",
337 "IDEA_MAC_GENERAL",
338 "IDEA_CBC_PAD");
339ENUM_NEXT(ck_mech_names, CKM_GENERIC_SECRET_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN,
340 CKM_IDEA_CBC_PAD,
341 "GENERIC_SECRET_KEY_GEN");
342ENUM_NEXT(ck_mech_names, CKM_CONCATENATE_BASE_AND_KEY, CKM_EXTRACT_KEY_FROM_KEY,
343 CKM_GENERIC_SECRET_KEY_GEN,
344 "CONCATENATE_BASE_AND_KEY",
345 "(0x361)",
346 "CONCATENATE_BASE_AND_DATA",
347 "CONCATENATE_DATA_AND_BASE",
348 "XOR_BASE_AND_DATA",
349 "EXTRACT_KEY_FROM_KEY");
350ENUM_NEXT(ck_mech_names, CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_MASTER_KEY_DERIVE_DH,
351 CKM_EXTRACT_KEY_FROM_KEY,
352 "SSL3_PRE_MASTER_KEY_GEN",
353 "SSL3_MASTER_KEY_DERIVE",
354 "SSL3_KEY_AND_MAC_DERIVE",
355 "SSL3_MASTER_KEY_DERIVE_DH",
356 "TLS_PRE_MASTER_KEY_GEN",
357 "TLS_MASTER_KEY_DERIVE",
358 "TLS_KEY_AND_MAC_DERIVE",
359 "TLS_MASTER_KEY_DERIVE_DH");
360ENUM_NEXT(ck_mech_names, CKM_SSL3_MD5_MAC, CKM_SSL3_SHA1_MAC,
361 CKM_TLS_MASTER_KEY_DERIVE_DH,
362 "SSL3_MD5_MAC",
363 "SSL3_SHA1_MAC");
364ENUM_NEXT(ck_mech_names, CKM_MD5_KEY_DERIVATION, CKM_SHA1_KEY_DERIVATION,
365 CKM_SSL3_SHA1_MAC,
366 "MD5_KEY_DERIVATION",
367 "MD2_KEY_DERIVATION",
368 "SHA1_KEY_DERIVATION");
369ENUM_NEXT(ck_mech_names, CKM_PBE_MD2_DES_CBC, CKM_PBE_SHA1_RC2_40_CBC,
370 CKM_SHA1_KEY_DERIVATION,
371 "PBE_MD2_DES_CBC",
372 "PBE_MD5_DES_CBC",
373 "PBE_MD5_CAST_CBC",
374 "PBE_MD5_CAST3_CBC",
375 "PBE_MD5_CAST128_CBC",
376 "PBE_SHA1_CAST128_CBC",
377 "PBE_SHA1_RC4_128",
378 "PBE_SHA1_RC4_40",
379 "PBE_SHA1_DES3_EDE_CBC",
380 "PBE_SHA1_DES2_EDE_CBC",
381 "PBE_SHA1_RC2_128_CBC",
382 "PBE_SHA1_RC2_40_CBC");
383ENUM_NEXT(ck_mech_names, CKM_PKCS5_PBKD2, CKM_PKCS5_PBKD2,
384 CKM_PBE_SHA1_RC2_40_CBC,
385 "PKCS5_PBKD2");
386ENUM_NEXT(ck_mech_names, CKM_PBA_SHA1_WITH_SHA1_HMAC, CKM_PBA_SHA1_WITH_SHA1_HMAC,
387 CKM_PKCS5_PBKD2,
388 "PBA_SHA1_WITH_SHA1_HMAC");
389ENUM_NEXT(ck_mech_names, CKM_KEY_WRAP_LYNKS, CKM_KEY_WRAP_SET_OAEP,
390 CKM_PBA_SHA1_WITH_SHA1_HMAC,
391 "KEY_WRAP_LYNKS",
392 "KEY_WRAP_SET_OAEP");
393ENUM_NEXT(ck_mech_names, CKM_SKIPJACK_KEY_GEN, CKM_SKIPJACK_RELAYX,
394 CKM_KEY_WRAP_SET_OAEP,
395 "SKIPJACK_KEY_GEN",
396 "SKIPJACK_ECB64",
397 "SKIPJACK_CBC64",
398 "SKIPJACK_OFB64",
399 "SKIPJACK_CFB64",
400 "SKIPJACK_CFB32",
401 "SKIPJACK_CFB16",
402 "SKIPJACK_CFB8",
403 "SKIPJACK_WRAP",
404 "SKIPJACK_PRIVATE_WRAP",
405 "SKIPJACK_RELAYX");
406ENUM_NEXT(ck_mech_names, CKM_KEA_KEY_PAIR_GEN, CKM_KEA_KEY_DERIVE,
407 CKM_SKIPJACK_RELAYX,
408 "KEA_KEY_PAIR_GEN",
409 "KEA_KEY_DERIVE");
410ENUM_NEXT(ck_mech_names, CKM_FORTEZZA_TIMESTAMP, CKM_FORTEZZA_TIMESTAMP,
411 CKM_KEA_KEY_DERIVE,
412 "FORTEZZA_TIMESTAMP");
413ENUM_NEXT(ck_mech_names, CKM_BATON_KEY_GEN, CKM_BATON_WRAP,
414 CKM_FORTEZZA_TIMESTAMP,
415 "BATON_KEY_GEN",
416 "BATON_ECB128",
417 "BATON_ECB96",
418 "BATON_CBC128",
419 "BATON_COUNTER",
420 "BATON_SHUFFLE",
421 "BATON_WRAP");
422ENUM_NEXT(ck_mech_names, CKM_ECDSA_KEY_PAIR_GEN, CKM_ECDSA_SHA1,
423 CKM_BATON_WRAP,
424 "ECDSA_KEY_PAIR_GEN",
425 "ECDSA",
426 "ECDSA_SHA1");
427ENUM_NEXT(ck_mech_names, CKM_ECDH1_DERIVE, CKM_ECMQV_DERIVE,
428 CKM_ECDSA_SHA1,
429 "ECDH1_DERIVE",
430 "ECDH1_COFACTOR_DERIVE",
431 "ECMQV_DERIVE");
432ENUM_NEXT(ck_mech_names, CKM_JUNIPER_KEY_GEN, CKM_JUNIPER_WRAP,
433 CKM_ECMQV_DERIVE,
434 "JUNIPER_KEY_GEN",
435 "JUNIPER_ECB128",
436 "JUNIPER_CBC128",
437 "JUNIPER_COUNTER",
438 "JUNIPER_SHUFFLE",
439 "JUNIPER_WRAP");
440ENUM_NEXT(ck_mech_names, CKM_FASTHASH, CKM_FASTHASH,
441 CKM_JUNIPER_WRAP,
442 "FASTHASH");
443ENUM_NEXT(ck_mech_names, CKM_AES_KEY_GEN, CKM_AES_CBC_PAD,
444 CKM_FASTHASH,
445 "AES_KEY_GEN",
446 "AES_ECB",
447 "AES_CBC",
448 "AES_MAC",
449 "AES_MAC_GENERAL",
450 "AES_CBC_PAD");
451ENUM_NEXT(ck_mech_names, CKM_DSA_PARAMETER_GEN, CKM_X9_42_DH_PARAMETER_GEN,
452 CKM_AES_CBC_PAD,
453 "DSA_PARAMETER_GEN",
454 "DH_PKCS_PARAMETER_GEN",
455 "X9_42_DH_PARAMETER_GEN");
456ENUM_END(ck_mech_names, CKM_X9_42_DH_PARAMETER_GEN);
457
6a5020fc
TB
458
459ENUM_BEGIN(ck_attr_names, CKA_CLASS, CKA_LABEL,
460 "CLASS",
461 "TOKEN",
462 "PRIVATE",
463 "LABEL");
464ENUM_NEXT(ck_attr_names, CKA_APPLICATION, CKA_OBJECT_ID, CKA_LABEL,
465 "APPLICATION",
466 "VALUE",
467 "OBJECT_ID");
468ENUM_NEXT(ck_attr_names, CKA_CERTIFICATE_TYPE, CKA_HASH_OF_ISSUER_PUBLIC_KEY,
469 CKA_OBJECT_ID,
470 "CERTIFICATE_TYPE",
471 "ISSUER",
472 "SERIAL_NUMBER",
473 "AC_ISSUER",
474 "OWNER",
475 "ATTR_TYPES",
476 "TRUSTED",
477 "CERTIFICATE_CATEGORY",
478 "JAVA_MIDP_SECURITY_DOMAIN",
479 "URL",
480 "HASH_OF_SUBJECT_PUBLIC_KEY",
481 "HASH_OF_ISSUER_PUBLIC_KEY");
482ENUM_NEXT(ck_attr_names, CKA_CHECK_VALUE, CKA_CHECK_VALUE,
483 CKA_HASH_OF_ISSUER_PUBLIC_KEY,
484 "CHECK_VALUE");
485ENUM_NEXT(ck_attr_names, CKA_KEY_TYPE, CKA_DERIVE, CKA_CHECK_VALUE,
486 "KEY_TYPE",
487 "SUBJECT",
488 "ID",
489 "SENSITIVE",
490 "ENCRYPT",
491 "DECRYPT",
492 "WRAP",
493 "UNWRAP",
494 "SIGN",
495 "SIGN_RECOVER",
496 "VERIFY",
497 "VERIFY_RECOVER",
498 "DERIVE");
499ENUM_NEXT(ck_attr_names, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE,
500 "START_DATE",
501 "END_DATE");
502ENUM_NEXT(ck_attr_names, CKA_MODULUS, CKA_COEFFICIENT, CKA_END_DATE,
503 "MODULUS",
504 "MODULUS_BITS",
505 "PUBLIC_EXPONENT",
506 "PRIVATE_EXPONENT",
507 "PRIME_1",
508 "PRIME_2",
509 "EXPONENT_1",
510 "EXPONENT_2",
511 "COEFFICIENT");
512ENUM_NEXT(ck_attr_names, CKA_PRIME, CKA_SUB_PRIME_BITS, CKA_COEFFICIENT,
513 "PRIME",
514 "SUBPRIME",
515 "BASE",
516 "PRIME_BITS",
517 "SUB_PRIME_BITS");
518ENUM_NEXT(ck_attr_names, CKA_VALUE_BITS, CKA_KEY_GEN_MECHANISM,
519 CKA_SUB_PRIME_BITS,
520 "VALUE_BITS",
521 "VALUE_LEN",
522 "EXTRACTABLE",
523 "LOCAL",
524 "NEVER_EXTRACTABLE",
525 "ALWAYS_SENSITIVE",
526 "KEY_GEN_MECHANISM");
527ENUM_NEXT(ck_attr_names, CKA_MODIFIABLE, CKA_MODIFIABLE, CKA_KEY_GEN_MECHANISM,
528 "MODIFIABLE");
529ENUM_NEXT(ck_attr_names, CKA_EC_PARAMS, CKA_EC_POINT, CKA_MODIFIABLE,
530 "EC_PARAMS",
531 "EC_POINT");
532ENUM_NEXT(ck_attr_names, CKA_SECONDARY_AUTH, CKA_ALWAYS_AUTHENTICATE,
533 CKA_EC_POINT,
534 "SECONDARY_AUTH",
535 "AUTH_PIN_FLAGS",
536 "ALWAYS_AUTHENTICATE");
537ENUM_NEXT(ck_attr_names, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_WITH_TRUSTED,
538 CKA_ALWAYS_AUTHENTICATE,
539 "WRAP_WITH_TRUSTED");
540ENUM_NEXT(ck_attr_names, CKA_HW_FEATURE_TYPE, CKA_HAS_RESET,
541 CKA_WRAP_WITH_TRUSTED,
542 "HW_FEATURE_TYPE",
543 "RESET_ON_INIT",
544 "HAS_RESET");
545ENUM_NEXT(ck_attr_names, CKA_PIXEL_X, CKA_BITS_PER_PIXEL, CKA_HAS_RESET,
546 "PIXEL_X",
45c8399d 547 "PIXEL_Y",
6a5020fc
TB
548 "RESOLUTION",
549 "CHAR_ROWS",
550 "CHAR_COLUMNS",
551 "COLOR",
552 "BITS_PER_PIXEL");
553ENUM_NEXT(ck_attr_names, CKA_CHAR_SETS, CKA_MIME_TYPES, CKA_BITS_PER_PIXEL,
554 "CHAR_SETS",
555 "ENCODING_METHODS",
556 "MIME_TYPES");
557ENUM_NEXT(ck_attr_names, CKA_MECHANISM_TYPE, CKA_SUPPORTED_CMS_ATTRIBUTES,
558 CKA_MIME_TYPES,
559 "MECHANISM_TYPE",
560 "REQUIRED_CMS_ATTRIBUTES",
561 "DEFAULT_CMS_ATTRIBUTES",
562 "SUPPORTED_CMS_ATTRIBUTES");
563ENUM_NEXT(ck_attr_names, CKA_WRAP_TEMPLATE, CKA_UNWRAP_TEMPLATE,
564 CKA_SUPPORTED_CMS_ATTRIBUTES,
565 "WRAP_TEMPLATE",
566 "UNWRAP_TEMPLATE");
567ENUM_NEXT(ck_attr_names, CKA_ALLOWED_MECHANISMS, CKA_ALLOWED_MECHANISMS,
568 CKA_UNWRAP_TEMPLATE,
569 "ALLOWED_MECHANISMS");
570ENUM_END(ck_attr_names, CKA_ALLOWED_MECHANISMS);
571/* the values in an enum_name_t are stored as int, thus CKA_VENDOR_DEFINED
572 * will overflow and is thus not defined here */
573
574
575
34454dc3
MW
576/**
577 * Private data of an pkcs11_library_t object.
578 */
579struct private_pkcs11_library_t {
580
581 /**
582 * Public pkcs11_library_t interface.
583 */
584 pkcs11_library_t public;
585
586 /**
587 * dlopen() handle
588 */
589 void *handle;
71151d3c
MW
590
591 /**
592 * Name as passed to the constructor
593 */
594 char *name;
59df2d2a
MW
595
596 /**
597 * Supported feature set
598 */
599 pkcs11_feature_t features;
34454dc3
MW
600};
601
71151d3c
MW
602METHOD(pkcs11_library_t, get_name, char*,
603 private_pkcs11_library_t *this)
604{
605 return this->name;
606}
607
59df2d2a
MW
608METHOD(pkcs11_library_t, get_features, pkcs11_feature_t,
609 private_pkcs11_library_t *this)
610{
611 return this->features;
612}
613
9baa41c5
MW
614/**
615 * Object enumerator
616 */
617typedef struct {
618 /* implements enumerator_t */
619 enumerator_t public;
620 /* session */
621 CK_SESSION_HANDLE session;
622 /* pkcs11 library */
623 pkcs11_library_t *lib;
f3bb1bd0 624 /* attributes to retrieve */
d007ce32 625 CK_ATTRIBUTE_PTR attr;
6537be9c
TB
626 /* copy of the original attributes provided by the caller */
627 CK_ATTRIBUTE_PTR orig_attr;
d007ce32
MW
628 /* number of attributes */
629 CK_ULONG count;
c1985251
TB
630 /* object handle in case of a single object */
631 CK_OBJECT_HANDLE object;
d007ce32
MW
632 /* currently allocated attributes, to free */
633 linked_list_t *freelist;
9baa41c5
MW
634} object_enumerator_t;
635
d007ce32 636/**
6537be9c
TB
637 * Keep a copy of the original attribute values so we can restore them while
638 * enumerating e.g. if an attribute was unavailable for a particular object.
639 */
640static void init_attrs(object_enumerator_t *this)
641{
642 int i;
643
644 this->orig_attr = calloc(this->count, sizeof(CK_ATTRIBUTE));
645 for (i = 0; i < this->count; i++)
646 {
647 this->orig_attr[i] = this->attr[i];
648 }
649}
650
651/**
652 * Free contents of allocated attributes and reset them to their original
653 * values.
d007ce32
MW
654 */
655static void free_attrs(object_enumerator_t *this)
656{
657 CK_ATTRIBUTE_PTR attr;
6537be9c 658 int i;
d007ce32
MW
659
660 while (this->freelist->remove_last(this->freelist, (void**)&attr) == SUCCESS)
661 {
662 free(attr->pValue);
6537be9c
TB
663 }
664 for (i = 0; i < this->count; i++)
665 {
666 this->attr[i] = this->orig_attr[i];
d007ce32
MW
667 }
668}
669
4aab3153 670/**
b3ab7a48 671 * CKA_EC_POINT is encoded as ASN.1 octet string, we can't handle that and
4aab3153
TB
672 * some tokens actually return them even unwrapped.
673 *
674 * Because ASN1_OCTET_STRING is 0x04 and uncompressed EC_POINTs also begin with
675 * 0x04 (compressed ones with 0x02 or 0x03) there will be an attempt to parse
676 * unwrapped uncompressed EC_POINTs. This will fail in most cases as the length
677 * will not be correct, however, there is a small chance that the key's first
678 * byte denotes the correct length. Checking the first byte of the key should
679 * further reduce the risk of false positives, though.
680 *
681 * The original memory is freed if the value is unwrapped.
682 */
683static void unwrap_ec_point(chunk_t *data)
684{
685 chunk_t wrapped, unwrapped;
686
687 wrapped = unwrapped = *data;
688 if (asn1_unwrap(&unwrapped, &unwrapped) == ASN1_OCTET_STRING &&
689 unwrapped.len && unwrapped.ptr[0] >= 0x02 && unwrapped.ptr[0] <= 0x04)
690 {
691 *data = chunk_clone(unwrapped);
692 free(wrapped.ptr);
693 }
694}
695
d007ce32
MW
696/**
697 * Get attributes for a given object during enumeration
698 */
699static bool get_attributes(object_enumerator_t *this, CK_OBJECT_HANDLE object)
700{
4aab3153 701 chunk_t data;
d007ce32
MW
702 CK_RV rv;
703 int i;
704
705 free_attrs(this);
706
707 /* get length of objects first */
708 rv = this->lib->f->C_GetAttributeValue(this->session, object,
709 this->attr, this->count);
6537be9c
TB
710 if (rv != CKR_OK &&
711 rv != CKR_ATTRIBUTE_SENSITIVE &&
712 rv != CKR_ATTRIBUTE_TYPE_INVALID)
d007ce32
MW
713 {
714 DBG1(DBG_CFG, "C_GetAttributeValue(NULL) error: %N", ck_rv_names, rv);
715 return FALSE;
716 }
717 /* allocate required chunks */
718 for (i = 0; i < this->count; i++)
719 {
6537be9c
TB
720 if (this->attr[i].ulValueLen == CK_UNAVAILABLE_INFORMATION)
721 { /* reset this unavailable attribute before the next call */
722 this->attr[i] = this->orig_attr[i];
723 }
724 else if (this->attr[i].pValue == NULL &&
725 this->attr[i].ulValueLen != 0)
d007ce32
MW
726 {
727 this->attr[i].pValue = malloc(this->attr[i].ulValueLen);
728 this->freelist->insert_last(this->freelist, &this->attr[i]);
729 }
730 }
731 /* get the data */
732 rv = this->lib->f->C_GetAttributeValue(this->session, object,
733 this->attr, this->count);
6537be9c
TB
734 if (rv != CKR_OK &&
735 rv != CKR_ATTRIBUTE_SENSITIVE &&
736 rv != CKR_ATTRIBUTE_TYPE_INVALID)
d007ce32 737 {
df241121 738 DBG1(DBG_CFG, "C_GetAttributeValue() error: %N", ck_rv_names, rv);
d007ce32
MW
739 return FALSE;
740 }
4aab3153
TB
741 for (i = 0; i < this->count; i++)
742 {
743 if (this->attr[i].type == CKA_EC_POINT)
744 {
745 data = chunk_create(this->attr[i].pValue, this->attr[i].ulValueLen);
746 unwrap_ec_point(&data);
747 this->attr[i].pValue = data.ptr;
748 this->attr[i].ulValueLen = data.len;
749 }
750 }
d007ce32
MW
751 return TRUE;
752}
753
9baa41c5 754METHOD(enumerator_t, object_enumerate, bool,
95a63bf2 755 object_enumerator_t *this, va_list args)
9baa41c5 756{
95a63bf2 757 CK_OBJECT_HANDLE object, *out;
9baa41c5
MW
758 CK_ULONG found;
759 CK_RV rv;
760
95a63bf2
TB
761 VA_ARGS_VGET(args, out);
762
c1985251 763 if (!this->object)
9baa41c5 764 {
c1985251
TB
765 rv = this->lib->f->C_FindObjects(this->session, &object, 1, &found);
766 if (rv != CKR_OK)
767 {
768 DBG1(DBG_CFG, "C_FindObjects() failed: %N", ck_rv_names, rv);
769 return FALSE;
770 }
771 }
772 else
773 {
774 object = this->object;
775 found = 1;
9baa41c5
MW
776 }
777 if (found)
778 {
d007ce32
MW
779 if (this->attr)
780 {
781 if (!get_attributes(this, object))
782 {
783 return FALSE;
784 }
785 }
c1985251
TB
786 if (out)
787 {
788 *out = object;
789 }
9baa41c5
MW
790 return TRUE;
791 }
792 return FALSE;
793}
794
795METHOD(enumerator_t, object_destroy, void,
796 object_enumerator_t *this)
797{
c1985251
TB
798 if (!this->object)
799 {
800 this->lib->f->C_FindObjectsFinal(this->session);
801 }
d007ce32
MW
802 free_attrs(this);
803 this->freelist->destroy(this->freelist);
6537be9c 804 free(this->orig_attr);
9baa41c5
MW
805 free(this);
806}
807
808METHOD(pkcs11_library_t, create_object_enumerator, enumerator_t*,
809 private_pkcs11_library_t *this, CK_SESSION_HANDLE session,
d007ce32
MW
810 CK_ATTRIBUTE_PTR tmpl, CK_ULONG tcount,
811 CK_ATTRIBUTE_PTR attr, CK_ULONG acount)
9baa41c5
MW
812{
813 object_enumerator_t *enumerator;
814 CK_RV rv;
815
d007ce32 816 rv = this->public.f->C_FindObjectsInit(session, tmpl, tcount);
9baa41c5
MW
817 if (rv != CKR_OK)
818 {
819 DBG1(DBG_CFG, "C_FindObjectsInit() failed: %N", ck_rv_names, rv);
820 return enumerator_create_empty();
821 }
822
823 INIT(enumerator,
824 .public = {
95a63bf2
TB
825 .enumerate = enumerator_enumerate_default,
826 .venumerate = _object_enumerate,
9baa41c5
MW
827 .destroy = _object_destroy,
828 },
829 .session = session,
830 .lib = &this->public,
d007ce32
MW
831 .attr = attr,
832 .count = acount,
833 .freelist = linked_list_create(),
9baa41c5 834 );
6537be9c 835 init_attrs(enumerator);
9baa41c5
MW
836 return &enumerator->public;
837}
838
c1985251
TB
839METHOD(pkcs11_library_t, create_object_attr_enumerator, enumerator_t*,
840 private_pkcs11_library_t *this, CK_SESSION_HANDLE session,
841 CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR attr, CK_ULONG count)
842{
843 object_enumerator_t *enumerator;
844
845 INIT(enumerator,
846 .public = {
95a63bf2
TB
847 .enumerate = enumerator_enumerate_default,
848 .venumerate = _object_enumerate,
c1985251
TB
849 .destroy = _object_destroy,
850 },
851 .session = session,
852 .lib = &this->public,
853 .attr = attr,
854 .count = count,
855 .object = object,
856 .freelist = linked_list_create(),
857 );
6537be9c 858 init_attrs(enumerator);
c1985251
TB
859 return &enumerator->public;
860}
861
5a27bf8a
MW
862/**
863 * Enumerator over mechanisms
864 */
865typedef struct {
866 /* implements enumerator_t */
867 enumerator_t public;
868 /* PKCS#11 library */
869 pkcs11_library_t *lib;
870 /* slot of token */
871 CK_SLOT_ID slot;
872 /* mechanism type list */
873 CK_MECHANISM_TYPE_PTR mechs;
874 /* number of mechanism types */
875 CK_ULONG count;
876 /* current mechanism */
877 CK_ULONG current;
878} mechanism_enumerator_t;
879
880METHOD(enumerator_t, enumerate_mech, bool,
95a63bf2 881 mechanism_enumerator_t *this, va_list args)
5a27bf8a 882{
95a63bf2
TB
883 CK_MECHANISM_INFO *info;
884 CK_MECHANISM_TYPE *type;
5a27bf8a
MW
885 CK_RV rv;
886
95a63bf2
TB
887 VA_ARGS_VGET(args, type, info);
888
5a27bf8a
MW
889 if (this->current >= this->count)
890 {
891 return FALSE;
892 }
893 if (info)
894 {
895 rv = this->lib->f->C_GetMechanismInfo(this->slot,
896 this->mechs[this->current], info);
897 if (rv != CKR_OK)
898 {
899 DBG1(DBG_CFG, "C_GetMechanismInfo() failed: %N", ck_rv_names, rv);
900 return FALSE;
901 }
902 }
903 *type = this->mechs[this->current++];
904 return TRUE;
905}
906
907METHOD(enumerator_t, destroy_mech, void,
908 mechanism_enumerator_t *this)
909{
910 free(this->mechs);
911 free(this);
912}
913
914METHOD(pkcs11_library_t, create_mechanism_enumerator, enumerator_t*,
915 private_pkcs11_library_t *this, CK_SLOT_ID slot)
916{
917 mechanism_enumerator_t *enumerator;
918 CK_RV rv;
919
920 INIT(enumerator,
921 .public = {
95a63bf2
TB
922 .enumerate = enumerator_enumerate_default,
923 .venumerate = _enumerate_mech,
5a27bf8a
MW
924 .destroy = _destroy_mech,
925 },
926 .lib = &this->public,
927 .slot = slot,
928 );
929
930 rv = enumerator->lib->f->C_GetMechanismList(slot, NULL, &enumerator->count);
931 if (rv != CKR_OK)
932 {
933 DBG1(DBG_CFG, "C_GetMechanismList() failed: %N", ck_rv_names, rv);
934 free(enumerator);
935 return enumerator_create_empty();
936 }
937 enumerator->mechs = malloc(sizeof(CK_MECHANISM_TYPE) * enumerator->count);
826b4232 938 rv = enumerator->lib->f->C_GetMechanismList(slot, enumerator->mechs,
939 &enumerator->count);
5a27bf8a
MW
940 if (rv != CKR_OK)
941 {
942 DBG1(DBG_CFG, "C_GetMechanismList() failed: %N", ck_rv_names, rv);
943 destroy_mech(enumerator);
944 return enumerator_create_empty();
945 }
946 return &enumerator->public;
947}
948
85311065
TB
949METHOD(pkcs11_library_t, get_ck_attribute, bool,
950 private_pkcs11_library_t *this, CK_SESSION_HANDLE session,
951 CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_TYPE type, chunk_t *data)
952{
953 CK_ATTRIBUTE attr = { type, NULL, 0 };
954 CK_RV rv;
955 rv = this->public.f->C_GetAttributeValue(session, obj, &attr, 1);
956 if (rv != CKR_OK)
957 {
958 DBG1(DBG_CFG, "C_GetAttributeValue(%N) error: %N", ck_attr_names, type,
959 ck_rv_names, rv);
960 return FALSE;
961 }
962 *data = chunk_alloc(attr.ulValueLen);
963 attr.pValue = data->ptr;
964 rv = this->public.f->C_GetAttributeValue(session, obj, &attr, 1);
965 if (rv != CKR_OK)
966 {
967 DBG1(DBG_CFG, "C_GetAttributeValue(%N) error: %N", ck_attr_names, type,
968 ck_rv_names, rv);
969 chunk_free(data);
970 return FALSE;
971 }
4aab3153
TB
972 if (attr.type == CKA_EC_POINT)
973 {
974 unwrap_ec_point(data);
975 }
85311065
TB
976 return TRUE;
977}
978
34454dc3
MW
979METHOD(pkcs11_library_t, destroy, void,
980 private_pkcs11_library_t *this)
981{
982 this->public.f->C_Finalize(NULL);
66033012 983 dlclose(this->handle);
ca1c2ee2 984 free(this->name);
34454dc3
MW
985 free(this);
986}
987
988/**
b3b0e57c 989 * See header
34454dc3 990 */
b3b0e57c 991void pkcs11_library_trim(char *str, int len)
34454dc3
MW
992{
993 int i;
994
b3b0e57c
MW
995 str[len - 1] = '\0';
996 for (i = len - 2; i > 0; i--)
34454dc3
MW
997 {
998 if (str[i] == ' ')
999 {
1000 str[i] = '\0';
1001 continue;
1002 }
1003 break;
1004 }
1005}
1006
50e1a710
MW
1007/**
1008 * Mutex creation callback
1009 */
1010static CK_RV CreateMutex(CK_VOID_PTR_PTR data)
1011{
ea900422 1012 *data = mutex_create(MUTEX_TYPE_RECURSIVE);
50e1a710
MW
1013 return CKR_OK;
1014}
1015
1016/**
1017 * Mutex destruction callback
1018 */
1019static CK_RV DestroyMutex(CK_VOID_PTR data)
1020{
1021 mutex_t *mutex = (mutex_t*)data;
1022
1023 mutex->destroy(mutex);
1024 return CKR_OK;
1025}
1026
1027/**
1028 * Mutex lock callback
1029 */
1030static CK_RV LockMutex(CK_VOID_PTR data)
1031{
1032 mutex_t *mutex = (mutex_t*)data;
1033
1034 mutex->lock(mutex);
1035 return CKR_OK;
1036}
1037
1038/**
1039 * Mutex unlock callback
1040 */
1041static CK_RV UnlockMutex(CK_VOID_PTR data)
1042{
1043 mutex_t *mutex = (mutex_t*)data;
1044
1045 mutex->unlock(mutex);
1046 return CKR_OK;
1047}
1048
59df2d2a
MW
1049/**
1050 * Check if the library has at least a given cryptoki version
1051 */
1052static bool has_version(CK_INFO *info, int major, int minor)
1053{
1054 return info->cryptokiVersion.major > major ||
1055 (info->cryptokiVersion.major == major &&
1056 info->cryptokiVersion.minor >= minor);
1057}
1058
1059/**
1060 * Check for optional PKCS#11 library functionality
1061 */
1062static void check_features(private_pkcs11_library_t *this, CK_INFO *info)
1063{
1064 if (has_version(info, 2, 20))
1065 {
b78ca4b0 1066 this->features |= PKCS11_ALWAYS_AUTH_KEYS;
59df2d2a
MW
1067 }
1068}
1069
34454dc3
MW
1070/**
1071 * Initialize a PKCS#11 library
1072 */
9cda3992
MW
1073static bool initialize(private_pkcs11_library_t *this, char *name, char *file,
1074 bool os_locking)
34454dc3
MW
1075{
1076 CK_C_GetFunctionList pC_GetFunctionList;
1077 CK_INFO info;
1078 CK_RV rv;
cfa18d14 1079 static CK_C_INITIALIZE_ARGS args = {
50e1a710
MW
1080 .CreateMutex = CreateMutex,
1081 .DestroyMutex = DestroyMutex,
1082 .LockMutex = LockMutex,
1083 .UnlockMutex = UnlockMutex,
1084 };
cfa18d14
MW
1085 static CK_C_INITIALIZE_ARGS args_os = {
1086 .flags = CKF_OS_LOCKING_OK,
1087 };
34454dc3
MW
1088
1089 pC_GetFunctionList = dlsym(this->handle, "C_GetFunctionList");
1090 if (!pC_GetFunctionList)
1091 {
1092 DBG1(DBG_CFG, "C_GetFunctionList not found for '%s': %s", name, dlerror());
1093 return FALSE;
1094 }
1095 rv = pC_GetFunctionList(&this->public.f);
1096 if (rv != CKR_OK)
1097 {
a6456dd6
MW
1098 DBG1(DBG_CFG, "C_GetFunctionList() error for '%s': %N",
1099 name, ck_rv_names, rv);
34454dc3
MW
1100 return FALSE;
1101 }
9cda3992
MW
1102 if (os_locking)
1103 {
1104 rv = CKR_CANT_LOCK;
1105 }
1106 else
1107 {
1108 rv = this->public.f->C_Initialize(&args);
1109 }
50e1a710 1110 if (rv == CKR_CANT_LOCK)
9cda3992 1111 { /* fallback to OS locking */
cfa18d14
MW
1112 os_locking = TRUE;
1113 rv = this->public.f->C_Initialize(&args_os);
50e1a710 1114 }
34454dc3
MW
1115 if (rv != CKR_OK)
1116 {
a6456dd6
MW
1117 DBG1(DBG_CFG, "C_Initialize() error for '%s': %N",
1118 name, ck_rv_names, rv);
34454dc3
MW
1119 return FALSE;
1120 }
1121 rv = this->public.f->C_GetInfo(&info);
1122 if (rv != CKR_OK)
1123 {
a6456dd6
MW
1124 DBG1(DBG_CFG, "C_GetInfo() error for '%s': %N",
1125 name, ck_rv_names, rv);
34454dc3
MW
1126 this->public.f->C_Finalize(NULL);
1127 return FALSE;
1128 }
1129
b3b0e57c
MW
1130 pkcs11_library_trim(info.manufacturerID,
1131 strnlen(info.manufacturerID, sizeof(info.manufacturerID)));
1132 pkcs11_library_trim(info.libraryDescription,
1133 strnlen(info.libraryDescription, sizeof(info.libraryDescription)));
34454dc3
MW
1134
1135 DBG1(DBG_CFG, "loaded PKCS#11 v%d.%d library '%s' (%s)",
1136 info.cryptokiVersion.major, info.cryptokiVersion.minor, name, file);
b3b0e57c
MW
1137 DBG1(DBG_CFG, " %s: %s v%d.%d",
1138 info.manufacturerID, info.libraryDescription,
34454dc3 1139 info.libraryVersion.major, info.libraryVersion.minor);
cfa18d14 1140 if (os_locking)
50e1a710
MW
1141 {
1142 DBG1(DBG_CFG, " uses OS locking functions");
1143 }
59df2d2a
MW
1144
1145 check_features(this, &info);
34454dc3
MW
1146 return TRUE;
1147}
1148
1149/**
1150 * See header
1151 */
9cda3992 1152pkcs11_library_t *pkcs11_library_create(char *name, char *file, bool os_locking)
34454dc3
MW
1153{
1154 private_pkcs11_library_t *this;
1155
1156 INIT(this,
1157 .public = {
71151d3c 1158 .get_name = _get_name,
59df2d2a 1159 .get_features = _get_features,
9baa41c5 1160 .create_object_enumerator = _create_object_enumerator,
c1985251 1161 .create_object_attr_enumerator = _create_object_attr_enumerator,
5a27bf8a 1162 .create_mechanism_enumerator = _create_mechanism_enumerator,
85311065 1163 .get_ck_attribute = _get_ck_attribute,
34454dc3
MW
1164 .destroy = _destroy,
1165 },
ca1c2ee2 1166 .name = strdup(name),
34454dc3
MW
1167 .handle = dlopen(file, RTLD_LAZY),
1168 );
1169
1170 if (!this->handle)
1171 {
1172 DBG1(DBG_CFG, "opening PKCS#11 library failed: %s", dlerror());
1173 free(this);
1174 return NULL;
1175 }
1176
9cda3992 1177 if (!initialize(this, name, file, os_locking))
34454dc3
MW
1178 {
1179 dlclose(this->handle);
1180 free(this);
1181 return NULL;
1182 }
1183
1184 return &this->public;
1185}