1 /* Support of smartcards and cryptotokens
2 * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
3 * Copyright (C) 2004 David Buechi, Michael Meier
4 * Zuercher Hochschule Winterthur, Switzerland
6 * Copyright (C) 2005 Michael Joosten
8 * Copyright (C) 2005 Andreas Steffen
9 * Hochschule für Technik Rapperswil, Switzerland
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * RCSID $Id: smartcard.c,v 1.41 2006/01/04 21:03:52 as Exp $
33 #include <ipsec_policy.h>
35 #include "constants.h"
38 #include "rsaref/unix.h"
39 #include "rsaref/pkcs11.h"
49 #include "smartcard.h"
53 #define DEFAULT_BASE 16
55 /* chained list of smartcard records */
56 static smartcard_t
*smartcards
= NULL
;
58 /* number of generated sc objects */
59 static int sc_number
= 0;
61 const smartcard_t empty_sc
= {
64 { CERT_NONE
, {NULL
} }, /* last_cert */
70 { NULL
, 0 } , /* pin */
73 FALSE
, /* session_opened */
74 FALSE
, /* logged_in */
79 #ifdef SMARTCARD /* compile with smartcard support */
81 #define SCX_MAGIC 0xd00bed00
83 struct scx_pkcs11_module
{
88 typedef struct scx_pkcs11_module scx_pkcs11_module_t
;
90 /* PKCS #11 cryptoki context */
91 static bool scx_initialized
= FALSE
;
92 static scx_pkcs11_module_t
*pkcs11_module
= NULL_PTR
;
93 static CK_FUNCTION_LIST_PTR pkcs11_functions
= NULL_PTR
;
95 /* crytoki v2.11 - return values of PKCS #11 functions*/
97 static const char *const pkcs11_return_name
[] = {
101 "CKR_SLOT_ID_INVALID",
104 "CKR_FUNCTION_FAILED",
107 "CKR_NEED_TO_CREATE_THREADS",
111 static const char *const pkcs11_return_name_10
[] = {
112 "CKR_ATTRIBUTE_READ_ONLY",
113 "CKR_ATTRIBUTE_SENSITIVE",
114 "CKR_ATTRIBUTE_TYPE_INVALID",
115 "CKR_ATTRIBUTE_VALUE_INVALID"
118 static const char *const pkcs11_return_name_20
[] = {
123 static const char *const pkcs11_return_name_30
[] = {
129 static const char *const pkcs11_return_name_40
[] = {
130 "CKR_ENCRYPTED_DATA_INVALID",
131 "CKR_ENCRYPTED_DATA_LEN_RANGE"
134 static const char *const pkcs11_return_name_50
[] = {
135 "CKR_FUNCTION_CANCELED",
136 "CKR_FUNCTION_NOT_PARALLEL",
137 "CKR_0x52_UNDEFINED",
138 "CKR_0x53_UNDEFINED",
139 "CKR_FUNCTION_NOT_SUPPORTED"
142 static const char *const pkcs11_return_name_60
[] = {
143 "CKR_KEY_HANDLE_INVALID",
145 "CKR_KEY_SIZE_RANGE",
146 "CKR_KEY_TYPE_INCONSISTENT",
147 "CKR_KEY_NOT_NEEDED",
150 "CKR_KEY_INDIGESTIBLE",
151 "CKR_KEY_FUNCTION_NOT_PERMITTED",
152 "CKR_KEY_NOT_WRAPPABLE",
153 "CKR_KEY_UNEXTRACTABLE"
156 static const char *const pkcs11_return_name_70
[] = {
157 "CKR_MECHANISM_INVALID",
158 "CKR_MECHANISM_PARAM_INVALID"
161 static const char *const pkcs11_return_name_80
[] = {
162 "CKR_OBJECT_HANDLE_INVALID"
165 static const char *const pkcs11_return_name_90
[] = {
166 "CKR_OPERATION_ACTIVE",
167 "CKR_OPERATION_NOT_INITIALIZED"
170 static const char *const pkcs11_return_name_A0
[] = {
178 static const char *const pkcs11_return_name_B0
[] = {
179 "CKR_SESSION_CLOSED",
181 "CKR_0xB2_UNDEFINED",
182 "CKR_SESSION_HANDLE_INVALID",
183 "CKR_SESSION_PARALLEL_NOT_SUPPORTED",
184 "CKR_SESSION_READ_ONLY",
185 "CKR_SESSION_EXISTS",
186 "CKR_SESSION_READ_ONLY_EXISTS",
187 "CKR_SESSION_READ_WRITE_SO_EXISTS"
190 static const char *const pkcs11_return_name_C0
[] = {
191 "CKR_SIGNATURE_INVALID",
192 "CKR_SIGNATURE_LEN_RANGE"
195 static const char *const pkcs11_return_name_D0
[] = {
196 "CKR_TEMPLATE_INCOMPLETE",
197 "CKR_TEMPLATE_INCONSISTENT"
200 static const char *const pkcs11_return_name_E0
[] = {
201 "CKR_TOKEN_NOT_PRESENT",
202 "CKR_TOKEN_NOT_RECOGNIZED",
203 "CKR_TOKEN_WRITE_PROTECTED"
206 static const char *const pkcs11_return_name_F0
[] = {
207 "CKR_UNWRAPPING_KEY_HANDLE_INVALID",
208 "CKR_UNWRAPPING_KEY_SIZE_RANGE",
209 "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"
212 static const char *const pkcs11_return_name_100
[] = {
213 "CKR_USER_ALREADY_LOGGED_IN",
214 "CKR_USER_NOT_LOGGED_IN",
215 "CKR_USER_PIN_NOT_INITIALIZED",
216 "CKR_USER_TYPE_INVALID",
217 "CKR_USER_ANOTHER_ALREADY_LOGGED_IN",
218 "CKR_USER_TOO_MANY_TYPES"
221 static const char *const pkcs11_return_name_110
[] = {
222 "CKR_WRAPPED_KEY_INVALID",
223 "CKR_0x111_UNDEFINED",
224 "CKR_WRAPPED_KEY_LEN_RANGE",
225 "CKR_WRAPPING_KEY_HANDLE_INVALID",
226 "CKR_WRAPPING_KEY_SIZE_RANGE",
227 "CKR_WRAPPING_KEY_TYPE_INCONSISTENT"
230 static const char *const pkcs11_return_name_120
[] = {
231 "CKR_RANDOM_SEED_NOT_SUPPORTED",
235 static const char *const pkcs11_return_name_130
[] = {
236 "CKR_DOMAIN_PARAMS_INVALID"
239 static const char *const pkcs11_return_name_150
[] = {
240 "CKR_BUFFER_TOO_SMALL"
243 static const char *const pkcs11_return_name_160
[] = {
244 "CKR_SAVED_STATE_INVALID"
247 static const char *const pkcs11_return_name_170
[] = {
248 "CKR_INFORMATION_SENSITIVE"
251 static const char *const pkcs11_return_name_180
[] = {
252 "CKR_STATE_UNSAVEABLE"
255 static const char *const pkcs11_return_name_190
[] = {
256 "CKR_CRYPTOKI_NOT_INITIALIZED",
257 "CKR_CRYPTOKI_ALREADY_INITIALIZED"
260 static const char *const pkcs11_return_name_1A0
[] = {
262 "CKR_MUTEX_NOT_LOCKED"
265 static const char *const pkcs11_return_name_200
[] = {
266 "CKR_FUNCTION_REJECTED"
269 static const char *const pkcs11_return_name_vendor
[] = {
273 static enum_names pkcs11_return_names_vendor
=
274 { CKR_VENDOR_DEFINED
, CKR_VENDOR_DEFINED
275 , pkcs11_return_name_vendor
, NULL
};
277 static enum_names pkcs11_return_names_200
=
278 { CKR_FUNCTION_REJECTED
, CKR_FUNCTION_REJECTED
279 , pkcs11_return_name_200
, &pkcs11_return_names_vendor
};
281 static enum_names pkcs11_return_names_1A0
=
282 { CKR_MUTEX_BAD
, CKR_MUTEX_NOT_LOCKED
283 , pkcs11_return_name_1A0
, &pkcs11_return_names_200
};
285 static enum_names pkcs11_return_names_190
=
286 { CKR_CRYPTOKI_NOT_INITIALIZED
, CKR_CRYPTOKI_ALREADY_INITIALIZED
287 , pkcs11_return_name_190
, &pkcs11_return_names_1A0
};
289 static enum_names pkcs11_return_names_180
=
290 { CKR_STATE_UNSAVEABLE
, CKR_STATE_UNSAVEABLE
291 , pkcs11_return_name_180
, &pkcs11_return_names_190
};
293 static enum_names pkcs11_return_names_170
=
294 { CKR_INFORMATION_SENSITIVE
, CKR_INFORMATION_SENSITIVE
295 , pkcs11_return_name_170
, &pkcs11_return_names_180
};
297 static enum_names pkcs11_return_names_160
=
298 { CKR_SAVED_STATE_INVALID
, CKR_SAVED_STATE_INVALID
299 , pkcs11_return_name_160
, &pkcs11_return_names_170
};
301 static enum_names pkcs11_return_names_150
=
302 { CKR_BUFFER_TOO_SMALL
, CKR_BUFFER_TOO_SMALL
303 , pkcs11_return_name_150
, &pkcs11_return_names_160
};
305 static enum_names pkcs11_return_names_130
=
306 { CKR_DOMAIN_PARAMS_INVALID
, CKR_DOMAIN_PARAMS_INVALID
307 , pkcs11_return_name_130
, &pkcs11_return_names_150
};
309 static enum_names pkcs11_return_names_120
=
310 { CKR_RANDOM_SEED_NOT_SUPPORTED
, CKR_RANDOM_NO_RNG
311 , pkcs11_return_name_120
, &pkcs11_return_names_130
};
313 static enum_names pkcs11_return_names_110
=
314 { CKR_WRAPPED_KEY_INVALID
, CKR_WRAPPING_KEY_TYPE_INCONSISTENT
315 , pkcs11_return_name_110
, &pkcs11_return_names_120
};
317 static enum_names pkcs11_return_names_100
=
318 { CKR_USER_ALREADY_LOGGED_IN
, CKR_USER_TOO_MANY_TYPES
319 , pkcs11_return_name_100
, &pkcs11_return_names_110
};
321 static enum_names pkcs11_return_names_F0
=
322 { CKR_UNWRAPPING_KEY_HANDLE_INVALID
, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
323 , pkcs11_return_name_F0
, &pkcs11_return_names_100
};
325 static enum_names pkcs11_return_names_E0
=
326 { CKR_TOKEN_NOT_PRESENT
, CKR_TOKEN_WRITE_PROTECTED
327 , pkcs11_return_name_E0
, &pkcs11_return_names_F0
};
329 static enum_names pkcs11_return_names_D0
=
330 { CKR_TEMPLATE_INCOMPLETE
, CKR_TEMPLATE_INCONSISTENT
331 , pkcs11_return_name_D0
,&pkcs11_return_names_E0
};
333 static enum_names pkcs11_return_names_C0
=
334 { CKR_SIGNATURE_INVALID
, CKR_SIGNATURE_LEN_RANGE
335 , pkcs11_return_name_C0
, &pkcs11_return_names_D0
};
337 static enum_names pkcs11_return_names_B0
=
338 { CKR_SESSION_CLOSED
, CKR_SESSION_READ_WRITE_SO_EXISTS
339 , pkcs11_return_name_B0
, &pkcs11_return_names_C0
};
341 static enum_names pkcs11_return_names_A0
=
342 { CKR_PIN_INCORRECT
, CKR_PIN_LOCKED
343 , pkcs11_return_name_A0
, &pkcs11_return_names_B0
};
345 static enum_names pkcs11_return_names_90
=
346 { CKR_OPERATION_ACTIVE
, CKR_OPERATION_NOT_INITIALIZED
347 , pkcs11_return_name_90
, &pkcs11_return_names_A0
};
349 static enum_names pkcs11_return_names_80
=
350 { CKR_OBJECT_HANDLE_INVALID
, CKR_OBJECT_HANDLE_INVALID
351 , pkcs11_return_name_80
, &pkcs11_return_names_90
};
353 static enum_names pkcs11_return_names_70
=
354 { CKR_MECHANISM_INVALID
, CKR_MECHANISM_PARAM_INVALID
355 , pkcs11_return_name_70
, &pkcs11_return_names_80
};
357 static enum_names pkcs11_return_names_60
=
358 { CKR_KEY_HANDLE_INVALID
, CKR_KEY_UNEXTRACTABLE
359 , pkcs11_return_name_60
, &pkcs11_return_names_70
};
361 static enum_names pkcs11_return_names_50
=
362 { CKR_FUNCTION_CANCELED
, CKR_FUNCTION_NOT_SUPPORTED
363 , pkcs11_return_name_50
, &pkcs11_return_names_60
};
365 static enum_names pkcs11_return_names_40
=
366 { CKR_ENCRYPTED_DATA_INVALID
, CKR_ENCRYPTED_DATA_LEN_RANGE
367 , pkcs11_return_name_40
, &pkcs11_return_names_50
};
369 static enum_names pkcs11_return_names_30
=
370 { CKR_DEVICE_ERROR
, CKR_DEVICE_REMOVED
371 , pkcs11_return_name_30
, &pkcs11_return_names_40
};
373 static enum_names pkcs11_return_names_20
=
374 { CKR_DATA_INVALID
, CKR_DATA_LEN_RANGE
375 , pkcs11_return_name_20
, &pkcs11_return_names_30
};
377 static enum_names pkcs11_return_names_10
=
378 { CKR_ATTRIBUTE_READ_ONLY
, CKR_ATTRIBUTE_VALUE_INVALID
379 , pkcs11_return_name_10
, &pkcs11_return_names_20
};
381 static enum_names pkcs11_return_names
=
382 { CKR_OK
, CKR_CANT_LOCK
383 , pkcs11_return_name
, &pkcs11_return_names_10
};
386 * Unload a PKCS#11 module.
387 * The calling application is responsible for cleaning up
388 * and calling C_Finalize()
391 scx_unload_pkcs11_module(scx_pkcs11_module_t
*mod
)
393 if (!mod
|| mod
->_magic
!= SCX_MAGIC
)
394 return CKR_ARGUMENTS_BAD
;
396 if (dlclose(mod
->handle
) < 0)
397 return CKR_FUNCTION_FAILED
;
399 memset(mod
, 0, sizeof(*mod
));
404 static scx_pkcs11_module_t
*
405 scx_load_pkcs11_module(const char *name
, CK_FUNCTION_LIST_PTR_PTR funcs
)
407 CK_RV (*c_get_function_list
)(CK_FUNCTION_LIST_PTR_PTR
);
408 scx_pkcs11_module_t
*mod
;
412 if (name
== NULL
|| *name
== '\0')
415 /* Try to load PKCS#11 library module*/
416 handle
= dlopen(name
, RTLD_NOW
);
420 mod
= alloc_thing(scx_pkcs11_module_t
, "scx_pkcs11_module");
421 mod
->_magic
= SCX_MAGIC
;
422 mod
->handle
= handle
;
424 /* Get the list of function pointers */
425 c_get_function_list
= (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR
))
426 dlsym(mod
->handle
, "C_GetFunctionList");
427 if (!c_get_function_list
)
430 rv
= c_get_function_list(funcs
);
434 failed
: scx_unload_pkcs11_module(mod
);
439 * retrieve a certificate object
442 scx_find_cert_object(CK_SESSION_HANDLE session
, CK_OBJECT_HANDLE object
443 , smartcard_t
*sc
, cert_t
*cert
)
445 size_t hex_len
, label_len
;
446 u_char
*hex_id
= NULL
;
448 x509cert_t
*x509cert
;
450 CK_ATTRIBUTE attr
[] = {
451 { CKA_ID
, NULL_PTR
, 0L },
452 { CKA_LABEL
, NULL_PTR
, 0L },
453 { CKA_VALUE
, NULL_PTR
, 0L }
456 /* initialize the return argument */
459 /* get the length of the attributes first */
460 CK_RV rv
= pkcs11_functions
->C_GetAttributeValue(session
, object
, attr
, 3);
463 plog("couldn't read the attribute sizes: %s"
464 , enum_show(&pkcs11_return_names
, rv
));
470 hex_id
= alloc_bytes(attr
[0].ulValueLen
, "hex id");
471 hex_len
= attr
[0].ulValueLen
;
472 sc
->label
= alloc_bytes(attr
[1].ulValueLen
+ 1, "sc label");
473 label_len
= attr
[1].ulValueLen
;
474 blob
.ptr
= alloc_bytes(attr
[2].ulValueLen
, "x509cert blob");
475 blob
.len
= attr
[2].ulValueLen
;
477 attr
[0].pValue
= hex_id
;
478 attr
[1].pValue
= sc
->label
;
479 attr
[2].pValue
= blob
.ptr
;
481 /* now get the attributes */
482 rv
= pkcs11_functions
->C_GetAttributeValue(session
, object
, attr
, 3);
485 plog("couldn't read the attributes: %s"
486 , enum_show(&pkcs11_return_names
, rv
));
495 /* convert id from hex to ASCII */
496 sc
->id
= alloc_bytes(2*hex_len
+ 1, " sc id");
497 datatot(hex_id
, hex_len
, 16, sc
->id
, 2*hex_len
+ 1);
500 /* safeguard in case the label is not null terminated */
501 sc
->label
[label_len
] = '\0';
503 /* parse the retrieved cert */
504 x509cert
= alloc_thing(x509cert_t
, "x509cert");
505 *x509cert
= empty_x509cert
;
506 x509cert
->smartcard
= TRUE
;
508 if (!parse_x509cert(blob
, 0, x509cert
))
510 plog("failed to load cert from smartcard, error in X.509 certificate");
511 free_x509cert(x509cert
);
514 cert
->type
= CERT_X509_SIGNATURE
;
515 cert
->u
.x509
= x509cert
;
520 * search a given slot for PKCS#11 certificate objects
523 scx_find_cert_objects(CK_SLOT_ID slot
, CK_SESSION_HANDLE session
)
526 CK_OBJECT_CLASS
class = CKO_CERTIFICATE
;
527 CK_ATTRIBUTE attr
[] = {{ CKA_CLASS
, &class, sizeof(class) }};
529 rv
= pkcs11_functions
->C_FindObjectsInit(session
, attr
, 1);
532 plog("error in C_FindObjectsInit: %s"
533 , enum_show(&pkcs11_return_names
, rv
));
539 CK_OBJECT_HANDLE object
;
540 CK_ULONG obj_count
= 0;
546 rv
= pkcs11_functions
->C_FindObjects(session
, &object
, 1, &obj_count
);
549 plog("error in C_FindObjects: %s"
550 , enum_show(&pkcs11_return_names
, rv
));
554 /* no objects left */
558 /* create and initialize a new smartcard object */
559 sc
= alloc_thing(smartcard_t
, "smartcard");
561 sc
->any_slot
= FALSE
;
564 if (!scx_find_cert_object(session
, object
, sc
, &sc
->last_cert
))
570 DBG_log("found cert in %s with id: %s, label: '%s'"
571 , scx_print_slot(sc
, ""), sc
->id
, sc
->label
)
574 /* check validity of certificate */
575 cert
= sc
->last_cert
.u
.x509
;
576 valid_until
= cert
->notAfter
;
577 ugh
= check_validity(cert
, &valid_until
);
588 DBG_log(" certificate is valid")
594 /* put end entity and ca certificates into different chains */
596 add_authcert(cert
, AUTH_CA
);
599 add_x509_public_key(cert
, valid_until
, DAL_LOCAL
);
600 sc
->last_cert
.u
.x509
= add_x509cert(cert
);
603 share_cert(sc
->last_cert
);
604 time(&sc
->last_load
);
607 rv
= pkcs11_functions
->C_FindObjectsFinal(session
);
610 plog("error in C_FindObjectsFinal: %s"
611 , enum_show(&pkcs11_return_names
, rv
));
616 * search all slots for PKCS#11 certificate objects
619 scx_find_all_cert_objects(void)
622 CK_SLOT_ID_PTR slots
= NULL_PTR
;
623 CK_ULONG slot_count
= 0;
626 if (!scx_initialized
)
628 plog("pkcs11 module not initialized");
632 /* read size, always returns CKR_OK ! */
633 rv
= pkcs11_functions
->C_GetSlotList(FALSE
, NULL_PTR
, &slot_count
);
635 /* allocate memory for the slots */
636 slots
= (CK_SLOT_ID
*)alloc_bytes(slot_count
* sizeof(CK_SLOT_ID
), "slots");
638 rv
= pkcs11_functions
->C_GetSlotList(FALSE
, slots
, &slot_count
);
641 plog("error in C_GetSlotList: %s", enum_show(&pkcs11_return_names
, rv
));
646 /* look in every slot for certificate objects */
647 for (i
= 0; i
< slot_count
; i
++)
649 CK_SLOT_ID slot
= slots
[i
];
651 CK_SESSION_HANDLE session
;
653 rv
= pkcs11_functions
->C_GetSlotInfo(slot
, &info
);
657 plog("error in C_GetSlotInfo: %s"
658 , enum_show(&pkcs11_return_names
, rv
));
662 if (!(info
.flags
& CKF_TOKEN_PRESENT
))
664 plog("no token present in slot %lu", slot
);
668 rv
= pkcs11_functions
->C_OpenSession(slot
669 , CKF_SERIAL_SESSION
, NULL_PTR
, NULL_PTR
, &session
);
672 plog("failed to open a session on slot %lu: %s"
673 , slot
, enum_show(&pkcs11_return_names
, rv
));
677 DBG_log("pkcs11 session #%ld for searching slot %lu", session
, slot
)
679 scx_find_cert_objects(slot
, session
);
681 rv
= pkcs11_functions
->C_CloseSession(session
);
684 plog("error in C_CloseSession: %s"
685 , enum_show(&pkcs11_return_names
, rv
));
693 * load and initialize PKCS#11 cryptoki module
695 * init_args should be unused when we have a PKCS#11 compliant module,
696 * but NSS softoken breaks that API.
699 scx_init(const char* module
, const char *init_args
)
702 CK_C_INITIALIZE_ARGS args
= { .pReserved
= init_args
, };
707 plog("weird - pkcs11 module seems already to be initialized");
712 #ifdef PKCS11_DEFAULT_LIB
713 module
= PKCS11_DEFAULT_LIB
;
716 plog("no pkcs11 module defined");
721 DBG(DBG_CONTROL
| DBG_CRYPT
,
722 DBG_log("pkcs11 module '%s' loading...", module
)
724 pkcs11_module
= scx_load_pkcs11_module(module
, &pkcs11_functions
);
725 if (pkcs11_module
== NULL
)
727 plog("failed to load pkcs11 module '%s'", module
);
731 DBG(DBG_CONTROL
| DBG_CRYPT
,
732 DBG_log("pkcs11 module initializing...")
734 rv
= pkcs11_functions
->C_Initialize(init_args ?
&args
: NULL
);
737 plog("failed to initialize pkcs11 module: %s"
738 , enum_show(&pkcs11_return_names
, rv
));
742 scx_initialized
= TRUE
;
743 DBG(DBG_CONTROL
| DBG_CRYPT
,
744 DBG_log("pkcs11 module loaded and initialized")
747 scx_find_all_cert_objects();
752 * finalize and unload PKCS#11 cryptoki module
758 while (smartcards
!= NULL
)
760 scx_release(smartcards
);
763 if (pkcs11_functions
!= NULL_PTR
)
765 pkcs11_functions
->C_Finalize(NULL_PTR
);
766 pkcs11_functions
= NULL_PTR
;
769 if (pkcs11_module
!= NULL
)
771 scx_unload_pkcs11_module(pkcs11_module
);
772 pkcs11_module
= NULL
;
775 scx_initialized
= FALSE
;
776 DBG(DBG_CONTROL
| DBG_CRYPT
,
777 DBG_log("pkcs11 module finalized and unloaded")
783 * does a filename contain the token %smartcard?
786 scx_on_smartcard(const char *filename
)
788 return strncmp(filename
, SCX_TOKEN
, strlen(SCX_TOKEN
)) == 0;
793 * find a specific object on the smartcard
796 scx_pkcs11_find_object( CK_SESSION_HANDLE session
,
797 CK_OBJECT_HANDLE_PTR object
,
798 CK_OBJECT_CLASS
class,
804 CK_ULONG obj_count
= 0;
805 CK_ULONG attr_count
= 1;
807 CK_ATTRIBUTE attr
[] = {
808 { CKA_CLASS
, &class, sizeof(class) },
814 ttodata(id
, strlen(id
), 16, buf
, BUF_LEN
, &len
);
815 attr
[1].ulValueLen
= len
;
819 /* get info for certificate with id */
820 rv
= pkcs11_functions
->C_FindObjectsInit(session
, attr
, attr_count
);
823 plog("error in C_FindObjectsInit: %s"
824 , enum_show(&pkcs11_return_names
, rv
));
828 rv
= pkcs11_functions
->C_FindObjects(session
, object
, 1, &obj_count
);
831 plog("error in C_FindObjects: %s"
832 , enum_show(&pkcs11_return_names
, rv
));
836 rv
= pkcs11_functions
->C_FindObjectsFinal(session
);
839 plog("error in C_FindObjectsFinal: %s"
840 , enum_show(&pkcs11_return_names
, rv
));
844 return (obj_count
!= 0);
848 * check if a given certificate object id is found in a slot
851 scx_find_cert_id_in_slot(smartcard_t
*sc
, CK_SLOT_ID slot
)
853 CK_SESSION_HANDLE session
;
854 CK_OBJECT_HANDLE object
;
857 CK_RV rv
= pkcs11_functions
->C_GetSlotInfo(slot
, &info
);
861 plog("error in C_GetSlotInfo: %s"
862 , enum_show(&pkcs11_return_names
, rv
));
866 if (!(info
.flags
& CKF_TOKEN_PRESENT
))
868 plog("no token present in slot %lu", slot
);
872 rv
= pkcs11_functions
->C_OpenSession(slot
873 , CKF_SERIAL_SESSION
, NULL_PTR
, NULL_PTR
, &session
);
876 plog("failed to open a session on slot %lu: %s"
877 , slot
, enum_show(&pkcs11_return_names
, rv
));
881 DBG_log("pkcs11 session #%ld for searching slot %lu", session
, slot
)
884 /* check if there is a certificate on the card in the specified slot */
885 if (scx_pkcs11_find_object(session
, &object
, CKO_CERTIFICATE
, sc
->id
))
888 sc
->any_slot
= FALSE
;
889 sc
->session
= session
;
890 sc
->session_opened
= TRUE
;
894 rv
= pkcs11_functions
->C_CloseSession(session
);
897 plog("error in C_CloseSession: %s"
898 , enum_show(&pkcs11_return_names
, rv
));
905 * Connect to the smart card in the reader and select the correct slot
908 scx_establish_context(smartcard_t
*sc
)
911 bool id_found
= FALSE
;
913 if (!scx_initialized
)
915 plog("pkcs11 module not initialized");
919 if (sc
->session_opened
)
921 DBG(DBG_CONTROL
| DBG_CRYPT
,
922 DBG_log("pkcs11 session #%ld already open", sc
->session
)
928 id_found
= scx_find_cert_id_in_slot(sc
, sc
->slot
);
934 CK_SLOT_ID_PTR slots
= NULL_PTR
;
935 CK_ULONG slot_count
= 0;
938 /* read size, always returns CKR_OK ! */
939 rv
= pkcs11_functions
->C_GetSlotList(FALSE
, NULL_PTR
, &slot_count
);
941 /* allocate memory for the slots */
942 slots
= (CK_SLOT_ID
*)alloc_bytes(slot_count
* sizeof(CK_SLOT_ID
), "slots");
944 rv
= pkcs11_functions
->C_GetSlotList(FALSE
, slots
, &slot_count
);
947 plog("error in C_GetSlotList: %s"
948 , enum_show(&pkcs11_return_names
, rv
));
953 /* look in every slot for a certificate with a given object ID */
954 for (i
= 0; i
< slot_count
; i
++)
957 id_found
= scx_find_cert_id_in_slot(sc
, slot
);
966 DBG(DBG_CONTROL
| DBG_CRYPT
,
967 DBG_log("found token with id %s in slot %lu", sc
->id
, sc
->slot
);
968 DBG_log("pkcs11 session #%ld opened", sc
->session
)
973 plog(" no certificate with id %s found on smartcard", sc
->id
);
977 plog("warning: SMARTCARD support is deactivated in pluto/Makefile!");
983 * log in to a session
986 scx_login(smartcard_t
*sc
)
993 DBG(DBG_CONTROL
| DBG_CRYPT
,
994 DBG_log("pkcs11 session #%ld login already done", sc
->session
)
999 if (sc
->pin
.ptr
== NULL
)
1001 plog("unable to log in without PIN!");
1005 if (!sc
->session_opened
)
1007 plog("session not opened");
1011 rv
= pkcs11_functions
->C_Login(sc
->session
, CKU_USER
1012 , (CK_UTF8CHAR
*) sc
->pin
.ptr
, sc
->pin
.len
);
1013 if (rv
!= CKR_OK
&& rv
!= CKR_USER_ALREADY_LOGGED_IN
)
1015 plog("unable to login: %s"
1016 , enum_show(&pkcs11_return_names
, rv
));
1019 DBG(DBG_CONTROL
| DBG_CRYPT
,
1020 DBG_log("pkcs11 session #%ld login successful", sc
->session
)
1022 sc
->logged_in
= TRUE
;
1031 * logout from a session
1034 scx_logout(smartcard_t
*sc
)
1038 rv
= pkcs11_functions
->C_Logout(sc
->session
);
1040 plog("error in C_Logout: %s"
1041 , enum_show(&pkcs11_return_names
, rv
));
1043 DBG(DBG_CONTROL
| DBG_CRYPT
,
1044 DBG_log("pkcs11 session #%ld logout", sc
->session
)
1046 sc
->logged_in
= FALSE
;
1052 * Release context and disconnect from card
1055 scx_release_context(smartcard_t
*sc
)
1060 if (!scx_initialized
)
1063 if (sc
->session_opened
)
1068 sc
->session_opened
= FALSE
;
1070 rv
= pkcs11_functions
->C_CloseSession(sc
->session
);
1072 plog("error in C_CloseSession: %s"
1073 , enum_show(&pkcs11_return_names
, rv
));
1075 DBG(DBG_CONTROL
| DBG_CRYPT
,
1076 DBG_log("pkcs11 session #%ld closed", sc
->session
)
1083 * Load host certificate from smartcard
1086 scx_load_cert(const char *filename
, smartcard_t
**scp
, cert_t
*cert
1089 #ifdef SMARTCARD /* compile with smartcard support */
1090 CK_OBJECT_HANDLE object
;
1092 const char *number_slot_id
= filename
+ strlen(SCX_TOKEN
);
1094 smartcard_t
*sc
= scx_add(scx_parse_number_slot_id(number_slot_id
));
1096 /* return the smartcard object */
1099 /* is there a cached smartcard certificate? */
1100 *cached
= sc
->last_cert
.type
!= CERT_NONE
1101 && (time(NULL
) - sc
->last_load
) < SCX_CERT_CACHE_INTERVAL
;
1105 *cert
= sc
->last_cert
;
1106 plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')"
1108 , scx_print_slot(sc
, "")
1114 if (!scx_establish_context(sc
))
1116 scx_release_context(sc
);
1120 /* find the certificate object */
1121 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_CERTIFICATE
, sc
->id
))
1123 scx_release_context(sc
);
1127 /* retrieve the certificate object */
1128 if (!scx_find_cert_object(sc
->session
, object
, sc
, cert
))
1130 scx_release_context(sc
);
1134 if (!pkcs11_keep_state
)
1135 scx_release_context(sc
);
1137 plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')"
1139 , scx_print_slot(sc
, "")
1145 plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
1151 * parse slot number and key id
1152 * the following syntax is allowed
1155 * %smartcard#2 2 - -
1157 * %smartcard:45 - - 45
1158 * %smartcard0:45 - 0 45
1161 scx_parse_number_slot_id(const char *number_slot_id
)
1163 int len
= strlen(number_slot_id
);
1164 smartcard_t
*sc
= alloc_thing(smartcard_t
, "smartcard");
1166 /* assign default values */
1169 if (len
== 0) /* default: use certificate #1 */
1173 else if (*number_slot_id
== '#') /* #number scheme */
1178 ugh
= atoul(number_slot_id
+1, len
-1 , 10, &ul
);
1180 sc
->number
= (int)ul
;
1182 plog("error parsing smartcard number: %s", ugh
);
1184 else /* slot:id scheme */
1187 char *p
= strchr(number_slot_id
, ':');
1191 int id_len
= len
- (p
+ 1 - number_slot_id
);
1192 slot_len
-= (1 + id_len
);
1194 if (id_len
> 0) /* we have an id */
1197 if (slot_len
> 0) /* we have a slot */
1202 ugh
= atoul(number_slot_id
, slot_len
, 10, &ul
);
1206 sc
->any_slot
= FALSE
;
1209 plog("error parsing smartcard slot number: %s", ugh
);
1212 /* unshare the id string */
1213 sc
->id
= clone_str(sc
->id
, "key id");
1218 * Verify pin on card
1221 scx_verify_pin(smartcard_t
*sc
)
1229 if (sc
->pin
.ptr
== NULL
)
1231 plog("unable to verify without PIN");
1235 /* establish context */
1236 if (!scx_establish_context(sc
))
1238 scx_release_context(sc
);
1242 rv
= pkcs11_functions
->C_Login(sc
->session
, CKU_USER
,
1243 (CK_UTF8CHAR
*) sc
->pin
.ptr
, sc
->pin
.len
);
1244 if (rv
== CKR_OK
|| rv
== CKR_USER_ALREADY_LOGGED_IN
)
1247 sc
->logged_in
= TRUE
;
1248 DBG(DBG_CONTROL
| DBG_CRYPT
,
1249 DBG_log((rv
== CKR_OK
)
1250 ?
"PIN code correct"
1251 : "already logged in, no PIN entry required");
1252 DBG_log("pkcs11 session #%ld login successful", sc
->session
)
1257 DBG(DBG_CONTROL
| DBG_CRYPT
,
1258 DBG_log("PIN code incorrect")
1261 if (!pkcs11_keep_state
)
1262 scx_release_context(sc
);
1270 * Sign hash on smartcard
1273 scx_sign_hash(smartcard_t
*sc
, const u_char
*in
, size_t inlen
1274 , u_char
*out
, size_t outlen
)
1278 CK_OBJECT_HANDLE object
;
1279 CK_ULONG siglen
= (CK_ULONG
)outlen
;
1280 CK_BBOOL sign_flag
, decrypt_flag
;
1281 CK_ATTRIBUTE attr
[] = {
1282 { CKA_SIGN
, &sign_flag
, sizeof(sign_flag
) },
1283 { CKA_DECRYPT
, &decrypt_flag
, sizeof(decrypt_flag
) }
1289 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_PRIVATE_KEY
, sc
->id
))
1291 plog("unable to find private key with id '%s'", sc
->id
);
1295 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
, attr
, 2);
1298 plog("couldn't read the private key attributes: %s"
1299 , enum_show(&pkcs11_return_names
, rv
));
1303 DBG_log("RSA key flags: sign = %s, decrypt = %s"
1304 , (sign_flag
)?
"true":"false"
1305 , (decrypt_flag
)?
"true":"false")
1310 CK_MECHANISM mech
= { CKM_RSA_PKCS
, NULL_PTR
, 0 };
1312 rv
= pkcs11_functions
->C_SignInit(sc
->session
, &mech
, object
);
1315 plog("error in C_SignInit: %s"
1316 , enum_show(&pkcs11_return_names
, rv
));
1320 rv
= pkcs11_functions
->C_Sign(sc
->session
, (CK_BYTE_PTR
)in
, inlen
1324 plog("error in C_Sign: %s"
1325 , enum_show(&pkcs11_return_names
, rv
));
1329 else if (decrypt_flag
)
1331 CK_MECHANISM mech
= { CKM_RSA_X_509
, NULL_PTR
, 0 };
1335 /* PKCS#1 v1.5 8.1 encryption-block formatting */
1337 *p
++ = 0x01; /* BT (block type) 01 */
1338 padlen
= outlen
- 3 - inlen
;
1339 memset(p
, 0xFF, padlen
);
1342 memcpy(p
, in
, inlen
);
1344 rv
= pkcs11_functions
->C_DecryptInit(sc
->session
, &mech
, object
);
1347 plog("error in C_DecryptInit: %s"
1348 , enum_show(&pkcs11_return_names
, rv
));
1352 rv
= pkcs11_functions
->C_Decrypt(sc
->session
, out
, outlen
1356 plog("error in C_Decrypt: %s"
1357 , enum_show(&pkcs11_return_names
, rv
));
1363 plog("private key has neither sign nor decrypt flag set");
1367 if (siglen
> (CK_ULONG
)outlen
)
1369 plog("signature length (%lu) larger than allocated buffer (%d)"
1370 , siglen
, (int)outlen
);
1380 * encrypt data block with an RSA public key
1383 scx_encrypt(smartcard_t
*sc
, const u_char
*in
, size_t inlen
1384 , u_char
*out
, size_t *outlen
)
1388 CK_OBJECT_HANDLE object
;
1389 CK_ULONG len
= (CK_ULONG
)(*outlen
);
1390 CK_BBOOL encrypt_flag
;
1391 CK_ATTRIBUTE attr
[] = {
1392 { CKA_MODULUS
, NULL_PTR
, 0L },
1393 { CKA_PUBLIC_EXPONENT
, NULL_PTR
, 0L },
1394 { CKA_ENCRYPT
, &encrypt_flag
, sizeof(encrypt_flag
) }
1396 CK_MECHANISM mech
= { CKM_RSA_PKCS
, NULL_PTR
, 0 };
1398 if (!scx_establish_context(sc
))
1400 scx_release_context(sc
);
1404 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_PUBLIC_KEY
, sc
->id
))
1406 plog("unable to find public key with id '%s'", sc
->id
);
1410 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
, attr
, 3);
1413 plog("couldn't read the public key attributes: %s"
1414 , enum_show(&pkcs11_return_names
, rv
));
1415 scx_release_context(sc
);
1421 plog("public key cannot be used for encryption");
1422 scx_release_context(sc
);
1426 /* there must be enough space left for the PKCS#1 v1.5 padding */
1427 if (inlen
> attr
[0].ulValueLen
- 11)
1429 plog("smartcard input data length (%d) exceeds maximum of %lu bytes"
1430 , (int)inlen
, attr
[0].ulValueLen
- 11);
1431 if (!pkcs11_keep_state
)
1432 scx_release_context(sc
);
1436 rv
= pkcs11_functions
->C_EncryptInit(sc
->session
, &mech
, object
);
1440 if (rv
== CKR_FUNCTION_NOT_SUPPORTED
)
1442 RSA_public_key_t rsa
;
1443 chunk_t plain_text
= {in
, inlen
};
1444 chunk_t cipher_text
;
1447 DBG_log("doing RSA encryption in software")
1449 attr
[0].pValue
= alloc_bytes(attr
[0].ulValueLen
, "modulus");
1450 attr
[1].pValue
= alloc_bytes(attr
[1].ulValueLen
, "exponent");
1452 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
, attr
, 2);
1455 plog("couldn't read modulus and public exponent: %s"
1456 , enum_show(&pkcs11_return_names
, rv
));
1457 pfree(attr
[0].pValue
);
1458 pfree(attr
[1].pValue
);
1459 scx_release_context(sc
);
1462 rsa
.k
= attr
[0].ulValueLen
;
1463 n_to_mpz(&rsa
.n
, attr
[0].pValue
, attr
[0].ulValueLen
);
1464 n_to_mpz(&rsa
.e
, attr
[1].pValue
, attr
[1].ulValueLen
);
1465 pfree(attr
[0].pValue
);
1466 pfree(attr
[1].pValue
);
1468 cipher_text
= RSA_encrypt(&rsa
, plain_text
);
1469 free_RSA_public_content(&rsa
);
1470 if (cipher_text
.ptr
== NULL
)
1472 plog("smartcard input data length is too large");
1473 if (!pkcs11_keep_state
)
1474 scx_release_context(sc
);
1478 memcpy(out
, cipher_text
.ptr
, cipher_text
.len
);
1479 *outlen
= cipher_text
.len
;
1480 freeanychunk(cipher_text
);
1481 if (!pkcs11_keep_state
)
1482 scx_release_context(sc
);
1487 plog("error in C_EncryptInit: %s"
1488 , enum_show(&pkcs11_return_names
, rv
));
1489 scx_release_context(sc
);
1495 DBG_log("doing RSA encryption on smartcard")
1497 rv
= pkcs11_functions
->C_Encrypt(sc
->session
, in
, inlen
1501 plog("error in C_Encrypt: %s"
1502 , enum_show(&pkcs11_return_names
, rv
));
1503 scx_release_context(sc
);
1506 if (!pkcs11_keep_state
)
1507 scx_release_context(sc
);
1509 *outlen
= (size_t)len
;
1516 * decrypt a data block with an RSA private key
1519 scx_decrypt(smartcard_t
*sc
, const u_char
*in
, size_t inlen
1520 , u_char
*out
, size_t *outlen
)
1524 CK_OBJECT_HANDLE object
;
1525 CK_ULONG len
= (CK_ULONG
)(*outlen
);
1526 CK_BBOOL decrypt_flag
;
1527 CK_ATTRIBUTE attr
[] = {
1528 { CKA_DECRYPT
, &decrypt_flag
, sizeof(decrypt_flag
) }
1530 CK_MECHANISM mech
= { CKM_RSA_PKCS
, NULL_PTR
, 0 };
1532 if (!scx_establish_context(sc
) || !scx_login(sc
))
1534 scx_release_context(sc
);
1538 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_PRIVATE_KEY
, sc
->id
))
1540 plog("unable to find private key with id '%s'", sc
->id
);
1544 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
, attr
, 1);
1547 plog("couldn't read the private key attributes: %s"
1548 , enum_show(&pkcs11_return_names
, rv
));
1554 plog("private key cannot be used for decryption");
1555 scx_release_context(sc
);
1560 DBG_log("doing RSA decryption on smartcard")
1562 rv
= pkcs11_functions
->C_DecryptInit(sc
->session
, &mech
, object
);
1565 plog("error in C_DecryptInit: %s"
1566 , enum_show(&pkcs11_return_names
, rv
));
1567 scx_release_context(sc
);
1571 rv
= pkcs11_functions
->C_Decrypt(sc
->session
, in
, inlen
1575 plog("error in C_Decrypt: %s"
1576 , enum_show(&pkcs11_return_names
, rv
));
1577 scx_release_context(sc
);
1580 if (!pkcs11_keep_state
)
1581 scx_release_context(sc
);
1583 *outlen
= (size_t)len
;
1590 /* receive an encrypted data block via whack,
1591 * decrypt it using a private RSA key and
1592 * return the decrypted data block via whack
1595 scx_op_via_whack(const char* msg
, int inbase
, int outbase
, sc_op_t op
1596 , const char* keyid
, int whackfd
)
1598 char inbuf
[RSA_MAX_OCTETS
];
1599 char outbuf
[2*RSA_MAX_OCTETS
+ 1];
1600 size_t outlen
= sizeof(inbuf
);
1602 smartcard_t
*sc
,*sc_new
;
1604 const char *number_slot_id
= "";
1606 err_t ugh
= ttodata(msg
, 0, inbase
, inbuf
, sizeof(inbuf
), &inlen
);
1608 /* no prefix - use default base */
1609 if (ugh
!= NULL
&& inbase
== 0)
1610 ugh
= ttodata(msg
, 0, DEFAULT_BASE
, inbuf
, sizeof(inbuf
), &inlen
);
1614 plog("format error in smartcard input data: %s", ugh
);
1620 number_slot_id
= (strncmp(keyid
, SCX_TOKEN
, strlen(SCX_TOKEN
)) == 0)
1621 ? keyid
+ strlen(SCX_TOKEN
) : keyid
;
1624 sc_new
= scx_parse_number_slot_id(number_slot_id
);
1625 sc
= scx_add(sc_new
);
1629 DBG((op
== SC_OP_ENCRYPT
)? DBG_PRIVATE
:DBG_RAW
,
1630 DBG_dump("smartcard input data:\n", inbuf
, inlen
)
1633 if (op
== SC_OP_DECRYPT
)
1635 if (!sc
->valid
&& whackfd
!= NULL_FD
)
1636 scx_get_pin(sc
, whackfd
);
1640 loglog(RC_NOVALIDPIN
, "cannot decrypt without valid PIN");
1645 DBG(DBG_CONTROL
| DBG_CRYPT
,
1646 DBG_log("using RSA key from smartcard (slot: %d, id: %s)"
1647 , (int)sc
->slot
, sc
->id
)
1653 if (!scx_encrypt(sc
, inbuf
, inlen
, inbuf
, &outlen
))
1657 if (!scx_decrypt(sc
, inbuf
, inlen
, inbuf
, &outlen
))
1664 DBG((op
== SC_OP_DECRYPT
)? DBG_PRIVATE
:DBG_RAW
,
1665 DBG_dump("smartcard output data:\n", inbuf
, outlen
)
1668 if (outbase
== 0) /* use default base */
1669 outbase
= DEFAULT_BASE
;
1671 if (outbase
== 256) /* ascii plain text */
1672 whack_log(RC_COMMENT
, "%.*s", (int)outlen
, inbuf
);
1675 outlen
= datatot(inbuf
, outlen
, outbase
, outbuf
, sizeof(outbuf
));
1678 plog("error in output format conversion");
1681 whack_log(RC_COMMENT
, "%s", outbuf
);
1687 * get length of RSA key in bytes
1690 scx_get_keylength(smartcard_t
*sc
)
1694 CK_OBJECT_HANDLE object
;
1695 CK_ATTRIBUTE attr
[] = {{ CKA_MODULUS
, NULL_PTR
, 0}};
1700 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_PRIVATE_KEY
, sc
->id
))
1702 plog("unable to find private key with id '%s'", sc
->id
);
1706 /* get the length of the private key */
1707 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
1708 , (CK_ATTRIBUTE_PTR
)&attr
, 1);
1711 plog("failed to get key length: %s"
1712 , enum_show(&pkcs11_return_names
, rv
));
1716 return attr
[0].ulValueLen
; /*Return key length in bytes */
1723 * prompt for pin and verify it
1726 scx_get_pin(smartcard_t
*sc
, int whackfd
)
1732 whack_log(RC_ENTERSECRET
, "need PIN for #%d (%s, id: %s, label: '%s')"
1733 , sc
->number
, scx_print_slot(sc
, ""), sc
->id
, sc
->label
);
1735 for (i
= 0; i
< SCX_MAX_PIN_TRIALS
; i
++)
1738 whack_log(RC_ENTERSECRET
, "invalid PIN, please try again");
1740 n
= read(whackfd
, pin
, BUF_LEN
);
1744 whack_log(RC_LOG_SERIOUS
, "read(whackfd) failed");
1748 if (strlen(pin
) == 0)
1750 whack_log(RC_LOG_SERIOUS
, "no PIN entered, aborted");
1755 sc
->pin
.len
= strlen(pin
);
1757 /* verify the pin */
1758 if (scx_verify_pin(sc
))
1760 clonetochunk(sc
->pin
, pin
, strlen(pin
), "pin");
1764 /* wrong pin - we try another round */
1765 sc
->pin
= empty_chunk
;
1769 whack_log(RC_SUCCESS
, "valid PIN");
1771 whack_log(RC_LOG_SERIOUS
, "invalid PIN, too many trials");
1774 whack_log(RC_LOG_SERIOUS
, "SMARTCARD support is deactivated in pluto/Makefile!");
1784 scx_free_pin(chunk_t
*pin
)
1786 if (pin
->ptr
!= NULL
)
1788 /* clear pin field in memory */
1789 memset(pin
->ptr
, '\0', pin
->len
);
1796 * frees a smartcard record
1799 scx_free(smartcard_t
*sc
)
1803 scx_release_context(sc
);
1805 pfreeany(sc
->label
);
1806 scx_free_pin(&sc
->pin
);
1811 /* release of a smartcard record decreases the count by one
1812 " the record is freed when the counter reaches zero
1815 scx_release(smartcard_t
*sc
)
1817 if (sc
!= NULL
&& --sc
->count
== 0)
1819 smartcard_t
**pp
= &smartcards
;
1823 release_cert(sc
->last_cert
);
1829 * compare two smartcard records by comparing their slots and ids
1832 scx_same(smartcard_t
*a
, smartcard_t
*b
)
1834 if (a
->number
&& b
->number
)
1837 return a
->number
== b
->number
;
1841 /* same id and/or same slot */
1842 return (!a
->id
|| (b
->id
&& streq(a
->id
, b
->id
)))
1843 && (a
->any_slot
|| b
->any_slot
|| a
->slot
== b
->slot
);
1847 /* for each link pointing to the smartcard record
1848 " increase the count by one
1851 scx_share(smartcard_t
*sc
)
1858 * adds a smartcard record to the chained list
1861 scx_add(smartcard_t
*smartcard
)
1863 smartcard_t
*sc
= smartcards
;
1864 smartcard_t
**psc
= &smartcards
;
1868 if (scx_same(smartcard
, sc
)) /* already in chain, free smartcard record */
1870 scx_free(smartcard
);
1877 /* insert new smartcard record at the end of the chain */
1879 smartcard
->number
= ++sc_number
;
1880 smartcard
->count
= 1;
1881 DBG(DBG_CONTROL
| DBG_PARSING
,
1882 DBG_log(" smartcard #%d added", sc_number
)
1888 * get the smartcard that belongs to an X.509 certificate
1891 scx_get(x509cert_t
*cert
)
1893 smartcard_t
*sc
= smartcards
;
1897 if (sc
->last_cert
.u
.x509
== cert
)
1905 * prints either the slot number or 'any slot'
1908 scx_print_slot(smartcard_t
*sc
, const char *whitespace
)
1910 char *buf
= temporary_cyclic_buffer();
1913 snprintf(buf
, BUF_LEN
, "any slot");
1915 snprintf(buf
, BUF_LEN
, "slot: %s%lu", whitespace
, sc
->slot
);
1920 * list all smartcard info records in a chained list
1925 smartcard_t
*sc
= smartcards
;
1929 whack_log(RC_COMMENT
, " ");
1930 whack_log(RC_COMMENT
, "List of Smartcard Objects:");
1931 whack_log(RC_COMMENT
, " ");
1936 whack_log(RC_COMMENT
, "%s, #%d, count: %d"
1937 , timetoa(&sc
->last_load
, utc
)
1940 whack_log(RC_COMMENT
, " %s, session %s, logged %s, has %s"
1941 , scx_print_slot(sc
, " ")
1942 , sc
->session_opened?
"opened" : "closed"
1943 , sc
->logged_in?
"in" : "out"
1944 , sc
->pinpad?
"pin pad"
1945 : ((sc
->pin
.ptr
== NULL
)?
"no pin"
1946 : sc
->valid?
"valid pin" : "invalid pin"));
1948 whack_log(RC_COMMENT
, " id: %s", sc
->id
);
1949 if (sc
->label
!= NULL
)
1950 whack_log(RC_COMMENT
, " label: '%s'", sc
->label
);
1951 if (sc
->last_cert
.type
== CERT_X509_SIGNATURE
)
1955 dntoa(buf
, BUF_LEN
, sc
->last_cert
.u
.x509
->subject
);
1956 whack_log(RC_COMMENT
, " subject: '%s'", buf
);