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 				&notAfterCurrent
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 				&notAfterNew
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 (&notAfterCurrent)),
166 			asctime (localtime (&notAfterNew))
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