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