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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2018, Joyent, Inc.
24 */
25
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <strings.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include "metaGlobal.h"
35
36 /* Size of the template for creating key used for wrap/unwrap */
37 #define WRAP_KEY_TEMPLATE_SIZE 7
38
39 /*
40 * Information necessary to create keys for C_WrapKey/C_UnwrapKey
41 */
42 typedef struct _wrap_info {
43 CK_OBJECT_CLASS class; /* class of the key for wrap/unwrap */
44 CK_KEY_TYPE key_type; /* key type of key for wrap/unwrap */
45 CK_ULONG key_length; /* length of key */
46 CK_MECHANISM_TYPE mech_type; /* mech used for wrap/unwrap */
47 CK_ULONG iv_length; /* length of iv for mech */
48
49 boolean_t src_supports;
50 boolean_t dst_supports;
51 } wrap_info_t;
52
53 extern pthread_rwlock_t meta_sessionlist_lock;
54 extern meta_session_t *meta_sessionlist_head;
55
56 static wrap_info_t common_wrap_info[] = {
57 {CKO_SECRET_KEY, CKK_AES, 16, CKM_AES_CBC_PAD, 16, B_FALSE, B_FALSE},
58 {CKO_SECRET_KEY, CKK_DES3, 24, CKM_DES3_CBC_PAD, 8, B_FALSE, B_FALSE},
59 {CKO_SECRET_KEY, CKK_DES, 8, CKM_DES_CBC_PAD, 8, B_FALSE, B_FALSE},
60 };
61
62 static unsigned int num_common_wrap_info =
63 sizeof (common_wrap_info) / sizeof (wrap_info_t);
64
65 static wrap_info_t special_wrap_info[] = {
66 {CKO_SECRET_KEY, CKK_SKIPJACK, 12, CKM_SKIPJACK_WRAP, 0,
67 B_FALSE, B_FALSE},
68 {CKO_SECRET_KEY, CKK_BATON, 40, CKM_BATON_WRAP, 0,
69 B_FALSE, B_FALSE},
70 {CKO_SECRET_KEY, CKK_JUNIPER, 40, CKM_JUNIPER_WRAP, 0,
71 B_FALSE, B_FALSE},
72 };
73 static unsigned int num_special_wrap_info =
74 sizeof (special_wrap_info) / sizeof (wrap_info_t);
75
76 static wrap_info_t rsa_wrap_info[] = {
77 {CKO_PUBLIC_KEY, CKK_RSA, 0, CKM_RSA_PKCS, 0,
78 B_FALSE, B_FALSE},
79 {CKO_PUBLIC_KEY, CKK_RSA, 0, CKM_RSA_X_509, 0,
80 B_FALSE, B_FALSE},
81 };
82 static unsigned int num_rsa_wrap_info =
83 sizeof (rsa_wrap_info) / sizeof (wrap_info_t);
84
85
86 static pthread_rwlock_t meta_objectclose_lock;
87 static pthread_rwlock_t tokenobject_list_lock;
88 static meta_object_t *tokenobject_list_head;
89
90 CK_BBOOL falsevalue = FALSE;
91 CK_BBOOL truevalue = TRUE;
92
93 /*
94 * Public and private exponent, and Module value for
95 * creating the RSA public/private key.
96 *
97 */
98 static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01};
99 CK_BYTE PriExpo[128] = {
100 0x8e, 0xc9, 0x70, 0x57, 0x6b, 0xcd, 0xfb, 0xa9,
101 0x19, 0xad, 0xcd, 0x91, 0x69, 0xd5, 0x52, 0xec,
102 0x72, 0x1e, 0x45, 0x15, 0x06, 0xdc, 0x65, 0x2d,
103 0x98, 0xc4, 0xce, 0x33, 0x54, 0x15, 0x70, 0x8d,
104 0xfa, 0x65, 0xea, 0x53, 0x44, 0xf3, 0x3e, 0x3f,
105 0xb4, 0x4c, 0x60, 0xd5, 0x01, 0x2d, 0xa4, 0x12,
106 0x99, 0xbf, 0x3f, 0x0b, 0xcd, 0xbb, 0x24, 0x10,
107 0x60, 0x30, 0x5e, 0x58, 0xf8, 0x59, 0xaa, 0xd1,
108 0x63, 0x3b, 0xbc, 0xcb, 0x94, 0x58, 0x38, 0x24,
109 0xfc, 0x65, 0x25, 0xc5, 0xa6, 0x51, 0xa2, 0x2e,
110 0xf1, 0x5e, 0xf5, 0xc1, 0xf5, 0x46, 0xf7, 0xbd,
111 0xc7, 0x62, 0xa8, 0xe2, 0x27, 0xd6, 0x94, 0x5b,
112 0xd3, 0xa2, 0xb5, 0x76, 0x42, 0x67, 0x6b, 0x86,
113 0x91, 0x97, 0x4d, 0x07, 0x92, 0x00, 0x4a, 0xdf,
114 0x0b, 0x65, 0x64, 0x05, 0x03, 0x48, 0x27, 0xeb,
115 0xce, 0x9a, 0x49, 0x7f, 0x3e, 0x10, 0xe0, 0x01};
116
117 static CK_BYTE Modulus[128] = {
118 0x94, 0x32, 0xb9, 0x12, 0x1d, 0x68, 0x2c, 0xda,
119 0x2b, 0xe0, 0xe4, 0x97, 0x1b, 0x4d, 0xdc, 0x43,
120 0xdf, 0x38, 0x6e, 0x7b, 0x9f, 0x07, 0x58, 0xae,
121 0x9d, 0x82, 0x1e, 0xc7, 0xbc, 0x92, 0xbf, 0xd3,
122 0xce, 0x00, 0xbb, 0x91, 0xc9, 0x79, 0x06, 0x03,
123 0x1f, 0xbc, 0x9f, 0x94, 0x75, 0x29, 0x5f, 0xd7,
124 0xc5, 0xf3, 0x73, 0x8a, 0xa4, 0x35, 0x43, 0x7a,
125 0x00, 0x32, 0x97, 0x3e, 0x86, 0xef, 0x70, 0x6f,
126 0x18, 0x56, 0x15, 0xaa, 0x6a, 0x87, 0xe7, 0x8d,
127 0x7d, 0xdd, 0x1f, 0xa4, 0xe4, 0x31, 0xd4, 0x7a,
128 0x8c, 0x0e, 0x20, 0xd2, 0x23, 0xf5, 0x57, 0x3c,
129 0x1b, 0xa8, 0x44, 0xa4, 0x57, 0x8f, 0x33, 0x52,
130 0xad, 0x83, 0xae, 0x4a, 0x97, 0xa6, 0x1e, 0xa6,
131 0x2b, 0xfa, 0xea, 0xeb, 0x6e, 0x71, 0xb8, 0xb6,
132 0x0a, 0x36, 0xed, 0x83, 0xce, 0xb0, 0xdf, 0xc1,
133 0xd4, 0x3a, 0xe9, 0x99, 0x6f, 0xf3, 0x96, 0xb7};
134
135 static CK_RV
136 meta_clone_template_setup(meta_object_t *object,
137 const generic_attr_t *attributes, size_t num_attributes);
138
139 /*
140 * meta_objectManager_initialize
141 *
142 * Called from meta_Initialize. Initializes all the variables used
143 * by the object manager.
144 */
145 CK_RV
meta_objectManager_initialize()146 meta_objectManager_initialize()
147 {
148 if (pthread_rwlock_init(&meta_objectclose_lock, NULL) != 0) {
149 return (CKR_FUNCTION_FAILED);
150 }
151
152 if (pthread_rwlock_init(&tokenobject_list_lock, NULL) != 0) {
153 (void) pthread_rwlock_destroy(&meta_objectclose_lock);
154 return (CKR_FUNCTION_FAILED);
155 }
156
157 tokenobject_list_head = NULL;
158
159 return (CKR_OK);
160 }
161
162 void
meta_objectManager_finalize()163 meta_objectManager_finalize()
164 {
165 /*
166 * If there are still any token object in the list, need to
167 * deactivate all of them.
168 */
169 (void) meta_token_object_deactivate(ALL_TOKEN);
170
171 (void) pthread_rwlock_destroy(&meta_objectclose_lock);
172 (void) pthread_rwlock_destroy(&tokenobject_list_lock);
173 }
174
175
176
177 /*
178 * meta_handle2object
179 *
180 * Convert a CK_OBJECT_HANDLE to the corresponding metaobject. If
181 * successful, a reader-lock on the object will be held to indicate
182 * that it's in use. Call OBJRELEASE() when finished.
183 *
184 */
185 CK_RV
meta_handle2object(CK_OBJECT_HANDLE hObject,meta_object_t ** object)186 meta_handle2object(CK_OBJECT_HANDLE hObject, meta_object_t **object)
187 {
188 meta_object_t *tmp_object = (meta_object_t *)(hObject);
189
190 /* Check for bad args (eg CK_INVALID_HANDLE, which is 0/NULL). */
191 if (tmp_object == NULL) {
192 *object = NULL;
193 return (CKR_OBJECT_HANDLE_INVALID);
194 }
195
196
197 /* Lock to ensure the magic-check + read-lock is atomic. */
198 (void) pthread_rwlock_rdlock(&meta_objectclose_lock);
199
200 if (tmp_object->magic_marker != METASLOT_OBJECT_MAGIC) {
201 (void) pthread_rwlock_unlock(&meta_objectclose_lock);
202 *object = NULL;
203 return (CKR_OBJECT_HANDLE_INVALID);
204 }
205 (void) pthread_rwlock_rdlock(&tmp_object->object_lock);
206 (void) pthread_rwlock_unlock(&meta_objectclose_lock);
207
208 *object = tmp_object;
209 return (CKR_OK);
210 }
211
212
213 /*
214 * meta_object_alloc
215 *
216 * Creates a new metaobject, but does not yet add it to the object list.
217 * Once the caller has finished initializing the object (by setting
218 * object attributes), meta_object_add should be called. This two-step
219 * process prevents others from seeing the object until fully intitialized.
220 *
221 */
222 CK_RV
meta_object_alloc(meta_session_t * session,meta_object_t ** object)223 meta_object_alloc(meta_session_t *session, meta_object_t **object)
224 {
225 meta_object_t *new_object;
226 CK_ULONG num_slots;
227
228 /* Allocate memory for the object. */
229 new_object = calloc(1, sizeof (meta_object_t));
230 if (new_object == NULL)
231 return (CKR_HOST_MEMORY);
232
233 num_slots = meta_slotManager_get_slotcount();
234
235 new_object->clones = calloc(num_slots, sizeof (slot_object_t *));
236 if (new_object->clones == NULL) {
237 free(new_object);
238 return (CKR_HOST_MEMORY);
239 }
240
241 new_object->tried_create_clone = calloc(num_slots, sizeof (boolean_t));
242 if (new_object->tried_create_clone == NULL) {
243 free(new_object->clones);
244 free(new_object);
245 return (CKR_HOST_MEMORY);
246 }
247
248 /* Initialize the object fields. */
249 new_object->magic_marker = METASLOT_OBJECT_MAGIC;
250 (void) pthread_rwlock_init(&new_object->object_lock, NULL);
251 (void) pthread_rwlock_init(&new_object->attribute_lock, NULL);
252 (void) pthread_mutex_init(&new_object->clone_create_lock, NULL);
253 (void) pthread_mutex_init(&new_object->isClosingObject_lock, NULL);
254 new_object->creator_session = session;
255
256 *object = new_object;
257
258 return (CKR_OK);
259 }
260
261
262 /*
263 * meta_object_get_attr
264 *
265 * Get attribute values to fill in attribute values
266 * being kept in the metaslot object. The following 4 attributes
267 * in the meta_object_t structure will be filled in:
268 * isToken, isPrivate, isSensitive, isExtractable
269 *
270 * It's basically an easy way to do a C_GetAttributeValue.
271 * So, the hSession argument is assumed
272 * to be valid, and the pointer to meta_object_t is also assumed
273 * to be valid.
274 */
275 CK_RV
meta_object_get_attr(slot_session_t * slot_session,CK_OBJECT_HANDLE hObject,meta_object_t * object)276 meta_object_get_attr(slot_session_t *slot_session, CK_OBJECT_HANDLE hObject,
277 meta_object_t *object)
278 {
279 CK_BBOOL is_sensitive = object->isSensitive;
280 CK_BBOOL is_extractable = object->isExtractable;
281 CK_BBOOL is_token = B_FALSE, is_private = B_FALSE;
282 CK_KEY_TYPE keytype;
283 CK_OBJECT_CLASS class;
284 CK_ATTRIBUTE attrs[3];
285 CK_RV rv;
286 CK_SESSION_HANDLE hSession = slot_session->hSession;
287 CK_SLOT_ID fw_st_id = slot_session->fw_st_id;
288 int count = 1;
289
290 attrs[0].type = CKA_CLASS;
291 attrs[0].pValue = &class;
292 attrs[0].ulValueLen = sizeof (class);
293
294 if (object->isFreeObject != FREE_ENABLED) {
295 attrs[1].type = CKA_TOKEN;
296 attrs[1].pValue = &is_token;
297 attrs[1].ulValueLen = sizeof (is_token);
298 count++;
299 }
300
301 /*
302 * If this is a freeobject, we already know the Private value
303 * and we don't want to overwrite it with the wrong value
304 */
305 if (object->isFreeObject <= FREE_DISABLED) {
306 attrs[count].type = CKA_PRIVATE;
307 attrs[count].pValue = &is_private;
308 attrs[count].ulValueLen = sizeof (is_private);
309 count++;
310 } else
311 is_private = object->isPrivate;
312
313 rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject,
314 attrs, count);
315 if (rv != CKR_OK) {
316 return (rv);
317 }
318
319 count = 0;
320 switch (class) {
321 case CKO_PRIVATE_KEY:
322 case CKO_SECRET_KEY:
323 /* Only need to check these for private & secret keys */
324 attrs[0].type = CKA_EXTRACTABLE;
325 attrs[0].pValue = &is_extractable;
326 attrs[0].ulValueLen = sizeof (is_extractable);
327 count = 1;
328
329 /*
330 * If this is a freeobject, we already know the Sensitive
331 * value and we don't want to overwrite it with the wrong
332 * value.
333 */
334
335 if (object->isFreeObject <= FREE_DISABLED) {
336 attrs[1].type = CKA_SENSITIVE;
337 attrs[1].pValue = &is_sensitive;
338 attrs[1].ulValueLen = sizeof (is_sensitive);
339 count = 2;
340
341 /*
342 * We only need the key type if this is the first
343 * time we've looked at the object
344 */
345 if (object->isFreeObject == FREE_UNCHECKED) {
346 attrs[2].type = CKA_KEY_TYPE;
347 attrs[2].pValue = &keytype;
348 attrs[2].ulValueLen = sizeof (keytype);
349 count = 3;
350 }
351 }
352
353 break;
354
355 case CKO_PUBLIC_KEY:
356 if (object->isFreeObject == FREE_UNCHECKED) {
357 attrs[count].type = CKA_KEY_TYPE;
358 attrs[count].pValue = &keytype;
359 attrs[count].ulValueLen = sizeof (keytype);
360 count++;
361 }
362 is_sensitive = CK_FALSE;
363 is_extractable = CK_TRUE;
364 break;
365
366 default:
367 object->isFreeObject = FREE_DISABLED;
368 is_sensitive = CK_FALSE;
369 is_extractable = CK_TRUE;
370 };
371
372 if (count > 0) {
373 rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject,
374 attrs, count);
375 if (rv != CKR_OK) {
376 return (rv);
377 }
378
379 if (object->isFreeObject == FREE_UNCHECKED) {
380 if (keytype == CKK_EC || keytype == CKK_RSA ||
381 keytype == CKK_DH) {
382 if (metaslot_config.auto_key_migrate) {
383 object->isFreeObject = FREE_DISABLED;
384 object->isFreeToken = FREE_DISABLED;
385 }
386
387 object->isFreeObject = FREE_ENABLED;
388 if (is_token)
389 object->isFreeToken = FREE_ENABLED;
390 } else
391 object->isFreeObject = FREE_DISABLED;
392
393 }
394
395 }
396
397 object->isToken = is_token;
398 object->isPrivate = is_private;
399 object->isSensitive = is_sensitive;
400 object->isExtractable = is_extractable;
401
402 return (CKR_OK);
403 }
404
405
406 /*
407 * meta_object_activate
408 *
409 * Add a new metaobject to the list of objects. See also meta_object_create,
410 * which would be called to create an object before it is added.
411 */
412 void
meta_object_activate(meta_object_t * new_object)413 meta_object_activate(meta_object_t *new_object)
414 {
415 pthread_rwlock_t *list_lock;
416 meta_object_t **list_head;
417
418 /*
419 * For session objects, we keep the list in the session that created
420 * this object, because this object will be destroyed when that session
421 * is closed.
422 *
423 * For token objects, the list is global (ie, not associated with any
424 * particular session).
425 */
426 if (new_object->isToken) {
427 list_lock = &tokenobject_list_lock;
428 list_head = &tokenobject_list_head;
429 } else {
430 list_lock = &new_object->creator_session->object_list_lock;
431 list_head = &new_object->creator_session->object_list_head;
432 }
433
434 /* Add object to the list of objects. */
435 (void) pthread_rwlock_wrlock(list_lock);
436 INSERT_INTO_LIST(*list_head, new_object);
437 (void) pthread_rwlock_unlock(list_lock);
438 }
439
440
441 /*
442 * meta_object_deactivate
443 *
444 * Removes the object from the list of valid meta objects. Note
445 * that this function does not clean up any allocated
446 * resources (memory, object clones, etc). Cleaning up of
447 * allocated resources is done by calling the meta_object_dealloc()
448 *
449 */
450 CK_RV
meta_object_deactivate(meta_object_t * object,boolean_t have_list_lock,boolean_t have_object_lock)451 meta_object_deactivate(meta_object_t *object, boolean_t have_list_lock,
452 boolean_t have_object_lock)
453 {
454 pthread_rwlock_t *list_lock;
455 meta_object_t **list_head;
456
457 if (!have_object_lock) {
458 (void) pthread_rwlock_rdlock(&object->object_lock);
459 }
460
461 (void) pthread_mutex_lock(&object->isClosingObject_lock);
462 if (object->isClosingObject) {
463 /* Lost a delete race. */
464 (void) pthread_mutex_unlock(&object->isClosingObject_lock);
465 OBJRELEASE(object);
466 return (CKR_OBJECT_HANDLE_INVALID);
467 }
468 object->isClosingObject = B_TRUE;
469 (void) pthread_mutex_unlock(&object->isClosingObject_lock);
470
471 if (object->isToken || (object->isFreeToken == FREE_ENABLED)) {
472 list_lock = &tokenobject_list_lock;
473 list_head = &tokenobject_list_head;
474 } else {
475 list_lock = &object->creator_session->object_list_lock;
476 list_head = &object->creator_session->object_list_head;
477 }
478
479 /*
480 * Remove object from the object list. Once removed, it will not
481 * be possible for another thread to begin using the object.
482 */
483 (void) pthread_rwlock_wrlock(&meta_objectclose_lock);
484 if (!have_list_lock) {
485 (void) pthread_rwlock_wrlock(list_lock);
486 }
487
488
489 object->magic_marker = METASLOT_OBJECT_BADMAGIC;
490 /*
491 * Can't use the regular REMOVE_FROM_LIST() function because
492 * that will miss the "error cleanup" situation where object is not yet
493 * in the list (object->next == NULL && object->prev == NULL)
494 */
495 if (*list_head == object) {
496 /* Object is the first one in the list */
497 if (object->next) {
498 *list_head = object->next;
499 object->next->prev = NULL;
500 } else {
501 /* Object is the only one in the list */
502 *list_head = NULL;
503 }
504 } else if (object->next != NULL || object->prev != NULL) {
505 if (object->next) {
506 object->prev->next = object->next;
507 object->next->prev = object->prev;
508 } else {
509 /* Object is the last one in the list */
510 object->prev->next = NULL;
511 }
512 }
513
514 if (!have_list_lock) {
515 (void) pthread_rwlock_unlock(list_lock);
516 }
517 (void) pthread_rwlock_unlock(&meta_objectclose_lock);
518
519 /*
520 * Wait for anyone already using object to finish, by obtaining
521 * a writer-lock (need to release our reader-lock first). Once we
522 * get the write lock, we can just release it and finish cleaning
523 * up the object.
524 */
525 (void) pthread_rwlock_unlock(&object->object_lock); /* rdlock */
526 (void) pthread_rwlock_wrlock(&object->object_lock);
527 (void) pthread_rwlock_unlock(&object->object_lock); /* wrlock */
528
529
530 return (CKR_OK);
531 }
532
533
534 /*
535 * meta_object_dealloc
536 *
537 * Performs final object cleanup, releasing any allocated memory and
538 * destroying any clones on other slots. Caller is assumed to have
539 * called meta_object_deactivate() before this function.
540 *
541 * Caller is assumed to have only reference to object, but should have
542 * released any lock.
543 *
544 * If "nukeSourceObj" argument is true, we will actually delete the
545 * object from the underlying slot.
546 */
547 CK_RV
meta_object_dealloc(meta_session_t * session,meta_object_t * object,boolean_t nukeSourceObj)548 meta_object_dealloc(meta_session_t *session, meta_object_t *object,
549 boolean_t nukeSourceObj)
550 {
551 CK_RV rv, save_rv = CKR_OK;
552 CK_ULONG slotnum, num_slots;
553 CK_ULONG i;
554
555 /* First, delete all the clones of this object on other slots. */
556 num_slots = meta_slotManager_get_slotcount();
557 for (slotnum = 0; slotnum < num_slots; slotnum++) {
558 slot_session_t *obj_session;
559 slot_object_t *clone;
560
561 clone = object->clones[slotnum];
562 if (clone == NULL)
563 continue;
564 if (nukeSourceObj || (!object->isToken &&
565 !(object->isFreeToken == FREE_ENABLED &&
566 get_keystore_slotnum() == slotnum))) {
567
568 rv = meta_get_slot_session(slotnum, &obj_session,
569 (session == NULL) ?
570 object->creator_session->session_flags :
571 session->session_flags);
572
573 if (rv == CKR_OK) {
574 rv = FUNCLIST(obj_session->fw_st_id)->\
575 C_DestroyObject(obj_session->hSession,
576 clone->hObject);
577
578 meta_release_slot_session(obj_session);
579 if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
580 save_rv = rv;
581 }
582 }
583
584 }
585
586 meta_slot_object_deactivate(clone);
587 meta_slot_object_dealloc(clone);
588
589 object->clones[slotnum] = NULL;
590 }
591
592 /* Now erase and delete any attributes in the metaobject. */
593 dealloc_attributes(object->attributes, object->num_attributes);
594
595 free(object->clones);
596 free(object->tried_create_clone);
597
598 if (object->clone_template) {
599 for (i = 0; i < object->clone_template_size; i++) {
600 freezero((object->clone_template)[i].pValue,
601 (object->clone_template)[i].ulValueLen);
602 }
603 free(object->clone_template);
604 }
605
606 /* Cleanup remaining object fields. */
607 (void) pthread_rwlock_destroy(&object->object_lock);
608 (void) pthread_rwlock_destroy(&object->attribute_lock);
609 (void) pthread_mutex_destroy(&object->isClosingObject_lock);
610 (void) pthread_mutex_destroy(&object->clone_create_lock);
611
612 meta_object_delay_free(object);
613
614 return (save_rv);
615 }
616
617
618 /*
619 * meta_slot_object_alloc
620 */
621 CK_RV
meta_slot_object_alloc(slot_object_t ** object)622 meta_slot_object_alloc(slot_object_t **object)
623 {
624 slot_object_t *new_object;
625
626 new_object = calloc(1, sizeof (slot_object_t));
627 if (new_object == NULL)
628 return (CKR_HOST_MEMORY);
629
630 *object = new_object;
631 return (CKR_OK);
632 }
633
634
635 /*
636 * meta_slot_object_activate
637 */
638 void
meta_slot_object_activate(slot_object_t * object,slot_session_t * creator_session,boolean_t isToken)639 meta_slot_object_activate(slot_object_t *object,
640 slot_session_t *creator_session, boolean_t isToken)
641 {
642 object->creator_session = creator_session;
643
644 if (isToken) {
645 extern slot_data_t *slots;
646 slot_data_t *slot;
647
648 slot = &(slots[object->creator_session->slotnum]);
649
650 (void) pthread_rwlock_wrlock(&slot->tokenobject_list_lock);
651 INSERT_INTO_LIST(slot->tokenobject_list_head, object);
652 (void) pthread_rwlock_unlock(&slot->tokenobject_list_lock);
653 } else {
654 slot_session_t *session = object->creator_session;
655
656 /* Add to session's list of session objects. */
657 (void) pthread_rwlock_wrlock(&session->object_list_lock);
658 INSERT_INTO_LIST(session->object_list_head, object);
659 (void) pthread_rwlock_unlock(&session->object_list_lock);
660 }
661
662 /*
663 * This set tells the slot object that we are in the token list,
664 * but does not cause harm with the metaobject knowing the object
665 * isn't a token, but a freetoken
666 */
667
668 object->isToken = isToken;
669 }
670
671
672 /*
673 * meta_slot_object_deactivate
674 *
675 * Remove the specified slot object from the appropriate object list.
676 */
677 void
meta_slot_object_deactivate(slot_object_t * object)678 meta_slot_object_deactivate(slot_object_t *object)
679 {
680 slot_object_t **list_head;
681 pthread_rwlock_t *list_lock;
682
683 if (object->isToken) {
684 extern slot_data_t *slots;
685 slot_data_t *slot;
686
687 slot = &(slots[object->creator_session->slotnum]);
688
689 list_head = &slot->tokenobject_list_head;
690 list_lock = &slot->tokenobject_list_lock;
691 } else {
692 list_head = &object->creator_session->object_list_head;
693 list_lock = &object->creator_session->object_list_lock;
694 }
695
696 (void) pthread_rwlock_wrlock(list_lock);
697 REMOVE_FROM_LIST(*list_head, object);
698 (void) pthread_rwlock_unlock(list_lock);
699 }
700
701
702 /*
703 * meta_slot_object_dealloc
704 */
705 void
meta_slot_object_dealloc(slot_object_t * object)706 meta_slot_object_dealloc(slot_object_t *object)
707 {
708 /* Not much cleanup for slot objects, unlike meta objects... */
709 free(object);
710 }
711
712
713 /*
714 * meta_object_copyin
715 *
716 * When a key is generated/derived/unwrapped, the attribute values
717 * created by the token are not immediately read into our copy of the
718 * attributes. We defer this work until we actually need to know.
719 */
720 CK_RV
meta_object_copyin(meta_object_t * object)721 meta_object_copyin(meta_object_t *object)
722 {
723 CK_RV rv = CKR_OK;
724 slot_session_t *session = NULL;
725 CK_ATTRIBUTE *attrs = NULL, *attrs_with_val = NULL;
726 slot_object_t *slot_object = NULL;
727 CK_ULONG num_attrs = 0, i, num_attrs_with_val;
728 CK_SESSION_HANDLE hSession;
729 CK_SLOT_ID fw_st_id;
730
731 /* Make sure no one else is looking at attributes. */
732 (void) pthread_rwlock_wrlock(&object->attribute_lock);
733
734 /* Did we just lose a copyin race with another thread */
735 if (object->attributes != NULL) {
736 goto finish;
737 }
738
739 slot_object = object->clones[object->master_clone_slotnum];
740
741 rv = meta_get_slot_session(object->master_clone_slotnum, &session,
742 object->creator_session->session_flags);
743 if (rv != CKR_OK) {
744 goto finish;
745 }
746
747 /*
748 * first, get the master template of all the attributes
749 * for this object
750 */
751 rv = get_master_attributes_by_object(session, slot_object,
752 &(object->attributes), &(object->num_attributes));
753 if (rv != CKR_OK) {
754 goto finish;
755 }
756
757 /*
758 * Get value for each attribute items.
759 *
760 * Some attributes are required by the given object type.
761 * Some are optional. Get all the values first, and then
762 * make sure we have value for all required values,
763 */
764 attrs = calloc(object->num_attributes, sizeof (CK_ATTRIBUTE));
765 if (attrs == NULL) {
766 rv = CKR_HOST_MEMORY;
767 goto finish;
768 }
769
770
771 for (i = 0; i < object->num_attributes; i++) {
772 attrs[i].type =
773 ((object->attributes[i]).attribute).type;
774 }
775 num_attrs = object->num_attributes;
776
777 hSession = session->hSession;
778 fw_st_id = session->fw_st_id;
779
780 /* first, call C_GetAttributeValue() to get size for each attribute */
781 rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
782 slot_object->hObject, attrs, num_attrs);
783 /*
784 * If the return value is not CKR_OK, allow it to be
785 * CKR_ATTRIBUTE_TYPE_INVALID for now.
786 * Some attributes defined in PKCS#11 version 2.11
787 * might not be defined in earlier versions. We will
788 * TRY to work with those providers if the attribute
789 * is optional.
790 */
791 if ((rv != CKR_OK) && (rv != CKR_ATTRIBUTE_TYPE_INVALID)) {
792 rv = CKR_FUNCTION_FAILED; /* make sure rv is appropriate */
793 goto finish;
794 }
795
796 /*
797 * allocate space.
798 * Since we don't know how many attributes have
799 * values at this time, just assume all of them
800 * have values so we save one loop to count the number
801 * of attributes that have value.
802 */
803 attrs_with_val = calloc(num_attrs, sizeof (CK_ATTRIBUTE));
804 if (attrs_with_val == NULL) {
805 rv = CKR_HOST_MEMORY;
806 goto finish;
807 }
808
809
810 num_attrs_with_val = 0;
811 for (i = 0; i < num_attrs; i++) {
812 if (!(((CK_LONG)(attrs[i].ulValueLen)) > 0)) {
813 /* if it isn't an optional attr, len should be > 0 */
814 if (!object->attributes[i].canBeEmptyValue) {
815 rv = CKR_FUNCTION_FAILED;
816 goto finish;
817 }
818 } else {
819 attrs_with_val[num_attrs_with_val].type = attrs[i].type;
820 attrs_with_val[num_attrs_with_val].ulValueLen =
821 attrs[i].ulValueLen;
822 attrs_with_val[num_attrs_with_val].pValue =
823 malloc(attrs[i].ulValueLen);
824 if (attrs_with_val[num_attrs_with_val].pValue == NULL) {
825 rv = CKR_HOST_MEMORY;
826 goto finish;
827 }
828 num_attrs_with_val++;
829 }
830 }
831
832 rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
833 slot_object->hObject, attrs_with_val, num_attrs_with_val);
834 if (rv != CKR_OK) {
835 goto finish;
836 }
837
838 /* store these values into the meta object */
839 for (i = 0; i < num_attrs_with_val; i++) {
840 rv = attribute_set_value(&(attrs_with_val[i]),
841 object->attributes, object->num_attributes);
842 if (rv != CKR_OK) {
843 goto finish;
844 }
845 }
846
847 finish:
848 (void) pthread_rwlock_unlock(&object->attribute_lock);
849
850 if (session)
851 meta_release_slot_session(session);
852
853 if (attrs) {
854 for (i = 0; i < num_attrs; i++) {
855 if (attrs[i].pValue != NULL) {
856 free(attrs[i].pValue);
857 }
858 }
859 free(attrs);
860 }
861
862 if (attrs_with_val) {
863 for (i = 0; i < num_attrs; i++) {
864 if (attrs_with_val[i].pValue != NULL) {
865 freezero(attrs_with_val[i].pValue,
866 attrs_with_val[i].ulValueLen);
867 }
868 }
869 free(attrs_with_val);
870 }
871 return (rv);
872 }
873
874 /*
875 * Create an object to be used for wrapping and unwrapping.
876 * The same template will be used for all wrapping/unwrapping keys all
877 * the time
878 */
879
880 static CK_RV
create_wrap_unwrap_key(slot_session_t * slot_session,CK_OBJECT_HANDLE * hObject,wrap_info_t * wrap_info,char * key_data,CK_ULONG key_len)881 create_wrap_unwrap_key(slot_session_t *slot_session, CK_OBJECT_HANDLE *hObject,
882 wrap_info_t *wrap_info, char *key_data, CK_ULONG key_len)
883 {
884
885 CK_OBJECT_CLASS objclass;
886 CK_KEY_TYPE keytype;
887 CK_RV rv = CKR_OK;
888 int i;
889 CK_ATTRIBUTE template[WRAP_KEY_TEMPLATE_SIZE];
890
891 i = 0;
892 objclass = wrap_info->class;
893 template[i].type = CKA_CLASS;
894 template[i].pValue = &objclass;
895 template[i].ulValueLen = sizeof (objclass);
896
897 i++;
898 keytype = wrap_info->key_type;
899 template[i].type = CKA_KEY_TYPE;
900 template[i].pValue = &keytype;
901 template[i].ulValueLen = sizeof (keytype);
902
903 i++;
904 template[i].type = CKA_TOKEN;
905 template[i].pValue = &falsevalue;
906 template[i].ulValueLen = sizeof (falsevalue);
907
908
909 if (objclass == CKO_SECRET_KEY) {
910 i++;
911 template[i].type = CKA_VALUE;
912 template[i].pValue = key_data;
913 template[i].ulValueLen = key_len;
914
915 i++;
916 template[i].type = CKA_WRAP;
917 template[i].pValue = &truevalue;
918 template[i].ulValueLen = sizeof (truevalue);
919
920 i++;
921 template[i].type = CKA_UNWRAP;
922 template[i].pValue = &truevalue;
923 template[i].ulValueLen = sizeof (truevalue);
924 } else {
925 /* Modulus is the same for rsa public and private key */
926 i++;
927 template[i].type = CKA_MODULUS;
928 template[i].pValue = Modulus;
929 template[i].ulValueLen = sizeof (Modulus);
930
931 if (objclass == CKO_PUBLIC_KEY) {
932 /* RSA public key */
933 i++;
934 template[i].type = CKA_PUBLIC_EXPONENT;
935 template[i].pValue = PubExpo;
936 template[i].ulValueLen = sizeof (PubExpo);
937
938 i++;
939 template[i].type = CKA_WRAP;
940 template[i].pValue = &truevalue;
941 template[i].ulValueLen = sizeof (truevalue);
942 } else {
943 /* RSA private key */
944 i++;
945 template[i].type = CKA_PRIVATE_EXPONENT;
946 template[i].pValue = PriExpo;
947 template[i].ulValueLen = sizeof (PriExpo);
948
949 i++;
950 template[i].type = CKA_UNWRAP;
951 template[i].pValue = &truevalue;
952 template[i].ulValueLen = sizeof (truevalue);
953 }
954 }
955
956 rv = FUNCLIST(slot_session->fw_st_id)->C_CreateObject(
957 slot_session->hSession, template, i + 1, hObject);
958
959 return (rv);
960 }
961
962
963 /*
964 * Create a clone of a non-sensitive and extractable object.
965 * If the template required for creating the clone doesn't exist,
966 * it will be retrieved from the master clone.
967 */
968 static CK_RV
clone_by_create(meta_object_t * object,slot_object_t * new_clone,slot_session_t * dst_slot_session)969 clone_by_create(meta_object_t *object, slot_object_t *new_clone,
970 slot_session_t *dst_slot_session)
971 {
972 CK_RV rv;
973 int free_token_index = -1;
974
975 if (object->attributes == NULL) {
976 rv = meta_object_copyin(object);
977 if (rv != CKR_OK) {
978 return (rv);
979 }
980 }
981
982 if (object->clone_template == NULL) {
983 rv = meta_clone_template_setup(object, object->attributes,
984 object->num_attributes);
985 if (rv != CKR_OK) {
986 return (rv);
987 }
988 }
989
990 if (object->isFreeToken == FREE_ENABLED) {
991 if (dst_slot_session->slotnum == get_keystore_slotnum())
992 free_token_index = set_template_boolean(CKA_TOKEN,
993 object->clone_template,
994 object->clone_template_size, B_FALSE, &truevalue);
995 else
996 free_token_index = set_template_boolean(CKA_TOKEN,
997 object->clone_template,
998 object->clone_template_size, B_FALSE, &falsevalue);
999 }
1000
1001 /* Create the clone... */
1002 rv = FUNCLIST(dst_slot_session->fw_st_id)->C_CreateObject(
1003 dst_slot_session->hSession, object->clone_template,
1004 object->clone_template_size, &(new_clone->hObject));
1005
1006 if (free_token_index != -1) {
1007 free_token_index = set_template_boolean(CKA_TOKEN,
1008 object->clone_template, object->clone_template_size,
1009 B_FALSE, &falsevalue);
1010 }
1011
1012 if (rv != CKR_OK) {
1013 return (rv);
1014 }
1015
1016 return (CKR_OK);
1017 }
1018
1019 /*
1020 * Goes through the list of wraping mechanisms, and returns the first
1021 * one that is supported by both the source and the destination slot.
1022 * If none of the mechanisms are supported by both slot, return the
1023 * first mechanism that's supported by the source slot
1024 */
1025 static CK_RV
find_best_match_wrap_mech(wrap_info_t * wrap_info,int num_info,CK_ULONG src_slotnum,CK_ULONG dst_slotnum,int * first_both_mech,int * first_src_mech)1026 find_best_match_wrap_mech(wrap_info_t *wrap_info, int num_info,
1027 CK_ULONG src_slotnum, CK_ULONG dst_slotnum, int *first_both_mech,
1028 int *first_src_mech)
1029 {
1030
1031 int i;
1032 boolean_t src_supports, dst_supports;
1033 CK_RV rv;
1034 CK_MECHANISM_INFO mech_info;
1035
1036 mech_info.flags = CKF_WRAP;
1037
1038 for (i = 0; i < num_info; i++) {
1039 src_supports = B_FALSE;
1040 dst_supports = B_FALSE;
1041
1042 rv = meta_mechManager_slot_supports_mech(
1043 (wrap_info[i]).mech_type, src_slotnum,
1044 &src_supports, NULL, B_FALSE, &mech_info);
1045 if (rv != CKR_OK) {
1046 return (rv);
1047 }
1048
1049 rv = meta_mechManager_slot_supports_mech(
1050 (wrap_info[i]).mech_type, dst_slotnum,
1051 &dst_supports, NULL, B_FALSE, &mech_info);
1052 if (rv != CKR_OK) {
1053 return (rv);
1054 }
1055
1056 /* both source and destination supports the mech */
1057 if ((src_supports) && (dst_supports)) {
1058 *first_both_mech = i;
1059 return (CKR_OK);
1060 }
1061
1062 if ((src_supports) && (*first_src_mech == -1)) {
1063 *first_src_mech = i;
1064 }
1065 }
1066 return (CKR_OK);
1067 }
1068
1069 /*
1070 * Determine the wrapping/unwrapping mechanism to be used
1071 *
1072 * If possible, select a mechanism that's supported by both source
1073 * and destination slot. If none of the mechanisms are supported
1074 * by both slot, then, select the first one supported by
1075 * the source slot.
1076 */
1077
1078 static CK_RV
get_wrap_mechanism(CK_OBJECT_CLASS obj_class,CK_KEY_TYPE key_type,CK_ULONG src_slotnum,CK_ULONG dst_slotnum,wrap_info_t * wrap_info)1079 get_wrap_mechanism(CK_OBJECT_CLASS obj_class, CK_KEY_TYPE key_type,
1080 CK_ULONG src_slotnum, CK_ULONG dst_slotnum, wrap_info_t *wrap_info)
1081 {
1082 wrap_info_t *wrap_info_to_search = NULL;
1083 unsigned int num_wrap_info;
1084 CK_RV rv;
1085 int i;
1086 boolean_t src_supports = B_FALSE, dst_supports = B_FALSE;
1087 int first_src_mech, rsa_first_src_mech, first_both_mech;
1088 CK_MECHANISM_INFO mech_info;
1089
1090 mech_info.flags = CKF_WRAP;
1091
1092 if ((obj_class == CKO_PRIVATE_KEY) && (key_type == CKK_KEA)) {
1093 /*
1094 * only SKIPJACK keys can be used for wrapping
1095 * KEA private keys
1096 */
1097
1098 for (i = 0; i < num_special_wrap_info; i++) {
1099 if ((special_wrap_info[i]).mech_type
1100 != CKM_SKIPJACK_WRAP) {
1101 continue;
1102 }
1103
1104 src_supports = B_FALSE;
1105 dst_supports = B_FALSE;
1106
1107 rv = meta_mechManager_slot_supports_mech(
1108 (special_wrap_info[i]).mech_type, src_slotnum,
1109 &src_supports, NULL, B_FALSE, &mech_info);
1110 if (rv != CKR_OK) {
1111 goto finish;
1112 }
1113
1114 rv = meta_mechManager_slot_supports_mech(
1115 (special_wrap_info[i]).mech_type, dst_slotnum,
1116 &dst_supports, NULL, B_FALSE, &mech_info);
1117 if (rv != CKR_OK) {
1118 goto finish;
1119 }
1120
1121 if (src_supports) {
1122 /*
1123 * both src and dst supports the mech or
1124 * only the src supports the mech
1125 */
1126 (void) memcpy(wrap_info,
1127 &(special_wrap_info[i]),
1128 sizeof (wrap_info_t));
1129
1130 wrap_info->src_supports = src_supports;
1131 wrap_info->dst_supports = dst_supports;
1132 rv = CKR_OK;
1133 goto finish;
1134 }
1135
1136 }
1137
1138 /*
1139 * if we are here, that means neither the source slot
1140 * nor the destination slots supports CKM_SKIPJACK_WRAP.
1141 */
1142 rv = CKR_FUNCTION_FAILED;
1143 goto finish;
1144 }
1145
1146 if ((key_type == CKK_SKIPJACK) || (key_type == CKK_BATON) ||
1147 (key_type == CKK_JUNIPER)) {
1148 /* special key types */
1149 wrap_info_to_search = special_wrap_info;
1150 num_wrap_info = num_special_wrap_info;
1151 } else {
1152 /* use the regular wrapping mechanisms */
1153 wrap_info_to_search = common_wrap_info;
1154 num_wrap_info = num_common_wrap_info;
1155 }
1156
1157 first_both_mech = -1;
1158 first_src_mech = -1;
1159
1160 rv = find_best_match_wrap_mech(wrap_info_to_search, num_wrap_info,
1161 src_slotnum, dst_slotnum, &first_both_mech, &first_src_mech);
1162 if (rv != CKR_OK) {
1163 goto finish;
1164 }
1165
1166 if (first_both_mech != -1) {
1167 (void) memcpy(wrap_info,
1168 &(wrap_info_to_search[first_both_mech]),
1169 sizeof (wrap_info_t));
1170
1171 wrap_info->src_supports = B_TRUE;
1172 wrap_info->dst_supports = B_TRUE;
1173 rv = CKR_OK;
1174 goto finish;
1175 }
1176
1177 /*
1178 * If we are here, we did not find a mechanism that's supported
1179 * by both source and destination slot.
1180 *
1181 * If it is a secret key, can also try to wrap it with
1182 * a RSA public key
1183 */
1184 if (obj_class == CKO_SECRET_KEY) {
1185 first_both_mech = -1;
1186 rsa_first_src_mech = -1;
1187
1188 rv = find_best_match_wrap_mech(rsa_wrap_info,
1189 num_rsa_wrap_info, src_slotnum, dst_slotnum,
1190 &first_both_mech, &rsa_first_src_mech);
1191
1192 if (rv != CKR_OK) {
1193 goto finish;
1194 }
1195
1196 if (first_both_mech > -1) {
1197 (void) memcpy(wrap_info,
1198 &(rsa_wrap_info[first_both_mech]),
1199 sizeof (wrap_info_t));
1200
1201 wrap_info->src_supports = B_TRUE;
1202 wrap_info->dst_supports = B_TRUE;
1203 rv = CKR_OK;
1204 goto finish;
1205 }
1206 }
1207
1208 /*
1209 * if we are here, that means none of the mechanisms are supported
1210 * by both the source and the destination
1211 */
1212 if (first_src_mech > -1) {
1213 /* source slot support one of the secret key mechs */
1214 (void) memcpy(wrap_info,
1215 &(wrap_info_to_search[first_src_mech]),
1216 sizeof (wrap_info_t));
1217 wrap_info->src_supports = B_TRUE;
1218 wrap_info->dst_supports = B_FALSE;
1219 rv = CKR_OK;
1220 } else if (rsa_first_src_mech > -1) {
1221 /* source slot support one of the RSA mechs */
1222 (void) memcpy(wrap_info, &(rsa_wrap_info[rsa_first_src_mech]),
1223 sizeof (wrap_info_t));
1224
1225 wrap_info->src_supports = B_TRUE;
1226 wrap_info->dst_supports = B_FALSE;
1227 rv = CKR_OK;
1228 } else {
1229 /* neither source nor destination support any wrap mechs */
1230 rv = CKR_FUNCTION_FAILED;
1231 }
1232
1233 finish:
1234 return (rv);
1235 }
1236
1237
1238 /*
1239 * This is called if the object to be cloned is a sensitive object
1240 */
1241 static CK_RV
clone_by_wrap(meta_object_t * object,slot_object_t * new_clone,slot_session_t * dst_slot_session)1242 clone_by_wrap(meta_object_t *object, slot_object_t *new_clone,
1243 slot_session_t *dst_slot_session)
1244 {
1245 slot_session_t *src_slot_session = NULL;
1246 CK_OBJECT_HANDLE wrappingKey = 0, unwrappingKey = 0;
1247 CK_MECHANISM wrappingMech;
1248 CK_BYTE *wrappedKey = NULL;
1249 CK_ULONG wrappedKeyLen = 0;
1250 slot_object_t *slot_object = NULL;
1251 CK_RV rv = CKR_OK;
1252 CK_OBJECT_HANDLE unwrapped_obj;
1253 meta_object_t *tmp_meta_obj = NULL;
1254 slot_object_t *tmp_slot_obj = NULL;
1255 CK_OBJECT_CLASS obj_class;
1256 CK_KEY_TYPE key_type;
1257 meta_session_t *tmp_meta_session = NULL;
1258 CK_ATTRIBUTE unwrap_template[4];
1259 char key_data[1024]; /* should be big enough for any key size */
1260 char ivbuf[1024]; /* should be big enough for any mech */
1261 wrap_info_t wrap_info;
1262 CK_ULONG key_len, unwrap_template_size;
1263
1264 slot_object = object->clones[object->master_clone_slotnum];
1265
1266 rv = meta_get_slot_session(object->master_clone_slotnum,
1267 &src_slot_session, object->creator_session->session_flags);
1268 if (rv != CKR_OK) {
1269 return (rv);
1270 }
1271
1272 /*
1273 * get the object class and key type for unwrap template
1274 * This information will also be used for determining
1275 * which wrap mechanism and which key to use for
1276 * doing the wrapping
1277 */
1278 unwrap_template[0].type = CKA_CLASS;
1279 unwrap_template[0].pValue = &obj_class;
1280 unwrap_template[0].ulValueLen = sizeof (obj_class);
1281
1282 unwrap_template[1].type = CKA_KEY_TYPE;
1283 unwrap_template[1].pValue = &key_type;
1284 unwrap_template[1].ulValueLen = sizeof (key_type);
1285
1286 rv = FUNCLIST(src_slot_session->fw_st_id)->C_GetAttributeValue(
1287 src_slot_session->hSession, slot_object->hObject,
1288 unwrap_template, 2);
1289 if (rv != CKR_OK) {
1290 goto finish;
1291 }
1292
1293 rv = get_wrap_mechanism(obj_class, key_type, src_slot_session->slotnum,
1294 dst_slot_session->slotnum, &wrap_info);
1295 if (rv != CKR_OK) {
1296 goto finish;
1297 }
1298
1299 /*
1300 * read number of bytes required from random device for
1301 * creating a secret key for wrapping and unwrapping
1302 */
1303 if (wrap_info.class == CKO_SECRET_KEY) {
1304
1305 /*
1306 * /dev/urandom will be used for generating the key used
1307 * for doing the wrap/unwrap. It's should be ok to
1308 * use /dev/urandom because this key is used for this
1309 * one time operation only. It doesn't need to be stored.
1310 */
1311 key_len = wrap_info.key_length;
1312 if (pkcs11_get_urandom(key_data, key_len) < 0) {
1313 rv = CKR_FUNCTION_FAILED;
1314 goto finish;
1315 }
1316
1317 if (wrap_info.iv_length > 0) {
1318 if (pkcs11_get_urandom(
1319 ivbuf, wrap_info.iv_length) < 0) {
1320 rv = CKR_FUNCTION_FAILED;
1321 goto finish;
1322 }
1323 }
1324 }
1325
1326 /* create the wrapping key */
1327 rv = create_wrap_unwrap_key(src_slot_session, &wrappingKey,
1328 &wrap_info, key_data, key_len);
1329 if (rv != CKR_OK) {
1330 goto finish;
1331 }
1332
1333 wrappingMech.mechanism = wrap_info.mech_type;
1334 wrappingMech.pParameter = ((wrap_info.iv_length > 0) ? ivbuf : NULL);
1335 wrappingMech.ulParameterLen = wrap_info.iv_length;
1336
1337 /* get the size of the wrapped key */
1338 rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
1339 src_slot_session->hSession, &wrappingMech,
1340 wrappingKey, slot_object->hObject, NULL, &wrappedKeyLen);
1341
1342 if (rv != CKR_OK) {
1343 goto finish;
1344 }
1345
1346 wrappedKey = malloc(wrappedKeyLen * sizeof (CK_BYTE));
1347 if (wrappedKey == NULL) {
1348 rv = CKR_HOST_MEMORY;
1349 goto finish;
1350 }
1351
1352 /* do the actual key wrapping */
1353 rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
1354 src_slot_session->hSession, &wrappingMech,
1355 wrappingKey, slot_object->hObject, wrappedKey, &wrappedKeyLen);
1356
1357 if (rv != CKR_OK) {
1358 goto finish;
1359 }
1360
1361 /* explicitly force the unwrapped object to be not sensitive */
1362 unwrap_template[2].type = CKA_SENSITIVE;
1363 unwrap_template[2].pValue = &falsevalue;
1364 unwrap_template[2].ulValueLen = sizeof (falsevalue);
1365
1366 unwrap_template[3].type = CKA_TOKEN;
1367 unwrap_template[3].pValue = &falsevalue;
1368 unwrap_template[3].ulValueLen = sizeof (falsevalue);
1369
1370 unwrap_template_size =
1371 sizeof (unwrap_template) / sizeof (CK_ATTRIBUTE);
1372
1373 if (!wrap_info.dst_supports) {
1374 /*
1375 * if we know for sure that the destination slot doesn't
1376 * support the wrapping mechanism, no point in trying.
1377 * go directly to unwrap in source slot, and create key
1378 * in destination
1379 */
1380 goto unwrap_in_source;
1381 }
1382
1383 /* create the unwrapping key in destination slot */
1384 if (wrap_info.key_type == CKK_RSA) {
1385 /* for RSA key, the unwrapping key need to be private key */
1386 wrap_info.class = CKO_PRIVATE_KEY;
1387 }
1388 rv = create_wrap_unwrap_key(dst_slot_session,
1389 &unwrappingKey, &wrap_info, key_data, key_len);
1390 if (rv != CKR_OK) {
1391 goto finish;
1392 }
1393
1394 rv = FUNCLIST(dst_slot_session->fw_st_id)->C_UnwrapKey(
1395 dst_slot_session->hSession, &wrappingMech,
1396 unwrappingKey, wrappedKey, wrappedKeyLen, unwrap_template,
1397 unwrap_template_size, &(new_clone->hObject));
1398
1399 if (rv != CKR_OK) {
1400 unwrap_in_source:
1401
1402 /*
1403 * There seemed to be a problem with unwrapping in the
1404 * destination slot.
1405 * Try to do the unwrap in the src slot so it becomes
1406 * a non-sensitive object, then, get all the attributes
1407 * and create the object in the destination slot
1408 */
1409
1410
1411 if (wrap_info.class == CKO_SECRET_KEY) {
1412 /* unwrap with same key used for wrapping */
1413 rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
1414 src_slot_session->hSession,
1415 &wrappingMech, wrappingKey, wrappedKey,
1416 wrappedKeyLen, unwrap_template,
1417 unwrap_template_size, &(unwrapped_obj));
1418 } else {
1419 /*
1420 * If the object is wrapping with RSA public key, need
1421 * need to create RSA private key for unwrapping
1422 */
1423 wrap_info.class = CKO_PRIVATE_KEY;
1424 rv = create_wrap_unwrap_key(src_slot_session,
1425 &unwrappingKey, &wrap_info, key_data, key_len);
1426 if (rv != CKR_OK) {
1427 goto finish;
1428 }
1429 rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
1430 src_slot_session->hSession,
1431 &wrappingMech, unwrappingKey, wrappedKey,
1432 wrappedKeyLen, unwrap_template,
1433 unwrap_template_size, &(unwrapped_obj));
1434 }
1435
1436
1437 if (rv != CKR_OK) {
1438 goto finish;
1439 }
1440
1441 rv = meta_session_alloc(&tmp_meta_session);
1442 if (rv != CKR_OK) {
1443 goto finish;
1444 }
1445
1446 tmp_meta_session->session_flags = CKF_SERIAL_SESSION;
1447
1448 rv = meta_object_alloc(tmp_meta_session, &tmp_meta_obj);
1449 if (rv != CKR_OK) {
1450 goto finish;
1451 }
1452
1453 rv = meta_slot_object_alloc(&tmp_slot_obj);
1454 if (rv != CKR_OK) {
1455 goto finish;
1456 }
1457
1458 tmp_meta_obj->master_clone_slotnum = src_slot_session->slotnum;
1459 tmp_slot_obj->hObject = unwrapped_obj;
1460 tmp_meta_obj->clones[tmp_meta_obj->master_clone_slotnum]
1461 = tmp_slot_obj;
1462 meta_slot_object_activate(tmp_slot_obj, src_slot_session,
1463 B_FALSE);
1464 tmp_slot_obj = NULL;
1465
1466 rv = clone_by_create(tmp_meta_obj, new_clone,
1467 dst_slot_session);
1468 if (rv != CKR_OK) {
1469 goto finish;
1470 }
1471 }
1472
1473 finish:
1474 if (unwrappingKey) {
1475 (void) FUNCLIST(dst_slot_session->fw_st_id)->C_DestroyObject(
1476 dst_slot_session->hSession, unwrappingKey);
1477 }
1478
1479 if (wrappingKey) {
1480 (void) FUNCLIST(src_slot_session->fw_st_id)->C_DestroyObject(
1481 src_slot_session->hSession, wrappingKey);
1482 }
1483
1484 if (tmp_slot_obj) {
1485 (void) meta_slot_object_dealloc(tmp_slot_obj);
1486 }
1487
1488 if (tmp_meta_obj) {
1489 (void) meta_object_dealloc(tmp_meta_session, tmp_meta_obj,
1490 B_TRUE);
1491 }
1492
1493 if (tmp_meta_session) {
1494 (void) meta_session_dealloc(tmp_meta_session);
1495 }
1496
1497 if (wrappedKey) {
1498 freezero(wrappedKey, wrappedKeyLen);
1499 }
1500
1501 if (src_slot_session) {
1502 meta_release_slot_session(src_slot_session);
1503 }
1504
1505 return (rv);
1506
1507 }
1508
1509
1510 /*
1511 * meta_object_get_clone
1512 *
1513 * Creates a "clone" of a metaobject on the specified slot. A clone is a
1514 * copy of the object.
1515 *
1516 * Clones are cached, so that they can be reused with subsequent operations.
1517 */
1518 CK_RV
meta_object_get_clone(meta_object_t * object,CK_ULONG slot_num,slot_session_t * slot_session,slot_object_t ** clone)1519 meta_object_get_clone(meta_object_t *object,
1520 CK_ULONG slot_num, slot_session_t *slot_session, slot_object_t **clone)
1521 {
1522 CK_RV rv = CKR_OK;
1523 slot_object_t *newclone = NULL;
1524
1525 /* Does a clone already exist? */
1526 if (object->clones[slot_num] != NULL) {
1527 *clone = object->clones[slot_num];
1528 return (CKR_OK);
1529 }
1530
1531 if ((object->isSensitive) && (object->isToken) &&
1532 (!metaslot_auto_key_migrate)) {
1533 /*
1534 * if the object is a sensitive token object, and auto
1535 * key migrate is not allowed, will not create the clone
1536 * in another slot
1537 */
1538 return (CKR_FUNCTION_FAILED);
1539 }
1540
1541 /* object attributes can't be extracted and attributes are not known */
1542 if ((!object->isExtractable) && (object->attributes == NULL)) {
1543 return (CKR_FUNCTION_FAILED);
1544 }
1545
1546 (void) pthread_mutex_lock(&object->clone_create_lock);
1547
1548 /* Maybe someone just created one? */
1549 if (object->clones[slot_num] != NULL) {
1550 *clone = object->clones[slot_num];
1551 goto finish;
1552 }
1553
1554 /*
1555 * has an attempt already been made to create this object in
1556 * slot? If yes, and there's no clone, as indicated above,
1557 * that means this object can't be created in this slot.
1558 */
1559 if (object->tried_create_clone[slot_num]) {
1560 (void) pthread_mutex_unlock(&object->clone_create_lock);
1561 return (CKR_FUNCTION_FAILED);
1562 }
1563
1564 rv = meta_slot_object_alloc(&newclone);
1565 if (rv != CKR_OK)
1566 goto finish;
1567
1568 object->tried_create_clone[slot_num] = B_TRUE;
1569
1570 /*
1571 * If this object is sensitive and we do not have not copied in the
1572 * attributes via FreeObject functionality, then we need to wrap it off
1573 * the provider. If we do have attributes, we can just create the
1574 * clone
1575 */
1576
1577 if (object->isSensitive && object->attributes == NULL) {
1578 rv = clone_by_wrap(object, newclone, slot_session);
1579 } else {
1580 rv = clone_by_create(object, newclone, slot_session);
1581 }
1582
1583 if (rv != CKR_OK) {
1584 goto finish;
1585 }
1586
1587 object->clones[slot_num] = newclone;
1588 meta_slot_object_activate(newclone, slot_session, object->isToken);
1589
1590 *clone = newclone;
1591 newclone = NULL;
1592 finish:
1593 (void) pthread_mutex_unlock(&object->clone_create_lock);
1594
1595 if (newclone)
1596 meta_slot_object_dealloc(newclone);
1597
1598 return (rv);
1599 }
1600
1601
1602 /*
1603 * meta_setup_clone_template
1604 *
1605 * Create a clone template for the specified object.
1606 */
1607 static CK_RV
meta_clone_template_setup(meta_object_t * object,const generic_attr_t * attributes,size_t num_attributes)1608 meta_clone_template_setup(meta_object_t *object,
1609 const generic_attr_t *attributes, size_t num_attributes)
1610 {
1611 CK_RV rv = CKR_OK;
1612 CK_ATTRIBUTE *clone_template;
1613 size_t i, c = 0;
1614
1615 clone_template = malloc(num_attributes * sizeof (CK_ATTRIBUTE));
1616 if (clone_template == NULL) {
1617 rv = CKR_HOST_MEMORY;
1618 goto finish;
1619 }
1620
1621 /* Don't allow attributes to change while we look at them. */
1622 (void) pthread_rwlock_rdlock(&object->attribute_lock);
1623
1624 for (i = 0; i < num_attributes; i++) {
1625 if (!attributes[i].isCloneAttr ||
1626 (attributes[i].attribute.type == CKA_TOKEN &&
1627 object->isFreeToken == FREE_DISABLED)) {
1628 continue;
1629 }
1630 if ((!(attributes[i].hasValueForClone)) &&
1631 (attributes[i].canBeEmptyValue)) {
1632 continue;
1633 }
1634
1635 clone_template[c].type = attributes[i].attribute.type;
1636 clone_template[c].ulValueLen =
1637 attributes[i].attribute.ulValueLen;
1638 /* Allocate space to store the attribute value. */
1639 clone_template[c].pValue = malloc(clone_template[c].ulValueLen);
1640 if (clone_template[c].pValue == NULL) {
1641 free(clone_template);
1642 rv = CKR_HOST_MEMORY;
1643 (void) pthread_rwlock_unlock(&object->attribute_lock);
1644 goto finish;
1645 }
1646
1647 (void) memcpy(clone_template[c].pValue,
1648 object->attributes[i].attribute.pValue,
1649 clone_template[c].ulValueLen);
1650 c++;
1651 }
1652
1653 (void) pthread_rwlock_unlock(&object->attribute_lock);
1654
1655 object->clone_template = clone_template;
1656 object->clone_template_size = c;
1657
1658 finish:
1659 return (rv);
1660 }
1661
1662
1663 /*
1664 * meta_object_find_by_handle
1665 *
1666 * Search for an existing metaobject, using the object handle of a clone
1667 * on a particular slot.
1668 *
1669 * Returns a matching metaobject, or NULL if no match was found.
1670 */
1671 meta_object_t *
meta_object_find_by_handle(CK_OBJECT_HANDLE hObject,CK_ULONG slotnum,boolean_t token_only)1672 meta_object_find_by_handle(CK_OBJECT_HANDLE hObject, CK_ULONG slotnum,
1673 boolean_t token_only)
1674 {
1675 meta_object_t *object = NULL, *tmp_obj;
1676 meta_session_t *session;
1677
1678 if (!token_only) {
1679 (void) pthread_rwlock_rdlock(&meta_sessionlist_lock);
1680 session = meta_sessionlist_head;
1681 while (session != NULL) {
1682 /* lock the objects list while we look at it */
1683 (void) pthread_rwlock_rdlock(
1684 &(session->object_list_lock));
1685 tmp_obj = session->object_list_head;
1686 while (tmp_obj != NULL) {
1687 slot_object_t *slot_object;
1688
1689 (void) pthread_rwlock_rdlock(
1690 &(tmp_obj->object_lock));
1691 slot_object = tmp_obj->clones[slotnum];
1692 if (slot_object != NULL) {
1693 if (slot_object->hObject == hObject) {
1694 object = tmp_obj;
1695 }
1696 }
1697 (void) pthread_rwlock_unlock(
1698 &(tmp_obj->object_lock));
1699 if (object != NULL) {
1700 break;
1701 }
1702 tmp_obj = tmp_obj->next;
1703 }
1704 (void) pthread_rwlock_unlock(
1705 &(session->object_list_lock));
1706 if (object != NULL) {
1707 break;
1708 }
1709 session = session->next;
1710 }
1711 (void) pthread_rwlock_unlock(&meta_sessionlist_lock);
1712 }
1713
1714 if (object != NULL) {
1715 /* found the object, no need to look further */
1716 return (object);
1717 }
1718
1719 /*
1720 * Look at list of token objects
1721 */
1722 (void) pthread_rwlock_rdlock(&tokenobject_list_lock);
1723 tmp_obj = tokenobject_list_head;
1724
1725 while (tmp_obj != NULL) {
1726 slot_object_t *slot_object;
1727
1728 (void) pthread_rwlock_rdlock(&(tmp_obj->object_lock));
1729 slot_object = tmp_obj->clones[slotnum];
1730 if (slot_object != NULL) {
1731 if (slot_object->hObject == hObject)
1732 object = tmp_obj;
1733 }
1734 (void) pthread_rwlock_unlock(&(tmp_obj->object_lock));
1735 if (object != NULL) {
1736 break;
1737 }
1738 tmp_obj = tmp_obj->next;
1739 }
1740 (void) pthread_rwlock_unlock(&tokenobject_list_lock);
1741
1742 return (object);
1743 }
1744
1745 CK_RV
meta_token_object_deactivate(token_obj_type_t token_type)1746 meta_token_object_deactivate(token_obj_type_t token_type)
1747 {
1748 meta_object_t *object, *tmp_object;
1749 CK_RV save_rv = CKR_OK, rv;
1750
1751 /* get a write lock on the token object list */
1752 (void) pthread_rwlock_wrlock(&tokenobject_list_lock);
1753
1754 object = tokenobject_list_head;
1755
1756 /* go through each object and delete the one with matching type */
1757 while (object != NULL) {
1758 tmp_object = object->next;
1759
1760 if ((token_type == ALL_TOKEN) ||
1761 ((object->isPrivate) && (token_type == PRIVATE_TOKEN)) ||
1762 ((!object->isPrivate) && (token_type == PUBLIC_TOKEN))) {
1763 rv = meta_object_deactivate(object, B_TRUE, B_FALSE);
1764 if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
1765 save_rv = rv;
1766 goto finish;
1767 }
1768 rv = meta_object_dealloc(NULL, object, B_FALSE);
1769 if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
1770 save_rv = rv;
1771 goto finish;
1772 }
1773 }
1774 object = tmp_object;
1775 }
1776 finish:
1777 (void) pthread_rwlock_unlock(&tokenobject_list_lock);
1778 return (save_rv);
1779 }
1780
1781 /*
1782 * This function adds the to-be-freed meta object to a linked list.
1783 * When the number of objects queued in the linked list reaches the
1784 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
1785 * object (FIFO) in the list.
1786 */
1787 void
meta_object_delay_free(meta_object_t * objp)1788 meta_object_delay_free(meta_object_t *objp)
1789 {
1790 meta_object_t *tmp;
1791
1792 (void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
1793
1794 /* Add the newly deleted object at the end of the list */
1795 objp->next = NULL;
1796 if (obj_delay_freed.first == NULL) {
1797 obj_delay_freed.last = objp;
1798 obj_delay_freed.first = objp;
1799 } else {
1800 obj_delay_freed.last->next = objp;
1801 obj_delay_freed.last = objp;
1802 }
1803
1804 if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
1805 /*
1806 * Free the first object in the list only if
1807 * the total count reaches maximum threshold.
1808 */
1809 obj_delay_freed.count--;
1810 tmp = obj_delay_freed.first->next;
1811 free(obj_delay_freed.first);
1812 obj_delay_freed.first = tmp;
1813 }
1814 (void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
1815 }
1816
1817
1818 /*
1819 * This function checks if the object passed can be a freeobject.
1820 *
1821 * If there is more than one provider that supports the supported freeobject
1822 * mechanisms then allow freeobjects to be an option.
1823 */
1824
1825 boolean_t
meta_freeobject_check(meta_session_t * session,meta_object_t * object,CK_MECHANISM * pMech,CK_ATTRIBUTE * tmpl,CK_ULONG tmpl_len,CK_KEY_TYPE keytype)1826 meta_freeobject_check(meta_session_t *session, meta_object_t *object,
1827 CK_MECHANISM *pMech, CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len,
1828 CK_KEY_TYPE keytype)
1829 {
1830 mech_support_info_t *info = &(session->mech_support_info);
1831
1832 /*
1833 * If key migration is turned off, or the object does not has any of
1834 * the required flags and there is only one slot, then we don't need
1835 * FreeObjects.
1836 */
1837 if (!metaslot_auto_key_migrate ||
1838 (!object->isToken && !object->isSensitive &&
1839 meta_slotManager_get_slotcount() < 2))
1840 goto failure;
1841
1842 /*
1843 * If this call is for key generation, check pMech for supported
1844 * FreeObject mechs
1845 */
1846 if (pMech != NULL) {
1847 if (pMech->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN ||
1848 pMech->mechanism == CKM_EC_KEY_PAIR_GEN ||
1849 pMech->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN ||
1850 pMech->mechanism == CKM_DH_PKCS_DERIVE)
1851 info->mech = pMech->mechanism;
1852 else
1853 goto failure;
1854
1855 /*
1856 * If this call is for an object creation, look inside the template
1857 * for supported FreeObject mechs
1858 */
1859 } else if (tmpl_len > 0) {
1860 if (!get_template_ulong(CKA_KEY_TYPE, tmpl, tmpl_len, &keytype))
1861 goto failure;
1862
1863 switch (keytype) {
1864 case CKK_RSA:
1865 info->mech = CKM_RSA_PKCS_KEY_PAIR_GEN;
1866 break;
1867 case CKK_EC:
1868 info->mech = CKM_EC_KEY_PAIR_GEN;
1869 break;
1870 case CKK_DH:
1871 info->mech = CKM_DH_PKCS_KEY_PAIR_GEN;
1872 break;
1873 default:
1874 goto failure;
1875 }
1876 } else
1877 goto failure;
1878
1879 /* Get the slot that support this mech... */
1880 if (meta_mechManager_get_slots(info, B_FALSE, NULL) != CKR_OK)
1881 goto failure;
1882
1883 /*
1884 * If there is only one slot with the mech or the first slot in
1885 * the list is the keystore slot, we should bail.
1886 */
1887 if (info->num_supporting_slots < 2 &&
1888 info->supporting_slots[0]->slotnum == get_keystore_slotnum())
1889 goto failure;
1890
1891 if (object->isToken)
1892 object->isFreeToken = FREE_ALLOWED_KEY;
1893 else
1894 object->isFreeToken = FREE_DISABLED;
1895
1896 object->isFreeObject = FREE_ALLOWED_KEY;
1897
1898 return (B_TRUE);
1899
1900 failure:
1901 object->isFreeToken = FREE_DISABLED;
1902 object->isFreeObject = FREE_DISABLED;
1903 return (B_FALSE);
1904 }
1905
1906 /*
1907 * This function assumes meta_freeobject_check() has just been called and set
1908 * the isFreeObject and/or isFreeToken vars to FREE_ALLOWED_KEY.
1909 *
1910 * If the template value for CKA_PRIVATE, CKA_SENSITIVE and/or CKA_TOKEN are
1911 * true, then isFreeObject is fully enabled. In addition isFreeToken is
1912 * enabled if is CKA_TOKEN true.
1913 *
1914 * If create is true, we are doing a C_CreateObject operation and don't
1915 * handle CKA_PRIVATE & CKA_SENSITIVE flags, we only care about CKA_TOKEN.
1916 */
1917
1918 boolean_t
meta_freeobject_set(meta_object_t * object,CK_ATTRIBUTE * tmpl,CK_ULONG tmpl_len,boolean_t create)1919 meta_freeobject_set(meta_object_t *object, CK_ATTRIBUTE *tmpl,
1920 CK_ULONG tmpl_len, boolean_t create)
1921 {
1922
1923 /* This check should never be true, if it is, it's a bug */
1924 if (object->isFreeObject < FREE_ALLOWED_KEY)
1925 return (B_FALSE);
1926
1927 if (!create) {
1928 /* Turn off the Sensitive flag */
1929 if (object->isSensitive) {
1930 if (set_template_boolean(CKA_SENSITIVE, tmpl, tmpl_len,
1931 B_TRUE, &falsevalue) == -1)
1932 goto failure;
1933
1934 object->isFreeObject = FREE_ENABLED;
1935 }
1936
1937 /* Turn off the Private flag */
1938 if (object->isPrivate) {
1939 if (set_template_boolean(CKA_PRIVATE, tmpl, tmpl_len,
1940 B_TRUE, &falsevalue) == -1)
1941 goto failure;
1942
1943 object->isFreeObject = FREE_ENABLED;
1944 }
1945 }
1946
1947 if (object->isToken) {
1948 object->isToken = B_FALSE;
1949 object->isFreeToken = FREE_ENABLED;
1950 object->isFreeObject = FREE_ENABLED;
1951 } else
1952 object->isFreeToken = FREE_DISABLED;
1953
1954 /*
1955 * If isFreeObject is not in the FREE_ENABLED state yet, it can be
1956 * turned off because the object doesn't not need to be a FreeObject.
1957 */
1958 if (object->isFreeObject == FREE_ALLOWED_KEY)
1959 object->isFreeObject = FREE_DISABLED;
1960
1961 return (B_TRUE);
1962
1963 failure:
1964 object->isFreeToken = FREE_DISABLED;
1965 object->isFreeObject = FREE_DISABLED;
1966 return (B_FALSE);
1967 }
1968
1969 /*
1970 * This function sets the CKA_TOKEN flag on a given object template depending
1971 * if the slot being used is a keystore.
1972 *
1973 * If the object is a token, but the slot is not the system keystore or has
1974 * no keystore, then set the template to token = false; otherwise it's true.
1975 * In addition we know ahead of time what the value is, so if the value is
1976 * already correct, bypass the setting function
1977 */
1978 CK_RV
meta_freetoken_set(CK_ULONG slot_num,CK_BBOOL * current_value,CK_ATTRIBUTE * tmpl,CK_ULONG tmpl_len)1979 meta_freetoken_set(CK_ULONG slot_num, CK_BBOOL *current_value,
1980 CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len)
1981 {
1982
1983 if (slot_num == get_keystore_slotnum()) {
1984 if (*current_value == TRUE)
1985 return (CKR_OK);
1986
1987 if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
1988 &truevalue) == -1)
1989 return (CKR_FUNCTION_FAILED);
1990
1991 } else {
1992
1993 if (*current_value == FALSE)
1994 return (CKR_OK);
1995
1996 if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
1997 &falsevalue) == -1)
1998 return (CKR_FUNCTION_FAILED);
1999
2000 *current_value = FALSE;
2001 }
2002
2003 return (CKR_OK);
2004 }
2005
2006 /*
2007 * Cloning function for meta_freeobject_clone() to use. This function
2008 * is streamlined because we know what the object is and this should
2009 * not be called as a generic cloner.
2010 */
2011
2012 static CK_RV
meta_freeobject_clone_maker(meta_session_t * session,meta_object_t * object,CK_ULONG slotnum)2013 meta_freeobject_clone_maker(meta_session_t *session, meta_object_t *object,
2014 CK_ULONG slotnum)
2015 {
2016
2017 slot_object_t *slot_object = NULL;
2018 slot_session_t *slot_session = NULL;
2019 CK_RV rv;
2020
2021 rv = meta_slot_object_alloc(&slot_object);
2022 if (rv != CKR_OK)
2023 goto cleanup;
2024
2025 rv = meta_get_slot_session(slotnum, &slot_session,
2026 session->session_flags);
2027 if (rv != CKR_OK)
2028 goto cleanup;
2029
2030 rv = clone_by_create(object, slot_object, slot_session);
2031 if (rv == CKR_OK) {
2032 object->clones[slotnum] = slot_object;
2033 meta_slot_object_activate(slot_object, slot_session, B_TRUE);
2034 }
2035
2036 cleanup:
2037 meta_release_slot_session(slot_session);
2038 return (rv);
2039
2040 }
2041
2042 /*
2043 * This function is called when a object is a FreeObject.
2044 *
2045 * What we are given is an object that has been generated on a provider
2046 * that is not its final usage place. That maybe because:
2047 * 1) it's a token and needs to be stored in keystore.
2048 * 2) it was to be a private/sensitive object that we modified so we could know
2049 * the important attributes for cloning before we make it private/sensitive.
2050 */
2051
2052 boolean_t
meta_freeobject_clone(meta_session_t * session,meta_object_t * object)2053 meta_freeobject_clone(meta_session_t *session, meta_object_t *object)
2054 {
2055 CK_RV rv;
2056 CK_ULONG keystore_slotnum;
2057 CK_ATTRIBUTE attr[2];
2058 boolean_t failover = B_FALSE;
2059
2060 if (object->attributes == NULL) {
2061 rv = meta_object_copyin(object);
2062 if (rv != CKR_OK)
2063 return (rv);
2064 }
2065
2066 if (object->isPrivate) {
2067 CK_OBJECT_HANDLE new_clone;
2068 CK_ULONG slotnum = object->master_clone_slotnum;
2069 slot_session_t *slot_session;
2070
2071 attr[0].type = CKA_PRIVATE;
2072 attr[0].pValue = &truevalue;
2073 attr[0].ulValueLen = sizeof (truevalue);
2074
2075 /* Set the master attribute list */
2076 rv = attribute_set_value(attr, object->attributes,
2077 object->num_attributes);
2078 if (rv > 0)
2079 return (CKR_FUNCTION_FAILED);
2080
2081 /* Get a slot session */
2082 rv = meta_get_slot_session(slotnum, &slot_session,
2083 session->session_flags);
2084 if (rv > 0)
2085 return (rv);
2086
2087 /* Create the new CKA_PRIVATE one */
2088 rv = FUNCLIST(slot_session->fw_st_id)->\
2089 C_CopyObject(slot_session->hSession,
2090 object->clones[slotnum]->hObject, attr, 1, &new_clone);
2091
2092 if (rv == CKR_USER_NOT_LOGGED_IN) {
2093 /*
2094 * If the CopyObject fails, we may be using a provider
2095 * that has a keystore that is not the default
2096 * keystore set in metaslot or has object management
2097 * abilities. In which case we should write this
2098 * object to metaslot's keystore and let the failover.
2099 * rest of the function know we've changed providers.
2100 */
2101 failover = B_TRUE;
2102 keystore_slotnum = get_keystore_slotnum();
2103 if (object->clones[keystore_slotnum] == NULL) {
2104 rv = meta_freeobject_clone_maker(session,
2105 object, keystore_slotnum);
2106 if (rv != CKR_OK) {
2107 goto failure;
2108 }
2109 }
2110 object->master_clone_slotnum = keystore_slotnum;
2111
2112 } else if (rv != CKR_OK) {
2113 meta_release_slot_session(slot_session);
2114 goto failure;
2115 }
2116 /* Remove the old object */
2117 rv = FUNCLIST(slot_session->fw_st_id)-> \
2118 C_DestroyObject(slot_session->hSession,
2119 object->clones[slotnum]->hObject);
2120 if (rv != CKR_OK) {
2121 meta_release_slot_session(slot_session);
2122 goto failure;
2123 }
2124
2125 if (!failover)
2126 object->clones[slotnum]->hObject = new_clone;
2127 else
2128 object->clones[slotnum] = NULL;
2129
2130 meta_release_slot_session(slot_session);
2131
2132 }
2133
2134 if (object->isSensitive) {
2135 slot_session_t *slot_session;
2136 CK_ULONG slotnum = object->master_clone_slotnum;
2137
2138 attr[0].type = CKA_SENSITIVE;
2139 attr[0].pValue = &truevalue;
2140 attr[0].ulValueLen = sizeof (truevalue);
2141 rv = attribute_set_value(attr, object->attributes,
2142 object->num_attributes);
2143 if (rv != CKR_OK)
2144 goto failure;
2145
2146 rv = meta_get_slot_session(slotnum, &slot_session,
2147 session->session_flags);
2148 if (rv == CKR_OK) {
2149 rv = FUNCLIST(slot_session->fw_st_id)-> \
2150 C_SetAttributeValue(slot_session->hSession,
2151 object->clones[slotnum]->hObject, attr, 1);
2152
2153 meta_release_slot_session(slot_session);
2154 }
2155 }
2156
2157 if (object->isFreeToken == FREE_ENABLED || failover) {
2158 keystore_slotnum = get_keystore_slotnum();
2159 if (object->clones[keystore_slotnum] == NULL) {
2160 rv = meta_freeobject_clone_maker(session, object,
2161 keystore_slotnum);
2162 if (rv != CKR_OK)
2163 goto failure;
2164
2165 object->master_clone_slotnum = keystore_slotnum;
2166 }
2167 object->isFreeToken = FREE_ENABLED;
2168 }
2169
2170 object->isFreeObject = FREE_ENABLED;
2171 return (CKR_OK);
2172
2173 failure:
2174 object->isFreeToken = FREE_DISABLED;
2175 object->isFreeObject = FREE_DISABLED;
2176 return (rv);
2177
2178 }
2179