1 /* 2 * The Initial Developer of the Original Code is International 3 * Business Machines Corporation. Portions created by IBM 4 * Corporation are Copyright (C) 2005 International Business 5 * Machines Corporation. All Rights Reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the Common Public License as published by 9 * IBM Corporation; either version 1 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * Common Public License for more details. 16 * 17 * You should have received a copy of the Common Public License 18 * along with this program; if not, a copy can be viewed at 19 * http://www.opensource.org/licenses/cpl1.0.php. 20 */ 21 /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include "tpmtok_int.h" 28 29 static CK_BBOOL true = TRUE, false = FALSE; 30 31 static CK_RV 32 key_mgr_get_private_key_type( 33 CK_BYTE *keydata, 34 CK_ULONG keylen, 35 CK_KEY_TYPE *keytype) 36 { 37 CK_BYTE *alg = NULL; 38 CK_BYTE *priv_key = NULL; 39 CK_ULONG alg_len; 40 CK_RV rc; 41 42 rc = ber_decode_PrivateKeyInfo(keydata, keylen, &alg, 43 &alg_len, &priv_key); 44 if (rc != CKR_OK) { 45 return (rc); 46 } 47 if (alg_len >= ber_rsaEncryptionLen) { 48 if (memcmp(alg, ber_rsaEncryption, 49 ber_rsaEncryptionLen) == 0) { 50 *keytype = CKK_RSA; 51 return (CKR_OK); 52 } 53 } 54 55 return (CKR_TEMPLATE_INCOMPLETE); 56 } 57 58 CK_RV 59 key_mgr_generate_key_pair(SESSION * sess, 60 CK_MECHANISM * mech, 61 CK_ATTRIBUTE * publ_tmpl, 62 CK_ULONG publ_count, 63 CK_ATTRIBUTE * priv_tmpl, 64 CK_ULONG priv_count, 65 CK_OBJECT_HANDLE * publ_key_handle, 66 CK_OBJECT_HANDLE * priv_key_handle) 67 { 68 OBJECT * publ_key_obj = NULL; 69 OBJECT * priv_key_obj = NULL; 70 CK_ATTRIBUTE * attr = NULL; 71 CK_ATTRIBUTE * new_attr = NULL; 72 CK_ULONG i, keyclass, subclass = 0; 73 CK_BBOOL flag; 74 CK_RV rc; 75 76 if (! sess || ! mech || ! publ_key_handle || ! priv_key_handle) { 77 return (CKR_FUNCTION_FAILED); 78 } 79 if (! publ_tmpl && (publ_count != 0)) { 80 return (CKR_FUNCTION_FAILED); 81 } 82 if (! priv_tmpl && (priv_count != 0)) { 83 return (CKR_FUNCTION_FAILED); 84 } 85 86 for (i = 0; i < publ_count; i++) { 87 if (publ_tmpl[i].type == CKA_CLASS) { 88 keyclass = *(CK_OBJECT_CLASS *)publ_tmpl[i].pValue; 89 if (keyclass != CKO_PUBLIC_KEY) { 90 return (CKR_TEMPLATE_INCONSISTENT); 91 } 92 } 93 94 if (publ_tmpl[i].type == CKA_KEY_TYPE) 95 subclass = *(CK_ULONG *)publ_tmpl[i].pValue; 96 } 97 98 99 for (i = 0; i < priv_count; i++) { 100 if (priv_tmpl[i].type == CKA_CLASS) { 101 keyclass = *(CK_OBJECT_CLASS *)priv_tmpl[i].pValue; 102 if (keyclass != CKO_PRIVATE_KEY) { 103 return (CKR_TEMPLATE_INCONSISTENT); 104 } 105 } 106 107 if (priv_tmpl[i].type == CKA_KEY_TYPE) { 108 CK_ULONG temp = *(CK_ULONG *)priv_tmpl[i].pValue; 109 if (temp != subclass) { 110 return (CKR_TEMPLATE_INCONSISTENT); 111 } 112 } 113 } 114 115 116 switch (mech->mechanism) { 117 case CKM_RSA_PKCS_KEY_PAIR_GEN: 118 if (subclass != 0 && subclass != CKK_RSA) { 119 return (CKR_TEMPLATE_INCONSISTENT); 120 } 121 122 subclass = CKK_RSA; 123 break; 124 125 default: 126 return (CKR_MECHANISM_INVALID); 127 } 128 129 130 rc = object_mgr_create_skel(sess, 131 publ_tmpl, publ_count, MODE_KEYGEN, 132 CKO_PUBLIC_KEY, subclass, &publ_key_obj); 133 134 if (rc != CKR_OK) { 135 goto error; 136 } 137 rc = object_mgr_create_skel(sess, 138 priv_tmpl, priv_count, MODE_KEYGEN, 139 CKO_PRIVATE_KEY, subclass, &priv_key_obj); 140 141 if (rc != CKR_OK) { 142 goto error; 143 } 144 145 switch (mech->mechanism) { 146 case CKM_RSA_PKCS_KEY_PAIR_GEN: 147 rc = ckm_rsa_key_pair_gen( 148 sess->hContext, 149 publ_key_obj->template, 150 priv_key_obj->template); 151 break; 152 153 default: 154 rc = CKR_MECHANISM_INVALID; 155 break; 156 } 157 158 if (rc != CKR_OK) { 159 goto error; 160 } 161 162 /* 163 * we can now set CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE 164 * to their appropriate values. this only applies to CKO_SECRET_KEY 165 * and CKO_PRIVATE_KEY objects 166 */ 167 flag = template_attribute_find(priv_key_obj->template, 168 CKA_SENSITIVE, &attr); 169 if (flag == TRUE) { 170 flag = *(CK_BBOOL *)attr->pValue; 171 172 rc = build_attribute(CKA_ALWAYS_SENSITIVE, &flag, 173 sizeof (CK_BBOOL), &new_attr); 174 if (rc != CKR_OK) { 175 goto error; 176 } 177 (void) template_update_attribute(priv_key_obj->template, 178 new_attr); 179 180 } else { 181 rc = CKR_FUNCTION_FAILED; 182 goto error; 183 } 184 185 186 flag = template_attribute_find(priv_key_obj->template, 187 CKA_EXTRACTABLE, &attr); 188 if (flag == TRUE) { 189 flag = *(CK_BBOOL *)attr->pValue; 190 191 rc = build_attribute(CKA_NEVER_EXTRACTABLE, &true, 192 sizeof (CK_BBOOL), &new_attr); 193 if (rc != CKR_OK) { 194 goto error; 195 } 196 if (flag == TRUE) 197 *(CK_BBOOL *)new_attr->pValue = false; 198 199 (void) template_update_attribute(priv_key_obj->template, 200 new_attr); 201 202 } else { 203 rc = CKR_FUNCTION_FAILED; 204 goto error; 205 } 206 207 rc = object_mgr_create_final(sess, publ_key_obj, publ_key_handle); 208 if (rc != CKR_OK) { 209 goto error; 210 } 211 rc = object_mgr_create_final(sess, priv_key_obj, priv_key_handle); 212 if (rc != CKR_OK) { 213 (void) object_mgr_destroy_object(sess, *publ_key_handle); 214 publ_key_obj = NULL; 215 goto error; 216 } 217 return (rc); 218 219 error: 220 if (publ_key_obj) 221 (void) object_free(publ_key_obj); 222 if (priv_key_obj) 223 (void) object_free(priv_key_obj); 224 225 *publ_key_handle = 0; 226 *priv_key_handle = 0; 227 228 return (rc); 229 } 230 231 CK_RV 232 key_mgr_wrap_key(SESSION * sess, 233 CK_BBOOL length_only, 234 CK_MECHANISM * mech, 235 CK_OBJECT_HANDLE h_wrapping_key, 236 CK_OBJECT_HANDLE h_key, 237 CK_BYTE * wrapped_key, 238 CK_ULONG * wrapped_key_len) { 239 ENCR_DECR_CONTEXT * ctx = NULL; 240 OBJECT * key1_obj = NULL; 241 OBJECT * key2_obj = NULL; 242 CK_ATTRIBUTE * attr = NULL; 243 CK_BYTE * data = NULL; 244 CK_ULONG data_len; 245 CK_OBJECT_CLASS class; 246 CK_KEY_TYPE keytype; 247 CK_BBOOL flag; 248 CK_RV rc; 249 250 if (! sess || ! wrapped_key_len) { 251 return (CKR_FUNCTION_FAILED); 252 } 253 254 rc = object_mgr_find_in_map1(sess->hContext, h_wrapping_key, &key1_obj); 255 if (rc != CKR_OK) { 256 return (CKR_WRAPPING_KEY_HANDLE_INVALID); 257 } 258 rc = object_mgr_find_in_map1(sess->hContext, h_key, &key2_obj); 259 if (rc != CKR_OK) { 260 return (CKR_KEY_HANDLE_INVALID); 261 } 262 263 rc = template_attribute_find(key2_obj->template, 264 CKA_EXTRACTABLE, &attr); 265 if (rc == FALSE) { 266 return (CKR_KEY_NOT_WRAPPABLE); 267 } else { 268 flag = *(CK_BBOOL *)attr->pValue; 269 if (flag == FALSE) { 270 return (CKR_KEY_NOT_WRAPPABLE); 271 } 272 } 273 274 rc = template_attribute_find(key2_obj->template, CKA_CLASS, &attr); 275 if (rc == FALSE) { 276 return (CKR_KEY_NOT_WRAPPABLE); 277 } else 278 class = *(CK_OBJECT_CLASS *)attr->pValue; 279 280 switch (mech->mechanism) { 281 case CKM_RSA_PKCS: 282 if (class != CKO_SECRET_KEY) { 283 return (CKR_KEY_NOT_WRAPPABLE); 284 } 285 break; 286 287 default: 288 return (CKR_KEY_NOT_WRAPPABLE); 289 } 290 291 rc = template_attribute_find(key2_obj->template, 292 CKA_KEY_TYPE, &attr); 293 if (rc == FALSE) 294 return (CKR_KEY_NOT_WRAPPABLE); 295 else 296 keytype = *(CK_KEY_TYPE *)attr->pValue; 297 298 switch (keytype) { 299 case CKK_RSA: 300 rc = rsa_priv_wrap_get_data(key2_obj->template, length_only, 301 &data, &data_len); 302 if (rc != CKR_OK) { 303 return (rc); 304 } 305 break; 306 307 case CKK_GENERIC_SECRET: 308 rc = generic_secret_wrap_get_data(key2_obj->template, 309 length_only, &data, &data_len); 310 if (rc != CKR_OK) { 311 return (rc); 312 } 313 break; 314 default: 315 return (CKR_KEY_NOT_WRAPPABLE); 316 } 317 318 switch (mech->mechanism) { 319 case CKM_RSA_PKCS: 320 break; 321 322 default: 323 return (CKR_KEY_NOT_WRAPPABLE); 324 } 325 326 ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof (ENCR_DECR_CONTEXT)); 327 if (! ctx) { 328 return (CKR_HOST_MEMORY); 329 } 330 (void) memset(ctx, 0x0, sizeof (ENCR_DECR_CONTEXT)); 331 332 rc = encr_mgr_init(sess, ctx, OP_WRAP, mech, h_wrapping_key); 333 if (rc != CKR_OK) { 334 return (rc); 335 } 336 rc = encr_mgr_encrypt(sess, length_only, 337 ctx, data, data_len, wrapped_key, wrapped_key_len); 338 339 if (data != NULL) { 340 free(data); 341 } 342 (void) encr_mgr_cleanup(ctx); 343 free(ctx); 344 345 return (rc); 346 } 347 348 CK_RV 349 key_mgr_unwrap_key(SESSION * sess, 350 CK_MECHANISM * mech, 351 CK_ATTRIBUTE * attributes, 352 CK_ULONG attrib_count, 353 CK_BYTE * wrapped_key, 354 CK_ULONG wrapped_key_len, 355 CK_OBJECT_HANDLE h_unwrapping_key, 356 CK_OBJECT_HANDLE * h_unwrapped_key) 357 { 358 ENCR_DECR_CONTEXT * ctx = NULL; 359 OBJECT * key_obj = NULL; 360 CK_BYTE * data = NULL; 361 CK_ULONG data_len; 362 CK_ULONG keyclass, keytype; 363 CK_ULONG i; 364 CK_BBOOL found_class, found_type, fromend; 365 CK_RV rc; 366 367 368 if (! sess || ! wrapped_key || ! h_unwrapped_key) { 369 return (CKR_FUNCTION_FAILED); 370 } 371 372 rc = object_mgr_find_in_map1(sess->hContext, h_unwrapping_key, 373 &key_obj); 374 if (rc != CKR_OK) { 375 return (CKR_WRAPPING_KEY_HANDLE_INVALID); 376 } 377 378 found_class = FALSE; 379 found_type = FALSE; 380 381 switch (mech->mechanism) { 382 case CKM_RSA_PKCS: 383 keyclass = CKO_SECRET_KEY; 384 found_class = TRUE; 385 break; 386 } 387 388 for (i = 0; i < attrib_count; i++) { 389 switch (attributes[i].type) { 390 case CKA_CLASS: 391 keyclass = *(CK_OBJECT_CLASS *)attributes[i].pValue; 392 found_class = TRUE; 393 break; 394 395 case CKA_KEY_TYPE: 396 keytype = *(CK_KEY_TYPE *)attributes[i].pValue; 397 found_type = TRUE; 398 break; 399 } 400 } 401 402 if (found_class == FALSE || (found_type == FALSE && keyclass != 403 CKO_PRIVATE_KEY)) { 404 return (CKR_TEMPLATE_INCOMPLETE); 405 } 406 407 switch (mech->mechanism) { 408 case CKM_RSA_PKCS: 409 if (keyclass != CKO_SECRET_KEY) { 410 return (CKR_TEMPLATE_INCONSISTENT); 411 } 412 break; 413 default: 414 return (CKR_MECHANISM_INVALID); 415 } 416 417 418 ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof (ENCR_DECR_CONTEXT)); 419 if (! ctx) { 420 return (CKR_HOST_MEMORY); 421 } 422 (void) memset(ctx, 0x0, sizeof (ENCR_DECR_CONTEXT)); 423 424 rc = decr_mgr_init(sess, ctx, OP_UNWRAP, mech, h_unwrapping_key); 425 if (rc != CKR_OK) 426 return (rc); 427 428 rc = decr_mgr_decrypt(sess, 429 TRUE, ctx, wrapped_key, wrapped_key_len, 430 data, &data_len); 431 if (rc != CKR_OK) { 432 goto error; 433 } 434 data = (CK_BYTE *)malloc(data_len); 435 if (! data) { 436 rc = CKR_HOST_MEMORY; 437 goto error; 438 } 439 440 rc = decr_mgr_decrypt(sess, 441 FALSE, ctx, wrapped_key, wrapped_key_len, 442 data, &data_len); 443 444 (void) decr_mgr_cleanup(ctx); 445 free(ctx); 446 447 if (rc != CKR_OK) { 448 goto error; 449 } 450 /* 451 * if we use X.509, the data will be padded from the front with zeros. 452 * PKCS #11 specifies that for this mechanism, CK_VALUE is to be read 453 * from the end of the data. 454 * 455 * Note: the PKCS #11 reference implementation gets this wrong. 456 */ 457 if (mech->mechanism == CKM_RSA_X_509) 458 fromend = TRUE; 459 else 460 fromend = FALSE; 461 462 if (keyclass == CKO_PRIVATE_KEY) { 463 rc = key_mgr_get_private_key_type(data, data_len, &keytype); 464 if (rc != CKR_OK) { 465 goto error; 466 } 467 } 468 469 rc = object_mgr_create_skel(sess, 470 attributes, attrib_count, 471 MODE_UNWRAP, keyclass, keytype, 472 &key_obj); 473 if (rc != CKR_OK) { 474 goto error; 475 } 476 switch (keyclass) { 477 case CKO_SECRET_KEY: 478 rc = secret_key_unwrap(key_obj->template, keytype, data, 479 data_len, fromend); 480 break; 481 482 case CKO_PRIVATE_KEY: 483 rc = priv_key_unwrap(key_obj->template, keytype, 484 data, data_len); 485 break; 486 487 default: 488 rc = CKR_WRAPPED_KEY_INVALID; 489 break; 490 } 491 492 if (rc != CKR_OK) { 493 goto error; 494 } 495 rc = object_mgr_create_final(sess, key_obj, h_unwrapped_key); 496 if (rc != CKR_OK) { 497 goto error; 498 } 499 if (data) free(data); 500 return (rc); 501 502 error: 503 if (key_obj) (void) object_free(key_obj); 504 if (data) free(data); 505 506 return (rc); 507 } 508