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 2005 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 boolean_t tlsprf = B_FALSE; 260 261 CK_MECHANISM metaMech; 262 CK_OBJECT_HANDLE *phBaseKey2 = NULL; 263 CK_X9_42_DH2_DERIVE_PARAMS x942_params, *x9_tmpptr; 264 CK_ECDH2_DERIVE_PARAMS ecdh_params, *ec_tmpptr; 265 CK_SSL3_KEY_MAT_OUT *ssl_key_mat; 266 CK_SSL3_KEY_MAT_PARAMS *keyparams; 267 268 if (pMech == NULL) { 269 return (CKR_ARGUMENTS_BAD); 270 } 271 272 /* 273 * Special case: Normally, the caller must always provide storage 274 * for the derived key handle at phKey. Two (related) mechanisms 275 * are special, in that multiple keys are instead returned via 276 * pMech->pParameter. In these cases the spec says (see 12.38.4 277 * and 12.39.4) that phKey should be a NULL pointer, as it is not used. 278 */ 279 switch (pMech->mechanism) { 280 case CKM_SSL3_KEY_AND_MAC_DERIVE: 281 case CKM_TLS_KEY_AND_MAC_DERIVE: 282 keyparams = (CK_SSL3_KEY_MAT_PARAMS*)pMech->pParameter; 283 284 if ((keyparams == NULL) || (pMech->ulParameterLen 285 != sizeof (CK_SSL3_KEY_MAT_PARAMS))) 286 return (CKR_ARGUMENTS_BAD); 287 288 ssl_key_mat = keyparams->pReturnedKeyMaterial; 289 if (ssl_key_mat == NULL) 290 return (CKR_ARGUMENTS_BAD); 291 292 ssl_keys = B_TRUE; 293 break; 294 295 case CKM_TLS_PRF: 296 tlsprf = B_TRUE; 297 break; 298 299 default: 300 if (phKey == NULL) 301 return (CKR_ARGUMENTS_BAD); 302 }; 303 304 rv = meta_handle2session(hSession, &session); 305 if (rv != CKR_OK) 306 return (rv); 307 308 rv = meta_handle2object(hBaseKey, &basekey1); 309 if (rv != CKR_OK) 310 goto finish; 311 312 313 /* 314 * A few oddball mechanisms pass a 2nd object handle in the parameters. 315 * Here we validate that handle, and create a duplicate copy of the 316 * mechanism and parameters. This is done because the application 317 * does not expect these values to be changing, and could be using the 318 * same data in multiple threads (eg concurrent calls to C_DeriveKey). 319 * We copy the data to make sure there are no MT-Safe problems. 320 */ 321 switch (pMech->mechanism) { 322 323 case CKM_ECMQV_DERIVE: 324 /* uses CK_ECDH2_DERIVE_PARAMS struct as the parameter */ 325 326 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen 327 != sizeof (CK_ECDH2_DERIVE_PARAMS))) { 328 rv = CKR_ARGUMENTS_BAD; 329 goto finish; 330 } 331 332 /* Duplicate the mechanism and paramaters */ 333 ec_tmpptr = (CK_ECDH2_DERIVE_PARAMS *)pMech->pParameter; 334 ecdh_params = *ec_tmpptr; 335 metaMech = *pMech; 336 metaMech.pParameter = &ecdh_params; 337 pMech = &metaMech; 338 339 /* Get the key the application is providing */ 340 phBaseKey2 = &ecdh_params.hPrivateData; 341 break; 342 343 case CKM_X9_42_DH_HYBRID_DERIVE: 344 case CKM_X9_42_MQV_DERIVE: 345 /* both use CK_X9_42_DH2_DERIVE_PARAMS as the parameter */ 346 347 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen 348 != sizeof (CK_X9_42_DH2_DERIVE_PARAMS))) { 349 rv = CKR_ARGUMENTS_BAD; 350 goto finish; 351 } 352 353 /* Duplicate the mechanism and paramaters */ 354 x9_tmpptr = (CK_X9_42_DH2_DERIVE_PARAMS *)pMech->pParameter; 355 x942_params = *x9_tmpptr; 356 metaMech = *pMech; 357 metaMech.pParameter = &x942_params; 358 pMech = &metaMech; 359 360 /* Get the key the application is providing */ 361 phBaseKey2 = &x942_params.hPrivateData; 362 break; 363 364 case CKM_CONCATENATE_BASE_AND_KEY: 365 /* uses a CK_OBJECT_HANDLE as the parameter */ 366 367 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen 368 != sizeof (CK_OBJECT_HANDLE))) { 369 rv = CKR_ARGUMENTS_BAD; 370 goto finish; 371 } 372 373 /* Duplicate the mechanism and paramaters */ 374 metaMech = *pMech; 375 pMech = &metaMech; 376 377 /* Get the key the application is providing */ 378 phBaseKey2 = (CK_OBJECT_HANDLE *) &metaMech.pParameter; 379 break; 380 381 default: 382 /* nothing special to do. */ 383 break; 384 } 385 386 if (phBaseKey2) { 387 rv = meta_handle2object(*phBaseKey2, &basekey2); 388 if (rv != CKR_OK) 389 goto finish; 390 } 391 392 /* 393 * Allocate meta objects to store the derived key(s). Normally just 394 * a single key is created, but the SSL/TLS mechanisms generate four. 395 */ 396 rv = meta_object_alloc(session, &newKey1); 397 if (rv != CKR_OK) 398 goto finish; 399 400 if (ssl_keys) { 401 rv = meta_object_alloc(session, &newKey2); 402 if (rv != CKR_OK) 403 goto finish; 404 rv = meta_object_alloc(session, &newKey3); 405 if (rv != CKR_OK) 406 goto finish; 407 rv = meta_object_alloc(session, &newKey4); 408 if (rv != CKR_OK) 409 goto finish; 410 } 411 412 413 /* Perform the actual key derive operation. */ 414 rv = meta_derive_key(session, pMech, basekey1, basekey2, phBaseKey2, 415 pTemplate, ulAttributeCount, 416 newKey1, newKey2, newKey3, newKey4); 417 if (rv != CKR_OK) 418 goto finish; 419 420 /* Make the derived key(s) active and visible to other threads. */ 421 meta_object_activate(newKey1); 422 if (ssl_keys) { 423 meta_object_activate(newKey2); 424 meta_object_activate(newKey3); 425 meta_object_activate(newKey4); 426 427 ssl_key_mat->hClientMacSecret = (CK_OBJECT_HANDLE) newKey1; 428 ssl_key_mat->hServerMacSecret = (CK_OBJECT_HANDLE) newKey2; 429 ssl_key_mat->hClientKey = (CK_OBJECT_HANDLE) newKey3; 430 ssl_key_mat->hServerKey = (CK_OBJECT_HANDLE) newKey4; 431 /* phKey is not used (it's NULL) for these SSL/TLS mechs. */ 432 433 } else if (!tlsprf) { 434 *phKey = (CK_OBJECT_HANDLE) newKey1; 435 } 436 437 finish: 438 if (rv != CKR_OK) { 439 if (newKey1) 440 (void) meta_object_dealloc(newKey1, B_TRUE); 441 if (newKey2) 442 (void) meta_object_dealloc(newKey2, B_TRUE); 443 if (newKey3) 444 (void) meta_object_dealloc(newKey3, B_TRUE); 445 if (newKey4) 446 (void) meta_object_dealloc(newKey4, B_TRUE); 447 } 448 449 if (basekey1) 450 OBJRELEASE(basekey1); 451 if (basekey2) 452 OBJRELEASE(basekey2); 453 REFRELEASE(session); 454 455 return (rv); 456 } 457