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