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