xref: /onnv-gate/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelUtil.c (revision 12856:2377353d2b97)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52935Skrishna  * Common Development and Distribution License (the "License").
62935Skrishna  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12856SZdenek.Kotala@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <stdlib.h>
260Sstevel@tonic-gate #include <string.h>
270Sstevel@tonic-gate #include <strings.h>
287011Sda73024 #include <stdio.h>
290Sstevel@tonic-gate #include <cryptoutil.h>
300Sstevel@tonic-gate #include <errno.h>
310Sstevel@tonic-gate #include <security/cryptoki.h>
320Sstevel@tonic-gate #include <sys/crypto/common.h>
330Sstevel@tonic-gate #include <sys/crypto/ioctl.h>
340Sstevel@tonic-gate #include "kernelGlobal.h"
350Sstevel@tonic-gate #include "kernelObject.h"
360Sstevel@tonic-gate #include "kernelSlot.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate #define	ENCODE_ATTR(type, value, len) {		\
390Sstevel@tonic-gate 	cur_attr->oa_type = type;		\
400Sstevel@tonic-gate 	(void) memcpy(ptr, value, len);		\
410Sstevel@tonic-gate 	cur_attr->oa_value = ptr;		\
420Sstevel@tonic-gate 	cur_attr->oa_value_len = len;		\
430Sstevel@tonic-gate 	cur_attr++;				\
440Sstevel@tonic-gate }
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate  * In order to fit everything on one line, the 'CRYPTO_' prefix
480Sstevel@tonic-gate  * has been dropped from the KCF #defines, e.g.
490Sstevel@tonic-gate  * CRYPTO_SUCCESS becomes SUCCESS.
500Sstevel@tonic-gate  */
510Sstevel@tonic-gate 
52*12856SZdenek.Kotala@Sun.COM static CK_RV error_number_table[CRYPTO_LAST_ERROR+1] = {
530Sstevel@tonic-gate CKR_OK,					/* SUCCESS */
540Sstevel@tonic-gate CKR_CANCEL,				/* CANCEL */
550Sstevel@tonic-gate CKR_HOST_MEMORY,			/* HOST_MEMORY */
560Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* GENERAL_ERROR */
570Sstevel@tonic-gate CKR_FUNCTION_FAILED,			/* FAILED */
580Sstevel@tonic-gate CKR_ARGUMENTS_BAD,			/* ARGUMENTS_BAD */
590Sstevel@tonic-gate CKR_ATTRIBUTE_READ_ONLY,		/* ATTRIBUTE_READ_ONLY */
600Sstevel@tonic-gate CKR_ATTRIBUTE_SENSITIVE,		/* ATTRIBUTE_SENSITIVE */
610Sstevel@tonic-gate CKR_ATTRIBUTE_TYPE_INVALID,		/* ATTRIBUTE_TYPE_INVALID */
620Sstevel@tonic-gate CKR_ATTRIBUTE_VALUE_INVALID,		/* ATTRIBUTE_VALUE_INVALID */
630Sstevel@tonic-gate CKR_FUNCTION_FAILED,			/* CANCELED */
640Sstevel@tonic-gate CKR_DATA_INVALID,			/* DATA_INVALID */
650Sstevel@tonic-gate CKR_DATA_LEN_RANGE,			/* DATA_LEN_RANGE */
660Sstevel@tonic-gate CKR_DEVICE_ERROR,			/* DEVICE_ERROR */
670Sstevel@tonic-gate CKR_DEVICE_MEMORY,			/* DEVICE_MEMORY */
680Sstevel@tonic-gate CKR_DEVICE_REMOVED,			/* DEVICE_REMOVED */
690Sstevel@tonic-gate CKR_ENCRYPTED_DATA_INVALID,		/* ENCRYPTED_DATA_INVALID */
700Sstevel@tonic-gate CKR_ENCRYPTED_DATA_LEN_RANGE,		/* ENCRYPTED_DATA_LEN_RANGE */
710Sstevel@tonic-gate CKR_KEY_HANDLE_INVALID,			/* KEY_HANDLE_INVALID */
720Sstevel@tonic-gate CKR_KEY_SIZE_RANGE,			/* KEY_SIZE_RANGE */
730Sstevel@tonic-gate CKR_KEY_TYPE_INCONSISTENT,		/* KEY_TYPE_INCONSISTENT */
740Sstevel@tonic-gate CKR_KEY_NOT_NEEDED,			/* KEY_NOT_NEEDED */
750Sstevel@tonic-gate CKR_KEY_CHANGED,			/* KEY_CHANGED */
760Sstevel@tonic-gate CKR_KEY_NEEDED,				/* KEY_NEEDED */
770Sstevel@tonic-gate CKR_KEY_INDIGESTIBLE,			/* KEY_INDIGESTIBLE */
780Sstevel@tonic-gate CKR_KEY_FUNCTION_NOT_PERMITTED,		/* KEY_FUNCTION_NOT_PERMITTED */
790Sstevel@tonic-gate CKR_KEY_NOT_WRAPPABLE,			/* KEY_NOT_WRAPPABLE */
800Sstevel@tonic-gate CKR_KEY_UNEXTRACTABLE,			/* KEY_UNEXTRACTABLE */
810Sstevel@tonic-gate CKR_MECHANISM_INVALID,			/* MECHANISM_INVALID */
820Sstevel@tonic-gate CKR_MECHANISM_PARAM_INVALID,		/* MECHANISM_PARAM_INVALID */
830Sstevel@tonic-gate CKR_OBJECT_HANDLE_INVALID,		/* OBJECT_HANDLE_INVALID */
840Sstevel@tonic-gate CKR_OPERATION_ACTIVE,			/* OPERATION_ACTIVE */
850Sstevel@tonic-gate CKR_OPERATION_NOT_INITIALIZED,		/* OPERATION_NOT_INITIALIZED */
860Sstevel@tonic-gate CKR_PIN_INCORRECT,			/* PIN_INCORRECT */
870Sstevel@tonic-gate CKR_PIN_INVALID,			/* PIN_INVALID */
880Sstevel@tonic-gate CKR_PIN_LEN_RANGE,			/* PIN_LEN_RANGE */
890Sstevel@tonic-gate CKR_PIN_EXPIRED,			/* PIN_EXPIRED */
900Sstevel@tonic-gate CKR_PIN_LOCKED,				/* PIN_LOCKED */
910Sstevel@tonic-gate CKR_SESSION_CLOSED,			/* SESSION_CLOSED */
920Sstevel@tonic-gate CKR_SESSION_COUNT,			/* SESSION_COUNT */
930Sstevel@tonic-gate CKR_SESSION_HANDLE_INVALID,		/* SESSION_HANDLE_INVALID */
940Sstevel@tonic-gate CKR_SESSION_READ_ONLY,			/* SESSION_READ_ONLY */
950Sstevel@tonic-gate CKR_SESSION_EXISTS,			/* SESSION_EXISTS */
960Sstevel@tonic-gate CKR_SESSION_READ_ONLY_EXISTS,		/* SESSION_READ_ONLY_EXISTS */
970Sstevel@tonic-gate CKR_SESSION_READ_WRITE_SO_EXISTS,	/* SESSION_READ_WRITE_SO_EXISTS */
980Sstevel@tonic-gate CKR_SIGNATURE_INVALID,			/* SIGNATURE_INVALID */
990Sstevel@tonic-gate CKR_SIGNATURE_LEN_RANGE,		/* SIGNATURE_LEN_RANGE */
1000Sstevel@tonic-gate CKR_TEMPLATE_INCOMPLETE,		/* TEMPLATE_INCOMPLETE */
1010Sstevel@tonic-gate CKR_TEMPLATE_INCONSISTENT,		/* TEMPLATE_INCONSISTENT */
1020Sstevel@tonic-gate CKR_UNWRAPPING_KEY_HANDLE_INVALID,	/* UNWRAPPING_KEY_HANDLE_INVALID */
1030Sstevel@tonic-gate CKR_UNWRAPPING_KEY_SIZE_RANGE,		/* UNWRAPPING_KEY_SIZE_RANGE */
1040Sstevel@tonic-gate CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,	/* UNWRAPPING_KEY_TYPE_INCONSISTENT */
1050Sstevel@tonic-gate CKR_USER_ALREADY_LOGGED_IN,		/* USER_ALREADY_LOGGED_IN */
1060Sstevel@tonic-gate CKR_USER_NOT_LOGGED_IN,			/* USER_NOT_LOGGED_IN */
1070Sstevel@tonic-gate CKR_USER_PIN_NOT_INITIALIZED,		/* USER_PIN_NOT_INITIALIZED */
1080Sstevel@tonic-gate CKR_USER_TYPE_INVALID,			/* USER_TYPE_INVALID */
1090Sstevel@tonic-gate CKR_USER_ANOTHER_ALREADY_LOGGED_IN,	/* USER_ANOTHER_ALREADY_LOGGED_IN */
1100Sstevel@tonic-gate CKR_USER_TOO_MANY_TYPES,		/* USER_TOO_MANY_TYPES */
1110Sstevel@tonic-gate CKR_WRAPPED_KEY_INVALID,		/* WRAPPED_KEY_INVALID */
1120Sstevel@tonic-gate CKR_WRAPPED_KEY_LEN_RANGE,		/* WRAPPED_KEY_LEN_RANGE */
1130Sstevel@tonic-gate CKR_WRAPPING_KEY_HANDLE_INVALID,	/* WRAPPING_KEY_HANDLE_INVALID */
1140Sstevel@tonic-gate CKR_WRAPPING_KEY_SIZE_RANGE,		/* WRAPPING_KEY_SIZE_RANGE */
1150Sstevel@tonic-gate CKR_WRAPPING_KEY_TYPE_INCONSISTENT,	/* WRAPPING_KEY_TYPE_INCONSISTENT */
1160Sstevel@tonic-gate CKR_RANDOM_SEED_NOT_SUPPORTED,		/* RANDOM_SEED_NOT_SUPPORTED */
1170Sstevel@tonic-gate CKR_RANDOM_NO_RNG,			/* RANDOM_NO_RNG */
1180Sstevel@tonic-gate CKR_DOMAIN_PARAMS_INVALID,		/* DOMAIN_PARAMS_INVALID */
1190Sstevel@tonic-gate CKR_BUFFER_TOO_SMALL,			/* BUFFER_TOO_SMALL */
1200Sstevel@tonic-gate CKR_INFORMATION_SENSITIVE,		/* INFORMATION_SENSITIVE */
1210Sstevel@tonic-gate CKR_FUNCTION_NOT_SUPPORTED,		/* NOT_SUPPORTED */
1220Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* QUEUED */
1230Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* BUFFER_TOO_BIG */
1240Sstevel@tonic-gate CKR_OPERATION_NOT_INITIALIZED,		/* INVALID_CONTEXT */
1250Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* INVALID_MAC */
1260Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* MECH_NOT_SUPPORTED */
1270Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* INCONSISTENT_ATTRIBUTE */
1280Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* NO_PERMISSION */
1290Sstevel@tonic-gate CKR_SLOT_ID_INVALID,			/* INVALID_PROVIDER_ID */
1300Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* VERSION_MISMATCH */
1310Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* BUSY */
1320Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* UNKNOWN_PROVIDER */
1330Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* MODVERIFICATION_FAILED */
1340Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* OLD_CTX_TEMPLATE */
1350Sstevel@tonic-gate CKR_GENERAL_ERROR,			/* WEAK_KEY */
136*12856SZdenek.Kotala@Sun.COM CKR_GENERAL_ERROR			/* FIPS140_ERROR */
1370Sstevel@tonic-gate };
1380Sstevel@tonic-gate 
139*12856SZdenek.Kotala@Sun.COM #if CRYPTO_LAST_ERROR != CRYPTO_FIPS140_ERROR
140*12856SZdenek.Kotala@Sun.COM #error "Crypto to PKCS11 error mapping table needs to be updated!"
141*12856SZdenek.Kotala@Sun.COM #endif
142*12856SZdenek.Kotala@Sun.COM 
1430Sstevel@tonic-gate /*
1440Sstevel@tonic-gate  * Map KCF error codes into PKCS11 error codes.
1450Sstevel@tonic-gate  */
1460Sstevel@tonic-gate CK_RV
crypto2pkcs11_error_number(uint_t n)1470Sstevel@tonic-gate crypto2pkcs11_error_number(uint_t n)
1480Sstevel@tonic-gate {
149*12856SZdenek.Kotala@Sun.COM 	if (n >= sizeof (error_number_table) / sizeof (error_number_table[0]))
1500Sstevel@tonic-gate 		return (CKR_GENERAL_ERROR);
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	return (error_number_table[n]);
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate 
1552935Skrishna #define	MECH_HASH(type)	(((uintptr_t)type) % KMECH_HASHTABLE_SIZE)
1562935Skrishna /*
1572935Skrishna  * Serialize writes to the hash table. We don't need a per bucket lock as
1582935Skrishna  * there are only a few writes and we don't need the lock for reads.
1592935Skrishna  */
1609661SZdenek.Kotala@Sun.COM pthread_mutex_t mechhash_mutex = PTHREAD_MUTEX_INITIALIZER;
1612935Skrishna 
1622935Skrishna static CK_RV
kmech_hash_insert(CK_MECHANISM_TYPE type,crypto_mech_type_t kmech)1632935Skrishna kmech_hash_insert(CK_MECHANISM_TYPE type, crypto_mech_type_t kmech)
1642935Skrishna {
1652935Skrishna 	uint_t h;
1662935Skrishna 	kmh_elem_t *elem, *cur;
1672935Skrishna 
1682935Skrishna 	elem = malloc(sizeof (kmh_elem_t));
1692935Skrishna 	if (elem == NULL)
1702935Skrishna 		return (CKR_HOST_MEMORY);
1712935Skrishna 
1722935Skrishna 	h = MECH_HASH(type);
1732935Skrishna 	elem->type = type;
1742935Skrishna 	elem->kmech = kmech;
1752935Skrishna 
1762935Skrishna 	(void) pthread_mutex_lock(&mechhash_mutex);
1772935Skrishna 	for (cur = kernel_mechhash[h]; cur != NULL; cur = cur->knext) {
1782935Skrishna 		if (type == cur->type) {
1792935Skrishna 			/* Some other thread beat us to it. */
1802935Skrishna 			(void) pthread_mutex_unlock(&mechhash_mutex);
1812935Skrishna 			free(elem);
1822935Skrishna 			return (CKR_OK);
1832935Skrishna 		}
1842935Skrishna 	}
1852935Skrishna 	elem->knext = kernel_mechhash[h];
1862935Skrishna 	kernel_mechhash[h] = elem;
1872935Skrishna 	(void) pthread_mutex_unlock(&mechhash_mutex);
1882935Skrishna 
1892935Skrishna 	return (CKR_OK);
1902935Skrishna }
1912935Skrishna 
1920Sstevel@tonic-gate CK_RV
kernel_mech(CK_MECHANISM_TYPE type,crypto_mech_type_t * k_number)1930Sstevel@tonic-gate kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 	crypto_get_mechanism_number_t get_number;
1967011Sda73024 	const char *string;
1970Sstevel@tonic-gate 	CK_RV rv;
1980Sstevel@tonic-gate 	int r;
1992935Skrishna 	kmh_elem_t *elem;
2002935Skrishna 	uint_t h;
2017011Sda73024 	char buf[11];   /* Num chars for representing ulong in ASCII */
2022935Skrishna 
2032935Skrishna 	/*
2042935Skrishna 	 * Search for an existing entry. No need to lock since we are
2052935Skrishna 	 * just a reader and we never free the entries in the hash table.
2062935Skrishna 	 */
2072935Skrishna 	h = MECH_HASH(type);
2082935Skrishna 	for (elem = kernel_mechhash[h]; elem != NULL; elem = elem->knext) {
2092935Skrishna 		if (type == elem->type) {
2102935Skrishna 			*k_number = elem->kmech;
2112935Skrishna 			return (CKR_OK);
2122935Skrishna 		}
2132935Skrishna 	}
2140Sstevel@tonic-gate 
2157106Sda73024 	if (type >= CKM_VENDOR_DEFINED) {
2167011Sda73024 		(void) snprintf(buf, sizeof (buf), "%#lx", type);
2177011Sda73024 		string = buf;
2187011Sda73024 	} else {
2197011Sda73024 		string = pkcs11_mech2str(type);
2207011Sda73024 	}
2217011Sda73024 
2220Sstevel@tonic-gate 	if (string == NULL)
2230Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
2240Sstevel@tonic-gate 
2257011Sda73024 	get_number.pn_mechanism_string = (char *)string;
2260Sstevel@tonic-gate 	get_number.pn_mechanism_len = strlen(string) + 1;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_GET_MECHANISM_NUMBER,
2290Sstevel@tonic-gate 	    &get_number)) < 0) {
2300Sstevel@tonic-gate 		if (errno != EINTR)
2310Sstevel@tonic-gate 			break;
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate 	if (r < 0) {
2340Sstevel@tonic-gate 		rv = CKR_MECHANISM_INVALID;
2350Sstevel@tonic-gate 	} else {
2360Sstevel@tonic-gate 		if (get_number.pn_return_value != CRYPTO_SUCCESS) {
2370Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
2380Sstevel@tonic-gate 			    get_number.pn_return_value);
2390Sstevel@tonic-gate 		} else {
2400Sstevel@tonic-gate 			rv = CKR_OK;
2410Sstevel@tonic-gate 		}
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 
2442935Skrishna 	if (rv == CKR_OK) {
2450Sstevel@tonic-gate 		*k_number = get_number.pn_internal_number;
2462935Skrishna 		/* Add this to the hash table */
2472935Skrishna 		(void) kmech_hash_insert(type, *k_number);
2482935Skrishna 	}
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	return (rv);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate /*
2550Sstevel@tonic-gate  * Return the value of a secret key object.
2560Sstevel@tonic-gate  * This routine allocates memory for the value.
2570Sstevel@tonic-gate  * A null pointer is returned on error.
2580Sstevel@tonic-gate  */
2590Sstevel@tonic-gate unsigned char *
get_symmetric_key_value(kernel_object_t * key_p)2600Sstevel@tonic-gate get_symmetric_key_value(kernel_object_t *key_p)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate 	uint8_t *cipherKey;
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	switch (key_p->class) {
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	case CKO_SECRET_KEY:
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 		cipherKey = malloc(OBJ_SEC(key_p)->sk_value_len);
2690Sstevel@tonic-gate 		if (cipherKey == NULL)
2700Sstevel@tonic-gate 			return (NULL);
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 		(void) memcpy(cipherKey, OBJ_SEC(key_p)->sk_value,
2730Sstevel@tonic-gate 		    OBJ_SEC(key_p)->sk_value_len);
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 		return (cipherKey);
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	default:
2780Sstevel@tonic-gate 		return (NULL);
2790Sstevel@tonic-gate 	}
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate /*
2830Sstevel@tonic-gate  * Convert a RSA private key object into a crypto_key structure.
2840Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the crypto_key
2850Sstevel@tonic-gate  * structure.  Memory for the crypto_key structure is not
2860Sstevel@tonic-gate  * allocated.  Attributes can be freed by free_key_attributes().
2870Sstevel@tonic-gate  */
2880Sstevel@tonic-gate CK_RV
get_rsa_private_key(kernel_object_t * object_p,crypto_key_t * key)2890Sstevel@tonic-gate get_rsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
2900Sstevel@tonic-gate {
2910Sstevel@tonic-gate 	biginteger_t *big;
2920Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
2930Sstevel@tonic-gate 	char *ptr;
2940Sstevel@tonic-gate 	CK_RV rv;
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
2970Sstevel@tonic-gate 	if (object_p->key_type != CKK_RSA ||
2980Sstevel@tonic-gate 	    object_p->class != CKO_PRIVATE_KEY) {
2990Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
3000Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_TYPE_INVALID);
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	attrs = calloc(1,
3040Sstevel@tonic-gate 	    RSA_PRI_ATTR_COUNT * sizeof (crypto_object_attribute_t));
3050Sstevel@tonic-gate 	if (attrs == NULL) {
3060Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
3070Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
3080Sstevel@tonic-gate 	}
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
3110Sstevel@tonic-gate 	key->ck_attrs = attrs;
3120Sstevel@tonic-gate 	cur_attr = attrs;
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	/*
3150Sstevel@tonic-gate 	 * Allocate memory for each key attribute and set up the value
3160Sstevel@tonic-gate 	 * value length.
3170Sstevel@tonic-gate 	 */
3180Sstevel@tonic-gate 	key->ck_count = 0;
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	/* CKA_MODULUS is required. */
3210Sstevel@tonic-gate 	big = OBJ_PRI_RSA_MOD(object_p);
3220Sstevel@tonic-gate 	if (big->big_value == NULL) {
3230Sstevel@tonic-gate 		rv = CKR_ATTRIBUTE_TYPE_INVALID;
3240Sstevel@tonic-gate 		goto fail_cleanup;
3250Sstevel@tonic-gate 	} else {
3260Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3270Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3280Sstevel@tonic-gate 			goto fail_cleanup;
3290Sstevel@tonic-gate 		}
3300Sstevel@tonic-gate 		ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
3310Sstevel@tonic-gate 		key->ck_count++;
3320Sstevel@tonic-gate 	}
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	/* CKA_PRIVATE_EXPONENT is required. */
3350Sstevel@tonic-gate 	big = OBJ_PRI_RSA_PRIEXPO(object_p);
3360Sstevel@tonic-gate 	if (big->big_value == NULL) {
3370Sstevel@tonic-gate 		rv = CKR_ATTRIBUTE_TYPE_INVALID;
3380Sstevel@tonic-gate 		goto fail_cleanup;
3390Sstevel@tonic-gate 	} else {
3400Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3410Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3420Sstevel@tonic-gate 			goto fail_cleanup;
3430Sstevel@tonic-gate 		}
3440Sstevel@tonic-gate 		ENCODE_ATTR(CKA_PRIVATE_EXPONENT, big->big_value,
3450Sstevel@tonic-gate 		    big->big_value_len);
3460Sstevel@tonic-gate 		key->ck_count++;
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	/* CKA_PRIME_1 is optional. */
3500Sstevel@tonic-gate 	big = OBJ_PRI_RSA_PRIME1(object_p);
3510Sstevel@tonic-gate 	if (big->big_value != NULL) {
3520Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3530Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3540Sstevel@tonic-gate 			goto fail_cleanup;
3550Sstevel@tonic-gate 		}
3560Sstevel@tonic-gate 		ENCODE_ATTR(CKA_PRIME_1, big->big_value, big->big_value_len);
3570Sstevel@tonic-gate 		key->ck_count++;
3580Sstevel@tonic-gate 	}
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	/* CKA_PRIME_2 is optional. */
3610Sstevel@tonic-gate 	big = OBJ_PRI_RSA_PRIME2(object_p);
3620Sstevel@tonic-gate 	if (big->big_value != NULL) {
3630Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3640Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3650Sstevel@tonic-gate 			goto fail_cleanup;
3660Sstevel@tonic-gate 		}
3670Sstevel@tonic-gate 		ENCODE_ATTR(CKA_PRIME_2, big->big_value, big->big_value_len);
3680Sstevel@tonic-gate 		key->ck_count++;
3690Sstevel@tonic-gate 	}
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	/* CKA_EXPONENT_1 is optional. */
3720Sstevel@tonic-gate 	big = OBJ_PRI_RSA_EXPO1(object_p);
3730Sstevel@tonic-gate 	if (big->big_value != NULL) {
3740Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3750Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3760Sstevel@tonic-gate 			goto fail_cleanup;
3770Sstevel@tonic-gate 		}
3780Sstevel@tonic-gate 		ENCODE_ATTR(CKA_EXPONENT_1, big->big_value,
3790Sstevel@tonic-gate 		    big->big_value_len);
3800Sstevel@tonic-gate 		key->ck_count++;
3810Sstevel@tonic-gate 	}
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 	/* CKA_EXPONENT_2 is optional. */
3840Sstevel@tonic-gate 	big = OBJ_PRI_RSA_EXPO2(object_p);
3850Sstevel@tonic-gate 	if (big->big_value != NULL) {
3860Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3870Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
3880Sstevel@tonic-gate 			goto fail_cleanup;
3890Sstevel@tonic-gate 		}
3900Sstevel@tonic-gate 		ENCODE_ATTR(CKA_EXPONENT_2, big->big_value,
3910Sstevel@tonic-gate 		    big->big_value_len);
3920Sstevel@tonic-gate 		key->ck_count++;
3930Sstevel@tonic-gate 	}
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 	/* CKA_COEFFICIENT is optional. */
3960Sstevel@tonic-gate 	big = OBJ_PRI_RSA_COEF(object_p);
3970Sstevel@tonic-gate 	if (big->big_value != NULL) {
3980Sstevel@tonic-gate 		if ((ptr = malloc(big->big_value_len)) == NULL) {
3990Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
4000Sstevel@tonic-gate 			goto fail_cleanup;
4010Sstevel@tonic-gate 		}
4020Sstevel@tonic-gate 		ENCODE_ATTR(CKA_COEFFICIENT, big->big_value,
4030Sstevel@tonic-gate 		    big->big_value_len);
4040Sstevel@tonic-gate 		key->ck_count++;
4050Sstevel@tonic-gate 	}
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
4080Sstevel@tonic-gate 	return (CKR_OK);
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate fail_cleanup:
4110Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
4120Sstevel@tonic-gate 	free_key_attributes(key);
4130Sstevel@tonic-gate 	return (rv);
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate /*
4170Sstevel@tonic-gate  * Convert a RSA public key object into a crypto_key structure.
4180Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the crypto_key
4190Sstevel@tonic-gate  * structure.  Memory for the crypto_key structure is not
4200Sstevel@tonic-gate  * allocated.  Attributes can be freed by free_key_attributes().
4210Sstevel@tonic-gate  */
4220Sstevel@tonic-gate CK_RV
get_rsa_public_key(kernel_object_t * object_p,crypto_key_t * key)4230Sstevel@tonic-gate get_rsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
4240Sstevel@tonic-gate {
4250Sstevel@tonic-gate 	biginteger_t *big;
4260Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
4270Sstevel@tonic-gate 	char *ptr;
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
4300Sstevel@tonic-gate 	if (object_p->key_type != CKK_RSA ||
4310Sstevel@tonic-gate 	    object_p->class != CKO_PUBLIC_KEY) {
4320Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
4330Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_TYPE_INVALID);
4340Sstevel@tonic-gate 	}
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	attrs = calloc(1,
4370Sstevel@tonic-gate 	    RSA_PUB_ATTR_COUNT * sizeof (crypto_object_attribute_t));
4380Sstevel@tonic-gate 	if (attrs == NULL) {
4390Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
4400Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
4410Sstevel@tonic-gate 	}
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
4440Sstevel@tonic-gate 	key->ck_count = RSA_PUB_ATTR_COUNT;
4450Sstevel@tonic-gate 	key->ck_attrs = attrs;
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 	cur_attr = attrs;
4480Sstevel@tonic-gate 	big = OBJ_PUB_RSA_PUBEXPO(object_p);
4490Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
4500Sstevel@tonic-gate 		goto mem_failure;
4510Sstevel@tonic-gate 	ENCODE_ATTR(CKA_PUBLIC_EXPONENT, big->big_value, big->big_value_len);
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	big = OBJ_PUB_RSA_MOD(object_p);
4540Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
4550Sstevel@tonic-gate 		goto mem_failure;
4560Sstevel@tonic-gate 	ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	if ((ptr = malloc(sizeof (CK_ULONG))) == NULL)
4590Sstevel@tonic-gate 		goto mem_failure;
4600Sstevel@tonic-gate 	ENCODE_ATTR(CKA_MODULUS_BITS, &OBJ_PUB_RSA_MOD_BITS(object_p),
4610Sstevel@tonic-gate 	    sizeof (CK_ULONG));
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
4640Sstevel@tonic-gate 	return (CKR_OK);
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate mem_failure:
4670Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
4680Sstevel@tonic-gate 	free_key_attributes(key);
4690Sstevel@tonic-gate 	return (CKR_HOST_MEMORY);
4700Sstevel@tonic-gate }
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate /*
4730Sstevel@tonic-gate  * Free attribute storage in a crypto_key structure.
4740Sstevel@tonic-gate  */
4750Sstevel@tonic-gate void
free_key_attributes(crypto_key_t * key)4760Sstevel@tonic-gate free_key_attributes(crypto_key_t *key)
4770Sstevel@tonic-gate {
4780Sstevel@tonic-gate 	int i;
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	if (key->ck_format == CRYPTO_KEY_ATTR_LIST &&
4810Sstevel@tonic-gate 	    (key->ck_count > 0) && key->ck_attrs != NULL) {
4820Sstevel@tonic-gate 		for (i = 0; i < key->ck_count; i++) {
4830Sstevel@tonic-gate 			if (key->ck_attrs[i].oa_value != NULL) {
4840Sstevel@tonic-gate 				bzero(key->ck_attrs[i].oa_value,
4850Sstevel@tonic-gate 				    key->ck_attrs[i].oa_value_len);
4860Sstevel@tonic-gate 				free(key->ck_attrs[i].oa_value);
4870Sstevel@tonic-gate 			}
4880Sstevel@tonic-gate 		}
4890Sstevel@tonic-gate 		free(key->ck_attrs);
4900Sstevel@tonic-gate 	}
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate /*
4950Sstevel@tonic-gate  * Convert a DSA private key object into a crypto_key structure.
4960Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the crypto_key
4970Sstevel@tonic-gate  * structure.  Memory for the crypto_key structure is not
4980Sstevel@tonic-gate  * allocated.  Attributes can be freed by free_dsa_key_attributes().
4990Sstevel@tonic-gate  */
5000Sstevel@tonic-gate CK_RV
get_dsa_private_key(kernel_object_t * object_p,crypto_key_t * key)5010Sstevel@tonic-gate get_dsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
5020Sstevel@tonic-gate {
5030Sstevel@tonic-gate 	biginteger_t *big;
5040Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
5050Sstevel@tonic-gate 	char *ptr;
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
5080Sstevel@tonic-gate 	if (object_p->key_type != CKK_DSA ||
5090Sstevel@tonic-gate 	    object_p->class != CKO_PRIVATE_KEY) {
5100Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5110Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_TYPE_INVALID);
5120Sstevel@tonic-gate 	}
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	attrs = calloc(1,
5150Sstevel@tonic-gate 	    DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
5160Sstevel@tonic-gate 	if (attrs == NULL) {
5170Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5180Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
5190Sstevel@tonic-gate 	}
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
5220Sstevel@tonic-gate 	key->ck_count = DSA_ATTR_COUNT;
5230Sstevel@tonic-gate 	key->ck_attrs = attrs;
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate 	cur_attr = attrs;
5260Sstevel@tonic-gate 	big = OBJ_PRI_DSA_PRIME(object_p);
5270Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5280Sstevel@tonic-gate 		goto mem_failure;
5290Sstevel@tonic-gate 	ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	big = OBJ_PRI_DSA_SUBPRIME(object_p);
5320Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5330Sstevel@tonic-gate 		goto mem_failure;
5340Sstevel@tonic-gate 	ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	big = OBJ_PRI_DSA_BASE(object_p);
5370Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5380Sstevel@tonic-gate 		goto mem_failure;
5390Sstevel@tonic-gate 	ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	big = OBJ_PRI_DSA_VALUE(object_p);
5420Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5430Sstevel@tonic-gate 		goto mem_failure;
5440Sstevel@tonic-gate 	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
5470Sstevel@tonic-gate 	return (CKR_OK);
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate mem_failure:
5500Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
5510Sstevel@tonic-gate 	free_key_attributes(key);
5520Sstevel@tonic-gate 	return (CKR_HOST_MEMORY);
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate /*
5570Sstevel@tonic-gate  * Convert a DSA public key object into a crypto_key structure.
5580Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the crypto_key
5590Sstevel@tonic-gate  * structure.  Memory for the crypto_key structure is not
5600Sstevel@tonic-gate  * allocated.  Attributes can be freed by free_dsa_key_attributes().
5610Sstevel@tonic-gate  */
5620Sstevel@tonic-gate CK_RV
get_dsa_public_key(kernel_object_t * object_p,crypto_key_t * key)5630Sstevel@tonic-gate get_dsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
5640Sstevel@tonic-gate {
5650Sstevel@tonic-gate 	biginteger_t *big;
5660Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
5670Sstevel@tonic-gate 	char *ptr;
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
5700Sstevel@tonic-gate 	if (object_p->key_type != CKK_DSA ||
5710Sstevel@tonic-gate 	    object_p->class != CKO_PUBLIC_KEY) {
5720Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5730Sstevel@tonic-gate 		return (CKR_ATTRIBUTE_TYPE_INVALID);
5740Sstevel@tonic-gate 	}
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 	attrs = calloc(1,
5770Sstevel@tonic-gate 	    DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
5780Sstevel@tonic-gate 	if (attrs == NULL) {
5790Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5800Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
5810Sstevel@tonic-gate 	}
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
5840Sstevel@tonic-gate 	key->ck_count = DSA_ATTR_COUNT;
5850Sstevel@tonic-gate 	key->ck_attrs = attrs;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	cur_attr = attrs;
5880Sstevel@tonic-gate 	big = OBJ_PUB_DSA_PRIME(object_p);
5890Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5900Sstevel@tonic-gate 		goto mem_failure;
5910Sstevel@tonic-gate 	ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	big = OBJ_PUB_DSA_SUBPRIME(object_p);
5940Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
5950Sstevel@tonic-gate 		goto mem_failure;
5960Sstevel@tonic-gate 	ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	big = OBJ_PUB_DSA_BASE(object_p);
5990Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
6000Sstevel@tonic-gate 		goto mem_failure;
6010Sstevel@tonic-gate 	ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 	big = OBJ_PUB_DSA_VALUE(object_p);
6040Sstevel@tonic-gate 	if ((ptr = malloc(big->big_value_len)) == NULL)
6050Sstevel@tonic-gate 		goto mem_failure;
6060Sstevel@tonic-gate 	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
6090Sstevel@tonic-gate 	return (CKR_OK);
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate mem_failure:
6120Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
6130Sstevel@tonic-gate 	free_key_attributes(key);
6140Sstevel@tonic-gate 	return (CKR_HOST_MEMORY);
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate /*
6194219Smcpowers  * Convert a EC private key object into a crypto_key structure.
6204219Smcpowers  * Memory is allocated for each attribute stored in the crypto_key
6214219Smcpowers  * structure.  Memory for the crypto_key structure is not
6224219Smcpowers  * allocated.  Attributes can be freed by free_ec_key_attributes().
6234219Smcpowers  */
6244219Smcpowers CK_RV
get_ec_private_key(kernel_object_t * object_p,crypto_key_t * key)6254219Smcpowers get_ec_private_key(kernel_object_t *object_p, crypto_key_t *key)
6264219Smcpowers {
6274219Smcpowers 	biginteger_t *big;
6284219Smcpowers 	crypto_object_attribute_t *attrs, *cur_attr;
6294219Smcpowers 	CK_ATTRIBUTE tmp;
6304219Smcpowers 	char *ptr;
6314219Smcpowers 	int rv;
6324219Smcpowers 
6334219Smcpowers 	(void) pthread_mutex_lock(&object_p->object_mutex);
6344219Smcpowers 	if (object_p->key_type != CKK_EC ||
6354219Smcpowers 	    object_p->class != CKO_PRIVATE_KEY) {
6364219Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
6374219Smcpowers 		return (CKR_ATTRIBUTE_TYPE_INVALID);
6384219Smcpowers 	}
6394219Smcpowers 
6405072Smcpowers 	attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
6414219Smcpowers 	if (attrs == NULL) {
6424219Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
6434219Smcpowers 		return (CKR_HOST_MEMORY);
6444219Smcpowers 	}
6454219Smcpowers 
6464219Smcpowers 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
6475072Smcpowers 	key->ck_count = EC_ATTR_COUNT;
6484219Smcpowers 	key->ck_attrs = attrs;
6494219Smcpowers 
6504219Smcpowers 	cur_attr = attrs;
6514219Smcpowers 	big = OBJ_PRI_EC_VALUE(object_p);
6524219Smcpowers 	if ((ptr = malloc(big->big_value_len)) == NULL) {
6534219Smcpowers 		rv = CKR_HOST_MEMORY;
6544219Smcpowers 		goto fail;
6554219Smcpowers 	}
6564219Smcpowers 	ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
6574219Smcpowers 
6584219Smcpowers 	tmp.type = CKA_EC_PARAMS;
6594219Smcpowers 	tmp.pValue = NULL;
6604219Smcpowers 	rv = kernel_get_attribute(object_p, &tmp);
6614219Smcpowers 	if (rv != CKR_OK) {
6624219Smcpowers 		goto fail;
6634219Smcpowers 	}
6644219Smcpowers 
6654219Smcpowers 	tmp.pValue = malloc(tmp.ulValueLen);
6664219Smcpowers 	if (tmp.pValue == NULL) {
6674219Smcpowers 		rv = CKR_HOST_MEMORY;
6684219Smcpowers 		goto fail;
6694219Smcpowers 	}
6704219Smcpowers 
6714219Smcpowers 	rv = kernel_get_attribute(object_p, &tmp);
6724219Smcpowers 	if (rv != CKR_OK) {
6734219Smcpowers 		free(tmp.pValue);
6744219Smcpowers 		goto fail;
6754219Smcpowers 	}
6764219Smcpowers 
6774219Smcpowers 	cur_attr->oa_type = tmp.type;
6784219Smcpowers 	cur_attr->oa_value = tmp.pValue;
6794219Smcpowers 	cur_attr->oa_value_len = tmp.ulValueLen;
6804219Smcpowers 
6814219Smcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
6824219Smcpowers 	return (CKR_OK);
6834219Smcpowers 
6844219Smcpowers fail:
6854219Smcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
6864219Smcpowers 	free_key_attributes(key);
6874219Smcpowers 	return (rv);
6884219Smcpowers }
6894219Smcpowers 
6904219Smcpowers /*
6914219Smcpowers  * Convert an EC public key object into a crypto_key structure.
6924219Smcpowers  * Memory is allocated for each attribute stored in the crypto_key
6934219Smcpowers  * structure.  Memory for the crypto_key structure is not
6944219Smcpowers  * allocated.  Attributes can be freed by free_ec_key_attributes().
6954219Smcpowers  */
6964219Smcpowers CK_RV
get_ec_public_key(kernel_object_t * object_p,crypto_key_t * key)6974219Smcpowers get_ec_public_key(kernel_object_t *object_p, crypto_key_t *key)
6984219Smcpowers {
6994219Smcpowers 	biginteger_t *big;
7004219Smcpowers 	crypto_object_attribute_t *attrs, *cur_attr;
7015072Smcpowers 	CK_ATTRIBUTE tmp;
7024219Smcpowers 	char *ptr;
7035072Smcpowers 	int rv;
7044219Smcpowers 
7054219Smcpowers 	(void) pthread_mutex_lock(&object_p->object_mutex);
7064219Smcpowers 	if (object_p->key_type != CKK_EC ||
7074219Smcpowers 	    object_p->class != CKO_PUBLIC_KEY) {
7084219Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
7094219Smcpowers 		return (CKR_ATTRIBUTE_TYPE_INVALID);
7104219Smcpowers 	}
7114219Smcpowers 
7125072Smcpowers 	attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
7134219Smcpowers 	if (attrs == NULL) {
7144219Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
7154219Smcpowers 		return (CKR_HOST_MEMORY);
7164219Smcpowers 	}
7174219Smcpowers 
7184219Smcpowers 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
7194219Smcpowers 	key->ck_count = EC_ATTR_COUNT;
7204219Smcpowers 	key->ck_attrs = attrs;
7214219Smcpowers 
7224219Smcpowers 	cur_attr = attrs;
7234219Smcpowers 	big = OBJ_PUB_EC_POINT(object_p);
7244219Smcpowers 	if ((ptr = malloc(big->big_value_len)) == NULL) {
7255072Smcpowers 		rv = CKR_HOST_MEMORY;
7265072Smcpowers 		goto fail;
7274219Smcpowers 	}
7284219Smcpowers 	ENCODE_ATTR(CKA_EC_POINT, big->big_value, big->big_value_len);
7294219Smcpowers 
7305072Smcpowers 	tmp.type = CKA_EC_PARAMS;
7315072Smcpowers 	tmp.pValue = NULL;
7325072Smcpowers 	rv = kernel_get_attribute(object_p, &tmp);
7335072Smcpowers 	if (rv != CKR_OK) {
7345072Smcpowers 		goto fail;
7355072Smcpowers 	}
7365072Smcpowers 
7375072Smcpowers 	tmp.pValue = malloc(tmp.ulValueLen);
7385072Smcpowers 	if (tmp.pValue == NULL) {
7395072Smcpowers 		rv = CKR_HOST_MEMORY;
7405072Smcpowers 		goto fail;
7415072Smcpowers 	}
7425072Smcpowers 
7435072Smcpowers 	rv = kernel_get_attribute(object_p, &tmp);
7445072Smcpowers 	if (rv != CKR_OK) {
7455072Smcpowers 		free(tmp.pValue);
7465072Smcpowers 		goto fail;
7475072Smcpowers 	}
7485072Smcpowers 
7495072Smcpowers 	cur_attr->oa_type = tmp.type;
7505072Smcpowers 	cur_attr->oa_value = tmp.pValue;
7515072Smcpowers 	cur_attr->oa_value_len = tmp.ulValueLen;
7525072Smcpowers 
7534219Smcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
7544219Smcpowers 	return (CKR_OK);
7555072Smcpowers 
7565072Smcpowers fail:
7575072Smcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
7585072Smcpowers 	free_key_attributes(key);
7595072Smcpowers 	return (rv);
7604219Smcpowers }
7614219Smcpowers 
7624219Smcpowers /*
7630Sstevel@tonic-gate  * Convert an attribute template into an obj_attrs array.
7640Sstevel@tonic-gate  * Memory is allocated for each attribute stored in the obj_attrs.
7650Sstevel@tonic-gate  * The memory can be freed by free_object_attributes().
7660Sstevel@tonic-gate  *
7670Sstevel@tonic-gate  * If the boolean pointer is_token_obj is not NULL, the caller wants to
7680Sstevel@tonic-gate  * retrieve the value of the CKA_TOKEN attribute if it is specified in the
7690Sstevel@tonic-gate  * template.
7700Sstevel@tonic-gate  * - When this routine is called thru C_CreateObject(), C_CopyObject(), or
7710Sstevel@tonic-gate  *   any key management function, is_token_obj should NOT be NULL.
7720Sstevel@tonic-gate  * - When this routine is called thru C_GetAttributeValue() or
7730Sstevel@tonic-gate  *   C_SetAttributeValue(), "is_token_obj" should be NULL.
7740Sstevel@tonic-gate  */
7750Sstevel@tonic-gate CK_RV
process_object_attributes(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,caddr_t * obj_attrs,CK_BBOOL * is_token_obj)7760Sstevel@tonic-gate process_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
7770Sstevel@tonic-gate     caddr_t *obj_attrs, CK_BBOOL *is_token_obj)
7780Sstevel@tonic-gate {
7790Sstevel@tonic-gate 	crypto_object_attribute_t *attrs, *cur_attr;
7800Sstevel@tonic-gate 	int i, cur_i;
7810Sstevel@tonic-gate 	char *ptr;
7820Sstevel@tonic-gate 	CK_RV rv;
7830Sstevel@tonic-gate 	ssize_t value_len;
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	if (ulCount == 0) {
7860Sstevel@tonic-gate 		obj_attrs = NULL;
7870Sstevel@tonic-gate 		return (CKR_OK);
7880Sstevel@tonic-gate 	}
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	attrs = calloc(1, ulCount * sizeof (crypto_object_attribute_t));
7910Sstevel@tonic-gate 	if (attrs == NULL) {
7920Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
7930Sstevel@tonic-gate 	}
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	cur_attr = attrs;
7960Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
7970Sstevel@tonic-gate 		/*
7980Sstevel@tonic-gate 		 * The length of long attributes must be set correctly
7990Sstevel@tonic-gate 		 * so providers can determine whether they came from 32
8000Sstevel@tonic-gate 		 * or 64-bit applications.
8010Sstevel@tonic-gate 		 */
8020Sstevel@tonic-gate 		switch (pTemplate[i].type) {
8030Sstevel@tonic-gate 		case CKA_CLASS:
8040Sstevel@tonic-gate 		case CKA_CERTIFICATE_TYPE:
8050Sstevel@tonic-gate 		case CKA_KEY_TYPE:
8064219Smcpowers 		case CKA_MODULUS_BITS:
8070Sstevel@tonic-gate 		case CKA_HW_FEATURE_TYPE:
8080Sstevel@tonic-gate 			value_len = sizeof (ulong_t);
809904Smcpowers 			if (pTemplate[i].pValue != NULL &&
810904Smcpowers 			    (pTemplate[i].ulValueLen < value_len)) {
8117512SAnthony.Scarpino@Sun.COM 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
8120Sstevel@tonic-gate 				cur_i = i;
8130Sstevel@tonic-gate 				goto fail_cleanup;
8140Sstevel@tonic-gate 			}
8150Sstevel@tonic-gate 			break;
8160Sstevel@tonic-gate 		default:
8170Sstevel@tonic-gate 			value_len = pTemplate[i].ulValueLen;
8180Sstevel@tonic-gate 		}
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 		cur_attr->oa_type = pTemplate[i].type;
8210Sstevel@tonic-gate 		cur_attr->oa_value_len = value_len;
8220Sstevel@tonic-gate 		cur_attr->oa_value = NULL;
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 		if ((pTemplate[i].pValue != NULL) &&
8250Sstevel@tonic-gate 		    (pTemplate[i].ulValueLen > 0)) {
8260Sstevel@tonic-gate 			ptr = malloc(pTemplate[i].ulValueLen);
8270Sstevel@tonic-gate 			if (ptr == NULL) {
8280Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
8290Sstevel@tonic-gate 				cur_i = i;
8300Sstevel@tonic-gate 				goto fail_cleanup;
8310Sstevel@tonic-gate 			} else {
8320Sstevel@tonic-gate 				(void) memcpy(ptr, pTemplate[i].pValue,
8330Sstevel@tonic-gate 				    pTemplate[i].ulValueLen);
8340Sstevel@tonic-gate 				cur_attr->oa_value = ptr;
8350Sstevel@tonic-gate 			}
8360Sstevel@tonic-gate 		}
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate 		if ((is_token_obj != NULL) &&
8390Sstevel@tonic-gate 		    (pTemplate[i].type == CKA_TOKEN)) {
8400Sstevel@tonic-gate 			/* Get the CKA_TOKEN attribute value. */
8410Sstevel@tonic-gate 			if (pTemplate[i].pValue == NULL) {
8420Sstevel@tonic-gate 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
8430Sstevel@tonic-gate 				cur_i = i;
8440Sstevel@tonic-gate 				goto fail_cleanup;
8450Sstevel@tonic-gate 			} else {
8460Sstevel@tonic-gate 				*is_token_obj =
8470Sstevel@tonic-gate 				    *(CK_BBOOL *)pTemplate[i].pValue;
8480Sstevel@tonic-gate 			}
8490Sstevel@tonic-gate 		}
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate 		cur_attr++;
8520Sstevel@tonic-gate 	}
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 	*obj_attrs = (char *)attrs;
8550Sstevel@tonic-gate 	return (CKR_OK);
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate fail_cleanup:
8580Sstevel@tonic-gate 	cur_attr = attrs;
8590Sstevel@tonic-gate 	for (i = 0; i < cur_i; i++) {
8600Sstevel@tonic-gate 		if (cur_attr->oa_value != NULL) {
8610Sstevel@tonic-gate 			(void) free(cur_attr->oa_value);
8620Sstevel@tonic-gate 		}
8630Sstevel@tonic-gate 		cur_attr++;
8640Sstevel@tonic-gate 	}
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate 	(void) free(attrs);
8670Sstevel@tonic-gate 	return (rv);
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate /*
8720Sstevel@tonic-gate  * Copy the attribute values from obj_attrs to pTemplate.
8730Sstevel@tonic-gate  * The obj_attrs is an image of the Template and is expected to have the
8740Sstevel@tonic-gate  * same attributes in the same order and each one of the attribute pValue
8750Sstevel@tonic-gate  * in obj_attr has enough space allocated for the corresponding valueLen
8760Sstevel@tonic-gate  * in pTemplate.
8770Sstevel@tonic-gate  */
8780Sstevel@tonic-gate CK_RV
get_object_attributes(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,caddr_t obj_attrs)8790Sstevel@tonic-gate get_object_attributes(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
8800Sstevel@tonic-gate     caddr_t obj_attrs)
8810Sstevel@tonic-gate {
8820Sstevel@tonic-gate 	crypto_object_attribute_t *cur_attr;
8830Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
8840Sstevel@tonic-gate 	int i;
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 	/* LINTED */
8870Sstevel@tonic-gate 	cur_attr = (crypto_object_attribute_t *)obj_attrs;
8880Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
8890Sstevel@tonic-gate 		if (pTemplate[i].type != cur_attr->oa_type) {
8900Sstevel@tonic-gate 			/* The attribute type doesn't match, this is bad. */
8910Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
8920Sstevel@tonic-gate 			return (rv);
8930Sstevel@tonic-gate 		}
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 		pTemplate[i].ulValueLen = cur_attr->oa_value_len;
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 		if ((pTemplate[i].pValue != NULL) &&
8980Sstevel@tonic-gate 		    ((CK_LONG)pTemplate[i].ulValueLen != -1)) {
8990Sstevel@tonic-gate 			(void) memcpy(pTemplate[i].pValue, cur_attr->oa_value,
9000Sstevel@tonic-gate 			    pTemplate[i].ulValueLen);
9010Sstevel@tonic-gate 		}
9020Sstevel@tonic-gate 		cur_attr++;
9030Sstevel@tonic-gate 	}
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate 	return (rv);
9060Sstevel@tonic-gate }
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate /*
9090Sstevel@tonic-gate  * Free the attribute storage in a crypto_object_attribute_t structure.
9100Sstevel@tonic-gate  */
9110Sstevel@tonic-gate void
free_object_attributes(caddr_t obj_attrs,CK_ULONG ulCount)9120Sstevel@tonic-gate free_object_attributes(caddr_t obj_attrs, CK_ULONG ulCount)
9130Sstevel@tonic-gate {
9140Sstevel@tonic-gate 	crypto_object_attribute_t *cur_attr;
9150Sstevel@tonic-gate 	int i;
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	if ((ulCount == 0) || (obj_attrs == NULL)) {
9180Sstevel@tonic-gate 		return;
9190Sstevel@tonic-gate 	}
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 	/* LINTED */
9220Sstevel@tonic-gate 	cur_attr = (crypto_object_attribute_t *)obj_attrs;
9230Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
9244219Smcpowers 		/* XXX check that oa_value > 0 */
9250Sstevel@tonic-gate 		if (cur_attr->oa_value != NULL) {
9260Sstevel@tonic-gate 			free(cur_attr->oa_value);
9270Sstevel@tonic-gate 		}
9280Sstevel@tonic-gate 		cur_attr++;
9290Sstevel@tonic-gate 	}
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 	free(obj_attrs);
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate 
9340Sstevel@tonic-gate /*
9350Sstevel@tonic-gate  * This function is called by process_found_objects().  It will check the
9360Sstevel@tonic-gate  * CKA_PRIVATE and CKA_TOKEN attributes for the kernel object "oid", then
9370Sstevel@tonic-gate  * initialize all the necessary fields in the object wrapper "objp".
9380Sstevel@tonic-gate  */
9390Sstevel@tonic-gate static CK_RV
create_new_tobj_in_lib(kernel_slot_t * pslot,kernel_session_t * sp,kernel_object_t * objp,crypto_object_id_t oid)9400Sstevel@tonic-gate create_new_tobj_in_lib(kernel_slot_t *pslot, kernel_session_t *sp,
9410Sstevel@tonic-gate     kernel_object_t *objp,  crypto_object_id_t oid)
9420Sstevel@tonic-gate {
9430Sstevel@tonic-gate 	CK_RV  rv = CKR_OK;
9440Sstevel@tonic-gate 	crypto_object_get_attribute_value_t obj_ga;
9450Sstevel@tonic-gate 	boolean_t is_pri_obj;
9460Sstevel@tonic-gate 	boolean_t is_token_obj;
9470Sstevel@tonic-gate 	CK_BBOOL pri_value, token_value;
9480Sstevel@tonic-gate 	CK_ATTRIBUTE  pTemplate[2];
9490Sstevel@tonic-gate 	int r;
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 	/*
9520Sstevel@tonic-gate 	 * Make a CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE ioctl call to get this
9530Sstevel@tonic-gate 	 * kernel object's attribute values for CKA_PRIVATE and CKA_TOKEN.
9540Sstevel@tonic-gate 	 */
9550Sstevel@tonic-gate 	obj_ga.og_session = sp->k_session;
9560Sstevel@tonic-gate 	obj_ga.og_handle = oid;
9570Sstevel@tonic-gate 	obj_ga.og_count = 2;
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 	pTemplate[0].type = CKA_PRIVATE;
9600Sstevel@tonic-gate 	pTemplate[0].pValue = &pri_value;
9610Sstevel@tonic-gate 	pTemplate[0].ulValueLen = sizeof (pri_value);
9620Sstevel@tonic-gate 	pTemplate[1].type = CKA_TOKEN;
9630Sstevel@tonic-gate 	pTemplate[1].pValue = &token_value;
9640Sstevel@tonic-gate 	pTemplate[1].ulValueLen = sizeof (token_value);
9650Sstevel@tonic-gate 	rv = process_object_attributes(pTemplate, 2, &obj_ga.og_attributes,
9660Sstevel@tonic-gate 	    NULL);
9670Sstevel@tonic-gate 	if (rv != CKR_OK) {
9680Sstevel@tonic-gate 		return (rv);
9690Sstevel@tonic-gate 	}
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
9720Sstevel@tonic-gate 	    &obj_ga)) < 0) {
9730Sstevel@tonic-gate 		if (errno != EINTR)
9740Sstevel@tonic-gate 			break;
9750Sstevel@tonic-gate 	}
9760Sstevel@tonic-gate 	if (r < 0) {
9770Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
9780Sstevel@tonic-gate 	} else {
9790Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
9800Sstevel@tonic-gate 	}
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 	if (rv == CKR_OK) {
9830Sstevel@tonic-gate 		rv = get_object_attributes(pTemplate, 2, obj_ga.og_attributes);
9840Sstevel@tonic-gate 		if (rv == CKR_OK) {
9850Sstevel@tonic-gate 			is_pri_obj = *(CK_BBOOL *)pTemplate[0].pValue;
9860Sstevel@tonic-gate 			is_token_obj = *(CK_BBOOL *)pTemplate[1].pValue;
9870Sstevel@tonic-gate 		}
9880Sstevel@tonic-gate 	}
9890Sstevel@tonic-gate 
9900Sstevel@tonic-gate 	free_object_attributes(obj_ga.og_attributes, 2);
9910Sstevel@tonic-gate 	if (rv != CKR_OK) {
9920Sstevel@tonic-gate 		return (rv);
9930Sstevel@tonic-gate 	}
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 	/* Make sure it is a token object. */
9960Sstevel@tonic-gate 	if (!is_token_obj) {
9970Sstevel@tonic-gate 		rv = CKR_ATTRIBUTE_VALUE_INVALID;
9980Sstevel@tonic-gate 		return (rv);
9990Sstevel@tonic-gate 	}
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 	/* If it is a private object, make sure the user has logged in. */
10020Sstevel@tonic-gate 	if (is_pri_obj && (pslot->sl_state != CKU_USER)) {
10030Sstevel@tonic-gate 		rv = CKR_ATTRIBUTE_VALUE_INVALID;
10040Sstevel@tonic-gate 		return (rv);
10050Sstevel@tonic-gate 	}
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 	objp->is_lib_obj = B_FALSE;
10080Sstevel@tonic-gate 	objp->k_handle = oid;
10090Sstevel@tonic-gate 	objp->bool_attr_mask |= TOKEN_BOOL_ON;
10100Sstevel@tonic-gate 	if (is_pri_obj) {
10110Sstevel@tonic-gate 		objp->bool_attr_mask |= PRIVATE_BOOL_ON;
10120Sstevel@tonic-gate 	} else {
10130Sstevel@tonic-gate 		objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
10140Sstevel@tonic-gate 	}
10150Sstevel@tonic-gate 
10160Sstevel@tonic-gate 	(void) pthread_mutex_init(&objp->object_mutex, NULL);
10170Sstevel@tonic-gate 	objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
10180Sstevel@tonic-gate 	objp->session_handle = (CK_SESSION_HANDLE) sp;
10190Sstevel@tonic-gate 
10200Sstevel@tonic-gate 	return (CKR_OK);
10210Sstevel@tonic-gate }
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate /*
10240Sstevel@tonic-gate  * This function processes the kernel object handles returned from the
10250Sstevel@tonic-gate  * CRYPTO_OBJECT_FIND_UPDATE ioctl and returns an object handle list
10260Sstevel@tonic-gate  * and the number of object handles to the caller - C_FindObjects().
10270Sstevel@tonic-gate  * The caller acquires the slot lock and the session lock.
10280Sstevel@tonic-gate  */
10290Sstevel@tonic-gate CK_RV
process_found_objects(kernel_session_t * cur_sp,CK_OBJECT_HANDLE * obj_found,CK_ULONG * found_obj_count,crypto_object_find_update_t obj_fu)10300Sstevel@tonic-gate process_found_objects(kernel_session_t *cur_sp, CK_OBJECT_HANDLE *obj_found,
10310Sstevel@tonic-gate     CK_ULONG *found_obj_count, crypto_object_find_update_t obj_fu)
10320Sstevel@tonic-gate {
10330Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
10340Sstevel@tonic-gate 	crypto_object_id_t  *oid_p;
10350Sstevel@tonic-gate 	kernel_slot_t *pslot;
10360Sstevel@tonic-gate 	kernel_object_t *objp;
10370Sstevel@tonic-gate 	kernel_object_t *objp1;
10380Sstevel@tonic-gate 	kernel_object_t *new_tobj_list = NULL;
10390Sstevel@tonic-gate 	kernel_session_t  *sp;
10400Sstevel@tonic-gate 	CK_ULONG num_obj_found = 0;
10410Sstevel@tonic-gate 	boolean_t is_in_lib;
10420Sstevel@tonic-gate 	int i;
10430Sstevel@tonic-gate 
10440Sstevel@tonic-gate 	if (obj_fu.fu_count == 0) {
10450Sstevel@tonic-gate 		*found_obj_count = 0;
10460Sstevel@tonic-gate 		return (CKR_OK);
10470Sstevel@tonic-gate 	}
10480Sstevel@tonic-gate 
10490Sstevel@tonic-gate 	pslot = slot_table[cur_sp->ses_slotid];
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate 	/* LINTED */
10520Sstevel@tonic-gate 	oid_p = (crypto_object_id_t *)obj_fu.fu_handles;
10530Sstevel@tonic-gate 	for (i = 0; i < obj_fu.fu_count; i++) {
10540Sstevel@tonic-gate 		is_in_lib = B_FALSE;
10550Sstevel@tonic-gate 		/*
10560Sstevel@tonic-gate 		 * Check if this oid has an object wrapper in the library
10570Sstevel@tonic-gate 		 * already.  First, search the slot's token object list.
10580Sstevel@tonic-gate 		 */
10590Sstevel@tonic-gate 		objp = pslot->sl_tobj_list;
10600Sstevel@tonic-gate 		while (!is_in_lib && objp) {
10610Sstevel@tonic-gate 			if (objp->k_handle == *oid_p) {
10620Sstevel@tonic-gate 				is_in_lib = B_TRUE;
10630Sstevel@tonic-gate 			} else {
10640Sstevel@tonic-gate 				objp = objp->next;
10650Sstevel@tonic-gate 			}
10660Sstevel@tonic-gate 		}
10670Sstevel@tonic-gate 
10680Sstevel@tonic-gate 		/*
10690Sstevel@tonic-gate 		 * If it is not in the slot's token object list,
10700Sstevel@tonic-gate 		 * search it in all the sessions.
10710Sstevel@tonic-gate 		 */
10720Sstevel@tonic-gate 		if (!is_in_lib) {
10730Sstevel@tonic-gate 			sp = pslot->sl_sess_list;
10740Sstevel@tonic-gate 			while (!is_in_lib && sp) {
10750Sstevel@tonic-gate 				objp = sp->object_list;
10760Sstevel@tonic-gate 				while (!is_in_lib && objp) {
10770Sstevel@tonic-gate 					if (objp->k_handle == *oid_p) {
10780Sstevel@tonic-gate 						is_in_lib = B_TRUE;
10790Sstevel@tonic-gate 					} else {
10800Sstevel@tonic-gate 						objp = objp->next;
10810Sstevel@tonic-gate 					}
10820Sstevel@tonic-gate 				}
10830Sstevel@tonic-gate 				sp = sp->next;
10840Sstevel@tonic-gate 			}
10850Sstevel@tonic-gate 		}
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate 		/*
10880Sstevel@tonic-gate 		 * If this object is in the library already, add its object
10890Sstevel@tonic-gate 		 * wrapper to the returned find object list.
10900Sstevel@tonic-gate 		 */
10910Sstevel@tonic-gate 		if (is_in_lib) {
10920Sstevel@tonic-gate 			obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
10930Sstevel@tonic-gate 		}
10940Sstevel@tonic-gate 
10950Sstevel@tonic-gate 		/*
10960Sstevel@tonic-gate 		 * If we still do not find it in the library.  This object
10970Sstevel@tonic-gate 		 * must be a token object pre-existed in the HW provider.
10980Sstevel@tonic-gate 		 * We need to create an object wrapper for it in the library.
10990Sstevel@tonic-gate 		 */
11000Sstevel@tonic-gate 		if (!is_in_lib) {
11010Sstevel@tonic-gate 			objp1 = calloc(1, sizeof (kernel_object_t));
11020Sstevel@tonic-gate 			if (objp1 == NULL) {
11030Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
11040Sstevel@tonic-gate 				goto failed_exit;
11050Sstevel@tonic-gate 			}
11060Sstevel@tonic-gate 			rv = create_new_tobj_in_lib(pslot, cur_sp, objp1,
11070Sstevel@tonic-gate 			    *oid_p);
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate 			if (rv == CKR_OK) {
11100Sstevel@tonic-gate 				/* Save the new object to the new_tobj_list. */
11110Sstevel@tonic-gate 				if (new_tobj_list == NULL) {
11120Sstevel@tonic-gate 					new_tobj_list = objp1;
11130Sstevel@tonic-gate 					objp1->next = NULL;
11140Sstevel@tonic-gate 					objp1->prev = NULL;
11150Sstevel@tonic-gate 				} else {
11160Sstevel@tonic-gate 					new_tobj_list->prev = objp1;
11170Sstevel@tonic-gate 					objp1->next = new_tobj_list;
11180Sstevel@tonic-gate 					objp1->prev = NULL;
11190Sstevel@tonic-gate 					new_tobj_list = objp1;
11200Sstevel@tonic-gate 				}
11210Sstevel@tonic-gate 			} else {
11220Sstevel@tonic-gate 				/*
11230Sstevel@tonic-gate 				 * If create_new_tobj_in_lib() doesn't fail
11240Sstevel@tonic-gate 				 * with CKR_HOST_MEMORY, the failure should be
11250Sstevel@tonic-gate 				 * caused by the attributes' checking. We will
11260Sstevel@tonic-gate 				 * just ignore this object and continue on.
11270Sstevel@tonic-gate 				 */
11280Sstevel@tonic-gate 				free(objp1);
11290Sstevel@tonic-gate 				if (rv == CKR_HOST_MEMORY) {
11300Sstevel@tonic-gate 					goto failed_exit;
11310Sstevel@tonic-gate 				}
11320Sstevel@tonic-gate 			}
11330Sstevel@tonic-gate 		}
11340Sstevel@tonic-gate 
11350Sstevel@tonic-gate 		/* Process next one */
11360Sstevel@tonic-gate 		oid_p++;
11370Sstevel@tonic-gate 	}
11380Sstevel@tonic-gate 
11390Sstevel@tonic-gate 	/*
11400Sstevel@tonic-gate 	 * Add the newly created token object wrappers to the found object
11410Sstevel@tonic-gate 	 * list and to the slot's token object list.
11420Sstevel@tonic-gate 	 */
11430Sstevel@tonic-gate 	if (new_tobj_list != NULL) {
11440Sstevel@tonic-gate 		/* Add to the obj_found array. */
11450Sstevel@tonic-gate 		objp = new_tobj_list;
11460Sstevel@tonic-gate 		while (objp) {
11470Sstevel@tonic-gate 			obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
11480Sstevel@tonic-gate 			if (objp->next == NULL) {
11490Sstevel@tonic-gate 				break;
11500Sstevel@tonic-gate 			}
11510Sstevel@tonic-gate 			objp = objp->next;
11520Sstevel@tonic-gate 		}
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 		/* Add to the beginning of the slot's token object list. */
11550Sstevel@tonic-gate 		if (pslot->sl_tobj_list != NULL) {
11560Sstevel@tonic-gate 			objp->next = pslot->sl_tobj_list;
11570Sstevel@tonic-gate 			pslot->sl_tobj_list->prev = objp;
11580Sstevel@tonic-gate 		}
11590Sstevel@tonic-gate 		pslot->sl_tobj_list = new_tobj_list;
11600Sstevel@tonic-gate 	}
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate 	*found_obj_count = num_obj_found;
11630Sstevel@tonic-gate 	return (CKR_OK);
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate failed_exit:
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 	/* Free the newly created token object wrappers. */
11680Sstevel@tonic-gate 	objp = new_tobj_list;
11690Sstevel@tonic-gate 	while (objp) {
11700Sstevel@tonic-gate 		objp1 = objp->next;
11710Sstevel@tonic-gate 		(void) pthread_mutex_destroy(&objp->object_mutex);
11720Sstevel@tonic-gate 		free(objp);
11730Sstevel@tonic-gate 		objp = objp1;
11740Sstevel@tonic-gate 	}
11750Sstevel@tonic-gate 
11760Sstevel@tonic-gate 	return (rv);
11770Sstevel@tonic-gate }
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 
11800Sstevel@tonic-gate /*
11810Sstevel@tonic-gate  * Get the value of the CKA_PRIVATE attribute for the object just returned
11820Sstevel@tonic-gate  * from the HW provider.  This function will be called by any function
11830Sstevel@tonic-gate  * that creates a new object, because the CKA_PRIVATE value of an object is
11847011Sda73024  * token specific.  The CKA_PRIVATE attribute value of the new object will be
11850Sstevel@tonic-gate  * stored in the object structure in the library, which will be used later at
11860Sstevel@tonic-gate  * C_Logout to clean up all private objects.
11870Sstevel@tonic-gate  */
11880Sstevel@tonic-gate CK_RV
get_cka_private_value(kernel_session_t * sp,crypto_object_id_t oid,CK_BBOOL * is_pri_obj)11890Sstevel@tonic-gate get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
11900Sstevel@tonic-gate     CK_BBOOL *is_pri_obj)
11910Sstevel@tonic-gate {
11920Sstevel@tonic-gate 	CK_RV  rv = CKR_OK;
11930Sstevel@tonic-gate 	crypto_object_get_attribute_value_t obj_ga;
11940Sstevel@tonic-gate 	crypto_object_attribute_t obj_attr;
11950Sstevel@tonic-gate 	CK_BBOOL pri_value;
11960Sstevel@tonic-gate 	int r;
11970Sstevel@tonic-gate 
11980Sstevel@tonic-gate 	obj_ga.og_session = sp->k_session;
11990Sstevel@tonic-gate 	obj_ga.og_handle = oid;
12000Sstevel@tonic-gate 	obj_ga.og_count = 1;
12010Sstevel@tonic-gate 
12020Sstevel@tonic-gate 	obj_attr.oa_type = CKA_PRIVATE;
12030Sstevel@tonic-gate 	obj_attr.oa_value = (char *)&pri_value;
12040Sstevel@tonic-gate 	obj_attr.oa_value_len = sizeof (CK_BBOOL);
12050Sstevel@tonic-gate 	obj_ga.og_attributes = (char *)&obj_attr;
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
12080Sstevel@tonic-gate 	    &obj_ga)) < 0) {
12090Sstevel@tonic-gate 		if (errno != EINTR)
12100Sstevel@tonic-gate 			break;
12110Sstevel@tonic-gate 	}
12120Sstevel@tonic-gate 	if (r < 0) {
12130Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
12140Sstevel@tonic-gate 	} else {
12150Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
12160Sstevel@tonic-gate 	}
12170Sstevel@tonic-gate 
12180Sstevel@tonic-gate 	if (rv == CKR_OK) {
12190Sstevel@tonic-gate 		*is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
12200Sstevel@tonic-gate 	}
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate 	return (rv);
12230Sstevel@tonic-gate }
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 
12260Sstevel@tonic-gate CK_RV
get_mechanism_info(kernel_slot_t * pslot,CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo,uint32_t * k_mi_flags)12270Sstevel@tonic-gate get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
12280Sstevel@tonic-gate     CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
12290Sstevel@tonic-gate {
12300Sstevel@tonic-gate 	crypto_get_provider_mechanism_info_t mechanism_info;
12317011Sda73024 	const char *string;
12320Sstevel@tonic-gate 	CK_FLAGS flags, mi_flags;
12330Sstevel@tonic-gate 	CK_RV rv;
12340Sstevel@tonic-gate 	int r;
12357011Sda73024 	char buf[11];   /* Num chars for representing ulong in ASCII */
12360Sstevel@tonic-gate 
12377106Sda73024 	if (type >= CKM_VENDOR_DEFINED) {
12387011Sda73024 		/* allocate/build a string containing the mechanism number */
12397011Sda73024 		(void) snprintf(buf, sizeof (buf), "%#lx", type);
12407011Sda73024 		string = buf;
12417011Sda73024 	} else {
12427011Sda73024 		string = pkcs11_mech2str(type);
12437011Sda73024 	}
12447011Sda73024 
12450Sstevel@tonic-gate 	if (string == NULL)
12460Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
12470Sstevel@tonic-gate 
12480Sstevel@tonic-gate 	(void) strcpy(mechanism_info.mi_mechanism_name, string);
12490Sstevel@tonic-gate 	mechanism_info.mi_provider_id = pslot->sl_provider_id;
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 	while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
12520Sstevel@tonic-gate 	    &mechanism_info)) < 0) {
12530Sstevel@tonic-gate 		if (errno != EINTR)
12540Sstevel@tonic-gate 			break;
12550Sstevel@tonic-gate 	}
12560Sstevel@tonic-gate 	if (r < 0) {
12570Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
12580Sstevel@tonic-gate 	} else {
12590Sstevel@tonic-gate 		rv = crypto2pkcs11_error_number(
12600Sstevel@tonic-gate 		    mechanism_info.mi_return_value);
12610Sstevel@tonic-gate 	}
12620Sstevel@tonic-gate 
12630Sstevel@tonic-gate 	if (rv != CKR_OK) {
12647011Sda73024 		return (rv);
12650Sstevel@tonic-gate 	}
12660Sstevel@tonic-gate 
12670Sstevel@tonic-gate 	/*
12680Sstevel@tonic-gate 	 * Atomic flags are not part of PKCS#11 so we filter
12690Sstevel@tonic-gate 	 * them out here.
12700Sstevel@tonic-gate 	 */
12710Sstevel@tonic-gate 	mi_flags = mechanism_info.mi_flags;
12720Sstevel@tonic-gate 	mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
12730Sstevel@tonic-gate 	    CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
12740Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
12750Sstevel@tonic-gate 	    CRYPTO_FG_SIGN_RECOVER_ATOMIC |
12760Sstevel@tonic-gate 	    CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
12770Sstevel@tonic-gate 	    CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
12780Sstevel@tonic-gate 	    CRYPTO_FG_MAC_DECRYPT_ATOMIC);
12790Sstevel@tonic-gate 
12800Sstevel@tonic-gate 	if (mi_flags == 0) {
12817011Sda73024 		return (CKR_MECHANISM_INVALID);
12820Sstevel@tonic-gate 	}
12830Sstevel@tonic-gate 
12840Sstevel@tonic-gate 	if (rv == CKR_OK) {
12850Sstevel@tonic-gate 		/* set the value of k_mi_flags first */
12860Sstevel@tonic-gate 		*k_mi_flags = mi_flags;
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate 		/* convert KEF flags into pkcs11 flags */
12890Sstevel@tonic-gate 		flags = CKF_HW;
12900Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_ENCRYPT)
12910Sstevel@tonic-gate 			flags |= CKF_ENCRYPT;
12920Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_DECRYPT) {
12930Sstevel@tonic-gate 			flags |= CKF_DECRYPT;
12940Sstevel@tonic-gate 			/*
12950Sstevel@tonic-gate 			 * Since we'll be emulating C_UnwrapKey() for some
12960Sstevel@tonic-gate 			 * cases, we can go ahead and claim CKF_UNWRAP
12970Sstevel@tonic-gate 			 */
12980Sstevel@tonic-gate 			flags |= CKF_UNWRAP;
12990Sstevel@tonic-gate 		}
13000Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_DIGEST)
13010Sstevel@tonic-gate 			flags |= CKF_DIGEST;
13020Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_SIGN)
13030Sstevel@tonic-gate 			flags |= CKF_SIGN;
13040Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
13050Sstevel@tonic-gate 			flags |= CKF_SIGN_RECOVER;
13060Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_VERIFY)
13070Sstevel@tonic-gate 			flags |= CKF_VERIFY;
13080Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
13090Sstevel@tonic-gate 			flags |= CKF_VERIFY_RECOVER;
13100Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_GENERATE)
13110Sstevel@tonic-gate 			flags |= CKF_GENERATE;
13120Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
13130Sstevel@tonic-gate 			flags |= CKF_GENERATE_KEY_PAIR;
13140Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_WRAP)
13150Sstevel@tonic-gate 			flags |= CKF_WRAP;
13160Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_UNWRAP)
13170Sstevel@tonic-gate 			flags |= CKF_UNWRAP;
13180Sstevel@tonic-gate 		if (mi_flags & CRYPTO_FG_DERIVE)
13190Sstevel@tonic-gate 			flags |= CKF_DERIVE;
13200Sstevel@tonic-gate 
13210Sstevel@tonic-gate 		pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
13220Sstevel@tonic-gate 		pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
13230Sstevel@tonic-gate 		pInfo->flags = flags;
13240Sstevel@tonic-gate 
13250Sstevel@tonic-gate 	}
13260Sstevel@tonic-gate 
13270Sstevel@tonic-gate 	return (rv);
13280Sstevel@tonic-gate }
1329