xref: /titanic_51/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelUtil.c (revision e8ab7b17355c311dfdb9f3aef33d179d9da74433)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56f3f1c68Skrishna  * Common Development and Distribution License (the "License").
66f3f1c68Skrishna  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*e8ab7b17SZdenek Kotala  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #include <stdlib.h>
267c478bd9Sstevel@tonic-gate #include <string.h>
277c478bd9Sstevel@tonic-gate #include <strings.h>
282321aa36Sda73024 #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
327c478bd9Sstevel@tonic-gate #include <sys/crypto/common.h>
337c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h>
347c478bd9Sstevel@tonic-gate #include "kernelGlobal.h"
357c478bd9Sstevel@tonic-gate #include "kernelObject.h"
367c478bd9Sstevel@tonic-gate #include "kernelSlot.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #define	ENCODE_ATTR(type, value, len) {		\
397c478bd9Sstevel@tonic-gate 	cur_attr->oa_type = type;		\
407c478bd9Sstevel@tonic-gate 	(void) memcpy(ptr, value, len);		\
417c478bd9Sstevel@tonic-gate 	cur_attr->oa_value = ptr;		\
427c478bd9Sstevel@tonic-gate 	cur_attr->oa_value_len = len;		\
437c478bd9Sstevel@tonic-gate 	cur_attr++;				\
447c478bd9Sstevel@tonic-gate }
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate  * In order to fit everything on one line, the 'CRYPTO_' prefix
487c478bd9Sstevel@tonic-gate  * has been dropped from the KCF #defines, e.g.
497c478bd9Sstevel@tonic-gate  * CRYPTO_SUCCESS becomes SUCCESS.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate 
52*e8ab7b17SZdenek Kotala static CK_RV error_number_table[CRYPTO_LAST_ERROR+1] = {
537c478bd9Sstevel@tonic-gate CKR_OK,					/* SUCCESS */
547c478bd9Sstevel@tonic-gate CKR_CANCEL,				/* CANCEL */
557c478bd9Sstevel@tonic-gate CKR_HOST_MEMORY,			/* HOST_MEMORY */
567c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* GENERAL_ERROR */
577c478bd9Sstevel@tonic-gate CKR_FUNCTION_FAILED,			/* FAILED */
587c478bd9Sstevel@tonic-gate CKR_ARGUMENTS_BAD,			/* ARGUMENTS_BAD */
597c478bd9Sstevel@tonic-gate CKR_ATTRIBUTE_READ_ONLY,		/* ATTRIBUTE_READ_ONLY */
607c478bd9Sstevel@tonic-gate CKR_ATTRIBUTE_SENSITIVE,		/* ATTRIBUTE_SENSITIVE */
617c478bd9Sstevel@tonic-gate CKR_ATTRIBUTE_TYPE_INVALID,		/* ATTRIBUTE_TYPE_INVALID */
627c478bd9Sstevel@tonic-gate CKR_ATTRIBUTE_VALUE_INVALID,		/* ATTRIBUTE_VALUE_INVALID */
637c478bd9Sstevel@tonic-gate CKR_FUNCTION_FAILED,			/* CANCELED */
647c478bd9Sstevel@tonic-gate CKR_DATA_INVALID,			/* DATA_INVALID */
657c478bd9Sstevel@tonic-gate CKR_DATA_LEN_RANGE,			/* DATA_LEN_RANGE */
667c478bd9Sstevel@tonic-gate CKR_DEVICE_ERROR,			/* DEVICE_ERROR */
677c478bd9Sstevel@tonic-gate CKR_DEVICE_MEMORY,			/* DEVICE_MEMORY */
687c478bd9Sstevel@tonic-gate CKR_DEVICE_REMOVED,			/* DEVICE_REMOVED */
697c478bd9Sstevel@tonic-gate CKR_ENCRYPTED_DATA_INVALID,		/* ENCRYPTED_DATA_INVALID */
707c478bd9Sstevel@tonic-gate CKR_ENCRYPTED_DATA_LEN_RANGE,		/* ENCRYPTED_DATA_LEN_RANGE */
717c478bd9Sstevel@tonic-gate CKR_KEY_HANDLE_INVALID,			/* KEY_HANDLE_INVALID */
727c478bd9Sstevel@tonic-gate CKR_KEY_SIZE_RANGE,			/* KEY_SIZE_RANGE */
737c478bd9Sstevel@tonic-gate CKR_KEY_TYPE_INCONSISTENT,		/* KEY_TYPE_INCONSISTENT */
747c478bd9Sstevel@tonic-gate CKR_KEY_NOT_NEEDED,			/* KEY_NOT_NEEDED */
757c478bd9Sstevel@tonic-gate CKR_KEY_CHANGED,			/* KEY_CHANGED */
767c478bd9Sstevel@tonic-gate CKR_KEY_NEEDED,				/* KEY_NEEDED */
777c478bd9Sstevel@tonic-gate CKR_KEY_INDIGESTIBLE,			/* KEY_INDIGESTIBLE */
787c478bd9Sstevel@tonic-gate CKR_KEY_FUNCTION_NOT_PERMITTED,		/* KEY_FUNCTION_NOT_PERMITTED */
797c478bd9Sstevel@tonic-gate CKR_KEY_NOT_WRAPPABLE,			/* KEY_NOT_WRAPPABLE */
807c478bd9Sstevel@tonic-gate CKR_KEY_UNEXTRACTABLE,			/* KEY_UNEXTRACTABLE */
817c478bd9Sstevel@tonic-gate CKR_MECHANISM_INVALID,			/* MECHANISM_INVALID */
827c478bd9Sstevel@tonic-gate CKR_MECHANISM_PARAM_INVALID,		/* MECHANISM_PARAM_INVALID */
837c478bd9Sstevel@tonic-gate CKR_OBJECT_HANDLE_INVALID,		/* OBJECT_HANDLE_INVALID */
847c478bd9Sstevel@tonic-gate CKR_OPERATION_ACTIVE,			/* OPERATION_ACTIVE */
857c478bd9Sstevel@tonic-gate CKR_OPERATION_NOT_INITIALIZED,		/* OPERATION_NOT_INITIALIZED */
867c478bd9Sstevel@tonic-gate CKR_PIN_INCORRECT,			/* PIN_INCORRECT */
877c478bd9Sstevel@tonic-gate CKR_PIN_INVALID,			/* PIN_INVALID */
887c478bd9Sstevel@tonic-gate CKR_PIN_LEN_RANGE,			/* PIN_LEN_RANGE */
897c478bd9Sstevel@tonic-gate CKR_PIN_EXPIRED,			/* PIN_EXPIRED */
907c478bd9Sstevel@tonic-gate CKR_PIN_LOCKED,				/* PIN_LOCKED */
917c478bd9Sstevel@tonic-gate CKR_SESSION_CLOSED,			/* SESSION_CLOSED */
927c478bd9Sstevel@tonic-gate CKR_SESSION_COUNT,			/* SESSION_COUNT */
937c478bd9Sstevel@tonic-gate CKR_SESSION_HANDLE_INVALID,		/* SESSION_HANDLE_INVALID */
947c478bd9Sstevel@tonic-gate CKR_SESSION_READ_ONLY,			/* SESSION_READ_ONLY */
957c478bd9Sstevel@tonic-gate CKR_SESSION_EXISTS,			/* SESSION_EXISTS */
967c478bd9Sstevel@tonic-gate CKR_SESSION_READ_ONLY_EXISTS,		/* SESSION_READ_ONLY_EXISTS */
977c478bd9Sstevel@tonic-gate CKR_SESSION_READ_WRITE_SO_EXISTS,	/* SESSION_READ_WRITE_SO_EXISTS */
987c478bd9Sstevel@tonic-gate CKR_SIGNATURE_INVALID,			/* SIGNATURE_INVALID */
997c478bd9Sstevel@tonic-gate CKR_SIGNATURE_LEN_RANGE,		/* SIGNATURE_LEN_RANGE */
1007c478bd9Sstevel@tonic-gate CKR_TEMPLATE_INCOMPLETE,		/* TEMPLATE_INCOMPLETE */
1017c478bd9Sstevel@tonic-gate CKR_TEMPLATE_INCONSISTENT,		/* TEMPLATE_INCONSISTENT */
1027c478bd9Sstevel@tonic-gate CKR_UNWRAPPING_KEY_HANDLE_INVALID,	/* UNWRAPPING_KEY_HANDLE_INVALID */
1037c478bd9Sstevel@tonic-gate CKR_UNWRAPPING_KEY_SIZE_RANGE,		/* UNWRAPPING_KEY_SIZE_RANGE */
1047c478bd9Sstevel@tonic-gate CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,	/* UNWRAPPING_KEY_TYPE_INCONSISTENT */
1057c478bd9Sstevel@tonic-gate CKR_USER_ALREADY_LOGGED_IN,		/* USER_ALREADY_LOGGED_IN */
1067c478bd9Sstevel@tonic-gate CKR_USER_NOT_LOGGED_IN,			/* USER_NOT_LOGGED_IN */
1077c478bd9Sstevel@tonic-gate CKR_USER_PIN_NOT_INITIALIZED,		/* USER_PIN_NOT_INITIALIZED */
1087c478bd9Sstevel@tonic-gate CKR_USER_TYPE_INVALID,			/* USER_TYPE_INVALID */
1097c478bd9Sstevel@tonic-gate CKR_USER_ANOTHER_ALREADY_LOGGED_IN,	/* USER_ANOTHER_ALREADY_LOGGED_IN */
1107c478bd9Sstevel@tonic-gate CKR_USER_TOO_MANY_TYPES,		/* USER_TOO_MANY_TYPES */
1117c478bd9Sstevel@tonic-gate CKR_WRAPPED_KEY_INVALID,		/* WRAPPED_KEY_INVALID */
1127c478bd9Sstevel@tonic-gate CKR_WRAPPED_KEY_LEN_RANGE,		/* WRAPPED_KEY_LEN_RANGE */
1137c478bd9Sstevel@tonic-gate CKR_WRAPPING_KEY_HANDLE_INVALID,	/* WRAPPING_KEY_HANDLE_INVALID */
1147c478bd9Sstevel@tonic-gate CKR_WRAPPING_KEY_SIZE_RANGE,		/* WRAPPING_KEY_SIZE_RANGE */
1157c478bd9Sstevel@tonic-gate CKR_WRAPPING_KEY_TYPE_INCONSISTENT,	/* WRAPPING_KEY_TYPE_INCONSISTENT */
1167c478bd9Sstevel@tonic-gate CKR_RANDOM_SEED_NOT_SUPPORTED,		/* RANDOM_SEED_NOT_SUPPORTED */
1177c478bd9Sstevel@tonic-gate CKR_RANDOM_NO_RNG,			/* RANDOM_NO_RNG */
1187c478bd9Sstevel@tonic-gate CKR_DOMAIN_PARAMS_INVALID,		/* DOMAIN_PARAMS_INVALID */
1197c478bd9Sstevel@tonic-gate CKR_BUFFER_TOO_SMALL,			/* BUFFER_TOO_SMALL */
1207c478bd9Sstevel@tonic-gate CKR_INFORMATION_SENSITIVE,		/* INFORMATION_SENSITIVE */
1217c478bd9Sstevel@tonic-gate CKR_FUNCTION_NOT_SUPPORTED,		/* NOT_SUPPORTED */
1227c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* QUEUED */
1237c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* BUFFER_TOO_BIG */
1247c478bd9Sstevel@tonic-gate CKR_OPERATION_NOT_INITIALIZED,		/* INVALID_CONTEXT */
1257c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* INVALID_MAC */
1267c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* MECH_NOT_SUPPORTED */
1277c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* INCONSISTENT_ATTRIBUTE */
1287c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* NO_PERMISSION */
1297c478bd9Sstevel@tonic-gate CKR_SLOT_ID_INVALID,			/* INVALID_PROVIDER_ID */
1307c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* VERSION_MISMATCH */
1317c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* BUSY */
1327c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* UNKNOWN_PROVIDER */
1337c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* MODVERIFICATION_FAILED */
1347c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* OLD_CTX_TEMPLATE */
1357c478bd9Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* WEAK_KEY */
136*e8ab7b17SZdenek Kotala CKR_GENERAL_ERROR			/* FIPS140_ERROR */
1377c478bd9Sstevel@tonic-gate };
1387c478bd9Sstevel@tonic-gate 
139*e8ab7b17SZdenek Kotala #if CRYPTO_LAST_ERROR != CRYPTO_FIPS140_ERROR
140*e8ab7b17SZdenek Kotala #error "Crypto to PKCS11 error mapping table needs to be updated!"
141*e8ab7b17SZdenek Kotala #endif
142*e8ab7b17SZdenek Kotala 
1437c478bd9Sstevel@tonic-gate /*
1447c478bd9Sstevel@tonic-gate  * Map KCF error codes into PKCS11 error codes.
1457c478bd9Sstevel@tonic-gate  */
1467c478bd9Sstevel@tonic-gate CK_RV
1477c478bd9Sstevel@tonic-gate crypto2pkcs11_error_number(uint_t n)
1487c478bd9Sstevel@tonic-gate {
149*e8ab7b17SZdenek Kotala 	if (n >= sizeof (error_number_table) / sizeof (error_number_table[0]))
1507c478bd9Sstevel@tonic-gate 		return (CKR_GENERAL_ERROR);
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	return (error_number_table[n]);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
1556f3f1c68Skrishna #define	MECH_HASH(type)	(((uintptr_t)type) % KMECH_HASHTABLE_SIZE)
1566f3f1c68Skrishna /*
1576f3f1c68Skrishna  * Serialize writes to the hash table. We don't need a per bucket lock as
1586f3f1c68Skrishna  * there are only a few writes and we don't need the lock for reads.
1596f3f1c68Skrishna  */
1601f49a79aSZdenek Kotala pthread_mutex_t mechhash_mutex = PTHREAD_MUTEX_INITIALIZER;
1616f3f1c68Skrishna 
1626f3f1c68Skrishna static CK_RV
1636f3f1c68Skrishna kmech_hash_insert(CK_MECHANISM_TYPE type, crypto_mech_type_t kmech)
1646f3f1c68Skrishna {
1656f3f1c68Skrishna 	uint_t h;
1666f3f1c68Skrishna 	kmh_elem_t *elem, *cur;
1676f3f1c68Skrishna 
1686f3f1c68Skrishna 	elem = malloc(sizeof (kmh_elem_t));
1696f3f1c68Skrishna 	if (elem == NULL)
1706f3f1c68Skrishna 		return (CKR_HOST_MEMORY);
1716f3f1c68Skrishna 
1726f3f1c68Skrishna 	h = MECH_HASH(type);
1736f3f1c68Skrishna 	elem->type = type;
1746f3f1c68Skrishna 	elem->kmech = kmech;
1756f3f1c68Skrishna 
1766f3f1c68Skrishna 	(void) pthread_mutex_lock(&mechhash_mutex);
1776f3f1c68Skrishna 	for (cur = kernel_mechhash[h]; cur != NULL; cur = cur->knext) {
1786f3f1c68Skrishna 		if (type == cur->type) {
1796f3f1c68Skrishna 			/* Some other thread beat us to it. */
1806f3f1c68Skrishna 			(void) pthread_mutex_unlock(&mechhash_mutex);
1816f3f1c68Skrishna 			free(elem);
1826f3f1c68Skrishna 			return (CKR_OK);
1836f3f1c68Skrishna 		}
1846f3f1c68Skrishna 	}
1856f3f1c68Skrishna 	elem->knext = kernel_mechhash[h];
1866f3f1c68Skrishna 	kernel_mechhash[h] = elem;
1876f3f1c68Skrishna 	(void) pthread_mutex_unlock(&mechhash_mutex);
1886f3f1c68Skrishna 
1896f3f1c68Skrishna 	return (CKR_OK);
1906f3f1c68Skrishna }
1916f3f1c68Skrishna 
1927c478bd9Sstevel@tonic-gate CK_RV
1937c478bd9Sstevel@tonic-gate kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate 	crypto_get_mechanism_number_t get_number;
1962321aa36Sda73024 	const char *string;
1977c478bd9Sstevel@tonic-gate 	CK_RV rv;
1987c478bd9Sstevel@tonic-gate 	int r;
1996f3f1c68Skrishna 	kmh_elem_t *elem;
2006f3f1c68Skrishna 	uint_t h;
2012321aa36Sda73024 	char buf[11];   /* Num chars for representing ulong in ASCII */
2026f3f1c68Skrishna 
2036f3f1c68Skrishna 	/*
2046f3f1c68Skrishna 	 * Search for an existing entry. No need to lock since we are
2056f3f1c68Skrishna 	 * just a reader and we never free the entries in the hash table.
2066f3f1c68Skrishna 	 */
2076f3f1c68Skrishna 	h = MECH_HASH(type);
2086f3f1c68Skrishna 	for (elem = kernel_mechhash[h]; elem != NULL; elem = elem->knext) {
2096f3f1c68Skrishna 		if (type == elem->type) {
2106f3f1c68Skrishna 			*k_number = elem->kmech;
2116f3f1c68Skrishna 			return (CKR_OK);
2126f3f1c68Skrishna 		}
2136f3f1c68Skrishna 	}
2147c478bd9Sstevel@tonic-gate 
21576d1b5a9Sda73024 	if (type >= CKM_VENDOR_DEFINED) {
2162321aa36Sda73024 		(void) snprintf(buf, sizeof (buf), "%#lx", type);
2172321aa36Sda73024 		string = buf;
2182321aa36Sda73024 	} else {
2197c478bd9Sstevel@tonic-gate 		string = pkcs11_mech2str(type);
2202321aa36Sda73024 	}
2212321aa36Sda73024 
2227c478bd9Sstevel@tonic-gate 	if (string == NULL)
2237c478bd9Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
2247c478bd9Sstevel@tonic-gate 
2252321aa36Sda73024 	get_number.pn_mechanism_string = (char *)string;
2267c478bd9Sstevel@tonic-gate 	get_number.pn_mechanism_len = strlen(string) + 1;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_GET_MECHANISM_NUMBER,
2297c478bd9Sstevel@tonic-gate 	    &get_number)) < 0) {
2307c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
2317c478bd9Sstevel@tonic-gate 			break;
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 	if (r < 0) {
2347c478bd9Sstevel@tonic-gate 		rv = CKR_MECHANISM_INVALID;
2357c478bd9Sstevel@tonic-gate 	} else {
2367c478bd9Sstevel@tonic-gate 		if (get_number.pn_return_value != CRYPTO_SUCCESS) {
2377c478bd9Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
2387c478bd9Sstevel@tonic-gate 			    get_number.pn_return_value);
2397c478bd9Sstevel@tonic-gate 		} else {
2407c478bd9Sstevel@tonic-gate 			rv = CKR_OK;
2417c478bd9Sstevel@tonic-gate 		}
2427c478bd9Sstevel@tonic-gate 	}
2437c478bd9Sstevel@tonic-gate 
2446f3f1c68Skrishna 	if (rv == CKR_OK) {
2457c478bd9Sstevel@tonic-gate 		*k_number = get_number.pn_internal_number;
2466f3f1c68Skrishna 		/* Add this to the hash table */
2476f3f1c68Skrishna 		(void) kmech_hash_insert(type, *k_number);
2486f3f1c68Skrishna 	}
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	return (rv);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate /*
2557c478bd9Sstevel@tonic-gate  * Return the value of a secret key object.
2567c478bd9Sstevel@tonic-gate  * This routine allocates memory for the value.
2577c478bd9Sstevel@tonic-gate  * A null pointer is returned on error.
2587c478bd9Sstevel@tonic-gate  */
2597c478bd9Sstevel@tonic-gate unsigned char *
2607c478bd9Sstevel@tonic-gate get_symmetric_key_value(kernel_object_t *key_p)
2617c478bd9Sstevel@tonic-gate {
2627c478bd9Sstevel@tonic-gate 	uint8_t *cipherKey;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	switch (key_p->class) {
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	case CKO_SECRET_KEY:
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		cipherKey = malloc(OBJ_SEC(key_p)->sk_value_len);
2697c478bd9Sstevel@tonic-gate 		if (cipherKey == NULL)
2707c478bd9Sstevel@tonic-gate 			return (NULL);
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 		(void) memcpy(cipherKey, OBJ_SEC(key_p)->sk_value,
2737c478bd9Sstevel@tonic-gate 		    OBJ_SEC(key_p)->sk_value_len);
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 		return (cipherKey);
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	default:
2787c478bd9Sstevel@tonic-gate 		return (NULL);
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate /*
2837c478bd9Sstevel@tonic-gate  * Convert a RSA private key object into a crypto_key structure.
2847c478bd9Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the crypto_key
2857c478bd9Sstevel@tonic-gate  * structure.  Memory for the crypto_key structure is not
2867c478bd9Sstevel@tonic-gate  * allocated.  Attributes can be freed by free_key_attributes().
2877c478bd9Sstevel@tonic-gate  */
2887c478bd9Sstevel@tonic-gate CK_RV
2897c478bd9Sstevel@tonic-gate get_rsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
2907c478bd9Sstevel@tonic-gate {
2917c478bd9Sstevel@tonic-gate 	biginteger_t *big;
2927c478bd9Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
2937c478bd9Sstevel@tonic-gate 	char *ptr;
2947c478bd9Sstevel@tonic-gate 	CK_RV rv;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
2977c478bd9Sstevel@tonic-gate 	if (object_p->key_type != CKK_RSA ||
2987c478bd9Sstevel@tonic-gate 	    object_p->class != CKO_PRIVATE_KEY) {
2997c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
3007c478bd9Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_TYPE_INVALID);
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	attrs = calloc(1,
3047c478bd9Sstevel@tonic-gate 	    RSA_PRI_ATTR_COUNT * sizeof (crypto_object_attribute_t));
3057c478bd9Sstevel@tonic-gate 	if (attrs == NULL) {
3067c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
3077c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
3087c478bd9Sstevel@tonic-gate 	}
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
3117c478bd9Sstevel@tonic-gate 	key->ck_attrs = attrs;
3127c478bd9Sstevel@tonic-gate 	cur_attr = attrs;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	/*
3157c478bd9Sstevel@tonic-gate 	 * Allocate memory for each key attribute and set up the value
3167c478bd9Sstevel@tonic-gate 	 * value length.
3177c478bd9Sstevel@tonic-gate 	 */
3187c478bd9Sstevel@tonic-gate 	key->ck_count = 0;
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	/* CKA_MODULUS is required. */
3217c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_RSA_MOD(object_p);
3227c478bd9Sstevel@tonic-gate 	if (big->big_value == NULL) {
3237c478bd9Sstevel@tonic-gate 		rv = CKR_ATTRIBUTE_TYPE_INVALID;
3247c478bd9Sstevel@tonic-gate 		goto fail_cleanup;
3257c478bd9Sstevel@tonic-gate 	} else {
3267c478bd9Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3277c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3287c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
3297c478bd9Sstevel@tonic-gate 		}
3307c478bd9Sstevel@tonic-gate 		ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
3317c478bd9Sstevel@tonic-gate 		key->ck_count++;
3327c478bd9Sstevel@tonic-gate 	}
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	/* CKA_PRIVATE_EXPONENT is required. */
3357c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_RSA_PRIEXPO(object_p);
3367c478bd9Sstevel@tonic-gate 	if (big->big_value == NULL) {
3377c478bd9Sstevel@tonic-gate 		rv = CKR_ATTRIBUTE_TYPE_INVALID;
3387c478bd9Sstevel@tonic-gate 		goto fail_cleanup;
3397c478bd9Sstevel@tonic-gate 	} else {
3407c478bd9Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3417c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3427c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
3437c478bd9Sstevel@tonic-gate 		}
3447c478bd9Sstevel@tonic-gate 		ENCODE_ATTR(CKA_PRIVATE_EXPONENT, big->big_value,
3457c478bd9Sstevel@tonic-gate 		    big->big_value_len);
3467c478bd9Sstevel@tonic-gate 		key->ck_count++;
3477c478bd9Sstevel@tonic-gate 	}
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	/* CKA_PRIME_1 is optional. */
3507c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_RSA_PRIME1(object_p);
3517c478bd9Sstevel@tonic-gate 	if (big->big_value != NULL) {
3527c478bd9Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3537c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3547c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
3557c478bd9Sstevel@tonic-gate 		}
3567c478bd9Sstevel@tonic-gate 		ENCODE_ATTR(CKA_PRIME_1, big->big_value, big->big_value_len);
3577c478bd9Sstevel@tonic-gate 		key->ck_count++;
3587c478bd9Sstevel@tonic-gate 	}
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	/* CKA_PRIME_2 is optional. */
3617c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_RSA_PRIME2(object_p);
3627c478bd9Sstevel@tonic-gate 	if (big->big_value != NULL) {
3637c478bd9Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3647c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3657c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
3667c478bd9Sstevel@tonic-gate 		}
3677c478bd9Sstevel@tonic-gate 		ENCODE_ATTR(CKA_PRIME_2, big->big_value, big->big_value_len);
3687c478bd9Sstevel@tonic-gate 		key->ck_count++;
3697c478bd9Sstevel@tonic-gate 	}
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	/* CKA_EXPONENT_1 is optional. */
3727c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_RSA_EXPO1(object_p);
3737c478bd9Sstevel@tonic-gate 	if (big->big_value != NULL) {
3747c478bd9Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3757c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3767c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
3777c478bd9Sstevel@tonic-gate 		}
3787c478bd9Sstevel@tonic-gate 		ENCODE_ATTR(CKA_EXPONENT_1, big->big_value,
3797c478bd9Sstevel@tonic-gate 		    big->big_value_len);
3807c478bd9Sstevel@tonic-gate 		key->ck_count++;
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	/* CKA_EXPONENT_2 is optional. */
3847c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_RSA_EXPO2(object_p);
3857c478bd9Sstevel@tonic-gate 	if (big->big_value != NULL) {
3867c478bd9Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3877c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3887c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
3897c478bd9Sstevel@tonic-gate 		}
3907c478bd9Sstevel@tonic-gate 		ENCODE_ATTR(CKA_EXPONENT_2, big->big_value,
3917c478bd9Sstevel@tonic-gate 		    big->big_value_len);
3927c478bd9Sstevel@tonic-gate 		key->ck_count++;
3937c478bd9Sstevel@tonic-gate 	}
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	/* CKA_COEFFICIENT is optional. */
3967c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_RSA_COEF(object_p);
3977c478bd9Sstevel@tonic-gate 	if (big->big_value != NULL) {
3987c478bd9Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3997c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
4007c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
4017c478bd9Sstevel@tonic-gate 		}
4027c478bd9Sstevel@tonic-gate 		ENCODE_ATTR(CKA_COEFFICIENT, big->big_value,
4037c478bd9Sstevel@tonic-gate 		    big->big_value_len);
4047c478bd9Sstevel@tonic-gate 		key->ck_count++;
4057c478bd9Sstevel@tonic-gate 	}
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
4087c478bd9Sstevel@tonic-gate 	return (CKR_OK);
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate fail_cleanup:
4117c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
4127c478bd9Sstevel@tonic-gate 	free_key_attributes(key);
4137c478bd9Sstevel@tonic-gate 	return (rv);
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate /*
4177c478bd9Sstevel@tonic-gate  * Convert a RSA public key object into a crypto_key structure.
4187c478bd9Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the crypto_key
4197c478bd9Sstevel@tonic-gate  * structure.  Memory for the crypto_key structure is not
4207c478bd9Sstevel@tonic-gate  * allocated.  Attributes can be freed by free_key_attributes().
4217c478bd9Sstevel@tonic-gate  */
4227c478bd9Sstevel@tonic-gate CK_RV
4237c478bd9Sstevel@tonic-gate get_rsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate 	biginteger_t *big;
4267c478bd9Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
4277c478bd9Sstevel@tonic-gate 	char *ptr;
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
4307c478bd9Sstevel@tonic-gate 	if (object_p->key_type != CKK_RSA ||
4317c478bd9Sstevel@tonic-gate 	    object_p->class != CKO_PUBLIC_KEY) {
4327c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
4337c478bd9Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_TYPE_INVALID);
4347c478bd9Sstevel@tonic-gate 	}
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	attrs = calloc(1,
4377c478bd9Sstevel@tonic-gate 	    RSA_PUB_ATTR_COUNT * sizeof (crypto_object_attribute_t));
4387c478bd9Sstevel@tonic-gate 	if (attrs == NULL) {
4397c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
4407c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
4417c478bd9Sstevel@tonic-gate 	}
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
4447c478bd9Sstevel@tonic-gate 	key->ck_count = RSA_PUB_ATTR_COUNT;
4457c478bd9Sstevel@tonic-gate 	key->ck_attrs = attrs;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	cur_attr = attrs;
4487c478bd9Sstevel@tonic-gate 	big = OBJ_PUB_RSA_PUBEXPO(object_p);
4497c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
4507c478bd9Sstevel@tonic-gate 		goto mem_failure;
4517c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_PUBLIC_EXPONENT, big->big_value, big->big_value_len);
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	big = OBJ_PUB_RSA_MOD(object_p);
4547c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
4557c478bd9Sstevel@tonic-gate 		goto mem_failure;
4567c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(sizeof (CK_ULONG))) == NULL)
4597c478bd9Sstevel@tonic-gate 		goto mem_failure;
4607c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_MODULUS_BITS, &OBJ_PUB_RSA_MOD_BITS(object_p),
4617c478bd9Sstevel@tonic-gate 	    sizeof (CK_ULONG));
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
4647c478bd9Sstevel@tonic-gate 	return (CKR_OK);
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate mem_failure:
4677c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
4687c478bd9Sstevel@tonic-gate 	free_key_attributes(key);
4697c478bd9Sstevel@tonic-gate 	return (CKR_HOST_MEMORY);
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate /*
4737c478bd9Sstevel@tonic-gate  * Free attribute storage in a crypto_key structure.
4747c478bd9Sstevel@tonic-gate  */
4757c478bd9Sstevel@tonic-gate void
4767c478bd9Sstevel@tonic-gate free_key_attributes(crypto_key_t *key)
4777c478bd9Sstevel@tonic-gate {
4787c478bd9Sstevel@tonic-gate 	int i;
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	if (key->ck_format == CRYPTO_KEY_ATTR_LIST &&
4817c478bd9Sstevel@tonic-gate 	    (key->ck_count > 0) && key->ck_attrs != NULL) {
4827c478bd9Sstevel@tonic-gate 		for (i = 0; i < key->ck_count; i++) {
4837c478bd9Sstevel@tonic-gate 			if (key->ck_attrs[i].oa_value != NULL) {
4847c478bd9Sstevel@tonic-gate 				bzero(key->ck_attrs[i].oa_value,
4857c478bd9Sstevel@tonic-gate 				    key->ck_attrs[i].oa_value_len);
4867c478bd9Sstevel@tonic-gate 				free(key->ck_attrs[i].oa_value);
4877c478bd9Sstevel@tonic-gate 			}
4887c478bd9Sstevel@tonic-gate 		}
4897c478bd9Sstevel@tonic-gate 		free(key->ck_attrs);
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate /*
4957c478bd9Sstevel@tonic-gate  * Convert a DSA private key object into a crypto_key structure.
4967c478bd9Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the crypto_key
4977c478bd9Sstevel@tonic-gate  * structure.  Memory for the crypto_key structure is not
4987c478bd9Sstevel@tonic-gate  * allocated.  Attributes can be freed by free_dsa_key_attributes().
4997c478bd9Sstevel@tonic-gate  */
5007c478bd9Sstevel@tonic-gate CK_RV
5017c478bd9Sstevel@tonic-gate get_dsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
5027c478bd9Sstevel@tonic-gate {
5037c478bd9Sstevel@tonic-gate 	biginteger_t *big;
5047c478bd9Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
5057c478bd9Sstevel@tonic-gate 	char *ptr;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
5087c478bd9Sstevel@tonic-gate 	if (object_p->key_type != CKK_DSA ||
5097c478bd9Sstevel@tonic-gate 	    object_p->class != CKO_PRIVATE_KEY) {
5107c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5117c478bd9Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_TYPE_INVALID);
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	attrs = calloc(1,
5157c478bd9Sstevel@tonic-gate 	    DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
5167c478bd9Sstevel@tonic-gate 	if (attrs == NULL) {
5177c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5187c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
5227c478bd9Sstevel@tonic-gate 	key->ck_count = DSA_ATTR_COUNT;
5237c478bd9Sstevel@tonic-gate 	key->ck_attrs = attrs;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	cur_attr = attrs;
5267c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_DSA_PRIME(object_p);
5277c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5287c478bd9Sstevel@tonic-gate 		goto mem_failure;
5297c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_DSA_SUBPRIME(object_p);
5327c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5337c478bd9Sstevel@tonic-gate 		goto mem_failure;
5347c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_DSA_BASE(object_p);
5377c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5387c478bd9Sstevel@tonic-gate 		goto mem_failure;
5397c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	big = OBJ_PRI_DSA_VALUE(object_p);
5427c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5437c478bd9Sstevel@tonic-gate 		goto mem_failure;
5447c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
5477c478bd9Sstevel@tonic-gate 	return (CKR_OK);
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate mem_failure:
5507c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
5517c478bd9Sstevel@tonic-gate 	free_key_attributes(key);
5527c478bd9Sstevel@tonic-gate 	return (CKR_HOST_MEMORY);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate /*
5577c478bd9Sstevel@tonic-gate  * Convert a DSA public key object into a crypto_key structure.
5587c478bd9Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the crypto_key
5597c478bd9Sstevel@tonic-gate  * structure.  Memory for the crypto_key structure is not
5607c478bd9Sstevel@tonic-gate  * allocated.  Attributes can be freed by free_dsa_key_attributes().
5617c478bd9Sstevel@tonic-gate  */
5627c478bd9Sstevel@tonic-gate CK_RV
5637c478bd9Sstevel@tonic-gate get_dsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
5647c478bd9Sstevel@tonic-gate {
5657c478bd9Sstevel@tonic-gate 	biginteger_t *big;
5667c478bd9Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
5677c478bd9Sstevel@tonic-gate 	char *ptr;
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
5707c478bd9Sstevel@tonic-gate 	if (object_p->key_type != CKK_DSA ||
5717c478bd9Sstevel@tonic-gate 	    object_p->class != CKO_PUBLIC_KEY) {
5727c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5737c478bd9Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_TYPE_INVALID);
5747c478bd9Sstevel@tonic-gate 	}
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	attrs = calloc(1,
5777c478bd9Sstevel@tonic-gate 	    DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
5787c478bd9Sstevel@tonic-gate 	if (attrs == NULL) {
5797c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5807c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
5847c478bd9Sstevel@tonic-gate 	key->ck_count = DSA_ATTR_COUNT;
5857c478bd9Sstevel@tonic-gate 	key->ck_attrs = attrs;
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	cur_attr = attrs;
5887c478bd9Sstevel@tonic-gate 	big = OBJ_PUB_DSA_PRIME(object_p);
5897c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5907c478bd9Sstevel@tonic-gate 		goto mem_failure;
5917c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	big = OBJ_PUB_DSA_SUBPRIME(object_p);
5947c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5957c478bd9Sstevel@tonic-gate 		goto mem_failure;
5967c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	big = OBJ_PUB_DSA_BASE(object_p);
5997c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
6007c478bd9Sstevel@tonic-gate 		goto mem_failure;
6017c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	big = OBJ_PUB_DSA_VALUE(object_p);
6047c478bd9Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
6057c478bd9Sstevel@tonic-gate 		goto mem_failure;
6067c478bd9Sstevel@tonic-gate 	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
6097c478bd9Sstevel@tonic-gate 	return (CKR_OK);
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate mem_failure:
6127c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
6137c478bd9Sstevel@tonic-gate 	free_key_attributes(key);
6147c478bd9Sstevel@tonic-gate 	return (CKR_HOST_MEMORY);
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate /*
619034448feSmcpowers  * Convert a EC private key object into a crypto_key structure.
620034448feSmcpowers  * Memory is allocated for each attribute stored in the crypto_key
621034448feSmcpowers  * structure.  Memory for the crypto_key structure is not
622034448feSmcpowers  * allocated.  Attributes can be freed by free_ec_key_attributes().
623034448feSmcpowers  */
624034448feSmcpowers CK_RV
625034448feSmcpowers get_ec_private_key(kernel_object_t *object_p, crypto_key_t *key)
626034448feSmcpowers {
627034448feSmcpowers 	biginteger_t *big;
628034448feSmcpowers 	crypto_object_attribute_t *attrs, *cur_attr;
629034448feSmcpowers 	CK_ATTRIBUTE tmp;
630034448feSmcpowers 	char *ptr;
631034448feSmcpowers 	int rv;
632034448feSmcpowers 
633034448feSmcpowers 	(void) pthread_mutex_lock(&object_p->object_mutex);
634034448feSmcpowers 	if (object_p->key_type != CKK_EC ||
635034448feSmcpowers 	    object_p->class != CKO_PRIVATE_KEY) {
636034448feSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
637034448feSmcpowers 		return (CKR_ATTRIBUTE_TYPE_INVALID);
638034448feSmcpowers 	}
639034448feSmcpowers 
640d2b32306Smcpowers 	attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
641034448feSmcpowers 	if (attrs == NULL) {
642034448feSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
643034448feSmcpowers 		return (CKR_HOST_MEMORY);
644034448feSmcpowers 	}
645034448feSmcpowers 
646034448feSmcpowers 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
647d2b32306Smcpowers 	key->ck_count = EC_ATTR_COUNT;
648034448feSmcpowers 	key->ck_attrs = attrs;
649034448feSmcpowers 
650034448feSmcpowers 	cur_attr = attrs;
651034448feSmcpowers 	big = OBJ_PRI_EC_VALUE(object_p);
652034448feSmcpowers 	if ((ptr = malloc(big->big_value_len)) == NULL) {
653034448feSmcpowers 		rv = CKR_HOST_MEMORY;
654034448feSmcpowers 		goto fail;
655034448feSmcpowers 	}
656034448feSmcpowers 	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
657034448feSmcpowers 
658034448feSmcpowers 	tmp.type = CKA_EC_PARAMS;
659034448feSmcpowers 	tmp.pValue = NULL;
660034448feSmcpowers 	rv = kernel_get_attribute(object_p, &tmp);
661034448feSmcpowers 	if (rv != CKR_OK) {
662034448feSmcpowers 		goto fail;
663034448feSmcpowers 	}
664034448feSmcpowers 
665034448feSmcpowers 	tmp.pValue = malloc(tmp.ulValueLen);
666034448feSmcpowers 	if (tmp.pValue == NULL) {
667034448feSmcpowers 		rv = CKR_HOST_MEMORY;
668034448feSmcpowers 		goto fail;
669034448feSmcpowers 	}
670034448feSmcpowers 
671034448feSmcpowers 	rv = kernel_get_attribute(object_p, &tmp);
672034448feSmcpowers 	if (rv != CKR_OK) {
673034448feSmcpowers 		free(tmp.pValue);
674034448feSmcpowers 		goto fail;
675034448feSmcpowers 	}
676034448feSmcpowers 
677034448feSmcpowers 	cur_attr->oa_type = tmp.type;
678034448feSmcpowers 	cur_attr->oa_value = tmp.pValue;
679034448feSmcpowers 	cur_attr->oa_value_len = tmp.ulValueLen;
680034448feSmcpowers 
681034448feSmcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
682034448feSmcpowers 	return (CKR_OK);
683034448feSmcpowers 
684034448feSmcpowers fail:
685034448feSmcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
686034448feSmcpowers 	free_key_attributes(key);
687034448feSmcpowers 	return (rv);
688034448feSmcpowers }
689034448feSmcpowers 
690034448feSmcpowers /*
691034448feSmcpowers  * Convert an EC public key object into a crypto_key structure.
692034448feSmcpowers  * Memory is allocated for each attribute stored in the crypto_key
693034448feSmcpowers  * structure.  Memory for the crypto_key structure is not
694034448feSmcpowers  * allocated.  Attributes can be freed by free_ec_key_attributes().
695034448feSmcpowers  */
696034448feSmcpowers CK_RV
697034448feSmcpowers get_ec_public_key(kernel_object_t *object_p, crypto_key_t *key)
698034448feSmcpowers {
699034448feSmcpowers 	biginteger_t *big;
700034448feSmcpowers 	crypto_object_attribute_t *attrs, *cur_attr;
701d2b32306Smcpowers 	CK_ATTRIBUTE tmp;
702034448feSmcpowers 	char *ptr;
703d2b32306Smcpowers 	int rv;
704034448feSmcpowers 
705034448feSmcpowers 	(void) pthread_mutex_lock(&object_p->object_mutex);
706034448feSmcpowers 	if (object_p->key_type != CKK_EC ||
707034448feSmcpowers 	    object_p->class != CKO_PUBLIC_KEY) {
708034448feSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
709034448feSmcpowers 		return (CKR_ATTRIBUTE_TYPE_INVALID);
710034448feSmcpowers 	}
711034448feSmcpowers 
712d2b32306Smcpowers 	attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
713034448feSmcpowers 	if (attrs == NULL) {
714034448feSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
715034448feSmcpowers 		return (CKR_HOST_MEMORY);
716034448feSmcpowers 	}
717034448feSmcpowers 
718034448feSmcpowers 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
719034448feSmcpowers 	key->ck_count = EC_ATTR_COUNT;
720034448feSmcpowers 	key->ck_attrs = attrs;
721034448feSmcpowers 
722034448feSmcpowers 	cur_attr = attrs;
723034448feSmcpowers 	big = OBJ_PUB_EC_POINT(object_p);
724034448feSmcpowers 	if ((ptr = malloc(big->big_value_len)) == NULL) {
725d2b32306Smcpowers 		rv = CKR_HOST_MEMORY;
726d2b32306Smcpowers 		goto fail;
727034448feSmcpowers 	}
728034448feSmcpowers 	ENCODE_ATTR(CKA_EC_POINT, big->big_value, big->big_value_len);
729034448feSmcpowers 
730d2b32306Smcpowers 	tmp.type = CKA_EC_PARAMS;
731d2b32306Smcpowers 	tmp.pValue = NULL;
732d2b32306Smcpowers 	rv = kernel_get_attribute(object_p, &tmp);
733d2b32306Smcpowers 	if (rv != CKR_OK) {
734d2b32306Smcpowers 		goto fail;
735d2b32306Smcpowers 	}
736d2b32306Smcpowers 
737d2b32306Smcpowers 	tmp.pValue = malloc(tmp.ulValueLen);
738d2b32306Smcpowers 	if (tmp.pValue == NULL) {
739d2b32306Smcpowers 		rv = CKR_HOST_MEMORY;
740d2b32306Smcpowers 		goto fail;
741d2b32306Smcpowers 	}
742d2b32306Smcpowers 
743d2b32306Smcpowers 	rv = kernel_get_attribute(object_p, &tmp);
744d2b32306Smcpowers 	if (rv != CKR_OK) {
745d2b32306Smcpowers 		free(tmp.pValue);
746d2b32306Smcpowers 		goto fail;
747d2b32306Smcpowers 	}
748d2b32306Smcpowers 
749d2b32306Smcpowers 	cur_attr->oa_type = tmp.type;
750d2b32306Smcpowers 	cur_attr->oa_value = tmp.pValue;
751d2b32306Smcpowers 	cur_attr->oa_value_len = tmp.ulValueLen;
752d2b32306Smcpowers 
753034448feSmcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
754034448feSmcpowers 	return (CKR_OK);
755d2b32306Smcpowers 
756d2b32306Smcpowers fail:
757d2b32306Smcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
758d2b32306Smcpowers 	free_key_attributes(key);
759d2b32306Smcpowers 	return (rv);
760034448feSmcpowers }
761034448feSmcpowers 
762034448feSmcpowers /*
7637c478bd9Sstevel@tonic-gate  * Convert an attribute template into an obj_attrs array.
7647c478bd9Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the obj_attrs.
7657c478bd9Sstevel@tonic-gate  * The memory can be freed by free_object_attributes().
7667c478bd9Sstevel@tonic-gate  *
7677c478bd9Sstevel@tonic-gate  * If the boolean pointer is_token_obj is not NULL, the caller wants to
7687c478bd9Sstevel@tonic-gate  * retrieve the value of the CKA_TOKEN attribute if it is specified in the
7697c478bd9Sstevel@tonic-gate  * template.
7707c478bd9Sstevel@tonic-gate  * - When this routine is called thru C_CreateObject(), C_CopyObject(), or
7717c478bd9Sstevel@tonic-gate  *   any key management function, is_token_obj should NOT be NULL.
7727c478bd9Sstevel@tonic-gate  * - When this routine is called thru C_GetAttributeValue() or
7737c478bd9Sstevel@tonic-gate  *   C_SetAttributeValue(), "is_token_obj" should be NULL.
7747c478bd9Sstevel@tonic-gate  */
7757c478bd9Sstevel@tonic-gate CK_RV
7767c478bd9Sstevel@tonic-gate process_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
7777c478bd9Sstevel@tonic-gate     caddr_t *obj_attrs, CK_BBOOL *is_token_obj)
7787c478bd9Sstevel@tonic-gate {
7797c478bd9Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
7807c478bd9Sstevel@tonic-gate 	int i, cur_i;
7817c478bd9Sstevel@tonic-gate 	char *ptr;
7827c478bd9Sstevel@tonic-gate 	CK_RV rv;
7837c478bd9Sstevel@tonic-gate 	ssize_t value_len;
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate 	if (ulCount == 0) {
7867c478bd9Sstevel@tonic-gate 		obj_attrs = NULL;
7877c478bd9Sstevel@tonic-gate 		return (CKR_OK);
7887c478bd9Sstevel@tonic-gate 	}
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	attrs = calloc(1, ulCount * sizeof (crypto_object_attribute_t));
7917c478bd9Sstevel@tonic-gate 	if (attrs == NULL) {
7927c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
7937c478bd9Sstevel@tonic-gate 	}
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	cur_attr = attrs;
7967c478bd9Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
7977c478bd9Sstevel@tonic-gate 		/*
7987c478bd9Sstevel@tonic-gate 		 * The length of long attributes must be set correctly
7997c478bd9Sstevel@tonic-gate 		 * so providers can determine whether they came from 32
8007c478bd9Sstevel@tonic-gate 		 * or 64-bit applications.
8017c478bd9Sstevel@tonic-gate 		 */
8027c478bd9Sstevel@tonic-gate 		switch (pTemplate[i].type) {
8037c478bd9Sstevel@tonic-gate 		case CKA_CLASS:
8047c478bd9Sstevel@tonic-gate 		case CKA_CERTIFICATE_TYPE:
8057c478bd9Sstevel@tonic-gate 		case CKA_KEY_TYPE:
806034448feSmcpowers 		case CKA_MODULUS_BITS:
8077c478bd9Sstevel@tonic-gate 		case CKA_HW_FEATURE_TYPE:
8087c478bd9Sstevel@tonic-gate 			value_len = sizeof (ulong_t);
809894b2776Smcpowers 			if (pTemplate[i].pValue != NULL &&
810894b2776Smcpowers 			    (pTemplate[i].ulValueLen < value_len)) {
8117739299dSAnthony Scarpino 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
8127c478bd9Sstevel@tonic-gate 				cur_i = i;
8137c478bd9Sstevel@tonic-gate 				goto fail_cleanup;
8147c478bd9Sstevel@tonic-gate 			}
8157c478bd9Sstevel@tonic-gate 			break;
8167c478bd9Sstevel@tonic-gate 		default:
8177c478bd9Sstevel@tonic-gate 			value_len = pTemplate[i].ulValueLen;
8187c478bd9Sstevel@tonic-gate 		}
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 		cur_attr->oa_type = pTemplate[i].type;
8217c478bd9Sstevel@tonic-gate 		cur_attr->oa_value_len = value_len;
8227c478bd9Sstevel@tonic-gate 		cur_attr->oa_value = NULL;
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 		if ((pTemplate[i].pValue != NULL) &&
8257c478bd9Sstevel@tonic-gate 		    (pTemplate[i].ulValueLen > 0)) {
8267c478bd9Sstevel@tonic-gate 			ptr = malloc(pTemplate[i].ulValueLen);
8277c478bd9Sstevel@tonic-gate 			if (ptr == NULL) {
8287c478bd9Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
8297c478bd9Sstevel@tonic-gate 				cur_i = i;
8307c478bd9Sstevel@tonic-gate 				goto fail_cleanup;
8317c478bd9Sstevel@tonic-gate 			} else {
8327c478bd9Sstevel@tonic-gate 				(void) memcpy(ptr, pTemplate[i].pValue,
8337c478bd9Sstevel@tonic-gate 				    pTemplate[i].ulValueLen);
8347c478bd9Sstevel@tonic-gate 				cur_attr->oa_value = ptr;
8357c478bd9Sstevel@tonic-gate 			}
8367c478bd9Sstevel@tonic-gate 		}
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 		if ((is_token_obj != NULL) &&
8397c478bd9Sstevel@tonic-gate 		    (pTemplate[i].type == CKA_TOKEN)) {
8407c478bd9Sstevel@tonic-gate 			/* Get the CKA_TOKEN attribute value. */
8417c478bd9Sstevel@tonic-gate 			if (pTemplate[i].pValue == NULL) {
8427c478bd9Sstevel@tonic-gate 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
8437c478bd9Sstevel@tonic-gate 				cur_i = i;
8447c478bd9Sstevel@tonic-gate 				goto fail_cleanup;
8457c478bd9Sstevel@tonic-gate 			} else {
8467c478bd9Sstevel@tonic-gate 				*is_token_obj =
8477c478bd9Sstevel@tonic-gate 				    *(CK_BBOOL *)pTemplate[i].pValue;
8487c478bd9Sstevel@tonic-gate 			}
8497c478bd9Sstevel@tonic-gate 		}
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 		cur_attr++;
8527c478bd9Sstevel@tonic-gate 	}
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	*obj_attrs = (char *)attrs;
8557c478bd9Sstevel@tonic-gate 	return (CKR_OK);
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate fail_cleanup:
8587c478bd9Sstevel@tonic-gate 	cur_attr = attrs;
8597c478bd9Sstevel@tonic-gate 	for (i = 0; i < cur_i; i++) {
8607c478bd9Sstevel@tonic-gate 		if (cur_attr->oa_value != NULL) {
8617c478bd9Sstevel@tonic-gate 			(void) free(cur_attr->oa_value);
8627c478bd9Sstevel@tonic-gate 		}
8637c478bd9Sstevel@tonic-gate 		cur_attr++;
8647c478bd9Sstevel@tonic-gate 	}
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	(void) free(attrs);
8677c478bd9Sstevel@tonic-gate 	return (rv);
8687c478bd9Sstevel@tonic-gate }
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate /*
8727c478bd9Sstevel@tonic-gate  * Copy the attribute values from obj_attrs to pTemplate.
8737c478bd9Sstevel@tonic-gate  * The obj_attrs is an image of the Template and is expected to have the
8747c478bd9Sstevel@tonic-gate  * same attributes in the same order and each one of the attribute pValue
8757c478bd9Sstevel@tonic-gate  * in obj_attr has enough space allocated for the corresponding valueLen
8767c478bd9Sstevel@tonic-gate  * in pTemplate.
8777c478bd9Sstevel@tonic-gate  */
8787c478bd9Sstevel@tonic-gate CK_RV
8797c478bd9Sstevel@tonic-gate get_object_attributes(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
8807c478bd9Sstevel@tonic-gate     caddr_t obj_attrs)
8817c478bd9Sstevel@tonic-gate {
8827c478bd9Sstevel@tonic-gate 	crypto_object_attribute_t *cur_attr;
8837c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
8847c478bd9Sstevel@tonic-gate 	int i;
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 	/* LINTED */
8877c478bd9Sstevel@tonic-gate 	cur_attr = (crypto_object_attribute_t *)obj_attrs;
8887c478bd9Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
8897c478bd9Sstevel@tonic-gate 		if (pTemplate[i].type != cur_attr->oa_type) {
8907c478bd9Sstevel@tonic-gate 			/* The attribute type doesn't match, this is bad. */
8917c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
8927c478bd9Sstevel@tonic-gate 			return (rv);
8937c478bd9Sstevel@tonic-gate 		}
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 		pTemplate[i].ulValueLen = cur_attr->oa_value_len;
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 		if ((pTemplate[i].pValue != NULL) &&
8987c478bd9Sstevel@tonic-gate 		    ((CK_LONG)pTemplate[i].ulValueLen != -1)) {
8997c478bd9Sstevel@tonic-gate 			(void) memcpy(pTemplate[i].pValue, cur_attr->oa_value,
9007c478bd9Sstevel@tonic-gate 			    pTemplate[i].ulValueLen);
9017c478bd9Sstevel@tonic-gate 		}
9027c478bd9Sstevel@tonic-gate 		cur_attr++;
9037c478bd9Sstevel@tonic-gate 	}
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 	return (rv);
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate /*
9097c478bd9Sstevel@tonic-gate  * Free the attribute storage in a crypto_object_attribute_t structure.
9107c478bd9Sstevel@tonic-gate  */
9117c478bd9Sstevel@tonic-gate void
9127c478bd9Sstevel@tonic-gate free_object_attributes(caddr_t obj_attrs, CK_ULONG ulCount)
9137c478bd9Sstevel@tonic-gate {
9147c478bd9Sstevel@tonic-gate 	crypto_object_attribute_t *cur_attr;
9157c478bd9Sstevel@tonic-gate 	int i;
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	if ((ulCount == 0) || (obj_attrs == NULL)) {
9187c478bd9Sstevel@tonic-gate 		return;
9197c478bd9Sstevel@tonic-gate 	}
9207c478bd9Sstevel@tonic-gate 
9217c478bd9Sstevel@tonic-gate 	/* LINTED */
9227c478bd9Sstevel@tonic-gate 	cur_attr = (crypto_object_attribute_t *)obj_attrs;
9237c478bd9Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
924034448feSmcpowers 		/* XXX check that oa_value > 0 */
9257c478bd9Sstevel@tonic-gate 		if (cur_attr->oa_value != NULL) {
9267c478bd9Sstevel@tonic-gate 			free(cur_attr->oa_value);
9277c478bd9Sstevel@tonic-gate 		}
9287c478bd9Sstevel@tonic-gate 		cur_attr++;
9297c478bd9Sstevel@tonic-gate 	}
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	free(obj_attrs);
9327c478bd9Sstevel@tonic-gate }
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate /*
9357c478bd9Sstevel@tonic-gate  * This function is called by process_found_objects().  It will check the
9367c478bd9Sstevel@tonic-gate  * CKA_PRIVATE and CKA_TOKEN attributes for the kernel object "oid", then
9377c478bd9Sstevel@tonic-gate  * initialize all the necessary fields in the object wrapper "objp".
9387c478bd9Sstevel@tonic-gate  */
9397c478bd9Sstevel@tonic-gate static CK_RV
9407c478bd9Sstevel@tonic-gate create_new_tobj_in_lib(kernel_slot_t *pslot, kernel_session_t *sp,
9417c478bd9Sstevel@tonic-gate     kernel_object_t *objp,  crypto_object_id_t oid)
9427c478bd9Sstevel@tonic-gate {
9437c478bd9Sstevel@tonic-gate 	CK_RV  rv = CKR_OK;
9447c478bd9Sstevel@tonic-gate 	crypto_object_get_attribute_value_t obj_ga;
9457c478bd9Sstevel@tonic-gate 	boolean_t is_pri_obj;
9467c478bd9Sstevel@tonic-gate 	boolean_t is_token_obj;
9477c478bd9Sstevel@tonic-gate 	CK_BBOOL pri_value, token_value;
9487c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE  pTemplate[2];
9497c478bd9Sstevel@tonic-gate 	int r;
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 	/*
9527c478bd9Sstevel@tonic-gate 	 * Make a CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE ioctl call to get this
9537c478bd9Sstevel@tonic-gate 	 * kernel object's attribute values for CKA_PRIVATE and CKA_TOKEN.
9547c478bd9Sstevel@tonic-gate 	 */
9557c478bd9Sstevel@tonic-gate 	obj_ga.og_session = sp->k_session;
9567c478bd9Sstevel@tonic-gate 	obj_ga.og_handle = oid;
9577c478bd9Sstevel@tonic-gate 	obj_ga.og_count = 2;
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 	pTemplate[0].type = CKA_PRIVATE;
9607c478bd9Sstevel@tonic-gate 	pTemplate[0].pValue = &pri_value;
9617c478bd9Sstevel@tonic-gate 	pTemplate[0].ulValueLen = sizeof (pri_value);
9627c478bd9Sstevel@tonic-gate 	pTemplate[1].type = CKA_TOKEN;
9637c478bd9Sstevel@tonic-gate 	pTemplate[1].pValue = &token_value;
9647c478bd9Sstevel@tonic-gate 	pTemplate[1].ulValueLen = sizeof (token_value);
9657c478bd9Sstevel@tonic-gate 	rv = process_object_attributes(pTemplate, 2, &obj_ga.og_attributes,
9667c478bd9Sstevel@tonic-gate 	    NULL);
9677c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
9687c478bd9Sstevel@tonic-gate 		return (rv);
9697c478bd9Sstevel@tonic-gate 	}
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
9727c478bd9Sstevel@tonic-gate 	    &obj_ga)) < 0) {
9737c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
9747c478bd9Sstevel@tonic-gate 			break;
9757c478bd9Sstevel@tonic-gate 	}
9767c478bd9Sstevel@tonic-gate 	if (r < 0) {
9777c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
9787c478bd9Sstevel@tonic-gate 	} else {
9797c478bd9Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
9807c478bd9Sstevel@tonic-gate 	}
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
9837c478bd9Sstevel@tonic-gate 		rv = get_object_attributes(pTemplate, 2, obj_ga.og_attributes);
9847c478bd9Sstevel@tonic-gate 		if (rv == CKR_OK) {
9857c478bd9Sstevel@tonic-gate 			is_pri_obj = *(CK_BBOOL *)pTemplate[0].pValue;
9867c478bd9Sstevel@tonic-gate 			is_token_obj = *(CK_BBOOL *)pTemplate[1].pValue;
9877c478bd9Sstevel@tonic-gate 		}
9887c478bd9Sstevel@tonic-gate 	}
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 	free_object_attributes(obj_ga.og_attributes, 2);
9917c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
9927c478bd9Sstevel@tonic-gate 		return (rv);
9937c478bd9Sstevel@tonic-gate 	}
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 	/* Make sure it is a token object. */
9967c478bd9Sstevel@tonic-gate 	if (!is_token_obj) {
9977c478bd9Sstevel@tonic-gate 		rv = CKR_ATTRIBUTE_VALUE_INVALID;
9987c478bd9Sstevel@tonic-gate 		return (rv);
9997c478bd9Sstevel@tonic-gate 	}
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 	/* If it is a private object, make sure the user has logged in. */
10027c478bd9Sstevel@tonic-gate 	if (is_pri_obj && (pslot->sl_state != CKU_USER)) {
10037c478bd9Sstevel@tonic-gate 		rv = CKR_ATTRIBUTE_VALUE_INVALID;
10047c478bd9Sstevel@tonic-gate 		return (rv);
10057c478bd9Sstevel@tonic-gate 	}
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	objp->is_lib_obj = B_FALSE;
10087c478bd9Sstevel@tonic-gate 	objp->k_handle = oid;
10097c478bd9Sstevel@tonic-gate 	objp->bool_attr_mask |= TOKEN_BOOL_ON;
10107c478bd9Sstevel@tonic-gate 	if (is_pri_obj) {
10117c478bd9Sstevel@tonic-gate 		objp->bool_attr_mask |= PRIVATE_BOOL_ON;
10127c478bd9Sstevel@tonic-gate 	} else {
10137c478bd9Sstevel@tonic-gate 		objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
10147c478bd9Sstevel@tonic-gate 	}
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&objp->object_mutex, NULL);
10177c478bd9Sstevel@tonic-gate 	objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
10187c478bd9Sstevel@tonic-gate 	objp->session_handle = (CK_SESSION_HANDLE) sp;
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 	return (CKR_OK);
10217c478bd9Sstevel@tonic-gate }
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate /*
10247c478bd9Sstevel@tonic-gate  * This function processes the kernel object handles returned from the
10257c478bd9Sstevel@tonic-gate  * CRYPTO_OBJECT_FIND_UPDATE ioctl and returns an object handle list
10267c478bd9Sstevel@tonic-gate  * and the number of object handles to the caller - C_FindObjects().
10277c478bd9Sstevel@tonic-gate  * The caller acquires the slot lock and the session lock.
10287c478bd9Sstevel@tonic-gate  */
10297c478bd9Sstevel@tonic-gate CK_RV
10307c478bd9Sstevel@tonic-gate process_found_objects(kernel_session_t *cur_sp, CK_OBJECT_HANDLE *obj_found,
10317c478bd9Sstevel@tonic-gate     CK_ULONG *found_obj_count, crypto_object_find_update_t obj_fu)
10327c478bd9Sstevel@tonic-gate {
10337c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
10347c478bd9Sstevel@tonic-gate 	crypto_object_id_t  *oid_p;
10357c478bd9Sstevel@tonic-gate 	kernel_slot_t *pslot;
10367c478bd9Sstevel@tonic-gate 	kernel_object_t *objp;
10377c478bd9Sstevel@tonic-gate 	kernel_object_t *objp1;
10387c478bd9Sstevel@tonic-gate 	kernel_object_t *new_tobj_list = NULL;
10397c478bd9Sstevel@tonic-gate 	kernel_session_t  *sp;
10407c478bd9Sstevel@tonic-gate 	CK_ULONG num_obj_found = 0;
10417c478bd9Sstevel@tonic-gate 	boolean_t is_in_lib;
10427c478bd9Sstevel@tonic-gate 	int i;
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 	if (obj_fu.fu_count == 0) {
10457c478bd9Sstevel@tonic-gate 		*found_obj_count = 0;
10467c478bd9Sstevel@tonic-gate 		return (CKR_OK);
10477c478bd9Sstevel@tonic-gate 	}
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 	pslot = slot_table[cur_sp->ses_slotid];
10507c478bd9Sstevel@tonic-gate 
10517c478bd9Sstevel@tonic-gate 	/* LINTED */
10527c478bd9Sstevel@tonic-gate 	oid_p = (crypto_object_id_t *)obj_fu.fu_handles;
10537c478bd9Sstevel@tonic-gate 	for (i = 0; i < obj_fu.fu_count; i++) {
10547c478bd9Sstevel@tonic-gate 		is_in_lib = B_FALSE;
10557c478bd9Sstevel@tonic-gate 		/*
10567c478bd9Sstevel@tonic-gate 		 * Check if this oid has an object wrapper in the library
10577c478bd9Sstevel@tonic-gate 		 * already.  First, search the slot's token object list.
10587c478bd9Sstevel@tonic-gate 		 */
10597c478bd9Sstevel@tonic-gate 		objp = pslot->sl_tobj_list;
10607c478bd9Sstevel@tonic-gate 		while (!is_in_lib && objp) {
10617c478bd9Sstevel@tonic-gate 			if (objp->k_handle == *oid_p) {
10627c478bd9Sstevel@tonic-gate 				is_in_lib = B_TRUE;
10637c478bd9Sstevel@tonic-gate 			} else {
10647c478bd9Sstevel@tonic-gate 				objp = objp->next;
10657c478bd9Sstevel@tonic-gate 			}
10667c478bd9Sstevel@tonic-gate 		}
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 		/*
10697c478bd9Sstevel@tonic-gate 		 * If it is not in the slot's token object list,
10707c478bd9Sstevel@tonic-gate 		 * search it in all the sessions.
10717c478bd9Sstevel@tonic-gate 		 */
10727c478bd9Sstevel@tonic-gate 		if (!is_in_lib) {
10737c478bd9Sstevel@tonic-gate 			sp = pslot->sl_sess_list;
10747c478bd9Sstevel@tonic-gate 			while (!is_in_lib && sp) {
10757c478bd9Sstevel@tonic-gate 				objp = sp->object_list;
10767c478bd9Sstevel@tonic-gate 				while (!is_in_lib && objp) {
10777c478bd9Sstevel@tonic-gate 					if (objp->k_handle == *oid_p) {
10787c478bd9Sstevel@tonic-gate 						is_in_lib = B_TRUE;
10797c478bd9Sstevel@tonic-gate 					} else {
10807c478bd9Sstevel@tonic-gate 						objp = objp->next;
10817c478bd9Sstevel@tonic-gate 					}
10827c478bd9Sstevel@tonic-gate 				}
10837c478bd9Sstevel@tonic-gate 				sp = sp->next;
10847c478bd9Sstevel@tonic-gate 			}
10857c478bd9Sstevel@tonic-gate 		}
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate 		/*
10887c478bd9Sstevel@tonic-gate 		 * If this object is in the library already, add its object
10897c478bd9Sstevel@tonic-gate 		 * wrapper to the returned find object list.
10907c478bd9Sstevel@tonic-gate 		 */
10917c478bd9Sstevel@tonic-gate 		if (is_in_lib) {
10927c478bd9Sstevel@tonic-gate 			obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
10937c478bd9Sstevel@tonic-gate 		}
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 		/*
10967c478bd9Sstevel@tonic-gate 		 * If we still do not find it in the library.  This object
10977c478bd9Sstevel@tonic-gate 		 * must be a token object pre-existed in the HW provider.
10987c478bd9Sstevel@tonic-gate 		 * We need to create an object wrapper for it in the library.
10997c478bd9Sstevel@tonic-gate 		 */
11007c478bd9Sstevel@tonic-gate 		if (!is_in_lib) {
11017c478bd9Sstevel@tonic-gate 			objp1 = calloc(1, sizeof (kernel_object_t));
11027c478bd9Sstevel@tonic-gate 			if (objp1 == NULL) {
11037c478bd9Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
11047c478bd9Sstevel@tonic-gate 				goto failed_exit;
11057c478bd9Sstevel@tonic-gate 			}
11067c478bd9Sstevel@tonic-gate 			rv = create_new_tobj_in_lib(pslot, cur_sp, objp1,
11077c478bd9Sstevel@tonic-gate 			    *oid_p);
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 			if (rv == CKR_OK) {
11107c478bd9Sstevel@tonic-gate 				/* Save the new object to the new_tobj_list. */
11117c478bd9Sstevel@tonic-gate 				if (new_tobj_list == NULL) {
11127c478bd9Sstevel@tonic-gate 					new_tobj_list = objp1;
11137c478bd9Sstevel@tonic-gate 					objp1->next = NULL;
11147c478bd9Sstevel@tonic-gate 					objp1->prev = NULL;
11157c478bd9Sstevel@tonic-gate 				} else {
11167c478bd9Sstevel@tonic-gate 					new_tobj_list->prev = objp1;
11177c478bd9Sstevel@tonic-gate 					objp1->next = new_tobj_list;
11187c478bd9Sstevel@tonic-gate 					objp1->prev = NULL;
11197c478bd9Sstevel@tonic-gate 					new_tobj_list = objp1;
11207c478bd9Sstevel@tonic-gate 				}
11217c478bd9Sstevel@tonic-gate 			} else {
11227c478bd9Sstevel@tonic-gate 				/*
11237c478bd9Sstevel@tonic-gate 				 * If create_new_tobj_in_lib() doesn't fail
11247c478bd9Sstevel@tonic-gate 				 * with CKR_HOST_MEMORY, the failure should be
11257c478bd9Sstevel@tonic-gate 				 * caused by the attributes' checking. We will
11267c478bd9Sstevel@tonic-gate 				 * just ignore this object and continue on.
11277c478bd9Sstevel@tonic-gate 				 */
11287c478bd9Sstevel@tonic-gate 				free(objp1);
11297c478bd9Sstevel@tonic-gate 				if (rv == CKR_HOST_MEMORY) {
11307c478bd9Sstevel@tonic-gate 					goto failed_exit;
11317c478bd9Sstevel@tonic-gate 				}
11327c478bd9Sstevel@tonic-gate 			}
11337c478bd9Sstevel@tonic-gate 		}
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 		/* Process next one */
11367c478bd9Sstevel@tonic-gate 		oid_p++;
11377c478bd9Sstevel@tonic-gate 	}
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 	/*
11407c478bd9Sstevel@tonic-gate 	 * Add the newly created token object wrappers to the found object
11417c478bd9Sstevel@tonic-gate 	 * list and to the slot's token object list.
11427c478bd9Sstevel@tonic-gate 	 */
11437c478bd9Sstevel@tonic-gate 	if (new_tobj_list != NULL) {
11447c478bd9Sstevel@tonic-gate 		/* Add to the obj_found array. */
11457c478bd9Sstevel@tonic-gate 		objp = new_tobj_list;
11467c478bd9Sstevel@tonic-gate 		while (objp) {
11477c478bd9Sstevel@tonic-gate 			obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
11487c478bd9Sstevel@tonic-gate 			if (objp->next == NULL) {
11497c478bd9Sstevel@tonic-gate 				break;
11507c478bd9Sstevel@tonic-gate 			}
11517c478bd9Sstevel@tonic-gate 			objp = objp->next;
11527c478bd9Sstevel@tonic-gate 		}
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 		/* Add to the beginning of the slot's token object list. */
11557c478bd9Sstevel@tonic-gate 		if (pslot->sl_tobj_list != NULL) {
11567c478bd9Sstevel@tonic-gate 			objp->next = pslot->sl_tobj_list;
11577c478bd9Sstevel@tonic-gate 			pslot->sl_tobj_list->prev = objp;
11587c478bd9Sstevel@tonic-gate 		}
11597c478bd9Sstevel@tonic-gate 		pslot->sl_tobj_list = new_tobj_list;
11607c478bd9Sstevel@tonic-gate 	}
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	*found_obj_count = num_obj_found;
11637c478bd9Sstevel@tonic-gate 	return (CKR_OK);
11647c478bd9Sstevel@tonic-gate 
11657c478bd9Sstevel@tonic-gate failed_exit:
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate 	/* Free the newly created token object wrappers. */
11687c478bd9Sstevel@tonic-gate 	objp = new_tobj_list;
11697c478bd9Sstevel@tonic-gate 	while (objp) {
11707c478bd9Sstevel@tonic-gate 		objp1 = objp->next;
11717c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_destroy(&objp->object_mutex);
11727c478bd9Sstevel@tonic-gate 		free(objp);
11737c478bd9Sstevel@tonic-gate 		objp = objp1;
11747c478bd9Sstevel@tonic-gate 	}
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate 	return (rv);
11777c478bd9Sstevel@tonic-gate }
11787c478bd9Sstevel@tonic-gate 
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate /*
11817c478bd9Sstevel@tonic-gate  * Get the value of the CKA_PRIVATE attribute for the object just returned
11827c478bd9Sstevel@tonic-gate  * from the HW provider.  This function will be called by any function
11837c478bd9Sstevel@tonic-gate  * that creates a new object, because the CKA_PRIVATE value of an object is
11842321aa36Sda73024  * token specific.  The CKA_PRIVATE attribute value of the new object will be
11857c478bd9Sstevel@tonic-gate  * stored in the object structure in the library, which will be used later at
11867c478bd9Sstevel@tonic-gate  * C_Logout to clean up all private objects.
11877c478bd9Sstevel@tonic-gate  */
11887c478bd9Sstevel@tonic-gate CK_RV
11897c478bd9Sstevel@tonic-gate get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
11907c478bd9Sstevel@tonic-gate     CK_BBOOL *is_pri_obj)
11917c478bd9Sstevel@tonic-gate {
11927c478bd9Sstevel@tonic-gate 	CK_RV  rv = CKR_OK;
11937c478bd9Sstevel@tonic-gate 	crypto_object_get_attribute_value_t obj_ga;
11947c478bd9Sstevel@tonic-gate 	crypto_object_attribute_t obj_attr;
11957c478bd9Sstevel@tonic-gate 	CK_BBOOL pri_value;
11967c478bd9Sstevel@tonic-gate 	int r;
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate 	obj_ga.og_session = sp->k_session;
11997c478bd9Sstevel@tonic-gate 	obj_ga.og_handle = oid;
12007c478bd9Sstevel@tonic-gate 	obj_ga.og_count = 1;
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate 	obj_attr.oa_type = CKA_PRIVATE;
12037c478bd9Sstevel@tonic-gate 	obj_attr.oa_value = (char *)&pri_value;
12047c478bd9Sstevel@tonic-gate 	obj_attr.oa_value_len = sizeof (CK_BBOOL);
12057c478bd9Sstevel@tonic-gate 	obj_ga.og_attributes = (char *)&obj_attr;
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
12087c478bd9Sstevel@tonic-gate 	    &obj_ga)) < 0) {
12097c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
12107c478bd9Sstevel@tonic-gate 			break;
12117c478bd9Sstevel@tonic-gate 	}
12127c478bd9Sstevel@tonic-gate 	if (r < 0) {
12137c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
12147c478bd9Sstevel@tonic-gate 	} else {
12157c478bd9Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
12167c478bd9Sstevel@tonic-gate 	}
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
12197c478bd9Sstevel@tonic-gate 		*is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
12207c478bd9Sstevel@tonic-gate 	}
12217c478bd9Sstevel@tonic-gate 
12227c478bd9Sstevel@tonic-gate 	return (rv);
12237c478bd9Sstevel@tonic-gate }
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate 
12267c478bd9Sstevel@tonic-gate CK_RV
12277c478bd9Sstevel@tonic-gate get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
12287c478bd9Sstevel@tonic-gate     CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
12297c478bd9Sstevel@tonic-gate {
12307c478bd9Sstevel@tonic-gate 	crypto_get_provider_mechanism_info_t mechanism_info;
12312321aa36Sda73024 	const char *string;
12327c478bd9Sstevel@tonic-gate 	CK_FLAGS flags, mi_flags;
12337c478bd9Sstevel@tonic-gate 	CK_RV rv;
12347c478bd9Sstevel@tonic-gate 	int r;
12352321aa36Sda73024 	char buf[11];   /* Num chars for representing ulong in ASCII */
12367c478bd9Sstevel@tonic-gate 
123776d1b5a9Sda73024 	if (type >= CKM_VENDOR_DEFINED) {
12382321aa36Sda73024 		/* allocate/build a string containing the mechanism number */
12392321aa36Sda73024 		(void) snprintf(buf, sizeof (buf), "%#lx", type);
12402321aa36Sda73024 		string = buf;
12412321aa36Sda73024 	} else {
12427c478bd9Sstevel@tonic-gate 		string = pkcs11_mech2str(type);
12432321aa36Sda73024 	}
12442321aa36Sda73024 
12457c478bd9Sstevel@tonic-gate 	if (string == NULL)
12467c478bd9Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 	(void) strcpy(mechanism_info.mi_mechanism_name, string);
12497c478bd9Sstevel@tonic-gate 	mechanism_info.mi_provider_id = pslot->sl_provider_id;
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
12527c478bd9Sstevel@tonic-gate 	    &mechanism_info)) < 0) {
12537c478bd9Sstevel@tonic-gate 		if (errno != EINTR)
12547c478bd9Sstevel@tonic-gate 			break;
12557c478bd9Sstevel@tonic-gate 	}
12567c478bd9Sstevel@tonic-gate 	if (r < 0) {
12577c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
12587c478bd9Sstevel@tonic-gate 	} else {
12597c478bd9Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(
12607c478bd9Sstevel@tonic-gate 		    mechanism_info.mi_return_value);
12617c478bd9Sstevel@tonic-gate 	}
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
12642321aa36Sda73024 		return (rv);
12657c478bd9Sstevel@tonic-gate 	}
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate 	/*
12687c478bd9Sstevel@tonic-gate 	 * Atomic flags are not part of PKCS#11 so we filter
12697c478bd9Sstevel@tonic-gate 	 * them out here.
12707c478bd9Sstevel@tonic-gate 	 */
12717c478bd9Sstevel@tonic-gate 	mi_flags = mechanism_info.mi_flags;
12727c478bd9Sstevel@tonic-gate 	mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
12737c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
12747c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
12757c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER_ATOMIC |
12767c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
12777c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
12787c478bd9Sstevel@tonic-gate 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC);
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	if (mi_flags == 0) {
12812321aa36Sda73024 		return (CKR_MECHANISM_INVALID);
12827c478bd9Sstevel@tonic-gate 	}
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
12857c478bd9Sstevel@tonic-gate 		/* set the value of k_mi_flags first */
12867c478bd9Sstevel@tonic-gate 		*k_mi_flags = mi_flags;
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate 		/* convert KEF flags into pkcs11 flags */
12897c478bd9Sstevel@tonic-gate 		flags = CKF_HW;
12907c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_ENCRYPT)
12917c478bd9Sstevel@tonic-gate 			flags |= CKF_ENCRYPT;
12927c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_DECRYPT) {
12937c478bd9Sstevel@tonic-gate 			flags |= CKF_DECRYPT;
12947c478bd9Sstevel@tonic-gate 			/*
12957c478bd9Sstevel@tonic-gate 			 * Since we'll be emulating C_UnwrapKey() for some
12967c478bd9Sstevel@tonic-gate 			 * cases, we can go ahead and claim CKF_UNWRAP
12977c478bd9Sstevel@tonic-gate 			 */
12987c478bd9Sstevel@tonic-gate 			flags |= CKF_UNWRAP;
12997c478bd9Sstevel@tonic-gate 		}
13007c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_DIGEST)
13017c478bd9Sstevel@tonic-gate 			flags |= CKF_DIGEST;
13027c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_SIGN)
13037c478bd9Sstevel@tonic-gate 			flags |= CKF_SIGN;
13047c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
13057c478bd9Sstevel@tonic-gate 			flags |= CKF_SIGN_RECOVER;
13067c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_VERIFY)
13077c478bd9Sstevel@tonic-gate 			flags |= CKF_VERIFY;
13087c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
13097c478bd9Sstevel@tonic-gate 			flags |= CKF_VERIFY_RECOVER;
13107c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_GENERATE)
13117c478bd9Sstevel@tonic-gate 			flags |= CKF_GENERATE;
13127c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
13137c478bd9Sstevel@tonic-gate 			flags |= CKF_GENERATE_KEY_PAIR;
13147c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_WRAP)
13157c478bd9Sstevel@tonic-gate 			flags |= CKF_WRAP;
13167c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_UNWRAP)
13177c478bd9Sstevel@tonic-gate 			flags |= CKF_UNWRAP;
13187c478bd9Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_DERIVE)
13197c478bd9Sstevel@tonic-gate 			flags |= CKF_DERIVE;
13207c478bd9Sstevel@tonic-gate 
13217c478bd9Sstevel@tonic-gate 		pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
13227c478bd9Sstevel@tonic-gate 		pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
13237c478bd9Sstevel@tonic-gate 		pInfo->flags = flags;
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate 	}
13267c478bd9Sstevel@tonic-gate 
13277c478bd9Sstevel@tonic-gate 	return (rv);
13287c478bd9Sstevel@tonic-gate }
1329