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