Print this page
9642 PKCS#11 softtoken should use explicit_bzero
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Alex Wilson <alex.wilson@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelObjectUtil.c
+++ new/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelObjectUtil.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + * Copyright (c) 2018, Joyent, Inc.
24 25 */
25 26
26 27 #include <stdio.h>
27 28 #include <stdlib.h>
28 29 #include <strings.h>
29 30 #include <errno.h>
30 31 #include <security/cryptoki.h>
31 32 #include <cryptoutil.h>
32 33 #include "kernelGlobal.h"
33 34 #include "kernelObject.h"
34 35 #include "kernelSession.h"
35 36 #include "kernelSlot.h"
36 37
37 38 /*
38 39 * Add an object to the session's object list.
39 40 *
40 41 * This function will acquire the lock on the session, and release
41 42 * that lock after adding the object to the session's object list.
42 43 */
43 44 void
44 45 kernel_add_object_to_session(kernel_object_t *objp, kernel_session_t *sp)
45 46 {
46 47 /* Acquire the session lock. */
47 48 (void) pthread_mutex_lock(&sp->session_mutex);
48 49
49 50 /* Insert the new object in front of session's object list. */
50 51 if (sp->object_list == NULL) {
51 52 sp->object_list = objp;
52 53 objp->next = NULL;
53 54 objp->prev = NULL;
54 55 } else {
55 56 sp->object_list->prev = objp;
56 57 objp->next = sp->object_list;
57 58 objp->prev = NULL;
58 59 sp->object_list = objp;
59 60 }
60 61
61 62 /* Release the session lock. */
62 63 (void) pthread_mutex_unlock(&sp->session_mutex);
63 64 }
64 65
65 66 /*
66 67 * Clean up and release the storage allocated to the object.
67 68 *
68 69 * The function is called either with the object lock being held
69 70 * (by caller kernel_delete_object()), or there is no object lock
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
70 71 * yet (by kernel_build_XXX_object() during creating an object).
71 72 */
72 73 void
73 74 kernel_cleanup_object(kernel_object_t *objp)
74 75 {
75 76 /*
76 77 * Free the storage allocated to a secret key object.
77 78 */
78 79 if (objp->class == CKO_SECRET_KEY) {
79 80 if (OBJ_SEC(objp) != NULL && OBJ_SEC_VALUE(objp) != NULL) {
80 - bzero(OBJ_SEC_VALUE(objp), OBJ_SEC_VALUE_LEN(objp));
81 - free(OBJ_SEC_VALUE(objp));
81 + freezero(OBJ_SEC_VALUE(objp), OBJ_SEC_VALUE_LEN(objp));
82 82 OBJ_SEC_VALUE(objp) = NULL;
83 83 OBJ_SEC_VALUE_LEN(objp) = 0;
84 84 }
85 85 free(OBJ_SEC(objp));
86 86 OBJ_SEC(objp) = NULL;
87 87 } else {
88 88 kernel_cleanup_object_bigint_attrs(objp);
89 89 }
90 90
91 91 /*
92 92 * Free the storage allocated to the extra attribute list.
93 93 */
94 94 kernel_cleanup_extra_attr(objp);
95 95 }
96 96
97 97 /*
98 98 * Create a new object. Copy the attributes that can be modified
99 99 * (in the boolean attribute mask field and extra attribute list)
100 100 * from the old object to the new object.
101 101 *
102 102 * The caller of this function holds the lock on the old object.
103 103 */
104 104 CK_RV
105 105 kernel_copy_object(kernel_object_t *old_object, kernel_object_t **new_object,
106 106 boolean_t copy_everything, kernel_session_t *sp)
107 107 {
108 108 CK_RV rv = CKR_OK;
109 109 kernel_object_t *new_objp = NULL;
110 110 CK_ATTRIBUTE_INFO_PTR attrp;
111 111
112 112 /* Allocate new object. */
113 113 new_objp = calloc(1, sizeof (kernel_object_t));
114 114 if (new_objp == NULL)
115 115 return (CKR_HOST_MEMORY);
116 116
117 117 new_objp->class = old_object->class;
118 118 new_objp->bool_attr_mask = old_object->bool_attr_mask;
119 119
120 120 attrp = old_object->extra_attrlistp;
121 121 while (attrp) {
122 122 /*
123 123 * Copy the attribute_info struct from the old
124 124 * object to a new attribute_info struct, and add
125 125 * that new struct to the extra attribute list
126 126 * of the new object.
127 127 */
128 128 rv = kernel_copy_extra_attr(attrp, new_objp);
129 129 if (rv != CKR_OK) {
130 130 kernel_cleanup_extra_attr(new_objp);
131 131 free(new_objp);
132 132 return (rv);
133 133 }
134 134 attrp = attrp->next;
135 135 }
136 136
137 137 *new_object = new_objp;
138 138
139 139 if (!copy_everything) {
140 140 /* done with copying all information that can be modified */
141 141 return (CKR_OK);
142 142 }
143 143
144 144 /*
145 145 * Copy the rest of the object.
146 146 * Certain fields that are not appropriate for coping will be
147 147 * initialized.
148 148 */
149 149 new_objp->key_type = old_object->key_type;
150 150 new_objp->magic_marker = old_object->magic_marker;
151 151 new_objp->mechanism = old_object->mechanism;
152 152 new_objp->session_handle = (CK_SESSION_HANDLE)sp;
153 153 (void) pthread_mutex_init(&(new_objp->object_mutex), NULL);
154 154 /* copy key related information */
155 155 switch (new_objp->class) {
156 156 case CKO_PUBLIC_KEY:
157 157 rv = kernel_copy_public_key_attr(OBJ_PUB(old_object),
158 158 &(OBJ_PUB(new_objp)), new_objp->key_type);
159 159 break;
160 160 case CKO_PRIVATE_KEY:
161 161 rv = kernel_copy_private_key_attr(OBJ_PRI(old_object),
162 162 &(OBJ_PRI(new_objp)), new_objp->key_type);
163 163 break;
164 164 case CKO_SECRET_KEY:
165 165 rv = kernel_copy_secret_key_attr(OBJ_SEC(old_object),
166 166 &(OBJ_SEC(new_objp)));
167 167 break;
168 168 default:
169 169 /* should never be this case */
170 170 break;
171 171 }
172 172 if (rv != CKR_OK) {
173 173 /*
174 174 * don't need to cleanup the memory from failure of copying
175 175 * any key related stuff. Each individual function for
176 176 * copying key attr will free the memory if it fails
177 177 */
178 178 kernel_cleanup_extra_attr(new_objp);
179 179 free(new_objp);
180 180 }
181 181 return (rv);
182 182 }
183 183
184 184 /*
185 185 * Copy the attributes (in the boolean attribute mask field and
186 186 * extra attribute list) from the new object back to the original
187 187 * object. Also, clean up and release all the storage in the extra
188 188 * attribute list of the original object.
189 189 *
190 190 * The caller of this function holds the lock on the old object.
191 191 */
192 192 void
193 193 kernel_merge_object(kernel_object_t *old_object, kernel_object_t *new_object)
194 194 {
195 195
196 196 old_object->bool_attr_mask = new_object->bool_attr_mask;
197 197 kernel_cleanup_extra_attr(old_object);
198 198 old_object->extra_attrlistp = new_object->extra_attrlistp;
199 199
200 200 }
201 201
202 202 /*
203 203 * Create a new object struct. If it is a session object, add the object to
204 204 * the session's object list. If it is a token object, add it to the slot's
205 205 * token object list. The caller does not hold the slot lock.
206 206 */
207 207 CK_RV
208 208 kernel_add_object(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
209 209 CK_ULONG *objecthandle_p, kernel_session_t *sp)
210 210 {
211 211 CK_RV rv = CKR_OK;
212 212 kernel_object_t *new_objp = NULL;
213 213 kernel_slot_t *pslot;
214 214 crypto_object_create_t objc;
215 215 CK_BBOOL is_pri_obj;
216 216 CK_BBOOL is_token_obj = B_FALSE;
217 217 int r;
218 218
219 219 new_objp = calloc(1, sizeof (kernel_object_t));
220 220 if (new_objp == NULL) {
221 221 rv = CKR_HOST_MEMORY;
222 222 goto fail_cleanup;
223 223 }
224 224
225 225 new_objp->extra_attrlistp = NULL;
226 226 new_objp->is_lib_obj = B_TRUE;
227 227
228 228 /*
229 229 * If the HW provider supports object creation, create the object
230 230 * in the HW provider by calling the CRYPTO_OBJECT_CREATE ioctl.
231 231 * Otherwise, create the object in the library.
232 232 */
233 233 pslot = slot_table[sp->ses_slotid];
234 234 if (pslot->sl_func_list.fl_object_create) {
235 235 new_objp->is_lib_obj = B_FALSE;
236 236 objc.oc_session = sp->k_session;
237 237 objc.oc_count = ulCount;
238 238 rv = process_object_attributes(pTemplate, ulCount,
239 239 &objc.oc_attributes, &is_token_obj);
240 240 if (rv != CKR_OK) {
241 241 goto fail_cleanup;
242 242 }
243 243
244 244 /* Cannot create a token object with a READ-ONLY session */
245 245 if (is_token_obj && sp->ses_RO) {
246 246 free_object_attributes(objc.oc_attributes, ulCount);
247 247 rv = CKR_SESSION_READ_ONLY;
248 248 goto fail_cleanup;
249 249 }
250 250
251 251 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_CREATE,
252 252 &objc)) < 0) {
253 253 if (errno != EINTR)
254 254 break;
255 255 }
256 256 if (r < 0) {
257 257 rv = CKR_FUNCTION_FAILED;
258 258 } else {
259 259 rv = crypto2pkcs11_error_number(objc.oc_return_value);
260 260 }
261 261
262 262 free_object_attributes(objc.oc_attributes, ulCount);
263 263
264 264 if (rv != CKR_OK) {
265 265 goto fail_cleanup;
266 266 }
267 267
268 268 /* Get the CKA_PRIVATE value of this object. */
269 269 new_objp->k_handle = objc.oc_handle;
270 270 rv = get_cka_private_value(sp, new_objp->k_handle,
271 271 &is_pri_obj);
272 272 if (rv != CKR_OK) {
273 273 goto fail_cleanup;
274 274 }
275 275
276 276 /* Set the PRIVATE_BOOL_ON and TOKEN_BOOL_ON attributes */
277 277 if (is_pri_obj)
278 278 new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
279 279 else
280 280 new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
281 281
282 282 if (is_token_obj)
283 283 new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
284 284 else
285 285 new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
286 286
287 287 } else {
288 288 /*
289 289 * Create the object in the library.
290 290 * Validate attribute template and fill in the attributes
291 291 * in the kernel_object_t.
292 292 */
293 293 rv = kernel_build_object(pTemplate, ulCount, new_objp, sp,
294 294 KERNEL_CREATE_OBJ);
295 295 if (rv != CKR_OK) {
296 296 goto fail_cleanup;
297 297 }
298 298 }
299 299
300 300 /* Initialize the rest of stuffs in kernel_object_t. */
301 301 (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
302 302 new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
303 303 new_objp->session_handle = (CK_SESSION_HANDLE)sp;
304 304
305 305 if (is_token_obj) {
306 306 /* Add the new object to the slot's token object list. */
307 307 pslot = slot_table[sp->ses_slotid];
308 308 kernel_add_token_object_to_slot(new_objp, pslot);
309 309 } else {
310 310 /* Add the new object to the session's object list. */
311 311 kernel_add_object_to_session(new_objp, sp);
312 312 }
313 313
314 314 /* Type casting the address of an object struct to an object handle. */
315 315 *objecthandle_p = (CK_ULONG)new_objp;
316 316
317 317 return (CKR_OK);
318 318
319 319 fail_cleanup:
320 320 if (new_objp) {
321 321 /*
322 322 * If the object is created in the HW provider, the storage
323 323 * allocated for the ioctl call is always cleaned up after
324 324 * the call. If the object is created in the library,
325 325 * the storage allocated inside of this object should
326 326 * have been cleaned up in the kernel_build_object()
327 327 * after an error occurred. Therefore, we can safely
328 328 * free the object.
329 329 */
330 330 free(new_objp);
331 331 }
332 332
333 333 return (rv);
334 334 }
335 335
336 336 /*
337 337 * Remove an object from the session's object list.
338 338 *
339 339 * The caller of this function holds the session lock.
340 340 */
341 341 CK_RV
342 342 kernel_remove_object_from_session(kernel_object_t *objp, kernel_session_t *sp)
343 343 {
344 344 kernel_object_t *tmp_objp;
345 345 boolean_t found = B_FALSE;
346 346
347 347 /*
348 348 * Remove the object from the session's object list.
349 349 */
350 350 if ((sp == NULL) ||
351 351 (sp->magic_marker != KERNELTOKEN_SESSION_MAGIC)) {
352 352 return (CKR_SESSION_HANDLE_INVALID);
353 353 }
354 354
355 355 if ((sp->object_list == NULL) || (objp == NULL) ||
356 356 (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC)) {
357 357 return (CKR_OBJECT_HANDLE_INVALID);
358 358 }
359 359
360 360 tmp_objp = sp->object_list;
361 361 while (tmp_objp) {
362 362 if (tmp_objp == objp) {
363 363 found = B_TRUE;
364 364 break;
365 365 }
366 366 tmp_objp = tmp_objp->next;
367 367 }
368 368 if (!found)
369 369 return (CKR_OBJECT_HANDLE_INVALID);
370 370
371 371 if (sp->object_list == objp) {
372 372 /* Object is the first one in the list. */
373 373 if (objp->next) {
374 374 sp->object_list = objp->next;
375 375 objp->next->prev = NULL;
376 376 } else {
377 377 /* Object is the only one in the list. */
378 378 sp->object_list = NULL;
379 379 }
380 380 } else {
381 381 /* Object is not the first one in the list. */
382 382 if (objp->next) {
383 383 /* Object is in the middle of the list. */
384 384 objp->prev->next = objp->next;
385 385 objp->next->prev = objp->prev;
386 386 } else {
387 387 /* Object is the last one in the list. */
388 388 objp->prev->next = NULL;
389 389 }
390 390 }
391 391 return (CKR_OK);
392 392 }
393 393
394 394 static void
395 395 kernel_delete_object_cleanup(kernel_object_t *objp, boolean_t wrapper_only)
396 396 {
397 397 /* Acquire the lock on the object. */
398 398 (void) pthread_mutex_lock(&objp->object_mutex);
399 399
400 400 /*
401 401 * Make sure another thread hasn't freed the object.
402 402 */
403 403 if (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC) {
404 404 (void) pthread_mutex_unlock(&objp->object_mutex);
405 405 return;
406 406 }
407 407
408 408 /*
409 409 * The deletion of an object must be blocked when the object
410 410 * reference count is not zero. This means if any object related
411 411 * operation starts prior to the delete object operation gets in,
412 412 * the object deleting thread must wait for the non-deleting
413 413 * operation to be completed before it can proceed the delete
414 414 * operation.
415 415 *
416 416 * Unless we are being forced to shut everything down, this only
417 417 * happens if the library's _fini() is running not if someone
418 418 * explicitly called C_Finalize().
419 419 */
420 420 if (wrapper_only) {
421 421 objp->obj_refcnt = 0;
422 422 }
423 423
424 424 while (objp->obj_refcnt != 0) {
425 425 /*
426 426 * We set the OBJECT_REFCNT_WAITING flag before we put
427 427 * this deleting thread in a wait state, so other non-deleting
428 428 * operation thread will signal to wake it up only when
429 429 * the object reference count becomes zero and this flag
430 430 * is set.
431 431 */
432 432 objp->obj_delete_sync |= OBJECT_REFCNT_WAITING;
433 433 (void) pthread_cond_wait(&objp->obj_free_cond,
434 434 &objp->object_mutex);
435 435 }
436 436
437 437 objp->obj_delete_sync &= ~OBJECT_REFCNT_WAITING;
438 438
439 439 /* Mark object as no longer valid. */
440 440 objp->magic_marker = 0;
441 441
442 442 (void) pthread_cond_destroy(&objp->obj_free_cond);
443 443 }
444 444
445 445 /*
446 446 * Delete a session object:
447 447 * - Remove the object from the session's object list.
448 448 * - Release the storage allocated to the object.
449 449 *
450 450 * The boolean argument ses_lock_held is used to indicate that whether
451 451 * the caller holds the session lock or not.
452 452 * - When called by kernel_delete_all_objects_in_session() or
453 453 * kernel_delete_pri_objects_in_slot() -- ses_lock_held = TRUE.
454 454 *
455 455 * The boolean argument wrapper_only is used to indicate that whether
456 456 * the caller only wants to clean up the object wrapper from the library and
457 457 * needs not to make an ioctl call.
458 458 * - This argument only applies to the object created in the provider level.
459 459 * - When called by kernel_cleanup_pri_objects_in_slot(), wrapper_only is TRUE.
460 460 * - When called by C_DestroyObject(), wrapper_only is FALSE.
461 461 * - When called by kernel_delete_all_objects_in_session(), the value of
462 462 * wrapper_only depends on its caller.
463 463 */
464 464 CK_RV
465 465 kernel_delete_session_object(kernel_session_t *sp, kernel_object_t *objp,
466 466 boolean_t ses_lock_held, boolean_t wrapper_only)
467 467 {
468 468 CK_RV rv = CKR_OK;
469 469 crypto_object_destroy_t obj_destroy;
470 470
471 471 /*
472 472 * Check to see if the caller holds the lock on the session.
473 473 * If not, we need to acquire that lock in order to proceed.
474 474 */
475 475 if (!ses_lock_held) {
476 476 /* Acquire the session lock. */
477 477 (void) pthread_mutex_lock(&sp->session_mutex);
478 478 }
479 479
480 480 /* Remove the object from the session's object list first. */
481 481 rv = kernel_remove_object_from_session(objp, sp);
482 482 if (!ses_lock_held) {
483 483 /*
484 484 * If the session lock is obtained by this function,
485 485 * then release that lock after removing the object
486 486 * from session's object list.
487 487 * We want the releasing of the object storage to
488 488 * be done without holding the session lock.
489 489 */
490 490 (void) pthread_mutex_unlock(&sp->session_mutex);
491 491 }
492 492
493 493 if (rv != CKR_OK)
494 494 return (rv);
495 495
496 496 kernel_delete_object_cleanup(objp, wrapper_only);
497 497
498 498 /* Destroy the object. */
499 499 if (objp->is_lib_obj) {
500 500 /*
501 501 * If this object is created in the library, cleanup the
502 502 * contents of this object such as free all the storage
503 503 * allocated for this object.
504 504 */
505 505 kernel_cleanup_object(objp);
506 506 } else {
507 507 /*
508 508 * This object is created in the HW provider. If wrapper_only
509 509 * is FALSE, make an ioctl call to destroy it in kernel.
510 510 */
511 511 if (!wrapper_only) {
512 512 obj_destroy.od_session = sp->k_session;
513 513 obj_destroy.od_handle = objp->k_handle;
514 514
515 515 while (ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY,
516 516 &obj_destroy) < 0) {
517 517 if (errno != EINTR)
518 518 break;
519 519 }
520 520
521 521 /*
522 522 * Ignore ioctl return codes for a session object.
523 523 * If the kernel can not delete a session object, it
524 524 * is likely caused by the HW provider. There's not
525 525 * much that can be done. The library will still
526 526 * cleanup the object wrapper in the library. The HW
527 527 * provider will destroy all session objects when
528 528 * the application exits.
529 529 */
530 530 }
531 531 }
532 532
533 533 /* Reset OBJECT_IS_DELETING flag. */
534 534 objp->obj_delete_sync &= ~OBJECT_IS_DELETING;
535 535
536 536 (void) pthread_mutex_unlock(&objp->object_mutex);
537 537 /* Destroy the object lock */
538 538 (void) pthread_mutex_destroy(&objp->object_mutex);
539 539 /* Free the object itself */
540 540 kernel_object_delay_free(objp);
541 541
542 542 return (CKR_OK);
543 543 }
544 544
545 545 /*
546 546 * Delete all the objects in a session. The caller holds the lock
547 547 * on the session. If the wrapper_only argument is TRUE, the caller only
548 548 * want to clean up object wrappers in the library.
549 549 */
550 550 void
551 551 kernel_delete_all_objects_in_session(kernel_session_t *sp,
552 552 boolean_t wrapper_only)
553 553 {
554 554 kernel_object_t *objp = sp->object_list;
555 555 kernel_object_t *objp1;
556 556
557 557 /* Delete all the objects in the session. */
558 558 while (objp) {
559 559 objp1 = objp->next;
560 560
561 561 /*
562 562 * Delete an session object by calling
563 563 * kernel_delete_session_object():
564 564 * - The 3rd TRUE boolean argument indicates that the caller
565 565 * holds the session lock.
566 566 * - The 4th boolean argument indicates whether we only want
567 567 * clean up object wrappers in the library.
568 568 */
569 569 (void) kernel_delete_session_object(sp, objp, B_TRUE,
570 570 wrapper_only);
571 571
572 572 objp = objp1;
573 573 }
574 574 }
575 575
576 576 static CK_RV
577 577 add_to_search_result(kernel_object_t *obj, find_context_t *fcontext,
578 578 CK_ULONG *num_result_alloc)
579 579 {
580 580 /*
581 581 * allocate space for storing results if the currently
582 582 * allocated space is not enough
583 583 */
584 584 if (*num_result_alloc <= fcontext->num_results) {
585 585 fcontext->objs_found = realloc(fcontext->objs_found,
586 586 sizeof (kernel_object_t *) * (*num_result_alloc + BUFSIZ));
587 587 if (fcontext->objs_found == NULL) {
588 588 return (CKR_HOST_MEMORY);
589 589 }
590 590 *num_result_alloc += BUFSIZ;
591 591 }
592 592
593 593 (fcontext->objs_found)[(fcontext->num_results)++] = obj;
594 594 return (CKR_OK);
595 595 }
596 596
597 597 static CK_RV
598 598 search_for_objects(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
599 599 CK_ULONG ulCount, find_context_t *fcontext)
600 600 {
601 601 kernel_session_t *session_p;
602 602 kernel_object_t *obj;
603 603 CK_OBJECT_CLASS pclasses[6]; /* classes attrs possibly exist */
604 604 CK_ULONG num_pclasses; /* number of possible classes */
605 605 CK_ULONG num_result_alloc = 0; /* spaces allocated for results */
606 606 CK_RV rv = CKR_OK;
607 607 kernel_slot_t *pslot;
608 608
609 609 if (ulCount > 0) {
610 610 /* there are some search requirement */
611 611 kernel_process_find_attr(pclasses, &num_pclasses,
612 612 pTemplate, ulCount);
613 613 }
614 614
615 615 /* Acquire the slot lock */
616 616 pslot = slot_table[sp->ses_slotid];
617 617 (void) pthread_mutex_lock(&pslot->sl_mutex);
618 618
619 619 /*
620 620 * Go through all objects in each session.
621 621 * Acquire individual session lock for the session
622 622 * we are searching.
623 623 */
624 624 session_p = pslot->sl_sess_list;
625 625 while (session_p) {
626 626 (void) pthread_mutex_lock(&session_p->session_mutex);
627 627 obj = session_p->object_list;
628 628 while (obj) {
629 629 (void) pthread_mutex_lock(&obj->object_mutex);
630 630 if (ulCount > 0) {
631 631 if (kernel_find_match_attrs(obj, pclasses,
632 632 num_pclasses, pTemplate, ulCount)) {
633 633 rv = add_to_search_result(
634 634 obj, fcontext, &num_result_alloc);
635 635 }
636 636 } else {
637 637 /* no search criteria, just record the object */
638 638 rv = add_to_search_result(obj, fcontext,
639 639 &num_result_alloc);
640 640 }
641 641 (void) pthread_mutex_unlock(&obj->object_mutex);
642 642 if (rv != CKR_OK) {
643 643 (void) pthread_mutex_unlock(
644 644 &session_p->session_mutex);
645 645 goto cleanup;
646 646 }
647 647 obj = obj->next;
648 648 }
649 649 (void) pthread_mutex_unlock(&session_p->session_mutex);
650 650 session_p = session_p->next;
651 651 }
652 652
653 653 cleanup:
654 654 /* Release the slot lock */
655 655 (void) pthread_mutex_unlock(&pslot->sl_mutex);
656 656 return (rv);
657 657 }
658 658
659 659 /*
660 660 * Initialize the context for C_FindObjects() calls
661 661 */
662 662 CK_RV
663 663 kernel_find_objects_init(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
664 664 CK_ULONG ulCount)
665 665 {
666 666 CK_RV rv = CKR_OK;
667 667 CK_OBJECT_CLASS class; /* for kernel_validate_attr(). Value unused */
668 668 find_context_t *fcontext;
669 669
670 670 if (ulCount) {
671 671 rv = kernel_validate_attr(pTemplate, ulCount, &class);
672 672 /* Make sure all attributes in template are valid */
673 673 if (rv != CKR_OK) {
674 674 return (rv);
675 675 }
676 676 }
677 677
678 678 /* prepare the find context */
679 679 fcontext = calloc(1, sizeof (find_context_t));
680 680 if (fcontext == NULL) {
681 681 return (CKR_HOST_MEMORY);
682 682 }
683 683
684 684 rv = search_for_objects(sp, pTemplate, ulCount, fcontext);
685 685 if (rv != CKR_OK) {
686 686 free(fcontext);
687 687 return (rv);
688 688 }
689 689
690 690 /* store the find_context in the session */
691 691 sp->find_objects.context = (CK_VOID_PTR)fcontext;
692 692
693 693 return (rv);
694 694 }
695 695
696 696 void
697 697 kernel_find_objects_final(kernel_session_t *sp)
698 698 {
699 699 find_context_t *fcontext;
700 700
701 701 fcontext = sp->find_objects.context;
702 702 sp->find_objects.context = NULL;
703 703 sp->find_objects.flags = 0;
704 704 if (fcontext->objs_found != NULL) {
705 705 free(fcontext->objs_found);
706 706 }
707 707
708 708 free(fcontext);
709 709 }
710 710
711 711 void
712 712 kernel_find_objects(kernel_session_t *sp, CK_OBJECT_HANDLE *obj_found,
713 713 CK_ULONG max_obj_requested, CK_ULONG *found_obj_count)
714 714 {
715 715 find_context_t *fcontext;
716 716 CK_ULONG num_obj_found = 0;
717 717 CK_ULONG i;
718 718 kernel_object_t *obj;
719 719
720 720 fcontext = sp->find_objects.context;
721 721
722 722 for (i = fcontext->next_result_index;
723 723 ((num_obj_found < max_obj_requested) &&
724 724 (i < fcontext->num_results));
725 725 i++) {
726 726 obj = fcontext->objs_found[i];
727 727 if (obj != NULL) {
728 728 (void) pthread_mutex_lock(&obj->object_mutex);
729 729 /* a sanity check to make sure the obj is still valid */
730 730 if (obj->magic_marker == KERNELTOKEN_OBJECT_MAGIC) {
731 731 obj_found[num_obj_found] =
732 732 (CK_OBJECT_HANDLE)obj;
733 733 num_obj_found++;
734 734 }
735 735 (void) pthread_mutex_unlock(&obj->object_mutex);
736 736 }
737 737 }
738 738 fcontext->next_result_index = i;
739 739 *found_obj_count = num_obj_found;
740 740 }
741 741
742 742 /*
743 743 * Add an token object to the token object list in slot.
744 744 *
745 745 * This function will acquire the lock on the slot, and release
746 746 * that lock after adding the object to the slot's token object list.
747 747 */
748 748 void
749 749 kernel_add_token_object_to_slot(kernel_object_t *objp, kernel_slot_t *pslot)
750 750 {
751 751 /* Acquire the slot lock. */
752 752 (void) pthread_mutex_lock(&pslot->sl_mutex);
753 753
754 754 /* Insert the new object in front of slot's token object list. */
755 755 if (pslot->sl_tobj_list == NULL) {
756 756 pslot->sl_tobj_list = objp;
757 757 objp->next = NULL;
758 758 objp->prev = NULL;
759 759 } else {
760 760 pslot->sl_tobj_list->prev = objp;
761 761 objp->next = pslot->sl_tobj_list;
762 762 objp->prev = NULL;
763 763 pslot->sl_tobj_list = objp;
764 764 }
765 765
766 766 /* Release the slot lock. */
767 767 (void) pthread_mutex_unlock(&pslot->sl_mutex);
768 768 }
769 769
770 770 /*
771 771 * Remove an token object from the slot's token object list.
772 772 * This routine is called by kernel_delete_token_object().
773 773 * The caller of this function hold the slot lock.
774 774 */
775 775 void
776 776 kernel_remove_token_object_from_slot(kernel_slot_t *pslot,
777 777 kernel_object_t *objp)
778 778 {
779 779
780 780 if (pslot->sl_tobj_list == objp) {
781 781 /* Object is the first one in the list */
782 782 if (objp->next) {
783 783 pslot->sl_tobj_list = objp->next;
784 784 objp->next->prev = NULL;
785 785 } else {
786 786 /* Object is the only one in the list. */
787 787 pslot->sl_tobj_list = NULL;
788 788 }
789 789 } else {
790 790 /* Object is not the first one in the list. */
791 791 if (objp->next) {
792 792 /* Object is in the middle of the list. */
793 793 objp->prev->next = objp->next;
794 794 objp->next->prev = objp->prev;
795 795 } else {
796 796 /* Object is the last one in the list. */
797 797 objp->prev->next = NULL;
798 798 }
799 799 }
800 800 }
801 801
802 802 /*
803 803 * Delete a token object:
804 804 * - Remove the object from the slot's token object list.
805 805 * - Release the storage allocated to the object.
806 806 *
807 807 * The boolean argument slot_lock_held is used to indicate that whether
808 808 * the caller holds the slot lock or not. When the caller does not hold
809 809 * the slot lock, this function will acquire that lock in order to proceed,
810 810 * and also release that lock before returning to caller.
811 811 *
812 812 * The boolean argument wrapper_only is used to indicate that whether
813 813 * the caller only wants to the object wrapper from library.
814 814 */
815 815 CK_RV
816 816 kernel_delete_token_object(kernel_slot_t *pslot, kernel_session_t *sp,
817 817 kernel_object_t *objp, boolean_t slot_lock_held, boolean_t wrapper_only)
818 818 {
819 819 CK_RV rv;
820 820 crypto_object_destroy_t obj_destroy;
821 821 int r;
822 822
823 823 /*
824 824 * Check to see if the caller holds the lock on the slot.
825 825 * If not, we need to acquire that lock in order to proceed.
826 826 */
827 827 if (!slot_lock_held) {
828 828 (void) pthread_mutex_lock(&pslot->sl_mutex);
829 829 }
830 830
831 831 /* Remove the object from the slot's token object list first. */
832 832 kernel_remove_token_object_from_slot(pslot, objp);
833 833
834 834 /* Release the slot lock if the call doesn't hold the lock. */
835 835 if (!slot_lock_held) {
836 836 (void) pthread_mutex_unlock(&pslot->sl_mutex);
837 837 }
838 838
839 839 kernel_delete_object_cleanup(objp, wrapper_only);
840 840
841 841 if (!wrapper_only) {
842 842 obj_destroy.od_session = sp->k_session;
843 843 obj_destroy.od_handle = objp->k_handle;
844 844
845 845 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY,
846 846 &obj_destroy)) < 0) {
847 847 if (errno != EINTR)
848 848 break;
849 849 }
850 850 if (r < 0) {
851 851 rv = CKR_FUNCTION_FAILED;
852 852 } else {
853 853 rv = crypto2pkcs11_error_number(
854 854 obj_destroy.od_return_value);
855 855 }
856 856
857 857 /*
858 858 * Could not destroy an object from kernel. Write a warning
859 859 * in syslog, but we still clean up the object wrapper in
860 860 * the library.
861 861 */
862 862 if (rv != CKR_OK) {
863 863 cryptoerror(LOG_ERR, "pkcs11_kernel: Could not "
864 864 "destroy an object in kernel.");
865 865 }
866 866 }
867 867
868 868 (void) pthread_mutex_unlock(&objp->object_mutex);
869 869 /* Destroy the object lock */
870 870 (void) pthread_mutex_destroy(&objp->object_mutex);
871 871 /* Free the object itself */
872 872 kernel_object_delay_free(objp);
873 873
874 874 return (CKR_OK);
875 875 }
876 876
877 877 /*
878 878 * Clean up private object wrappers in this slot. The caller holds the slot
879 879 * lock.
880 880 */
881 881 void
882 882 kernel_cleanup_pri_objects_in_slot(kernel_slot_t *pslot,
883 883 kernel_session_t *cur_sp)
884 884 {
885 885 kernel_session_t *session_p;
886 886 kernel_object_t *objp;
887 887 kernel_object_t *objp1;
888 888
889 889 /*
890 890 * Delete every private token object from the slot' token object list
891 891 */
892 892 objp = pslot->sl_tobj_list;
893 893 while (objp) {
894 894 objp1 = objp->next;
895 895 /*
896 896 * The first TRUE boolean argument indicates that the caller
897 897 * hold the slot lock. The second TRUE boolean argument
898 898 * indicates that the caller just wants to clean up the object
899 899 * wrapper from the library only.
900 900 */
901 901 if (objp->bool_attr_mask & PRIVATE_BOOL_ON) {
902 902 (void) kernel_delete_token_object(pslot, cur_sp, objp,
903 903 B_TRUE, B_TRUE);
904 904 }
905 905 objp = objp1;
906 906 }
907 907
908 908 /*
909 909 * Walk through all the sessions in this slot and delete every
910 910 * private object.
911 911 */
912 912 session_p = pslot->sl_sess_list;
913 913 while (session_p) {
914 914
915 915 /* Delete all the objects in the session. */
916 916 objp = session_p->object_list;
917 917 while (objp) {
918 918 objp1 = objp->next;
919 919 /*
920 920 * The FALSE boolean argument indicates that the
921 921 * caller does not hold the session lock. The TRUE
922 922 * boolean argument indicates that the caller just
923 923 * want to clean upt the object wrapper from the
924 924 * library only.
925 925 */
926 926 if (objp->bool_attr_mask & PRIVATE_BOOL_ON) {
927 927 (void) kernel_delete_session_object(session_p,
928 928 objp, B_FALSE, B_TRUE);
929 929 }
930 930
931 931 objp = objp1;
932 932 }
933 933
934 934 session_p = session_p->next;
935 935 }
936 936 }
937 937
938 938 /*
939 939 * Get the object size in bytes for the objects created in the library.
940 940 */
941 941 CK_RV
942 942 kernel_get_object_size(kernel_object_t *obj, CK_ULONG_PTR pulSize)
943 943 {
944 944 CK_RV rv = CKR_OK;
945 945 CK_ULONG obj_size;
946 946 biginteger_t *big;
947 947
948 948 obj_size = sizeof (kernel_object_t);
949 949
950 950 switch (obj->class) {
951 951 case CKO_PUBLIC_KEY:
952 952 if (obj->key_type == CKK_RSA) {
953 953 big = OBJ_PUB_RSA_PUBEXPO(obj);
954 954 obj_size += big->big_value_len;
955 955 big = OBJ_PUB_RSA_MOD(obj);
956 956 obj_size += big->big_value_len;
957 957
958 958 } else if (obj->key_type == CKK_DSA) {
959 959 big = OBJ_PUB_DSA_PRIME(obj);
960 960 obj_size += big->big_value_len;
961 961 big = OBJ_PUB_DSA_SUBPRIME(obj);
962 962 obj_size += big->big_value_len;
963 963 big = OBJ_PUB_DSA_BASE(obj);
964 964 obj_size += big->big_value_len;
965 965 big = OBJ_PUB_DSA_VALUE(obj);
966 966 obj_size += big->big_value_len;
967 967
968 968 } else if (obj->key_type == CKK_EC) {
969 969 big = OBJ_PUB_EC_POINT(obj);
970 970 obj_size += big->big_value_len;
971 971
972 972 } else {
973 973 rv = CKR_OBJECT_HANDLE_INVALID;
974 974 }
975 975 break;
976 976
977 977 case CKO_PRIVATE_KEY:
978 978 if (obj->key_type == CKK_RSA) {
979 979 big = OBJ_PRI_RSA_MOD(obj);
980 980 obj_size += big->big_value_len;
981 981
982 982 big = OBJ_PRI_RSA_PUBEXPO(obj); /* optional */
983 983 if (big != NULL) {
984 984 obj_size += big->big_value_len;
985 985 }
986 986
987 987 big = OBJ_PRI_RSA_PRIEXPO(obj);
988 988 obj_size += big->big_value_len;
989 989
990 990 big = OBJ_PRI_RSA_PRIME1(obj); /* optional */
991 991 if (big != NULL) {
992 992 obj_size += big->big_value_len;
993 993 }
994 994
995 995 big = OBJ_PRI_RSA_PRIME2(obj); /* optional */
996 996 if (big != NULL) {
997 997 obj_size += big->big_value_len;
998 998 }
999 999
1000 1000 big = OBJ_PRI_RSA_EXPO1(obj); /* optional */
1001 1001 if (big != NULL) {
1002 1002 obj_size += big->big_value_len;
1003 1003 }
1004 1004
1005 1005 big = OBJ_PRI_RSA_EXPO2(obj); /* optional */
1006 1006 if (big != NULL) {
1007 1007 obj_size += big->big_value_len;
1008 1008 }
1009 1009
1010 1010 big = OBJ_PRI_RSA_COEF(obj); /* optional */
1011 1011 if (big != NULL) {
1012 1012 obj_size += big->big_value_len;
1013 1013 }
1014 1014
1015 1015 } else if (obj->key_type == CKK_DSA) {
1016 1016 big = OBJ_PRI_DSA_PRIME(obj);
1017 1017 obj_size += big->big_value_len;
1018 1018 big = OBJ_PRI_DSA_SUBPRIME(obj);
1019 1019 obj_size += big->big_value_len;
1020 1020 big = OBJ_PRI_DSA_BASE(obj);
1021 1021 obj_size += big->big_value_len;
1022 1022 big = OBJ_PRI_DSA_VALUE(obj);
1023 1023 obj_size += big->big_value_len;
1024 1024
1025 1025 } else if (obj->key_type == CKK_EC) {
1026 1026 big = OBJ_PRI_EC_VALUE(obj);
1027 1027 obj_size += big->big_value_len;
1028 1028
1029 1029 } else {
1030 1030 rv = CKR_OBJECT_HANDLE_INVALID;
1031 1031 }
1032 1032 break;
1033 1033
1034 1034 case CKO_SECRET_KEY:
1035 1035 obj_size += OBJ_SEC_VALUE_LEN(obj);
1036 1036 break;
1037 1037
1038 1038 default:
1039 1039 rv = CKR_OBJECT_HANDLE_INVALID;
1040 1040 }
1041 1041
1042 1042 if (rv == CKR_OK) {
1043 1043 *pulSize = obj_size;
1044 1044 }
1045 1045
1046 1046 return (rv);
1047 1047 }
1048 1048
1049 1049 /*
1050 1050 * This function adds the to-be-freed session object to a linked list.
1051 1051 * When the number of objects queued in the linked list reaches the
1052 1052 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
1053 1053 * object (FIFO) in the list.
1054 1054 */
1055 1055 void
1056 1056 kernel_object_delay_free(kernel_object_t *objp)
1057 1057 {
1058 1058 kernel_object_t *tmp;
1059 1059
1060 1060 (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
1061 1061
1062 1062 /* Add the newly deleted object at the end of the list */
1063 1063 objp->next = NULL;
1064 1064 if (obj_delay_freed.first == NULL) {
1065 1065 obj_delay_freed.last = objp;
1066 1066 obj_delay_freed.first = objp;
1067 1067 } else {
1068 1068 obj_delay_freed.last->next = objp;
1069 1069 obj_delay_freed.last = objp;
1070 1070 }
1071 1071
1072 1072 if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
1073 1073 /*
1074 1074 * Free the first object in the list only if
1075 1075 * the total count reaches maximum threshold.
1076 1076 */
1077 1077 obj_delay_freed.count--;
1078 1078 tmp = obj_delay_freed.first->next;
1079 1079 free(obj_delay_freed.first);
1080 1080 obj_delay_freed.first = tmp;
1081 1081 }
1082 1082 (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
1083 1083 }
↓ open down ↓ |
992 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX