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