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 #if defined(ENABLE_PKCS11H_CERTIFICATE)
54
55 #include <pkcs11-helper-1.0/pkcs11h-token.h>
56 #include <pkcs11-helper-1.0/pkcs11h-certificate.h>
57 #include "_pkcs11h-mem.h"
58 #include "_pkcs11h-sys.h"
59 #include "_pkcs11h-crypto.h"
60 #include "_pkcs11h-session.h"
61 #include "_pkcs11h-token.h"
62 #include "_pkcs11h-certificate.h"
63
64 enum __pkcs11h_private_op_e {
65 __pkcs11h_private_op_sign=0,
66 __pkcs11h_private_op_sign_recover,
67 __pkcs11h_private_op_decrypt,
68 __pkcs11h_private_op_unwrap
69 };
70
71 static
72 CK_RV
73 __pkcs11h_certificate_doPrivateOperation (
74 IN const pkcs11h_certificate_t certificate,
75 IN const enum __pkcs11h_private_op_e op,
76 IN const CK_MECHANISM_TYPE mech_type,
77 IN const unsigned char * const source,
78 IN const size_t source_size,
79 OUT unsigned char * const target,
80 IN OUT size_t * const p_target_size
81 );
82
83 static
84 CK_RV
85 __pkcs11h_certificate_loadCertificate (
86 IN const pkcs11h_certificate_t certificate
87 );
88
89 static
90 CK_RV
91 __pkcs11h_certificate_updateCertificateIdDescription (
92 IN OUT pkcs11h_certificate_id_t certificate_id
93 );
94
95 static
96 CK_RV
97 __pkcs11h_certificate_getKeyAttributes (
98 IN const pkcs11h_certificate_t certificate
99 );
100
101 static
102 CK_RV
103 __pkcs11h_certificate_splitCertificateIdList (
104 IN const pkcs11h_certificate_id_list_t cert_id_all,
105 OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
106 OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
107 );
108
109 PKCS11H_BOOL
_pkcs11h_certificate_isBetterCertificate(IN const unsigned char * const current,IN const size_t current_size,IN const unsigned char * const newone,IN const size_t newone_size)110 _pkcs11h_certificate_isBetterCertificate (
111 IN const unsigned char * const current,
112 IN const size_t current_size,
113 IN const unsigned char * const newone,
114 IN const size_t newone_size
115 ) {
116 PKCS11H_BOOL is_better = FALSE;
117
118 /*_PKCS11H_ASSERT (current!=NULL); NOT NEEDED */
119 _PKCS11H_ASSERT (newone!=NULL);
120
121 _PKCS11H_DEBUG (
122 PKCS11H_LOG_DEBUG2,
123 "PKCS#11: _pkcs11h_certificate_isBetterCertificate entry current=%p, current_size="P_Z", newone=%p, newone_size="P_Z"",
124 current,
125 current_size,
126 newone,
127 newone_size
128 );
129
130 /*
131 * First certificae
132 * always select
133 */
134 if (current_size == 0 || current == NULL) {
135 is_better = TRUE;
136 }
137 else {
138 time_t notAfterCurrent, notAfterNew;
139
140 if (
141 !_g_pkcs11h_crypto_engine.certificate_get_expiration (
142 _g_pkcs11h_crypto_engine.global_data,
143 current,
144 current_size,
145 ¬AfterCurrent
146 )
147 ) {
148 notAfterCurrent = (time_t)0;
149 }
150
151 if (
152 !_g_pkcs11h_crypto_engine.certificate_get_expiration (
153 _g_pkcs11h_crypto_engine.global_data,
154 newone,
155 newone_size,
156 ¬AfterNew
157 )
158 ) {
159 notAfterCurrent = (time_t)0;
160 }
161
162 _PKCS11H_DEBUG (
163 PKCS11H_LOG_DEBUG2,
164 "PKCS#11: _pkcs11h_certificate_isBetterCertificate notAfterCurrent='%s', notAfterNew='%s'",
165 asctime (localtime (¬AfterCurrent)),
166 asctime (localtime (¬AfterNew))
167 );
168
169 is_better = notAfterNew > notAfterCurrent;
170 }
171
172 _PKCS11H_DEBUG (
173 PKCS11H_LOG_DEBUG2,
174 "PKCS#11: _pkcs11h_certificate_isBetterCertificate return is_better=%d",
175 is_better ? 1 : 0
176 );
177
178 return is_better;
179 }
180
181 CK_RV
_pkcs11h_certificate_newCertificateId(OUT pkcs11h_certificate_id_t * const p_certificate_id)182 _pkcs11h_certificate_newCertificateId (
183 OUT pkcs11h_certificate_id_t * const p_certificate_id
184 ) {
185 CK_RV rv = CKR_FUNCTION_FAILED;
186
187 _PKCS11H_ASSERT (p_certificate_id!=NULL);
188
189 _PKCS11H_DEBUG (
190 PKCS11H_LOG_DEBUG2,
191 "PKCS#11: _pkcs11h_certificate_newCertificateId entry p_certificate_id=%p",
192 (void *)p_certificate_id
193 );
194
195 *p_certificate_id = NULL;
196
197 if (
198 (rv = _pkcs11h_mem_malloc (
199 (void *)p_certificate_id,
200 sizeof (struct pkcs11h_certificate_id_s)
201 )) != CKR_OK
202 ) {
203 goto cleanup;
204 }
205
206 rv = CKR_OK;
207
208 cleanup:
209
210 _PKCS11H_DEBUG (
211 PKCS11H_LOG_DEBUG2,
212 "PKCS#11: _pkcs11h_certificate_newCertificateId return rv=%lu-'%s', *p_certificate_id=%p",
213 rv,
214 pkcs11h_getMessage (rv),
215 (void *)*p_certificate_id
216 );
217
218 return rv;
219 }
220
221 static
222 CK_RV
__pkcs11h_certificate_loadCertificate(IN const pkcs11h_certificate_t certificate)223 __pkcs11h_certificate_loadCertificate (
224 IN const pkcs11h_certificate_t certificate
225 ) {
226 /*
227 * THREADING:
228 * certificate->mutex must be locked
229 */
230 #if defined(ENABLE_PKCS11H_THREADING)
231 PKCS11H_BOOL mutex_locked = FALSE;
232 #endif
233 CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
234 CK_ATTRIBUTE cert_filter[] = {
235 {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)},
236 {CKA_ID, NULL, 0}
237 };
238
239 CK_OBJECT_HANDLE *objects = NULL;
240 CK_ULONG objects_found = 0;
241 CK_RV rv = CKR_FUNCTION_FAILED;
242
243 CK_ULONG i;
244
245 _PKCS11H_ASSERT (certificate!=NULL);
246 _PKCS11H_ASSERT (certificate->id!=NULL);
247
248 /* Must be after assert */
249 cert_filter[1].pValue = certificate->id->attrCKA_ID;
250 cert_filter[1].ulValueLen = certificate->id->attrCKA_ID_size;
251
252 _PKCS11H_DEBUG (
253 PKCS11H_LOG_DEBUG2,
254 "PKCS#11: __pkcs11h_certificate_loadCertificate entry certificate=%p",
255 (void *)certificate
256 );
257
258 #if defined(ENABLE_PKCS11H_THREADING)
259 if ((rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) != CKR_OK) {
260 goto cleanup;
261 }
262 mutex_locked = TRUE;
263 #endif
264
265 if ((rv = _pkcs11h_session_validate (certificate->session)) != CKR_OK) {
266 goto cleanup;
267 }
268
269 if (
270 (rv = _pkcs11h_session_findObjects (
271 certificate->session,
272 cert_filter,
273 sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
274 &objects,
275 &objects_found
276 )) != CKR_OK
277 ) {
278 goto cleanup;
279 }
280
281 for (i=0;i < objects_found;i++) {
282 CK_ATTRIBUTE attrs[] = {
283 {CKA_VALUE, NULL, 0}
284 };
285
286 if (
287 (rv = _pkcs11h_session_getObjectAttributes (
288 certificate->session,
289 objects[i],
290 attrs,
291 sizeof (attrs) / sizeof (CK_ATTRIBUTE)
292 )) != CKR_OK
293 ) {
294 _PKCS11H_DEBUG (
295 PKCS11H_LOG_DEBUG1,
296 "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%lu-'%s'",
297 certificate->session->provider->manufacturerID,
298 objects[i],
299 rv,
300 pkcs11h_getMessage (rv)
301 );
302 }
303 else {
304 if (
305 _pkcs11h_certificate_isBetterCertificate (
306 certificate->id->certificate_blob,
307 certificate->id->certificate_blob_size,
308 attrs[0].pValue,
309 attrs[0].ulValueLen
310 )
311 ) {
312 if (certificate->id->certificate_blob != NULL) {
313 _pkcs11h_mem_free ((void *)&certificate->id->certificate_blob);
314 }
315
316 if (
317 (rv = _pkcs11h_mem_duplicate (
318 (void*)&certificate->id->certificate_blob,
319 &certificate->id->certificate_blob_size,
320 attrs[0].pValue,
321 attrs[0].ulValueLen
322 )) != CKR_OK
323 ) {
324 goto retry1;
325 }
326 }
327 }
328
329 rv = CKR_OK;
330
331 retry1:
332
333 _pkcs11h_session_freeObjectAttributes (
334 attrs,
335 sizeof (attrs) / sizeof (CK_ATTRIBUTE)
336 );
337
338 if (rv != CKR_OK) {
339 goto cleanup;
340 }
341 }
342
343 if (certificate->id->certificate_blob == NULL) {
344 rv = CKR_ATTRIBUTE_VALUE_INVALID;
345 goto cleanup;
346 }
347
348 if ((rv = __pkcs11h_certificate_updateCertificateIdDescription (certificate->id)) != CKR_OK) {
349 goto cleanup;
350 }
351
352 rv = CKR_OK;
353
354 cleanup:
355
356 #if defined(ENABLE_PKCS11H_THREADING)
357 if (mutex_locked) {
358 _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
359 mutex_locked = FALSE;
360 }
361 #endif
362
363 if (objects != NULL) {
364 _pkcs11h_mem_free ((void *)&objects);
365 }
366
367 /*
368 * No need to free allocated objects
369 * on error, since the certificate_id
370 * should be free by caller.
371 */
372
373 _PKCS11H_DEBUG (
374 PKCS11H_LOG_DEBUG2,
375 "PKCS#11: __pkcs11h_certificate_loadCertificate return rv=%lu-'%s'",
376 rv,
377 pkcs11h_getMessage (rv)
378 );
379
380 return rv;
381 }
382
383 static
384 CK_RV
__pkcs11h_certificate_updateCertificateIdDescription(IN OUT pkcs11h_certificate_id_t certificate_id)385 __pkcs11h_certificate_updateCertificateIdDescription (
386 IN OUT pkcs11h_certificate_id_t certificate_id
387 ) {
388 static const char * separator = " on ";
389 static const char * unknown = "UNKNOWN";
390
391 _PKCS11H_ASSERT (certificate_id!=NULL);
392
393 _PKCS11H_DEBUG (
394 PKCS11H_LOG_DEBUG2,
395 "PKCS#11: __pkcs11h_certificate_updateCertificateIdDescription entry certificate_id=%p",
396 (void *)certificate_id
397 );
398
399 if (
400 certificate_id->certificate_blob_size != 0 &&
401 !_g_pkcs11h_crypto_engine.certificate_get_dn (
402 _g_pkcs11h_crypto_engine.global_data,
403 certificate_id->certificate_blob,
404 certificate_id->certificate_blob_size,
405 certificate_id->displayName,
406 sizeof (certificate_id->displayName)
407 )
408 ) {
409 certificate_id->displayName[0] = '\x0';
410 }
411
412 if (strlen (certificate_id->displayName) == 0) {
413 strncpy (
414 certificate_id->displayName,
415 unknown,
416 sizeof (certificate_id->displayName)-1
417 );
418 }
419
420 /*
421 * Try to avoid using snprintf,
422 * may be unavailable
423 */
424 strncat (
425 certificate_id->displayName,
426 separator,
427 sizeof (certificate_id->displayName)-1-strlen (certificate_id->displayName)
428 );
429 strncat (
430 certificate_id->displayName,
431 certificate_id->token_id->display,
432 sizeof (certificate_id->displayName)-1-strlen (certificate_id->displayName)
433 );
434 certificate_id->displayName[sizeof (certificate_id->displayName) - 1] = '\0';
435
436 _PKCS11H_DEBUG (
437 PKCS11H_LOG_DEBUG2,
438 "PKCS#11: __pkcs11h_certificate_updateCertificateIdDescription return displayName='%s'",
439 certificate_id->displayName
440 );
441
442 return CKR_OK;
443 }
444
445 static
446 CK_RV
__pkcs11h_certificate_getKeyAttributes(IN const pkcs11h_certificate_t certificate)447 __pkcs11h_certificate_getKeyAttributes (
448 IN const pkcs11h_certificate_t certificate
449 ) {
450 #if defined(ENABLE_PKCS11H_THREADING)
451 PKCS11H_BOOL mutex_locked = FALSE;
452 #endif
453 CK_RV rv = CKR_FUNCTION_FAILED;
454
455 PKCS11H_BOOL op_succeed = FALSE;
456 PKCS11H_BOOL login_retry = FALSE;
457
458 _PKCS11H_ASSERT (certificate!=NULL);
459
460 _PKCS11H_DEBUG (
461 PKCS11H_LOG_DEBUG2,
462 "PKCS#11: __pkcs11h_certificate_getKeyAttributes entry certificate=%p",
463 (void *)certificate
464 );
465
466 #if defined(ENABLE_PKCS11H_THREADING)
467 if ((rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) != CKR_OK) {
468 goto cleanup;
469 }
470 mutex_locked = TRUE;
471 #endif
472
473 certificate->mask_private_mode = 0;
474 while (!op_succeed) {
475 CK_ATTRIBUTE key_attrs[] = {
476 {CKA_SIGN, NULL, 0},
477 {CKA_SIGN_RECOVER, NULL, 0},
478 {CKA_DECRYPT, NULL, 0},
479 {CKA_UNWRAP, NULL, 0}
480 };
481
482 /*
483 * Don't try invalid object
484 */
485 if (certificate->key_handle == _PKCS11H_INVALID_OBJECT_HANDLE) {
486 rv = CKR_OBJECT_HANDLE_INVALID;
487 goto retry;
488 }
489
490 if (certificate->session->provider->mask_private_mode != 0) {
491 certificate->mask_private_mode = certificate->session->provider->mask_private_mode;
492 _PKCS11H_DEBUG (
493 PKCS11H_LOG_DEBUG1,
494 "PKCS#11: Key attributes enforced by provider (%08x)",
495 certificate->mask_private_mode
496 );
497
498 op_succeed = TRUE;
499 }
500 else {
501 CK_BBOOL *key_attrs_sign;
502 CK_BBOOL *key_attrs_sign_recover;
503 CK_BBOOL *key_attrs_decrypt;
504 CK_BBOOL *key_attrs_unwrap;
505
506 if (
507 (rv = _pkcs11h_session_getObjectAttributes (
508 certificate->session,
509 certificate->key_handle,
510 key_attrs,
511 sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
512 )) != CKR_OK
513 ) {
514 goto retry;
515 }
516
517 key_attrs_sign = (CK_BBOOL *)key_attrs[0].pValue;
518 key_attrs_sign_recover = (CK_BBOOL *)key_attrs[1].pValue;
519 key_attrs_decrypt = (CK_BBOOL *)key_attrs[2].pValue;
520 key_attrs_unwrap = (CK_BBOOL *)key_attrs[3].pValue;
521
522 if (key_attrs_sign != NULL && *key_attrs_sign != CK_FALSE) {
523 certificate->mask_private_mode |= PKCS11H_PRIVATEMODE_MASK_SIGN;
524 }
525 if (key_attrs_sign_recover != NULL && *key_attrs_sign_recover != CK_FALSE) {
526 certificate->mask_private_mode |= PKCS11H_PRIVATEMODE_MASK_RECOVER;
527 }
528 if (key_attrs_decrypt != NULL && *key_attrs_decrypt != CK_FALSE) {
529 certificate->mask_private_mode |= PKCS11H_PRIVATEMODE_MASK_DECRYPT;
530 }
531 if (key_attrs_unwrap != NULL && *key_attrs_unwrap != CK_FALSE) {
532 certificate->mask_private_mode |= PKCS11H_PRIVATEMODE_MASK_UNWRAP;
533 }
534 if (certificate->mask_private_mode == 0) {
535 rv = CKR_KEY_TYPE_INCONSISTENT;
536 goto retry;
537 }
538
539 _PKCS11H_DEBUG (
540 PKCS11H_LOG_DEBUG1,
541 "PKCS#11: Key attributes loaded (%08x)",
542 certificate->mask_private_mode
543 );
544
545 op_succeed = TRUE;
546 }
547
548 rv = CKR_OK;
549
550 retry:
551
552 _pkcs11h_session_freeObjectAttributes (
553 key_attrs,
554 sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
555 );
556
557 if (!op_succeed) {
558 if (!login_retry) {
559 _PKCS11H_DEBUG (
560 PKCS11H_LOG_DEBUG1,
561 "PKCS#11: Get private key attributes failed: %ld:'%s'",
562 rv,
563 pkcs11h_getMessage (rv)
564 );
565
566 rv = _pkcs11h_certificate_resetSession (
567 certificate,
568 FALSE,
569 TRUE
570 );
571
572 login_retry = TRUE;
573 }
574
575 if (rv != CKR_OK) {
576 goto cleanup;
577 }
578 }
579 }
580
581 rv = CKR_OK;
582
583 cleanup:
584
585 #if defined(ENABLE_PKCS11H_THREADING)
586 if (mutex_locked) {
587 _pkcs11h_threading_mutexRelease (&certificate->mutex);
588 mutex_locked = FALSE;
589 }
590 #endif
591
592 _PKCS11H_DEBUG (
593 PKCS11H_LOG_DEBUG2,
594 "PKCS#11: __pkcs11h_certificate_getKeyAttributes return rv=%lu-'%s'",
595 rv,
596 pkcs11h_getMessage (rv)
597 );
598
599 return rv;
600 }
601
602 CK_RV
_pkcs11h_certificate_validateSession(IN const pkcs11h_certificate_t certificate)603 _pkcs11h_certificate_validateSession (
604 IN const pkcs11h_certificate_t certificate
605 ) {
606 /*
607 * THREADING:
608 * certificate->mutex must be locked
609 * certificate->session->mutex must be locked
610 */
611 CK_RV rv = CKR_FUNCTION_FAILED;
612
613 _PKCS11H_ASSERT (certificate!=NULL);
614
615 _PKCS11H_DEBUG (
616 PKCS11H_LOG_DEBUG2,
617 "PKCS#11: _pkcs11h_certificate_validateSession entry certificate=%p",
618 (void *)certificate
619 );
620
621 if ((rv = _pkcs11h_session_validate (certificate->session)) != CKR_OK) {
622 goto cleanup;
623 }
624
625 if (certificate->key_handle == _PKCS11H_INVALID_OBJECT_HANDLE) {
626 rv = CKR_OBJECT_HANDLE_INVALID;
627 goto cleanup;
628 }
629
630 rv = CKR_OK;
631
632 cleanup:
633
634 _PKCS11H_DEBUG (
635 PKCS11H_LOG_DEBUG2,
636 "PKCS#11: _pkcs11h_certificate_validateSession return rv=%lu-'%s'",
637 rv,
638 pkcs11h_getMessage (rv)
639 );
640
641 return rv;
642 }
643
644 CK_RV
_pkcs11h_certificate_resetSession(IN const pkcs11h_certificate_t certificate,IN const PKCS11H_BOOL public_only,IN const PKCS11H_BOOL session_mutex_locked)645 _pkcs11h_certificate_resetSession (
646 IN const pkcs11h_certificate_t certificate,
647 IN const PKCS11H_BOOL public_only,
648 IN const PKCS11H_BOOL session_mutex_locked
649 ) {
650 /*
651 * THREADING:
652 * certificate->mutex must be locked
653 */
654 #if defined(ENABLE_PKCS11H_THREADING)
655 PKCS11H_BOOL mutex_locked = FALSE;
656 #endif
657 PKCS11H_BOOL session_valid = FALSE;
658 CK_OBJECT_HANDLE cert_handle;
659 CK_RV rv = CKR_FUNCTION_FAILED;
660
661 _PKCS11H_ASSERT (certificate!=NULL);
662
663 _PKCS11H_DEBUG (
664 PKCS11H_LOG_DEBUG2,
665 "PKCS#11: _pkcs11h_certificate_resetSession entry certificate=%p, public_only=%d, session_mutex_locked=%d",
666 (void *)certificate,
667 public_only ? 1 : 0,
668 session_mutex_locked ? 1 : 0
669 );
670
671 #if defined(ENABLE_PKCS11H_THREADING)
672 if (!session_mutex_locked) {
673 if ((rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) != CKR_OK) {
674 goto cleanup;
675 }
676 mutex_locked = TRUE;
677 }
678 #endif
679
680 /*
681 * First, if session seems to be valid
682 * and key handle is invalid (hard-set),
683 * try to fetch key handle,
684 * maybe the token is already logged in
685 */
686 if (
687 certificate->session->session_handle != _PKCS11H_INVALID_SESSION_HANDLE &&
688 certificate->key_handle == _PKCS11H_INVALID_OBJECT_HANDLE
689 ) {
690 if (!public_only || certificate->session->provider->cert_is_private) {
691 if (
692 (rv = _pkcs11h_session_getObjectById (
693 certificate->session,
694 CKO_PRIVATE_KEY,
695 certificate->id->attrCKA_ID,
696 certificate->id->attrCKA_ID_size,
697 &certificate->key_handle
698 )) == CKR_OK
699 ) {
700 session_valid = TRUE;
701 }
702 else {
703 certificate->key_handle = _PKCS11H_INVALID_OBJECT_HANDLE;
704 }
705 }
706 else {
707 if (
708 (rv = _pkcs11h_session_getObjectById (
709 certificate->session,
710 CKO_CERTIFICATE,
711 certificate->id->attrCKA_ID,
712 certificate->id->attrCKA_ID_size,
713 &cert_handle
714 )) == CKR_OK
715 ) {
716 session_valid = TRUE;
717 }
718 else {
719 certificate->key_handle = _PKCS11H_INVALID_OBJECT_HANDLE;
720 }
721 }
722 }
723
724 if (!session_valid) {
725 certificate->key_handle = _PKCS11H_INVALID_OBJECT_HANDLE;
726
727 if (
728 (rv = _pkcs11h_session_login (
729 certificate->session,
730 public_only,
731 TRUE,
732 certificate->user_data,
733 certificate->mask_prompt
734 )) != CKR_OK
735 ) {
736 goto cleanup;
737 }
738 }
739
740 if (!public_only && certificate->key_handle == _PKCS11H_INVALID_OBJECT_HANDLE) {
741 if (
742 (rv = _pkcs11h_session_getObjectById (
743 certificate->session,
744 CKO_PRIVATE_KEY,
745 certificate->id->attrCKA_ID,
746 certificate->id->attrCKA_ID_size,
747 &certificate->key_handle
748 )) != CKR_OK
749 ) {
750 goto cleanup;
751 }
752 }
753
754 rv = CKR_OK;
755
756 cleanup:
757
758 #if defined(ENABLE_PKCS11H_THREADING)
759 if (mutex_locked) {
760 _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
761 mutex_locked = FALSE;
762 }
763 #endif
764
765 _PKCS11H_DEBUG (
766 PKCS11H_LOG_DEBUG2,
767 "PKCS#11: _pkcs11h_certificate_resetSession return rv=%lu-'%s'",
768 rv,
769 pkcs11h_getMessage (rv)
770 );
771
772 return rv;
773 }
774
775 static
776 CK_RV
__pkcs11h_certificate_doPrivateOperation(IN const pkcs11h_certificate_t certificate,IN const enum __pkcs11h_private_op_e op,IN const CK_MECHANISM_TYPE mech_type,IN const unsigned char * const source,IN const size_t source_size,OUT unsigned char * const target,IN OUT size_t * const p_target_size)777 __pkcs11h_certificate_doPrivateOperation (
778 IN const pkcs11h_certificate_t certificate,
779 IN const enum __pkcs11h_private_op_e op,
780 IN const CK_MECHANISM_TYPE mech_type,
781 IN const unsigned char * const source,
782 IN const size_t source_size,
783 OUT unsigned char * const target,
784 IN OUT size_t * const p_target_size
785 ) {
786 #if defined(ENABLE_PKCS11H_THREADING)
787 PKCS11H_BOOL mutex_locked = FALSE;
788 #endif
789 CK_MECHANISM mech = {
790 mech_type, NULL, 0
791 };
792
793 /* CK_BBOOL wrap_attrs_false = CK_FALSE; */
794 CK_BBOOL wrap_attrs_true = CK_TRUE;
795 CK_OBJECT_CLASS class = CKO_SECRET_KEY;
796 CK_KEY_TYPE keytype = CKK_GENERIC_SECRET;
797 CK_ATTRIBUTE wrap_attrs[] = {
798 {CKA_CLASS, &class, sizeof (class)},
799 {CKA_KEY_TYPE, &keytype, sizeof (keytype)},
800 {CKA_EXTRACTABLE, &wrap_attrs_true, sizeof (wrap_attrs_true)}
801 /* OpenSC fail! {CKA_TOKEN, &wrap_attrs_false, sizeof (wrap_attrs_false)} */
802 };
803 CK_ATTRIBUTE wrap_value[] = {
804 {CKA_VALUE, target, 0}
805 };
806 CK_OBJECT_HANDLE wrap_key = _PKCS11H_INVALID_OBJECT_HANDLE;
807
808 CK_RV rv = CKR_FUNCTION_FAILED;
809 PKCS11H_BOOL login_retry = FALSE;
810 PKCS11H_BOOL op_succeed = FALSE;
811
812 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
813 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
814 _PKCS11H_ASSERT (certificate!=NULL);
815 _PKCS11H_ASSERT (source!=NULL);
816 /*_PKCS11H_ASSERT (target); NOT NEEDED*/
817 _PKCS11H_ASSERT (p_target_size!=NULL);
818
819 _PKCS11H_DEBUG (
820 PKCS11H_LOG_DEBUG2,
821 "PKCS#11: __pkcs11h_certificate_doPrivateOperation entry certificate=%p, op=%d, mech_type=%ld, source=%p, source_size="P_Z", target=%p, *p_target_size="P_Z"",
822 (void *)certificate,
823 op,
824 mech_type,
825 source,
826 source_size,
827 target,
828 target != NULL ? *p_target_size : 0
829 );
830
831 if (target == NULL) {
832 *p_target_size = 0;
833 }
834
835 #if defined(ENABLE_PKCS11H_THREADING)
836 if ((rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) != CKR_OK) {
837 goto cleanup;
838 }
839 mutex_locked = TRUE;
840 #endif
841
842 while (!op_succeed) {
843 CK_ULONG size;
844
845 if (!certificate->operation_active) {
846 if ((rv = _pkcs11h_certificate_validateSession (certificate)) != CKR_OK) {
847 goto retry;
848 }
849
850 switch (op) {
851 case __pkcs11h_private_op_sign:
852 rv = certificate->session->provider->f->C_SignInit (
853 certificate->session->session_handle,
854 &mech,
855 certificate->key_handle
856 );
857 break;
858 case __pkcs11h_private_op_sign_recover:
859 rv = certificate->session->provider->f->C_SignRecoverInit (
860 certificate->session->session_handle,
861 &mech,
862 certificate->key_handle
863 );
864 break;
865 case __pkcs11h_private_op_decrypt:
866 rv = certificate->session->provider->f->C_DecryptInit (
867 certificate->session->session_handle,
868 &mech,
869 certificate->key_handle
870 );
871 break;
872 case __pkcs11h_private_op_unwrap:
873 rv = certificate->session->provider->f->C_UnwrapKey (
874 certificate->session->session_handle,
875 &mech,
876 certificate->key_handle,
877 (CK_BYTE_PTR)source,
878 source_size,
879 wrap_attrs,
880 sizeof (wrap_attrs) / sizeof (CK_ATTRIBUTE),
881 &wrap_key
882 );
883 break;
884 default:
885 rv = CKR_ARGUMENTS_BAD;
886 break;
887 }
888
889 _PKCS11H_DEBUG (
890 PKCS11H_LOG_DEBUG2,
891 "PKCS#11: __pkcs11h_certificate_doPrivateOperation init rv=%ld",
892 rv
893 );
894
895 if (rv != CKR_OK) {
896 goto retry;
897 }
898 }
899
900 /*
901 * Assume one call operation
902 */
903 certificate->operation_active = FALSE;
904
905 size = *p_target_size;
906
907 switch (op) {
908 case __pkcs11h_private_op_sign:
909 rv = certificate->session->provider->f->C_Sign (
910 certificate->session->session_handle,
911 (CK_BYTE_PTR)source,
912 source_size,
913 (CK_BYTE_PTR)target,
914 &size
915 );
916 break;
917 case __pkcs11h_private_op_sign_recover:
918 rv = certificate->session->provider->f->C_SignRecover (
919 certificate->session->session_handle,
920 (CK_BYTE_PTR)source,
921 source_size,
922 (CK_BYTE_PTR)target,
923 &size
924 );
925 break;
926 case __pkcs11h_private_op_decrypt:
927 rv = certificate->session->provider->f->C_Decrypt (
928 certificate->session->session_handle,
929 (CK_BYTE_PTR)source,
930 source_size,
931 (CK_BYTE_PTR)target,
932 &size
933 );
934 break;
935 case __pkcs11h_private_op_unwrap:
936 wrap_value[0].ulValueLen = size;
937
938 rv = certificate->session->provider->f->C_GetAttributeValue (
939 certificate->session->session_handle,
940 wrap_key,
941 wrap_value,
942 sizeof (wrap_value) / sizeof (CK_ATTRIBUTE)
943 );
944
945 size = wrap_value[0].ulValueLen;
946 break;
947 default:
948 rv = CKR_ARGUMENTS_BAD;
949 break;
950 }
951
952 /*
953 * Must be before checking for rv.
954 */
955 *p_target_size = size;
956
957 _PKCS11H_DEBUG (
958 PKCS11H_LOG_DEBUG2,
959 "PKCS#11: __pkcs11h_certificate_doPrivateOperation op rv=%ld",
960 rv
961 );
962
963 if (rv == CKR_BUFFER_TOO_SMALL && op != __pkcs11h_private_op_unwrap) {
964 certificate->operation_active = TRUE;
965 }
966
967 if (target != NULL) {
968 if (rv != CKR_OK) {
969 goto retry;
970 }
971 }
972 else {
973 if (rv == CKR_OK) {
974 if (op != __pkcs11h_private_op_unwrap) {
975 certificate->operation_active = TRUE;
976 }
977 }
978 else {
979 goto retry;
980 }
981 }
982
983 op_succeed = TRUE;
984 rv = CKR_OK;
985
986 retry:
987
988 if (wrap_key != _PKCS11H_INVALID_OBJECT_HANDLE) {
989 certificate->session->provider->f->C_DestroyObject (
990 certificate->session->session_handle,
991 wrap_key
992 );
993 wrap_key = _PKCS11H_INVALID_OBJECT_HANDLE;
994 }
995
996 if (!op_succeed) {
997 if (rv == CKR_BUFFER_TOO_SMALL) {
998 goto cleanup;
999 }
1000
1001 /*
1002 * OpenSC workaround
1003 * It still allows C_FindObjectsInit when
1004 * token is removed/inserted but fails
1005 * private key operation.
1006 * So we force logout.
1007 * bug#108 at OpenSC trac
1008 */
1009 if (login_retry && rv == CKR_DEVICE_REMOVED) {
1010 login_retry = FALSE;
1011 _pkcs11h_session_logout (certificate->session);
1012 }
1013 /* End OpenSC workaround */
1014
1015 if (!login_retry) {
1016 _PKCS11H_DEBUG (
1017 PKCS11H_LOG_DEBUG1,
1018 "PKCS#11: Private key operation failed rv=%lu-'%s'",
1019 rv,
1020 pkcs11h_getMessage (rv)
1021 );
1022 login_retry = TRUE;
1023 rv = _pkcs11h_certificate_resetSession (
1024 certificate,
1025 FALSE,
1026 TRUE
1027 );
1028 }
1029
1030 if (rv != CKR_OK) {
1031 goto cleanup;
1032 }
1033 }
1034 }
1035
1036 cleanup:
1037
1038 #if defined(ENABLE_PKCS11H_THREADING)
1039 if (mutex_locked) {
1040 _pkcs11h_threading_mutexRelease (&certificate->mutex);
1041 mutex_locked = FALSE;
1042 }
1043 #endif
1044
1045 _PKCS11H_DEBUG (
1046 PKCS11H_LOG_DEBUG2,
1047 "PKCS#11: __pkcs11h_certificate_doPrivateOperation return rv=%lu-'%s', *p_target_size="P_Z"",
1048 rv,
1049 pkcs11h_getMessage (rv),
1050 *p_target_size
1051 );
1052
1053 return rv;
1054 }
1055
1056 CK_RV
pkcs11h_certificate_freeCertificateId(IN pkcs11h_certificate_id_t certificate_id)1057 pkcs11h_certificate_freeCertificateId (
1058 IN pkcs11h_certificate_id_t certificate_id
1059 ) {
1060 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1061 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1062 _PKCS11H_ASSERT (certificate_id!=NULL);
1063
1064 _PKCS11H_DEBUG (
1065 PKCS11H_LOG_DEBUG2,
1066 "PKCS#11: pkcs11h_certificate_freeCertificateId entry certificate_id=%p",
1067 (void *)certificate_id
1068 );
1069
1070 if (certificate_id->attrCKA_ID != NULL) {
1071 _pkcs11h_mem_free ((void *)&certificate_id->attrCKA_ID);
1072 }
1073 if (certificate_id->certificate_blob != NULL) {
1074 _pkcs11h_mem_free ((void *)&certificate_id->certificate_blob);
1075 }
1076 if (certificate_id->token_id != NULL) {
1077 pkcs11h_token_freeTokenId (certificate_id->token_id);
1078 certificate_id->token_id = NULL;
1079 }
1080 _pkcs11h_mem_free ((void *)&certificate_id);
1081
1082 _PKCS11H_DEBUG (
1083 PKCS11H_LOG_DEBUG2,
1084 "PKCS#11: pkcs11h_certificate_freeCertificateId return"
1085 );
1086
1087 return CKR_OK;
1088 }
1089
1090 CK_RV
pkcs11h_certificate_duplicateCertificateId(OUT pkcs11h_certificate_id_t * const to,IN const pkcs11h_certificate_id_t from)1091 pkcs11h_certificate_duplicateCertificateId (
1092 OUT pkcs11h_certificate_id_t * const to,
1093 IN const pkcs11h_certificate_id_t from
1094 ) {
1095 CK_RV rv = CKR_FUNCTION_FAILED;
1096
1097 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1098 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1099 _PKCS11H_ASSERT (to!=NULL);
1100 _PKCS11H_ASSERT (from!=NULL);
1101
1102 _PKCS11H_DEBUG (
1103 PKCS11H_LOG_DEBUG2,
1104 "PKCS#11: pkcs11h_certificate_duplicateCertificateId entry to=%p form=%p",
1105 (void *)to,
1106 (void *)from
1107 );
1108
1109 *to = NULL;
1110
1111 if (
1112 (rv = _pkcs11h_mem_duplicate (
1113 (void*)to,
1114 NULL,
1115 from,
1116 sizeof (struct pkcs11h_certificate_id_s)
1117 )) != CKR_OK ||
1118 (rv = _pkcs11h_mem_duplicate (
1119 (void*)&(*to)->token_id,
1120 NULL,
1121 from->token_id,
1122 sizeof (struct pkcs11h_token_id_s)
1123 )) != CKR_OK ||
1124 (rv = _pkcs11h_mem_duplicate (
1125 (void*)&(*to)->attrCKA_ID,
1126 &(*to)->attrCKA_ID_size,
1127 from->attrCKA_ID,
1128 from->attrCKA_ID_size
1129 )) ||
1130 (rv = _pkcs11h_mem_duplicate (
1131 (void*)&(*to)->certificate_blob,
1132 &(*to)->certificate_blob_size,
1133 from->certificate_blob,
1134 from->certificate_blob_size
1135 ))
1136 ) {
1137 goto cleanup;
1138 }
1139
1140 rv = CKR_OK;
1141
1142 cleanup:
1143
1144 _PKCS11H_DEBUG (
1145 PKCS11H_LOG_DEBUG2,
1146 "PKCS#11: pkcs11h_certificate_duplicateCertificateId return rv=%lu-'%s', *to=%p",
1147 rv,
1148 pkcs11h_getMessage (rv),
1149 (void *)*to
1150 );
1151
1152 return rv;
1153 }
1154
1155 CK_RV
pkcs11h_certificate_setCertificateIdCertificateBlob(IN const pkcs11h_certificate_id_t certificate_id,IN const unsigned char * const blob,IN const size_t blob_size)1156 pkcs11h_certificate_setCertificateIdCertificateBlob (
1157 IN const pkcs11h_certificate_id_t certificate_id,
1158 IN const unsigned char * const blob,
1159 IN const size_t blob_size
1160 ) {
1161 CK_RV rv = CKR_FUNCTION_FAILED;
1162
1163 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1164 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1165 _PKCS11H_ASSERT (certificate_id!=NULL);
1166 _PKCS11H_ASSERT (blob!=NULL);
1167
1168 _PKCS11H_DEBUG (
1169 PKCS11H_LOG_DEBUG2,
1170 "PKCS#11: pkcs11h_certificate_setCertificateIdCertificateBlob entry certificate_id=%p",
1171 (void *)certificate_id
1172 );
1173
1174 if (certificate_id->certificate_blob != NULL) {
1175 if ((rv = _pkcs11h_mem_free ((void *)&certificate_id->certificate_blob)) != CKR_OK) {
1176 goto cleanup;
1177 }
1178 }
1179
1180 if (
1181 (rv = _pkcs11h_mem_duplicate (
1182 (void *)&certificate_id->certificate_blob,
1183 &certificate_id->certificate_blob_size,
1184 blob,
1185 blob_size
1186 )) != CKR_OK
1187 ) {
1188 goto cleanup;
1189 }
1190
1191 if ((rv = __pkcs11h_certificate_updateCertificateIdDescription (certificate_id)) != CKR_OK) {
1192 goto cleanup;
1193 }
1194
1195 rv = CKR_OK;
1196
1197 cleanup:
1198
1199 _PKCS11H_DEBUG (
1200 PKCS11H_LOG_DEBUG2,
1201 "PKCS#11: pkcs11h_certificate_setCertificateIdCertificateBlob return rv=%lu-'%s'",
1202 rv,
1203 pkcs11h_getMessage (rv)
1204 );
1205
1206 return rv;
1207 }
1208
1209 CK_RV
pkcs11h_certificate_freeCertificate(IN pkcs11h_certificate_t certificate)1210 pkcs11h_certificate_freeCertificate (
1211 IN pkcs11h_certificate_t certificate
1212 ) {
1213 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1214 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1215
1216 _PKCS11H_DEBUG (
1217 PKCS11H_LOG_DEBUG2,
1218 "PKCS#11: pkcs11h_certificate_freeCertificate entry certificate=%p",
1219 (void *)certificate
1220 );
1221
1222 if (certificate != NULL) {
1223 if (certificate->session != NULL) {
1224 _pkcs11h_session_release (certificate->session);
1225 certificate->session = NULL;
1226 }
1227 if (certificate->id != NULL) {
1228 pkcs11h_certificate_freeCertificateId (certificate->id);
1229 certificate->id = NULL;
1230 }
1231
1232 #if defined(ENABLE_PKCS11H_THREADING)
1233 _pkcs11h_threading_mutexFree (&certificate->mutex);
1234 #endif
1235
1236 _pkcs11h_mem_free ((void *)&certificate);
1237 }
1238
1239 _PKCS11H_DEBUG (
1240 PKCS11H_LOG_DEBUG2,
1241 "PKCS#11: pkcs11h_certificate_freeCertificate return"
1242 );
1243
1244 return CKR_OK;
1245 }
1246
1247 CK_RV
pkcs11h_certificate_lockSession(IN const pkcs11h_certificate_t certificate)1248 pkcs11h_certificate_lockSession (
1249 IN const pkcs11h_certificate_t certificate
1250 ) {
1251 #if defined(ENABLE_PKCS11H_THREADING)
1252 CK_RV rv = CKR_FUNCTION_FAILED;
1253
1254 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1255 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1256 _PKCS11H_ASSERT (certificate!=NULL);
1257
1258 if ((rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) != CKR_OK) {
1259 goto cleanup;
1260 }
1261
1262 rv = CKR_OK;
1263
1264 cleanup:
1265
1266 return rv;
1267 #else
1268 return CKR_OK;
1269 #endif
1270 }
1271
1272 CK_RV
pkcs11h_certificate_releaseSession(IN const pkcs11h_certificate_t certificate)1273 pkcs11h_certificate_releaseSession (
1274 IN const pkcs11h_certificate_t certificate
1275 ) {
1276 #if defined(ENABLE_PKCS11H_THREADING)
1277 CK_RV rv = CKR_FUNCTION_FAILED;
1278
1279 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1280 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1281 _PKCS11H_ASSERT (certificate!=NULL);
1282
1283 if (certificate->session != NULL) {
1284 if ((rv = _pkcs11h_threading_mutexRelease (&certificate->session->mutex)) != CKR_OK) {
1285 goto cleanup;
1286 }
1287 }
1288
1289 rv = CKR_OK;
1290
1291 cleanup:
1292
1293 return rv;
1294 #else
1295 return CKR_OK;
1296 #endif
1297 }
1298
1299 CK_RV
pkcs11h_certificate_sign(IN const pkcs11h_certificate_t certificate,IN const CK_MECHANISM_TYPE mech_type,IN const unsigned char * const source,IN const size_t source_size,OUT unsigned char * const target,IN OUT size_t * const p_target_size)1300 pkcs11h_certificate_sign (
1301 IN const pkcs11h_certificate_t certificate,
1302 IN const CK_MECHANISM_TYPE mech_type,
1303 IN const unsigned char * const source,
1304 IN const size_t source_size,
1305 OUT unsigned char * const target,
1306 IN OUT size_t * const p_target_size
1307 ) {
1308 CK_RV rv = CKR_FUNCTION_FAILED;
1309
1310 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1311 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1312 _PKCS11H_ASSERT (certificate!=NULL);
1313 _PKCS11H_ASSERT (source!=NULL);
1314 /*_PKCS11H_ASSERT (target); NOT NEEDED*/
1315 _PKCS11H_ASSERT (p_target_size!=NULL);
1316
1317 _PKCS11H_DEBUG (
1318 PKCS11H_LOG_DEBUG2,
1319 "PKCS#11: pkcs11h_certificate_sign entry certificate=%p, mech_type=%ld, source=%p, source_size="P_Z", target=%p, *p_target_size="P_Z"",
1320 (void *)certificate,
1321 mech_type,
1322 source,
1323 source_size,
1324 target,
1325 target != NULL ? *p_target_size : 0
1326 );
1327
1328 if (target == NULL) {
1329 *p_target_size = 0;
1330 }
1331
1332 if (
1333 (rv = __pkcs11h_certificate_doPrivateOperation (
1334 certificate,
1335 __pkcs11h_private_op_sign,
1336 mech_type,
1337 source,
1338 source_size,
1339 target,
1340 p_target_size
1341 )) != CKR_OK
1342 ) {
1343 goto cleanup;
1344 }
1345
1346 rv = CKR_OK;
1347
1348 cleanup:
1349
1350 _PKCS11H_DEBUG (
1351 PKCS11H_LOG_DEBUG2,
1352 "PKCS#11: pkcs11h_certificate_sign return rv=%lu-'%s', *p_target_size="P_Z"",
1353 rv,
1354 pkcs11h_getMessage (rv),
1355 *p_target_size
1356 );
1357
1358 return rv;
1359 }
1360
1361 CK_RV
pkcs11h_certificate_signRecover(IN const pkcs11h_certificate_t certificate,IN const CK_MECHANISM_TYPE mech_type,IN const unsigned char * const source,IN const size_t source_size,OUT unsigned char * const target,IN OUT size_t * const p_target_size)1362 pkcs11h_certificate_signRecover (
1363 IN const pkcs11h_certificate_t certificate,
1364 IN const CK_MECHANISM_TYPE mech_type,
1365 IN const unsigned char * const source,
1366 IN const size_t source_size,
1367 OUT unsigned char * const target,
1368 IN OUT size_t * const p_target_size
1369 ) {
1370 CK_RV rv = CKR_FUNCTION_FAILED;
1371
1372 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1373 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1374 _PKCS11H_ASSERT (certificate!=NULL);
1375 _PKCS11H_ASSERT (source!=NULL);
1376 /*_PKCS11H_ASSERT (target); NOT NEEDED*/
1377 _PKCS11H_ASSERT (p_target_size!=NULL);
1378
1379 _PKCS11H_DEBUG (
1380 PKCS11H_LOG_DEBUG2,
1381 "PKCS#11: pkcs11h_certificate_signRecover entry certificate=%p, mech_type=%ld, source=%p, source_size="P_Z", target=%p, *p_target_size="P_Z"",
1382 (void *)certificate,
1383 mech_type,
1384 source,
1385 source_size,
1386 target,
1387 target != NULL ? *p_target_size : 0
1388 );
1389
1390 if (target == NULL) {
1391 *p_target_size = 0;
1392 }
1393
1394 if (
1395 (rv = __pkcs11h_certificate_doPrivateOperation (
1396 certificate,
1397 __pkcs11h_private_op_sign_recover,
1398 mech_type,
1399 source,
1400 source_size,
1401 target,
1402 p_target_size
1403 )) != CKR_OK
1404 ) {
1405 goto cleanup;
1406 }
1407
1408 rv = CKR_OK;
1409
1410 cleanup:
1411
1412 _PKCS11H_DEBUG (
1413 PKCS11H_LOG_DEBUG2,
1414 "PKCS#11: pkcs11h_certificate_signRecover return rv=%lu-'%s', *p_target_size="P_Z"",
1415 rv,
1416 pkcs11h_getMessage (rv),
1417 *p_target_size
1418 );
1419
1420 return rv;
1421 }
1422
1423 CK_RV
pkcs11h_certificate_decrypt(IN const pkcs11h_certificate_t certificate,IN const CK_MECHANISM_TYPE mech_type,IN const unsigned char * const source,IN const size_t source_size,OUT unsigned char * const target,IN OUT size_t * const p_target_size)1424 pkcs11h_certificate_decrypt (
1425 IN const pkcs11h_certificate_t certificate,
1426 IN const CK_MECHANISM_TYPE mech_type,
1427 IN const unsigned char * const source,
1428 IN const size_t source_size,
1429 OUT unsigned char * const target,
1430 IN OUT size_t * const p_target_size
1431 ) {
1432 CK_RV rv = CKR_FUNCTION_FAILED;
1433
1434 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1435 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1436 _PKCS11H_ASSERT (certificate!=NULL);
1437 _PKCS11H_ASSERT (source!=NULL);
1438 /*_PKCS11H_ASSERT (target); NOT NEEDED*/
1439 _PKCS11H_ASSERT (p_target_size!=NULL);
1440
1441 _PKCS11H_DEBUG (
1442 PKCS11H_LOG_DEBUG2,
1443 "PKCS#11: pkcs11h_certificate_decrypt entry certificate=%p, mech_type=%ld, source=%p, source_size="P_Z", target=%p, *p_target_size="P_Z"",
1444 (void *)certificate,
1445 mech_type,
1446 source,
1447 source_size,
1448 target,
1449 target != NULL ? *p_target_size : 0
1450 );
1451
1452 if (target == NULL) {
1453 *p_target_size = 0;
1454 }
1455
1456 if (
1457 (rv = __pkcs11h_certificate_doPrivateOperation (
1458 certificate,
1459 __pkcs11h_private_op_decrypt,
1460 mech_type,
1461 source,
1462 source_size,
1463 target,
1464 p_target_size
1465 )) != CKR_OK
1466 ) {
1467 goto cleanup;
1468 }
1469
1470 rv = CKR_OK;
1471
1472 cleanup:
1473
1474 _PKCS11H_DEBUG (
1475 PKCS11H_LOG_DEBUG2,
1476 "PKCS#11: pkcs11h_certificate_decrypt return rv=%lu-'%s', *p_target_size="P_Z"",
1477 rv,
1478 pkcs11h_getMessage (rv),
1479 *p_target_size
1480 );
1481
1482 return rv;
1483 }
1484
1485 CK_RV
pkcs11h_certificate_unwrap(IN const pkcs11h_certificate_t certificate,IN const CK_MECHANISM_TYPE mech_type,IN const unsigned char * const source,IN const size_t source_size,OUT unsigned char * const target,IN OUT size_t * const p_target_size)1486 pkcs11h_certificate_unwrap (
1487 IN const pkcs11h_certificate_t certificate,
1488 IN const CK_MECHANISM_TYPE mech_type,
1489 IN const unsigned char * const source,
1490 IN const size_t source_size,
1491 OUT unsigned char * const target,
1492 IN OUT size_t * const p_target_size
1493 ) {
1494 CK_RV rv = CKR_FUNCTION_FAILED;
1495
1496 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1497 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1498 _PKCS11H_ASSERT (certificate!=NULL);
1499 _PKCS11H_ASSERT (source!=NULL);
1500 /*_PKCS11H_ASSERT (target); NOT NEEDED*/
1501 _PKCS11H_ASSERT (p_target_size!=NULL);
1502
1503 _PKCS11H_DEBUG (
1504 PKCS11H_LOG_DEBUG2,
1505 "PKCS#11: pkcs11h_certificate_unwrap entry certificate=%p, mech_type=%ld, source=%p, source_size="P_Z", target=%p, *p_target_size="P_Z"",
1506 (void *)certificate,
1507 mech_type,
1508 source,
1509 source_size,
1510 target,
1511 target != NULL ? *p_target_size : 0
1512 );
1513
1514 if (target == NULL) {
1515 *p_target_size = 0;
1516 }
1517
1518 if (
1519 (rv = __pkcs11h_certificate_doPrivateOperation (
1520 certificate,
1521 __pkcs11h_private_op_unwrap,
1522 mech_type,
1523 source,
1524 source_size,
1525 target,
1526 p_target_size
1527 )) != CKR_OK
1528 ) {
1529 goto cleanup;
1530 }
1531
1532 rv = CKR_OK;
1533
1534 cleanup:
1535
1536 _PKCS11H_DEBUG (
1537 PKCS11H_LOG_DEBUG2,
1538 "PKCS#11: pkcs11h_certificate_unwrap return rv=%lu-'%s', *p_target_size="P_Z"",
1539 rv,
1540 pkcs11h_getMessage (rv),
1541 *p_target_size
1542 );
1543
1544 return rv;
1545 }
1546
1547 CK_RV
pkcs11h_certificate_signAny(IN const pkcs11h_certificate_t certificate,IN const CK_MECHANISM_TYPE mech_type,IN const unsigned char * const source,IN const size_t source_size,OUT unsigned char * const target,IN OUT size_t * const p_target_size)1548 pkcs11h_certificate_signAny (
1549 IN const pkcs11h_certificate_t certificate,
1550 IN const CK_MECHANISM_TYPE mech_type,
1551 IN const unsigned char * const source,
1552 IN const size_t source_size,
1553 OUT unsigned char * const target,
1554 IN OUT size_t * const p_target_size
1555 ) {
1556 CK_RV rv = CKR_FUNCTION_FAILED;
1557 PKCS11H_BOOL acked = FALSE;
1558
1559 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1560 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1561 _PKCS11H_ASSERT (certificate!=NULL);
1562 _PKCS11H_ASSERT (source!=NULL);
1563 /*_PKCS11H_ASSERT (target); NOT NEEDED*/
1564 _PKCS11H_ASSERT (p_target_size!=NULL);
1565
1566 _PKCS11H_DEBUG (
1567 PKCS11H_LOG_DEBUG2,
1568 "PKCS#11: pkcs11h_certificate_signAny entry certificate=%p, mech_type=%ld, source=%p, source_size="P_Z", target=%p, *p_target_size="P_Z"",
1569 (void *)certificate,
1570 mech_type,
1571 source,
1572 source_size,
1573 target,
1574 target != NULL ? *p_target_size : 0
1575 );
1576
1577 if (certificate->mask_private_mode == 0) {
1578 _PKCS11H_DEBUG (
1579 PKCS11H_LOG_DEBUG1,
1580 "PKCS#11: Getting key attributes"
1581 );
1582
1583 if ((rv = __pkcs11h_certificate_getKeyAttributes (certificate)) != CKR_OK) {
1584 goto cleanup;
1585 }
1586 }
1587
1588 if (
1589 !acked &&
1590 (certificate->mask_private_mode & PKCS11H_PRIVATEMODE_MASK_SIGN) != 0
1591 ) {
1592 switch (
1593 (rv = pkcs11h_certificate_sign (
1594 certificate,
1595 mech_type,
1596 source,
1597 source_size,
1598 target,
1599 p_target_size
1600 ))
1601 ) {
1602 case CKR_OK:
1603 acked = TRUE;
1604 break;
1605 case CKR_FUNCTION_NOT_SUPPORTED:
1606 case CKR_KEY_FUNCTION_NOT_PERMITTED:
1607 case CKR_KEY_TYPE_INCONSISTENT:
1608 certificate->mask_private_mode &= ~PKCS11H_PRIVATEMODE_MASK_SIGN;
1609 break;
1610 default:
1611 goto cleanup;
1612 }
1613 }
1614
1615 if (
1616 !acked &&
1617 (certificate->mask_private_mode & PKCS11H_PRIVATEMODE_MASK_RECOVER) != 0
1618 ) {
1619 switch (
1620 (rv = pkcs11h_certificate_signRecover (
1621 certificate,
1622 mech_type,
1623 source,
1624 source_size,
1625 target,
1626 p_target_size
1627 ))
1628 ) {
1629 case CKR_OK:
1630 acked = TRUE;
1631 break;
1632 case CKR_FUNCTION_NOT_SUPPORTED:
1633 case CKR_KEY_FUNCTION_NOT_PERMITTED:
1634 case CKR_KEY_TYPE_INCONSISTENT:
1635 certificate->mask_private_mode &= ~PKCS11H_PRIVATEMODE_MASK_RECOVER;
1636 break;
1637 default:
1638 goto cleanup;
1639 }
1640 }
1641
1642 if (!acked) {
1643 rv = CKR_FUNCTION_FAILED;
1644 goto cleanup;
1645 }
1646
1647 rv = CKR_OK;
1648
1649 cleanup:
1650
1651 _PKCS11H_DEBUG (
1652 PKCS11H_LOG_DEBUG2,
1653 "PKCS#11: pkcs11h_certificate_signAny return rv=%lu-'%s', *p_target_size="P_Z"",
1654 rv,
1655 pkcs11h_getMessage (rv),
1656 *p_target_size
1657 );
1658
1659 return rv;
1660 }
1661
1662 CK_RV
pkcs11h_certificate_decryptAny(IN const pkcs11h_certificate_t certificate,IN const CK_MECHANISM_TYPE mech_type,IN const unsigned char * const source,IN const size_t source_size,OUT unsigned char * const target,IN OUT size_t * const p_target_size)1663 pkcs11h_certificate_decryptAny (
1664 IN const pkcs11h_certificate_t certificate,
1665 IN const CK_MECHANISM_TYPE mech_type,
1666 IN const unsigned char * const source,
1667 IN const size_t source_size,
1668 OUT unsigned char * const target,
1669 IN OUT size_t * const p_target_size
1670 ) {
1671 CK_RV rv = CKR_FUNCTION_FAILED;
1672 PKCS11H_BOOL acked = FALSE;
1673
1674 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1675 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1676 _PKCS11H_ASSERT (certificate!=NULL);
1677 _PKCS11H_ASSERT (source!=NULL);
1678 /*_PKCS11H_ASSERT (target); NOT NEEDED*/
1679 _PKCS11H_ASSERT (p_target_size!=NULL);
1680
1681 _PKCS11H_DEBUG (
1682 PKCS11H_LOG_DEBUG2,
1683 "PKCS#11: pkcs11h_certificate_decryptAny entry certificate=%p, mech_type=%ld, source=%p, source_size="P_Z", target=%p, *p_target_size="P_Z"",
1684 (void *)certificate,
1685 mech_type,
1686 source,
1687 source_size,
1688 target,
1689 target != NULL ? *p_target_size : 0
1690 );
1691
1692 if (certificate->mask_private_mode == 0) {
1693 _PKCS11H_DEBUG (
1694 PKCS11H_LOG_DEBUG1,
1695 "PKCS#11: Getting key attributes"
1696 );
1697 if ((rv = __pkcs11h_certificate_getKeyAttributes (certificate)) != CKR_OK) {
1698 goto cleanup;
1699 }
1700 }
1701
1702 if (
1703 !acked &&
1704 (certificate->mask_private_mode & PKCS11H_PRIVATEMODE_MASK_DECRYPT) != 0
1705 ) {
1706 switch (
1707 pkcs11h_certificate_decrypt (
1708 certificate,
1709 mech_type,
1710 source,
1711 source_size,
1712 target,
1713 p_target_size
1714 )
1715 ) {
1716 case CKR_OK:
1717 acked = TRUE;
1718 break;
1719 case CKR_FUNCTION_NOT_SUPPORTED:
1720 case CKR_KEY_FUNCTION_NOT_PERMITTED:
1721 case CKR_KEY_TYPE_INCONSISTENT:
1722 certificate->mask_private_mode &= ~PKCS11H_PRIVATEMODE_MASK_DECRYPT;
1723 break;
1724 default:
1725 goto cleanup;
1726 }
1727 }
1728
1729 if (
1730 !acked &&
1731 (certificate->mask_private_mode & PKCS11H_PRIVATEMODE_MASK_UNWRAP) != 0
1732 ) {
1733 switch (
1734 pkcs11h_certificate_unwrap (
1735 certificate,
1736 mech_type,
1737 source,
1738 source_size,
1739 target,
1740 p_target_size
1741 )
1742 ) {
1743 case CKR_OK:
1744 acked = TRUE;
1745 break;
1746 case CKR_FUNCTION_NOT_SUPPORTED:
1747 case CKR_KEY_FUNCTION_NOT_PERMITTED:
1748 case CKR_KEY_TYPE_INCONSISTENT:
1749 certificate->mask_private_mode &= ~PKCS11H_PRIVATEMODE_MASK_UNWRAP;
1750 break;
1751 default:
1752 goto cleanup;
1753 }
1754 }
1755
1756 if (!acked) {
1757 rv = CKR_FUNCTION_FAILED;
1758 goto cleanup;
1759 }
1760
1761 rv = CKR_OK;
1762
1763 cleanup:
1764
1765 _PKCS11H_DEBUG (
1766 PKCS11H_LOG_DEBUG2,
1767 "PKCS#11: pkcs11h_certificate_decryptAny return rv=%lu-'%s', *p_target_size="P_Z"",
1768 rv,
1769 pkcs11h_getMessage (rv),
1770 *p_target_size
1771 );
1772
1773 return rv;
1774 }
1775
1776 CK_RV
pkcs11h_certificate_create(IN const pkcs11h_certificate_id_t certificate_id,IN void * const user_data,IN const unsigned mask_prompt,IN const int pin_cache_period,OUT pkcs11h_certificate_t * const p_certificate)1777 pkcs11h_certificate_create (
1778 IN const pkcs11h_certificate_id_t certificate_id,
1779 IN void * const user_data,
1780 IN const unsigned mask_prompt,
1781 IN const int pin_cache_period,
1782 OUT pkcs11h_certificate_t * const p_certificate
1783 ) {
1784 #if defined(ENABLE_PKCS11H_THREADING)
1785 PKCS11H_BOOL have_mutex = FALSE;
1786 PKCS11H_BOOL mutex_locked = FALSE;
1787 #endif
1788 pkcs11h_certificate_t certificate = NULL;
1789 CK_RV rv = CKR_FUNCTION_FAILED;
1790
1791 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1792 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1793 /*_PKCS11H_ASSERT (user_data!=NULL); NOT NEEDED */
1794 _PKCS11H_ASSERT (p_certificate!=NULL);
1795
1796 _PKCS11H_DEBUG (
1797 PKCS11H_LOG_DEBUG2,
1798 "PKCS#11: pkcs11h_certificate_create entry certificate_id=%p, user_data=%p, mask_prompt=%08x, pin_cache_period=%d, p_certificate=%p",
1799 (void *)certificate_id,
1800 user_data,
1801 mask_prompt,
1802 pin_cache_period,
1803 (void *)p_certificate
1804 );
1805
1806 *p_certificate = NULL;
1807
1808 if ((rv = _pkcs11h_mem_malloc ((void*)&certificate, sizeof (struct pkcs11h_certificate_s))) != CKR_OK) {
1809 goto cleanup;
1810 }
1811
1812 certificate->user_data = user_data;
1813 certificate->mask_prompt = mask_prompt;
1814 certificate->key_handle = _PKCS11H_INVALID_OBJECT_HANDLE;
1815 certificate->pin_cache_period = pin_cache_period;
1816
1817 #if defined(ENABLE_PKCS11H_THREADING)
1818 if ((rv = _pkcs11h_threading_mutexInit (&certificate->mutex)) != CKR_OK) {
1819 goto cleanup;
1820 }
1821 have_mutex = TRUE;
1822 #endif
1823
1824 if ((rv = pkcs11h_certificate_duplicateCertificateId (&certificate->id, certificate_id)) != CKR_OK) {
1825 goto cleanup;
1826 }
1827
1828 if (
1829 (rv = _pkcs11h_session_getSessionByTokenId (
1830 certificate->id->token_id,
1831 &certificate->session
1832 )) != CKR_OK
1833 ) {
1834 goto cleanup;
1835 }
1836
1837 #if defined(ENABLE_PKCS11H_THREADING)
1838 if ((rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) != CKR_OK) {
1839 goto cleanup;
1840 }
1841 mutex_locked = TRUE;
1842 #endif
1843
1844 if (certificate->pin_cache_period != PKCS11H_PIN_CACHE_INFINITE) {
1845 if (certificate->session->pin_cache_period == PKCS11H_PIN_CACHE_INFINITE) {
1846 certificate->session->pin_cache_period = certificate->pin_cache_period;
1847 }
1848 else {
1849 if (certificate->session->pin_cache_period > certificate->pin_cache_period) {
1850 certificate->session->pin_expire_time = (
1851 certificate->session->pin_expire_time -
1852 (time_t)certificate->session->pin_cache_period +
1853 (time_t)certificate->pin_cache_period
1854 );
1855 certificate->session->pin_cache_period = certificate->pin_cache_period;
1856 }
1857 }
1858 }
1859
1860 *p_certificate = certificate;
1861 certificate = NULL;
1862 rv = CKR_OK;
1863
1864 cleanup:
1865
1866 #if defined(ENABLE_PKCS11H_THREADING)
1867 if (mutex_locked) {
1868 if (certificate != NULL) {
1869 _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
1870 }
1871 else {
1872 _pkcs11h_threading_mutexRelease (&(*p_certificate)->session->mutex);
1873 }
1874 mutex_locked = FALSE;
1875 }
1876 #endif
1877
1878 if (certificate != NULL) {
1879 if (certificate->session != NULL) {
1880 _pkcs11h_session_release (certificate->session);
1881 certificate->session = NULL;
1882 }
1883 if (certificate->id != NULL) {
1884 pkcs11h_certificate_freeCertificateId (certificate->id);
1885 certificate->id = NULL;
1886 }
1887 #if defined(ENABLE_PKCS11H_THREADING)
1888 if (have_mutex) {
1889 _pkcs11h_threading_mutexFree (&certificate->mutex);
1890 }
1891 #endif
1892 _pkcs11h_mem_free ((void *)&certificate);
1893 }
1894
1895 _PKCS11H_DEBUG (
1896 PKCS11H_LOG_DEBUG2,
1897 "PKCS#11: pkcs11h_certificate_create return rv=%lu-'%s' *p_certificate=%p",
1898 rv,
1899 pkcs11h_getMessage (rv),
1900 (void *)*p_certificate
1901 );
1902
1903 return rv;
1904 }
1905
1906 unsigned
pkcs11h_certificate_getPromptMask(IN const pkcs11h_certificate_t certificate)1907 pkcs11h_certificate_getPromptMask (
1908 IN const pkcs11h_certificate_t certificate
1909 ) {
1910 _PKCS11H_ASSERT (certificate!=NULL);
1911
1912 return certificate->mask_prompt;
1913 }
1914
1915 void
pkcs11h_certificate_setPromptMask(IN const pkcs11h_certificate_t certificate,IN const unsigned mask_prompt)1916 pkcs11h_certificate_setPromptMask (
1917 IN const pkcs11h_certificate_t certificate,
1918 IN const unsigned mask_prompt
1919 ) {
1920 _PKCS11H_ASSERT (certificate!=NULL);
1921
1922 certificate->mask_prompt = mask_prompt;
1923 }
1924
1925 void *
pkcs11h_certificate_getUserData(IN const pkcs11h_certificate_t certificate)1926 pkcs11h_certificate_getUserData (
1927 IN const pkcs11h_certificate_t certificate
1928 ) {
1929 _PKCS11H_ASSERT (certificate!=NULL);
1930
1931 return certificate->user_data;
1932 }
1933
1934 void
pkcs11h_certificate_setUserData(IN const pkcs11h_certificate_t certificate,IN void * const user_data)1935 pkcs11h_certificate_setUserData (
1936 IN const pkcs11h_certificate_t certificate,
1937 IN void * const user_data
1938 ) {
1939 _PKCS11H_ASSERT (certificate!=NULL);
1940
1941 certificate->user_data = user_data;
1942 }
1943
1944 CK_RV
pkcs11h_certificate_getCertificateId(IN const pkcs11h_certificate_t certificate,OUT pkcs11h_certificate_id_t * const p_certificate_id)1945 pkcs11h_certificate_getCertificateId (
1946 IN const pkcs11h_certificate_t certificate,
1947 OUT pkcs11h_certificate_id_t * const p_certificate_id
1948 ) {
1949 CK_RV rv = CKR_FUNCTION_FAILED;
1950
1951 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1952 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
1953 _PKCS11H_ASSERT (certificate!=NULL);
1954 _PKCS11H_ASSERT (p_certificate_id!=NULL);
1955
1956 _PKCS11H_DEBUG (
1957 PKCS11H_LOG_DEBUG2,
1958 "PKCS#11: pkcs11h_certificate_getCertificateId entry certificate=%p, certificate_id=%p",
1959 (void *)certificate,
1960 (void *)p_certificate_id
1961 );
1962
1963 if (
1964 (rv = pkcs11h_certificate_duplicateCertificateId (
1965 p_certificate_id,
1966 certificate->id
1967 )) != CKR_OK
1968 ) {
1969 goto cleanup;
1970 }
1971
1972 rv = CKR_OK;
1973
1974 cleanup:
1975
1976 _PKCS11H_DEBUG (
1977 PKCS11H_LOG_DEBUG2,
1978 "PKCS#11: pkcs11h_certificate_getCertificateId return rv=%lu-'%s'",
1979 rv,
1980 pkcs11h_getMessage (rv)
1981 );
1982
1983 return rv;
1984 }
1985
1986 CK_RV
pkcs11h_certificate_getCertificateBlob(IN const pkcs11h_certificate_t certificate,OUT unsigned char * const certificate_blob,IN OUT size_t * const p_certificate_blob_size)1987 pkcs11h_certificate_getCertificateBlob (
1988 IN const pkcs11h_certificate_t certificate,
1989 OUT unsigned char * const certificate_blob,
1990 IN OUT size_t * const p_certificate_blob_size
1991 ) {
1992 #if defined(ENABLE_PKCS11H_THREADING)
1993 PKCS11H_BOOL mutex_locked = FALSE;
1994 #endif
1995 CK_RV rv = CKR_FUNCTION_FAILED;
1996 size_t certifiate_blob_size_max = 0;
1997
1998 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
1999 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
2000 _PKCS11H_ASSERT (certificate!=NULL);
2001 /*_PKCS11H_ASSERT (certificate_blob!=NULL); NOT NEEDED */
2002 _PKCS11H_ASSERT (p_certificate_blob_size!=NULL);
2003
2004 _PKCS11H_DEBUG (
2005 PKCS11H_LOG_DEBUG2,
2006 "PKCS#11: pkcs11h_certificate_getCertificateBlob entry certificate=%p, certificate_blob=%p, *p_certificate_blob_size="P_Z"",
2007 (void *)certificate,
2008 certificate_blob,
2009 certificate_blob != NULL ? *p_certificate_blob_size : 0
2010 );
2011
2012 if (certificate_blob != NULL) {
2013 certifiate_blob_size_max = *p_certificate_blob_size;
2014 }
2015 *p_certificate_blob_size = 0;
2016
2017 #if defined(ENABLE_PKCS11H_THREADING)
2018 if ((rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) != CKR_OK) {
2019 goto cleanup;
2020 }
2021 mutex_locked = TRUE;
2022 #endif
2023
2024 if (certificate->id->certificate_blob == NULL) {
2025 PKCS11H_BOOL op_succeed = FALSE;
2026 PKCS11H_BOOL login_retry = FALSE;
2027
2028 while (!op_succeed) {
2029 if ((rv = __pkcs11h_certificate_loadCertificate (certificate)) != CKR_OK) {
2030 goto retry;
2031 }
2032
2033 op_succeed = TRUE;
2034 rv = CKR_OK;
2035
2036 retry:
2037 if (!op_succeed) {
2038 if (!login_retry) {
2039 login_retry = TRUE;
2040 rv = _pkcs11h_certificate_resetSession (
2041 certificate,
2042 TRUE,
2043 FALSE
2044 );
2045 }
2046
2047 if (rv != CKR_OK) {
2048 goto cleanup;
2049 }
2050 }
2051 }
2052 }
2053
2054 if (certificate->id->certificate_blob == NULL) {
2055 rv = CKR_FUNCTION_REJECTED;
2056 goto cleanup;
2057 }
2058
2059 *p_certificate_blob_size = certificate->id->certificate_blob_size;
2060
2061 if (certificate_blob != NULL) {
2062 if (certificate->id->certificate_blob_size > certifiate_blob_size_max) {
2063 rv = CKR_BUFFER_TOO_SMALL;
2064 goto cleanup;
2065 }
2066
2067 memmove (
2068 certificate_blob,
2069 certificate->id->certificate_blob,
2070 *p_certificate_blob_size
2071 );
2072 }
2073
2074 rv = CKR_OK;
2075
2076 cleanup:
2077
2078 #if defined(ENABLE_PKCS11H_THREADING)
2079 if (mutex_locked) {
2080 _pkcs11h_threading_mutexRelease (&certificate->mutex);
2081 mutex_locked = FALSE;
2082 }
2083 #endif
2084
2085 _PKCS11H_DEBUG (
2086 PKCS11H_LOG_DEBUG2,
2087 "PKCS#11: pkcs11h_certificate_getCertificateBlob return rv=%lu-'%s'",
2088 rv,
2089 pkcs11h_getMessage (rv)
2090 );
2091
2092 return rv;
2093 }
2094
2095 CK_RV
pkcs11h_certificate_ensureCertificateAccess(IN const pkcs11h_certificate_t certificate)2096 pkcs11h_certificate_ensureCertificateAccess (
2097 IN const pkcs11h_certificate_t certificate
2098 ) {
2099 #if defined(ENABLE_PKCS11H_THREADING)
2100 PKCS11H_BOOL mutex_locked_cert = FALSE;
2101 PKCS11H_BOOL mutex_locked_sess = FALSE;
2102 #endif
2103 PKCS11H_BOOL validCert = FALSE;
2104 CK_RV rv = CKR_FUNCTION_FAILED;
2105
2106 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
2107 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
2108 _PKCS11H_ASSERT (certificate!=NULL);
2109
2110 _PKCS11H_DEBUG (
2111 PKCS11H_LOG_DEBUG2,
2112 "PKCS#11: pkcs11h_certificate_ensureCertificateAccess entry certificate=%p",
2113 (void *)certificate
2114 );
2115
2116 #if defined(ENABLE_PKCS11H_THREADING)
2117 if ((rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) != CKR_OK) {
2118 goto cleanup;
2119 }
2120 mutex_locked_cert = TRUE;
2121 #endif
2122
2123 if (!validCert) {
2124 CK_OBJECT_HANDLE h = _PKCS11H_INVALID_OBJECT_HANDLE;
2125
2126 #if defined(ENABLE_PKCS11H_THREADING)
2127 if ((rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) != CKR_OK) {
2128 goto retry1;
2129 }
2130 mutex_locked_sess = TRUE;
2131 #endif
2132
2133 if (
2134 (rv = _pkcs11h_session_getObjectById (
2135 certificate->session,
2136 CKO_CERTIFICATE,
2137 certificate->id->attrCKA_ID,
2138 certificate->id->attrCKA_ID_size,
2139 &h
2140 )) != CKR_OK
2141 ) {
2142 goto retry1;
2143 }
2144
2145 validCert = TRUE;
2146
2147 retry1:
2148
2149 #if defined(ENABLE_PKCS11H_THREADING)
2150 if (mutex_locked_sess) {
2151 _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
2152 mutex_locked_sess = FALSE;
2153 }
2154 #endif
2155
2156 if (!validCert) {
2157 _PKCS11H_DEBUG (
2158 PKCS11H_LOG_DEBUG1,
2159 "PKCS#11: Cannot access existing object rv=%lu-'%s'",
2160 rv,
2161 pkcs11h_getMessage (rv)
2162 );
2163 }
2164 }
2165
2166 if (!validCert) {
2167 if (
2168 (rv = _pkcs11h_certificate_resetSession (
2169 certificate,
2170 TRUE,
2171 FALSE
2172 )) != CKR_OK
2173 ) {
2174 goto cleanup;
2175 }
2176
2177 validCert = TRUE;
2178 }
2179
2180 if (validCert) {
2181 rv = CKR_OK;
2182 }
2183
2184 cleanup:
2185
2186 #if defined(ENABLE_PKCS11H_THREADING)
2187 if (mutex_locked_cert) {
2188 _pkcs11h_threading_mutexRelease (&certificate->mutex);
2189 mutex_locked_cert = FALSE;
2190 }
2191 #endif
2192
2193 _PKCS11H_DEBUG (
2194 PKCS11H_LOG_DEBUG2,
2195 "PKCS#11: pkcs11h_certificate_ensureCertificateAccess return rv=%lu-'%s'",
2196 rv,
2197 pkcs11h_getMessage (rv)
2198 );
2199
2200 return rv;
2201 }
2202
2203 CK_RV
pkcs11h_certificate_ensureKeyAccess(IN const pkcs11h_certificate_t certificate)2204 pkcs11h_certificate_ensureKeyAccess (
2205 IN const pkcs11h_certificate_t certificate
2206 ) {
2207 #if defined(ENABLE_PKCS11H_THREADING)
2208 PKCS11H_BOOL mutex_locked_cert = FALSE;
2209 PKCS11H_BOOL mutex_locked_sess = FALSE;
2210 #endif
2211 CK_RV rv = CKR_FUNCTION_FAILED;
2212 PKCS11H_BOOL valid_key = FALSE;
2213
2214 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
2215 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
2216 _PKCS11H_ASSERT (certificate!=NULL);
2217
2218 _PKCS11H_DEBUG (
2219 PKCS11H_LOG_DEBUG2,
2220 "PKCS#11: pkcs11h_certificate_ensureKeyAccess entry certificate=%p",
2221 (void *)certificate
2222 );
2223
2224 #if defined(ENABLE_PKCS11H_THREADING)
2225 if ((rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) != CKR_OK) {
2226 goto cleanup;
2227 }
2228 mutex_locked_cert = TRUE;
2229 #endif
2230
2231 if (!valid_key) {
2232 #if defined(ENABLE_PKCS11H_THREADING)
2233 if ((rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) != CKR_OK) {
2234 goto retry1;
2235 }
2236 mutex_locked_sess = TRUE;
2237 #endif
2238
2239 if (
2240 (rv = _pkcs11h_session_getObjectById (
2241 certificate->session,
2242 CKO_PRIVATE_KEY,
2243 certificate->id->attrCKA_ID,
2244 certificate->id->attrCKA_ID_size,
2245 &certificate->key_handle
2246 )) != CKR_OK
2247 ) {
2248 goto retry1;
2249 }
2250
2251 valid_key = TRUE;
2252
2253 retry1:
2254
2255 #if defined(ENABLE_PKCS11H_THREADING)
2256 if (mutex_locked_sess) {
2257 _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
2258 mutex_locked_sess = FALSE;
2259 }
2260 #endif
2261
2262 if (!valid_key) {
2263 _PKCS11H_DEBUG (
2264 PKCS11H_LOG_DEBUG1,
2265 "PKCS#11: Cannot access existing object rv=%lu-'%s'",
2266 rv,
2267 pkcs11h_getMessage (rv)
2268 );
2269 certificate->key_handle = _PKCS11H_INVALID_OBJECT_HANDLE;
2270 }
2271 }
2272
2273 if (!valid_key) {
2274 if (
2275 (rv = _pkcs11h_certificate_resetSession (
2276 certificate,
2277 FALSE,
2278 FALSE
2279 )) != CKR_OK
2280 ) {
2281 goto cleanup;
2282 }
2283
2284 valid_key = TRUE;
2285 }
2286
2287 if (valid_key) {
2288 rv = CKR_OK;
2289 }
2290
2291 cleanup:
2292
2293 #if defined(ENABLE_PKCS11H_THREADING)
2294 if (mutex_locked_cert) {
2295 _pkcs11h_threading_mutexRelease (&certificate->mutex);
2296 mutex_locked_cert = FALSE;
2297 }
2298 #endif
2299
2300 _PKCS11H_DEBUG (
2301 PKCS11H_LOG_DEBUG2,
2302 "PKCS#11: pkcs11h_certificate_ensureKeyAccess return rv=%lu-'%s'",
2303 rv,
2304 pkcs11h_getMessage (rv)
2305 );
2306
2307 return rv;
2308 }
2309
2310 CK_RV
_pkcs11h_certificate_enumSessionCertificates(IN const _pkcs11h_session_t session,IN void * const user_data,IN const unsigned mask_prompt)2311 _pkcs11h_certificate_enumSessionCertificates (
2312 IN const _pkcs11h_session_t session,
2313 IN void * const user_data,
2314 IN const unsigned mask_prompt
2315 ) {
2316 #if defined(ENABLE_PKCS11H_THREADING)
2317 PKCS11H_BOOL mutex_locked = FALSE;
2318 #endif
2319 PKCS11H_BOOL op_succeed = FALSE;
2320 PKCS11H_BOOL login_retry = FALSE;
2321
2322 CK_RV rv = CKR_FUNCTION_FAILED;
2323
2324 _PKCS11H_ASSERT (session!=NULL);
2325 /*_PKCS11H_ASSERT (user_data) NOT NEEDED */
2326
2327 _PKCS11H_DEBUG (
2328 PKCS11H_LOG_DEBUG2,
2329 "PKCS#11: _pkcs11h_certificate_enumSessionCertificates entry session=%p, user_data=%p, mask_prompt=%08x",
2330 (void *)session,
2331 user_data,
2332 mask_prompt
2333 );
2334
2335 /* THREADS: NO NEED TO LOCK, GLOBAL CACHE IS LOCKED */
2336 #if defined(ENABLE_PKCS11H_THREADING)
2337 if ((rv = _pkcs11h_threading_mutexLock (&session->mutex)) != CKR_OK) {
2338 goto cleanup;
2339 }
2340 mutex_locked = TRUE;
2341 #endif
2342
2343 while (!op_succeed) {
2344 CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
2345 CK_ATTRIBUTE cert_filter[] = {
2346 {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)}
2347 };
2348
2349 CK_OBJECT_HANDLE *objects = NULL;
2350 CK_ULONG objects_found = 0;
2351
2352 CK_ULONG i;
2353
2354 if ((rv = _pkcs11h_session_validate (session)) != CKR_OK) {
2355 goto retry;
2356 }
2357
2358 if (
2359 (rv = _pkcs11h_session_findObjects (
2360 session,
2361 cert_filter,
2362 sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
2363 &objects,
2364 &objects_found
2365 )) != CKR_OK
2366 ) {
2367 goto retry;
2368 }
2369
2370 for (i=0;i < objects_found;i++) {
2371 pkcs11h_certificate_id_t certificate_id = NULL;
2372 pkcs11h_certificate_id_list_t new_element = NULL;
2373
2374 CK_ATTRIBUTE attrs[] = {
2375 {CKA_ID, NULL, 0},
2376 {CKA_VALUE, NULL, 0}
2377 };
2378
2379 if (
2380 (rv = _pkcs11h_session_getObjectAttributes (
2381 session,
2382 objects[i],
2383 attrs,
2384 sizeof (attrs) / sizeof (CK_ATTRIBUTE)
2385 )) != CKR_OK
2386 ) {
2387 goto retry1;
2388 }
2389
2390 /*
2391 * skip objects without CKA_ID as we
2392 * won't be able to retrieve them.
2393 */
2394 if (
2395 attrs[0].pValue == NULL ||
2396 attrs[0].ulValueLen == 0
2397 ) {
2398 rv = CKR_OK;
2399 goto retry1;
2400 }
2401
2402 if (
2403 (rv = _pkcs11h_certificate_newCertificateId (&certificate_id)) != CKR_OK ||
2404 (rv = pkcs11h_token_duplicateTokenId (
2405 &certificate_id->token_id,
2406 session->token_id
2407 )) != CKR_OK ||
2408 (rv = _pkcs11h_mem_duplicate (
2409 (void*)&certificate_id->attrCKA_ID,
2410 &certificate_id->attrCKA_ID_size,
2411 attrs[0].pValue,
2412 attrs[0].ulValueLen
2413 )) != CKR_OK ||
2414 (rv = _pkcs11h_mem_duplicate (
2415 (void*)&certificate_id->certificate_blob,
2416 &certificate_id->certificate_blob_size,
2417 attrs[1].pValue,
2418 attrs[1].ulValueLen
2419 )) != CKR_OK ||
2420 (rv = __pkcs11h_certificate_updateCertificateIdDescription (
2421 certificate_id
2422 )) != CKR_OK ||
2423 (rv = _pkcs11h_mem_malloc (
2424 (void *)&new_element,
2425 sizeof (struct pkcs11h_certificate_id_list_s)
2426 )) != CKR_OK
2427 ) {
2428 goto retry1;
2429 }
2430
2431 new_element->next = session->cached_certs;
2432 new_element->certificate_id = certificate_id;
2433 certificate_id = NULL;
2434
2435 session->cached_certs = new_element;
2436 new_element = NULL;
2437 rv = CKR_OK;
2438
2439 retry1:
2440
2441 if (certificate_id != NULL) {
2442 pkcs11h_certificate_freeCertificateId (certificate_id);
2443 certificate_id = NULL;
2444 }
2445
2446 if (new_element != NULL) {
2447 _pkcs11h_mem_free ((void *)&new_element);
2448 new_element = NULL;
2449 }
2450
2451 _pkcs11h_session_freeObjectAttributes (
2452 attrs,
2453 sizeof (attrs) / sizeof (CK_ATTRIBUTE)
2454 );
2455
2456 if (rv != CKR_OK) {
2457 _PKCS11H_DEBUG (
2458 PKCS11H_LOG_DEBUG1,
2459 "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%lu-'%s'",
2460 session->provider->manufacturerID,
2461 objects[i],
2462 rv,
2463 pkcs11h_getMessage (rv)
2464 );
2465 }
2466 }
2467
2468 op_succeed = TRUE;
2469 rv = CKR_OK;
2470
2471 retry:
2472
2473 if (objects != NULL) {
2474 _pkcs11h_mem_free ((void *)&objects);
2475 }
2476
2477 if (!op_succeed) {
2478 if (!login_retry) {
2479 _PKCS11H_DEBUG (
2480 PKCS11H_LOG_DEBUG1,
2481 "PKCS#11: Get certificate attributes failed: %ld:'%s'",
2482 rv,
2483 pkcs11h_getMessage (rv)
2484 );
2485
2486 rv = _pkcs11h_session_login (
2487 session,
2488 TRUE,
2489 TRUE,
2490 user_data,
2491 (mask_prompt & PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT)
2492 );
2493
2494 login_retry = TRUE;
2495 }
2496
2497 if (rv != CKR_OK) {
2498 goto cleanup;
2499 }
2500 }
2501 }
2502
2503 cleanup:
2504
2505 #if defined(ENABLE_PKCS11H_THREADING)
2506 if (mutex_locked) {
2507 _pkcs11h_threading_mutexRelease (&session->mutex);
2508 mutex_locked = FALSE;
2509 }
2510 #endif
2511
2512 _PKCS11H_DEBUG (
2513 PKCS11H_LOG_DEBUG2,
2514 "PKCS#11: _pkcs11h_certificate_enumSessionCertificates return rv=%lu-'%s'",
2515 rv,
2516 pkcs11h_getMessage (rv)
2517 );
2518
2519 return rv;
2520 }
2521
2522 static
2523 CK_RV
__pkcs11h_certificate_splitCertificateIdList(IN const pkcs11h_certificate_id_list_t cert_id_all,OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list)2524 __pkcs11h_certificate_splitCertificateIdList (
2525 IN const pkcs11h_certificate_id_list_t cert_id_all,
2526 OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
2527 OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
2528 ) {
2529 typedef struct info_s {
2530 struct info_s *next;
2531 pkcs11h_certificate_id_t e;
2532 PKCS11H_BOOL is_issuer;
2533 } *info_t;
2534
2535 pkcs11h_certificate_id_list_t cert_id_issuers_list = NULL;
2536 pkcs11h_certificate_id_list_t cert_id_end_list = NULL;
2537 pkcs11h_certificate_id_list_t entry = NULL;
2538
2539 info_t head = NULL;
2540 info_t info = NULL;
2541
2542 CK_RV rv = CKR_FUNCTION_FAILED;
2543
2544 /*_PKCS11H_ASSERT (cert_id_all!=NULL); NOT NEEDED */
2545 /*_PKCS11H_ASSERT (p_cert_id_issuers_list!=NULL); NOT NEEDED*/
2546 _PKCS11H_ASSERT (p_cert_id_end_list!=NULL);
2547
2548 _PKCS11H_DEBUG (
2549 PKCS11H_LOG_DEBUG2,
2550 "PKCS#11: __pkcs11h_certificate_splitCertificateIdList entry cert_id_all=%p, p_cert_id_issuers_list=%p, p_cert_id_end_list=%p",
2551 (void *)cert_id_all,
2552 (void *)p_cert_id_issuers_list,
2553 (void *)p_cert_id_end_list
2554 );
2555
2556 if (p_cert_id_issuers_list != NULL) {
2557 *p_cert_id_issuers_list = NULL;
2558 }
2559 *p_cert_id_end_list = NULL;
2560
2561 for (
2562 entry = cert_id_all;
2563 entry != NULL;
2564 entry = entry->next
2565 ) {
2566 info_t new_info = NULL;
2567
2568 if ((rv = _pkcs11h_mem_malloc ((void *)&new_info, sizeof (struct info_s))) != CKR_OK) {
2569 goto cleanup;
2570 }
2571
2572 new_info->next = head;
2573 new_info->e = entry->certificate_id;
2574 head = new_info;
2575 new_info = NULL;
2576 }
2577
2578 for (
2579 info = head;
2580 info != NULL;
2581 info = info->next
2582 ) {
2583 info_t info2 = NULL;
2584
2585 for (
2586 info2 = head;
2587 info2 != NULL && !info->is_issuer;
2588 info2 = info2->next
2589 ) {
2590 if (info != info2) {
2591 info->is_issuer = _g_pkcs11h_crypto_engine.certificate_is_issuer (
2592 _g_pkcs11h_crypto_engine.global_data,
2593 info->e->certificate_blob,
2594 info->e->certificate_blob_size,
2595 info2->e->certificate_blob,
2596 info2->e->certificate_blob_size
2597 );
2598 }
2599
2600 }
2601 }
2602
2603 rv = CKR_OK;
2604 for (
2605 info = head;
2606 info != NULL;
2607 info = info->next
2608 ) {
2609 pkcs11h_certificate_id_list_t new_entry = NULL;
2610
2611 if (
2612 (rv = _pkcs11h_mem_malloc (
2613 (void *)&new_entry,
2614 sizeof (struct pkcs11h_certificate_id_list_s)
2615 )) != CKR_OK ||
2616 (rv = pkcs11h_certificate_duplicateCertificateId (
2617 &new_entry->certificate_id,
2618 info->e
2619 )) != CKR_OK
2620 ) {
2621 if (new_entry != NULL) {
2622 if (new_entry->certificate_id != NULL) {
2623 pkcs11h_certificate_freeCertificateId (new_entry->certificate_id);
2624 }
2625 _pkcs11h_mem_free ((void *)&new_entry);
2626 }
2627 goto cleanup;
2628 }
2629
2630 /*
2631 * Should not free base list
2632 */
2633 info->e = NULL;
2634
2635 if (info->is_issuer) {
2636 new_entry->next = cert_id_issuers_list;
2637 cert_id_issuers_list = new_entry;
2638 new_entry = NULL;
2639 }
2640 else {
2641 new_entry->next = cert_id_end_list;
2642 cert_id_end_list = new_entry;
2643 new_entry = NULL;
2644 }
2645 }
2646
2647
2648 if (p_cert_id_issuers_list != NULL ) {
2649 *p_cert_id_issuers_list = cert_id_issuers_list;
2650 cert_id_issuers_list = NULL;
2651 }
2652
2653 *p_cert_id_end_list = cert_id_end_list;
2654 cert_id_end_list = NULL;
2655
2656 rv = CKR_OK;
2657
2658 cleanup:
2659
2660 while (head != NULL) {
2661 info_t entry = head;
2662 head = head->next;
2663
2664 _pkcs11h_mem_free ((void *)&entry);
2665 }
2666
2667 if (cert_id_issuers_list != NULL) {
2668 pkcs11h_certificate_freeCertificateIdList (cert_id_issuers_list);
2669 }
2670
2671 if (cert_id_end_list != NULL) {
2672 pkcs11h_certificate_freeCertificateIdList (cert_id_end_list);
2673 }
2674
2675 _PKCS11H_DEBUG (
2676 PKCS11H_LOG_DEBUG2,
2677 "PKCS#11: __pkcs11h_certificate_splitCertificateIdList return rv=%lu-'%s'",
2678 rv,
2679 pkcs11h_getMessage (rv)
2680 );
2681
2682 return rv;
2683 }
2684
2685 CK_RV
pkcs11h_certificate_freeCertificateIdList(IN const pkcs11h_certificate_id_list_t cert_id_list)2686 pkcs11h_certificate_freeCertificateIdList (
2687 IN const pkcs11h_certificate_id_list_t cert_id_list
2688 ) {
2689 pkcs11h_certificate_id_list_t _id = cert_id_list;
2690
2691 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
2692 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
2693 /*_PKCS11H_ASSERT (cert_id_list!=NULL); NOT NEEDED*/
2694
2695 _PKCS11H_DEBUG (
2696 PKCS11H_LOG_DEBUG2,
2697 "PKCS#11: pkcs11h_certificate_freeCertificateIdList entry cert_id_list=%p",
2698 (void *)cert_id_list
2699 );
2700
2701 while (_id != NULL) {
2702 pkcs11h_certificate_id_list_t x = _id;
2703 _id = _id->next;
2704 if (x->certificate_id != NULL) {
2705 pkcs11h_certificate_freeCertificateId (x->certificate_id);
2706 }
2707 x->next = NULL;
2708 _pkcs11h_mem_free ((void *)&x);
2709 }
2710
2711 _PKCS11H_DEBUG (
2712 PKCS11H_LOG_DEBUG2,
2713 "PKCS#11: pkcs11h_certificate_freeCertificateIdList return"
2714 );
2715
2716 return CKR_OK;
2717 }
2718
2719 CK_RV
pkcs11h_certificate_enumTokenCertificateIds(IN const pkcs11h_token_id_t token_id,IN const unsigned method,IN void * const user_data,IN const unsigned mask_prompt,OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list)2720 pkcs11h_certificate_enumTokenCertificateIds (
2721 IN const pkcs11h_token_id_t token_id,
2722 IN const unsigned method,
2723 IN void * const user_data,
2724 IN const unsigned mask_prompt,
2725 OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
2726 OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
2727 ) {
2728 #if defined(ENABLE_PKCS11H_THREADING)
2729 PKCS11H_BOOL mutex_locked = FALSE;
2730 #endif
2731 _pkcs11h_session_t session = NULL;
2732 CK_RV rv = CKR_FUNCTION_FAILED;
2733
2734 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
2735 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
2736 _PKCS11H_ASSERT (token_id!=NULL);
2737 /*_PKCS11H_ASSERT (user_data) NOT NEEDED */
2738 /*_PKCS11H_ASSERT (p_cert_id_issuers_list!=NULL); NOT NEEDED*/
2739 _PKCS11H_ASSERT (p_cert_id_end_list!=NULL);
2740
2741 _PKCS11H_DEBUG (
2742 PKCS11H_LOG_DEBUG2,
2743 "PKCS#11: pkcs11h_certificate_enumTokenCertificateIds entry token_id=%p, method=%u, user_data=%p, mask_prompt=%08x, p_cert_id_issuers_list=%p, p_cert_id_end_list=%p",
2744 (void *)token_id,
2745 method,
2746 user_data,
2747 mask_prompt,
2748 (void *)p_cert_id_issuers_list,
2749 (void *)p_cert_id_end_list
2750 );
2751
2752 if (p_cert_id_issuers_list != NULL) {
2753 *p_cert_id_issuers_list = NULL;
2754 }
2755 *p_cert_id_end_list = NULL;
2756
2757 #if defined(ENABLE_PKCS11H_THREADING)
2758 if ((rv = _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.cache)) != CKR_OK) {
2759 goto cleanup;
2760 }
2761 mutex_locked = TRUE;
2762 #endif
2763
2764 if (
2765 (rv = _pkcs11h_session_getSessionByTokenId (
2766 token_id,
2767 &session
2768 )) != CKR_OK
2769 ) {
2770 goto cleanup;
2771 }
2772
2773 if (method == PKCS11H_ENUM_METHOD_RELOAD) {
2774 pkcs11h_certificate_freeCertificateIdList (session->cached_certs);
2775 session->cached_certs = NULL;
2776 }
2777
2778 if (session->cached_certs == NULL) {
2779 rv = _pkcs11h_certificate_enumSessionCertificates (session, user_data, mask_prompt);
2780 }
2781
2782 if (
2783 (rv = __pkcs11h_certificate_splitCertificateIdList (
2784 session->cached_certs,
2785 p_cert_id_issuers_list,
2786 p_cert_id_end_list
2787 )) != CKR_OK
2788 ) {
2789 goto cleanup;
2790 }
2791
2792 rv = CKR_OK;
2793
2794 cleanup:
2795
2796 if (session != NULL) {
2797 _pkcs11h_session_release (session);
2798 }
2799
2800 #if defined(ENABLE_PKCS11H_THREADING)
2801 if (mutex_locked) {
2802 _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.cache);
2803 mutex_locked = FALSE;
2804 }
2805 #endif
2806
2807 _PKCS11H_DEBUG (
2808 PKCS11H_LOG_DEBUG2,
2809 "PKCS#11: pkcs11h_certificate_enumTokenCertificateIds return rv=%lu-'%s'",
2810 rv,
2811 pkcs11h_getMessage (rv)
2812 );
2813
2814 return rv;
2815 }
2816
2817 CK_RV
pkcs11h_certificate_enumCertificateIds(IN const unsigned method,IN void * const user_data,IN const unsigned mask_prompt,OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list)2818 pkcs11h_certificate_enumCertificateIds (
2819 IN const unsigned method,
2820 IN void * const user_data,
2821 IN const unsigned mask_prompt,
2822 OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
2823 OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
2824 ) {
2825 #if defined(ENABLE_PKCS11H_THREADING)
2826 PKCS11H_BOOL mutex_locked = FALSE;
2827 #endif
2828 pkcs11h_certificate_id_list_t cert_id_list = NULL;
2829 _pkcs11h_provider_t current_provider;
2830 _pkcs11h_session_t current_session;
2831 CK_RV rv = CKR_FUNCTION_FAILED;
2832
2833 _PKCS11H_ASSERT (_g_pkcs11h_data!=NULL);
2834 _PKCS11H_ASSERT (_g_pkcs11h_data->initialized);
2835 /*_PKCS11H_ASSERT (user_data!=NULL); NOT NEEDED*/
2836 /*_PKCS11H_ASSERT (p_cert_id_issuers_list!=NULL); NOT NEEDED*/
2837 _PKCS11H_ASSERT (p_cert_id_end_list!=NULL);
2838
2839 _PKCS11H_DEBUG (
2840 PKCS11H_LOG_DEBUG2,
2841 "PKCS#11: pkcs11h_certificate_enumCertificateIds entry method=%u, mask_prompt=%08x, p_cert_id_issuers_list=%p, p_cert_id_end_list=%p",
2842 method,
2843 mask_prompt,
2844 (void *)p_cert_id_issuers_list,
2845 (void *)p_cert_id_end_list
2846 );
2847
2848 if (p_cert_id_issuers_list != NULL) {
2849 *p_cert_id_issuers_list = NULL;
2850 }
2851 *p_cert_id_end_list = NULL;
2852
2853 #if defined(ENABLE_PKCS11H_THREADING)
2854 if ((rv = _pkcs11h_threading_mutexLock (&_g_pkcs11h_data->mutexes.cache)) != CKR_OK) {
2855 goto cleanup;
2856 }
2857 mutex_locked = TRUE;
2858 #endif
2859
2860 for (
2861 current_session = _g_pkcs11h_data->sessions;
2862 current_session != NULL;
2863 current_session = current_session->next
2864 ) {
2865 current_session->touch = FALSE;
2866 if (method == PKCS11H_ENUM_METHOD_RELOAD) {
2867 pkcs11h_certificate_freeCertificateIdList (current_session->cached_certs);
2868 current_session->cached_certs = NULL;
2869 }
2870 }
2871
2872 for (
2873 current_provider = _g_pkcs11h_data->providers;
2874 current_provider != NULL;
2875 current_provider = current_provider->next
2876 ) {
2877 CK_SLOT_ID_PTR slots = NULL;
2878 CK_ULONG slotnum;
2879 CK_SLOT_ID slot_index;
2880
2881 if (!current_provider->enabled) {
2882 continue;
2883 }
2884
2885 if (
2886 (rv = _pkcs11h_session_getSlotList (
2887 current_provider,
2888 CK_TRUE,
2889 &slots,
2890 &slotnum
2891 )) != CKR_OK
2892 ) {
2893 goto retry1;
2894 }
2895
2896 for (
2897 slot_index=0;
2898 slot_index < slotnum;
2899 slot_index++
2900 ) {
2901 _pkcs11h_session_t session = NULL;
2902 pkcs11h_token_id_t token_id = NULL;
2903 CK_TOKEN_INFO info;
2904
2905 if (
2906 (rv = current_provider->f->C_GetTokenInfo (
2907 slots[slot_index],
2908 &info
2909 )) != CKR_OK ||
2910 (rv = _pkcs11h_token_getTokenId (
2911 &info,
2912 &token_id
2913 )) != CKR_OK ||
2914 (rv = _pkcs11h_session_getSessionByTokenId (
2915 token_id,
2916 &session
2917 )) != CKR_OK
2918 ) {
2919 goto retry11;
2920 }
2921
2922 session->touch = TRUE;
2923
2924 if (session->cached_certs == NULL) {
2925 if (
2926 (rv = _pkcs11h_certificate_enumSessionCertificates (
2927 session,
2928 user_data,
2929 mask_prompt
2930 )) != CKR_OK
2931 ) {
2932 goto retry11;
2933 }
2934 }
2935
2936 rv = CKR_OK;
2937
2938 retry11:
2939
2940 if (rv != CKR_OK) {
2941 _PKCS11H_DEBUG (
2942 PKCS11H_LOG_DEBUG1,
2943 "PKCS#11: Cannot get token information for provider '%s' slot %ld rv=%lu-'%s'",
2944 current_provider->manufacturerID,
2945 slots[slot_index],
2946 rv,
2947 pkcs11h_getMessage (rv)
2948 );
2949 }
2950
2951 if (session != NULL) {
2952 _pkcs11h_session_release (session);
2953 session = NULL;
2954 }
2955
2956 if (token_id != NULL) {
2957 pkcs11h_token_freeTokenId (token_id);
2958 token_id = NULL;
2959 }
2960 }
2961
2962 rv = CKR_OK;
2963
2964 retry1:
2965
2966 if (rv != CKR_OK) {
2967 _PKCS11H_DEBUG (
2968 PKCS11H_LOG_DEBUG1,
2969 "PKCS#11: Cannot get slot list for provider '%s' rv=%lu-'%s'",
2970 current_provider->manufacturerID,
2971 rv,
2972 pkcs11h_getMessage (rv)
2973 );
2974 }
2975
2976 if (slots != NULL) {
2977 _pkcs11h_mem_free ((void *)&slots);
2978 slots = NULL;
2979 }
2980 }
2981
2982 for (
2983 current_session = _g_pkcs11h_data->sessions;
2984 current_session != NULL;
2985 current_session = current_session->next
2986 ) {
2987 if (
2988 method == PKCS11H_ENUM_METHOD_CACHE ||
2989 (
2990 (
2991 method == PKCS11H_ENUM_METHOD_RELOAD ||
2992 method == PKCS11H_ENUM_METHOD_CACHE_EXIST
2993 ) &&
2994 current_session->touch
2995 )
2996 ) {
2997 pkcs11h_certificate_id_list_t entry = NULL;
2998
2999 for (
3000 entry = current_session->cached_certs;
3001 entry != NULL;
3002 entry = entry->next
3003 ) {
3004 pkcs11h_certificate_id_list_t new_entry = NULL;
3005
3006 if (
3007 (rv = _pkcs11h_mem_malloc (
3008 (void *)&new_entry,
3009 sizeof (struct pkcs11h_certificate_id_list_s)
3010 )) != CKR_OK ||
3011 (rv = pkcs11h_certificate_duplicateCertificateId (
3012 &new_entry->certificate_id,
3013 entry->certificate_id
3014 )) != CKR_OK
3015 ) {
3016 if (new_entry != NULL) {
3017 new_entry->next = NULL;
3018 pkcs11h_certificate_freeCertificateIdList (new_entry);
3019 new_entry = NULL;
3020 }
3021 goto cleanup;
3022 }
3023
3024 new_entry->next = cert_id_list;
3025 cert_id_list = new_entry;
3026 new_entry = NULL;
3027 }
3028 }
3029 }
3030
3031 if (
3032 (rv = __pkcs11h_certificate_splitCertificateIdList (
3033 cert_id_list,
3034 p_cert_id_issuers_list,
3035 p_cert_id_end_list
3036 )) != CKR_OK
3037 ) {
3038 goto cleanup;
3039 }
3040
3041 rv = CKR_OK;
3042
3043 cleanup:
3044
3045 if (cert_id_list != NULL) {
3046 pkcs11h_certificate_freeCertificateIdList (cert_id_list);
3047 cert_id_list = NULL;
3048 }
3049
3050
3051 #if defined(ENABLE_PKCS11H_THREADING)
3052 if (mutex_locked) {
3053 _pkcs11h_threading_mutexRelease (&_g_pkcs11h_data->mutexes.cache);
3054 mutex_locked = FALSE;
3055 }
3056 #endif
3057
3058 _PKCS11H_DEBUG (
3059 PKCS11H_LOG_DEBUG2,
3060 "PKCS#11: pkcs11h_certificate_enumCertificateIds return rv=%lu-'%s'",
3061 rv,
3062 pkcs11h_getMessage (rv)
3063 );
3064
3065 return rv;
3066 }
3067
3068 #endif /* ENABLE_PKCS11H_CERTIFICATE */
3069