xref: /titanic_51/usr/src/lib/pkcs11/libpkcs11/common/pkcs11SUNWExtensions.c (revision 00756404c8f37791d5661850515a1be29d414db7)
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
590e0e8c4Sizick  * Common Development and Distribution License (the "License").
690e0e8c4Sizick  * 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*00756404SDarren J Moffat  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  * Solaris specific functions to reduce the initialization
277c478bd9Sstevel@tonic-gate  * overhead of using PKCS #11
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
337c478bd9Sstevel@tonic-gate #include <assert.h>
347c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
3590e0e8c4Sizick #include <pkcs11Global.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate static CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
387c478bd9Sstevel@tonic-gate static CK_BBOOL falsevalue = FALSE;
397c478bd9Sstevel@tonic-gate static CK_BBOOL truevalue = TRUE;
407c478bd9Sstevel@tonic-gate 
411c9bd843Sdinak #define	NUM_SECRETKEY_ATTRS	12
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate typedef struct _ATTRTYPE_MECHINFO_MAPPING {
447c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE_TYPE attr;
457c478bd9Sstevel@tonic-gate 	CK_FLAGS	flag;
467c478bd9Sstevel@tonic-gate } ATTRTYPE_MECHINFO_MAPPING;
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /* possible attribute types for creating key */
497c478bd9Sstevel@tonic-gate ATTRTYPE_MECHINFO_MAPPING mapping[] = {
507c478bd9Sstevel@tonic-gate 	{CKA_ENCRYPT, CKF_ENCRYPT},
517c478bd9Sstevel@tonic-gate 	{CKA_DECRYPT, CKF_DECRYPT},
527c478bd9Sstevel@tonic-gate 	{CKA_SIGN, CKF_SIGN},
531c9bd843Sdinak 	{CKA_VERIFY, CKF_VERIFY},
541c9bd843Sdinak 	{CKA_WRAP, CKF_WRAP},
551c9bd843Sdinak 	{CKA_UNWRAP, CKF_UNWRAP}
567c478bd9Sstevel@tonic-gate };
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * List of mechanisms that only supports asymmetric key operations
617c478bd9Sstevel@tonic-gate  * in PKCS #11 V2.11
627c478bd9Sstevel@tonic-gate  */
637c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE asymmetric_mechs[] = {
647c478bd9Sstevel@tonic-gate 	CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_9796, CKM_RSA_X_509,
657c478bd9Sstevel@tonic-gate 	CKM_RSA_PKCS_OAEP, CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31,
667c478bd9Sstevel@tonic-gate 	CKM_RSA_PKCS_PSS, CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1,
677c478bd9Sstevel@tonic-gate 	CKM_DSA_PARAMETER_GEN, CKM_ECDSA_KEY_PAIR_GEN, CKM_EC_KEY_PAIR_GEN,
687c478bd9Sstevel@tonic-gate 	CKM_ECDSA, CKM_ECDSA_SHA1, CKM_ECDH1_DERIVE,
697c478bd9Sstevel@tonic-gate 	CKM_ECDH1_COFACTOR_DERIVE, CKM_ECMQV_DERIVE
707c478bd9Sstevel@tonic-gate };
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 
731c9bd843Sdinak typedef struct _KEY_TYPE_SIZE_MAPPING {
741c9bd843Sdinak 	CK_KEY_TYPE type;
751c9bd843Sdinak 	CK_ULONG len;
761c9bd843Sdinak } KEY_TYPE_SIZE_MAPPING;
771c9bd843Sdinak 
781c9bd843Sdinak /*
791c9bd843Sdinak  * List of secret key types that have fixed sizes and their sizes.
801c9bd843Sdinak  * These key types do not allow CKA_VALUE_LEN for key generation.
811c9bd843Sdinak  * The sizes are in bytes.
821c9bd843Sdinak  *
831c9bd843Sdinak  * Discrete-sized keys, such as AES and Twofish, and variable sized
841c9bd843Sdinak  * keys, such as Blowfish, are not in this list.
851c9bd843Sdinak  */
861c9bd843Sdinak KEY_TYPE_SIZE_MAPPING fixed_size_secrets[] = {
871c9bd843Sdinak 	{CKK_DES, 8}, {CKK_DES2, 16}, {CKK_DES3, 24}, {CKK_IDEA, 16},
881c9bd843Sdinak 	{CKK_CDMF, 8}, {CKK_SKIPJACK, 12}, {CKK_BATON, 40}, {CKK_JUNIPER, 40}
891c9bd843Sdinak };
901c9bd843Sdinak 
9117e2ff97Sdinak /*
9217e2ff97Sdinak  * match_mech is an example of many possible criteria functions.
9317e2ff97Sdinak  * It matches the given mech type (in args) with the slot's mech info.
9417e2ff97Sdinak  * If no match is found, pkcs11_GetCriteriaSession is asked to return
9517e2ff97Sdinak  * CKR_MECHANISM_INVALID.
9617e2ff97Sdinak  */
9717e2ff97Sdinak boolean_t
9817e2ff97Sdinak match_mech(CK_SLOT_ID slot_id, void *args, CK_RV *rv)
9917e2ff97Sdinak {
10017e2ff97Sdinak 	CK_MECHANISM_INFO mech_info;
10117e2ff97Sdinak 	CK_MECHANISM_TYPE mech = (CK_MECHANISM_TYPE)args;
10217e2ff97Sdinak 
10317e2ff97Sdinak 	*rv = CKR_MECHANISM_INVALID;
10417e2ff97Sdinak 	return (C_GetMechanismInfo(slot_id, mech, &mech_info) == CKR_OK);
10517e2ff97Sdinak }
10617e2ff97Sdinak 
10717e2ff97Sdinak /*
10817e2ff97Sdinak  * pkcs11_GetCriteriaSession will initialize the framework and do all
10917e2ff97Sdinak  * the necessary work of calling C_GetSlotList(), C_GetMechanismInfo()
11017e2ff97Sdinak  * C_OpenSession() to create a session that meets all the criteria in
11117e2ff97Sdinak  * the given function pointer.
11217e2ff97Sdinak  *
11317e2ff97Sdinak  * The criteria function must return a boolean value of true or false.
11417e2ff97Sdinak  * The arguments to the function are the current slot id, an opaque
11517e2ff97Sdinak  * args value that is passed through to the function, and the error
11617e2ff97Sdinak  * value pkcs11_GetCriteriaSession should return if no slot id meets the
11717e2ff97Sdinak  * criteria.
11817e2ff97Sdinak  *
11917e2ff97Sdinak  * If the function is called multiple times, it will return a new session
12017e2ff97Sdinak  * without reinitializing the framework.
12117e2ff97Sdinak  */
12217e2ff97Sdinak CK_RV
12317e2ff97Sdinak pkcs11_GetCriteriaSession(
12417e2ff97Sdinak     boolean_t (*criteria)(CK_SLOT_ID slot_id, void *args, CK_RV *rv),
12517e2ff97Sdinak     void *args, CK_SESSION_HANDLE_PTR hSession)
12617e2ff97Sdinak {
12717e2ff97Sdinak 	CK_RV rv;
12817e2ff97Sdinak 	CK_ULONG slotcount;
12917e2ff97Sdinak 	CK_SLOT_ID_PTR slot_list;
13017e2ff97Sdinak 	CK_SLOT_ID slot_id;
13117e2ff97Sdinak 	CK_ULONG i;
13217e2ff97Sdinak 
13317e2ff97Sdinak 	if (hSession == NULL || criteria == NULL) {
13417e2ff97Sdinak 		return (CKR_ARGUMENTS_BAD);
13517e2ff97Sdinak 	}
13617e2ff97Sdinak 
13717e2ff97Sdinak 	/* initialize PKCS #11 */
13817e2ff97Sdinak 	if (!pkcs11_initialized) {
13917e2ff97Sdinak 		rv = C_Initialize(NULL);
14017e2ff97Sdinak 		if ((rv != CKR_OK) &&
14117e2ff97Sdinak 		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
14217e2ff97Sdinak 			return (rv);
14317e2ff97Sdinak 		}
14417e2ff97Sdinak 	}
14517e2ff97Sdinak 
14617e2ff97Sdinak 	/* get slot count */
14717e2ff97Sdinak 	rv = C_GetSlotList(0, NULL, &slotcount);
14817e2ff97Sdinak 	if (rv != CKR_OK) {
14917e2ff97Sdinak 		return (rv);
15017e2ff97Sdinak 	}
15117e2ff97Sdinak 
15217e2ff97Sdinak 	if (slotcount == 0) {
15317e2ff97Sdinak 		return (CKR_FUNCTION_FAILED);
15417e2ff97Sdinak 	}
15517e2ff97Sdinak 
15617e2ff97Sdinak 
15717e2ff97Sdinak 	/* allocate memory for slot list */
15817e2ff97Sdinak 	slot_list = malloc(slotcount * sizeof (CK_SLOT_ID));
15917e2ff97Sdinak 	if (slot_list == NULL) {
16017e2ff97Sdinak 		return (CKR_HOST_MEMORY);
16117e2ff97Sdinak 	}
16217e2ff97Sdinak 
16317e2ff97Sdinak 	if ((rv = C_GetSlotList(0, slot_list, &slotcount)) != CKR_OK) {
16417e2ff97Sdinak 		free(slot_list);
16517e2ff97Sdinak 		return (rv);
16617e2ff97Sdinak 	}
16717e2ff97Sdinak 
16817e2ff97Sdinak 	/* find slot with matching criteria */
16917e2ff97Sdinak 	for (i = 0; i < slotcount; i++) {
17017e2ff97Sdinak 		slot_id = slot_list[i];
17117e2ff97Sdinak 		if ((*criteria)(slot_id, args, &rv)) {
17217e2ff97Sdinak 			break;
17317e2ff97Sdinak 		}
17417e2ff97Sdinak 	}
17517e2ff97Sdinak 
17617e2ff97Sdinak 	if (i == slotcount) {
17717e2ff97Sdinak 		/* no matching slot found */
17817e2ff97Sdinak 		free(slot_list);
17917e2ff97Sdinak 		return (rv);	/* this rv is from the criteria function */
18017e2ff97Sdinak 	}
18117e2ff97Sdinak 
18217e2ff97Sdinak 	rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL,
18317e2ff97Sdinak 	    NULL, hSession);
18417e2ff97Sdinak 
18517e2ff97Sdinak 	free(slot_list);
18617e2ff97Sdinak 	return (rv);
18717e2ff97Sdinak }
1881c9bd843Sdinak 
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate  * SUNW_C_GetMechSession will initialize the framework and do all
1917c478bd9Sstevel@tonic-gate  * of the neccessary work of calling C_GetSlotList(), C_GetMechanismInfo()
19217e2ff97Sdinak  * C_OpenSession() to create a session capable of providing the requested
1937c478bd9Sstevel@tonic-gate  * mechanism.
1947c478bd9Sstevel@tonic-gate  *
1957c478bd9Sstevel@tonic-gate  * If the function is called multiple times, it will return a new session
1967c478bd9Sstevel@tonic-gate  * without reinitializing the framework.
1977c478bd9Sstevel@tonic-gate  */
1987c478bd9Sstevel@tonic-gate CK_RV
1997c478bd9Sstevel@tonic-gate SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE_PTR hSession)
2007c478bd9Sstevel@tonic-gate {
20117e2ff97Sdinak 	/*
20217e2ff97Sdinak 	 * All the code in this function can be replaced with one line:
20317e2ff97Sdinak 	 *
20417e2ff97Sdinak 	 * return (pkcs11_GetCriteriaSession(match_mech, (void *)mech,
20517e2ff97Sdinak 	 *	hSession));
20617e2ff97Sdinak 	 *
20717e2ff97Sdinak 	 */
2087c478bd9Sstevel@tonic-gate 	CK_RV rv;
2097c478bd9Sstevel@tonic-gate 	CK_ULONG slotcount;
2107c478bd9Sstevel@tonic-gate 	CK_SLOT_ID_PTR slot_list;
2117c478bd9Sstevel@tonic-gate 	CK_SLOT_ID slot_id;
2127c478bd9Sstevel@tonic-gate 	CK_MECHANISM_INFO mech_info;
2137c478bd9Sstevel@tonic-gate 	CK_ULONG i;
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	if (hSession == NULL) {
2167c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	/* initialize PKCS #11 */
22090e0e8c4Sizick 	if (!pkcs11_initialized) {
2217c478bd9Sstevel@tonic-gate 		rv = C_Initialize(NULL);
22290e0e8c4Sizick 		if ((rv != CKR_OK) &&
22390e0e8c4Sizick 		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
2247c478bd9Sstevel@tonic-gate 			return (rv);
2257c478bd9Sstevel@tonic-gate 		}
22690e0e8c4Sizick 	}
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	/* get slot count */
2297c478bd9Sstevel@tonic-gate 	rv = C_GetSlotList(0, NULL, &slotcount);
2307c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
2317c478bd9Sstevel@tonic-gate 		return (rv);
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	if (slotcount == 0) {
2357c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	/* allocate memory for slot list */
2407c478bd9Sstevel@tonic-gate 	slot_list = malloc(slotcount * sizeof (CK_SLOT_ID));
2417c478bd9Sstevel@tonic-gate 	if (slot_list == NULL) {
2427c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if ((rv = C_GetSlotList(0, slot_list, &slotcount)) != CKR_OK) {
2467c478bd9Sstevel@tonic-gate 		free(slot_list);
2477c478bd9Sstevel@tonic-gate 		return (rv);
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	/* find slot with matching mechanism */
2517c478bd9Sstevel@tonic-gate 	for (i = 0; i < slotcount; i++) {
2527c478bd9Sstevel@tonic-gate 		slot_id = slot_list[i];
2537c478bd9Sstevel@tonic-gate 		if (C_GetMechanismInfo(slot_id, mech, &mech_info) == CKR_OK) {
2547c478bd9Sstevel@tonic-gate 			/* found mechanism */
2557c478bd9Sstevel@tonic-gate 			break;
2567c478bd9Sstevel@tonic-gate 		}
2577c478bd9Sstevel@tonic-gate 	}
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	if (i == slotcount) {
2607c478bd9Sstevel@tonic-gate 		/* no matching mechanism found */
2617c478bd9Sstevel@tonic-gate 		free(slot_list);
2627c478bd9Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
2637c478bd9Sstevel@tonic-gate 	}
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL,
2667c478bd9Sstevel@tonic-gate 	    NULL, hSession);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	free(slot_list);
2697c478bd9Sstevel@tonic-gate 	return (rv);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate  * SUNW_C_KeyToObject creates a secret key object for the given
2747c478bd9Sstevel@tonic-gate  * mechanism from the rawkey data.
2757c478bd9Sstevel@tonic-gate  */
2767c478bd9Sstevel@tonic-gate CK_RV
2777c478bd9Sstevel@tonic-gate SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession, CK_MECHANISM_TYPE mech,
2787c478bd9Sstevel@tonic-gate     const void *rawkey, size_t rawkey_len, CK_OBJECT_HANDLE_PTR obj)
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	CK_RV rv;
2827c478bd9Sstevel@tonic-gate 	CK_SESSION_INFO session_info;
2837c478bd9Sstevel@tonic-gate 	CK_SLOT_ID slot_id;
2847c478bd9Sstevel@tonic-gate 	CK_MECHANISM_INFO mech_info;
2857c478bd9Sstevel@tonic-gate 	CK_ULONG i, j;
2867c478bd9Sstevel@tonic-gate 	CK_KEY_TYPE keytype;
2877c478bd9Sstevel@tonic-gate 	CK_ULONG num_asym_mechs, num_mapping;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	/* template for creating generic secret key object */
2907c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE template[NUM_SECRETKEY_ATTRS];
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	if ((hSession == NULL) || (obj == NULL) ||
2937c478bd9Sstevel@tonic-gate 	    (rawkey == NULL) || (rawkey_len == 0)) {
2947c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/*
2987c478bd9Sstevel@tonic-gate 	 * Check to make sure mechanism type is not for asymmetric key
2997c478bd9Sstevel@tonic-gate 	 * only operations.  This function is only applicable to
3007c478bd9Sstevel@tonic-gate 	 * generating secret key.
3017c478bd9Sstevel@tonic-gate 	 */
3027c478bd9Sstevel@tonic-gate 	num_asym_mechs = sizeof (asymmetric_mechs) / sizeof (CK_MECHANISM_TYPE);
3037c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_asym_mechs; i++) {
3047c478bd9Sstevel@tonic-gate 		if (mech == asymmetric_mechs[i]) {
3057c478bd9Sstevel@tonic-gate 			return (CKR_MECHANISM_INVALID);
3067c478bd9Sstevel@tonic-gate 		}
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	rv = C_GetSessionInfo(hSession, &session_info);
3107c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
3111c9bd843Sdinak 		return (rv);
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	slot_id = session_info.slotID;
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	i = 0;
3177c478bd9Sstevel@tonic-gate 	template[i].type = CKA_CLASS;
3187c478bd9Sstevel@tonic-gate 	template[i].pValue = &objclass;
3197c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (objclass);
3207c478bd9Sstevel@tonic-gate 	i++;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/* get the key type for this mechanism */
3237c478bd9Sstevel@tonic-gate 	if ((rv = pkcs11_mech2keytype(mech, &keytype)) != CKR_OK) {
3247c478bd9Sstevel@tonic-gate 		return (rv);
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	assert(i < NUM_SECRETKEY_ATTRS);
3287c478bd9Sstevel@tonic-gate 	template[i].type = CKA_KEY_TYPE;
3297c478bd9Sstevel@tonic-gate 	template[i].pValue = &keytype;
3307c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (keytype);
3317c478bd9Sstevel@tonic-gate 	i++;
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	rv = C_GetMechanismInfo(slot_id, mech, &mech_info);
3347c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
3351c9bd843Sdinak 		return (rv);
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate 
3381c9bd843Sdinak 	/* set the attribute type flag on object based on mechanism */
3397c478bd9Sstevel@tonic-gate 	num_mapping = sizeof (mapping) / sizeof (ATTRTYPE_MECHINFO_MAPPING);
3407c478bd9Sstevel@tonic-gate 	for (j = 0; j < num_mapping; j++) {
3417c478bd9Sstevel@tonic-gate 		assert(i < NUM_SECRETKEY_ATTRS);
3427c478bd9Sstevel@tonic-gate 		template[i].type = mapping[j].attr;
3437c478bd9Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (falsevalue);
3447c478bd9Sstevel@tonic-gate 		if (mech_info.flags & ((mapping[j]).flag)) {
3457c478bd9Sstevel@tonic-gate 			template[i].pValue = &truevalue;
3467c478bd9Sstevel@tonic-gate 		} else {
3477c478bd9Sstevel@tonic-gate 			template[i].pValue = &falsevalue;
3487c478bd9Sstevel@tonic-gate 		}
3497c478bd9Sstevel@tonic-gate 		i++;
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	assert(i < NUM_SECRETKEY_ATTRS);
3537c478bd9Sstevel@tonic-gate 	template[i].type = CKA_TOKEN;
3547c478bd9Sstevel@tonic-gate 	template[i].pValue = &falsevalue;
3557c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (falsevalue);
3567c478bd9Sstevel@tonic-gate 	i++;
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	assert(i < NUM_SECRETKEY_ATTRS);
3597c478bd9Sstevel@tonic-gate 	template[i].type = CKA_VALUE;
3607c478bd9Sstevel@tonic-gate 	template[i].pValue = (CK_VOID_PTR)rawkey;
3617c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = (CK_ULONG)rawkey_len;
3627c478bd9Sstevel@tonic-gate 	i++;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	rv = C_CreateObject(hSession, template, i, obj);
3651c9bd843Sdinak 	return (rv);
3661c9bd843Sdinak }
3671c9bd843Sdinak 
3681c9bd843Sdinak 
3691c9bd843Sdinak /*
3701c9bd843Sdinak  * pkcs11_PasswdToPBKD2Object will create a secret key from the given string
3711c9bd843Sdinak  * (e.g. passphrase) using PKCS#5 Password-Based Key Derivation Function 2
3721c9bd843Sdinak  * (PBKD2).
3731c9bd843Sdinak  *
3741c9bd843Sdinak  * Session must be open.  Salt and iterations use defaults.
3751c9bd843Sdinak  */
3761c9bd843Sdinak CK_RV
3771c9bd843Sdinak pkcs11_PasswdToPBKD2Object(CK_SESSION_HANDLE hSession, char *passphrase,
3781c9bd843Sdinak     size_t passphrase_len, void *salt, size_t salt_len, CK_ULONG iterations,
3791c9bd843Sdinak     CK_KEY_TYPE key_type, CK_ULONG key_len, CK_FLAGS key_flags,
3801c9bd843Sdinak     CK_OBJECT_HANDLE_PTR obj)
3811c9bd843Sdinak {
3821c9bd843Sdinak 	CK_RV rv;
3831c9bd843Sdinak 	CK_PKCS5_PBKD2_PARAMS params;
3841c9bd843Sdinak 	CK_MECHANISM mechanism;
3851c9bd843Sdinak 	CK_KEY_TYPE asym_key_type;
3861c9bd843Sdinak 	CK_ULONG i, j, num_asym_mechs, num_fixed_secs, num_mapping;
3871c9bd843Sdinak 	CK_ATTRIBUTE template[NUM_SECRETKEY_ATTRS];
3881c9bd843Sdinak 
3891c9bd843Sdinak 	if (hSession == NULL || obj == NULL ||
3901c9bd843Sdinak 	    passphrase == NULL || passphrase_len == 0 ||
3911c9bd843Sdinak 	    iterations == 0UL) {
3921c9bd843Sdinak 		return (CKR_ARGUMENTS_BAD);
3931c9bd843Sdinak 	}
3941c9bd843Sdinak 
3951c9bd843Sdinak 	/*
3961c9bd843Sdinak 	 * Check to make sure key type is not asymmetric.  This function
3971c9bd843Sdinak 	 * is only applicable to generating secret key.
3981c9bd843Sdinak 	 */
3991c9bd843Sdinak 	num_asym_mechs = sizeof (asymmetric_mechs) / sizeof (CK_MECHANISM_TYPE);
4001c9bd843Sdinak 	for (i = 0; i < num_asym_mechs; i++) {
4011c9bd843Sdinak 		rv = pkcs11_mech2keytype(asymmetric_mechs[i], &asym_key_type);
4021c9bd843Sdinak 		assert(rv == CKR_OK);
4031c9bd843Sdinak 		if (key_type == asym_key_type) {
4041c9bd843Sdinak 			return (CKR_KEY_TYPE_INCONSISTENT);
4051c9bd843Sdinak 		}
4061c9bd843Sdinak 	}
4071c9bd843Sdinak 
4081c9bd843Sdinak 	/*
4091c9bd843Sdinak 	 * Key length must either be 0 or the correct size for PBKD of
4101c9bd843Sdinak 	 * fixed-size secret keys.  However, underlying key generation
4111c9bd843Sdinak 	 * cannot have CKA_VALUE_LEN set for the key length attribute.
4121c9bd843Sdinak 	 */
4131c9bd843Sdinak 	num_fixed_secs =
4141c9bd843Sdinak 	    sizeof (fixed_size_secrets) / sizeof (KEY_TYPE_SIZE_MAPPING);
4151c9bd843Sdinak 	for (i = 0; i < num_fixed_secs; i++) {
4161c9bd843Sdinak 		if (key_type == fixed_size_secrets[i].type) {
4171c9bd843Sdinak 			if (key_len == fixed_size_secrets[i].len) {
4181c9bd843Sdinak 				key_len = 0;
4191c9bd843Sdinak 			}
4201c9bd843Sdinak 			if (key_len == 0) {
4211c9bd843Sdinak 				break;
4221c9bd843Sdinak 			}
4231c9bd843Sdinak 			return (CKR_KEY_SIZE_RANGE);
4241c9bd843Sdinak 		}
4251c9bd843Sdinak 	}
4261c9bd843Sdinak 
4271c9bd843Sdinak 	if (salt == NULL || salt_len == 0) {
4281c9bd843Sdinak 		params.saltSource = 0;
4291c9bd843Sdinak 		params.pSaltSourceData = NULL;
4301c9bd843Sdinak 		params.ulSaltSourceDataLen = 0;
4311c9bd843Sdinak 	} else {
4321c9bd843Sdinak 		params.saltSource = CKZ_SALT_SPECIFIED;
4331c9bd843Sdinak 		params.pSaltSourceData = salt;
4341c9bd843Sdinak 		params.ulSaltSourceDataLen = salt_len;
4351c9bd843Sdinak 	}
4361c9bd843Sdinak 	params.iterations = iterations;
4371c9bd843Sdinak 	params.prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
4381c9bd843Sdinak 	params.pPrfData = NULL;
4391c9bd843Sdinak 	params.ulPrfDataLen = 0;
4401c9bd843Sdinak 	params.pPassword = (CK_UTF8CHAR_PTR)passphrase;
4411c9bd843Sdinak 	params.ulPasswordLen = (CK_ULONG_PTR)&passphrase_len;
4421c9bd843Sdinak 	/*
4431c9bd843Sdinak 	 * PKCS#11 spec error, ulPasswordLen should have been pulPasswordLen,
4441c9bd843Sdinak 	 * or its type should have been CK_ULONG instead of CK_ULONG_PTR,
4451c9bd843Sdinak 	 * but it's legacy now
4461c9bd843Sdinak 	 */
4471c9bd843Sdinak 
4481c9bd843Sdinak 	mechanism.mechanism = CKM_PKCS5_PBKD2;
4491c9bd843Sdinak 	mechanism.pParameter = &params;
4501c9bd843Sdinak 	mechanism.ulParameterLen = sizeof (params);
4511c9bd843Sdinak 
4521c9bd843Sdinak 	i = 0;
4531c9bd843Sdinak 	template[i].type = CKA_CLASS;
4541c9bd843Sdinak 	template[i].pValue = &objclass;
4551c9bd843Sdinak 	template[i].ulValueLen = sizeof (objclass);
4561c9bd843Sdinak 	i++;
4571c9bd843Sdinak 
4581c9bd843Sdinak 	assert(i < NUM_SECRETKEY_ATTRS);
4591c9bd843Sdinak 	template[i].type = CKA_KEY_TYPE;
4601c9bd843Sdinak 	template[i].pValue = &key_type;
4611c9bd843Sdinak 	template[i].ulValueLen = sizeof (key_type);
4621c9bd843Sdinak 	i++;
4631c9bd843Sdinak 
4641c9bd843Sdinak 	assert(i < NUM_SECRETKEY_ATTRS);
4651c9bd843Sdinak 	template[i].type = CKA_TOKEN;
4661c9bd843Sdinak 	template[i].pValue = &falsevalue;
4671c9bd843Sdinak 	template[i].ulValueLen = sizeof (falsevalue);
4681c9bd843Sdinak 	i++;
4691c9bd843Sdinak 
4701c9bd843Sdinak 	if (key_len != 0) {
4711c9bd843Sdinak 		assert(i < NUM_SECRETKEY_ATTRS);
4721c9bd843Sdinak 		template[i].type = CKA_VALUE_LEN;
4731c9bd843Sdinak 		template[i].pValue = &key_len;
4741c9bd843Sdinak 		template[i].ulValueLen = sizeof (key_len);
4751c9bd843Sdinak 		i++;
4761c9bd843Sdinak 	}
4771c9bd843Sdinak 
4781c9bd843Sdinak 	/*
4791c9bd843Sdinak 	 * C_GenerateKey may not implicitly set capability attributes,
4801c9bd843Sdinak 	 * e.g. CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, ...
4811c9bd843Sdinak 	 */
4821c9bd843Sdinak 	num_mapping = sizeof (mapping) / sizeof (ATTRTYPE_MECHINFO_MAPPING);
4831c9bd843Sdinak 	for (j = 0; j < num_mapping; j++) {
4841c9bd843Sdinak 		assert(i < NUM_SECRETKEY_ATTRS);
4851c9bd843Sdinak 		template[i].type = mapping[j].attr;
4861c9bd843Sdinak 		template[i].pValue = (key_flags & ((mapping[j]).flag)) ?
4871c9bd843Sdinak 		    &truevalue : &falsevalue;
4881c9bd843Sdinak 		template[i].ulValueLen = sizeof (falsevalue);
4891c9bd843Sdinak 		i++;
4901c9bd843Sdinak 	}
4911c9bd843Sdinak 
4921c9bd843Sdinak 	rv = C_GenerateKey(hSession, &mechanism, template, i, obj);
4931c9bd843Sdinak 	return (rv);
4941c9bd843Sdinak }
4951c9bd843Sdinak 
4961c9bd843Sdinak /*
4971c9bd843Sdinak  * pkcs11_ObjectToKey gets the rawkey data from a secret key object.
4981c9bd843Sdinak  * The caller is responsible to free the allocated rawkey data.
4991c9bd843Sdinak  *
5001c9bd843Sdinak  * Optionally the object can be destroyed after the value is retrieved.
5011c9bd843Sdinak  * As an example, after using pkcs11_PasswdToPBKD2Object() to create a
5021c9bd843Sdinak  * secret key object from a passphrase, an app may call pkcs11_ObjectToKey
5031c9bd843Sdinak  * to get the rawkey data.  The intermediate object may no longer be needed
5041c9bd843Sdinak  * and should be destroyed.
5051c9bd843Sdinak  */
5061c9bd843Sdinak CK_RV
5071c9bd843Sdinak pkcs11_ObjectToKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE obj,
5081c9bd843Sdinak     void **rawkey, size_t *rawkey_len, boolean_t destroy_obj)
5091c9bd843Sdinak {
5101c9bd843Sdinak 	CK_RV rv;
5111c9bd843Sdinak 	CK_ATTRIBUTE template;
5121c9bd843Sdinak 
513*00756404SDarren J Moffat 	if (hSession == NULL)
514*00756404SDarren J Moffat 		return (CKR_SESSION_HANDLE_INVALID);
515*00756404SDarren J Moffat 	if (obj == NULL)
516*00756404SDarren J Moffat 		return (CKR_OBJECT_HANDLE_INVALID);
517*00756404SDarren J Moffat 	if (rawkey == NULL || rawkey_len == NULL)
5181c9bd843Sdinak 		return (CKR_ARGUMENTS_BAD);
5191c9bd843Sdinak 
5201c9bd843Sdinak 	template.type = CKA_VALUE;
5211c9bd843Sdinak 	template.pValue = NULL;
5221c9bd843Sdinak 	template.ulValueLen = 0;
5231c9bd843Sdinak 
5241c9bd843Sdinak 	/* First get the size of the rawkey */
5251c9bd843Sdinak 	rv = C_GetAttributeValue(hSession, obj, &template, 1);
5267c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
5277c478bd9Sstevel@tonic-gate 		return (rv);
5287c478bd9Sstevel@tonic-gate 	}
5297c478bd9Sstevel@tonic-gate 
5301c9bd843Sdinak 	template.pValue = malloc(template.ulValueLen);
5311c9bd843Sdinak 	if (template.pValue == NULL) {
5321c9bd843Sdinak 		return (CKR_HOST_MEMORY);
5331c9bd843Sdinak 	}
5347c478bd9Sstevel@tonic-gate 
5351c9bd843Sdinak 	/* Then get the rawkey data */
5361c9bd843Sdinak 	rv = C_GetAttributeValue(hSession, obj, &template, 1);
5371c9bd843Sdinak 	if (rv != CKR_OK) {
5381c9bd843Sdinak 		free(template.pValue);
5391c9bd843Sdinak 		return (rv);
5401c9bd843Sdinak 	}
5411c9bd843Sdinak 
5421c9bd843Sdinak 	if (destroy_obj) {
5431c9bd843Sdinak 		/*
5441c9bd843Sdinak 		 * Could have asserted rv == CKR_OK, making threaded
5451c9bd843Sdinak 		 * apps that share objects see stars.  Here mercy is ok.
5461c9bd843Sdinak 		 */
5471c9bd843Sdinak 		(void) C_DestroyObject(hSession, obj);
5481c9bd843Sdinak 	}
5491c9bd843Sdinak 
5501c9bd843Sdinak 	*rawkey = template.pValue;
5511c9bd843Sdinak 	*rawkey_len = template.ulValueLen;
5521c9bd843Sdinak 
5531c9bd843Sdinak 	return (CKR_OK);
5541c9bd843Sdinak }
5551c9bd843Sdinak 
5561c9bd843Sdinak /*
5571c9bd843Sdinak  * pkcs11_PasswdToKey will create PKCS#5 PBKD2 rawkey data from the
5581c9bd843Sdinak  * given passphrase.  The caller is responsible to free the allocated
5591c9bd843Sdinak  * rawkey data.
5601c9bd843Sdinak  */
5611c9bd843Sdinak CK_RV
5621c9bd843Sdinak pkcs11_PasswdToKey(CK_SESSION_HANDLE hSession, char *passphrase,
5631c9bd843Sdinak     size_t passphrase_len, void *salt, size_t salt_len, CK_KEY_TYPE key_type,
5641c9bd843Sdinak     CK_ULONG key_len, void **rawkey, size_t *rawkey_len)
5651c9bd843Sdinak {
5661c9bd843Sdinak 	CK_RV rv;
5671c9bd843Sdinak 	CK_OBJECT_HANDLE obj;
5681c9bd843Sdinak 
5691c9bd843Sdinak 	rv = pkcs11_PasswdToPBKD2Object(hSession, passphrase, passphrase_len,
5701c9bd843Sdinak 	    salt, salt_len, CK_PKCS5_PBKD2_ITERATIONS, key_type, key_len, 0,
5711c9bd843Sdinak 	    &obj);
5721c9bd843Sdinak 	if (rv != CKR_OK)
5731c9bd843Sdinak 		return (rv);
5741c9bd843Sdinak 	rv = pkcs11_ObjectToKey(hSession, obj, rawkey, rawkey_len, B_TRUE);
5757c478bd9Sstevel@tonic-gate 	return (rv);
5767c478bd9Sstevel@tonic-gate }
577