1 2 /* 3 * Licensed Materials - Property of IBM 4 * 5 * trousers - An open source TCG Software Stack 6 * 7 * (C) Copyright International Business Machines Corp. 2004-2006 8 * 9 */ 10 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 #include <errno.h> 17 #include <pwd.h> 18 #include <sys/types.h> 19 #include <sys/file.h> 20 #include <sys/stat.h> 21 #include <assert.h> 22 #include <fcntl.h> 23 #include <limits.h> 24 #include <netdb.h> 25 #if defined (HAVE_BYTEORDER_H) 26 #include <sys/byteorder.h> 27 #elif defined (HTOLE_DEFINED) 28 29 #ifndef __APPLE__ 30 #include <endian.h> 31 #else 32 #include "portable_endian.h" 33 #endif 34 35 #define LE_16 htole16 36 #define LE_32 htole32 37 #define LE_64 htole64 38 #else 39 #define LE_16(x) (x) 40 #define LE_32(x) (x) 41 #define LE_64(x) (x) 42 #endif 43 44 #include "trousers/tss.h" 45 #include "trousers/trousers.h" 46 #include "trousers_types.h" 47 #include "tcs_tsp.h" 48 #include "spi_utils.h" 49 #include "tspps.h" 50 #include "tsplog.h" 51 52 static int user_ps_fd = -1; 53 static MUTEX_DECLARE_INIT(user_ps_lock); 54 #if (defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__)) 55 static MUTEX_DECLARE_INIT(user_ps_path); 56 #endif 57 static struct flock fl; 58 59 60 /* 61 * Determine the default path to the persistent storage file and create it if it doesn't exist. 62 */ 63 TSS_RESULT 64 get_user_ps_path(char **file) 65 { 66 TSS_RESULT result; 67 char *file_name = NULL, *home_dir = NULL; 68 struct passwd *pwp; 69 #if (defined (__linux) || defined (linux) || defined(__GLIBC__)) 70 struct passwd pw; 71 #endif 72 struct stat stat_buf; 73 char buf[PASSWD_BUFSIZE]; 74 uid_t euid; 75 int rc; 76 77 if ((file_name = getenv("TSS_USER_PS_FILE"))) { 78 *file = strdup(file_name); 79 return (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY); 80 } 81 #if (defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__)) 82 MUTEX_LOCK(user_ps_path); 83 #endif 84 85 euid = geteuid(); 86 87 #if defined (SOLARIS) 88 /* 89 * Solaris keeps user PS in a local directory instead of 90 * in the user's home directory, which may be shared 91 * by multiple systems. 92 * 93 * The directory path on Solaris is /var/tpm/userps/[EUID]/ 94 */ 95 rc = snprintf(buf, sizeof (buf), "%s/%d", TSS_USER_PS_DIR, euid); 96 #else 97 setpwent(); 98 while (1) { 99 #if (defined (__linux) || defined (linux) || defined(__GLIBC__)) 100 rc = getpwent_r(&pw, buf, PASSWD_BUFSIZE, &pwp); 101 if (rc) { 102 LogDebugFn("USER PS: Error getting path to home directory: getpwent_r: %s", 103 strerror(rc)); 104 endpwent(); 105 return TSPERR(TSS_E_INTERNAL_ERROR); 106 } 107 108 #elif (defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__)) 109 if ((pwp = getpwent()) == NULL) { 110 LogDebugFn("USER PS: Error getting path to home directory: getpwent: %s", 111 strerror(rc)); 112 endpwent(); 113 MUTEX_UNLOCK(user_ps_path); 114 return TSPERR(TSS_E_INTERNAL_ERROR); 115 } 116 #endif 117 if (euid == pwp->pw_uid) { 118 home_dir = strdup(pwp->pw_dir); 119 break; 120 } 121 } 122 endpwent(); 123 124 if (!home_dir) 125 return TSPERR(TSS_E_OUTOFMEMORY); 126 127 /* Tack on TSS_USER_PS_DIR and see if it exists */ 128 rc = snprintf(buf, sizeof (buf), "%s/%s", home_dir, TSS_USER_PS_DIR); 129 #endif /* SOLARIS */ 130 if (rc == sizeof (buf)) { 131 LogDebugFn("USER PS: Path to file too long! (> %d bytes)", PASSWD_BUFSIZE); 132 result = TSPERR(TSS_E_INTERNAL_ERROR); 133 goto done; 134 } 135 136 errno = 0; 137 if ((rc = stat(buf, &stat_buf)) == -1) { 138 if (errno == ENOENT) { 139 errno = 0; 140 /* Create the user's ps directory if it is not there. */ 141 if ((rc = mkdir(buf, 0700)) == -1) { 142 LogDebugFn("USER PS: Error creating dir: %s: %s", buf, 143 strerror(errno)); 144 result = TSPERR(TSS_E_INTERNAL_ERROR); 145 goto done; 146 } 147 } else { 148 LogDebugFn("USER PS: Error stating dir: %s: %s", buf, strerror(errno)); 149 result = TSPERR(TSS_E_INTERNAL_ERROR); 150 goto done; 151 } 152 } 153 154 /* Directory exists or has been created, return the path to the file */ 155 #if defined (SOLARIS) 156 rc = snprintf(buf, sizeof (buf), "%s/%d/%s", TSS_USER_PS_DIR, euid, 157 TSS_USER_PS_FILE); 158 #else 159 rc = snprintf(buf, sizeof (buf), "%s/%s/%s", home_dir, TSS_USER_PS_DIR, 160 TSS_USER_PS_FILE); 161 #endif 162 if (rc == sizeof (buf)) { 163 LogDebugFn("USER PS: Path to file too long! (> %zd bytes)", sizeof (buf)); 164 } else 165 *file = strdup(buf); 166 167 result = (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY); 168 done: 169 free(home_dir); 170 return result; 171 } 172 173 TSS_RESULT 174 get_file(int *fd) 175 { 176 TSS_RESULT result; 177 int rc = 0; 178 char *file_name = NULL; 179 180 MUTEX_LOCK(user_ps_lock); 181 182 /* check the global file handle first. If it exists, lock it and return */ 183 if (user_ps_fd != -1) { 184 fl.l_type = F_WRLCK; 185 if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) { 186 LogDebug("USER PS: failed to lock file: %s", strerror(errno)); 187 MUTEX_UNLOCK(user_ps_lock); 188 return TSPERR(TSS_E_INTERNAL_ERROR); 189 } 190 *fd = user_ps_fd; 191 return TSS_SUCCESS; 192 } 193 194 /* open and lock the file */ 195 if ((result = get_user_ps_path(&file_name))) { 196 LogDebugFn("USER PS: error getting file path"); 197 MUTEX_UNLOCK(user_ps_lock); 198 return result; 199 } 200 201 user_ps_fd = open(file_name, O_CREAT|O_RDWR, 0600); 202 if (user_ps_fd < 0) { 203 LogDebug("USER PS: open of %s failed: %s", file_name, strerror(errno)); 204 free(file_name); 205 MUTEX_UNLOCK(user_ps_lock); 206 return TSPERR(TSS_E_INTERNAL_ERROR); 207 } 208 fl.l_type = F_WRLCK; 209 if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) { 210 LogDebug("USER PS: failed to get lock of %s: %s", file_name, strerror(errno)); 211 free(file_name); 212 close(user_ps_fd); 213 user_ps_fd = -1; 214 MUTEX_UNLOCK(user_ps_lock); 215 return TSPERR(TSS_E_INTERNAL_ERROR); 216 } 217 218 *fd = user_ps_fd; 219 free(file_name); 220 return TSS_SUCCESS; 221 } 222 223 int 224 put_file(int fd) 225 { 226 int rc = 0; 227 228 fsync(fd); 229 230 /* release the file lock */ 231 fl.l_type = F_UNLCK; 232 if ((rc = fcntl(fd, F_SETLKW, &fl))) { 233 LogDebug("USER PS: failed to unlock file: %s", strerror(errno)); 234 rc = -1; 235 } 236 237 MUTEX_UNLOCK(user_ps_lock); 238 return rc; 239 } 240 241 void 242 psfile_close(int fd) 243 { 244 close(fd); 245 user_ps_fd = -1; 246 MUTEX_UNLOCK(user_ps_lock); 247 } 248 249 TSS_RESULT 250 psfile_is_key_registered(int fd, TSS_UUID *uuid, TSS_BOOL *answer) 251 { 252 TSS_RESULT result; 253 struct key_disk_cache tmp; 254 255 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)) == TSS_SUCCESS) 256 *answer = TRUE; 257 else if (result == (TSS_E_PS_KEY_NOTFOUND | TSS_LAYER_TSP)) 258 *answer = FALSE; 259 else 260 return result; 261 262 return TSS_SUCCESS; 263 } 264 265 TSS_RESULT 266 psfile_get_parent_uuid_by_uuid(int fd, TSS_UUID *uuid, TSS_UUID *ret_uuid) 267 { 268 TSS_RESULT result; 269 struct key_disk_cache tmp; 270 271 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp))) 272 return result; 273 274 memcpy(ret_uuid, &tmp.parent_uuid, sizeof(TSS_UUID)); 275 276 return TSS_SUCCESS; 277 } 278 279 TSS_RESULT 280 psfile_get_parent_ps_type(int fd, TSS_UUID *uuid, UINT32 *type) 281 { 282 TSS_RESULT result; 283 struct key_disk_cache tmp; 284 285 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp))) 286 return result; 287 288 if (tmp.flags & CACHE_FLAG_PARENT_PS_SYSTEM) 289 *type = TSS_PS_TYPE_SYSTEM; 290 else 291 *type = TSS_PS_TYPE_USER; 292 293 return TSS_SUCCESS; 294 } 295 296 /* 297 * return a key struct from PS given a uuid 298 */ 299 TSS_RESULT 300 psfile_get_key_by_uuid(int fd, TSS_UUID *uuid, BYTE *key) 301 { 302 int rc; 303 TSS_RESULT result; 304 off_t file_offset; 305 struct key_disk_cache tmp; 306 BYTE buf[4096]; 307 308 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp))) 309 return result; 310 311 /* jump to the location of the key blob */ 312 file_offset = TSSPS_BLOB_DATA_OFFSET(&tmp); 313 314 rc = lseek(fd, file_offset, SEEK_SET); 315 if (rc == ((off_t)-1)) { 316 LogDebugFn("lseek: %s", strerror(errno)); 317 return TSPERR(TSS_E_INTERNAL_ERROR); 318 } 319 320 if (tmp.blob_size > 4096) { 321 LogError("Blob size greater than 4096! Size: %d", 322 tmp.blob_size); 323 return TSPERR(TSS_E_INTERNAL_ERROR); 324 } 325 if ((rc = read_data(fd, buf, tmp.blob_size))) { 326 LogDebugFn("Blob read from disk failed."); 327 return rc; 328 } 329 330 memcpy(key, buf, tmp.blob_size); 331 return TSS_SUCCESS; 332 } 333 334 /* 335 * return a key struct from PS given a public key 336 */ 337 TSS_RESULT 338 psfile_get_key_by_pub(int fd, TSS_UUID *uuid, UINT32 pub_size, BYTE *pub, BYTE *key) 339 { 340 int rc; 341 TSS_RESULT result; 342 off_t file_offset; 343 struct key_disk_cache tmp; 344 BYTE buf[4096]; 345 346 if ((result = psfile_get_cache_entry_by_pub(fd, pub_size, pub, &tmp))) 347 return result; 348 349 /* jump to the location of the key blob */ 350 file_offset = TSSPS_BLOB_DATA_OFFSET(&tmp); 351 352 rc = lseek(fd, file_offset, SEEK_SET); 353 if (rc == ((off_t)-1)) { 354 LogDebugFn("lseek: %s", strerror(errno)); 355 return TSPERR(TSS_E_INTERNAL_ERROR); 356 } 357 358 if (tmp.blob_size > 4096) { 359 LogError("Blob size greater than 4096! Size: %d", 360 tmp.blob_size); 361 return TSPERR(TSS_E_INTERNAL_ERROR); 362 } 363 364 if ((result = read_data(fd, buf, tmp.blob_size))) { 365 LogDebugFn("Blob read from disk failed."); 366 return result; 367 } 368 369 memcpy(key, buf, tmp.blob_size); 370 memcpy(uuid, &tmp.uuid, sizeof(TSS_UUID)); 371 372 return TSS_SUCCESS; 373 } 374 375 TSS_RESULT 376 psfile_get_uuid_by_pub(int fd, UINT32 pub_size, BYTE *pub, TSS_UUID *uuid) 377 { 378 TSS_RESULT result; 379 struct key_disk_cache tmp; 380 381 if ((result = psfile_get_cache_entry_by_pub(fd, pub_size, pub, &tmp))) 382 return result; 383 384 memcpy(uuid, &tmp.uuid, sizeof(TSS_UUID)); 385 386 return TSS_SUCCESS; 387 } 388 389 TSS_RESULT 390 psfile_change_num_keys(int fd, BYTE increment) 391 { 392 int rc; 393 TSS_RESULT result; 394 UINT32 num_keys; 395 396 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET); 397 if (rc == ((off_t)-1)) { 398 LogDebug("lseek: %s", strerror(errno)); 399 return TSPERR(TSS_E_INTERNAL_ERROR); 400 } 401 402 rc = read(fd, &num_keys, sizeof(UINT32)); 403 if (rc != sizeof(UINT32)) { 404 LogDebug("read of %zd bytes: %s", sizeof(UINT32), strerror(errno)); 405 return TSPERR(TSS_E_INTERNAL_ERROR); 406 } 407 num_keys = LE_32(num_keys); 408 409 if (increment) 410 num_keys++; 411 else 412 num_keys--; 413 414 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET); 415 if (rc == ((off_t)-1)) { 416 LogDebug("lseek: %s", strerror(errno)); 417 return TSPERR(TSS_E_INTERNAL_ERROR); 418 } 419 420 num_keys = LE_32(num_keys); 421 if ((result = write_data(fd, (void *)&num_keys, sizeof(UINT32)))) { 422 LogDebug("%s", __FUNCTION__); 423 return result; 424 } 425 426 return TSS_SUCCESS; 427 } 428 429 /* Write the initial header (number of keys and PS version) to initialize a new file */ 430 TSS_RESULT 431 psfile_write_key_header(int fd) 432 { 433 int rc; 434 TSS_RESULT result; 435 UINT32 i; 436 437 rc = lseek(fd, TSSPS_VERSION_OFFSET, SEEK_SET); 438 if (rc == ((off_t)-1)) { 439 LogDebug("lseek: %s", strerror(errno)); 440 return TSPERR(TSS_E_INTERNAL_ERROR); 441 } 442 443 i = TSSPS_VERSION; 444 if ((result = write_data(fd, &i, sizeof(BYTE)))) { 445 LogDebug("%s", __FUNCTION__); 446 return result; 447 } 448 449 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET); 450 if (rc == ((off_t)-1)) { 451 LogDebug("lseek: %s", strerror(errno)); 452 return TSPERR(TSS_E_INTERNAL_ERROR); 453 } 454 455 i = 0; 456 if ((result = write_data(fd, &i, sizeof(UINT32)))) { 457 LogDebug("%s", __FUNCTION__); 458 return result; 459 } 460 461 return TSS_SUCCESS; 462 } 463 464 /* 465 * disk store format: 466 * 467 * TrouSerS 0.2.1+ 468 * Version 1: cached? 469 * [BYTE PS version = '\1'] 470 * [UINT32 num_keys_on_disk ] 471 * [TSS_UUID uuid0 ] yes 472 * [TSS_UUID uuid_parent0 ] yes 473 * [UINT16 pub_data_size0 ] yes 474 * [UINT16 blob_size0 ] yes 475 * [UINT32 vendor_data_size0] yes 476 * [UINT16 cache_flags0 ] yes 477 * [BYTE[] pub_data0 ] 478 * [BYTE[] blob0 ] 479 * [BYTE[] vendor_data0 ] 480 * [...] 481 * 482 */ 483 TSS_RESULT 484 psfile_write_key(int fd, 485 TSS_UUID *uuid, 486 TSS_UUID *parent_uuid, 487 UINT32 parent_ps, 488 BYTE *key_blob, 489 UINT16 key_blob_size) 490 { 491 TSS_RESULT result; 492 TSS_KEY key; 493 UINT32 zero = 0; 494 UINT64 offset; 495 UINT16 pub_key_size, cache_flags = 0; 496 struct stat stat_buf; 497 int rc, file_offset; 498 499 /* leaving the cache flag for parent ps type as 0 implies TSS_PS_TYPE_USER */ 500 if (parent_ps == TSS_PS_TYPE_SYSTEM) 501 cache_flags |= CACHE_FLAG_PARENT_PS_SYSTEM; 502 503 if ((rc = fstat(fd, &stat_buf)) == -1) { 504 LogDebugFn("stat failed: %s", strerror(errno)); 505 return TSPERR(TSS_E_INTERNAL_ERROR); 506 } 507 508 file_offset = stat_buf.st_size; 509 510 if (file_offset < (int)TSSPS_KEYS_OFFSET) { 511 if ((result = psfile_write_key_header(fd))) 512 return result; 513 file_offset = TSSPS_KEYS_OFFSET; 514 } 515 516 rc = lseek(fd, file_offset, SEEK_SET); 517 if (rc == ((off_t)-1)) { 518 LogDebug("lseek: %s", strerror(errno)); 519 return TSPERR(TSS_E_INTERNAL_ERROR); 520 } 521 522 /* Unload the blob to get the public key */ 523 offset = 0; 524 if ((result = UnloadBlob_TSS_KEY(&offset, key_blob, &key))) 525 return result; 526 527 pub_key_size = key.pubKey.keyLength; 528 529 /* [TSS_UUID uuid0 ] yes */ 530 if ((result = write_data(fd, (void *)uuid, sizeof(TSS_UUID)))) { 531 LogDebug("%s", __FUNCTION__); 532 goto done; 533 } 534 535 /* [TSS_UUID uuid_parent0 ] yes */ 536 if ((result = write_data(fd, (void *)parent_uuid, sizeof(TSS_UUID)))) { 537 LogDebug("%s", __FUNCTION__); 538 goto done; 539 } 540 541 /* [UINT16 pub_data_size0 ] yes */ 542 pub_key_size = LE_16(pub_key_size); 543 if ((result = write_data(fd, &pub_key_size, sizeof(UINT16)))) { 544 LogDebug("%s", __FUNCTION__); 545 goto done; 546 } 547 pub_key_size = LE_16(pub_key_size); 548 549 /* [UINT16 blob_size0 ] yes */ 550 key_blob_size = LE_16(key_blob_size); 551 if ((result = write_data(fd, &key_blob_size, sizeof(UINT16)))) { 552 LogDebug("%s", __FUNCTION__); 553 goto done; 554 } 555 key_blob_size = LE_16(key_blob_size); 556 557 /* [UINT32 vendor_data_size0 ] yes */ 558 if ((result = write_data(fd, &zero, sizeof(UINT32)))) { 559 LogDebug("%s", __FUNCTION__); 560 goto done; 561 } 562 563 /* [UINT16 cache_flags0 ] yes */ 564 cache_flags = LE_16(cache_flags); 565 if ((result = write_data(fd, &cache_flags, sizeof(UINT16)))) { 566 LogDebug("%s", __FUNCTION__); 567 goto done; 568 } 569 cache_flags = LE_16(cache_flags); 570 571 /* [BYTE[] pub_data0 ] no */ 572 if ((result = write_data(fd, (void *)key.pubKey.key, pub_key_size))) { 573 LogDebug("%s", __FUNCTION__); 574 goto done; 575 } 576 577 /* [BYTE[] blob0 ] no */ 578 if ((result = write_data(fd, (void *)key_blob, key_blob_size))) { 579 LogDebug("%s", __FUNCTION__); 580 goto done; 581 } 582 583 if ((result = psfile_change_num_keys(fd, TSS_PSFILE_INCREMENT_NUM_KEYS))) { 584 LogDebug("%s", __FUNCTION__); 585 goto done; 586 } 587 588 done: 589 free_key_refs(&key); 590 return result; 591 } 592 593 TSS_RESULT 594 psfile_remove_key(int fd, TSS_UUID *uuid) 595 { 596 TSS_RESULT result; 597 UINT32 head_offset = 0, tail_offset; 598 int rc, size = 0; 599 struct key_disk_cache c; 600 BYTE buf[4096]; 601 602 if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &c))) 603 return result; 604 605 /* head_offset is the offset the beginning of the key */ 606 head_offset = TSSPS_UUID_OFFSET(&c); 607 608 /* tail_offset is the offset the beginning of the next key */ 609 tail_offset = TSSPS_VENDOR_DATA_OFFSET(&c) + c.vendor_data_size; 610 611 rc = lseek(fd, tail_offset, SEEK_SET); 612 if (rc == ((off_t)-1)) { 613 LogDebug("lseek: %s", strerror(errno)); 614 return TSPERR(TSS_E_INTERNAL_ERROR); 615 } 616 617 /* read in from tail, write out to head to fill the gap */ 618 while ((rc = read(fd, buf, sizeof(buf))) > 0) { 619 size = rc; 620 tail_offset += size; 621 622 /* set the file pointer to where we want to write */ 623 rc = lseek(fd, head_offset, SEEK_SET); 624 if (rc == ((off_t)-1)) { 625 LogDebug("lseek: %s", strerror(errno)); 626 return TSPERR(TSS_E_INTERNAL_ERROR); 627 } 628 629 /* write the data */ 630 if ((result = write_data(fd, (void *)buf, size))) { 631 LogDebug("%s", __FUNCTION__); 632 return result; 633 } 634 head_offset += size; 635 636 /* set the file pointer to where we want to read in the next 637 * loop */ 638 rc = lseek(fd, tail_offset, SEEK_SET); 639 if (rc == ((off_t)-1)) { 640 LogDebug("lseek: %s", strerror(errno)); 641 return TSPERR(TSS_E_INTERNAL_ERROR); 642 } 643 } 644 645 if (rc < 0) { 646 LogDebug("read: %s", strerror(errno)); 647 return TSPERR(TSS_E_INTERNAL_ERROR); 648 } 649 650 /* set the file pointer to where we want to write */ 651 rc = lseek(fd, head_offset, SEEK_SET); 652 if (rc == ((off_t)-1)) { 653 LogDebug("lseek: %s", strerror(errno)); 654 return TSPERR(TSS_E_INTERNAL_ERROR); 655 } 656 657 /* head_offset now contains a pointer to where we want to truncate the 658 * file. Zero out the old tail end of the file and truncate it. */ 659 660 __tspi_memset(buf, 0, sizeof(buf)); 661 662 /* Zero out the old tail end of the file */ 663 if ((result = write_data(fd, (void *)buf, tail_offset - head_offset))) { 664 LogDebug("%s", __FUNCTION__); 665 return result; 666 } 667 668 if ((rc = ftruncate(fd, head_offset)) < 0) { 669 LogDebug("ftruncate: %s", strerror(errno)); 670 return TSPERR(TSS_E_INTERNAL_ERROR); 671 } 672 673 /* we succeeded in removing a key from the disk. Decrement the number 674 * of keys in the file */ 675 if ((result = psfile_change_num_keys(fd, TSS_PSFILE_DECREMENT_NUM_KEYS))) 676 return result; 677 678 return TSS_SUCCESS; 679 } 680 681 TSS_RESULT 682 psfile_get_all_cache_entries(int fd, UINT32 *size, struct key_disk_cache **c) 683 { 684 UINT32 i, num_keys = psfile_get_num_keys(fd); 685 int offset; 686 TSS_RESULT result; 687 struct key_disk_cache *tmp = NULL; 688 689 if (num_keys == 0) { 690 *size = 0; 691 *c = NULL; 692 return TSS_SUCCESS; 693 } 694 695 /* make sure the file pointer is where we expect, just after the number 696 * of keys on disk at the head of the file 697 */ 698 offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET); 699 if (offset == ((off_t)-1)) { 700 LogDebug("lseek: %s", strerror(errno)); 701 return TSPERR(TSS_E_INTERNAL_ERROR); 702 } 703 704 if ((tmp = malloc(num_keys * sizeof(struct key_disk_cache))) == NULL) { 705 LogDebug("malloc of %zu bytes failed.", num_keys * sizeof(struct key_disk_cache)); 706 return TSPERR(TSS_E_OUTOFMEMORY); 707 } 708 709 for (i = 0; i < num_keys; i++) { 710 offset = lseek(fd, 0, SEEK_CUR); 711 if (offset == ((off_t)-1)) { 712 LogDebug("lseek: %s", strerror(errno)); 713 result = TSPERR(TSS_E_INTERNAL_ERROR); 714 goto err_exit; 715 } 716 tmp[i].offset = offset; 717 718 /* read UUID */ 719 if ((result = read_data(fd, &tmp[i].uuid, sizeof(TSS_UUID)))) { 720 LogDebug("%s", __FUNCTION__); 721 goto err_exit; 722 } 723 724 /* read parent UUID */ 725 if ((result = read_data(fd, &tmp[i].parent_uuid, sizeof(TSS_UUID)))) { 726 LogDebug("%s", __FUNCTION__); 727 goto err_exit; 728 } 729 730 /* pub data size */ 731 if ((result = read_data(fd, &tmp[i].pub_data_size, sizeof(UINT16)))) { 732 LogDebug("%s", __FUNCTION__); 733 goto err_exit; 734 } 735 tmp[i].pub_data_size = LE_16(tmp[i].pub_data_size); 736 737 DBG_ASSERT(tmp[i].pub_data_size <= 2048); 738 739 /* blob size */ 740 if ((result = read_data(fd, &tmp[i].blob_size, sizeof(UINT16)))) { 741 LogDebug("%s", __FUNCTION__); 742 goto err_exit; 743 } 744 tmp[i].blob_size = LE_16(tmp[i].blob_size); 745 746 DBG_ASSERT(tmp[i].blob_size <= 4096); 747 748 /* vendor data size */ 749 if ((result = read_data(fd, &tmp[i].vendor_data_size, sizeof(UINT32)))) { 750 LogDebug("%s", __FUNCTION__); 751 goto err_exit; 752 } 753 tmp[i].vendor_data_size = LE_32(tmp[i].vendor_data_size); 754 755 /* cache flags */ 756 if ((result = read_data(fd, &tmp[i].flags, sizeof(UINT16)))) { 757 LogDebug("%s", __FUNCTION__); 758 goto err_exit; 759 } 760 tmp[i].flags = LE_16(tmp[i].flags); 761 762 /* fast forward over the pub key */ 763 offset = lseek(fd, tmp[i].pub_data_size, SEEK_CUR); 764 if (offset == ((off_t)-1)) { 765 LogDebug("lseek: %s", strerror(errno)); 766 result = TSPERR(TSS_E_INTERNAL_ERROR); 767 goto err_exit; 768 } 769 770 /* fast forward over the blob */ 771 offset = lseek(fd, tmp[i].blob_size, SEEK_CUR); 772 if (offset == ((off_t)-1)) { 773 LogDebug("lseek: %s", strerror(errno)); 774 result = TSPERR(TSS_E_INTERNAL_ERROR); 775 goto err_exit; 776 } 777 778 /* ignore vendor data for user ps */ 779 } 780 781 *size = num_keys; 782 *c = tmp; 783 784 return TSS_SUCCESS; 785 786 err_exit: 787 free(tmp); 788 return result; 789 } 790 791 TSS_RESULT 792 copy_key_info(int fd, TSS_KM_KEYINFO *ki, struct key_disk_cache *c) 793 { 794 TSS_KEY key; 795 BYTE blob[4096]; 796 UINT64 offset; 797 TSS_RESULT result; 798 off_t off; 799 800 /* Set the file pointer to the offset that the key blob is at */ 801 off = lseek(fd, TSSPS_BLOB_DATA_OFFSET(c), SEEK_SET); 802 if (off == ((off_t)-1)) { 803 LogDebug("lseek: %s", strerror(errno)); 804 return TSPERR(TSS_E_INTERNAL_ERROR); 805 } 806 807 /* Read in the key blob */ 808 if ((result = read_data(fd, (void *)blob, c->blob_size))) { 809 LogDebug("%s", __FUNCTION__); 810 return result; 811 } 812 813 /* Expand the blob into a useable form */ 814 offset = 0; 815 if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key))) 816 return result; 817 818 if (key.hdr.key12.tag == TPM_TAG_KEY12) { 819 ki->versionInfo.bMajor = TSS_SPEC_MAJOR; 820 ki->versionInfo.bMinor = TSS_SPEC_MINOR; 821 ki->versionInfo.bRevMajor = 0; 822 ki->versionInfo.bRevMinor = 0; 823 } else 824 memcpy(&ki->versionInfo, &key.hdr.key11.ver, sizeof(TSS_VERSION)); 825 memcpy(&ki->keyUUID, &c->uuid, sizeof(TSS_UUID)); 826 memcpy(&ki->parentKeyUUID, &c->parent_uuid, sizeof(TSS_UUID)); 827 ki->bAuthDataUsage = key.authDataUsage; 828 829 free_key_refs(&key); 830 831 return TSS_SUCCESS; 832 } 833 834 TSS_RESULT 835 copy_key_info2(int fd, TSS_KM_KEYINFO2 *ki, struct key_disk_cache *c) 836 { 837 TSS_KEY key; 838 BYTE blob[4096]; 839 UINT64 offset; 840 TSS_RESULT result; 841 off_t off; 842 843 /* Set the file pointer to the offset that the key blob is at */ 844 off = lseek(fd, TSSPS_BLOB_DATA_OFFSET(c), SEEK_SET); 845 if (off == ((off_t)-1)) { 846 LogDebug("lseek: %s", strerror(errno)); 847 return TSPERR(TSS_E_INTERNAL_ERROR); 848 } 849 850 /* Read in the key blob */ 851 if ((result = read_data(fd, (void *)blob, c->blob_size))) { 852 LogDebug("%s", __FUNCTION__); 853 return result; 854 } 855 856 /* Expand the blob into a useable form */ 857 offset = 0; 858 if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key))) 859 return result; 860 861 if (key.hdr.key12.tag == TPM_TAG_KEY12) { 862 ki->versionInfo.bMajor = TSS_SPEC_MAJOR; 863 ki->versionInfo.bMinor = TSS_SPEC_MINOR; 864 ki->versionInfo.bRevMajor = 0; 865 ki->versionInfo.bRevMinor = 0; 866 } else 867 memcpy(&ki->versionInfo, &key.hdr.key11.ver, sizeof(TSS_VERSION)); 868 memcpy(&ki->keyUUID, &c->uuid, sizeof(TSS_UUID)); 869 memcpy(&ki->parentKeyUUID, &c->parent_uuid, sizeof(TSS_UUID)); 870 871 /* CHECK: fill the two new fields of TSS_KM_KEYINFO2 */ 872 ki->persistentStorageType = TSS_PS_TYPE_USER; 873 ki->persistentStorageTypeParent = c->flags & CACHE_FLAG_PARENT_PS_SYSTEM ? 874 TSS_PS_TYPE_SYSTEM : TSS_PS_TYPE_USER; 875 876 ki->bAuthDataUsage = key.authDataUsage; 877 878 free_key_refs(&key); 879 880 return TSS_SUCCESS; 881 } 882 883 884 TSS_RESULT 885 psfile_get_registered_keys(int fd, 886 TSS_UUID *uuid, 887 TSS_UUID *tcs_uuid, 888 UINT32 *size, 889 TSS_KM_KEYINFO **keys) 890 { 891 TSS_RESULT result; 892 struct key_disk_cache *cache_entries; 893 UINT32 cache_size, i, j; 894 TSS_KM_KEYINFO *keyinfos = NULL; 895 TSS_UUID *find_uuid; 896 897 if ((result = psfile_get_all_cache_entries(fd, &cache_size, &cache_entries))) 898 return result; 899 900 if (cache_size == 0) { 901 if (uuid) 902 return TSPERR(TSS_E_PS_KEY_NOTFOUND); 903 else { 904 *size = 0; 905 *keys = NULL; 906 return TSS_SUCCESS; 907 } 908 } 909 910 if (uuid) { 911 find_uuid = uuid; 912 j = 0; 913 914 restart_search: 915 /* Search for the requested UUID. When found, allocate new space for it, copy 916 * it in, then change the uuid to be searched for it its parent and start over. */ 917 for (i = 0; i < cache_size; i++) { 918 if (!memcmp(&cache_entries[i].uuid, find_uuid, sizeof(TSS_UUID))) { 919 if (!(keyinfos = realloc(keyinfos, 920 (j+1) * sizeof(TSS_KM_KEYINFO)))) { 921 free(cache_entries); 922 free(keyinfos); 923 return TSPERR(TSS_E_OUTOFMEMORY); 924 } 925 __tspi_memset(&keyinfos[j], 0, sizeof(TSS_KM_KEYINFO)); 926 927 if ((result = copy_key_info(fd, &keyinfos[j], &cache_entries[i]))) { 928 free(cache_entries); 929 free(keyinfos); 930 return result; 931 } 932 933 find_uuid = &keyinfos[j].parentKeyUUID; 934 j++; 935 goto restart_search; 936 } 937 } 938 939 /* Searching for keys in the user PS will always lead us up to some key in the 940 * system PS. Return that key's uuid so that the upper layers can call down to TCS 941 * to search for it. */ 942 memcpy(tcs_uuid, find_uuid, sizeof(TSS_UUID)); 943 944 *size = j; 945 } else { 946 if ((keyinfos = calloc(cache_size, sizeof(TSS_KM_KEYINFO))) == NULL) { 947 LogDebug("malloc of %zu bytes failed.", 948 cache_size * sizeof(TSS_KM_KEYINFO)); 949 free(cache_entries); 950 return TSPERR(TSS_E_OUTOFMEMORY); 951 } 952 953 for (i = 0; i < cache_size; i++) { 954 if ((result = copy_key_info(fd, &keyinfos[i], &cache_entries[i]))) { 955 free(cache_entries); 956 free(keyinfos); 957 return result; 958 } 959 } 960 961 *size = cache_size; 962 } 963 964 free(cache_entries); 965 966 *keys = keyinfos; 967 968 return TSS_SUCCESS; 969 } 970 971 TSS_RESULT 972 psfile_get_registered_keys2(int fd, 973 TSS_UUID *uuid, 974 TSS_UUID *tcs_uuid, 975 UINT32 *size, 976 TSS_KM_KEYINFO2 **keys) 977 { 978 TSS_RESULT result; 979 struct key_disk_cache *cache_entries; 980 UINT32 cache_size, i, j; 981 TSS_KM_KEYINFO2 *keyinfos = NULL; 982 TSS_UUID *find_uuid; 983 984 if ((result = psfile_get_all_cache_entries(fd, &cache_size, &cache_entries))) 985 return result; 986 987 if (cache_size == 0) { 988 if (uuid) 989 return TSPERR(TSS_E_PS_KEY_NOTFOUND); 990 else { 991 *size = 0; 992 *keys = NULL; 993 return TSS_SUCCESS; 994 } 995 } 996 997 if (uuid) { 998 find_uuid = uuid; 999 j = 0; 1000 1001 restart_search: 1002 /* Search for the requested UUID. When found, allocate new space for it, copy 1003 * it in, then change the uuid to be searched for it its parent and start over. */ 1004 for (i = 0; i < cache_size; i++) { 1005 /*Return 0 if normal finish*/ 1006 if (!memcmp(&cache_entries[i].uuid, find_uuid, sizeof(TSS_UUID))) { 1007 if (!(keyinfos = realloc(keyinfos, 1008 (j+1) * sizeof(TSS_KM_KEYINFO2)))) { 1009 free(cache_entries); 1010 free(keyinfos); 1011 return TSPERR(TSS_E_OUTOFMEMORY); 1012 } 1013 /* Here the key UUID is found and needs to be copied for the array*/ 1014 /* Initializes the keyinfos with 0's*/ 1015 __tspi_memset(&keyinfos[j], 0, sizeof(TSS_KM_KEYINFO2)); 1016 1017 if ((result = copy_key_info2(fd, &keyinfos[j], &cache_entries[i]))) { 1018 free(cache_entries); 1019 free(keyinfos); 1020 return result; 1021 } 1022 1023 find_uuid = &keyinfos[j].parentKeyUUID; 1024 j++; 1025 goto restart_search; 1026 } 1027 } 1028 1029 /* Searching for keys in the user PS will always lead us up to some key in the 1030 * system PS. Return that key's uuid so that the upper layers can call down to TCS 1031 * to search for it. */ 1032 memcpy(tcs_uuid, find_uuid, sizeof(TSS_UUID)); 1033 1034 *size = j; 1035 } else { 1036 if ((keyinfos = calloc(cache_size, sizeof(TSS_KM_KEYINFO2))) == NULL) { 1037 LogDebug("malloc of %zu bytes failed.", 1038 cache_size * sizeof(TSS_KM_KEYINFO2)); 1039 free(cache_entries); 1040 return TSPERR(TSS_E_OUTOFMEMORY); 1041 } 1042 1043 for (i = 0; i < cache_size; i++) { 1044 if ((result = copy_key_info2(fd, &keyinfos[i], &cache_entries[i]))) { 1045 free(cache_entries); 1046 free(keyinfos); 1047 return result; 1048 } 1049 } 1050 1051 *size = cache_size; 1052 } 1053 1054 free(cache_entries); 1055 1056 *keys = keyinfos; 1057 1058 return TSS_SUCCESS; 1059 } 1060 1061 /* 1062 * read into the PS file and return the number of keys 1063 */ 1064 UINT32 1065 psfile_get_num_keys(int fd) 1066 { 1067 UINT32 num_keys; 1068 int rc; 1069 1070 /* go to the number of keys */ 1071 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET); 1072 if (rc == ((off_t)-1)) { 1073 LogDebug("lseek: %s", strerror(errno)); 1074 return 0; 1075 } 1076 1077 rc = read(fd, &num_keys, sizeof(UINT32)); 1078 if (rc < 0) { 1079 LogDebug("read of %zd bytes: %s", sizeof(UINT32), strerror(errno)); 1080 return 0; 1081 } else if ((unsigned)rc < sizeof(UINT32)) { 1082 num_keys = 0; 1083 } 1084 1085 /* The system PS file is written in little-endian */ 1086 num_keys = LE_32(num_keys); 1087 return num_keys; 1088 } 1089 1090 /* 1091 * disk store format: 1092 * 1093 * TrouSerS 0.2.1+ 1094 * Version 1: cached? 1095 * [BYTE PS version = '\1'] 1096 * [UINT32 num_keys_on_disk ] 1097 * [TSS_UUID uuid0 ] yes 1098 * [TSS_UUID uuid_parent0 ] yes 1099 * [UINT16 pub_data_size0 ] yes 1100 * [UINT16 blob_size0 ] yes 1101 * [UINT32 vendor_data_size0] yes 1102 * [UINT16 cache_flags0 ] yes 1103 * [BYTE[] pub_data0 ] 1104 * [BYTE[] blob0 ] 1105 * [BYTE[] vendor_data0 ] 1106 * [...] 1107 * 1108 */ 1109 TSS_RESULT 1110 psfile_get_cache_entry_by_uuid(int fd, TSS_UUID *uuid, struct key_disk_cache *c) 1111 { 1112 UINT32 i, num_keys = psfile_get_num_keys(fd); 1113 int offset; 1114 TSS_RESULT result; 1115 BYTE found = 0; 1116 1117 if (num_keys == 0) 1118 return TSPERR(TSS_E_PS_KEY_NOTFOUND); 1119 1120 /* make sure the file pointer is where we expect, just after the number 1121 * of keys on disk at the head of the file 1122 */ 1123 offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET); 1124 if (offset == ((off_t)-1)) { 1125 LogDebug("lseek: %s", strerror(errno)); 1126 return TSPERR(TSS_E_INTERNAL_ERROR); 1127 } 1128 1129 for (i = 0; i < num_keys && !found; i++) { 1130 offset = lseek(fd, 0, SEEK_CUR); 1131 if (offset == ((off_t)-1)) { 1132 LogDebug("lseek: %s", strerror(errno)); 1133 return TSPERR(TSS_E_INTERNAL_ERROR); 1134 } 1135 c->offset = offset; 1136 1137 /* read UUID */ 1138 if ((result = read_data(fd, (void *)&c->uuid, sizeof(TSS_UUID)))) { 1139 LogDebug("%s", __FUNCTION__); 1140 return result; 1141 } 1142 1143 if (!memcmp(&c->uuid, uuid, sizeof(TSS_UUID))) { 1144 found = 1; 1145 1146 /* read parent UUID */ 1147 if ((result = read_data(fd, (void *)&c->parent_uuid, sizeof(TSS_UUID)))) { 1148 LogDebug("%s", __FUNCTION__); 1149 return result; 1150 } 1151 } else { 1152 /* fast forward over the parent UUID */ 1153 offset = lseek(fd, sizeof(TSS_UUID), SEEK_CUR); 1154 if (offset == ((off_t)-1)) { 1155 LogDebug("lseek: %s", strerror(errno)); 1156 return TSPERR(TSS_E_INTERNAL_ERROR); 1157 } 1158 } 1159 1160 /* pub data size */ 1161 if ((result = read_data(fd, &c->pub_data_size, sizeof(UINT16)))) { 1162 LogDebug("%s", __FUNCTION__); 1163 return result; 1164 } 1165 c->pub_data_size = LE_16(c->pub_data_size); 1166 DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0); 1167 1168 /* blob size */ 1169 if ((result = read_data(fd, &c->blob_size, sizeof(UINT16)))) { 1170 LogDebug("%s", __FUNCTION__); 1171 return result; 1172 } 1173 c->blob_size = LE_16(c->blob_size); 1174 DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0); 1175 1176 /* vendor data size */ 1177 if ((result = read_data(fd, &c->vendor_data_size, sizeof(UINT32)))) { 1178 LogDebug("%s", __FUNCTION__); 1179 return result; 1180 } 1181 c->vendor_data_size = LE_32(c->vendor_data_size); 1182 1183 /* cache flags */ 1184 if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) { 1185 LogDebug("%s", __FUNCTION__); 1186 return result; 1187 } 1188 c->flags = LE_16(c->flags); 1189 1190 /* fast forward over the pub key */ 1191 offset = lseek(fd, c->pub_data_size, SEEK_CUR); 1192 if (offset == ((off_t)-1)) { 1193 LogDebug("lseek: %s", strerror(errno)); 1194 return TSPERR(TSS_E_INTERNAL_ERROR); 1195 } 1196 1197 /* fast forward over the blob */ 1198 offset = lseek(fd, c->blob_size, SEEK_CUR); 1199 if (offset == ((off_t)-1)) { 1200 LogDebug("lseek: %s", strerror(errno)); 1201 return TSPERR(TSS_E_INTERNAL_ERROR); 1202 } 1203 1204 /* ignore vendor data in user ps */ 1205 } 1206 1207 return found ? TSS_SUCCESS : TSPERR(TSS_E_PS_KEY_NOTFOUND); 1208 } 1209 1210 TSS_RESULT 1211 psfile_get_cache_entry_by_pub(int fd, UINT32 pub_size, BYTE *pub, struct key_disk_cache *c) 1212 { 1213 BYTE blob[2048]; 1214 UINT32 i, num_keys = psfile_get_num_keys(fd); 1215 int offset; 1216 TSS_RESULT result; 1217 1218 if (num_keys == 0) 1219 return TSPERR(TSS_E_PS_KEY_NOTFOUND); 1220 1221 /* make sure the file pointer is where we expect, just after the number 1222 * of keys on disk at the head of the file 1223 */ 1224 offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET); 1225 if (offset == ((off_t)-1)) { 1226 LogDebug("lseek: %s", strerror(errno)); 1227 return TSPERR(TSS_E_INTERNAL_ERROR); 1228 } 1229 1230 for (i = 0; i < num_keys; i++) { 1231 offset = lseek(fd, 0, SEEK_CUR); 1232 if (offset == ((off_t)-1)) { 1233 LogDebug("lseek: %s", strerror(errno)); 1234 return TSPERR(TSS_E_INTERNAL_ERROR); 1235 } 1236 c->offset = offset; 1237 1238 /* read UUID */ 1239 if ((result = read_data(fd, (void *)&c->uuid, sizeof(TSS_UUID)))) { 1240 LogDebug("%s", __FUNCTION__); 1241 return result; 1242 } 1243 1244 /* read parent UUID */ 1245 if ((result = read_data(fd, (void *)&c->parent_uuid, sizeof(TSS_UUID)))) { 1246 LogDebug("%s", __FUNCTION__); 1247 return result; 1248 } 1249 1250 /* pub data size */ 1251 if ((result = read_data(fd, &c->pub_data_size, sizeof(UINT16)))) { 1252 LogDebug("%s", __FUNCTION__); 1253 return result; 1254 } 1255 1256 c->pub_data_size = LE_16(c->pub_data_size); 1257 DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0); 1258 1259 /* blob size */ 1260 if ((result = read_data(fd, &c->blob_size, sizeof(UINT16)))) { 1261 LogDebug("%s", __FUNCTION__); 1262 return result; 1263 } 1264 1265 c->blob_size = LE_16(c->blob_size); 1266 DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0); 1267 1268 /* vendor data size */ 1269 if ((result = read_data(fd, &c->vendor_data_size, sizeof(UINT32)))) { 1270 LogDebug("%s", __FUNCTION__); 1271 return result; 1272 } 1273 c->vendor_data_size = LE_32(c->vendor_data_size); 1274 1275 /* cache flags */ 1276 if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) { 1277 LogDebug("%s", __FUNCTION__); 1278 return result; 1279 } 1280 c->flags = LE_16(c->flags); 1281 1282 if (c->pub_data_size == pub_size) { 1283 /* read in the pub key */ 1284 if ((result = read_data(fd, blob, c->pub_data_size))) { 1285 LogDebug("%s", __FUNCTION__); 1286 return result; 1287 } 1288 1289 if (!memcmp(blob, pub, pub_size)) 1290 break; 1291 } 1292 1293 /* fast forward over the blob */ 1294 offset = lseek(fd, c->blob_size, SEEK_CUR); 1295 if (offset == ((off_t)-1)) { 1296 LogDebug("lseek: %s", strerror(errno)); 1297 return TSPERR(TSS_E_INTERNAL_ERROR); 1298 } 1299 1300 /* ignore vendor data */ 1301 } 1302 1303 return TSS_SUCCESS; 1304 } 1305