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 22 /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */ 23 /* 24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #include "tpmtok_int.h" 29 30 static CK_SLOT_INFO slot_info; 31 32 // Function: dlist_add_as_first() 33 // 34 // Adds the specified node to the start of the list 35 // 36 // Returns: pointer to the start of the list 37 // 38 DL_NODE * 39 dlist_add_as_first(DL_NODE *list, void *data) 40 { 41 DL_NODE *node = NULL; 42 43 if (! data) 44 return (list); 45 node = (DL_NODE *)malloc(sizeof (DL_NODE)); 46 if (! node) 47 return (NULL); 48 node->data = data; 49 node->prev = NULL; 50 node->next = list; 51 if (list) 52 list->prev = node; 53 54 return (node); 55 } 56 57 58 // Function: dlist_add_as_last() 59 // 60 // Adds the specified node to the end of the list 61 // 62 // Returns: pointer to the start of the list 63 // 64 DL_NODE * 65 dlist_add_as_last(DL_NODE *list, void *data) { 66 DL_NODE *node = NULL; 67 68 if (! data) 69 return (list); 70 node = (DL_NODE *)malloc(sizeof (DL_NODE)); 71 if (! node) 72 return (NULL); 73 node->data = data; 74 node->next = NULL; 75 76 if (! list) { 77 node->prev = NULL; 78 return (node); 79 } else { 80 DL_NODE *temp = dlist_get_last(list); 81 temp->next = node; 82 node->prev = temp; 83 84 return (list); 85 } 86 } 87 88 89 // Function: dlist_find() 90 // 91 DL_NODE * 92 dlist_find(DL_NODE *list, void *data) 93 { 94 DL_NODE *node = list; 95 96 while (node && node->data != data) 97 node = node->next; 98 99 return (node); 100 } 101 102 103 // Function: dlist_get_first() 104 // 105 // Returns the last node in the list or NULL if list is empty 106 // 107 DL_NODE * 108 dlist_get_first(DL_NODE *list) { 109 DL_NODE *temp = list; 110 111 if (! list) 112 return (NULL); 113 while (temp->prev != NULL) 114 temp = temp->prev; 115 116 return (temp); 117 } 118 119 120 // Function: dlist_get_last() 121 // 122 // Returns the last node in the list or NULL if list is empty 123 // 124 DL_NODE * 125 dlist_get_last(DL_NODE *list) { 126 DL_NODE *temp = list; 127 128 if (! list) 129 return (NULL); 130 while (temp->next != NULL) 131 temp = temp->next; 132 133 return (temp); 134 } 135 136 137 // 138 // 139 CK_ULONG 140 dlist_length(DL_NODE *list) { 141 DL_NODE *temp = list; 142 CK_ULONG len = 0; 143 144 while (temp) { 145 len++; 146 temp = temp->next; 147 } 148 149 return (len); 150 } 151 152 153 // 154 // 155 DL_NODE * 156 dlist_next(DL_NODE *node) 157 { 158 if (! node) 159 return (NULL); 160 return (node->next); 161 } 162 163 164 // 165 // 166 DL_NODE * 167 dlist_prev(DL_NODE *node) { 168 if (! node) 169 return (NULL); 170 return (node->prev); 171 } 172 173 174 // 175 // 176 void 177 dlist_purge(DL_NODE *list) { 178 DL_NODE *node; 179 180 if (! list) 181 return; 182 do { 183 node = list->next; 184 free(list); 185 list = node; 186 } while (list); 187 } 188 189 // Function: dlist_remove_node() 190 // 191 // Attempts to remove the specified node from the list. The caller is 192 // responsible for freeing the data associated with the node prior to 193 // calling this routine 194 // 195 DL_NODE * 196 dlist_remove_node(DL_NODE *list, DL_NODE *node) { 197 DL_NODE *temp = list; 198 199 if (! list || ! node) 200 return (NULL); 201 // special case: removing head of the list 202 // 203 if (list == node) { 204 temp = list->next; 205 if (temp) 206 temp->prev = NULL; 207 208 free(list); 209 return (temp); 210 } 211 212 // we have no guarantee that the node is in the list 213 // so search through the list to find it 214 // 215 while ((temp != NULL) && (temp->next != node)) 216 temp = temp->next; 217 218 if (temp != NULL) { 219 DL_NODE *next = node->next; 220 221 temp->next = next; 222 if (next) 223 next->prev = temp; 224 225 free(node); 226 } 227 228 return (list); 229 } 230 231 extern void set_perm(int); 232 233 void 234 CreateXProcLock(void *xproc) 235 { 236 pthread_mutexattr_t mtxattr; 237 238 (void) pthread_mutexattr_init(&mtxattr); 239 (void) pthread_mutexattr_setpshared(&mtxattr, PTHREAD_PROCESS_SHARED); 240 (void) pthread_mutex_init((pthread_mutex_t *)xproc, &mtxattr); 241 } 242 243 int 244 DestroyXProcLock(void *xproc) 245 { 246 return (pthread_mutex_destroy((pthread_mutex_t *)xproc)); 247 } 248 249 int 250 XProcLock(void *xproc) 251 { 252 return (pthread_mutex_lock((pthread_mutex_t *)xproc)); 253 } 254 255 int 256 XProcUnLock(void *xproc) 257 { 258 return (pthread_mutex_unlock((pthread_mutex_t *)xproc)); 259 } 260 261 // 262 // 263 // is_attribute_defined() 264 // 265 // determine whether the specified attribute is defined by Cryptoki 266 // 267 CK_BBOOL 268 is_attribute_defined(CK_ATTRIBUTE_TYPE type) 269 { 270 if (type >= CKA_VENDOR_DEFINED) 271 return (TRUE); 272 switch (type) { 273 case CKA_CLASS: 274 case CKA_TOKEN: 275 case CKA_PRIVATE: 276 case CKA_LABEL: 277 case CKA_APPLICATION: 278 case CKA_VALUE: 279 case CKA_CERTIFICATE_TYPE: 280 case CKA_ISSUER: 281 case CKA_SERIAL_NUMBER: 282 case CKA_KEY_TYPE: 283 case CKA_SUBJECT: 284 case CKA_ID: 285 case CKA_SENSITIVE: 286 case CKA_ENCRYPT: 287 case CKA_DECRYPT: 288 case CKA_WRAP: 289 case CKA_UNWRAP: 290 case CKA_SIGN: 291 case CKA_SIGN_RECOVER: 292 case CKA_VERIFY: 293 case CKA_VERIFY_RECOVER: 294 case CKA_DERIVE: 295 case CKA_START_DATE: 296 case CKA_END_DATE: 297 case CKA_MODULUS: 298 case CKA_MODULUS_BITS: 299 case CKA_PUBLIC_EXPONENT: 300 case CKA_PRIVATE_EXPONENT: 301 case CKA_PRIME_1: 302 case CKA_PRIME_2: 303 case CKA_EXPONENT_1: 304 case CKA_EXPONENT_2: 305 case CKA_COEFFICIENT: 306 case CKA_PRIME: 307 case CKA_SUBPRIME: 308 case CKA_BASE: 309 case CKA_VALUE_BITS: 310 case CKA_VALUE_LEN: 311 case CKA_EXTRACTABLE: 312 case CKA_LOCAL: 313 case CKA_NEVER_EXTRACTABLE: 314 case CKA_ALWAYS_SENSITIVE: 315 case CKA_MODIFIABLE: 316 case CKA_ECDSA_PARAMS: 317 case CKA_EC_POINT: 318 case CKA_HW_FEATURE_TYPE: 319 case CKA_HAS_RESET: 320 case CKA_RESET_ON_INIT: 321 case CKA_KEY_GEN_MECHANISM: 322 case CKA_PRIME_BITS: 323 case CKA_SUBPRIME_BITS: 324 case CKA_OBJECT_ID: 325 case CKA_AC_ISSUER: 326 case CKA_OWNER: 327 case CKA_ATTR_TYPES: 328 case CKA_TRUSTED: 329 return (TRUE); 330 } 331 332 return (FALSE); 333 } 334 335 void 336 init_slot_info(TOKEN_DATA *td) 337 { 338 /* 339 * Much of the token info is pulled from the TPM itself when 340 * C_Initialize is called. 341 */ 342 (void) (void) memset(&slot_info.slotDescription, ' ', 343 sizeof (slot_info.slotDescription) - 1); 344 (void) (void) memset(&slot_info.manufacturerID, ' ', 345 sizeof (slot_info.manufacturerID) - 1); 346 347 (void) (void) memcpy(&slot_info.slotDescription, 348 "PKCS#11 Interface for TPM", 349 strlen("PKCS#11 Interface for TPM")); 350 351 (void) (void) memcpy(&slot_info.manufacturerID, 352 td->token_info.manufacturerID, 353 strlen((char *)td->token_info.manufacturerID)); 354 355 slot_info.hardwareVersion = nv_token_data->token_info.hardwareVersion; 356 slot_info.firmwareVersion = nv_token_data->token_info.firmwareVersion; 357 slot_info.flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT; 358 } 359 360 /*ARGSUSED*/ 361 void 362 copy_slot_info(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR sinfo) 363 { 364 if (sinfo != NULL) 365 (void) memcpy(sinfo, &slot_info, sizeof (slot_info)); 366 } 367 368 static void 369 init_token_info(TOKEN_DATA *td) 370 { 371 CK_TOKEN_INFO *token_info = NULL; 372 373 token_info = &td->token_info; 374 375 (void) memset(token_info->model, ' ', 376 sizeof (token_info->model)); 377 (void) memset(token_info->serialNumber, ' ', 378 sizeof (token_info->serialNumber)); 379 380 // 381 // I don't see any API support for changing the clock so 382 // we will use the system clock for the token's clock. 383 // 384 token_info->flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_CLOCK_ON_TOKEN | 385 CKF_SO_PIN_TO_BE_CHANGED; 386 387 if (memcmp(td->user_pin_sha, "00000000000000000000", 388 SHA1_DIGEST_LENGTH) != 0) 389 token_info->flags |= CKF_USER_PIN_INITIALIZED; 390 else 391 token_info->flags |= CKF_USER_PIN_TO_BE_CHANGED; 392 393 // For the release, we made these 394 // values as CK_UNAVAILABLE_INFORMATION 395 // 396 token_info->ulMaxSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; 397 token_info->ulSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; 398 token_info->ulMaxRwSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; 399 token_info->ulRwSessionCount = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; 400 token_info->ulMaxPinLen = MAX_PIN_LEN; 401 token_info->ulMinPinLen = MIN_PIN_LEN; 402 token_info->ulTotalPublicMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; 403 token_info->ulFreePublicMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; 404 token_info->ulTotalPrivateMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; 405 token_info->ulFreePrivateMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION; 406 407 (void) memset(token_info->utcTime, ' ', sizeof (token_info->utcTime)); 408 } 409 410 CK_RV 411 init_token_data(TSS_HCONTEXT hContext, TOKEN_DATA *td) { 412 CK_RV rc; 413 414 (void) memset((char *)td, 0, sizeof (nv_token_data)); 415 // 416 // the normal USER pin is not set when the token is initialized 417 // 418 (void) memcpy(td->user_pin_sha, "00000000000000000000", 419 SHA1_DIGEST_LENGTH); 420 (void) memcpy(td->so_pin_sha, default_so_pin_sha, 421 SHA1_DIGEST_LENGTH); 422 423 (void) memset(user_pin_md5, 0x0, MD5_DIGEST_LENGTH); 424 (void) memcpy(so_pin_md5, default_so_pin_md5, MD5_DIGEST_LENGTH); 425 426 (void) memcpy(td->next_token_object_name, "00000000", 8); 427 428 td->tweak_vector.allow_key_mods = TRUE; 429 430 init_token_info(td); 431 432 rc = token_get_tpm_info(hContext, td); 433 if (rc != CKR_OK) 434 return (rc); 435 436 rc = save_token_data(td); 437 438 return (rc); 439 } 440 441 // Function: compute_next_token_obj_name() 442 // 443 // Given a token object name (8 bytes in the range [0 - 9A - Z]) 444 // increment by one adjusting as necessary 445 // 446 // This gives us a namespace of 36^8 = 2, 821, 109, 907, 456 447 // objects before wrapping around. 448 // 449 CK_RV 450 compute_next_token_obj_name(CK_BYTE *current, CK_BYTE *next) { 451 int val[8]; 452 int i; 453 454 if (! current || ! next) { 455 return (CKR_FUNCTION_FAILED); 456 } 457 // Convert to integral base 36 458 // 459 for (i = 0; i < 8; i++) { 460 if (current[i] >= '0' && current[i] <= '9') 461 val[i] = current[i] - '0'; 462 463 if (current[i] >= 'A' && current[i] <= 'Z') 464 val[i] = current[i] - 'A' + 10; 465 } 466 467 val[0]++; 468 469 i = 0; 470 471 while (val[i] > 35) { 472 val[i] = 0; 473 474 if (i + 1 < 8) { 475 val[i + 1]++; 476 i++; 477 } else { 478 val[0]++; 479 i = 0; // start pass 2 480 } 481 } 482 483 // now, convert back to [0 - 9A - Z] 484 // 485 for (i = 0; i < 8; i++) { 486 if (val[i] < 10) 487 next[i] = '0' + val[i]; 488 else 489 next[i] = 'A' + val[i] - 10; 490 } 491 492 return (CKR_OK); 493 } 494 495 496 // 497 // 498 CK_RV 499 build_attribute(CK_ATTRIBUTE_TYPE type, 500 CK_BYTE *data, 501 CK_ULONG data_len, 502 CK_ATTRIBUTE **attrib) { 503 CK_ATTRIBUTE *attr = NULL; 504 505 attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + data_len); 506 if (! attr) { 507 return (CKR_DEVICE_MEMORY); 508 } 509 attr->type = type; 510 attr->ulValueLen = data_len; 511 512 if (data_len > 0) { 513 attr->pValue = (CK_BYTE *)attr + sizeof (CK_ATTRIBUTE); 514 (void) memcpy(attr->pValue, data, data_len); 515 } 516 else 517 attr->pValue = NULL; 518 519 *attrib = attr; 520 521 return (CKR_OK); 522 } 523 524 525 // 526 // 527 CK_RV 528 add_pkcs_padding(CK_BYTE * ptr, 529 CK_ULONG block_size, 530 CK_ULONG data_len, 531 CK_ULONG total_len) 532 { 533 CK_ULONG i, pad_len; 534 CK_BYTE pad_value; 535 536 pad_len = block_size - (data_len % block_size); 537 pad_value = (CK_BYTE)pad_len; 538 539 if (data_len + pad_len > total_len) { 540 return (CKR_FUNCTION_FAILED); 541 } 542 for (i = 0; i < pad_len; i++) 543 ptr[i] = pad_value; 544 545 return (CKR_OK); 546 } 547 548 549 // 550 // 551 CK_RV 552 strip_pkcs_padding(CK_BYTE * ptr, 553 CK_ULONG total_len, 554 CK_ULONG * data_len) { 555 CK_BYTE pad_value; 556 557 pad_value = ptr[total_len - 1]; 558 559 // thus, we have 'pad_value' bytes of 'pad_value' appended to the end 560 // 561 *data_len = total_len - pad_value; 562 563 return (CKR_OK); 564 } 565 566 567 // 568 // 569 CK_RV 570 remove_leading_zeros(CK_ATTRIBUTE *attr) 571 { 572 CK_BYTE *ptr = NULL; 573 CK_ULONG new_len, i; 574 575 ptr = attr->pValue; 576 577 for (i = 0; i < attr->ulValueLen; i++) { 578 if (ptr[i] != 0x0) 579 break; 580 } 581 582 new_len = attr->ulValueLen - i; 583 584 (void) memcpy(ptr, ptr + i, new_len); 585 attr->ulValueLen = new_len; 586 587 return (CKR_OK); 588 } 589 590 CK_RV 591 parity_is_odd(CK_BYTE b) { 592 b = ((b >> 4) ^ b) & 0x0f; 593 b = ((b >> 2) ^ b) & 0x03; 594 b = ((b >> 1) ^ b) & 0x01; 595 596 if (b == 1) 597 return (TRUE); 598 else 599 return (FALSE); 600 } 601 602 CK_RV 603 attach_shm() { 604 if (global_shm != NULL) 605 return (CKR_OK); 606 607 global_shm = (LW_SHM_TYPE *)malloc(sizeof (LW_SHM_TYPE)); 608 if (global_shm == NULL) { 609 return (CKR_HOST_MEMORY); 610 } 611 CreateXProcLock(&global_shm->mutex); 612 613 xproclock = (void *)&global_shm->mutex; 614 (void) XProcLock(xproclock); 615 616 global_shm->num_publ_tok_obj = 0; 617 global_shm->num_priv_tok_obj = 0; 618 619 (void) memset(&global_shm->publ_tok_objs, 0x0, 620 2048 * sizeof (TOK_OBJ_ENTRY)); 621 (void) memset(&global_shm->priv_tok_objs, 0x0, 622 2048 * sizeof (TOK_OBJ_ENTRY)); 623 624 (void) XProcUnLock(xproclock); 625 626 return (CKR_OK); 627 } 628 629 CK_RV 630 detach_shm() 631 { 632 if (global_shm != NULL) { 633 free(global_shm); 634 global_shm = NULL; 635 } 636 637 return (CKR_OK); 638 } 639 640 CK_RV 641 compute_sha(CK_BYTE *data, 642 CK_ULONG len, 643 CK_BYTE * hash) 644 { 645 SHA1_CTX ctx; 646 647 SHA1Init(&ctx); 648 649 SHA1Update(&ctx, data, len); 650 651 SHA1Final(hash, &ctx); 652 return (CKR_OK); 653 } 654