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