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
get_file()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
put_file(int fd)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
close_file(int fd)109 close_file(int fd)
110 {
111 close(fd);
112 system_ps_fd = -1;
113 }
114
115 TSS_RESULT
psfile_get_parent_uuid_by_uuid(int fd,TSS_UUID * uuid,TSS_UUID * ret_uuid)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
psfile_get_key_by_uuid(int fd,TSS_UUID * uuid,BYTE * ret_buffer,UINT16 * ret_buffer_size)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
psfile_get_key_by_cache_entry(int fd,struct key_disk_cache * c,BYTE * ret_buffer,UINT16 * ret_buffer_size)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
psfile_get_vendor_data(int fd,struct key_disk_cache * c,UINT32 * size,BYTE ** data)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
psfile_get_ps_type_by_uuid(int fd,TSS_UUID * uuid,UINT32 * ret_ps_type)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
psfile_is_pub_registered(int fd,TCPA_STORE_PUBKEY * pub,TSS_BOOL * is_reg)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
psfile_get_uuid_by_pub(int fd,TCPA_STORE_PUBKEY * pub,TSS_UUID ** ret_uuid)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
psfile_get_key_by_pub(int fd,TCPA_STORE_PUBKEY * pub,UINT32 * size,BYTE ** ret_key)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
psfile_write_key(int fd,TSS_UUID * uuid,TSS_UUID * parent_uuid,UINT32 * parent_ps,BYTE * vendor_data,UINT32 vendor_size,BYTE * key_blob,UINT16 key_blob_size)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
psfile_remove_key(int fd,struct key_disk_cache * c)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