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