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 fuer 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
32 #include "constants.h"
35 #include "rsaref/unix.h"
36 #include "rsaref/pkcs11.h"
46 #include "smartcard.h"
50 #define DEFAULT_BASE 16
52 /* chained list of smartcard records */
53 static smartcard_t
*smartcards
= NULL
;
55 /* number of generated sc objects */
56 static int sc_number
= 0;
58 const smartcard_t empty_sc
= {
61 { CERT_NONE
, {NULL
} }, /* last_cert */
67 { NULL
, 0 } , /* pin */
70 FALSE
, /* session_opened */
71 FALSE
, /* logged_in */
76 #ifdef SMARTCARD /* compile with smartcard support */
78 #define SCX_MAGIC 0xd00bed00
80 struct scx_pkcs11_module
{
85 typedef struct scx_pkcs11_module scx_pkcs11_module_t
;
87 /* PKCS #11 cryptoki context */
88 static bool scx_initialized
= FALSE
;
89 static scx_pkcs11_module_t
*pkcs11_module
= NULL_PTR
;
90 static CK_FUNCTION_LIST_PTR pkcs11_functions
= NULL_PTR
;
92 /* crytoki v2.11 - return values of PKCS #11 functions*/
94 static const char *const pkcs11_return_name
[] = {
98 "CKR_SLOT_ID_INVALID",
101 "CKR_FUNCTION_FAILED",
104 "CKR_NEED_TO_CREATE_THREADS",
108 static const char *const pkcs11_return_name_10
[] = {
109 "CKR_ATTRIBUTE_READ_ONLY",
110 "CKR_ATTRIBUTE_SENSITIVE",
111 "CKR_ATTRIBUTE_TYPE_INVALID",
112 "CKR_ATTRIBUTE_VALUE_INVALID"
115 static const char *const pkcs11_return_name_20
[] = {
120 static const char *const pkcs11_return_name_30
[] = {
126 static const char *const pkcs11_return_name_40
[] = {
127 "CKR_ENCRYPTED_DATA_INVALID",
128 "CKR_ENCRYPTED_DATA_LEN_RANGE"
131 static const char *const pkcs11_return_name_50
[] = {
132 "CKR_FUNCTION_CANCELED",
133 "CKR_FUNCTION_NOT_PARALLEL",
134 "CKR_0x52_UNDEFINED",
135 "CKR_0x53_UNDEFINED",
136 "CKR_FUNCTION_NOT_SUPPORTED"
139 static const char *const pkcs11_return_name_60
[] = {
140 "CKR_KEY_HANDLE_INVALID",
142 "CKR_KEY_SIZE_RANGE",
143 "CKR_KEY_TYPE_INCONSISTENT",
144 "CKR_KEY_NOT_NEEDED",
147 "CKR_KEY_INDIGESTIBLE",
148 "CKR_KEY_FUNCTION_NOT_PERMITTED",
149 "CKR_KEY_NOT_WRAPPABLE",
150 "CKR_KEY_UNEXTRACTABLE"
153 static const char *const pkcs11_return_name_70
[] = {
154 "CKR_MECHANISM_INVALID",
155 "CKR_MECHANISM_PARAM_INVALID"
158 static const char *const pkcs11_return_name_80
[] = {
159 "CKR_OBJECT_HANDLE_INVALID"
162 static const char *const pkcs11_return_name_90
[] = {
163 "CKR_OPERATION_ACTIVE",
164 "CKR_OPERATION_NOT_INITIALIZED"
167 static const char *const pkcs11_return_name_A0
[] = {
175 static const char *const pkcs11_return_name_B0
[] = {
176 "CKR_SESSION_CLOSED",
178 "CKR_0xB2_UNDEFINED",
179 "CKR_SESSION_HANDLE_INVALID",
180 "CKR_SESSION_PARALLEL_NOT_SUPPORTED",
181 "CKR_SESSION_READ_ONLY",
182 "CKR_SESSION_EXISTS",
183 "CKR_SESSION_READ_ONLY_EXISTS",
184 "CKR_SESSION_READ_WRITE_SO_EXISTS"
187 static const char *const pkcs11_return_name_C0
[] = {
188 "CKR_SIGNATURE_INVALID",
189 "CKR_SIGNATURE_LEN_RANGE"
192 static const char *const pkcs11_return_name_D0
[] = {
193 "CKR_TEMPLATE_INCOMPLETE",
194 "CKR_TEMPLATE_INCONSISTENT"
197 static const char *const pkcs11_return_name_E0
[] = {
198 "CKR_TOKEN_NOT_PRESENT",
199 "CKR_TOKEN_NOT_RECOGNIZED",
200 "CKR_TOKEN_WRITE_PROTECTED"
203 static const char *const pkcs11_return_name_F0
[] = {
204 "CKR_UNWRAPPING_KEY_HANDLE_INVALID",
205 "CKR_UNWRAPPING_KEY_SIZE_RANGE",
206 "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"
209 static const char *const pkcs11_return_name_100
[] = {
210 "CKR_USER_ALREADY_LOGGED_IN",
211 "CKR_USER_NOT_LOGGED_IN",
212 "CKR_USER_PIN_NOT_INITIALIZED",
213 "CKR_USER_TYPE_INVALID",
214 "CKR_USER_ANOTHER_ALREADY_LOGGED_IN",
215 "CKR_USER_TOO_MANY_TYPES"
218 static const char *const pkcs11_return_name_110
[] = {
219 "CKR_WRAPPED_KEY_INVALID",
220 "CKR_0x111_UNDEFINED",
221 "CKR_WRAPPED_KEY_LEN_RANGE",
222 "CKR_WRAPPING_KEY_HANDLE_INVALID",
223 "CKR_WRAPPING_KEY_SIZE_RANGE",
224 "CKR_WRAPPING_KEY_TYPE_INCONSISTENT"
227 static const char *const pkcs11_return_name_120
[] = {
228 "CKR_RANDOM_SEED_NOT_SUPPORTED",
232 static const char *const pkcs11_return_name_130
[] = {
233 "CKR_DOMAIN_PARAMS_INVALID"
236 static const char *const pkcs11_return_name_150
[] = {
237 "CKR_BUFFER_TOO_SMALL"
240 static const char *const pkcs11_return_name_160
[] = {
241 "CKR_SAVED_STATE_INVALID"
244 static const char *const pkcs11_return_name_170
[] = {
245 "CKR_INFORMATION_SENSITIVE"
248 static const char *const pkcs11_return_name_180
[] = {
249 "CKR_STATE_UNSAVEABLE"
252 static const char *const pkcs11_return_name_190
[] = {
253 "CKR_CRYPTOKI_NOT_INITIALIZED",
254 "CKR_CRYPTOKI_ALREADY_INITIALIZED"
257 static const char *const pkcs11_return_name_1A0
[] = {
259 "CKR_MUTEX_NOT_LOCKED"
262 static const char *const pkcs11_return_name_200
[] = {
263 "CKR_FUNCTION_REJECTED"
266 static const char *const pkcs11_return_name_vendor
[] = {
270 static enum_names pkcs11_return_names_vendor
=
271 { CKR_VENDOR_DEFINED
, CKR_VENDOR_DEFINED
272 , pkcs11_return_name_vendor
, NULL
};
274 static enum_names pkcs11_return_names_200
=
275 { CKR_FUNCTION_REJECTED
, CKR_FUNCTION_REJECTED
276 , pkcs11_return_name_200
, &pkcs11_return_names_vendor
};
278 static enum_names pkcs11_return_names_1A0
=
279 { CKR_MUTEX_BAD
, CKR_MUTEX_NOT_LOCKED
280 , pkcs11_return_name_1A0
, &pkcs11_return_names_200
};
282 static enum_names pkcs11_return_names_190
=
283 { CKR_CRYPTOKI_NOT_INITIALIZED
, CKR_CRYPTOKI_ALREADY_INITIALIZED
284 , pkcs11_return_name_190
, &pkcs11_return_names_1A0
};
286 static enum_names pkcs11_return_names_180
=
287 { CKR_STATE_UNSAVEABLE
, CKR_STATE_UNSAVEABLE
288 , pkcs11_return_name_180
, &pkcs11_return_names_190
};
290 static enum_names pkcs11_return_names_170
=
291 { CKR_INFORMATION_SENSITIVE
, CKR_INFORMATION_SENSITIVE
292 , pkcs11_return_name_170
, &pkcs11_return_names_180
};
294 static enum_names pkcs11_return_names_160
=
295 { CKR_SAVED_STATE_INVALID
, CKR_SAVED_STATE_INVALID
296 , pkcs11_return_name_160
, &pkcs11_return_names_170
};
298 static enum_names pkcs11_return_names_150
=
299 { CKR_BUFFER_TOO_SMALL
, CKR_BUFFER_TOO_SMALL
300 , pkcs11_return_name_150
, &pkcs11_return_names_160
};
302 static enum_names pkcs11_return_names_130
=
303 { CKR_DOMAIN_PARAMS_INVALID
, CKR_DOMAIN_PARAMS_INVALID
304 , pkcs11_return_name_130
, &pkcs11_return_names_150
};
306 static enum_names pkcs11_return_names_120
=
307 { CKR_RANDOM_SEED_NOT_SUPPORTED
, CKR_RANDOM_NO_RNG
308 , pkcs11_return_name_120
, &pkcs11_return_names_130
};
310 static enum_names pkcs11_return_names_110
=
311 { CKR_WRAPPED_KEY_INVALID
, CKR_WRAPPING_KEY_TYPE_INCONSISTENT
312 , pkcs11_return_name_110
, &pkcs11_return_names_120
};
314 static enum_names pkcs11_return_names_100
=
315 { CKR_USER_ALREADY_LOGGED_IN
, CKR_USER_TOO_MANY_TYPES
316 , pkcs11_return_name_100
, &pkcs11_return_names_110
};
318 static enum_names pkcs11_return_names_F0
=
319 { CKR_UNWRAPPING_KEY_HANDLE_INVALID
, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
320 , pkcs11_return_name_F0
, &pkcs11_return_names_100
};
322 static enum_names pkcs11_return_names_E0
=
323 { CKR_TOKEN_NOT_PRESENT
, CKR_TOKEN_WRITE_PROTECTED
324 , pkcs11_return_name_E0
, &pkcs11_return_names_F0
};
326 static enum_names pkcs11_return_names_D0
=
327 { CKR_TEMPLATE_INCOMPLETE
, CKR_TEMPLATE_INCONSISTENT
328 , pkcs11_return_name_D0
,&pkcs11_return_names_E0
};
330 static enum_names pkcs11_return_names_C0
=
331 { CKR_SIGNATURE_INVALID
, CKR_SIGNATURE_LEN_RANGE
332 , pkcs11_return_name_C0
, &pkcs11_return_names_D0
};
334 static enum_names pkcs11_return_names_B0
=
335 { CKR_SESSION_CLOSED
, CKR_SESSION_READ_WRITE_SO_EXISTS
336 , pkcs11_return_name_B0
, &pkcs11_return_names_C0
};
338 static enum_names pkcs11_return_names_A0
=
339 { CKR_PIN_INCORRECT
, CKR_PIN_LOCKED
340 , pkcs11_return_name_A0
, &pkcs11_return_names_B0
};
342 static enum_names pkcs11_return_names_90
=
343 { CKR_OPERATION_ACTIVE
, CKR_OPERATION_NOT_INITIALIZED
344 , pkcs11_return_name_90
, &pkcs11_return_names_A0
};
346 static enum_names pkcs11_return_names_80
=
347 { CKR_OBJECT_HANDLE_INVALID
, CKR_OBJECT_HANDLE_INVALID
348 , pkcs11_return_name_80
, &pkcs11_return_names_90
};
350 static enum_names pkcs11_return_names_70
=
351 { CKR_MECHANISM_INVALID
, CKR_MECHANISM_PARAM_INVALID
352 , pkcs11_return_name_70
, &pkcs11_return_names_80
};
354 static enum_names pkcs11_return_names_60
=
355 { CKR_KEY_HANDLE_INVALID
, CKR_KEY_UNEXTRACTABLE
356 , pkcs11_return_name_60
, &pkcs11_return_names_70
};
358 static enum_names pkcs11_return_names_50
=
359 { CKR_FUNCTION_CANCELED
, CKR_FUNCTION_NOT_SUPPORTED
360 , pkcs11_return_name_50
, &pkcs11_return_names_60
};
362 static enum_names pkcs11_return_names_40
=
363 { CKR_ENCRYPTED_DATA_INVALID
, CKR_ENCRYPTED_DATA_LEN_RANGE
364 , pkcs11_return_name_40
, &pkcs11_return_names_50
};
366 static enum_names pkcs11_return_names_30
=
367 { CKR_DEVICE_ERROR
, CKR_DEVICE_REMOVED
368 , pkcs11_return_name_30
, &pkcs11_return_names_40
};
370 static enum_names pkcs11_return_names_20
=
371 { CKR_DATA_INVALID
, CKR_DATA_LEN_RANGE
372 , pkcs11_return_name_20
, &pkcs11_return_names_30
};
374 static enum_names pkcs11_return_names_10
=
375 { CKR_ATTRIBUTE_READ_ONLY
, CKR_ATTRIBUTE_VALUE_INVALID
376 , pkcs11_return_name_10
, &pkcs11_return_names_20
};
378 static enum_names pkcs11_return_names
=
379 { CKR_OK
, CKR_CANT_LOCK
380 , pkcs11_return_name
, &pkcs11_return_names_10
};
383 * Unload a PKCS#11 module.
384 * The calling application is responsible for cleaning up
385 * and calling C_Finalize()
388 scx_unload_pkcs11_module(scx_pkcs11_module_t
*mod
)
390 if (!mod
|| mod
->_magic
!= SCX_MAGIC
)
391 return CKR_ARGUMENTS_BAD
;
393 if (dlclose(mod
->handle
) < 0)
394 return CKR_FUNCTION_FAILED
;
396 memset(mod
, 0, sizeof(*mod
));
401 static scx_pkcs11_module_t
*
402 scx_load_pkcs11_module(const char *name
, CK_FUNCTION_LIST_PTR_PTR funcs
)
404 CK_RV (*c_get_function_list
)(CK_FUNCTION_LIST_PTR_PTR
);
405 scx_pkcs11_module_t
*mod
;
409 if (name
== NULL
|| *name
== '\0')
412 /* Try to load PKCS#11 library module*/
413 handle
= dlopen(name
, RTLD_NOW
);
417 mod
= malloc_thing(scx_pkcs11_module_t
);
418 mod
->_magic
= SCX_MAGIC
;
419 mod
->handle
= handle
;
421 /* Get the list of function pointers */
422 c_get_function_list
= (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR
))
423 dlsym(mod
->handle
, "C_GetFunctionList");
424 if (!c_get_function_list
)
427 rv
= c_get_function_list(funcs
);
431 failed
: scx_unload_pkcs11_module(mod
);
436 * retrieve a certificate object
439 scx_find_cert_object(CK_SESSION_HANDLE session
, CK_OBJECT_HANDLE object
440 , smartcard_t
*sc
, cert_t
*cert
)
442 size_t hex_len
, label_len
;
443 u_char
*hex_id
= NULL
;
445 x509cert_t
*x509cert
;
447 CK_ATTRIBUTE attr
[] = {
448 { CKA_ID
, NULL_PTR
, 0L },
449 { CKA_LABEL
, NULL_PTR
, 0L },
450 { CKA_VALUE
, NULL_PTR
, 0L }
453 /* initialize the return argument */
456 /* get the length of the attributes first */
457 CK_RV rv
= pkcs11_functions
->C_GetAttributeValue(session
, object
, attr
, 3);
460 plog("couldn't read the attribute sizes: %s"
461 , enum_show(&pkcs11_return_names
, rv
));
467 hex_id
= malloc(attr
[0].ulValueLen
);
468 hex_len
= attr
[0].ulValueLen
;
469 sc
->label
= malloc(attr
[1].ulValueLen
+ 1);
470 label_len
= attr
[1].ulValueLen
;
471 blob
.ptr
= malloc(attr
[2].ulValueLen
);
472 blob
.len
= attr
[2].ulValueLen
;
474 attr
[0].pValue
= hex_id
;
475 attr
[1].pValue
= sc
->label
;
476 attr
[2].pValue
= blob
.ptr
;
478 /* now get the attributes */
479 rv
= pkcs11_functions
->C_GetAttributeValue(session
, object
, attr
, 3);
482 plog("couldn't read the attributes: %s"
483 , enum_show(&pkcs11_return_names
, rv
));
492 /* convert id from hex to ASCII */
493 sc
->id
= malloc(2*hex_len
+ 1);
494 datatot(hex_id
, hex_len
, 16, sc
->id
, 2*hex_len
+ 1);
497 /* safeguard in case the label is not null terminated */
498 sc
->label
[label_len
] = '\0';
500 /* parse the retrieved cert */
501 x509cert
= malloc_thing(x509cert_t
);
502 *x509cert
= empty_x509cert
;
503 x509cert
->smartcard
= TRUE
;
505 if (!parse_x509cert(blob
, 0, x509cert
))
507 plog("failed to load cert from smartcard, error in X.509 certificate");
508 free_x509cert(x509cert
);
511 cert
->type
= CERT_X509_SIGNATURE
;
512 cert
->u
.x509
= x509cert
;
517 * search a given slot for PKCS#11 certificate objects
520 scx_find_cert_objects(CK_SLOT_ID slot
, CK_SESSION_HANDLE session
)
523 CK_OBJECT_CLASS
class = CKO_CERTIFICATE
;
524 CK_ATTRIBUTE attr
[] = {{ CKA_CLASS
, &class, sizeof(class) }};
526 rv
= pkcs11_functions
->C_FindObjectsInit(session
, attr
, 1);
529 plog("error in C_FindObjectsInit: %s"
530 , enum_show(&pkcs11_return_names
, rv
));
536 CK_OBJECT_HANDLE object
;
537 CK_ULONG obj_count
= 0;
543 rv
= pkcs11_functions
->C_FindObjects(session
, &object
, 1, &obj_count
);
546 plog("error in C_FindObjects: %s"
547 , enum_show(&pkcs11_return_names
, rv
));
551 /* no objects left */
555 /* create and initialize a new smartcard object */
556 sc
= malloc_thing(smartcard_t
);
558 sc
->any_slot
= FALSE
;
561 if (!scx_find_cert_object(session
, object
, sc
, &sc
->last_cert
))
567 DBG_log("found cert in %s with id: %s, label: '%s'"
568 , scx_print_slot(sc
, ""), sc
->id
, sc
->label
)
571 /* check validity of certificate */
572 cert
= sc
->last_cert
.u
.x509
;
573 valid_until
= cert
->notAfter
;
574 ugh
= check_validity(cert
, &valid_until
);
585 DBG_log(" certificate is valid")
591 /* put end entity and ca certificates into different chains */
594 sc
->last_cert
.u
.x509
= add_authcert(cert
, AUTH_CA
);
598 add_x509_public_key(cert
, valid_until
, DAL_LOCAL
);
599 sc
->last_cert
.u
.x509
= add_x509cert(cert
);
602 share_cert(sc
->last_cert
);
603 time(&sc
->last_load
);
606 rv
= pkcs11_functions
->C_FindObjectsFinal(session
);
609 plog("error in C_FindObjectsFinal: %s"
610 , enum_show(&pkcs11_return_names
, rv
));
615 * search all slots for PKCS#11 certificate objects
618 scx_find_all_cert_objects(void)
621 CK_SLOT_ID_PTR slots
= NULL_PTR
;
622 CK_ULONG slot_count
= 0;
625 if (!scx_initialized
)
627 plog("pkcs11 module not initialized");
631 /* read size, always returns CKR_OK ! */
632 rv
= pkcs11_functions
->C_GetSlotList(FALSE
, NULL_PTR
, &slot_count
);
634 /* allocate memory for the slots */
635 slots
= (CK_SLOT_ID
*)malloc(slot_count
* sizeof(CK_SLOT_ID
));
637 rv
= pkcs11_functions
->C_GetSlotList(FALSE
, slots
, &slot_count
);
640 plog("error in C_GetSlotList: %s", enum_show(&pkcs11_return_names
, rv
));
645 /* look in every slot for certificate objects */
646 for (i
= 0; i
< slot_count
; i
++)
648 CK_SLOT_ID slot
= slots
[i
];
650 CK_SESSION_HANDLE session
;
652 rv
= pkcs11_functions
->C_GetSlotInfo(slot
, &info
);
656 plog("error in C_GetSlotInfo: %s"
657 , enum_show(&pkcs11_return_names
, rv
));
661 if (!(info
.flags
& CKF_TOKEN_PRESENT
))
663 plog("no token present in slot %lu", slot
);
667 rv
= pkcs11_functions
->C_OpenSession(slot
668 , CKF_SERIAL_SESSION
, NULL_PTR
, NULL_PTR
, &session
);
671 plog("failed to open a session on slot %lu: %s"
672 , slot
, enum_show(&pkcs11_return_names
, rv
));
676 DBG_log("pkcs11 session #%ld for searching slot %lu", session
, slot
)
678 scx_find_cert_objects(slot
, session
);
680 rv
= pkcs11_functions
->C_CloseSession(session
);
683 plog("error in C_CloseSession: %s"
684 , enum_show(&pkcs11_return_names
, rv
));
692 * load and initialize PKCS#11 cryptoki module
694 * init_args should be unused when we have a PKCS#11 compliant module,
695 * but NSS softoken breaks that API.
698 scx_init(const char* module
, const char *init_args
)
701 CK_C_INITIALIZE_ARGS args
= { .pReserved
= (char *)init_args
, };
706 plog("weird - pkcs11 module seems already to be initialized");
711 #ifdef PKCS11_DEFAULT_LIB
712 module
= PKCS11_DEFAULT_LIB
;
715 plog("no pkcs11 module defined");
720 DBG(DBG_CONTROL
| DBG_CRYPT
,
721 DBG_log("pkcs11 module '%s' loading...", module
)
723 pkcs11_module
= scx_load_pkcs11_module(module
, &pkcs11_functions
);
724 if (pkcs11_module
== NULL
)
726 plog("failed to load pkcs11 module '%s'", module
);
730 DBG(DBG_CONTROL
| DBG_CRYPT
,
731 DBG_log("pkcs11 module initializing...")
733 rv
= pkcs11_functions
->C_Initialize(init_args ?
&args
: NULL
);
736 plog("failed to initialize pkcs11 module: %s"
737 , enum_show(&pkcs11_return_names
, rv
));
741 scx_initialized
= TRUE
;
742 DBG(DBG_CONTROL
| DBG_CRYPT
,
743 DBG_log("pkcs11 module loaded and initialized")
746 scx_find_all_cert_objects();
751 * finalize and unload PKCS#11 cryptoki module
757 while (smartcards
!= NULL
)
759 scx_release(smartcards
);
762 if (pkcs11_functions
!= NULL_PTR
)
764 pkcs11_functions
->C_Finalize(NULL_PTR
);
765 pkcs11_functions
= NULL_PTR
;
768 if (pkcs11_module
!= NULL
)
770 scx_unload_pkcs11_module(pkcs11_module
);
771 pkcs11_module
= NULL
;
774 scx_initialized
= FALSE
;
775 DBG(DBG_CONTROL
| DBG_CRYPT
,
776 DBG_log("pkcs11 module finalized and unloaded")
782 * does a filename contain the token %smartcard?
785 scx_on_smartcard(const char *filename
)
787 return strneq(filename
, SCX_TOKEN
, strlen(SCX_TOKEN
));
792 * find a specific object on the smartcard
795 scx_pkcs11_find_object( CK_SESSION_HANDLE session
,
796 CK_OBJECT_HANDLE_PTR object
,
797 CK_OBJECT_CLASS
class,
803 CK_ULONG obj_count
= 0;
804 CK_ULONG attr_count
= 1;
806 CK_ATTRIBUTE attr
[] = {
807 { CKA_CLASS
, &class, sizeof(class) },
813 ttodata(id
, strlen(id
), 16, buf
, BUF_LEN
, &len
);
814 attr
[1].ulValueLen
= len
;
818 /* get info for certificate with id */
819 rv
= pkcs11_functions
->C_FindObjectsInit(session
, attr
, attr_count
);
822 plog("error in C_FindObjectsInit: %s"
823 , enum_show(&pkcs11_return_names
, rv
));
827 rv
= pkcs11_functions
->C_FindObjects(session
, object
, 1, &obj_count
);
830 plog("error in C_FindObjects: %s"
831 , enum_show(&pkcs11_return_names
, rv
));
835 rv
= pkcs11_functions
->C_FindObjectsFinal(session
);
838 plog("error in C_FindObjectsFinal: %s"
839 , enum_show(&pkcs11_return_names
, rv
));
843 return (obj_count
!= 0);
847 * check if a given certificate object id is found in a slot
850 scx_find_cert_id_in_slot(smartcard_t
*sc
, CK_SLOT_ID slot
)
852 CK_SESSION_HANDLE session
;
853 CK_OBJECT_HANDLE object
;
856 CK_RV rv
= pkcs11_functions
->C_GetSlotInfo(slot
, &info
);
860 plog("error in C_GetSlotInfo: %s"
861 , enum_show(&pkcs11_return_names
, rv
));
865 if (!(info
.flags
& CKF_TOKEN_PRESENT
))
867 plog("no token present in slot %lu", slot
);
871 rv
= pkcs11_functions
->C_OpenSession(slot
872 , CKF_SERIAL_SESSION
, NULL_PTR
, NULL_PTR
, &session
);
875 plog("failed to open a session on slot %lu: %s"
876 , slot
, enum_show(&pkcs11_return_names
, rv
));
880 DBG_log("pkcs11 session #%ld for searching slot %lu", session
, slot
)
883 /* check if there is a certificate on the card in the specified slot */
884 if (scx_pkcs11_find_object(session
, &object
, CKO_CERTIFICATE
, sc
->id
))
887 sc
->any_slot
= FALSE
;
888 sc
->session
= session
;
889 sc
->session_opened
= TRUE
;
893 rv
= pkcs11_functions
->C_CloseSession(session
);
896 plog("error in C_CloseSession: %s"
897 , enum_show(&pkcs11_return_names
, rv
));
904 * Connect to the smart card in the reader and select the correct slot
907 scx_establish_context(smartcard_t
*sc
)
910 bool id_found
= FALSE
;
912 if (!scx_initialized
)
914 plog("pkcs11 module not initialized");
918 if (sc
->session_opened
)
920 DBG(DBG_CONTROL
| DBG_CRYPT
,
921 DBG_log("pkcs11 session #%ld already open", sc
->session
)
927 id_found
= scx_find_cert_id_in_slot(sc
, sc
->slot
);
933 CK_SLOT_ID_PTR slots
= NULL_PTR
;
934 CK_ULONG slot_count
= 0;
937 /* read size, always returns CKR_OK ! */
938 rv
= pkcs11_functions
->C_GetSlotList(FALSE
, NULL_PTR
, &slot_count
);
940 /* allocate memory for the slots */
941 slots
= (CK_SLOT_ID
*)malloc(slot_count
* sizeof(CK_SLOT_ID
));
943 rv
= pkcs11_functions
->C_GetSlotList(FALSE
, slots
, &slot_count
);
946 plog("error in C_GetSlotList: %s"
947 , enum_show(&pkcs11_return_names
, rv
));
952 /* look in every slot for a certificate with a given object ID */
953 for (i
= 0; i
< slot_count
; i
++)
956 id_found
= scx_find_cert_id_in_slot(sc
, slot
);
965 DBG(DBG_CONTROL
| DBG_CRYPT
,
966 DBG_log("found token with id %s in slot %lu", sc
->id
, sc
->slot
);
967 DBG_log("pkcs11 session #%ld opened", sc
->session
)
972 plog(" no certificate with id %s found on smartcard", sc
->id
);
976 plog("warning: SMARTCARD support is deactivated in pluto/Makefile!");
982 * log in to a session
985 scx_login(smartcard_t
*sc
)
992 DBG(DBG_CONTROL
| DBG_CRYPT
,
993 DBG_log("pkcs11 session #%ld login already done", sc
->session
)
998 if (sc
->pin
.ptr
== NULL
)
1000 plog("unable to log in without PIN!");
1004 if (!sc
->session_opened
)
1006 plog("session not opened");
1010 rv
= pkcs11_functions
->C_Login(sc
->session
, CKU_USER
1011 , (CK_UTF8CHAR
*) sc
->pin
.ptr
, sc
->pin
.len
);
1012 if (rv
!= CKR_OK
&& rv
!= CKR_USER_ALREADY_LOGGED_IN
)
1014 plog("unable to login: %s"
1015 , enum_show(&pkcs11_return_names
, rv
));
1018 DBG(DBG_CONTROL
| DBG_CRYPT
,
1019 DBG_log("pkcs11 session #%ld login successful", sc
->session
)
1021 sc
->logged_in
= TRUE
;
1030 * logout from a session
1033 scx_logout(smartcard_t
*sc
)
1037 rv
= pkcs11_functions
->C_Logout(sc
->session
);
1039 plog("error in C_Logout: %s"
1040 , enum_show(&pkcs11_return_names
, rv
));
1042 DBG(DBG_CONTROL
| DBG_CRYPT
,
1043 DBG_log("pkcs11 session #%ld logout", sc
->session
)
1045 sc
->logged_in
= FALSE
;
1051 * Release context and disconnect from card
1054 scx_release_context(smartcard_t
*sc
)
1059 if (!scx_initialized
)
1062 if (sc
->session_opened
)
1067 sc
->session_opened
= FALSE
;
1069 rv
= pkcs11_functions
->C_CloseSession(sc
->session
);
1071 plog("error in C_CloseSession: %s"
1072 , enum_show(&pkcs11_return_names
, rv
));
1074 DBG(DBG_CONTROL
| DBG_CRYPT
,
1075 DBG_log("pkcs11 session #%ld closed", sc
->session
)
1082 * Load host certificate from smartcard
1085 scx_load_cert(const char *filename
, smartcard_t
**scp
, cert_t
*cert
1088 #ifdef SMARTCARD /* compile with smartcard support */
1089 CK_OBJECT_HANDLE object
;
1091 const char *number_slot_id
= filename
+ strlen(SCX_TOKEN
);
1093 smartcard_t
*sc
= scx_add(scx_parse_number_slot_id(number_slot_id
));
1095 /* return the smartcard object */
1098 /* is there a cached smartcard certificate? */
1099 *cached
= sc
->last_cert
.type
!= CERT_NONE
1100 && (time(NULL
) - sc
->last_load
) < SCX_CERT_CACHE_INTERVAL
;
1104 *cert
= sc
->last_cert
;
1105 plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')"
1107 , scx_print_slot(sc
, "")
1113 if (!scx_establish_context(sc
))
1115 scx_release_context(sc
);
1119 /* find the certificate object */
1120 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_CERTIFICATE
, sc
->id
))
1122 scx_release_context(sc
);
1126 /* retrieve the certificate object */
1127 if (!scx_find_cert_object(sc
->session
, object
, sc
, cert
))
1129 scx_release_context(sc
);
1133 if (!pkcs11_keep_state
)
1134 scx_release_context(sc
);
1136 plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')"
1138 , scx_print_slot(sc
, "")
1144 plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!");
1150 * parse slot number and key id
1151 * the following syntax is allowed
1154 * %smartcard#2 2 - -
1156 * %smartcard:45 - - 45
1157 * %smartcard0:45 - 0 45
1160 scx_parse_number_slot_id(const char *number_slot_id
)
1162 int len
= strlen(number_slot_id
);
1163 smartcard_t
*sc
= malloc_thing(smartcard_t
);
1165 /* assign default values */
1168 if (len
== 0) /* default: use certificate #1 */
1172 else if (*number_slot_id
== '#') /* #number scheme */
1177 ugh
= atoul(number_slot_id
+1, len
-1 , 10, &ul
);
1179 sc
->number
= (int)ul
;
1181 plog("error parsing smartcard number: %s", ugh
);
1183 else /* slot:id scheme */
1186 char *p
= strchr(number_slot_id
, ':');
1190 int id_len
= len
- (p
+ 1 - number_slot_id
);
1191 slot_len
-= (1 + id_len
);
1193 if (id_len
> 0) /* we have an id */
1196 if (slot_len
> 0) /* we have a slot */
1201 ugh
= atoul(number_slot_id
, slot_len
, 10, &ul
);
1205 sc
->any_slot
= FALSE
;
1208 plog("error parsing smartcard slot number: %s", ugh
);
1211 /* unshare the id string */
1212 sc
->id
= clone_str(sc
->id
);
1217 * Verify pin on card
1220 scx_verify_pin(smartcard_t
*sc
)
1228 if (sc
->pin
.ptr
== NULL
)
1230 plog("unable to verify without PIN");
1234 /* establish context */
1235 if (!scx_establish_context(sc
))
1237 scx_release_context(sc
);
1241 rv
= pkcs11_functions
->C_Login(sc
->session
, CKU_USER
,
1242 (CK_UTF8CHAR
*) sc
->pin
.ptr
, sc
->pin
.len
);
1243 if (rv
== CKR_OK
|| rv
== CKR_USER_ALREADY_LOGGED_IN
)
1246 sc
->logged_in
= TRUE
;
1247 DBG(DBG_CONTROL
| DBG_CRYPT
,
1248 DBG_log((rv
== CKR_OK
)
1249 ?
"PIN code correct"
1250 : "already logged in, no PIN entry required");
1251 DBG_log("pkcs11 session #%ld login successful", sc
->session
)
1256 DBG(DBG_CONTROL
| DBG_CRYPT
,
1257 DBG_log("PIN code incorrect")
1260 if (!pkcs11_keep_state
)
1261 scx_release_context(sc
);
1269 * Sign hash on smartcard
1272 scx_sign_hash(smartcard_t
*sc
, const u_char
*in
, size_t inlen
1273 , u_char
*out
, size_t outlen
)
1277 CK_OBJECT_HANDLE object
;
1278 CK_ULONG siglen
= (CK_ULONG
)outlen
;
1279 CK_BBOOL sign_flag
, decrypt_flag
;
1280 CK_ATTRIBUTE attr
[] = {
1281 { CKA_SIGN
, &sign_flag
, sizeof(sign_flag
) },
1282 { CKA_DECRYPT
, &decrypt_flag
, sizeof(decrypt_flag
) }
1288 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_PRIVATE_KEY
, sc
->id
))
1290 plog("unable to find private key with id '%s'", sc
->id
);
1294 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
, attr
, 2);
1297 plog("couldn't read the private key attributes: %s"
1298 , enum_show(&pkcs11_return_names
, rv
));
1302 DBG_log("RSA key flags: sign = %s, decrypt = %s"
1303 , (sign_flag
)?
"true":"false"
1304 , (decrypt_flag
)?
"true":"false")
1309 CK_MECHANISM mech
= { CKM_RSA_PKCS
, NULL_PTR
, 0 };
1311 rv
= pkcs11_functions
->C_SignInit(sc
->session
, &mech
, object
);
1314 plog("error in C_SignInit: %s"
1315 , enum_show(&pkcs11_return_names
, rv
));
1319 rv
= pkcs11_functions
->C_Sign(sc
->session
, (CK_BYTE_PTR
)in
, inlen
1323 plog("error in C_Sign: %s"
1324 , enum_show(&pkcs11_return_names
, rv
));
1328 else if (decrypt_flag
)
1330 CK_MECHANISM mech
= { CKM_RSA_X_509
, NULL_PTR
, 0 };
1334 /* PKCS#1 v1.5 8.1 encryption-block formatting */
1336 *p
++ = 0x01; /* BT (block type) 01 */
1337 padlen
= outlen
- 3 - inlen
;
1338 memset(p
, 0xFF, padlen
);
1341 memcpy(p
, in
, inlen
);
1343 rv
= pkcs11_functions
->C_DecryptInit(sc
->session
, &mech
, object
);
1346 plog("error in C_DecryptInit: %s"
1347 , enum_show(&pkcs11_return_names
, rv
));
1351 rv
= pkcs11_functions
->C_Decrypt(sc
->session
, out
, outlen
1355 plog("error in C_Decrypt: %s"
1356 , enum_show(&pkcs11_return_names
, rv
));
1362 plog("private key has neither sign nor decrypt flag set");
1366 if (siglen
> (CK_ULONG
)outlen
)
1368 plog("signature length (%lu) larger than allocated buffer (%d)"
1369 , siglen
, (int)outlen
);
1379 * encrypt data block with an RSA public key
1382 scx_encrypt(smartcard_t
*sc
, const u_char
*in
, size_t inlen
1383 , u_char
*out
, size_t *outlen
)
1387 CK_OBJECT_HANDLE object
;
1388 CK_ULONG len
= (CK_ULONG
)(*outlen
);
1389 CK_BBOOL encrypt_flag
;
1390 CK_ATTRIBUTE attr
[] = {
1391 { CKA_MODULUS
, NULL_PTR
, 0L },
1392 { CKA_PUBLIC_EXPONENT
, NULL_PTR
, 0L },
1393 { CKA_ENCRYPT
, &encrypt_flag
, sizeof(encrypt_flag
) }
1395 CK_MECHANISM mech
= { CKM_RSA_PKCS
, NULL_PTR
, 0 };
1397 if (!scx_establish_context(sc
))
1399 scx_release_context(sc
);
1403 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_PUBLIC_KEY
, sc
->id
))
1405 plog("unable to find public key with id '%s'", sc
->id
);
1409 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
, attr
, 3);
1412 plog("couldn't read the public key attributes: %s"
1413 , enum_show(&pkcs11_return_names
, rv
));
1414 scx_release_context(sc
);
1420 plog("public key cannot be used for encryption");
1421 scx_release_context(sc
);
1425 /* there must be enough space left for the PKCS#1 v1.5 padding */
1426 if (inlen
> attr
[0].ulValueLen
- 11)
1428 plog("smartcard input data length (%d) exceeds maximum of %lu bytes"
1429 , (int)inlen
, attr
[0].ulValueLen
- 11);
1430 if (!pkcs11_keep_state
)
1431 scx_release_context(sc
);
1435 rv
= pkcs11_functions
->C_EncryptInit(sc
->session
, &mech
, object
);
1439 if (rv
== CKR_FUNCTION_NOT_SUPPORTED
)
1441 RSA_public_key_t rsa
;
1442 chunk_t plain_text
= {(u_char
*)in
, inlen
};
1443 chunk_t cipher_text
;
1446 DBG_log("doing RSA encryption in software")
1448 attr
[0].pValue
= malloc(attr
[0].ulValueLen
);
1449 attr
[1].pValue
= malloc(attr
[1].ulValueLen
);
1451 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
, attr
, 2);
1454 plog("couldn't read modulus and public exponent: %s"
1455 , enum_show(&pkcs11_return_names
, rv
));
1456 free(attr
[0].pValue
);
1457 free(attr
[1].pValue
);
1458 scx_release_context(sc
);
1461 rsa
.k
= attr
[0].ulValueLen
;
1462 n_to_mpz(&rsa
.n
, attr
[0].pValue
, attr
[0].ulValueLen
);
1463 n_to_mpz(&rsa
.e
, attr
[1].pValue
, attr
[1].ulValueLen
);
1464 free(attr
[0].pValue
);
1465 free(attr
[1].pValue
);
1467 cipher_text
= RSA_encrypt(&rsa
, plain_text
);
1468 free_RSA_public_content(&rsa
);
1469 if (cipher_text
.ptr
== NULL
)
1471 plog("smartcard input data length is too large");
1472 if (!pkcs11_keep_state
)
1473 scx_release_context(sc
);
1477 memcpy(out
, cipher_text
.ptr
, cipher_text
.len
);
1478 *outlen
= cipher_text
.len
;
1479 free(cipher_text
.ptr
);
1481 if (!pkcs11_keep_state
)
1483 scx_release_context(sc
);
1489 plog("error in C_EncryptInit: %s"
1490 , enum_show(&pkcs11_return_names
, rv
));
1491 scx_release_context(sc
);
1497 DBG_log("doing RSA encryption on smartcard")
1499 rv
= pkcs11_functions
->C_Encrypt(sc
->session
, (u_char
*)in
, inlen
1503 plog("error in C_Encrypt: %s"
1504 , enum_show(&pkcs11_return_names
, rv
));
1505 scx_release_context(sc
);
1508 if (!pkcs11_keep_state
)
1509 scx_release_context(sc
);
1511 *outlen
= (size_t)len
;
1518 * decrypt a data block with an RSA private key
1521 scx_decrypt(smartcard_t
*sc
, const u_char
*in
, size_t inlen
1522 , u_char
*out
, size_t *outlen
)
1526 CK_OBJECT_HANDLE object
;
1527 CK_ULONG len
= (CK_ULONG
)(*outlen
);
1528 CK_BBOOL decrypt_flag
;
1529 CK_ATTRIBUTE attr
[] = {
1530 { CKA_DECRYPT
, &decrypt_flag
, sizeof(decrypt_flag
) }
1532 CK_MECHANISM mech
= { CKM_RSA_PKCS
, NULL_PTR
, 0 };
1534 if (!scx_establish_context(sc
) || !scx_login(sc
))
1536 scx_release_context(sc
);
1540 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_PRIVATE_KEY
, sc
->id
))
1542 plog("unable to find private key with id '%s'", sc
->id
);
1546 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
, attr
, 1);
1549 plog("couldn't read the private key attributes: %s"
1550 , enum_show(&pkcs11_return_names
, rv
));
1556 plog("private key cannot be used for decryption");
1557 scx_release_context(sc
);
1562 DBG_log("doing RSA decryption on smartcard")
1564 rv
= pkcs11_functions
->C_DecryptInit(sc
->session
, &mech
, object
);
1567 plog("error in C_DecryptInit: %s"
1568 , enum_show(&pkcs11_return_names
, rv
));
1569 scx_release_context(sc
);
1573 rv
= pkcs11_functions
->C_Decrypt(sc
->session
, (u_char
*)in
, inlen
1577 plog("error in C_Decrypt: %s"
1578 , enum_show(&pkcs11_return_names
, rv
));
1579 scx_release_context(sc
);
1582 if (!pkcs11_keep_state
)
1583 scx_release_context(sc
);
1585 *outlen
= (size_t)len
;
1592 /* receive an encrypted data block via whack,
1593 * decrypt it using a private RSA key and
1594 * return the decrypted data block via whack
1597 scx_op_via_whack(const char* msg
, int inbase
, int outbase
, sc_op_t op
1598 , const char* keyid
, int whackfd
)
1600 char inbuf
[RSA_MAX_OCTETS
];
1601 char outbuf
[2*RSA_MAX_OCTETS
+ 1];
1602 size_t outlen
= sizeof(inbuf
);
1604 smartcard_t
*sc
,*sc_new
;
1606 const char *number_slot_id
= "";
1608 err_t ugh
= ttodata(msg
, 0, inbase
, inbuf
, sizeof(inbuf
), &inlen
);
1610 /* no prefix - use default base */
1611 if (ugh
!= NULL
&& inbase
== 0)
1612 ugh
= ttodata(msg
, 0, DEFAULT_BASE
, inbuf
, sizeof(inbuf
), &inlen
);
1616 plog("format error in smartcard input data: %s", ugh
);
1622 number_slot_id
= (strneq(keyid
, SCX_TOKEN
, strlen(SCX_TOKEN
)))
1623 ? keyid
+ strlen(SCX_TOKEN
) : keyid
;
1626 sc_new
= scx_parse_number_slot_id(number_slot_id
);
1627 sc
= scx_add(sc_new
);
1631 DBG((op
== SC_OP_ENCRYPT
)? DBG_PRIVATE
:DBG_RAW
,
1632 DBG_dump("smartcard input data:\n", inbuf
, inlen
)
1635 if (op
== SC_OP_DECRYPT
)
1637 if (!sc
->valid
&& whackfd
!= NULL_FD
)
1638 scx_get_pin(sc
, whackfd
);
1642 loglog(RC_NOVALIDPIN
, "cannot decrypt without valid PIN");
1647 DBG(DBG_CONTROL
| DBG_CRYPT
,
1648 DBG_log("using RSA key from smartcard (slot: %d, id: %s)"
1649 , (int)sc
->slot
, sc
->id
)
1655 if (!scx_encrypt(sc
, inbuf
, inlen
, inbuf
, &outlen
))
1659 if (!scx_decrypt(sc
, inbuf
, inlen
, inbuf
, &outlen
))
1666 DBG((op
== SC_OP_DECRYPT
)? DBG_PRIVATE
:DBG_RAW
,
1667 DBG_dump("smartcard output data:\n", inbuf
, outlen
)
1670 if (outbase
== 0) /* use default base */
1671 outbase
= DEFAULT_BASE
;
1673 if (outbase
== 256) /* ascii plain text */
1674 whack_log(RC_COMMENT
, "%.*s", (int)outlen
, inbuf
);
1677 outlen
= datatot(inbuf
, outlen
, outbase
, outbuf
, sizeof(outbuf
));
1680 plog("error in output format conversion");
1683 whack_log(RC_COMMENT
, "%s", outbuf
);
1689 * get length of RSA key in bytes
1692 scx_get_keylength(smartcard_t
*sc
)
1696 CK_OBJECT_HANDLE object
;
1697 CK_ATTRIBUTE attr
[] = {{ CKA_MODULUS
, NULL_PTR
, 0}};
1702 if (!scx_pkcs11_find_object(sc
->session
, &object
, CKO_PRIVATE_KEY
, sc
->id
))
1704 plog("unable to find private key with id '%s'", sc
->id
);
1708 /* get the length of the private key */
1709 rv
= pkcs11_functions
->C_GetAttributeValue(sc
->session
, object
1710 , (CK_ATTRIBUTE_PTR
)&attr
, 1);
1713 plog("failed to get key length: %s"
1714 , enum_show(&pkcs11_return_names
, rv
));
1718 return attr
[0].ulValueLen
; /*Return key length in bytes */
1725 * prompt for pin and verify it
1728 scx_get_pin(smartcard_t
*sc
, int whackfd
)
1734 whack_log(RC_ENTERSECRET
, "need PIN for #%d (%s, id: %s, label: '%s')"
1735 , sc
->number
, scx_print_slot(sc
, ""), sc
->id
, sc
->label
);
1737 for (i
= 0; i
< SCX_MAX_PIN_TRIALS
; i
++)
1740 whack_log(RC_ENTERSECRET
, "invalid PIN, please try again");
1742 n
= read(whackfd
, pin
, BUF_LEN
);
1746 whack_log(RC_LOG_SERIOUS
, "read(whackfd) failed");
1750 if (strlen(pin
) == 0)
1752 whack_log(RC_LOG_SERIOUS
, "no PIN entered, aborted");
1757 sc
->pin
.len
= strlen(pin
);
1759 /* verify the pin */
1760 if (scx_verify_pin(sc
))
1762 sc
->pin
= chunk_create(pin
, strlen(pin
));
1763 sc
->pin
= chunk_clone(sc
->pin
);
1767 /* wrong pin - we try another round */
1768 sc
->pin
= chunk_empty
;
1772 whack_log(RC_SUCCESS
, "valid PIN");
1774 whack_log(RC_LOG_SERIOUS
, "invalid PIN, too many trials");
1777 whack_log(RC_LOG_SERIOUS
, "SMARTCARD support is deactivated in pluto/Makefile!");
1787 scx_free_pin(chunk_t
*pin
)
1789 if (pin
->ptr
!= NULL
)
1791 /* clear pin field in memory */
1792 memset(pin
->ptr
, '\0', pin
->len
);
1799 * frees a smartcard record
1802 scx_free(smartcard_t
*sc
)
1806 scx_release_context(sc
);
1809 scx_free_pin(&sc
->pin
);
1814 /* release of a smartcard record decreases the count by one
1815 " the record is freed when the counter reaches zero
1818 scx_release(smartcard_t
*sc
)
1820 if (sc
!= NULL
&& --sc
->count
== 0)
1822 smartcard_t
**pp
= &smartcards
;
1826 release_cert(sc
->last_cert
);
1832 * compare two smartcard records by comparing their slots and ids
1835 scx_same(smartcard_t
*a
, smartcard_t
*b
)
1837 if (a
->number
&& b
->number
)
1840 return a
->number
== b
->number
;
1844 /* same id and/or same slot */
1845 return (!a
->id
|| (b
->id
&& streq(a
->id
, b
->id
)))
1846 && (a
->any_slot
|| b
->any_slot
|| a
->slot
== b
->slot
);
1850 /* for each link pointing to the smartcard record
1851 " increase the count by one
1854 scx_share(smartcard_t
*sc
)
1861 * adds a smartcard record to the chained list
1864 scx_add(smartcard_t
*smartcard
)
1866 smartcard_t
*sc
= smartcards
;
1867 smartcard_t
**psc
= &smartcards
;
1871 if (scx_same(smartcard
, sc
)) /* already in chain, free smartcard record */
1873 scx_free(smartcard
);
1880 /* insert new smartcard record at the end of the chain */
1882 smartcard
->number
= ++sc_number
;
1883 smartcard
->count
= 1;
1884 DBG(DBG_CONTROL
| DBG_PARSING
,
1885 DBG_log(" smartcard #%d added", sc_number
)
1891 * get the smartcard that belongs to an X.509 certificate
1894 scx_get(x509cert_t
*cert
)
1896 smartcard_t
*sc
= smartcards
;
1900 if (sc
->last_cert
.u
.x509
== cert
)
1908 * prints either the slot number or 'any slot'
1911 scx_print_slot(smartcard_t
*sc
, const char *whitespace
)
1913 char *buf
= temporary_cyclic_buffer();
1916 snprintf(buf
, BUF_LEN
, "any slot");
1918 snprintf(buf
, BUF_LEN
, "slot: %s%lu", whitespace
, sc
->slot
);
1923 * list all smartcard info records in a chained list
1928 smartcard_t
*sc
= smartcards
;
1932 whack_log(RC_COMMENT
, " ");
1933 whack_log(RC_COMMENT
, "List of Smartcard Objects:");
1934 whack_log(RC_COMMENT
, " ");
1939 whack_log(RC_COMMENT
, "%T, #%d, count: %d"
1940 , &sc
->last_load
, utc
1943 whack_log(RC_COMMENT
, " %s, session %s, logged %s, has %s"
1944 , scx_print_slot(sc
, " ")
1945 , sc
->session_opened?
"opened" : "closed"
1946 , sc
->logged_in?
"in" : "out"
1947 , sc
->pinpad?
"pin pad"
1948 : ((sc
->pin
.ptr
== NULL
)?
"no pin"
1949 : sc
->valid?
"valid pin" : "invalid pin"));
1951 whack_log(RC_COMMENT
, " id: %s", sc
->id
);
1952 if (sc
->label
!= NULL
)
1953 whack_log(RC_COMMENT
, " label: '%s'", sc
->label
);
1954 if (sc
->last_cert
.type
== CERT_X509_SIGNATURE
)
1958 dntoa(buf
, BUF_LEN
, sc
->last_cert
.u
.x509
->subject
);
1959 whack_log(RC_COMMENT
, " subject: '%s'", buf
);