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