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