1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <pthread.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <security/cryptoki.h>
31 #include "kernelGlobal.h"
32 #include "kernelObject.h"
33 #include "kernelSession.h"
34 #include <errno.h>
35 #include <string.h>
36 #include <cryptoutil.h>
37 
38 CK_RV
C_CreateObject(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phObject)39 C_CreateObject(CK_SESSION_HANDLE hSession,
40     CK_ATTRIBUTE_PTR pTemplate,
41     CK_ULONG ulCount,
42     CK_OBJECT_HANDLE_PTR phObject)
43 {
44 
45 	CK_RV rv;
46 	kernel_session_t *session_p;
47 	boolean_t ses_lock_held = B_FALSE;
48 
49 	if (!kernel_initialized)
50 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
51 
52 	if ((pTemplate == NULL) || (ulCount == 0) ||
53 	    (phObject == NULL)) {
54 		return (CKR_ARGUMENTS_BAD);
55 	}
56 
57 	/*
58 	 * Obtain the session pointer. Also, increment the session
59 	 * reference count.
60 	 */
61 	rv = handle2session(hSession, &session_p);
62 	if (rv != CKR_OK)
63 		return (rv);
64 
65 	/* Create a new object. */
66 	rv = kernel_add_object(pTemplate, ulCount, phObject, session_p);
67 
68 	/*
69 	 * Decrement the session reference count.
70 	 * We do not hold the session lock.
71 	 */
72 	REFRELE(session_p, ses_lock_held);
73 
74 	return (rv);
75 }
76 
77 
78 CK_RV
C_CopyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phNewObject)79 C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
80     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
81     CK_OBJECT_HANDLE_PTR phNewObject)
82 {
83 
84 	CK_RV rv;
85 	kernel_session_t *session_p;
86 	boolean_t ses_lock_held = B_FALSE;
87 	kernel_object_t *old_object;
88 	kernel_object_t *new_object = NULL;
89 	crypto_object_copy_t  object_copy;
90 	CK_BBOOL is_pri_obj = FALSE;
91 	CK_BBOOL is_token_obj = FALSE;
92 	kernel_slot_t	*pslot;
93 	int i, r;
94 
95 	if (!kernel_initialized)
96 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
97 
98 	/* Check arguments */
99 	if (((ulCount > 0) && (pTemplate == NULL)) ||
100 	    (phNewObject == NULL)) {
101 		return (CKR_ARGUMENTS_BAD);
102 	}
103 
104 	/*
105 	 * Obtain the session pointer. Also, increment the session
106 	 * reference count.
107 	 */
108 	rv = handle2session(hSession, &session_p);
109 	if (rv != CKR_OK)
110 		return (rv);
111 
112 	/* Obtain the object pointer. */
113 	HANDLE2OBJECT(hObject, old_object, rv);
114 	if (rv != CKR_OK) {
115 		/*
116 		 * Decrement the session reference count.
117 		 * We do not hold the session lock.
118 		 */
119 		REFRELE(session_p, ses_lock_held);
120 		return (rv);
121 	}
122 
123 	(void) pthread_mutex_lock(&old_object->object_mutex);
124 
125 	if (old_object->is_lib_obj) {
126 		/*
127 		 * Copy the old object to a new object.
128 		 * The 3rd argument with TRUE value indicates that
129 		 * everything in the object will be duplicated.
130 		 */
131 		rv = kernel_copy_object(old_object, &new_object, B_TRUE,
132 		    session_p);
133 		(void) pthread_mutex_unlock(&old_object->object_mutex);
134 		if ((rv != CKR_OK) || (new_object == NULL)) {
135 			/*
136 			 * Most likely we ran out of space.
137 			 * Decrement the session reference count.
138 			 * We do not hold the session lock.
139 			 */
140 			OBJ_REFRELE(old_object);
141 			REFRELE(session_p, ses_lock_held);
142 			return (rv);
143 		}
144 
145 		new_object->is_lib_obj = B_TRUE;
146 
147 		/* Modify the object attribute if requested */
148 		for (i = 0; i < ulCount; i++) {
149 			/* Set the requested attribute into the new object. */
150 			rv = kernel_set_attribute(new_object, &pTemplate[i],
151 			    B_TRUE, session_p);
152 
153 			if (rv != CKR_OK) {
154 				kernel_cleanup_object(new_object);
155 
156 				/*
157 				 * Decrement the session reference count.
158 				 * We do not hold the session lock.
159 				 */
160 				OBJ_REFRELE(old_object);
161 				REFRELE(session_p, ses_lock_held);
162 				return (rv);
163 			}
164 		}
165 
166 		/* Insert the new object into this session's object list. */
167 		kernel_add_object_to_session(new_object, session_p);
168 
169 		/*
170 		 * Decrement the session reference count.
171 		 * We do not hold the session lock.
172 		 */
173 		OBJ_REFRELE(old_object);
174 		REFRELE(session_p, ses_lock_held);
175 
176 		/* set handle of the new object */
177 		*phNewObject = (CK_ULONG)new_object;
178 
179 	} else {
180 		/*
181 		 * The old object was created in the HW provider.
182 		 * First, create an object wrapper in library.
183 		 */
184 		new_object = calloc(1, sizeof (kernel_object_t));
185 		if (new_object == NULL) {
186 			(void) pthread_mutex_unlock(&old_object->object_mutex);
187 			OBJ_REFRELE(old_object);
188 			REFRELE(session_p, ses_lock_held);
189 			return (CKR_HOST_MEMORY);
190 		}
191 
192 		/* Call CRYPTO_OBJECT_COPY ioctl to get a new object. */
193 		object_copy.oc_session = session_p->k_session;
194 		object_copy.oc_handle = old_object->k_handle;
195 		(void) pthread_mutex_unlock(&old_object->object_mutex);
196 		object_copy.oc_count = ulCount;
197 		object_copy.oc_new_attributes = NULL;
198 		if (ulCount > 0) {
199 			rv = process_object_attributes(pTemplate, ulCount,
200 			    &object_copy.oc_new_attributes, &is_token_obj);
201 			if (rv != CKR_OK) {
202 				goto failed_cleanup;
203 			}
204 		}
205 
206 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_COPY,
207 		    &object_copy)) < 0) {
208 			if (errno != EINTR)
209 				break;
210 		}
211 		if (r < 0) {
212 			rv = CKR_FUNCTION_FAILED;
213 		} else {
214 			rv = crypto2pkcs11_error_number(
215 			    object_copy.oc_return_value);
216 		}
217 
218 		/* Free the attributes' space allocated for ioctl */
219 		free_object_attributes(object_copy.oc_new_attributes, ulCount);
220 
221 		if (rv != CKR_OK) {
222 			goto failed_cleanup;
223 		}
224 
225 		/*
226 		 * Store the kernel object handle in the object wrapper and
227 		 * get the CKA_PRIVATE value of the new object.
228 		 */
229 		new_object->k_handle = object_copy.oc_new_handle;
230 		rv = get_cka_private_value(session_p, new_object->k_handle,
231 		    &is_pri_obj);
232 		if (rv != CKR_OK) {
233 			goto failed_cleanup;
234 		}
235 
236 		/*
237 		 * Initialize other field of the object wrapper.
238 		 */
239 		new_object->is_lib_obj = B_FALSE;
240 		new_object->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
241 		new_object->session_handle = (CK_SESSION_HANDLE)session_p;
242 		(void) pthread_mutex_init(&new_object->object_mutex, NULL);
243 
244 		if (is_pri_obj)
245 			new_object->bool_attr_mask |= PRIVATE_BOOL_ON;
246 		else
247 			new_object->bool_attr_mask &= ~PRIVATE_BOOL_ON;
248 
249 		if (is_token_obj)
250 			new_object->bool_attr_mask |= TOKEN_BOOL_ON;
251 		else
252 			new_object->bool_attr_mask &= ~TOKEN_BOOL_ON;
253 
254 		/*
255 		 * Add the new copied object into the slot's token list
256 		 * or the session list.  We don't hold the slot lock.
257 		 */
258 		if (is_token_obj) {
259 			pslot = slot_table[session_p->ses_slotid];
260 
261 			/*
262 			 * Decrement the session reference count.
263 			 * We do not hold the session lock.
264 			 */
265 			OBJ_REFRELE(old_object);
266 			REFRELE(session_p, ses_lock_held);
267 
268 			/* Add into the slot token object list. */
269 			kernel_add_token_object_to_slot(new_object, pslot);
270 		} else {
271 			kernel_add_object_to_session(new_object, session_p);
272 
273 			/*
274 			 * Decrement the session reference count.
275 			 * We do not hold the session lock.
276 			 */
277 			OBJ_REFRELE(old_object);
278 			REFRELE(session_p, ses_lock_held);
279 		}
280 
281 		/* set handle of the new object */
282 		*phNewObject = (CK_ULONG)new_object;
283 	}
284 
285 	return (rv);
286 
287 failed_cleanup:
288 	if (new_object != NULL) {
289 		(void) free(new_object);
290 	}
291 
292 	OBJ_REFRELE(old_object);
293 	REFRELE(session_p, ses_lock_held);
294 	return (rv);
295 }
296 
297 
298 CK_RV
C_DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject)299 C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
300 {
301 	CK_RV rv;
302 	kernel_object_t *object_p;
303 	kernel_session_t *session_p = (kernel_session_t *)(hSession);
304 	kernel_slot_t	*pslot;
305 	boolean_t ses_lock_held = B_FALSE;
306 	CK_SESSION_HANDLE creating_session;
307 
308 	if (!kernel_initialized)
309 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
310 
311 	/*
312 	 * The reason that we don't call handle2session is because
313 	 * the argument hSession may not be the creating_session of
314 	 * the object to be destroyed, and we want to avoid the lock
315 	 * contention. The handle2session will be called later for
316 	 * the creating_session.
317 	 */
318 	if ((session_p == NULL) ||
319 	    (session_p->magic_marker != KERNELTOKEN_SESSION_MAGIC)) {
320 		return (CKR_SESSION_HANDLE_INVALID);
321 	}
322 
323 	/* Obtain the object pointer without incrementing reference count. */
324 	HANDLE2OBJECT_DESTROY(hObject, object_p, rv);
325 	if (rv != CKR_OK) {
326 		return (rv);
327 	}
328 
329 	/* Only session objects can be destroyed at a read-only session. */
330 	if ((session_p->ses_RO) &&
331 	    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
332 		return (CKR_SESSION_READ_ONLY);
333 	}
334 
335 	/*
336 	 * If the object is a session object, obtain the session handle
337 	 * which object belongs to.  For a token object, we will use the
338 	 * session handle from the caller, because the session used to
339 	 * create the token object may no longer exist.
340 	 */
341 	if (!(object_p->bool_attr_mask & TOKEN_BOOL_ON))
342 		creating_session = object_p->session_handle;
343 	else
344 		creating_session = hSession;
345 
346 	rv = handle2session(creating_session, &session_p);
347 	if (rv != CKR_OK) {
348 		return (rv);
349 	}
350 
351 	/*
352 	 * Set OBJECT_IS_DELETING flag so any access to this
353 	 * object will be rejected.
354 	 */
355 	(void) pthread_mutex_lock(&object_p->object_mutex);
356 	if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
357 		(void) pthread_mutex_unlock(&object_p->object_mutex);
358 		REFRELE(session_p, ses_lock_held);
359 		return (CKR_OBJECT_HANDLE_INVALID);
360 	}
361 	object_p->obj_delete_sync |= OBJECT_IS_DELETING;
362 	(void) pthread_mutex_unlock(&object_p->object_mutex);
363 
364 	if (object_p->bool_attr_mask & TOKEN_BOOL_ON) {
365 		/*
366 		 * The first FALSE boolean argument indicates that the caller
367 		 * does not hold the slot lock.  The second FALSE boolean
368 		 * argument indicates that the caller wants to clean up the
369 		 * object in the HW provider also.
370 		 */
371 		pslot = slot_table[session_p->ses_slotid];
372 		rv = kernel_delete_token_object(pslot, session_p, object_p,
373 		    B_FALSE, B_FALSE);
374 	} else {
375 		/*
376 		 * The first FALSE boolean argument indicates that the caller
377 		 * does not hold the session lock.  The second FALSE boolean
378 		 * argument indicates that the caller wants to clean the object
379 		 * in the HW provider also.
380 		 */
381 		rv = kernel_delete_session_object(session_p, object_p, B_FALSE,
382 		    B_FALSE);
383 	}
384 	/*
385 	 * Decrement the session reference count.
386 	 * We do not hold the session lock.
387 	 */
388 	REFRELE(session_p, ses_lock_held);
389 	return (rv);
390 }
391 
392 
393 CK_RV
C_GetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)394 C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
395     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
396 {
397 
398 	CK_RV rv = CKR_OK, rv1 = CKR_OK;
399 	kernel_object_t *object_p;
400 	kernel_session_t *session_p;
401 	boolean_t ses_lock_held = B_FALSE;
402 	crypto_object_get_attribute_value_t obj_get_attr;
403 	int i, r;
404 
405 	if (!kernel_initialized)
406 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
407 
408 	if ((pTemplate == NULL) || (ulCount == 0))
409 		return (CKR_ARGUMENTS_BAD);
410 
411 	/*
412 	 * Obtain the session pointer. Also, increment the session
413 	 * reference count.
414 	 */
415 	rv = handle2session(hSession, &session_p);
416 	if (rv != CKR_OK)
417 		return (rv);
418 
419 	/* Obtain the object pointer. */
420 	HANDLE2OBJECT(hObject, object_p, rv);
421 	if (rv != CKR_OK) {
422 		/*
423 		 * Decrement the session reference count.
424 		 * We do not hold the session lock.
425 		 */
426 		REFRELE(session_p, ses_lock_held);
427 		return (rv);
428 	}
429 
430 	/* Acquire the lock on the object. */
431 	(void) pthread_mutex_lock(&object_p->object_mutex);
432 
433 	if (object_p->is_lib_obj) {
434 		/*
435 		 * The object was created in the library. The library
436 		 * contains the value information of each attribute.
437 		 */
438 		for (i = 0; i < ulCount; i++) {
439 			/*
440 			 * Get the value of each attribute in the template.
441 			 * (We must process EVERY attribute in the template.)
442 			 */
443 			rv = kernel_get_attribute(object_p, &pTemplate[i]);
444 			if (rv != CKR_OK)
445 				/* At least we catch some type of error. */
446 				rv1 = rv;
447 		}
448 		rv = rv1;
449 		(void) pthread_mutex_unlock(&object_p->object_mutex);
450 	} else {
451 		/*
452 		 * The object was created in HW provider, call ioctl to get
453 		 * the values of attributes.
454 		 */
455 		obj_get_attr.og_session = session_p->k_session;
456 		obj_get_attr.og_handle = object_p->k_handle;
457 		(void) pthread_mutex_unlock(&object_p->object_mutex);
458 		obj_get_attr.og_count = ulCount;
459 
460 		rv = process_object_attributes(pTemplate, ulCount,
461 		    &obj_get_attr.og_attributes, NULL);
462 		if (rv != CKR_OK) {
463 			goto clean_exit;
464 		}
465 
466 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
467 		    &obj_get_attr)) < 0) {
468 			if (errno != EINTR)
469 				break;
470 		}
471 		if (r < 0) {
472 			rv = CKR_FUNCTION_FAILED;
473 		} else {
474 			rv = crypto2pkcs11_error_number(
475 			    obj_get_attr.og_return_value);
476 		}
477 
478 		/*
479 		 * The error codes CKR_ATTRIBUTE_SENSITIVE,
480 		 * CKR_ATTRIBUTE_TYPE_INVALID, and CKR_BUFFER_TOO_SMALL
481 		 * do not denote true errors for this function. If a call
482 		 * returns any of these three values, then the call must
483 		 * nonetheless have processed every attribute in the
484 		 * template.  Every attribute in the template whose value
485 		 * can be returned will be returned.
486 		 */
487 		if ((rv == CKR_OK) ||
488 		    (rv == CKR_ATTRIBUTE_SENSITIVE) ||
489 		    (rv == CKR_ATTRIBUTE_TYPE_INVALID) ||
490 		    (rv == CKR_BUFFER_TOO_SMALL)) {
491 			rv1 = get_object_attributes(pTemplate, ulCount,
492 			    obj_get_attr.og_attributes);
493 			if (rv1 != CKR_OK) {
494 				rv = rv1;
495 			}
496 		}
497 
498 		/* Free the attributes' allocated for the ioctl call. */
499 		free_object_attributes(obj_get_attr.og_attributes, ulCount);
500 	}
501 
502 clean_exit:
503 	/*
504 	 * Decrement the session reference count.
505 	 * We do not hold the session lock.
506 	 */
507 	OBJ_REFRELE(object_p);
508 	REFRELE(session_p, ses_lock_held);
509 	return (rv);
510 }
511 
512 
513 CK_RV
C_SetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)514 C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
515     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
516 {
517 	CK_RV rv = CKR_OK;
518 	kernel_object_t *object_p;
519 	kernel_object_t *new_object = NULL;
520 	kernel_session_t *session_p;
521 	boolean_t ses_lock_held = B_FALSE;
522 	crypto_object_set_attribute_value_t obj_set_attr;
523 	int i, r;
524 
525 	if (!kernel_initialized)
526 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
527 
528 	if ((pTemplate == NULL) || (ulCount == 0))
529 		return (CKR_ARGUMENTS_BAD);
530 
531 	/*
532 	 * Obtain the session pointer. Also, increment the session
533 	 * reference count.
534 	 */
535 	rv = handle2session(hSession, &session_p);
536 	if (rv != CKR_OK)
537 		return (rv);
538 
539 	/* Obtain the object pointer. */
540 	HANDLE2OBJECT(hObject, object_p, rv);
541 	if (rv != CKR_OK) {
542 		/*
543 		 * Decrement the session reference count.
544 		 * We do not hold the session lock.
545 		 */
546 		REFRELE(session_p, ses_lock_held);
547 		return (rv);
548 	}
549 
550 	/* lock the object */
551 	(void) pthread_mutex_lock(&object_p->object_mutex);
552 
553 	/*
554 	 * If the object was created in the HW provider, changing its
555 	 * attributes' values need to be done in the provider too.
556 	 */
557 	if (!object_p->is_lib_obj) {
558 
559 		/* Cannot modify a token object with a READ-ONLY session */
560 		if (session_p->ses_RO &&
561 		    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
562 			(void) pthread_mutex_unlock(&object_p->object_mutex);
563 			rv = CKR_SESSION_READ_ONLY;
564 			goto clean_exit;
565 		}
566 
567 		obj_set_attr.sa_session = session_p->k_session;
568 		obj_set_attr.sa_handle = object_p->k_handle;
569 		(void) pthread_mutex_unlock(&object_p->object_mutex);
570 		obj_set_attr.sa_count = ulCount;
571 		rv = process_object_attributes(pTemplate, ulCount,
572 		    &obj_set_attr.sa_attributes, NULL);
573 		if (rv != CKR_OK) {
574 			goto clean_exit;
575 		}
576 
577 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE,
578 		    &obj_set_attr)) < 0) {
579 			if (errno != EINTR)
580 				break;
581 		}
582 		if (r < 0) {
583 			rv = CKR_FUNCTION_FAILED;
584 		} else {
585 			rv = crypto2pkcs11_error_number(
586 			    obj_set_attr.sa_return_value);
587 		}
588 
589 		/* Free the attributes' space allocated for the ioctl call. */
590 		free_object_attributes(obj_set_attr.sa_attributes, ulCount);
591 		goto clean_exit;
592 	}
593 
594 	/*
595 	 * if we come here, the object must have been created in the
596 	 * library.  The work will be done completely in the library.
597 	 *
598 	 * Copy the old object to a new object. We work on the copied
599 	 * version because in case of error we still keep the old one
600 	 * intact.
601 	 */
602 	rv = kernel_copy_object(object_p, &new_object, B_FALSE, NULL);
603 	(void) pthread_mutex_unlock(&object_p->object_mutex);
604 	if ((rv != CKR_OK) || (new_object == NULL)) {
605 		/*
606 		 * Most likely we ran out of space.
607 		 * Decrement the session reference count.
608 		 * We do not hold the session lock.
609 		 */
610 		goto clean_exit;
611 	}
612 
613 	for (i = 0; i < ulCount; i++) {
614 		/* Set the requested attribute into the new object. */
615 		rv = kernel_set_attribute(new_object, &pTemplate[i], B_FALSE,
616 		    session_p);
617 
618 		if (rv != CKR_OK) {
619 			kernel_cleanup_object(new_object);
620 			goto clean_exit;
621 		}
622 	}
623 
624 	/*
625 	 * We've successfully set all the requested attributes.
626 	 * Merge the new object with the old object, then destory
627 	 * the new one. The reason to do the merging is because we
628 	 * have to keep the original object handle (address of object).
629 	 */
630 	(void) pthread_mutex_lock(&object_p->object_mutex);
631 	kernel_merge_object(object_p, new_object);
632 	(void) pthread_mutex_unlock(&object_p->object_mutex);
633 
634 clean_exit:
635 	if (new_object != NULL)
636 		(void) free(new_object);
637 
638 	/*
639 	 * Decrement the session reference count.
640 	 * We do not hold the session lock.
641 	 */
642 	OBJ_REFRELE(object_p);
643 	REFRELE(session_p, ses_lock_held);
644 
645 	return (rv);
646 }
647 
648 
649 CK_RV
C_GetObjectSize(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ULONG_PTR pulSize)650 C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
651     CK_ULONG_PTR pulSize)
652 {
653 
654 	CK_RV rv = CKR_OK;
655 	kernel_object_t *object_p;
656 	kernel_session_t *session_p;
657 	boolean_t ses_lock_held = B_FALSE;
658 	crypto_object_get_size_t obj_gs;
659 	int r;
660 
661 	if (!kernel_initialized)
662 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
663 
664 	/* Check if pulSize is valid */
665 	if (pulSize == NULL) {
666 		return (CKR_ARGUMENTS_BAD);
667 	}
668 
669 	/*
670 	 * Obtain the session pointer. Also, increment the session
671 	 * reference count.
672 	 */
673 	rv = handle2session(hSession, &session_p);
674 	if (rv != CKR_OK)
675 		return (rv);
676 
677 	/* Obtain the object pointer. */
678 	HANDLE2OBJECT(hObject, object_p, rv);
679 	if (rv != CKR_OK) {
680 		/*
681 		 * Decrement the session reference count.
682 		 * We do not hold the session lock.
683 		 */
684 		REFRELE(session_p, ses_lock_held);
685 		return (rv);
686 	}
687 
688 	/* Acquire the lock on the object. */
689 	(void) pthread_mutex_lock(&object_p->object_mutex);
690 
691 	if (!object_p->is_lib_obj) {
692 		/*
693 		 * The object was created in HW provider, call the
694 		 * CRYPTO_OBJECT_GET_SIZE ioctl.
695 		 */
696 		obj_gs.gs_session = session_p->k_session;
697 		obj_gs.gs_handle = object_p->k_handle;
698 		(void) pthread_mutex_unlock(&object_p->object_mutex);
699 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_SIZE,
700 		    &obj_gs)) < 0) {
701 			if (errno != EINTR)
702 				break;
703 		}
704 		if (r < 0) {
705 			rv = CKR_FUNCTION_FAILED;
706 		} else {
707 			rv = crypto2pkcs11_error_number(
708 			    obj_gs.gs_return_value);
709 		}
710 
711 		if (rv == CKR_OK) {
712 			*pulSize = obj_gs.gs_size;
713 		}
714 
715 	} else {
716 		rv = kernel_get_object_size(object_p, pulSize);
717 		(void) pthread_mutex_unlock(&object_p->object_mutex);
718 	}
719 
720 	/*
721 	 * Decrement the session reference count.
722 	 * We do not hold the session lock.
723 	 */
724 	OBJ_REFRELE(object_p);
725 	REFRELE(session_p, ses_lock_held);
726 	return (rv);
727 }
728 
729 
730 CK_RV
C_FindObjectsInit(CK_SESSION_HANDLE sh,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)731 C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate,
732     CK_ULONG ulCount)
733 {
734 	CK_RV		rv;
735 	kernel_session_t	*session_p;
736 	boolean_t ses_lock_held = B_FALSE;
737 	kernel_slot_t *pslot;
738 	crypto_object_find_init_t obj_fi;
739 	int r;
740 
741 	if (!kernel_initialized)
742 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
743 
744 	/* Check the arguments */
745 	if ((ulCount > 0) && (pTemplate == NULL)) {
746 		return (CKR_ARGUMENTS_BAD);
747 	}
748 
749 	/*
750 	 * Obtain the session pointer. Also, increment the session
751 	 * reference count.
752 	 */
753 	rv = handle2session(sh, &session_p);
754 	if (rv != CKR_OK)
755 		return (rv);
756 
757 	/* Acquire the session lock */
758 	(void) pthread_mutex_lock(&session_p->session_mutex);
759 	ses_lock_held = B_TRUE;
760 
761 	/* Check to see if find operation is already active */
762 	if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) {
763 		/* decrement the session count, and unlock the mutex */
764 		REFRELE(session_p, ses_lock_held);
765 		return (CKR_OPERATION_ACTIVE);
766 	} else {
767 		/*
768 		 * This active flag will remain ON until application calls
769 		 * C_FindObjectsFinal.
770 		 */
771 		session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE;
772 	}
773 
774 
775 	/*
776 	 * If the HW provider supports object creation, we call the
777 	 * CRYPTO_OBJECT_FIND_INIT ioctl to initialize object finding.
778 	 * Otherwise, all the objects are created in the library and we
779 	 * do the find objects solely in the library.
780 	 */
781 	pslot = slot_table[session_p->ses_slotid];
782 	if (pslot->sl_func_list.fl_object_create) {
783 		obj_fi.fi_session = session_p->k_session;
784 		(void) pthread_mutex_unlock(&session_p->session_mutex);
785 		ses_lock_held = B_FALSE;
786 		obj_fi.fi_count = ulCount;
787 		rv = process_object_attributes(pTemplate, ulCount,
788 		    &obj_fi.fi_attributes, NULL);
789 		if (rv == CKR_OK) {
790 			while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_INIT,
791 			    &obj_fi)) < 0) {
792 				if (errno != EINTR)
793 					break;
794 			}
795 			if (r < 0) {
796 				rv = CKR_FUNCTION_FAILED;
797 			} else {
798 				rv = crypto2pkcs11_error_number(
799 				    obj_fi.fi_return_value);
800 			}
801 		}
802 
803 		/* Free the attributes' space allocated for the ioctl call. */
804 		free_object_attributes(obj_fi.fi_attributes, ulCount);
805 
806 	} else {
807 		(void) pthread_mutex_unlock(&session_p->session_mutex);
808 		ses_lock_held = B_FALSE;
809 		rv = kernel_find_objects_init(session_p,  pTemplate, ulCount);
810 	}
811 
812 	if (rv != CKR_OK) {
813 		(void) pthread_mutex_lock(&session_p->session_mutex);
814 		session_p->find_objects.flags = 0;
815 		(void) pthread_mutex_unlock(&session_p->session_mutex);
816 	}
817 
818 	/* decrement the session count, and unlock the mutex */
819 	REFRELE(session_p, ses_lock_held);
820 	return (rv);
821 
822 }
823 
824 CK_RV
C_FindObjects(CK_SESSION_HANDLE sh,CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount)825 C_FindObjects(CK_SESSION_HANDLE sh, CK_OBJECT_HANDLE_PTR phObject,
826     CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
827 {
828 	CK_RV rv = CKR_OK;
829 	kernel_slot_t		*pslot;
830 	kernel_session_t	*session_p;
831 	boolean_t ses_lock_held = B_FALSE;
832 	crypto_object_find_update_t obj_fu;
833 	int r;
834 
835 	if (!kernel_initialized)
836 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
837 
838 	/* check for invalid arguments */
839 	if (((phObject == NULL) && (ulMaxObjectCount != 0)) ||
840 	    (pulObjectCount == NULL)) {
841 		return (CKR_ARGUMENTS_BAD);
842 	}
843 
844 	if (ulMaxObjectCount == 0) {
845 		/* don't need to do anything, just return */
846 		*pulObjectCount = 0;
847 		return (CKR_OK);
848 	}
849 
850 	/*
851 	 * Obtain the session pointer. Also, increment the session
852 	 * reference count.
853 	 */
854 	rv = handle2session(sh, &session_p);
855 	if (rv != CKR_OK)
856 		return (rv);
857 
858 	/* Acquire the slot lock */
859 	pslot = slot_table[session_p->ses_slotid];
860 	(void) pthread_mutex_lock(&pslot->sl_mutex);
861 
862 	/* Acquire the session lock */
863 	(void) pthread_mutex_lock(&session_p->session_mutex);
864 	ses_lock_held = B_TRUE;
865 
866 	/* Check to see if find operation is active */
867 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
868 		rv = CKR_OPERATION_NOT_INITIALIZED;
869 		goto clean_exit;
870 	}
871 
872 	/*
873 	 * Similar to C_FindObjectInit(), if the HW provider supports object
874 	 * creation, we call the respective ioctl to find objects.
875 	 * Otherwise, all the objects are created in the library and we do
876 	 * the find objects solely in the library.
877 	 */
878 	if (pslot->sl_func_list.fl_object_create) {
879 		obj_fu.fu_session = session_p->k_session;
880 		obj_fu.fu_max_count = ulMaxObjectCount;
881 		obj_fu.fu_handles = (char *)calloc(1,
882 		    ulMaxObjectCount * sizeof (crypto_object_id_t));
883 		if (obj_fu.fu_handles == NULL) {
884 			rv = CKR_HOST_MEMORY;
885 			goto clean_exit;
886 		}
887 
888 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_UPDATE,
889 		    &obj_fu)) < 0) {
890 			if (errno != EINTR)
891 				break;
892 		}
893 		if (r < 0) {
894 			rv = CKR_FUNCTION_FAILED;
895 		} else {
896 			rv = crypto2pkcs11_error_number(
897 			    obj_fu.fu_return_value);
898 		}
899 
900 		if (rv == CKR_OK) {
901 			rv = process_found_objects(session_p, phObject,
902 			    pulObjectCount, obj_fu);
903 		}
904 		free(obj_fu.fu_handles);
905 
906 	} else {
907 
908 		kernel_find_objects(session_p, phObject, ulMaxObjectCount,
909 		    pulObjectCount);
910 		rv = CKR_OK;
911 	}
912 
913 clean_exit:
914 	/* decrement the session count, and release the session lock */
915 	REFRELE(session_p, ses_lock_held);
916 
917 	/* release the slot lock */
918 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
919 
920 	return (rv);
921 }
922 
923 
924 CK_RV
C_FindObjectsFinal(CK_SESSION_HANDLE sh)925 C_FindObjectsFinal(CK_SESSION_HANDLE sh)
926 {
927 
928 	kernel_session_t	*session_p;
929 	CK_RV rv;
930 	boolean_t ses_lock_held = B_FALSE;
931 	kernel_slot_t *pslot;
932 	crypto_object_find_final_t obj_ff;
933 	int r;
934 
935 	if (!kernel_initialized)
936 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
937 
938 	/*
939 	 * Obtain the session pointer. Also, increment the session
940 	 * reference count.
941 	 */
942 	rv = handle2session(sh, &session_p);
943 	if (rv != CKR_OK)
944 		return (rv);
945 
946 	/* Acquire the session lock */
947 	(void) pthread_mutex_lock(&session_p->session_mutex);
948 	ses_lock_held = B_TRUE;
949 
950 	/* Check to see if find operation is active */
951 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
952 		REFRELE(session_p, ses_lock_held);
953 		return (CKR_OPERATION_NOT_INITIALIZED);
954 	}
955 
956 	/*
957 	 * Similar to C_FindObjectInit(), if the HW provider supports object
958 	 * creation, we need to call the CRYPTO_OBJECT_FIND_FINAL ioctl.
959 	 */
960 	pslot = slot_table[session_p->ses_slotid];
961 	if (pslot->sl_func_list.fl_object_create) {
962 		obj_ff.ff_session = session_p->k_session;
963 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_FINAL,
964 		    &obj_ff)) < 0) {
965 			if (errno != EINTR)
966 				break;
967 		}
968 		if (r < 0) {
969 			rv = CKR_FUNCTION_FAILED;
970 		} else {
971 			rv = crypto2pkcs11_error_number(
972 			    obj_ff.ff_return_value);
973 		}
974 
975 		/* only need to reset find_objects.flags */
976 		if (rv == CKR_OK) {
977 			session_p->find_objects.flags = 0;
978 		}
979 
980 	} else {
981 		/*
982 		 * The find object operations were done in the library, we
983 		 * need to cleanup find_objects context.
984 		 */
985 		kernel_find_objects_final(session_p);
986 		rv = CKR_OK;
987 	}
988 
989 	/* decrement the session count, and release the lock */
990 	REFRELE(session_p, ses_lock_held);
991 	return (rv);
992 }
993