xref: /netbsd-src/crypto/external/cpl/trousers/dist/src/tcs/ps/tcsps.c (revision 1cebe59da2b9fbff2d2acd9c253d00a9ee60e9eb)
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