Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * Key Management Functions
     28  * (as defined in PKCS#11 spec section 11.14)
     29  */
     30 
     31 #include "metaGlobal.h"
     32 
     33 
     34 /*
     35  * meta_GenerateKey
     36  *
     37  */
     38 CK_RV
     39 meta_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
     40     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
     41 {
     42 	CK_RV rv;
     43 	meta_session_t *session;
     44 	meta_object_t *key = NULL;
     45 
     46 	if (pMechanism == NULL || phKey == NULL)
     47 		return (CKR_ARGUMENTS_BAD);
     48 
     49 	rv = meta_handle2session(hSession, &session);
     50 	if (rv != CKR_OK)
     51 		return (rv);
     52 
     53 
     54 	rv = meta_object_alloc(session, &key);
     55 	if (rv != CKR_OK)
     56 		goto finish;
     57 
     58 	rv = meta_generate_keys(session, pMechanism, pTemplate, ulCount, key,
     59 	    NULL, 0, NULL);
     60 	if (rv != CKR_OK)
     61 		goto finish;
     62 
     63 	meta_object_activate(key);
     64 
     65 	*phKey = (CK_OBJECT_HANDLE) key;
     66 
     67 finish:
     68 	if (rv != CKR_OK) {
     69 		if (key)
     70 			(void) meta_object_dealloc(session, key, B_TRUE);
     71 	}
     72 
     73 	REFRELEASE(session);
     74 
     75 	return (rv);
     76 }
     77 
     78 
     79 /*
     80  * meta_GenerateKeyPair
     81  *
     82  */
     83 CK_RV
     84 meta_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
     85     CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
     86     CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
     87     CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
     88 {
     89 	CK_RV rv;
     90 	meta_session_t *session;
     91 	meta_object_t *key1 = NULL, *key2 = NULL;
     92 
     93 	if (pMechanism == NULL || phPublicKey == NULL || phPrivateKey == NULL)
     94 		return (CKR_ARGUMENTS_BAD);
     95 
     96 	rv = meta_handle2session(hSession, &session);
     97 	if (rv != CKR_OK)
     98 		return (rv);
     99 
    100 
    101 	rv = meta_object_alloc(session, &key1);
    102 	if (rv != CKR_OK)
    103 		goto finish;
    104 
    105 	rv = meta_object_alloc(session, &key2);
    106 	if (rv != CKR_OK)
    107 		goto finish;
    108 
    109 	rv = meta_generate_keys(session, pMechanism,
    110 	    pPublicKeyTemplate, ulPublicKeyAttributeCount, key1,
    111 	    pPrivateKeyTemplate, ulPrivateKeyAttributeCount, key2);
    112 	if (rv != CKR_OK)
    113 		goto finish;
    114 
    115 	meta_object_activate(key1);
    116 	meta_object_activate(key2);
    117 
    118 	*phPublicKey = (CK_OBJECT_HANDLE) key1;
    119 	*phPrivateKey = (CK_OBJECT_HANDLE) key2;
    120 
    121 finish:
    122 	if (rv != CKR_OK) {
    123 		if (key1)
    124 			(void) meta_object_dealloc(session, key1, B_TRUE);
    125 		if (key2)
    126 			(void) meta_object_dealloc(session, key2, B_TRUE);
    127 	}
    128 
    129 	REFRELEASE(session);
    130 
    131 	return (rv);
    132 }
    133 
    134 
    135 /*
    136  * meta_WrapKey
    137  *
    138  */
    139 CK_RV
    140 meta_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
    141     CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
    142     CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
    143 {
    144 	CK_RV rv;
    145 	meta_session_t *session;
    146 	meta_object_t *wrappingKey, *inputKey;
    147 
    148 	if (pMechanism == NULL || pulWrappedKeyLen == NULL)
    149 		return (CKR_ARGUMENTS_BAD);
    150 
    151 	rv = meta_handle2session(hSession, &session);
    152 	if (rv != CKR_OK)
    153 		return (rv);
    154 
    155 	rv = meta_handle2object(hKey, &inputKey);
    156 	if (rv != CKR_OK) {
    157 		REFRELEASE(session);
    158 		return (rv);
    159 	}
    160 
    161 	rv = meta_handle2object(hWrappingKey, &wrappingKey);
    162 	if (rv != CKR_OK) {
    163 		OBJRELEASE(inputKey);
    164 		REFRELEASE(session);
    165 		return (rv);
    166 	}
    167 
    168 	rv = meta_wrap_key(session, pMechanism, wrappingKey,
    169 	    inputKey, pWrappedKey, pulWrappedKeyLen);
    170 
    171 finish:
    172 	OBJRELEASE(inputKey);
    173 	OBJRELEASE(wrappingKey);
    174 	REFRELEASE(session);
    175 
    176 	return (rv);
    177 }
    178 
    179 
    180 /*
    181  * meta_UnwrapKey
    182  *
    183  */
    184 CK_RV
    185 meta_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
    186     CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
    187     CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
    188     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
    189 {
    190 	CK_RV rv;
    191 	meta_session_t *session;
    192 	meta_object_t *unwrappingKey, *outputKey = NULL;
    193 
    194 	if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL)
    195 		return (CKR_ARGUMENTS_BAD);
    196 
    197 	rv = meta_handle2session(hSession, &session);
    198 	if (rv != CKR_OK)
    199 		return (rv);
    200 
    201 	rv = meta_handle2object(hUnwrappingKey, &unwrappingKey);
    202 	if (rv != CKR_OK) {
    203 		REFRELEASE(session);
    204 		return (rv);
    205 	}
    206 
    207 	rv = meta_object_alloc(session, &outputKey);
    208 	if (rv != CKR_OK)
    209 		goto finish;
    210 
    211 	(void) get_template_boolean(CKA_TOKEN, pTemplate, ulAttributeCount,
    212 	    &(outputKey->isToken));
    213 
    214 	rv = meta_unwrap_key(session, pMechanism, unwrappingKey,
    215 	    pWrappedKey, ulWrappedKeyLen,
    216 	    pTemplate, ulAttributeCount, outputKey);
    217 	if (rv != CKR_OK)
    218 		goto finish;
    219 
    220 	meta_object_activate(outputKey);
    221 
    222 	*phKey = (CK_OBJECT_HANDLE) outputKey;
    223 
    224 finish:
    225 	if (rv != CKR_OK) {
    226 		if (outputKey)
    227 			(void) meta_object_dealloc(session, outputKey, B_TRUE);
    228 	}
    229 
    230 	OBJRELEASE(unwrappingKey);
    231 	REFRELEASE(session);
    232 
    233 	return (rv);
    234 }
    235 
    236 
    237 /*
    238  * meta_DeriveKey
    239  *
    240  * This function is a bit gross because of PKCS#11 kludges that pass extra
    241  * object handles in some mechanism parameters. It probably needs to be
    242  * broken up into more managable pieces.
    243  */
    244 CK_RV
    245 meta_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
    246     CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
    247     CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
    248 {
    249 	CK_RV rv;
    250 	CK_MECHANISM *pMech = pMechanism;
    251 	meta_session_t *session;
    252 	meta_object_t *basekey1 = NULL, *basekey2 = NULL;
    253 	meta_object_t *newKey1 = NULL, *newKey2 = NULL, *newKey3 = NULL,
    254 	    *newKey4 = NULL;
    255 	boolean_t ssl_keys = B_FALSE;
    256 	boolean_t tlsprf = B_FALSE;
    257 
    258 	CK_MECHANISM metaMech;
    259 	CK_OBJECT_HANDLE *phBaseKey2 = NULL;
    260 	CK_X9_42_DH2_DERIVE_PARAMS x942_params, *x9_tmpptr;
    261 	CK_ECDH2_DERIVE_PARAMS ecdh_params, *ec_tmpptr;
    262 	CK_SSL3_KEY_MAT_OUT *ssl_key_mat;
    263 	CK_SSL3_KEY_MAT_PARAMS *keyparams;
    264 
    265 	if (pMech == NULL) {
    266 		return (CKR_ARGUMENTS_BAD);
    267 	}
    268 
    269 	/*
    270 	 * Special case: Normally, the caller must always provide storage
    271 	 * for the derived key handle at phKey. Two (related) mechanisms
    272 	 * are special, in that multiple keys are instead returned via
    273 	 * pMech->pParameter. In these cases the spec says (see 12.38.4
    274 	 * and 12.39.4) that phKey should be a NULL pointer, as it is not used.
    275 	 */
    276 	switch (pMech->mechanism) {
    277 	case CKM_SSL3_KEY_AND_MAC_DERIVE:
    278 	case CKM_TLS_KEY_AND_MAC_DERIVE:
    279 		keyparams = (CK_SSL3_KEY_MAT_PARAMS*)pMech->pParameter;
    280 
    281 		if ((keyparams == NULL) || (pMech->ulParameterLen
    282 		    != sizeof (CK_SSL3_KEY_MAT_PARAMS)))
    283 			return (CKR_ARGUMENTS_BAD);
    284 
    285 		ssl_key_mat = keyparams->pReturnedKeyMaterial;
    286 		if (ssl_key_mat == NULL)
    287 			return (CKR_ARGUMENTS_BAD);
    288 
    289 		ssl_keys = B_TRUE;
    290 		break;
    291 
    292 	case CKM_TLS_PRF:
    293 		tlsprf = B_TRUE;
    294 		break;
    295 
    296 	default:
    297 		if (phKey == NULL)
    298 			return (CKR_ARGUMENTS_BAD);
    299 	};
    300 
    301 	rv = meta_handle2session(hSession, &session);
    302 	if (rv != CKR_OK)
    303 		return (rv);
    304 
    305 	rv = meta_handle2object(hBaseKey, &basekey1);
    306 	if (rv != CKR_OK)
    307 		goto finish;
    308 
    309 
    310 	/*
    311 	 * A few oddball mechanisms pass a 2nd object handle in the parameters.
    312 	 * Here we validate that handle, and create a duplicate copy of the
    313 	 * mechanism and parameters. This is done because the application
    314 	 * does not expect these values to be changing, and could be using the
    315 	 * same data in multiple threads (eg concurrent calls to C_DeriveKey).
    316 	 * We copy the data to make sure there are no MT-Safe problems.
    317 	 */
    318 	switch (pMech->mechanism) {
    319 
    320 	case CKM_ECMQV_DERIVE:
    321 		/* uses CK_ECDH2_DERIVE_PARAMS struct as the parameter */
    322 
    323 		if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
    324 		    != sizeof (CK_ECDH2_DERIVE_PARAMS))) {
    325 			rv = CKR_ARGUMENTS_BAD;
    326 			goto finish;
    327 		}
    328 
    329 		/* Duplicate the mechanism and paramaters */
    330 		ec_tmpptr = (CK_ECDH2_DERIVE_PARAMS *)pMech->pParameter;
    331 		ecdh_params = *ec_tmpptr;
    332 		metaMech = *pMech;
    333 		metaMech.pParameter = &ecdh_params;
    334 		pMech = &metaMech;
    335 
    336 		/* Get the key the application is providing */
    337 		phBaseKey2 = &ecdh_params.hPrivateData;
    338 		break;
    339 
    340 	case CKM_X9_42_DH_HYBRID_DERIVE:
    341 	case CKM_X9_42_MQV_DERIVE:
    342 		/* both use CK_X9_42_DH2_DERIVE_PARAMS as the parameter */
    343 
    344 		if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
    345 		    != sizeof (CK_X9_42_DH2_DERIVE_PARAMS))) {
    346 			rv = CKR_ARGUMENTS_BAD;
    347 			goto finish;
    348 		}
    349 
    350 		/* Duplicate the mechanism and paramaters */
    351 		x9_tmpptr = (CK_X9_42_DH2_DERIVE_PARAMS *)pMech->pParameter;
    352 		x942_params = *x9_tmpptr;
    353 		metaMech = *pMech;
    354 		metaMech.pParameter  = &x942_params;
    355 		pMech = &metaMech;
    356 
    357 		/* Get the key the application is providing */
    358 		phBaseKey2 = &x942_params.hPrivateData;
    359 		break;
    360 
    361 	case CKM_CONCATENATE_BASE_AND_KEY:
    362 		/* uses a CK_OBJECT_HANDLE as the parameter */
    363 
    364 		if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
    365 		    != sizeof (CK_OBJECT_HANDLE))) {
    366 			rv = CKR_ARGUMENTS_BAD;
    367 			goto finish;
    368 		}
    369 
    370 		/* Duplicate the mechanism and paramaters */
    371 		metaMech = *pMech;
    372 		pMech = &metaMech;
    373 
    374 		/* Get the key the application is providing */
    375 		phBaseKey2 = (CK_OBJECT_HANDLE *) &metaMech.pParameter;
    376 		break;
    377 
    378 	default:
    379 		/* nothing special to do. */
    380 		break;
    381 	}
    382 
    383 	if (phBaseKey2) {
    384 		rv = meta_handle2object(*phBaseKey2, &basekey2);
    385 		if (rv != CKR_OK)
    386 			goto finish;
    387 	}
    388 
    389 	/*
    390 	 * Allocate meta objects to store the derived key(s). Normally just
    391 	 * a single key is created, but the SSL/TLS mechanisms generate four.
    392 	 */
    393 	rv = meta_object_alloc(session, &newKey1);
    394 	if (rv != CKR_OK)
    395 		goto finish;
    396 
    397 	if (ssl_keys) {
    398 		rv = meta_object_alloc(session, &newKey2);
    399 		if (rv != CKR_OK)
    400 			goto finish;
    401 		rv = meta_object_alloc(session, &newKey3);
    402 		if (rv != CKR_OK)
    403 			goto finish;
    404 		rv = meta_object_alloc(session, &newKey4);
    405 		if (rv != CKR_OK)
    406 			goto finish;
    407 	}
    408 
    409 
    410 	/* Perform the actual key derive operation. */
    411 	rv = meta_derive_key(session, pMech, basekey1, basekey2, phBaseKey2,
    412 	    pTemplate, ulAttributeCount, newKey1, newKey2, newKey3, newKey4);
    413 	if (rv != CKR_OK)
    414 		goto finish;
    415 
    416 	/* Make the derived key(s) active and visible to other threads. */
    417 	meta_object_activate(newKey1);
    418 	if (ssl_keys) {
    419 		meta_object_activate(newKey2);
    420 		meta_object_activate(newKey3);
    421 		meta_object_activate(newKey4);
    422 
    423 		ssl_key_mat->hClientMacSecret = (CK_OBJECT_HANDLE) newKey1;
    424 		ssl_key_mat->hServerMacSecret = (CK_OBJECT_HANDLE) newKey2;
    425 		ssl_key_mat->hClientKey = (CK_OBJECT_HANDLE) newKey3;
    426 		ssl_key_mat->hServerKey = (CK_OBJECT_HANDLE) newKey4;
    427 		/* phKey is not used (it's NULL) for these SSL/TLS mechs. */
    428 
    429 	} else if (!tlsprf) {
    430 		*phKey = (CK_OBJECT_HANDLE) newKey1;
    431 	}
    432 
    433 finish:
    434 	if (rv != CKR_OK) {
    435 		if (newKey1)
    436 			(void) meta_object_dealloc(session, newKey1, B_TRUE);
    437 		if (newKey2)
    438 			(void) meta_object_dealloc(session, newKey2, B_TRUE);
    439 		if (newKey3)
    440 			(void) meta_object_dealloc(session, newKey3, B_TRUE);
    441 		if (newKey4)
    442 			(void) meta_object_dealloc(session, newKey4, B_TRUE);
    443 	}
    444 
    445 	if (basekey1)
    446 		OBJRELEASE(basekey1);
    447 	if (basekey2)
    448 		OBJRELEASE(basekey2);
    449 	REFRELEASE(session);
    450 
    451 	return (rv);
    452 }
    453