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