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