xref: /titanic_44/usr/src/lib/pkcs11/libpkcs11/common/metaKeys.c (revision 9217f8fd97307134fc9a37e74da9fc2dd246e58a)
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
58cae6764SAnthony Scarpino  * Common Development and Distribution License (the "License").
68cae6764SAnthony Scarpino  * 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*9217f8fdSDan OpenSolaris Anderson  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Key Management Functions
287c478bd9Sstevel@tonic-gate  * (as defined in PKCS#11 spec section 11.14)
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include "metaGlobal.h"
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate  * meta_GenerateKey
367c478bd9Sstevel@tonic-gate  *
377c478bd9Sstevel@tonic-gate  */
387c478bd9Sstevel@tonic-gate CK_RV
meta_GenerateKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phKey)397c478bd9Sstevel@tonic-gate meta_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
407c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
417c478bd9Sstevel@tonic-gate {
427c478bd9Sstevel@tonic-gate 	CK_RV rv;
437c478bd9Sstevel@tonic-gate 	meta_session_t *session;
447c478bd9Sstevel@tonic-gate 	meta_object_t *key = NULL;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate 	if (pMechanism == NULL || phKey == NULL)
477c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
507c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
517c478bd9Sstevel@tonic-gate 		return (rv);
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate 	rv = meta_object_alloc(session, &key);
557c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
567c478bd9Sstevel@tonic-gate 		goto finish;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	rv = meta_generate_keys(session, pMechanism, pTemplate, ulCount, key,
597c478bd9Sstevel@tonic-gate 	    NULL, 0, NULL);
607c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
617c478bd9Sstevel@tonic-gate 		goto finish;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	meta_object_activate(key);
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	*phKey = (CK_OBJECT_HANDLE) key;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate finish:
687c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
697c478bd9Sstevel@tonic-gate 		if (key)
708cae6764SAnthony Scarpino 			(void) meta_object_dealloc(session, key, B_TRUE);
717c478bd9Sstevel@tonic-gate 	}
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	return (rv);
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  * meta_GenerateKeyPair
817c478bd9Sstevel@tonic-gate  *
827c478bd9Sstevel@tonic-gate  */
837c478bd9Sstevel@tonic-gate CK_RV
meta_GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey)847c478bd9Sstevel@tonic-gate meta_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
857c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
867c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
877c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
887c478bd9Sstevel@tonic-gate {
897c478bd9Sstevel@tonic-gate 	CK_RV rv;
907c478bd9Sstevel@tonic-gate 	meta_session_t *session;
917c478bd9Sstevel@tonic-gate 	meta_object_t *key1 = NULL, *key2 = NULL;
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	if (pMechanism == NULL || phPublicKey == NULL || phPrivateKey == NULL)
947c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
977c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
987c478bd9Sstevel@tonic-gate 		return (rv);
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	rv = meta_object_alloc(session, &key1);
1027c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1037c478bd9Sstevel@tonic-gate 		goto finish;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	rv = meta_object_alloc(session, &key2);
1067c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1077c478bd9Sstevel@tonic-gate 		goto finish;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	rv = meta_generate_keys(session, pMechanism,
1107c478bd9Sstevel@tonic-gate 	    pPublicKeyTemplate, ulPublicKeyAttributeCount, key1,
1117c478bd9Sstevel@tonic-gate 	    pPrivateKeyTemplate, ulPrivateKeyAttributeCount, key2);
1127c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1137c478bd9Sstevel@tonic-gate 		goto finish;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	meta_object_activate(key1);
1167c478bd9Sstevel@tonic-gate 	meta_object_activate(key2);
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	*phPublicKey = (CK_OBJECT_HANDLE) key1;
1197c478bd9Sstevel@tonic-gate 	*phPrivateKey = (CK_OBJECT_HANDLE) key2;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate finish:
1227c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1237c478bd9Sstevel@tonic-gate 		if (key1)
1248cae6764SAnthony Scarpino 			(void) meta_object_dealloc(session, key1, B_TRUE);
1257c478bd9Sstevel@tonic-gate 		if (key2)
1268cae6764SAnthony Scarpino 			(void) meta_object_dealloc(session, key2, B_TRUE);
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	return (rv);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate /*
1367c478bd9Sstevel@tonic-gate  * meta_WrapKey
1377c478bd9Sstevel@tonic-gate  *
1387c478bd9Sstevel@tonic-gate  */
1397c478bd9Sstevel@tonic-gate CK_RV
meta_WrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hWrappingKey,CK_OBJECT_HANDLE hKey,CK_BYTE_PTR pWrappedKey,CK_ULONG_PTR pulWrappedKeyLen)1407c478bd9Sstevel@tonic-gate meta_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
1417c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
1427c478bd9Sstevel@tonic-gate     CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate 	CK_RV rv;
1457c478bd9Sstevel@tonic-gate 	meta_session_t *session;
1467c478bd9Sstevel@tonic-gate 	meta_object_t *wrappingKey, *inputKey;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	if (pMechanism == NULL || pulWrappedKeyLen == NULL)
1497c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
1527c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1537c478bd9Sstevel@tonic-gate 		return (rv);
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	rv = meta_handle2object(hKey, &inputKey);
1567c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1577c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
1587c478bd9Sstevel@tonic-gate 		return (rv);
1597c478bd9Sstevel@tonic-gate 	}
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	rv = meta_handle2object(hWrappingKey, &wrappingKey);
1627c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1637c478bd9Sstevel@tonic-gate 		OBJRELEASE(inputKey);
1647c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
1657c478bd9Sstevel@tonic-gate 		return (rv);
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	rv = meta_wrap_key(session, pMechanism, wrappingKey,
1697c478bd9Sstevel@tonic-gate 	    inputKey, pWrappedKey, pulWrappedKeyLen);
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate finish:
1727c478bd9Sstevel@tonic-gate 	OBJRELEASE(inputKey);
1737c478bd9Sstevel@tonic-gate 	OBJRELEASE(wrappingKey);
1747c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	return (rv);
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate  * meta_UnwrapKey
1827c478bd9Sstevel@tonic-gate  *
1837c478bd9Sstevel@tonic-gate  */
1847c478bd9Sstevel@tonic-gate CK_RV
meta_UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)1857c478bd9Sstevel@tonic-gate meta_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
1867c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
1877c478bd9Sstevel@tonic-gate     CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
1887c478bd9Sstevel@tonic-gate     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate 	CK_RV rv;
1917c478bd9Sstevel@tonic-gate 	meta_session_t *session;
1927c478bd9Sstevel@tonic-gate 	meta_object_t *unwrappingKey, *outputKey = NULL;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL)
1957c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
1987c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1997c478bd9Sstevel@tonic-gate 		return (rv);
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	rv = meta_handle2object(hUnwrappingKey, &unwrappingKey);
2027c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
2037c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
2047c478bd9Sstevel@tonic-gate 		return (rv);
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	rv = meta_object_alloc(session, &outputKey);
2087c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
2097c478bd9Sstevel@tonic-gate 		goto finish;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	(void) get_template_boolean(CKA_TOKEN, pTemplate, ulAttributeCount,
2127c478bd9Sstevel@tonic-gate 	    &(outputKey->isToken));
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	rv = meta_unwrap_key(session, pMechanism, unwrappingKey,
2157c478bd9Sstevel@tonic-gate 	    pWrappedKey, ulWrappedKeyLen,
2167c478bd9Sstevel@tonic-gate 	    pTemplate, ulAttributeCount, outputKey);
2177c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
2187c478bd9Sstevel@tonic-gate 		goto finish;
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	meta_object_activate(outputKey);
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	*phKey = (CK_OBJECT_HANDLE) outputKey;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate finish:
2257c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
2267c478bd9Sstevel@tonic-gate 		if (outputKey)
2278cae6764SAnthony Scarpino 			(void) meta_object_dealloc(session, outputKey, B_TRUE);
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	OBJRELEASE(unwrappingKey);
2317c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	return (rv);
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate /*
2387c478bd9Sstevel@tonic-gate  * meta_DeriveKey
2397c478bd9Sstevel@tonic-gate  *
2407c478bd9Sstevel@tonic-gate  * This function is a bit gross because of PKCS#11 kludges that pass extra
2417c478bd9Sstevel@tonic-gate  * object handles in some mechanism parameters. It probably needs to be
2427c478bd9Sstevel@tonic-gate  * broken up into more managable pieces.
2437c478bd9Sstevel@tonic-gate  */
2447c478bd9Sstevel@tonic-gate CK_RV
meta_DeriveKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hBaseKey,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)2457c478bd9Sstevel@tonic-gate meta_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
2467c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
2477c478bd9Sstevel@tonic-gate     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
2487c478bd9Sstevel@tonic-gate {
2497c478bd9Sstevel@tonic-gate 	CK_RV rv;
2507c478bd9Sstevel@tonic-gate 	CK_MECHANISM *pMech = pMechanism;
2517c478bd9Sstevel@tonic-gate 	meta_session_t *session;
2527c478bd9Sstevel@tonic-gate 	meta_object_t *basekey1 = NULL, *basekey2 = NULL;
2537c478bd9Sstevel@tonic-gate 	meta_object_t *newKey1 = NULL, *newKey2 = NULL, *newKey3 = NULL,
2547c478bd9Sstevel@tonic-gate 	    *newKey4 = NULL;
2557c478bd9Sstevel@tonic-gate 	boolean_t ssl_keys = B_FALSE;
25660722cc8Sizick 	boolean_t tlsprf = B_FALSE;
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	CK_MECHANISM metaMech;
2597c478bd9Sstevel@tonic-gate 	CK_OBJECT_HANDLE *phBaseKey2 = NULL;
2607c478bd9Sstevel@tonic-gate 	CK_X9_42_DH2_DERIVE_PARAMS x942_params, *x9_tmpptr;
2617c478bd9Sstevel@tonic-gate 	CK_ECDH2_DERIVE_PARAMS ecdh_params, *ec_tmpptr;
2627c478bd9Sstevel@tonic-gate 	CK_SSL3_KEY_MAT_OUT *ssl_key_mat;
26360722cc8Sizick 	CK_SSL3_KEY_MAT_PARAMS *keyparams;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	if (pMech == NULL) {
2667c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
2677c478bd9Sstevel@tonic-gate 	}
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	/*
2707c478bd9Sstevel@tonic-gate 	 * Special case: Normally, the caller must always provide storage
2717c478bd9Sstevel@tonic-gate 	 * for the derived key handle at phKey. Two (related) mechanisms
2727c478bd9Sstevel@tonic-gate 	 * are special, in that multiple keys are instead returned via
2737c478bd9Sstevel@tonic-gate 	 * pMech->pParameter. In these cases the spec says (see 12.38.4
2747c478bd9Sstevel@tonic-gate 	 * and 12.39.4) that phKey should be a NULL pointer, as it is not used.
2757c478bd9Sstevel@tonic-gate 	 */
27660722cc8Sizick 	switch (pMech->mechanism) {
27760722cc8Sizick 	case CKM_SSL3_KEY_AND_MAC_DERIVE:
27860722cc8Sizick 	case CKM_TLS_KEY_AND_MAC_DERIVE:
27960722cc8Sizick 		keyparams = (CK_SSL3_KEY_MAT_PARAMS*)pMech->pParameter;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 		if ((keyparams == NULL) || (pMech->ulParameterLen
28260722cc8Sizick 		    != sizeof (CK_SSL3_KEY_MAT_PARAMS)))
2837c478bd9Sstevel@tonic-gate 			return (CKR_ARGUMENTS_BAD);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 		ssl_key_mat = keyparams->pReturnedKeyMaterial;
28660722cc8Sizick 		if (ssl_key_mat == NULL)
2877c478bd9Sstevel@tonic-gate 			return (CKR_ARGUMENTS_BAD);
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 		ssl_keys = B_TRUE;
29060722cc8Sizick 		break;
29160722cc8Sizick 
29260722cc8Sizick 	case CKM_TLS_PRF:
29360722cc8Sizick 		tlsprf = B_TRUE;
29460722cc8Sizick 		break;
29560722cc8Sizick 
29660722cc8Sizick 	default:
29760722cc8Sizick 		if (phKey == NULL)
2987c478bd9Sstevel@tonic-gate 			return (CKR_ARGUMENTS_BAD);
29960722cc8Sizick 	};
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
3027c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
3037c478bd9Sstevel@tonic-gate 		return (rv);
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	rv = meta_handle2object(hBaseKey, &basekey1);
3067c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
3077c478bd9Sstevel@tonic-gate 		goto finish;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	/*
3117c478bd9Sstevel@tonic-gate 	 * A few oddball mechanisms pass a 2nd object handle in the parameters.
3127c478bd9Sstevel@tonic-gate 	 * Here we validate that handle, and create a duplicate copy of the
3137c478bd9Sstevel@tonic-gate 	 * mechanism and parameters. This is done because the application
3147c478bd9Sstevel@tonic-gate 	 * does not expect these values to be changing, and could be using the
3157c478bd9Sstevel@tonic-gate 	 * same data in multiple threads (eg concurrent calls to C_DeriveKey).
3167c478bd9Sstevel@tonic-gate 	 * We copy the data to make sure there are no MT-Safe problems.
3177c478bd9Sstevel@tonic-gate 	 */
3187c478bd9Sstevel@tonic-gate 	switch (pMech->mechanism) {
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	case CKM_ECMQV_DERIVE:
3217c478bd9Sstevel@tonic-gate 		/* uses CK_ECDH2_DERIVE_PARAMS struct as the parameter */
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 		if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
3247c478bd9Sstevel@tonic-gate 		    != sizeof (CK_ECDH2_DERIVE_PARAMS))) {
3257c478bd9Sstevel@tonic-gate 			rv = CKR_ARGUMENTS_BAD;
3267c478bd9Sstevel@tonic-gate 			goto finish;
3277c478bd9Sstevel@tonic-gate 		}
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 		/* Duplicate the mechanism and paramaters */
3307c478bd9Sstevel@tonic-gate 		ec_tmpptr = (CK_ECDH2_DERIVE_PARAMS *)pMech->pParameter;
3317c478bd9Sstevel@tonic-gate 		ecdh_params = *ec_tmpptr;
3327c478bd9Sstevel@tonic-gate 		metaMech = *pMech;
3337c478bd9Sstevel@tonic-gate 		metaMech.pParameter = &ecdh_params;
3347c478bd9Sstevel@tonic-gate 		pMech = &metaMech;
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		/* Get the key the application is providing */
3377c478bd9Sstevel@tonic-gate 		phBaseKey2 = &ecdh_params.hPrivateData;
3387c478bd9Sstevel@tonic-gate 		break;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	case CKM_X9_42_DH_HYBRID_DERIVE:
3417c478bd9Sstevel@tonic-gate 	case CKM_X9_42_MQV_DERIVE:
3427c478bd9Sstevel@tonic-gate 		/* both use CK_X9_42_DH2_DERIVE_PARAMS as the parameter */
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 		if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
3457c478bd9Sstevel@tonic-gate 		    != sizeof (CK_X9_42_DH2_DERIVE_PARAMS))) {
3467c478bd9Sstevel@tonic-gate 			rv = CKR_ARGUMENTS_BAD;
3477c478bd9Sstevel@tonic-gate 			goto finish;
3487c478bd9Sstevel@tonic-gate 		}
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 		/* Duplicate the mechanism and paramaters */
3517c478bd9Sstevel@tonic-gate 		x9_tmpptr = (CK_X9_42_DH2_DERIVE_PARAMS *)pMech->pParameter;
3527c478bd9Sstevel@tonic-gate 		x942_params = *x9_tmpptr;
3537c478bd9Sstevel@tonic-gate 		metaMech = *pMech;
3547c478bd9Sstevel@tonic-gate 		metaMech.pParameter  = &x942_params;
3557c478bd9Sstevel@tonic-gate 		pMech = &metaMech;
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 		/* Get the key the application is providing */
3587c478bd9Sstevel@tonic-gate 		phBaseKey2 = &x942_params.hPrivateData;
3597c478bd9Sstevel@tonic-gate 		break;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	case CKM_CONCATENATE_BASE_AND_KEY:
3627c478bd9Sstevel@tonic-gate 		/* uses a CK_OBJECT_HANDLE as the parameter */
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 		if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
3657c478bd9Sstevel@tonic-gate 		    != sizeof (CK_OBJECT_HANDLE))) {
3667c478bd9Sstevel@tonic-gate 			rv = CKR_ARGUMENTS_BAD;
3677c478bd9Sstevel@tonic-gate 			goto finish;
3687c478bd9Sstevel@tonic-gate 		}
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 		/* Duplicate the mechanism and paramaters */
3717c478bd9Sstevel@tonic-gate 		metaMech = *pMech;
3727c478bd9Sstevel@tonic-gate 		pMech = &metaMech;
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 		/* Get the key the application is providing */
3757c478bd9Sstevel@tonic-gate 		phBaseKey2 = (CK_OBJECT_HANDLE *) &metaMech.pParameter;
3767c478bd9Sstevel@tonic-gate 		break;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	default:
3797c478bd9Sstevel@tonic-gate 		/* nothing special to do. */
3807c478bd9Sstevel@tonic-gate 		break;
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	if (phBaseKey2) {
3847c478bd9Sstevel@tonic-gate 		rv = meta_handle2object(*phBaseKey2, &basekey2);
3857c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
3867c478bd9Sstevel@tonic-gate 			goto finish;
3877c478bd9Sstevel@tonic-gate 	}
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	/*
3907c478bd9Sstevel@tonic-gate 	 * Allocate meta objects to store the derived key(s). Normally just
3917c478bd9Sstevel@tonic-gate 	 * a single key is created, but the SSL/TLS mechanisms generate four.
3927c478bd9Sstevel@tonic-gate 	 */
3937c478bd9Sstevel@tonic-gate 	rv = meta_object_alloc(session, &newKey1);
3947c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
3957c478bd9Sstevel@tonic-gate 		goto finish;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	if (ssl_keys) {
3987c478bd9Sstevel@tonic-gate 		rv = meta_object_alloc(session, &newKey2);
3997c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
4007c478bd9Sstevel@tonic-gate 			goto finish;
4017c478bd9Sstevel@tonic-gate 		rv = meta_object_alloc(session, &newKey3);
4027c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
4037c478bd9Sstevel@tonic-gate 			goto finish;
4047c478bd9Sstevel@tonic-gate 		rv = meta_object_alloc(session, &newKey4);
4057c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
4067c478bd9Sstevel@tonic-gate 			goto finish;
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	/* Perform the actual key derive operation. */
4117c478bd9Sstevel@tonic-gate 	rv = meta_derive_key(session, pMech, basekey1, basekey2, phBaseKey2,
4128cae6764SAnthony Scarpino 	    pTemplate, ulAttributeCount, newKey1, newKey2, newKey3, newKey4);
4137c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
4147c478bd9Sstevel@tonic-gate 		goto finish;
4157c478bd9Sstevel@tonic-gate 
416*9217f8fdSDan OpenSolaris Anderson 	if (tlsprf) {
417*9217f8fdSDan OpenSolaris Anderson 		(void) meta_object_dealloc(session, newKey1, B_TRUE);
418*9217f8fdSDan OpenSolaris Anderson 		newKey1 = NULL;
419*9217f8fdSDan OpenSolaris Anderson 		/* phKey isn't used (is NULL) for mechanism CKM_TLS_PRF. */
420*9217f8fdSDan OpenSolaris Anderson 
421*9217f8fdSDan OpenSolaris Anderson 	} else {
422*9217f8fdSDan OpenSolaris Anderson 		/* Make derived key(s) active and visible to other threads. */
4237c478bd9Sstevel@tonic-gate 		meta_object_activate(newKey1);
4247c478bd9Sstevel@tonic-gate 		if (ssl_keys) {
4257c478bd9Sstevel@tonic-gate 			meta_object_activate(newKey2);
4267c478bd9Sstevel@tonic-gate 			meta_object_activate(newKey3);
4277c478bd9Sstevel@tonic-gate 			meta_object_activate(newKey4);
4287c478bd9Sstevel@tonic-gate 
429*9217f8fdSDan OpenSolaris Anderson 			ssl_key_mat->hClientMacSecret
430*9217f8fdSDan OpenSolaris Anderson 			    = (CK_OBJECT_HANDLE) newKey1;
431*9217f8fdSDan OpenSolaris Anderson 			ssl_key_mat->hServerMacSecret
432*9217f8fdSDan OpenSolaris Anderson 			    = (CK_OBJECT_HANDLE) newKey2;
4337c478bd9Sstevel@tonic-gate 			ssl_key_mat->hClientKey = (CK_OBJECT_HANDLE) newKey3;
4347c478bd9Sstevel@tonic-gate 			ssl_key_mat->hServerKey = (CK_OBJECT_HANDLE) newKey4;
435*9217f8fdSDan OpenSolaris Anderson 			/* phKey isn't used (is NULL) for these SSL/TLS mechs */
43660722cc8Sizick 
437*9217f8fdSDan OpenSolaris Anderson 		} else {
4387c478bd9Sstevel@tonic-gate 			*phKey = (CK_OBJECT_HANDLE) newKey1;
4397c478bd9Sstevel@tonic-gate 		}
440*9217f8fdSDan OpenSolaris Anderson 	}
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate finish:
4437c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
4447c478bd9Sstevel@tonic-gate 		if (newKey1)
4458cae6764SAnthony Scarpino 			(void) meta_object_dealloc(session, newKey1, B_TRUE);
4467c478bd9Sstevel@tonic-gate 		if (newKey2)
4478cae6764SAnthony Scarpino 			(void) meta_object_dealloc(session, newKey2, B_TRUE);
4487c478bd9Sstevel@tonic-gate 		if (newKey3)
4498cae6764SAnthony Scarpino 			(void) meta_object_dealloc(session, newKey3, B_TRUE);
4507c478bd9Sstevel@tonic-gate 		if (newKey4)
4518cae6764SAnthony Scarpino 			(void) meta_object_dealloc(session, newKey4, B_TRUE);
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	if (basekey1)
4557c478bd9Sstevel@tonic-gate 		OBJRELEASE(basekey1);
4567c478bd9Sstevel@tonic-gate 	if (basekey2)
4577c478bd9Sstevel@tonic-gate 		OBJRELEASE(basekey2);
4587c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	return (rv);
4617c478bd9Sstevel@tonic-gate }
462