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 <sys/types.h> 18 #include <sys/file.h> 19 #include <sys/stat.h> 20 #if defined (HAVE_BYTEORDER_H) 21 #include <sys/byteorder.h> 22 #elif defined (HTOLE_DEFINED) 23 24 #ifndef __APPLE__ 25 #include <endian.h> 26 #else 27 #include "portable_endian.h" 28 #endif 29 30 #define LE_16 htole16 31 #define LE_32 htole32 32 #define LE_64 htole64 33 #else 34 #define LE_16(x) (x) 35 #define LE_32(x) (x) 36 #define LE_64(x) (x) 37 #endif 38 #include <assert.h> 39 #include <fcntl.h> 40 #include <limits.h> 41 42 #include "trousers/tss.h" 43 #include "trousers_types.h" 44 #include "tcsps.h" 45 #include "tcs_tsp.h" 46 #include "tcs_utils.h" 47 #include "capabilities.h" 48 #include "tcslog.h" 49 #include "tcsd_wrap.h" 50 #include "tcsd.h" 51 52 int system_ps_fd = -1; 53 MUTEX_DECLARE(disk_cache_lock); 54 55 static struct flock fl; 56 57 int 58 get_file() 59 { 60 int rc; 61 /* check the global file handle first. If it exists, lock it and return */ 62 if (system_ps_fd != -1) { 63 int rc = 0; 64 65 fl.l_type = F_WRLCK; 66 if ((rc = fcntl(system_ps_fd, F_SETLKW, &fl))) { 67 LogError("failed to get system PS lock: %s", strerror(errno)); 68 return -1; 69 } 70 71 return system_ps_fd; 72 } 73 74 /* open and lock the file */ 75 system_ps_fd = open(tcsd_options.system_ps_file, O_CREAT|O_RDWR, 0600); 76 if (system_ps_fd < 0) { 77 LogError("system PS: open() of %s failed: %s", 78 tcsd_options.system_ps_file, strerror(errno)); 79 return -1; 80 } 81 82 fl.l_type = F_WRLCK; 83 if ((rc = fcntl(system_ps_fd, F_SETLKW, &fl))) { 84 LogError("failed to get system PS lock of file %s: %s", 85 tcsd_options.system_ps_file, strerror(errno)); 86 return -1; 87 } 88 89 return system_ps_fd; 90 } 91 92 int 93 put_file(int fd) 94 { 95 int rc = 0; 96 /* release the file lock */ 97 98 fl.l_type = F_UNLCK; 99 if ((rc = fcntl(fd, F_SETLKW, &fl))) { 100 LogError("failed to unlock system PS file: %s", 101 strerror(errno)); 102 return -1; 103 } 104 105 return rc; 106 } 107 108 void 109 close_file(int fd) 110 { 111 close(fd); 112 system_ps_fd = -1; 113 } 114 115 TSS_RESULT 116 psfile_get_parent_uuid_by_uuid(int fd, TSS_UUID *uuid, TSS_UUID *ret_uuid) 117 { 118 int rc; 119 UINT32 file_offset = 0; 120 struct key_disk_cache *tmp; 121 122 MUTEX_LOCK(disk_cache_lock); 123 tmp = key_disk_cache_head; 124 125 while (tmp) { 126 if (memcmp(uuid, &tmp->uuid, sizeof(TSS_UUID)) || !(tmp->flags & CACHE_FLAG_VALID)) { 127 tmp = tmp->next; 128 continue; 129 } 130 131 /* jump to the location of the parent uuid */ 132 file_offset = TSSPS_PARENT_UUID_OFFSET(tmp); 133 134 rc = lseek(fd, file_offset, SEEK_SET); 135 if (rc == ((off_t) - 1)) { 136 LogError("lseek: %s", strerror(errno)); 137 MUTEX_UNLOCK(disk_cache_lock); 138 return -1; 139 } 140 141 if ((rc = read_data(fd, ret_uuid, sizeof(TSS_UUID)))) { 142 LogError("%s", __FUNCTION__); 143 MUTEX_UNLOCK(disk_cache_lock); 144 return rc; 145 } 146 147 MUTEX_UNLOCK(disk_cache_lock); 148 return TSS_SUCCESS; 149 } 150 MUTEX_UNLOCK(disk_cache_lock); 151 /* key not found */ 152 return -2; 153 } 154 155 /* 156 * return a key blob from PS given a uuid 157 */ 158 TSS_RESULT 159 psfile_get_key_by_uuid(int fd, TSS_UUID *uuid, BYTE *ret_buffer, UINT16 *ret_buffer_size) 160 { 161 int rc; 162 UINT32 file_offset = 0; 163 struct key_disk_cache *tmp; 164 165 MUTEX_LOCK(disk_cache_lock); 166 tmp = key_disk_cache_head; 167 168 while (tmp) { 169 if (memcmp(uuid, &tmp->uuid, sizeof(TSS_UUID)) || !(tmp->flags & CACHE_FLAG_VALID)) { 170 tmp = tmp->next; 171 continue; 172 } 173 174 /* jump to the location of the key blob */ 175 file_offset = TSSPS_BLOB_DATA_OFFSET(tmp); 176 177 rc = lseek(fd, file_offset, SEEK_SET); 178 if (rc == ((off_t) - 1)) { 179 LogError("lseek: %s", strerror(errno)); 180 MUTEX_UNLOCK(disk_cache_lock); 181 return TCSERR(TSS_E_INTERNAL_ERROR); 182 } 183 184 /* we found the key; file ptr is pointing at the blob */ 185 if (*ret_buffer_size < tmp->blob_size) { 186 /* not enough room */ 187 MUTEX_UNLOCK(disk_cache_lock); 188 return TCSERR(TSS_E_FAIL); 189 } 190 191 if ((rc = read_data(fd, ret_buffer, tmp->blob_size))) { 192 LogError("%s", __FUNCTION__); 193 MUTEX_UNLOCK(disk_cache_lock); 194 return rc; 195 } 196 *ret_buffer_size = tmp->blob_size; 197 LogDebugUnrollKey(ret_buffer); 198 MUTEX_UNLOCK(disk_cache_lock); 199 return TSS_SUCCESS; 200 } 201 MUTEX_UNLOCK(disk_cache_lock); 202 /* key not found */ 203 return TCSERR(TSS_E_FAIL); 204 } 205 206 /* 207 * return a key blob from PS given its cache entry. The disk cache must be 208 * locked by the caller. 209 */ 210 TSS_RESULT 211 psfile_get_key_by_cache_entry(int fd, struct key_disk_cache *c, BYTE *ret_buffer, 212 UINT16 *ret_buffer_size) 213 { 214 int rc; 215 UINT32 file_offset = 0; 216 217 /* jump to the location of the key blob */ 218 file_offset = TSSPS_BLOB_DATA_OFFSET(c); 219 220 rc = lseek(fd, file_offset, SEEK_SET); 221 if (rc == ((off_t) - 1)) { 222 LogError("lseek: %s", strerror(errno)); 223 return TCSERR(TSS_E_INTERNAL_ERROR); 224 } 225 226 /* we found the key; file ptr is pointing at the blob */ 227 if (*ret_buffer_size < c->blob_size) { 228 /* not enough room */ 229 LogError("%s: Buf size too small. Needed %d bytes, passed %d", __FUNCTION__, 230 c->blob_size, *ret_buffer_size); 231 return TCSERR(TSS_E_INTERNAL_ERROR); 232 } 233 234 if ((rc = read_data(fd, ret_buffer, c->blob_size))) { 235 LogError("%s: error reading %d bytes", __FUNCTION__, c->blob_size); 236 return TCSERR(TSS_E_INTERNAL_ERROR); 237 } 238 *ret_buffer_size = c->blob_size; 239 240 return TSS_SUCCESS; 241 } 242 243 /* 244 * return the vendor data from PS given its cache entry. The disk cache must be 245 * locked by the caller. 246 */ 247 TSS_RESULT 248 psfile_get_vendor_data(int fd, struct key_disk_cache *c, UINT32 *size, BYTE **data) 249 { 250 int rc; 251 UINT32 file_offset; 252 253 /* jump to the location of the data */ 254 file_offset = TSSPS_VENDOR_DATA_OFFSET(c); 255 256 rc = lseek(fd, file_offset, SEEK_SET); 257 if (rc == ((off_t) - 1)) { 258 LogError("lseek: %s", strerror(errno)); 259 return TCSERR(TSS_E_INTERNAL_ERROR); 260 } 261 262 if ((*data = malloc(c->vendor_data_size)) == NULL) { 263 LogError("malloc of %u bytes failed", c->vendor_data_size); 264 return TCSERR(TSS_E_OUTOFMEMORY); 265 } 266 267 if ((rc = read_data(fd, *data, c->vendor_data_size))) { 268 LogError("%s: error reading %u bytes", __FUNCTION__, c->vendor_data_size); 269 free(*data); 270 *data = NULL; 271 return TCSERR(TSS_E_INTERNAL_ERROR); 272 } 273 *size = c->vendor_data_size; 274 275 return TSS_SUCCESS; 276 } 277 278 TSS_RESULT 279 psfile_get_ps_type_by_uuid(int fd, TSS_UUID *uuid, UINT32 *ret_ps_type) 280 { 281 struct key_disk_cache *tmp; 282 283 MUTEX_LOCK(disk_cache_lock); 284 tmp = key_disk_cache_head; 285 286 while (tmp) { 287 if (memcmp(uuid, &tmp->uuid, sizeof(TSS_UUID)) || 288 !(tmp->flags & CACHE_FLAG_VALID)) { 289 tmp = tmp->next; 290 continue; 291 } 292 293 if (tmp->flags & CACHE_FLAG_PARENT_PS_SYSTEM) { 294 *ret_ps_type = TSS_PS_TYPE_SYSTEM; 295 goto done; 296 } else 297 break; 298 } 299 300 *ret_ps_type = TSS_PS_TYPE_USER; 301 done: 302 MUTEX_UNLOCK(disk_cache_lock); 303 return TSS_SUCCESS; 304 } 305 306 TSS_RESULT 307 psfile_is_pub_registered(int fd, TCPA_STORE_PUBKEY *pub, TSS_BOOL *is_reg) 308 { 309 int rc; 310 UINT32 file_offset = 0; 311 struct key_disk_cache *tmp; 312 char tmp_buffer[2048]; 313 314 MUTEX_LOCK(disk_cache_lock); 315 tmp = key_disk_cache_head; 316 317 while (tmp) { 318 /* if the key is of the wrong size or is invalid, try the next one */ 319 if (pub->keyLength != tmp->pub_data_size || !(tmp->flags & CACHE_FLAG_VALID)) { 320 tmp = tmp->next; 321 continue; 322 } 323 324 /* we have a valid key with the same key size as the one we're looking for. 325 * grab the pub key data off disk and compare it. */ 326 327 /* jump to the location of the public key */ 328 file_offset = TSSPS_PUB_DATA_OFFSET(tmp); 329 330 rc = lseek(fd, file_offset, SEEK_SET); 331 if (rc == ((off_t) - 1)) { 332 LogError("lseek: %s", strerror(errno)); 333 MUTEX_UNLOCK(disk_cache_lock); 334 return TCSERR(TSS_E_INTERNAL_ERROR); 335 } 336 337 DBG_ASSERT(tmp->pub_data_size < 2048); 338 339 /* read in the key */ 340 if ((rc = read_data(fd, tmp_buffer, tmp->pub_data_size))) { 341 LogError("%s", __FUNCTION__); 342 MUTEX_UNLOCK(disk_cache_lock); 343 return rc; 344 } 345 346 /* do the compare */ 347 if (memcmp(tmp_buffer, pub->key, tmp->pub_data_size)) { 348 tmp = tmp->next; 349 continue; 350 } 351 352 /* the key matches, copy the uuid out */ 353 *is_reg = TRUE; 354 355 MUTEX_UNLOCK(disk_cache_lock); 356 return TSS_SUCCESS; 357 } 358 MUTEX_UNLOCK(disk_cache_lock); 359 /* key not found */ 360 *is_reg = FALSE; 361 return TSS_SUCCESS; 362 } 363 364 365 TSS_RESULT 366 psfile_get_uuid_by_pub(int fd, TCPA_STORE_PUBKEY *pub, TSS_UUID **ret_uuid) 367 { 368 int rc; 369 UINT32 file_offset = 0; 370 struct key_disk_cache *tmp; 371 char tmp_buffer[2048]; 372 373 MUTEX_LOCK(disk_cache_lock); 374 tmp = key_disk_cache_head; 375 376 while (tmp) { 377 /* if the key is of the wrong size or is invalid, try the next one */ 378 if (pub->keyLength != tmp->pub_data_size || !(tmp->flags & CACHE_FLAG_VALID)) { 379 tmp = tmp->next; 380 continue; 381 } 382 383 /* we have a valid key with the same key size as the one we're looking for. 384 * grab the pub key data off disk and compare it. */ 385 386 /* jump to the location of the public key */ 387 file_offset = TSSPS_PUB_DATA_OFFSET(tmp); 388 389 rc = lseek(fd, file_offset, SEEK_SET); 390 if (rc == ((off_t) - 1)) { 391 LogError("lseek: %s", strerror(errno)); 392 MUTEX_UNLOCK(disk_cache_lock); 393 return TCSERR(TSS_E_INTERNAL_ERROR); 394 } 395 396 DBG_ASSERT(tmp->pub_data_size < 2048); 397 398 if (tmp->pub_data_size > sizeof(tmp_buffer)) { 399 LogError("Source buffer size too big! Size: %d", 400 tmp->pub_data_size); 401 MUTEX_UNLOCK(disk_cache_lock); 402 return TCSERR(TSS_E_INTERNAL_ERROR); 403 } 404 /* read in the key */ 405 if ((rc = read_data(fd, tmp_buffer, tmp->pub_data_size))) { 406 LogError("%s", __FUNCTION__); 407 MUTEX_UNLOCK(disk_cache_lock); 408 return rc; 409 } 410 411 /* do the compare */ 412 if (memcmp(tmp_buffer, pub->key, tmp->pub_data_size)) { 413 tmp = tmp->next; 414 continue; 415 } 416 417 *ret_uuid = (TSS_UUID *)malloc(sizeof(TSS_UUID)); 418 if (*ret_uuid == NULL) { 419 LogError("malloc of %zd bytes failed.", sizeof(TSS_UUID)); 420 MUTEX_UNLOCK(disk_cache_lock); 421 return TCSERR(TSS_E_OUTOFMEMORY); 422 } 423 424 /* the key matches, copy the uuid out */ 425 memcpy(*ret_uuid, &tmp->uuid, sizeof(TSS_UUID)); 426 427 MUTEX_UNLOCK(disk_cache_lock); 428 return TSS_SUCCESS; 429 } 430 MUTEX_UNLOCK(disk_cache_lock); 431 /* key not found */ 432 return TCSERR(TSS_E_PS_KEY_NOTFOUND); 433 } 434 435 TSS_RESULT 436 psfile_get_key_by_pub(int fd, TCPA_STORE_PUBKEY *pub, UINT32 *size, BYTE **ret_key) 437 { 438 int rc; 439 UINT32 file_offset = 0; 440 struct key_disk_cache *tmp; 441 BYTE tmp_buffer[4096]; 442 443 MUTEX_LOCK(disk_cache_lock); 444 tmp = key_disk_cache_head; 445 446 while (tmp) { 447 /* if the key is of the wrong size or is invalid, try the next one */ 448 if (pub->keyLength != tmp->pub_data_size || !(tmp->flags & CACHE_FLAG_VALID)) { 449 tmp = tmp->next; 450 continue; 451 } 452 453 /* we have a valid key with the same key size as the one we're looking for. 454 * grab the pub key data off disk and compare it. */ 455 456 /* jump to the location of the public key */ 457 file_offset = TSSPS_PUB_DATA_OFFSET(tmp); 458 459 rc = lseek(fd, file_offset, SEEK_SET); 460 if (rc == ((off_t) - 1)) { 461 LogError("lseek: %s", strerror(errno)); 462 MUTEX_UNLOCK(disk_cache_lock); 463 return TCSERR(TSS_E_INTERNAL_ERROR); 464 } 465 466 DBG_ASSERT(tmp->pub_data_size < 2048); 467 if (tmp->pub_data_size > sizeof(tmp_buffer)) { 468 LogError("Source buffer size too big! Size: %d", 469 tmp->pub_data_size); 470 MUTEX_UNLOCK(disk_cache_lock); 471 return TCSERR(TSS_E_INTERNAL_ERROR); 472 } 473 474 /* read in the key */ 475 if ((rc = read_data(fd, tmp_buffer, tmp->pub_data_size))) { 476 LogError("%s", __FUNCTION__); 477 MUTEX_UNLOCK(disk_cache_lock); 478 return rc; 479 } 480 481 /* do the compare */ 482 if (memcmp(tmp_buffer, pub->key, tmp->pub_data_size)) { 483 tmp = tmp->next; 484 continue; 485 } 486 487 /* jump to the location of the key blob */ 488 file_offset = TSSPS_BLOB_DATA_OFFSET(tmp); 489 490 rc = lseek(fd, file_offset, SEEK_SET); 491 if (rc == ((off_t) - 1)) { 492 LogError("lseek: %s", strerror(errno)); 493 MUTEX_UNLOCK(disk_cache_lock); 494 return TCSERR(TSS_E_INTERNAL_ERROR); 495 } 496 497 DBG_ASSERT(tmp->blob_size < 4096); 498 if (tmp->blob_size > sizeof(tmp_buffer)) { 499 LogError("Blob size greater than 4096! Size: %d", 500 tmp->blob_size); 501 MUTEX_UNLOCK(disk_cache_lock); 502 return TCSERR(TSS_E_INTERNAL_ERROR); 503 } 504 505 /* read in the key blob */ 506 if ((rc = read_data(fd, tmp_buffer, tmp->blob_size))) { 507 LogError("%s", __FUNCTION__); 508 MUTEX_UNLOCK(disk_cache_lock); 509 return rc; 510 } 511 512 *ret_key = malloc(tmp->blob_size); 513 if (*ret_key == NULL) { 514 LogError("malloc of %d bytes failed.", tmp->blob_size); 515 MUTEX_UNLOCK(disk_cache_lock); 516 return TCSERR(TSS_E_OUTOFMEMORY); 517 } 518 519 memcpy(*ret_key, tmp_buffer, tmp->blob_size); 520 *size = tmp->blob_size; 521 522 MUTEX_UNLOCK(disk_cache_lock); 523 return rc; 524 } 525 MUTEX_UNLOCK(disk_cache_lock); 526 /* key not found */ 527 return -2; 528 } 529 530 /* 531 * disk store format: 532 * 533 * TrouSerS 0.2.0 and before: 534 * Version 0: cached? 535 * [UINT32 num_keys_on_disk] 536 * [TSS_UUID uuid0 ] yes 537 * [TSS_UUID uuid_parent0 ] yes 538 * [UINT16 pub_data_size0 ] yes 539 * [UINT16 blob_size0 ] yes 540 * [UINT16 cache_flags0 ] yes 541 * [BYTE[] pub_data0 ] 542 * [BYTE[] blob0 ] 543 * [...] 544 * 545 * TrouSerS 0.2.1+ 546 * Version 1: cached? 547 * [BYTE PS version = '\1'] 548 * [UINT32 num_keys_on_disk ] 549 * [TSS_UUID uuid0 ] yes 550 * [TSS_UUID uuid_parent0 ] yes 551 * [UINT16 pub_data_size0 ] yes 552 * [UINT16 blob_size0 ] yes 553 * [UINT32 vendor_data_size0] yes 554 * [UINT16 cache_flags0 ] yes 555 * [BYTE[] pub_data0 ] 556 * [BYTE[] blob0 ] 557 * [BYTE[] vendor_data0 ] 558 * [...] 559 * 560 */ 561 TSS_RESULT 562 psfile_write_key(int fd, 563 TSS_UUID *uuid, 564 TSS_UUID *parent_uuid, 565 UINT32 *parent_ps, 566 BYTE *vendor_data, 567 UINT32 vendor_size, 568 BYTE *key_blob, 569 UINT16 key_blob_size) 570 { 571 TSS_KEY key; 572 UINT16 pub_key_size, cache_flags = CACHE_FLAG_VALID; 573 UINT64 offset; 574 int rc = 0; 575 576 /* leaving the cache flag for parent ps type as 0 implies TSS_PS_TYPE_USER */ 577 if (*parent_ps == TSS_PS_TYPE_SYSTEM) 578 cache_flags |= CACHE_FLAG_PARENT_PS_SYSTEM; 579 580 /* Unload the blob to get the public key */ 581 offset = 0; 582 if ((rc = UnloadBlob_TSS_KEY(&offset, key_blob, &key))) 583 return rc; 584 585 pub_key_size = key.pubKey.keyLength; 586 587 if ((rc = write_key_init(fd, pub_key_size, key_blob_size, vendor_size)) < 0) 588 goto done; 589 590 /* offset now holds the number of bytes from the beginning of the file 591 * the key will be stored at 592 */ 593 offset = rc; 594 595 #ifdef TSS_DEBUG 596 if (offset == 0) 597 LogDebug("ERROR: key being written with offset 0!!"); 598 #endif 599 600 /* [TSS_UUID uuid0 ] yes */ 601 if ((rc = write_data(fd, (void *)uuid, sizeof(TSS_UUID)))) { 602 LogError("%s", __FUNCTION__); 603 goto done; 604 } 605 606 /* [TSS_UUID uuid_parent0 ] yes */ 607 if ((rc = write_data(fd, (void *)parent_uuid, sizeof(TSS_UUID)))) { 608 LogError("%s", __FUNCTION__); 609 goto done; 610 } 611 612 /* [UINT16 pub_data_size0 ] yes */ 613 pub_key_size = LE_16(pub_key_size); 614 if ((rc = write_data(fd, &pub_key_size, sizeof(UINT16)))) { 615 LogError("%s", __FUNCTION__); 616 goto done; 617 } 618 /* Swap it back for later */ 619 pub_key_size = LE_16(pub_key_size); 620 621 /* [UINT16 blob_size0 ] yes */ 622 key_blob_size = LE_16(key_blob_size); 623 if ((rc = write_data(fd, &key_blob_size, sizeof(UINT16)))) { 624 LogError("%s", __FUNCTION__); 625 goto done; 626 } 627 /* Swap it back for later */ 628 key_blob_size = LE_16(key_blob_size); 629 630 /* [UINT32 vendor_data_size0 ] yes */ 631 vendor_size = LE_32(vendor_size); 632 if ((rc = write_data(fd, &vendor_size, sizeof(UINT32)))) { 633 LogError("%s", __FUNCTION__); 634 goto done; 635 } 636 /* Swap it back for later */ 637 vendor_size = LE_32(vendor_size); 638 639 /* [UINT16 cache_flags0 ] yes */ 640 cache_flags = LE_16(cache_flags); 641 if ((rc = write_data(fd, &cache_flags, sizeof(UINT16)))) { 642 LogError("%s", __FUNCTION__); 643 goto done; 644 } 645 /* Swap it back for later */ 646 cache_flags = LE_16(cache_flags); 647 648 /* [BYTE[] pub_data0 ] no */ 649 if ((rc = write_data(fd, (void *)key.pubKey.key, pub_key_size))) { 650 LogError("%s", __FUNCTION__); 651 goto done; 652 } 653 654 /* [BYTE[] blob0 ] no */ 655 if ((rc = write_data(fd, (void *)key_blob, key_blob_size))) { 656 LogError("%s", __FUNCTION__); 657 goto done; 658 } 659 660 /* [BYTE[] vendor_data0 ] no */ 661 if (vendor_size > 0) { 662 if ((rc = write_data(fd, (void *)vendor_data, vendor_size))) { 663 LogError("%s", __FUNCTION__); 664 goto done; 665 } 666 } 667 668 if ((rc = cache_key((UINT32)offset, cache_flags, uuid, parent_uuid, pub_key_size, 669 key_blob_size, vendor_size))) 670 goto done; 671 done: 672 destroy_key_refs(&key); 673 674 return rc; 675 } 676 677 TSS_RESULT 678 psfile_remove_key(int fd, struct key_disk_cache *c) 679 { 680 TSS_RESULT result; 681 UINT32 head_offset = 0, tail_offset, num_keys; 682 BYTE buf[4096]; 683 struct stat stat_buf; 684 int rc, size = 0; 685 686 if ((rc = fstat(fd, &stat_buf)) != 0) { 687 LogError("fstat: %s", strerror(errno)); 688 return TSS_E_INTERNAL_ERROR; 689 } 690 691 /* head_offset is the offset the beginning of the key */ 692 head_offset = TSSPS_UUID_OFFSET(c); 693 694 /* tail_offset is the offset the beginning of the next key */ 695 tail_offset = TSSPS_VENDOR_DATA_OFFSET(c) + c->vendor_data_size; 696 697 rc = lseek(fd, tail_offset, SEEK_SET); 698 if (rc == ((off_t) - 1)) { 699 LogError("lseek: %s", strerror(errno)); 700 return TCSERR(TSS_E_INTERNAL_ERROR); 701 } 702 703 /* read in from tail, write out to head to fill the gap */ 704 while ((rc = read(fd, buf, sizeof(buf))) > 0) { 705 size = rc; 706 tail_offset += size; 707 708 /* set the file pointer to where we want to write */ 709 rc = lseek(fd, head_offset, SEEK_SET); 710 if (rc == ((off_t) - 1)) { 711 LogError("lseek: %s", strerror(errno)); 712 return TCSERR(TSS_E_INTERNAL_ERROR); 713 } 714 715 /* write the data */ 716 if ((result = write_data(fd, (void *)buf, size))) { 717 LogError("%s", __FUNCTION__); 718 return result; 719 } 720 head_offset += size; 721 722 /* set the file pointer to where we want to read in the next 723 * loop */ 724 rc = lseek(fd, tail_offset, SEEK_SET); 725 if (rc == ((off_t) - 1)) { 726 LogError("lseek: %s", strerror(errno)); 727 return TCSERR(TSS_E_INTERNAL_ERROR); 728 } 729 } 730 731 if (rc < 0) { 732 LogError("read: %s", strerror(errno)); 733 return TCSERR(TSS_E_INTERNAL_ERROR); 734 } 735 736 /* set the file pointer to where we want to write */ 737 rc = lseek(fd, head_offset, SEEK_SET); 738 if (rc == ((off_t) - 1)) { 739 LogError("lseek: %s", strerror(errno)); 740 return TCSERR(TSS_E_INTERNAL_ERROR); 741 } 742 743 /* head_offset now contains a pointer to where we want to truncate the 744 * file. Zero out the old tail end of the file and truncate it. */ 745 746 memset(buf, 0, sizeof(buf)); 747 748 /* Zero out the old tail end of the file */ 749 if ((result = write_data(fd, (void *)buf, tail_offset - head_offset))) { 750 LogError("%s", __FUNCTION__); 751 return result; 752 } 753 754 if ((rc = ftruncate(fd, head_offset)) < 0) { 755 LogError("ftruncate: %s", strerror(errno)); 756 return TCSERR(TSS_E_INTERNAL_ERROR); 757 } 758 759 /* we succeeded in removing a key from the disk. Decrement the number 760 * of keys in the file */ 761 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET); 762 if (rc == ((off_t) - 1)) { 763 LogError("lseek: %s", strerror(errno)); 764 return TCSERR(TSS_E_INTERNAL_ERROR); 765 } 766 767 rc = read(fd, &num_keys, sizeof(UINT32)); 768 num_keys = LE_32(num_keys); 769 if (rc != sizeof(UINT32)) { 770 LogError("read of %zd bytes: %s", sizeof(UINT32), strerror(errno)); 771 return TCSERR(TSS_E_INTERNAL_ERROR); 772 } 773 774 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET); 775 if (rc == ((off_t) - 1)) { 776 LogError("lseek: %s", strerror(errno)); 777 return TCSERR(TSS_E_INTERNAL_ERROR); 778 } 779 780 /* decrement, then write back out to disk */ 781 num_keys--; 782 783 num_keys = LE_32(num_keys); 784 if ((result = write_data(fd, (void *)&num_keys, sizeof(UINT32)))) { 785 LogError("%s", __FUNCTION__); 786 return result; 787 } 788 789 return TSS_SUCCESS; 790 } 791