1 /*
2 * Copyright (c) 2005-2018 Alon Bar-Lev <alon.barlev@gmail.com>
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, or the BSD license.
7 *
8 * GNU General Public License (GPL) Version 2
9 * ===========================================
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING.GPL included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 *
24 * BSD License
25 * ============
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions are met:
28 *
29 * o Redistributions of source code must retain the above copyright notice,
30 * this list of conditions and the following disclaimer.
31 * o Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * o Neither the name of the Alon Bar-Lev nor the names of its
35 * contributors may be used to endorse or promote products derived from
36 * this software without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
39 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
42 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
43 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
44 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48 * POSSIBILITY OF SUCH DAMAGE.
49 */
50
51 #include "common.h"
52
53 #include <pkcs11-helper-1.0/pkcs11h-token.h>
54 #include "_pkcs11h-mem.h"
55 #include "_pkcs11h-session.h"
56 #include "_pkcs11h-util.h"
57 #include "_pkcs11h-token.h"
58
59 CK_RV
pkcs11h_token_freeTokenId(IN pkcs11h_token_id_t token_id)60 pkcs11h_token_freeTokenId (
61 IN pkcs11h_token_id_t token_id
62 ) {
63 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
64 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
65 _PKCS11H_ASSERT (token_id!=NULL);
66
67 _PKCS11H_DEBUG (
68 PKCS11H_LOG_DEBUG2,
69 "PKCS#11: pkcs11h_token_freeTokenId entry certificate_id=%p",
70 (void *)token_id
71 );
72
73 _pkcs11h_mem_free ((void *)&token_id);
74
75 _PKCS11H_DEBUG (
76 PKCS11H_LOG_DEBUG2,
77 "PKCS#11: pkcs11h_token_freeTokenId return"
78 );
79
80 return CKR_OK;
81 }
82
83 CK_RV
pkcs11h_token_duplicateTokenId(OUT pkcs11h_token_id_t * const to,IN const pkcs11h_token_id_t from)84 pkcs11h_token_duplicateTokenId (
85 OUT pkcs11h_token_id_t * const to,
86 IN const pkcs11h_token_id_t from
87 ) {
88 CK_RV rv = CKR_FUNCTION_FAILED;
89
90 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
91 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
92 _PKCS11H_ASSERT (to!=NULL);
93 _PKCS11H_ASSERT (from!=NULL);
94
95 _PKCS11H_DEBUG (
96 PKCS11H_LOG_DEBUG2,
97 "PKCS#11: pkcs11h_token_duplicateTokenId entry to=%p form=%p",
98 (void *)to,
99 (void *)from
100 );
101
102 *to = NULL;
103
104 if (
105 (rv = _pkcs11h_mem_duplicate (
106 (void*)to,
107 NULL,
108 from,
109 sizeof (struct pkcs11h_token_id_s)
110 )) != CKR_OK
111 ) {
112 goto cleanup;
113 }
114
115 rv = CKR_OK;
116
117 cleanup:
118
119 _PKCS11H_DEBUG (
120 PKCS11H_LOG_DEBUG2,
121 "PKCS#11: pkcs11h_token_duplicateTokenId return rv=%lu-'%s', *to=%p",
122 rv,
123 pkcs11h_getMessage (rv),
124 (void *)*to
125 );
126
127 return rv;
128 }
129
130 PKCS11H_BOOL
pkcs11h_token_sameTokenId(IN const pkcs11h_token_id_t a,IN const pkcs11h_token_id_t b)131 pkcs11h_token_sameTokenId (
132 IN const pkcs11h_token_id_t a,
133 IN const pkcs11h_token_id_t b
134 ) {
135 _PKCS11H_ASSERT (a!=NULL);
136 _PKCS11H_ASSERT (b!=NULL);
137
138 return (
139 !strcmp (a->manufacturerID, b->manufacturerID) &&
140 !strcmp (a->model, b->model) &&
141 !strcmp (a->serialNumber, b->serialNumber) &&
142 !strcmp (a->label, b->label)
143 );
144 }
145
146 CK_RV
_pkcs11h_token_getTokenId(IN const CK_TOKEN_INFO_PTR info,OUT pkcs11h_token_id_t * const p_token_id)147 _pkcs11h_token_getTokenId (
148 IN const CK_TOKEN_INFO_PTR info,
149 OUT pkcs11h_token_id_t * const p_token_id
150 ) {
151 pkcs11h_token_id_t token_id;
152 CK_RV rv = CKR_FUNCTION_FAILED;
153
154 _PKCS11H_ASSERT (info!=NULL);
155 _PKCS11H_ASSERT (p_token_id!=NULL);
156
157 _PKCS11H_DEBUG (
158 PKCS11H_LOG_DEBUG2,
159 "PKCS#11: _pkcs11h_token_getTokenId entry p_token_id=%p",
160 (void *)p_token_id
161 );
162
163 *p_token_id = NULL;
164
165 if ((rv = _pkcs11h_token_newTokenId (&token_id)) != CKR_OK) {
166 goto cleanup;
167 }
168
169 _pkcs11h_util_fixupFixedString (
170 token_id->label,
171 (char *)info->label,
172 sizeof (info->label)
173 );
174 _pkcs11h_util_fixupFixedString (
175 token_id->manufacturerID,
176 (char *)info->manufacturerID,
177 sizeof (info->manufacturerID)
178 );
179 _pkcs11h_util_fixupFixedString (
180 token_id->model,
181 (char *)info->model,
182 sizeof (info->model)
183 );
184 _pkcs11h_util_fixupFixedString (
185 token_id->serialNumber,
186 (char *)info->serialNumber,
187 sizeof (info->serialNumber)
188 );
189 strncpy (
190 token_id->display,
191 token_id->label,
192 sizeof (token_id->display)
193 );
194
195 *p_token_id = token_id;
196 token_id = NULL;
197 rv = CKR_OK;
198
199 cleanup:
200
201 if (token_id != NULL) {
202 _pkcs11h_mem_free ((void *)&token_id);
203 }
204
205 _PKCS11H_DEBUG (
206 PKCS11H_LOG_DEBUG2,
207 "PKCS#11: _pkcs11h_token_getTokenId return rv=%lu-'%s', *p_token_id=%p",
208 rv,
209 pkcs11h_getMessage (rv),
210 (void *)*p_token_id
211 );
212
213 return rv;
214 }
215
216 CK_RV
_pkcs11h_token_newTokenId(OUT pkcs11h_token_id_t * const p_token_id)217 _pkcs11h_token_newTokenId (
218 OUT pkcs11h_token_id_t * const p_token_id
219 ) {
220 CK_RV rv = CKR_FUNCTION_FAILED;
221
222 pkcs11h_token_id_t token_id = NULL;
223
224 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
225 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
226 _PKCS11H_ASSERT (p_token_id!=NULL);
227
228 _PKCS11H_DEBUG (
229 PKCS11H_LOG_DEBUG2,
230 "PKCS#11: _pkcs11h_token_newTokenId entry p_token_id=%p",
231 (void *)p_token_id
232 );
233
234 *p_token_id = NULL;
235
236 if ((rv = _pkcs11h_mem_malloc ((void *)&token_id, sizeof (struct pkcs11h_token_id_s))) != CKR_OK) {
237 goto cleanup;
238 }
239
240 *p_token_id = token_id;
241 token_id = NULL;
242
243 rv = CKR_OK;
244
245 cleanup:
246
247 if (token_id != NULL) {
248 _pkcs11h_mem_free ((void *)&token_id);
249 token_id = NULL;
250 }
251
252 _PKCS11H_DEBUG (
253 PKCS11H_LOG_DEBUG2,
254 "PKCS#11: _pkcs11h_token_newTokenId return rv=%lu-'%s', *p_token_id=%p",
255 rv,
256 pkcs11h_getMessage (rv),
257 (void *)*p_token_id
258 );
259
260 return rv;
261 }
262
263 CK_RV
pkcs11h_token_logout(IN const pkcs11h_token_id_t token_id)264 pkcs11h_token_logout (
265 IN const pkcs11h_token_id_t token_id
266 ) {
267 #if defined(ENABLE_PKCS11H_THREADING)
268 PKCS11H_BOOL mutex_locked = FALSE;
269 #endif
270 CK_RV rv = CKR_FUNCTION_FAILED;
271
272 _pkcs11h_session_t session = NULL;
273
274 _PKCS11H_ASSERT (token_id!=NULL);
275
276 _PKCS11H_DEBUG (
277 PKCS11H_LOG_DEBUG2,
278 "PKCS#11: pkcs11h_token_logout entry token_id=%p\n",
279 (void *)token_id
280 );
281
282 if (
283 (rv = _pkcs11h_session_getSessionByTokenId (
284 token_id,
285 &session
286 )) != CKR_OK
287 ) {
288 goto cleanup;
289 }
290
291 #if defined(ENABLE_PKCS11H_THREADING)
292 if ((rv = _pkcs11h_threading_mutexLock (&session->mutex)) != CKR_OK) {
293 goto cleanup;
294 }
295 mutex_locked = TRUE;
296 #endif
297
298 if (
299 (rv = _pkcs11h_session_logout (session)) != CKR_OK
300 ) {
301 goto cleanup;
302 }
303
304 rv = CKR_OK;
305
306 cleanup:
307
308 #if defined(ENABLE_PKCS11H_THREADING)
309 if (mutex_locked) {
310 _pkcs11h_threading_mutexRelease (&session->mutex);
311 mutex_locked = FALSE;
312 }
313 #endif
314
315 if (session != NULL) {
316 _pkcs11h_session_release (session);
317 session = NULL;
318 }
319
320 _PKCS11H_DEBUG (
321 PKCS11H_LOG_DEBUG2,
322 "PKCS#11: pkcs11h_token_logout return rv=%lu-'%s'",
323 rv,
324 pkcs11h_getMessage (rv)
325 );
326
327 return rv;
328 }
329
330 CK_RV
pkcs11h_token_login(IN const pkcs11h_token_id_t token_id,IN const PKCS11H_BOOL readonly,IN const char * const pin)331 pkcs11h_token_login (
332 IN const pkcs11h_token_id_t token_id,
333 IN const PKCS11H_BOOL readonly,
334 IN const char * const pin
335 ) {
336 #if defined(ENABLE_PKCS11H_THREADING)
337 PKCS11H_BOOL mutex_locked = FALSE;
338 #endif
339 CK_SLOT_ID slot = _PKCS11H_INVALID_SLOT_ID;
340 CK_ULONG pin_size = 0;
341 CK_RV rv = CKR_FUNCTION_FAILED;
342
343 _pkcs11h_session_t session = NULL;
344
345 _PKCS11H_ASSERT (token_id!=NULL);
346 /*_PKCS11H_ASSERT (pin!=NULL); NOT NEEDED*/
347
348 _PKCS11H_DEBUG (
349 PKCS11H_LOG_DEBUG2,
350 "PKCS#11: pkcs11h_token_login entry token_id=%p, readonly=%d\n",
351 (void *)token_id,
352 readonly ? 1 : 0
353 );
354
355 if (pin != NULL) {
356 pin_size = strlen (pin);
357 }
358
359 if (
360 (rv = _pkcs11h_session_getSessionByTokenId (
361 token_id,
362 &session
363 )) != CKR_OK
364 ) {
365 goto cleanup;
366 }
367
368 #if defined(ENABLE_PKCS11H_THREADING)
369 if ((rv = _pkcs11h_threading_mutexLock (&session->mutex)) != CKR_OK) {
370 goto cleanup;
371 }
372 mutex_locked = TRUE;
373 #endif
374
375 if (
376 (rv = _pkcs11h_session_logout (session)) != CKR_OK ||
377 (rv = _pkcs11h_session_reset (session, NULL, 0, &slot)) != CKR_OK ||
378 (rv = __pkcs11h_session_touch (session)) != CKR_OK ||
379 (rv = session->provider->f->C_OpenSession (
380 slot,
381 (
382 CKF_SERIAL_SESSION |
383 (readonly ? 0 : CKF_RW_SESSION)
384 ),
385 NULL_PTR,
386 NULL_PTR,
387 &session->session_handle
388 )) != CKR_OK
389 ) {
390 goto cleanup;
391 }
392 if (
393 (rv = session->provider->f->C_Login (
394 session->session_handle,
395 CKU_USER,
396 (CK_UTF8CHAR_PTR)pin,
397 pin_size
398 )) != CKR_OK
399 ) {
400 if (rv != CKR_USER_ALREADY_LOGGED_IN) {
401 goto cleanup;
402 }
403 }
404
405 rv = CKR_OK;
406
407 cleanup:
408
409 #if defined(ENABLE_PKCS11H_THREADING)
410 if (mutex_locked) {
411 _pkcs11h_threading_mutexRelease (&session->mutex);
412 mutex_locked = FALSE;
413 }
414 #endif
415
416 if (session != NULL) {
417 _pkcs11h_session_release (session);
418 session = NULL;
419 }
420
421 _PKCS11H_DEBUG (
422 PKCS11H_LOG_DEBUG2,
423 "PKCS#11: pkcs11h_token_login return rv=%lu-'%s'",
424 rv,
425 pkcs11h_getMessage (rv)
426 );
427
428 return rv;
429 }
430
431 #if defined(ENABLE_PKCS11H_TOKEN)
432
433 CK_RV
pkcs11h_token_ensureAccess(IN const pkcs11h_token_id_t token_id,IN void * const user_data,IN const unsigned mask_prompt)434 pkcs11h_token_ensureAccess (
435 IN const pkcs11h_token_id_t token_id,
436 IN void * const user_data,
437 IN const unsigned mask_prompt
438 ) {
439 #if defined(ENABLE_PKCS11H_THREADING)
440 PKCS11H_BOOL mutex_locked = FALSE;
441 #endif
442 _pkcs11h_session_t session = NULL;
443
444 CK_RV rv = CKR_FUNCTION_FAILED;
445 CK_SLOT_ID slot;
446
447 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
448 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
449 _PKCS11H_ASSERT (token_id!=NULL);
450 /*_PKCS11H_ASSERT (user_data) NOT NEEDED */
451
452 _PKCS11H_DEBUG (
453 PKCS11H_LOG_DEBUG2,
454 "PKCS#11: pkcs11h_token_ensureAccess entry token_id=%p, user_data=%p, mask_prompt=%08x",
455 (void *)token_id,
456 user_data,
457 mask_prompt
458 );
459
460 if (
461 (rv = _pkcs11h_session_getSessionByTokenId (
462 token_id,
463 &session
464 )) != CKR_OK
465 ) {
466 goto cleanup;
467 }
468
469 #if defined(ENABLE_PKCS11H_THREADING)
470 if ((rv = _pkcs11h_threading_mutexLock (&session->mutex)) != CKR_OK) {
471 goto cleanup;
472 }
473 mutex_locked = TRUE;
474 #endif
475
476
477 if (
478 (rv = _pkcs11h_session_reset (
479 session,
480 user_data,
481 mask_prompt,
482 &slot
483 )) != CKR_OK
484 ) {
485 goto cleanup;
486 }
487
488 rv = CKR_OK;
489
490 cleanup:
491
492 #if defined(ENABLE_PKCS11H_THREADING)
493 if (mutex_locked) {
494 _pkcs11h_threading_mutexRelease (&session->mutex);
495 mutex_locked = FALSE;
496 }
497 #endif
498
499 if (session != NULL) {
500 _pkcs11h_session_release (session);
501 session = NULL;
502 }
503
504 _PKCS11H_DEBUG (
505 PKCS11H_LOG_DEBUG2,
506 "PKCS#11: pkcs11h_token_ensureAccess return rv=%lu-'%s'",
507 rv,
508 pkcs11h_getMessage (rv)
509 );
510
511 return rv;
512 }
513
514 CK_RV
pkcs11h_token_freeTokenIdList(IN const pkcs11h_token_id_list_t token_id_list)515 pkcs11h_token_freeTokenIdList (
516 IN const pkcs11h_token_id_list_t token_id_list
517 ) {
518 pkcs11h_token_id_list_t _id = token_id_list;
519
520 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
521 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
522 /*_PKCS11H_ASSERT (token_id_list!=NULL); NOT NEEDED*/
523
524 _PKCS11H_DEBUG (
525 PKCS11H_LOG_DEBUG2,
526 "PKCS#11: pkcs11h_token_freeTokenIdList entry token_id_list=%p",
527 (void *)token_id_list
528 );
529
530 while (_id != NULL) {
531 pkcs11h_token_id_list_t x = _id;
532 _id = _id->next;
533 if (x->token_id != NULL) {
534 pkcs11h_token_freeTokenId (x->token_id);
535 }
536 x->next = NULL;
537 _pkcs11h_mem_free ((void *)&x);
538 }
539
540 _PKCS11H_DEBUG (
541 PKCS11H_LOG_DEBUG2,
542 "PKCS#11: pkcs11h_token_freeTokenIdList return"
543 );
544
545 return CKR_OK;
546 }
547
548 CK_RV
pkcs11h_token_enumTokenIds(IN const unsigned method,OUT pkcs11h_token_id_list_t * const p_token_id_list)549 pkcs11h_token_enumTokenIds (
550 IN const unsigned method,
551 OUT pkcs11h_token_id_list_t * const p_token_id_list
552 ) {
553 #if defined(ENABLE_PKCS11H_THREADING)
554 PKCS11H_BOOL mutex_locked = FALSE;
555 #endif
556
557 pkcs11h_token_id_list_t token_id_list = NULL;
558 _pkcs11h_provider_t current_provider;
559 CK_RV rv = CKR_FUNCTION_FAILED;
560
561 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
562 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
563 _PKCS11H_ASSERT (p_token_id_list!=NULL);
564
565 _PKCS11H_DEBUG (
566 PKCS11H_LOG_DEBUG2,
567 "PKCS#11: pkcs11h_token_enumTokenIds entry method=%u, p_token_id_list=%p",
568 method,
569 (void *)p_token_id_list
570 );
571
572 *p_token_id_list = NULL;
573
574 #if defined(ENABLE_PKCS11H_THREADING)
575 if ((rv = _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.global)) != CKR_OK) {
576 goto cleanup;
577 }
578 mutex_locked = TRUE;
579 #endif
580
581 for (
582 current_provider = _g_pkcs11h_data->providers;
583 current_provider != NULL;
584 current_provider = current_provider->next
585 ) {
586 CK_SLOT_ID_PTR slots = NULL;
587 CK_ULONG slotnum;
588 CK_SLOT_ID slot_index;
589
590 /*
591 * Skip disabled providers
592 */
593 if (!current_provider->enabled) {
594 continue;
595 }
596
597 if (
598 (rv = _pkcs11h_session_getSlotList (
599 current_provider,
600 CK_TRUE,
601 &slots,
602 &slotnum
603 )) != CKR_OK
604 ) {
605 _PKCS11H_DEBUG (
606 PKCS11H_LOG_DEBUG1,
607 "PKCS#11: Cannot get slot list for provider '%s' rv=%lu-'%s'",
608 current_provider->manufacturerID,
609 rv,
610 pkcs11h_getMessage (rv)
611 );
612 goto retry1;
613 }
614
615 for (
616 slot_index=0;
617 slot_index < slotnum;
618 slot_index++
619 ) {
620 pkcs11h_token_id_list_t entry = NULL;
621 CK_TOKEN_INFO info;
622
623 if (
624 (rv = _pkcs11h_mem_malloc (
625 (void *)&entry,
626 sizeof (struct pkcs11h_token_id_list_s)
627 )) != CKR_OK ||
628 (rv = current_provider->f->C_GetTokenInfo (
629 slots[slot_index],
630 &info
631 )) != CKR_OK ||
632 (rv = _pkcs11h_token_getTokenId (
633 &info,
634 &entry->token_id
635 ))
636 ) {
637 goto retry11;
638 }
639
640 entry->next = token_id_list;
641 token_id_list = entry;
642 entry = NULL;
643 rv = CKR_OK;
644
645 retry11:
646
647 if (entry != NULL) {
648 pkcs11h_token_freeTokenIdList (entry);
649 entry = NULL;
650 }
651 }
652
653 retry1:
654
655 if (slots != NULL) {
656 _pkcs11h_mem_free ((void *)&slots);
657 slots = NULL;
658 }
659 }
660
661 if (method == PKCS11H_ENUM_METHOD_CACHE) {
662 _pkcs11h_session_t session = NULL;
663
664 for (
665 session = _g_pkcs11h_data->sessions;
666 session != NULL;
667 session = session->next
668 ) {
669 pkcs11h_token_id_list_t entry = NULL;
670 PKCS11H_BOOL found = FALSE;
671
672 for (
673 entry = token_id_list;
674 entry != NULL && !found;
675 entry = entry->next
676 ) {
677 if (
678 pkcs11h_token_sameTokenId (
679 session->token_id,
680 entry->token_id
681 )
682 ) {
683 found = TRUE;
684 }
685 }
686
687 if (!found) {
688 entry = NULL;
689
690 if (
691 (rv = _pkcs11h_mem_malloc (
692 (void *)&entry,
693 sizeof (struct pkcs11h_token_id_list_s)
694 )) != CKR_OK ||
695 (rv = pkcs11h_token_duplicateTokenId (
696 &entry->token_id,
697 session->token_id
698 )) != CKR_OK
699 ) {
700 goto retry12;
701 }
702
703 entry->next = token_id_list;
704 token_id_list = entry;
705 entry = NULL;
706
707 retry12:
708
709 if (entry != NULL) {
710 if (entry->token_id != NULL) {
711 pkcs11h_token_freeTokenId (entry->token_id);
712 }
713 _pkcs11h_mem_free ((void *)&entry);
714 }
715 }
716 }
717 }
718
719 *p_token_id_list = token_id_list;
720 token_id_list = NULL;
721 rv = CKR_OK;
722
723 cleanup:
724
725 if (token_id_list != NULL) {
726 pkcs11h_token_freeTokenIdList (token_id_list);
727 token_id_list = NULL;
728 }
729
730 #if defined(ENABLE_PKCS11H_THREADING)
731 if (mutex_locked) {
732 rv = _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.global);
733 mutex_locked = FALSE;
734 }
735 #endif
736
737 _PKCS11H_DEBUG (
738 PKCS11H_LOG_DEBUG2,
739 "PKCS#11: pkcs11h_token_enumTokenIds return rv=%lu-'%s', *p_token_id_list=%p",
740 rv,
741 pkcs11h_getMessage (rv),
742 (void *)p_token_id_list
743 );
744
745 return rv;
746 }
747
748 #endif /* ENABLE_PKCS11H_TOKEN */
749