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