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 2010 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 OBJRELEASE(inputKey); 172 OBJRELEASE(wrappingKey); 173 REFRELEASE(session); 174 175 return (rv); 176 } 177 178 179 /* 180 * meta_UnwrapKey 181 * 182 */ 183 CK_RV 184 meta_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 185 CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, 186 CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, 187 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 188 { 189 CK_RV rv; 190 meta_session_t *session; 191 meta_object_t *unwrappingKey, *outputKey = NULL; 192 193 if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) 194 return (CKR_ARGUMENTS_BAD); 195 196 rv = meta_handle2session(hSession, &session); 197 if (rv != CKR_OK) 198 return (rv); 199 200 rv = meta_handle2object(hUnwrappingKey, &unwrappingKey); 201 if (rv != CKR_OK) { 202 REFRELEASE(session); 203 return (rv); 204 } 205 206 rv = meta_object_alloc(session, &outputKey); 207 if (rv != CKR_OK) 208 goto finish; 209 210 (void) get_template_boolean(CKA_TOKEN, pTemplate, ulAttributeCount, 211 &(outputKey->isToken)); 212 213 rv = meta_unwrap_key(session, pMechanism, unwrappingKey, 214 pWrappedKey, ulWrappedKeyLen, 215 pTemplate, ulAttributeCount, outputKey); 216 if (rv != CKR_OK) 217 goto finish; 218 219 meta_object_activate(outputKey); 220 221 *phKey = (CK_OBJECT_HANDLE) outputKey; 222 223 finish: 224 if (rv != CKR_OK) { 225 if (outputKey) 226 (void) meta_object_dealloc(session, outputKey, B_TRUE); 227 } 228 229 OBJRELEASE(unwrappingKey); 230 REFRELEASE(session); 231 232 return (rv); 233 } 234 235 236 /* 237 * meta_DeriveKey 238 * 239 * This function is a bit gross because of PKCS#11 kludges that pass extra 240 * object handles in some mechanism parameters. It probably needs to be 241 * broken up into more managable pieces. 242 */ 243 CK_RV 244 meta_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 245 CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, 246 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) 247 { 248 CK_RV rv; 249 CK_MECHANISM *pMech = pMechanism; 250 meta_session_t *session; 251 meta_object_t *basekey1 = NULL, *basekey2 = NULL; 252 meta_object_t *newKey1 = NULL, *newKey2 = NULL, *newKey3 = NULL, 253 *newKey4 = NULL; 254 boolean_t ssl_keys = B_FALSE; 255 boolean_t tlsprf = B_FALSE; 256 257 CK_MECHANISM metaMech; 258 CK_OBJECT_HANDLE *phBaseKey2 = NULL; 259 CK_X9_42_DH2_DERIVE_PARAMS x942_params, *x9_tmpptr; 260 CK_ECDH2_DERIVE_PARAMS ecdh_params, *ec_tmpptr; 261 CK_SSL3_KEY_MAT_OUT *ssl_key_mat; 262 CK_SSL3_KEY_MAT_PARAMS *keyparams; 263 264 if (pMech == NULL) { 265 return (CKR_ARGUMENTS_BAD); 266 } 267 268 /* 269 * Special case: Normally, the caller must always provide storage 270 * for the derived key handle at phKey. Two (related) mechanisms 271 * are special, in that multiple keys are instead returned via 272 * pMech->pParameter. In these cases the spec says (see 12.38.4 273 * and 12.39.4) that phKey should be a NULL pointer, as it is not used. 274 */ 275 switch (pMech->mechanism) { 276 case CKM_SSL3_KEY_AND_MAC_DERIVE: 277 case CKM_TLS_KEY_AND_MAC_DERIVE: 278 keyparams = (CK_SSL3_KEY_MAT_PARAMS*)pMech->pParameter; 279 280 if ((keyparams == NULL) || (pMech->ulParameterLen 281 != sizeof (CK_SSL3_KEY_MAT_PARAMS))) 282 return (CKR_ARGUMENTS_BAD); 283 284 ssl_key_mat = keyparams->pReturnedKeyMaterial; 285 if (ssl_key_mat == NULL) 286 return (CKR_ARGUMENTS_BAD); 287 288 ssl_keys = B_TRUE; 289 break; 290 291 case CKM_TLS_PRF: 292 tlsprf = B_TRUE; 293 break; 294 295 default: 296 if (phKey == NULL) 297 return (CKR_ARGUMENTS_BAD); 298 }; 299 300 rv = meta_handle2session(hSession, &session); 301 if (rv != CKR_OK) 302 return (rv); 303 304 rv = meta_handle2object(hBaseKey, &basekey1); 305 if (rv != CKR_OK) 306 goto finish; 307 308 309 /* 310 * A few oddball mechanisms pass a 2nd object handle in the parameters. 311 * Here we validate that handle, and create a duplicate copy of the 312 * mechanism and parameters. This is done because the application 313 * does not expect these values to be changing, and could be using the 314 * same data in multiple threads (eg concurrent calls to C_DeriveKey). 315 * We copy the data to make sure there are no MT-Safe problems. 316 */ 317 switch (pMech->mechanism) { 318 319 case CKM_ECMQV_DERIVE: 320 /* uses CK_ECDH2_DERIVE_PARAMS struct as the parameter */ 321 322 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen 323 != sizeof (CK_ECDH2_DERIVE_PARAMS))) { 324 rv = CKR_ARGUMENTS_BAD; 325 goto finish; 326 } 327 328 /* Duplicate the mechanism and paramaters */ 329 ec_tmpptr = (CK_ECDH2_DERIVE_PARAMS *)pMech->pParameter; 330 ecdh_params = *ec_tmpptr; 331 metaMech = *pMech; 332 metaMech.pParameter = &ecdh_params; 333 pMech = &metaMech; 334 335 /* Get the key the application is providing */ 336 phBaseKey2 = &ecdh_params.hPrivateData; 337 break; 338 339 case CKM_X9_42_DH_HYBRID_DERIVE: 340 case CKM_X9_42_MQV_DERIVE: 341 /* both use CK_X9_42_DH2_DERIVE_PARAMS as the parameter */ 342 343 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen 344 != sizeof (CK_X9_42_DH2_DERIVE_PARAMS))) { 345 rv = CKR_ARGUMENTS_BAD; 346 goto finish; 347 } 348 349 /* Duplicate the mechanism and paramaters */ 350 x9_tmpptr = (CK_X9_42_DH2_DERIVE_PARAMS *)pMech->pParameter; 351 x942_params = *x9_tmpptr; 352 metaMech = *pMech; 353 metaMech.pParameter = &x942_params; 354 pMech = &metaMech; 355 356 /* Get the key the application is providing */ 357 phBaseKey2 = &x942_params.hPrivateData; 358 break; 359 360 case CKM_CONCATENATE_BASE_AND_KEY: 361 /* uses a CK_OBJECT_HANDLE as the parameter */ 362 363 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen 364 != sizeof (CK_OBJECT_HANDLE))) { 365 rv = CKR_ARGUMENTS_BAD; 366 goto finish; 367 } 368 369 /* Duplicate the mechanism and paramaters */ 370 metaMech = *pMech; 371 pMech = &metaMech; 372 373 /* Get the key the application is providing */ 374 phBaseKey2 = (CK_OBJECT_HANDLE *) &metaMech.pParameter; 375 break; 376 377 default: 378 /* nothing special to do. */ 379 break; 380 } 381 382 if (phBaseKey2) { 383 rv = meta_handle2object(*phBaseKey2, &basekey2); 384 if (rv != CKR_OK) 385 goto finish; 386 } 387 388 /* 389 * Allocate meta objects to store the derived key(s). Normally just 390 * a single key is created, but the SSL/TLS mechanisms generate four. 391 */ 392 rv = meta_object_alloc(session, &newKey1); 393 if (rv != CKR_OK) 394 goto finish; 395 396 if (ssl_keys) { 397 rv = meta_object_alloc(session, &newKey2); 398 if (rv != CKR_OK) 399 goto finish; 400 rv = meta_object_alloc(session, &newKey3); 401 if (rv != CKR_OK) 402 goto finish; 403 rv = meta_object_alloc(session, &newKey4); 404 if (rv != CKR_OK) 405 goto finish; 406 } 407 408 409 /* Perform the actual key derive operation. */ 410 rv = meta_derive_key(session, pMech, basekey1, basekey2, phBaseKey2, 411 pTemplate, ulAttributeCount, newKey1, newKey2, newKey3, newKey4); 412 if (rv != CKR_OK) 413 goto finish; 414 415 if (tlsprf) { 416 (void) meta_object_dealloc(session, newKey1, B_TRUE); 417 newKey1 = NULL; 418 /* phKey isn't used (is NULL) for mechanism CKM_TLS_PRF. */ 419 420 } else { 421 /* Make derived key(s) active and visible to other threads. */ 422 meta_object_activate(newKey1); 423 if (ssl_keys) { 424 meta_object_activate(newKey2); 425 meta_object_activate(newKey3); 426 meta_object_activate(newKey4); 427 428 ssl_key_mat->hClientMacSecret 429 = (CK_OBJECT_HANDLE) newKey1; 430 ssl_key_mat->hServerMacSecret 431 = (CK_OBJECT_HANDLE) newKey2; 432 ssl_key_mat->hClientKey = (CK_OBJECT_HANDLE) newKey3; 433 ssl_key_mat->hServerKey = (CK_OBJECT_HANDLE) newKey4; 434 /* phKey isn't used (is NULL) for these SSL/TLS mechs */ 435 436 } else { 437 *phKey = (CK_OBJECT_HANDLE) newKey1; 438 } 439 } 440 441 finish: 442 if (rv != CKR_OK) { 443 if (newKey1) 444 (void) meta_object_dealloc(session, newKey1, B_TRUE); 445 if (newKey2) 446 (void) meta_object_dealloc(session, newKey2, B_TRUE); 447 if (newKey3) 448 (void) meta_object_dealloc(session, newKey3, B_TRUE); 449 if (newKey4) 450 (void) meta_object_dealloc(session, newKey4, B_TRUE); 451 } 452 453 if (basekey1) 454 OBJRELEASE(basekey1); 455 if (basekey2) 456 OBJRELEASE(basekey2); 457 REFRELEASE(session); 458 459 return (rv); 460 } 461