xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelUtil.c (revision d321a33cdd896e6b211d113a33698dd76e89b861)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <cryptoutil.h>
32 #include <errno.h>
33 #include <security/cryptoki.h>
34 #include <sys/crypto/common.h>
35 #include <sys/crypto/ioctl.h>
36 #include "kernelGlobal.h"
37 #include "kernelObject.h"
38 #include "kernelSlot.h"
39 
40 #define	ENCODE_ATTR(type, value, len) {		\
41 	cur_attr->oa_type = type;		\
42 	(void) memcpy(ptr, value, len);		\
43 	cur_attr->oa_value = ptr;		\
44 	cur_attr->oa_value_len = len;		\
45 	cur_attr++;				\
46 }
47 
48 #define	CRYPTO_LAST_ERROR	(CRYPTO_WEAK_KEY + 1)
49 
50 /*
51  * In order to fit everything on one line, the 'CRYPTO_' prefix
52  * has been dropped from the KCF #defines, e.g.
53  * CRYPTO_SUCCESS becomes SUCCESS.
54  */
55 
56 static CK_RV error_number_table[CRYPTO_LAST_ERROR] = {
57 CKR_OK,					/* SUCCESS */
58 CKR_CANCEL,				/* CANCEL */
59 CKR_HOST_MEMORY,			/* HOST_MEMORY */
60 CKR_GENERAL_ERROR,			/* GENERAL_ERROR */
61 CKR_FUNCTION_FAILED,			/* FAILED */
62 CKR_ARGUMENTS_BAD,			/* ARGUMENTS_BAD */
63 CKR_ATTRIBUTE_READ_ONLY,		/* ATTRIBUTE_READ_ONLY */
64 CKR_ATTRIBUTE_SENSITIVE,		/* ATTRIBUTE_SENSITIVE */
65 CKR_ATTRIBUTE_TYPE_INVALID,		/* ATTRIBUTE_TYPE_INVALID */
66 CKR_ATTRIBUTE_VALUE_INVALID,		/* ATTRIBUTE_VALUE_INVALID */
67 CKR_FUNCTION_FAILED,			/* CANCELED */
68 CKR_DATA_INVALID,			/* DATA_INVALID */
69 CKR_DATA_LEN_RANGE,			/* DATA_LEN_RANGE */
70 CKR_DEVICE_ERROR,			/* DEVICE_ERROR */
71 CKR_DEVICE_MEMORY,			/* DEVICE_MEMORY */
72 CKR_DEVICE_REMOVED,			/* DEVICE_REMOVED */
73 CKR_ENCRYPTED_DATA_INVALID,		/* ENCRYPTED_DATA_INVALID */
74 CKR_ENCRYPTED_DATA_LEN_RANGE,		/* ENCRYPTED_DATA_LEN_RANGE */
75 CKR_KEY_HANDLE_INVALID,			/* KEY_HANDLE_INVALID */
76 CKR_KEY_SIZE_RANGE,			/* KEY_SIZE_RANGE */
77 CKR_KEY_TYPE_INCONSISTENT,		/* KEY_TYPE_INCONSISTENT */
78 CKR_KEY_NOT_NEEDED,			/* KEY_NOT_NEEDED */
79 CKR_KEY_CHANGED,			/* KEY_CHANGED */
80 CKR_KEY_NEEDED,				/* KEY_NEEDED */
81 CKR_KEY_INDIGESTIBLE,			/* KEY_INDIGESTIBLE */
82 CKR_KEY_FUNCTION_NOT_PERMITTED,		/* KEY_FUNCTION_NOT_PERMITTED */
83 CKR_KEY_NOT_WRAPPABLE,			/* KEY_NOT_WRAPPABLE */
84 CKR_KEY_UNEXTRACTABLE,			/* KEY_UNEXTRACTABLE */
85 CKR_MECHANISM_INVALID,			/* MECHANISM_INVALID */
86 CKR_MECHANISM_PARAM_INVALID,		/* MECHANISM_PARAM_INVALID */
87 CKR_OBJECT_HANDLE_INVALID,		/* OBJECT_HANDLE_INVALID */
88 CKR_OPERATION_ACTIVE,			/* OPERATION_ACTIVE */
89 CKR_OPERATION_NOT_INITIALIZED,		/* OPERATION_NOT_INITIALIZED */
90 CKR_PIN_INCORRECT,			/* PIN_INCORRECT */
91 CKR_PIN_INVALID,			/* PIN_INVALID */
92 CKR_PIN_LEN_RANGE,			/* PIN_LEN_RANGE */
93 CKR_PIN_EXPIRED,			/* PIN_EXPIRED */
94 CKR_PIN_LOCKED,				/* PIN_LOCKED */
95 CKR_SESSION_CLOSED,			/* SESSION_CLOSED */
96 CKR_SESSION_COUNT,			/* SESSION_COUNT */
97 CKR_SESSION_HANDLE_INVALID,		/* SESSION_HANDLE_INVALID */
98 CKR_SESSION_READ_ONLY,			/* SESSION_READ_ONLY */
99 CKR_SESSION_EXISTS,			/* SESSION_EXISTS */
100 CKR_SESSION_READ_ONLY_EXISTS,		/* SESSION_READ_ONLY_EXISTS */
101 CKR_SESSION_READ_WRITE_SO_EXISTS,	/* SESSION_READ_WRITE_SO_EXISTS */
102 CKR_SIGNATURE_INVALID,			/* SIGNATURE_INVALID */
103 CKR_SIGNATURE_LEN_RANGE,		/* SIGNATURE_LEN_RANGE */
104 CKR_TEMPLATE_INCOMPLETE,		/* TEMPLATE_INCOMPLETE */
105 CKR_TEMPLATE_INCONSISTENT,		/* TEMPLATE_INCONSISTENT */
106 CKR_UNWRAPPING_KEY_HANDLE_INVALID,	/* UNWRAPPING_KEY_HANDLE_INVALID */
107 CKR_UNWRAPPING_KEY_SIZE_RANGE,		/* UNWRAPPING_KEY_SIZE_RANGE */
108 CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,	/* UNWRAPPING_KEY_TYPE_INCONSISTENT */
109 CKR_USER_ALREADY_LOGGED_IN,		/* USER_ALREADY_LOGGED_IN */
110 CKR_USER_NOT_LOGGED_IN,			/* USER_NOT_LOGGED_IN */
111 CKR_USER_PIN_NOT_INITIALIZED,		/* USER_PIN_NOT_INITIALIZED */
112 CKR_USER_TYPE_INVALID,			/* USER_TYPE_INVALID */
113 CKR_USER_ANOTHER_ALREADY_LOGGED_IN,	/* USER_ANOTHER_ALREADY_LOGGED_IN */
114 CKR_USER_TOO_MANY_TYPES,		/* USER_TOO_MANY_TYPES */
115 CKR_WRAPPED_KEY_INVALID,		/* WRAPPED_KEY_INVALID */
116 CKR_WRAPPED_KEY_LEN_RANGE,		/* WRAPPED_KEY_LEN_RANGE */
117 CKR_WRAPPING_KEY_HANDLE_INVALID,	/* WRAPPING_KEY_HANDLE_INVALID */
118 CKR_WRAPPING_KEY_SIZE_RANGE,		/* WRAPPING_KEY_SIZE_RANGE */
119 CKR_WRAPPING_KEY_TYPE_INCONSISTENT,	/* WRAPPING_KEY_TYPE_INCONSISTENT */
120 CKR_RANDOM_SEED_NOT_SUPPORTED,		/* RANDOM_SEED_NOT_SUPPORTED */
121 CKR_RANDOM_NO_RNG,			/* RANDOM_NO_RNG */
122 CKR_DOMAIN_PARAMS_INVALID,		/* DOMAIN_PARAMS_INVALID */
123 CKR_BUFFER_TOO_SMALL,			/* BUFFER_TOO_SMALL */
124 CKR_INFORMATION_SENSITIVE,		/* INFORMATION_SENSITIVE */
125 CKR_FUNCTION_NOT_SUPPORTED,		/* NOT_SUPPORTED */
126 CKR_GENERAL_ERROR,			/* QUEUED */
127 CKR_GENERAL_ERROR,			/* BUFFER_TOO_BIG */
128 CKR_OPERATION_NOT_INITIALIZED,		/* INVALID_CONTEXT */
129 CKR_GENERAL_ERROR,			/* INVALID_MAC */
130 CKR_GENERAL_ERROR,			/* MECH_NOT_SUPPORTED */
131 CKR_GENERAL_ERROR,			/* INCONSISTENT_ATTRIBUTE */
132 CKR_GENERAL_ERROR,			/* NO_PERMISSION */
133 CKR_SLOT_ID_INVALID,			/* INVALID_PROVIDER_ID */
134 CKR_GENERAL_ERROR,			/* VERSION_MISMATCH */
135 CKR_GENERAL_ERROR,			/* BUSY */
136 CKR_GENERAL_ERROR,			/* UNKNOWN_PROVIDER */
137 CKR_GENERAL_ERROR,			/* MODVERIFICATION_FAILED */
138 CKR_GENERAL_ERROR,			/* OLD_CTX_TEMPLATE */
139 CKR_GENERAL_ERROR,			/* WEAK_KEY */
140 };
141 
142 /*
143  * Map KCF error codes into PKCS11 error codes.
144  */
145 CK_RV
146 crypto2pkcs11_error_number(uint_t n)
147 {
148 	if (n > CRYPTO_LAST_ERROR)
149 		return (CKR_GENERAL_ERROR);
150 
151 	return (error_number_table[n]);
152 }
153 
154 #define	MECH_HASH(type)	(((uintptr_t)type) % KMECH_HASHTABLE_SIZE)
155 /*
156  * Serialize writes to the hash table. We don't need a per bucket lock as
157  * there are only a few writes and we don't need the lock for reads.
158  */
159 static pthread_mutex_t mechhash_mutex = PTHREAD_MUTEX_INITIALIZER;
160 
161 static CK_RV
162 kmech_hash_insert(CK_MECHANISM_TYPE type, crypto_mech_type_t kmech)
163 {
164 	uint_t h;
165 	kmh_elem_t *elem, *cur;
166 
167 	elem = malloc(sizeof (kmh_elem_t));
168 	if (elem == NULL)
169 		return (CKR_HOST_MEMORY);
170 
171 	h = MECH_HASH(type);
172 	elem->type = type;
173 	elem->kmech = kmech;
174 
175 	(void) pthread_mutex_lock(&mechhash_mutex);
176 	for (cur = kernel_mechhash[h]; cur != NULL; cur = cur->knext) {
177 		if (type == cur->type) {
178 			/* Some other thread beat us to it. */
179 			(void) pthread_mutex_unlock(&mechhash_mutex);
180 			free(elem);
181 			return (CKR_OK);
182 		}
183 	}
184 	elem->knext = kernel_mechhash[h];
185 	kernel_mechhash[h] = elem;
186 	(void) pthread_mutex_unlock(&mechhash_mutex);
187 
188 	return (CKR_OK);
189 }
190 
191 CK_RV
192 kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number)
193 {
194 	crypto_get_mechanism_number_t get_number;
195 	char *string;
196 	CK_RV rv;
197 	int r;
198 	kmh_elem_t *elem;
199 	uint_t h;
200 
201 	/*
202 	 * Search for an existing entry. No need to lock since we are
203 	 * just a reader and we never free the entries in the hash table.
204 	 */
205 	h = MECH_HASH(type);
206 	for (elem = kernel_mechhash[h]; elem != NULL; elem = elem->knext) {
207 		if (type == elem->type) {
208 			*k_number = elem->kmech;
209 			return (CKR_OK);
210 		}
211 	}
212 
213 	string = pkcs11_mech2str(type);
214 	if (string == NULL)
215 		return (CKR_MECHANISM_INVALID);
216 
217 	get_number.pn_mechanism_string = string;
218 	get_number.pn_mechanism_len = strlen(string) + 1;
219 
220 	while ((r = ioctl(kernel_fd, CRYPTO_GET_MECHANISM_NUMBER,
221 	    &get_number)) < 0) {
222 		if (errno != EINTR)
223 			break;
224 	}
225 	if (r < 0) {
226 		rv = CKR_MECHANISM_INVALID;
227 	} else {
228 		if (get_number.pn_return_value != CRYPTO_SUCCESS) {
229 			rv = crypto2pkcs11_error_number(
230 			    get_number.pn_return_value);
231 		} else {
232 			rv = CKR_OK;
233 		}
234 	}
235 
236 	if (rv == CKR_OK) {
237 		*k_number = get_number.pn_internal_number;
238 		/* Add this to the hash table */
239 		(void) kmech_hash_insert(type, *k_number);
240 	}
241 
242 	free(string);
243 	return (rv);
244 }
245 
246 
247 /*
248  * Return the value of a secret key object.
249  * This routine allocates memory for the value.
250  * A null pointer is returned on error.
251  */
252 unsigned char *
253 get_symmetric_key_value(kernel_object_t *key_p)
254 {
255 	uint8_t *cipherKey;
256 
257 	switch (key_p->class) {
258 
259 	case CKO_SECRET_KEY:
260 
261 		cipherKey = malloc(OBJ_SEC(key_p)->sk_value_len);
262 		if (cipherKey == NULL)
263 			return (NULL);
264 
265 		(void) memcpy(cipherKey, OBJ_SEC(key_p)->sk_value,
266 		    OBJ_SEC(key_p)->sk_value_len);
267 
268 		return (cipherKey);
269 
270 	default:
271 		return (NULL);
272 	}
273 }
274 
275 /*
276  * Convert a RSA private key object into a crypto_key structure.
277  * Memory is allocated for each attribute stored in the crypto_key
278  * structure.  Memory for the crypto_key structure is not
279  * allocated.  Attributes can be freed by free_key_attributes().
280  */
281 CK_RV
282 get_rsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
283 {
284 	biginteger_t *big;
285 	crypto_object_attribute_t *attrs, *cur_attr;
286 	char *ptr;
287 	CK_RV rv;
288 
289 	(void) pthread_mutex_lock(&object_p->object_mutex);
290 	if (object_p->key_type != CKK_RSA ||
291 	    object_p->class != CKO_PRIVATE_KEY) {
292 		(void) pthread_mutex_unlock(&object_p->object_mutex);
293 		return (CKR_ATTRIBUTE_TYPE_INVALID);
294 	}
295 
296 	attrs = calloc(1,
297 	    RSA_PRI_ATTR_COUNT * sizeof (crypto_object_attribute_t));
298 	if (attrs == NULL) {
299 		(void) pthread_mutex_unlock(&object_p->object_mutex);
300 		return (CKR_HOST_MEMORY);
301 	}
302 
303 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
304 	key->ck_attrs = attrs;
305 	cur_attr = attrs;
306 
307 	/*
308 	 * Allocate memory for each key attribute and set up the value
309 	 * value length.
310 	 */
311 	key->ck_count = 0;
312 
313 	/* CKA_MODULUS is required. */
314 	big = OBJ_PRI_RSA_MOD(object_p);
315 	if (big->big_value == NULL) {
316 		rv = CKR_ATTRIBUTE_TYPE_INVALID;
317 		goto fail_cleanup;
318 	} else {
319 		if ((ptr = malloc(big->big_value_len)) == NULL) {
320 			rv = CKR_HOST_MEMORY;
321 			goto fail_cleanup;
322 		}
323 		ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
324 		key->ck_count++;
325 	}
326 
327 	/* CKA_PRIVATE_EXPONENT is required. */
328 	big = OBJ_PRI_RSA_PRIEXPO(object_p);
329 	if (big->big_value == NULL) {
330 		rv = CKR_ATTRIBUTE_TYPE_INVALID;
331 		goto fail_cleanup;
332 	} else {
333 		if ((ptr = malloc(big->big_value_len)) == NULL) {
334 			rv = CKR_HOST_MEMORY;
335 			goto fail_cleanup;
336 		}
337 		ENCODE_ATTR(CKA_PRIVATE_EXPONENT, big->big_value,
338 		    big->big_value_len);
339 		key->ck_count++;
340 	}
341 
342 	/* CKA_PRIME_1 is optional. */
343 	big = OBJ_PRI_RSA_PRIME1(object_p);
344 	if (big->big_value != NULL) {
345 		if ((ptr = malloc(big->big_value_len)) == NULL) {
346 			rv = CKR_HOST_MEMORY;
347 			goto fail_cleanup;
348 		}
349 		ENCODE_ATTR(CKA_PRIME_1, big->big_value, big->big_value_len);
350 		key->ck_count++;
351 	}
352 
353 	/* CKA_PRIME_2 is optional. */
354 	big = OBJ_PRI_RSA_PRIME2(object_p);
355 	if (big->big_value != NULL) {
356 		if ((ptr = malloc(big->big_value_len)) == NULL) {
357 			rv = CKR_HOST_MEMORY;
358 			goto fail_cleanup;
359 		}
360 		ENCODE_ATTR(CKA_PRIME_2, big->big_value, big->big_value_len);
361 		key->ck_count++;
362 	}
363 
364 	/* CKA_EXPONENT_1 is optional. */
365 	big = OBJ_PRI_RSA_EXPO1(object_p);
366 	if (big->big_value != NULL) {
367 		if ((ptr = malloc(big->big_value_len)) == NULL) {
368 			rv = CKR_HOST_MEMORY;
369 			goto fail_cleanup;
370 		}
371 		ENCODE_ATTR(CKA_EXPONENT_1, big->big_value,
372 		    big->big_value_len);
373 		key->ck_count++;
374 	}
375 
376 	/* CKA_EXPONENT_2 is optional. */
377 	big = OBJ_PRI_RSA_EXPO2(object_p);
378 	if (big->big_value != NULL) {
379 		if ((ptr = malloc(big->big_value_len)) == NULL) {
380 			rv = CKR_HOST_MEMORY;
381 			goto fail_cleanup;
382 		}
383 		ENCODE_ATTR(CKA_EXPONENT_2, big->big_value,
384 		    big->big_value_len);
385 		key->ck_count++;
386 	}
387 
388 	/* CKA_COEFFICIENT is optional. */
389 	big = OBJ_PRI_RSA_COEF(object_p);
390 	if (big->big_value != NULL) {
391 		if ((ptr = malloc(big->big_value_len)) == NULL) {
392 			rv = CKR_HOST_MEMORY;
393 			goto fail_cleanup;
394 		}
395 		ENCODE_ATTR(CKA_COEFFICIENT, big->big_value,
396 		    big->big_value_len);
397 		key->ck_count++;
398 	}
399 
400 	(void) pthread_mutex_unlock(&object_p->object_mutex);
401 	return (CKR_OK);
402 
403 fail_cleanup:
404 	(void) pthread_mutex_unlock(&object_p->object_mutex);
405 	free_key_attributes(key);
406 	return (rv);
407 }
408 
409 /*
410  * Convert a RSA public key object into a crypto_key structure.
411  * Memory is allocated for each attribute stored in the crypto_key
412  * structure.  Memory for the crypto_key structure is not
413  * allocated.  Attributes can be freed by free_key_attributes().
414  */
415 CK_RV
416 get_rsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
417 {
418 	biginteger_t *big;
419 	crypto_object_attribute_t *attrs, *cur_attr;
420 	char *ptr;
421 
422 	(void) pthread_mutex_lock(&object_p->object_mutex);
423 	if (object_p->key_type != CKK_RSA ||
424 	    object_p->class != CKO_PUBLIC_KEY) {
425 		(void) pthread_mutex_unlock(&object_p->object_mutex);
426 		return (CKR_ATTRIBUTE_TYPE_INVALID);
427 	}
428 
429 	attrs = calloc(1,
430 	    RSA_PUB_ATTR_COUNT * sizeof (crypto_object_attribute_t));
431 	if (attrs == NULL) {
432 		(void) pthread_mutex_unlock(&object_p->object_mutex);
433 		return (CKR_HOST_MEMORY);
434 	}
435 
436 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
437 	key->ck_count = RSA_PUB_ATTR_COUNT;
438 	key->ck_attrs = attrs;
439 
440 	cur_attr = attrs;
441 	big = OBJ_PUB_RSA_PUBEXPO(object_p);
442 	if ((ptr = malloc(big->big_value_len)) == NULL)
443 		goto mem_failure;
444 	ENCODE_ATTR(CKA_PUBLIC_EXPONENT, big->big_value, big->big_value_len);
445 
446 	big = OBJ_PUB_RSA_MOD(object_p);
447 	if ((ptr = malloc(big->big_value_len)) == NULL)
448 		goto mem_failure;
449 	ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
450 
451 	if ((ptr = malloc(sizeof (CK_ULONG))) == NULL)
452 		goto mem_failure;
453 	ENCODE_ATTR(CKA_MODULUS_BITS, &OBJ_PUB_RSA_MOD_BITS(object_p),
454 	    sizeof (CK_ULONG));
455 
456 	(void) pthread_mutex_unlock(&object_p->object_mutex);
457 	return (CKR_OK);
458 
459 mem_failure:
460 	(void) pthread_mutex_unlock(&object_p->object_mutex);
461 	free_key_attributes(key);
462 	return (CKR_HOST_MEMORY);
463 }
464 
465 /*
466  * Free attribute storage in a crypto_key structure.
467  */
468 void
469 free_key_attributes(crypto_key_t *key)
470 {
471 	int i;
472 
473 	if (key->ck_format == CRYPTO_KEY_ATTR_LIST &&
474 	    (key->ck_count > 0) && key->ck_attrs != NULL) {
475 		for (i = 0; i < key->ck_count; i++) {
476 			if (key->ck_attrs[i].oa_value != NULL) {
477 				bzero(key->ck_attrs[i].oa_value,
478 				    key->ck_attrs[i].oa_value_len);
479 				free(key->ck_attrs[i].oa_value);
480 			}
481 		}
482 		free(key->ck_attrs);
483 	}
484 }
485 
486 
487 /*
488  * Convert a DSA private key object into a crypto_key structure.
489  * Memory is allocated for each attribute stored in the crypto_key
490  * structure.  Memory for the crypto_key structure is not
491  * allocated.  Attributes can be freed by free_dsa_key_attributes().
492  */
493 CK_RV
494 get_dsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
495 {
496 	biginteger_t *big;
497 	crypto_object_attribute_t *attrs, *cur_attr;
498 	char *ptr;
499 
500 	(void) pthread_mutex_lock(&object_p->object_mutex);
501 	if (object_p->key_type != CKK_DSA ||
502 	    object_p->class != CKO_PRIVATE_KEY) {
503 		(void) pthread_mutex_unlock(&object_p->object_mutex);
504 		return (CKR_ATTRIBUTE_TYPE_INVALID);
505 	}
506 
507 	attrs = calloc(1,
508 	    DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
509 	if (attrs == NULL) {
510 		(void) pthread_mutex_unlock(&object_p->object_mutex);
511 		return (CKR_HOST_MEMORY);
512 	}
513 
514 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
515 	key->ck_count = DSA_ATTR_COUNT;
516 	key->ck_attrs = attrs;
517 
518 	cur_attr = attrs;
519 	big = OBJ_PRI_DSA_PRIME(object_p);
520 	if ((ptr = malloc(big->big_value_len)) == NULL)
521 		goto mem_failure;
522 	ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
523 
524 	big = OBJ_PRI_DSA_SUBPRIME(object_p);
525 	if ((ptr = malloc(big->big_value_len)) == NULL)
526 		goto mem_failure;
527 	ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
528 
529 	big = OBJ_PRI_DSA_BASE(object_p);
530 	if ((ptr = malloc(big->big_value_len)) == NULL)
531 		goto mem_failure;
532 	ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
533 
534 	big = OBJ_PRI_DSA_VALUE(object_p);
535 	if ((ptr = malloc(big->big_value_len)) == NULL)
536 		goto mem_failure;
537 	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
538 
539 	(void) pthread_mutex_unlock(&object_p->object_mutex);
540 	return (CKR_OK);
541 
542 mem_failure:
543 	(void) pthread_mutex_unlock(&object_p->object_mutex);
544 	free_key_attributes(key);
545 	return (CKR_HOST_MEMORY);
546 }
547 
548 
549 /*
550  * Convert a DSA public key object into a crypto_key structure.
551  * Memory is allocated for each attribute stored in the crypto_key
552  * structure.  Memory for the crypto_key structure is not
553  * allocated.  Attributes can be freed by free_dsa_key_attributes().
554  */
555 CK_RV
556 get_dsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
557 {
558 	biginteger_t *big;
559 	crypto_object_attribute_t *attrs, *cur_attr;
560 	char *ptr;
561 
562 	(void) pthread_mutex_lock(&object_p->object_mutex);
563 	if (object_p->key_type != CKK_DSA ||
564 	    object_p->class != CKO_PUBLIC_KEY) {
565 		(void) pthread_mutex_unlock(&object_p->object_mutex);
566 		return (CKR_ATTRIBUTE_TYPE_INVALID);
567 	}
568 
569 	attrs = calloc(1,
570 	    DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
571 	if (attrs == NULL) {
572 		(void) pthread_mutex_unlock(&object_p->object_mutex);
573 		return (CKR_HOST_MEMORY);
574 	}
575 
576 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
577 	key->ck_count = DSA_ATTR_COUNT;
578 	key->ck_attrs = attrs;
579 
580 	cur_attr = attrs;
581 	big = OBJ_PUB_DSA_PRIME(object_p);
582 	if ((ptr = malloc(big->big_value_len)) == NULL)
583 		goto mem_failure;
584 	ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
585 
586 	big = OBJ_PUB_DSA_SUBPRIME(object_p);
587 	if ((ptr = malloc(big->big_value_len)) == NULL)
588 		goto mem_failure;
589 	ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
590 
591 	big = OBJ_PUB_DSA_BASE(object_p);
592 	if ((ptr = malloc(big->big_value_len)) == NULL)
593 		goto mem_failure;
594 	ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
595 
596 	big = OBJ_PUB_DSA_VALUE(object_p);
597 	if ((ptr = malloc(big->big_value_len)) == NULL)
598 		goto mem_failure;
599 	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
600 
601 	(void) pthread_mutex_unlock(&object_p->object_mutex);
602 	return (CKR_OK);
603 
604 mem_failure:
605 	(void) pthread_mutex_unlock(&object_p->object_mutex);
606 	free_key_attributes(key);
607 	return (CKR_HOST_MEMORY);
608 }
609 
610 
611 /*
612  * Convert a EC private key object into a crypto_key structure.
613  * Memory is allocated for each attribute stored in the crypto_key
614  * structure.  Memory for the crypto_key structure is not
615  * allocated.  Attributes can be freed by free_ec_key_attributes().
616  */
617 CK_RV
618 get_ec_private_key(kernel_object_t *object_p, crypto_key_t *key)
619 {
620 	biginteger_t *big;
621 	crypto_object_attribute_t *attrs, *cur_attr;
622 	CK_ATTRIBUTE tmp;
623 	char *ptr;
624 	int rv;
625 
626 	(void) pthread_mutex_lock(&object_p->object_mutex);
627 	if (object_p->key_type != CKK_EC ||
628 	    object_p->class != CKO_PRIVATE_KEY) {
629 		(void) pthread_mutex_unlock(&object_p->object_mutex);
630 		return (CKR_ATTRIBUTE_TYPE_INVALID);
631 	}
632 
633 	attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
634 	if (attrs == NULL) {
635 		(void) pthread_mutex_unlock(&object_p->object_mutex);
636 		return (CKR_HOST_MEMORY);
637 	}
638 
639 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
640 	key->ck_count = EC_ATTR_COUNT;
641 	key->ck_attrs = attrs;
642 
643 	cur_attr = attrs;
644 	big = OBJ_PRI_EC_VALUE(object_p);
645 	if ((ptr = malloc(big->big_value_len)) == NULL) {
646 		rv = CKR_HOST_MEMORY;
647 		goto fail;
648 	}
649 	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
650 
651 	tmp.type = CKA_EC_PARAMS;
652 	tmp.pValue = NULL;
653 	rv = kernel_get_attribute(object_p, &tmp);
654 	if (rv != CKR_OK) {
655 		goto fail;
656 	}
657 
658 	tmp.pValue = malloc(tmp.ulValueLen);
659 	if (tmp.pValue == NULL) {
660 		rv = CKR_HOST_MEMORY;
661 		goto fail;
662 	}
663 
664 	rv = kernel_get_attribute(object_p, &tmp);
665 	if (rv != CKR_OK) {
666 		free(tmp.pValue);
667 		goto fail;
668 	}
669 
670 	cur_attr->oa_type = tmp.type;
671 	cur_attr->oa_value = tmp.pValue;
672 	cur_attr->oa_value_len = tmp.ulValueLen;
673 
674 	(void) pthread_mutex_unlock(&object_p->object_mutex);
675 	return (CKR_OK);
676 
677 fail:
678 	(void) pthread_mutex_unlock(&object_p->object_mutex);
679 	free_key_attributes(key);
680 	return (rv);
681 }
682 
683 /*
684  * Convert an EC public key object into a crypto_key structure.
685  * Memory is allocated for each attribute stored in the crypto_key
686  * structure.  Memory for the crypto_key structure is not
687  * allocated.  Attributes can be freed by free_ec_key_attributes().
688  */
689 CK_RV
690 get_ec_public_key(kernel_object_t *object_p, crypto_key_t *key)
691 {
692 	biginteger_t *big;
693 	crypto_object_attribute_t *attrs, *cur_attr;
694 	CK_ATTRIBUTE tmp;
695 	char *ptr;
696 	int rv;
697 
698 	(void) pthread_mutex_lock(&object_p->object_mutex);
699 	if (object_p->key_type != CKK_EC ||
700 	    object_p->class != CKO_PUBLIC_KEY) {
701 		(void) pthread_mutex_unlock(&object_p->object_mutex);
702 		return (CKR_ATTRIBUTE_TYPE_INVALID);
703 	}
704 
705 	attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
706 	if (attrs == NULL) {
707 		(void) pthread_mutex_unlock(&object_p->object_mutex);
708 		return (CKR_HOST_MEMORY);
709 	}
710 
711 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
712 	key->ck_count = EC_ATTR_COUNT;
713 	key->ck_attrs = attrs;
714 
715 	cur_attr = attrs;
716 	big = OBJ_PUB_EC_POINT(object_p);
717 	if ((ptr = malloc(big->big_value_len)) == NULL) {
718 		rv = CKR_HOST_MEMORY;
719 		goto fail;
720 	}
721 	ENCODE_ATTR(CKA_EC_POINT, big->big_value, big->big_value_len);
722 
723 	tmp.type = CKA_EC_PARAMS;
724 	tmp.pValue = NULL;
725 	rv = kernel_get_attribute(object_p, &tmp);
726 	if (rv != CKR_OK) {
727 		goto fail;
728 	}
729 
730 	tmp.pValue = malloc(tmp.ulValueLen);
731 	if (tmp.pValue == NULL) {
732 		rv = CKR_HOST_MEMORY;
733 		goto fail;
734 	}
735 
736 	rv = kernel_get_attribute(object_p, &tmp);
737 	if (rv != CKR_OK) {
738 		free(tmp.pValue);
739 		goto fail;
740 	}
741 
742 	cur_attr->oa_type = tmp.type;
743 	cur_attr->oa_value = tmp.pValue;
744 	cur_attr->oa_value_len = tmp.ulValueLen;
745 
746 	(void) pthread_mutex_unlock(&object_p->object_mutex);
747 	return (CKR_OK);
748 
749 fail:
750 	(void) pthread_mutex_unlock(&object_p->object_mutex);
751 	free_key_attributes(key);
752 	return (rv);
753 }
754 
755 /*
756  * Convert an attribute template into an obj_attrs array.
757  * Memory is allocated for each attribute stored in the obj_attrs.
758  * The memory can be freed by free_object_attributes().
759  *
760  * If the boolean pointer is_token_obj is not NULL, the caller wants to
761  * retrieve the value of the CKA_TOKEN attribute if it is specified in the
762  * template.
763  * - When this routine is called thru C_CreateObject(), C_CopyObject(), or
764  *   any key management function, is_token_obj should NOT be NULL.
765  * - When this routine is called thru C_GetAttributeValue() or
766  *   C_SetAttributeValue(), "is_token_obj" should be NULL.
767  */
768 CK_RV
769 process_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
770     caddr_t *obj_attrs, CK_BBOOL *is_token_obj)
771 {
772 	crypto_object_attribute_t *attrs, *cur_attr;
773 	int i, cur_i;
774 	char *ptr;
775 	CK_RV rv;
776 	ssize_t value_len;
777 
778 	if (ulCount == 0) {
779 		obj_attrs = NULL;
780 		return (CKR_OK);
781 	}
782 
783 	attrs = calloc(1, ulCount * sizeof (crypto_object_attribute_t));
784 	if (attrs == NULL) {
785 		return (CKR_HOST_MEMORY);
786 	}
787 
788 	cur_attr = attrs;
789 	for (i = 0; i < ulCount; i++) {
790 		/*
791 		 * The length of long attributes must be set correctly
792 		 * so providers can determine whether they came from 32
793 		 * or 64-bit applications.
794 		 */
795 		switch (pTemplate[i].type) {
796 		case CKA_CLASS:
797 		case CKA_CERTIFICATE_TYPE:
798 		case CKA_KEY_TYPE:
799 		case CKA_MODULUS_BITS:
800 		case CKA_HW_FEATURE_TYPE:
801 			value_len = sizeof (ulong_t);
802 			if (pTemplate[i].pValue != NULL &&
803 			    (pTemplate[i].ulValueLen < value_len)) {
804 				rv = CKR_BUFFER_TOO_SMALL;
805 				cur_i = i;
806 				goto fail_cleanup;
807 			}
808 			break;
809 		default:
810 			value_len = pTemplate[i].ulValueLen;
811 		}
812 
813 		cur_attr->oa_type = pTemplate[i].type;
814 		cur_attr->oa_value_len = value_len;
815 		cur_attr->oa_value = NULL;
816 
817 		if ((pTemplate[i].pValue != NULL) &&
818 		    (pTemplate[i].ulValueLen > 0)) {
819 			ptr = malloc(pTemplate[i].ulValueLen);
820 			if (ptr == NULL) {
821 				rv = CKR_HOST_MEMORY;
822 				cur_i = i;
823 				goto fail_cleanup;
824 			} else {
825 				(void) memcpy(ptr, pTemplate[i].pValue,
826 				    pTemplate[i].ulValueLen);
827 				cur_attr->oa_value = ptr;
828 			}
829 		}
830 
831 		if ((is_token_obj != NULL) &&
832 		    (pTemplate[i].type == CKA_TOKEN)) {
833 			/* Get the CKA_TOKEN attribute value. */
834 			if (pTemplate[i].pValue == NULL) {
835 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
836 				cur_i = i;
837 				goto fail_cleanup;
838 			} else {
839 				*is_token_obj =
840 				    *(CK_BBOOL *)pTemplate[i].pValue;
841 			}
842 		}
843 
844 		cur_attr++;
845 	}
846 
847 	*obj_attrs = (char *)attrs;
848 	return (CKR_OK);
849 
850 fail_cleanup:
851 	cur_attr = attrs;
852 	for (i = 0; i < cur_i; i++) {
853 		if (cur_attr->oa_value != NULL) {
854 			(void) free(cur_attr->oa_value);
855 		}
856 		cur_attr++;
857 	}
858 
859 	(void) free(attrs);
860 	return (rv);
861 }
862 
863 
864 /*
865  * Copy the attribute values from obj_attrs to pTemplate.
866  * The obj_attrs is an image of the Template and is expected to have the
867  * same attributes in the same order and each one of the attribute pValue
868  * in obj_attr has enough space allocated for the corresponding valueLen
869  * in pTemplate.
870  */
871 CK_RV
872 get_object_attributes(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
873     caddr_t obj_attrs)
874 {
875 	crypto_object_attribute_t *cur_attr;
876 	CK_RV rv = CKR_OK;
877 	int i;
878 
879 	/* LINTED */
880 	cur_attr = (crypto_object_attribute_t *)obj_attrs;
881 	for (i = 0; i < ulCount; i++) {
882 		if (pTemplate[i].type != cur_attr->oa_type) {
883 			/* The attribute type doesn't match, this is bad. */
884 			rv = CKR_FUNCTION_FAILED;
885 			return (rv);
886 		}
887 
888 		pTemplate[i].ulValueLen = cur_attr->oa_value_len;
889 
890 		if ((pTemplate[i].pValue != NULL) &&
891 		    ((CK_LONG)pTemplate[i].ulValueLen != -1)) {
892 			(void) memcpy(pTemplate[i].pValue, cur_attr->oa_value,
893 			    pTemplate[i].ulValueLen);
894 		}
895 		cur_attr++;
896 	}
897 
898 	return (rv);
899 }
900 
901 /*
902  * Free the attribute storage in a crypto_object_attribute_t structure.
903  */
904 void
905 free_object_attributes(caddr_t obj_attrs, CK_ULONG ulCount)
906 {
907 	crypto_object_attribute_t *cur_attr;
908 	int i;
909 
910 	if ((ulCount == 0) || (obj_attrs == NULL)) {
911 		return;
912 	}
913 
914 	/* LINTED */
915 	cur_attr = (crypto_object_attribute_t *)obj_attrs;
916 	for (i = 0; i < ulCount; i++) {
917 		/* XXX check that oa_value > 0 */
918 		if (cur_attr->oa_value != NULL) {
919 			free(cur_attr->oa_value);
920 		}
921 		cur_attr++;
922 	}
923 
924 	free(obj_attrs);
925 }
926 
927 /*
928  * This function is called by process_found_objects().  It will check the
929  * CKA_PRIVATE and CKA_TOKEN attributes for the kernel object "oid", then
930  * initialize all the necessary fields in the object wrapper "objp".
931  */
932 static CK_RV
933 create_new_tobj_in_lib(kernel_slot_t *pslot, kernel_session_t *sp,
934     kernel_object_t *objp,  crypto_object_id_t oid)
935 {
936 	CK_RV  rv = CKR_OK;
937 	crypto_object_get_attribute_value_t obj_ga;
938 	boolean_t is_pri_obj;
939 	boolean_t is_token_obj;
940 	CK_BBOOL pri_value, token_value;
941 	CK_ATTRIBUTE  pTemplate[2];
942 	int r;
943 
944 	/*
945 	 * Make a CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE ioctl call to get this
946 	 * kernel object's attribute values for CKA_PRIVATE and CKA_TOKEN.
947 	 */
948 	obj_ga.og_session = sp->k_session;
949 	obj_ga.og_handle = oid;
950 	obj_ga.og_count = 2;
951 
952 	pTemplate[0].type = CKA_PRIVATE;
953 	pTemplate[0].pValue = &pri_value;
954 	pTemplate[0].ulValueLen = sizeof (pri_value);
955 	pTemplate[1].type = CKA_TOKEN;
956 	pTemplate[1].pValue = &token_value;
957 	pTemplate[1].ulValueLen = sizeof (token_value);
958 	rv = process_object_attributes(pTemplate, 2, &obj_ga.og_attributes,
959 	    NULL);
960 	if (rv != CKR_OK) {
961 		return (rv);
962 	}
963 
964 	while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
965 	    &obj_ga)) < 0) {
966 		if (errno != EINTR)
967 			break;
968 	}
969 	if (r < 0) {
970 		rv = CKR_FUNCTION_FAILED;
971 	} else {
972 		rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
973 	}
974 
975 	if (rv == CKR_OK) {
976 		rv = get_object_attributes(pTemplate, 2, obj_ga.og_attributes);
977 		if (rv == CKR_OK) {
978 			is_pri_obj = *(CK_BBOOL *)pTemplate[0].pValue;
979 			is_token_obj = *(CK_BBOOL *)pTemplate[1].pValue;
980 		}
981 	}
982 
983 	free_object_attributes(obj_ga.og_attributes, 2);
984 	if (rv != CKR_OK) {
985 		return (rv);
986 	}
987 
988 	/* Make sure it is a token object. */
989 	if (!is_token_obj) {
990 		rv = CKR_ATTRIBUTE_VALUE_INVALID;
991 		return (rv);
992 	}
993 
994 	/* If it is a private object, make sure the user has logged in. */
995 	if (is_pri_obj && (pslot->sl_state != CKU_USER)) {
996 		rv = CKR_ATTRIBUTE_VALUE_INVALID;
997 		return (rv);
998 	}
999 
1000 	objp->is_lib_obj = B_FALSE;
1001 	objp->k_handle = oid;
1002 	objp->bool_attr_mask |= TOKEN_BOOL_ON;
1003 	if (is_pri_obj) {
1004 		objp->bool_attr_mask |= PRIVATE_BOOL_ON;
1005 	} else {
1006 		objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
1007 	}
1008 
1009 	(void) pthread_mutex_init(&objp->object_mutex, NULL);
1010 	objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1011 	objp->session_handle = (CK_SESSION_HANDLE) sp;
1012 
1013 	return (CKR_OK);
1014 }
1015 
1016 /*
1017  * This function processes the kernel object handles returned from the
1018  * CRYPTO_OBJECT_FIND_UPDATE ioctl and returns an object handle list
1019  * and the number of object handles to the caller - C_FindObjects().
1020  * The caller acquires the slot lock and the session lock.
1021  */
1022 CK_RV
1023 process_found_objects(kernel_session_t *cur_sp, CK_OBJECT_HANDLE *obj_found,
1024     CK_ULONG *found_obj_count, crypto_object_find_update_t obj_fu)
1025 {
1026 	CK_RV rv = CKR_OK;
1027 	crypto_object_id_t  *oid_p;
1028 	kernel_slot_t *pslot;
1029 	kernel_object_t *objp;
1030 	kernel_object_t *objp1;
1031 	kernel_object_t *new_tobj_list = NULL;
1032 	kernel_session_t  *sp;
1033 	CK_ULONG num_obj_found = 0;
1034 	boolean_t is_in_lib;
1035 	int i;
1036 
1037 	if (obj_fu.fu_count == 0) {
1038 		*found_obj_count = 0;
1039 		return (CKR_OK);
1040 	}
1041 
1042 	pslot = slot_table[cur_sp->ses_slotid];
1043 
1044 	/* LINTED */
1045 	oid_p = (crypto_object_id_t *)obj_fu.fu_handles;
1046 	for (i = 0; i < obj_fu.fu_count; i++) {
1047 		is_in_lib = B_FALSE;
1048 		/*
1049 		 * Check if this oid has an object wrapper in the library
1050 		 * already.  First, search the slot's token object list.
1051 		 */
1052 		objp = pslot->sl_tobj_list;
1053 		while (!is_in_lib && objp) {
1054 			if (objp->k_handle == *oid_p) {
1055 				is_in_lib = B_TRUE;
1056 			} else {
1057 				objp = objp->next;
1058 			}
1059 		}
1060 
1061 		/*
1062 		 * If it is not in the slot's token object list,
1063 		 * search it in all the sessions.
1064 		 */
1065 		if (!is_in_lib) {
1066 			sp = pslot->sl_sess_list;
1067 			while (!is_in_lib && sp) {
1068 				objp = sp->object_list;
1069 				while (!is_in_lib && objp) {
1070 					if (objp->k_handle == *oid_p) {
1071 						is_in_lib = B_TRUE;
1072 					} else {
1073 						objp = objp->next;
1074 					}
1075 				}
1076 				sp = sp->next;
1077 			}
1078 		}
1079 
1080 		/*
1081 		 * If this object is in the library already, add its object
1082 		 * wrapper to the returned find object list.
1083 		 */
1084 		if (is_in_lib) {
1085 			obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
1086 		}
1087 
1088 		/*
1089 		 * If we still do not find it in the library.  This object
1090 		 * must be a token object pre-existed in the HW provider.
1091 		 * We need to create an object wrapper for it in the library.
1092 		 */
1093 		if (!is_in_lib) {
1094 			objp1 = calloc(1, sizeof (kernel_object_t));
1095 			if (objp1 == NULL) {
1096 				rv = CKR_HOST_MEMORY;
1097 				goto failed_exit;
1098 			}
1099 			rv = create_new_tobj_in_lib(pslot, cur_sp, objp1,
1100 			    *oid_p);
1101 
1102 			if (rv == CKR_OK) {
1103 				/* Save the new object to the new_tobj_list. */
1104 				if (new_tobj_list == NULL) {
1105 					new_tobj_list = objp1;
1106 					objp1->next = NULL;
1107 					objp1->prev = NULL;
1108 				} else {
1109 					new_tobj_list->prev = objp1;
1110 					objp1->next = new_tobj_list;
1111 					objp1->prev = NULL;
1112 					new_tobj_list = objp1;
1113 				}
1114 			} else {
1115 				/*
1116 				 * If create_new_tobj_in_lib() doesn't fail
1117 				 * with CKR_HOST_MEMORY, the failure should be
1118 				 * caused by the attributes' checking. We will
1119 				 * just ignore this object and continue on.
1120 				 */
1121 				free(objp1);
1122 				if (rv == CKR_HOST_MEMORY) {
1123 					goto failed_exit;
1124 				}
1125 			}
1126 		}
1127 
1128 		/* Process next one */
1129 		oid_p++;
1130 	}
1131 
1132 	/*
1133 	 * Add the newly created token object wrappers to the found object
1134 	 * list and to the slot's token object list.
1135 	 */
1136 	if (new_tobj_list != NULL) {
1137 		/* Add to the obj_found array. */
1138 		objp = new_tobj_list;
1139 		while (objp) {
1140 			obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
1141 			if (objp->next == NULL) {
1142 				break;
1143 			}
1144 			objp = objp->next;
1145 		}
1146 
1147 		/* Add to the beginning of the slot's token object list. */
1148 		if (pslot->sl_tobj_list != NULL) {
1149 			objp->next = pslot->sl_tobj_list;
1150 			pslot->sl_tobj_list->prev = objp;
1151 		}
1152 		pslot->sl_tobj_list = new_tobj_list;
1153 	}
1154 
1155 	*found_obj_count = num_obj_found;
1156 	return (CKR_OK);
1157 
1158 failed_exit:
1159 
1160 	/* Free the newly created token object wrappers. */
1161 	objp = new_tobj_list;
1162 	while (objp) {
1163 		objp1 = objp->next;
1164 		(void) pthread_mutex_destroy(&objp->object_mutex);
1165 		free(objp);
1166 		objp = objp1;
1167 	}
1168 
1169 	return (rv);
1170 }
1171 
1172 
1173 /*
1174  * Get the value of the CKA_PRIVATE attribute for the object just returned
1175  * from the HW provider.  This function will be called by any function
1176  * that creates a new object, because the CKA_PRIVATE value of an object is
1177  * token sepecific.  The CKA_PRIVATE attribute value of the new object will be
1178  * stored in the object structure in the library, which will be used later at
1179  * C_Logout to clean up all private objects.
1180  */
1181 CK_RV
1182 get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
1183     CK_BBOOL *is_pri_obj)
1184 {
1185 	CK_RV  rv = CKR_OK;
1186 	crypto_object_get_attribute_value_t obj_ga;
1187 	crypto_object_attribute_t obj_attr;
1188 	CK_BBOOL pri_value;
1189 	int r;
1190 
1191 	obj_ga.og_session = sp->k_session;
1192 	obj_ga.og_handle = oid;
1193 	obj_ga.og_count = 1;
1194 
1195 	obj_attr.oa_type = CKA_PRIVATE;
1196 	obj_attr.oa_value = (char *)&pri_value;
1197 	obj_attr.oa_value_len = sizeof (CK_BBOOL);
1198 	obj_ga.og_attributes = (char *)&obj_attr;
1199 
1200 	while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
1201 	    &obj_ga)) < 0) {
1202 		if (errno != EINTR)
1203 			break;
1204 	}
1205 	if (r < 0) {
1206 		rv = CKR_FUNCTION_FAILED;
1207 	} else {
1208 		rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
1209 	}
1210 
1211 	if (rv == CKR_OK) {
1212 		*is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
1213 	}
1214 
1215 	return (rv);
1216 }
1217 
1218 
1219 CK_RV
1220 get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
1221     CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
1222 {
1223 	crypto_get_provider_mechanism_info_t mechanism_info;
1224 	char *string;
1225 	CK_FLAGS flags, mi_flags;
1226 	CK_RV rv;
1227 	int r;
1228 
1229 	string = pkcs11_mech2str(type);
1230 	if (string == NULL)
1231 		return (CKR_MECHANISM_INVALID);
1232 
1233 	(void) strcpy(mechanism_info.mi_mechanism_name, string);
1234 	mechanism_info.mi_provider_id = pslot->sl_provider_id;
1235 
1236 	while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
1237 	    &mechanism_info)) < 0) {
1238 		if (errno != EINTR)
1239 			break;
1240 	}
1241 	if (r < 0) {
1242 		rv = CKR_FUNCTION_FAILED;
1243 	} else {
1244 		rv = crypto2pkcs11_error_number(
1245 		    mechanism_info.mi_return_value);
1246 	}
1247 
1248 	if (rv != CKR_OK) {
1249 		goto out;
1250 	}
1251 
1252 	/*
1253 	 * Atomic flags are not part of PKCS#11 so we filter
1254 	 * them out here.
1255 	 */
1256 	mi_flags = mechanism_info.mi_flags;
1257 	mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
1258 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
1259 	    CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
1260 	    CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1261 	    CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
1262 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
1263 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC);
1264 
1265 	if (mi_flags == 0) {
1266 		rv = CKR_MECHANISM_INVALID;
1267 		goto out;
1268 	}
1269 
1270 	if (rv == CKR_OK) {
1271 		/* set the value of k_mi_flags first */
1272 		*k_mi_flags = mi_flags;
1273 
1274 		/* convert KEF flags into pkcs11 flags */
1275 		flags = CKF_HW;
1276 		if (mi_flags & CRYPTO_FG_ENCRYPT)
1277 			flags |= CKF_ENCRYPT;
1278 		if (mi_flags & CRYPTO_FG_DECRYPT) {
1279 			flags |= CKF_DECRYPT;
1280 			/*
1281 			 * Since we'll be emulating C_UnwrapKey() for some
1282 			 * cases, we can go ahead and claim CKF_UNWRAP
1283 			 */
1284 			flags |= CKF_UNWRAP;
1285 		}
1286 		if (mi_flags & CRYPTO_FG_DIGEST)
1287 			flags |= CKF_DIGEST;
1288 		if (mi_flags & CRYPTO_FG_SIGN)
1289 			flags |= CKF_SIGN;
1290 		if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
1291 			flags |= CKF_SIGN_RECOVER;
1292 		if (mi_flags & CRYPTO_FG_VERIFY)
1293 			flags |= CKF_VERIFY;
1294 		if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
1295 			flags |= CKF_VERIFY_RECOVER;
1296 		if (mi_flags & CRYPTO_FG_GENERATE)
1297 			flags |= CKF_GENERATE;
1298 		if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
1299 			flags |= CKF_GENERATE_KEY_PAIR;
1300 		if (mi_flags & CRYPTO_FG_WRAP)
1301 			flags |= CKF_WRAP;
1302 		if (mi_flags & CRYPTO_FG_UNWRAP)
1303 			flags |= CKF_UNWRAP;
1304 		if (mi_flags & CRYPTO_FG_DERIVE)
1305 			flags |= CKF_DERIVE;
1306 
1307 		pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
1308 		pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
1309 		pInfo->flags = flags;
1310 
1311 	}
1312 
1313 out:
1314 	free(string);
1315 	return (rv);
1316 }
1317