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 <pwd.h>
18 #include <sys/types.h>
19 #include <sys/file.h>
20 #include <sys/stat.h>
21 #include <assert.h>
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <netdb.h>
25 #if defined (HAVE_BYTEORDER_H)
26 #include <sys/byteorder.h>
27 #elif defined (HTOLE_DEFINED)
28 
29 #ifndef __APPLE__
30 #include <endian.h>
31 #else
32 #include "portable_endian.h"
33 #endif
34 
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 
44 #include "trousers/tss.h"
45 #include "trousers/trousers.h"
46 #include "trousers_types.h"
47 #include "tcs_tsp.h"
48 #include "spi_utils.h"
49 #include "tspps.h"
50 #include "tsplog.h"
51 
52 static int user_ps_fd = -1;
53 static MUTEX_DECLARE_INIT(user_ps_lock);
54 #if (defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__))
55 static MUTEX_DECLARE_INIT(user_ps_path);
56 #endif
57 static struct flock fl;
58 
59 
60 /*
61  * Determine the default path to the persistent storage file and create it if it doesn't exist.
62  */
63 TSS_RESULT
get_user_ps_path(char ** file)64 get_user_ps_path(char **file)
65 {
66           TSS_RESULT result;
67           char *file_name = NULL, *home_dir = NULL;
68           struct passwd *pwp;
69 #if (defined (__linux) || defined (linux) || defined(__GLIBC__))
70           struct passwd pw;
71 #endif
72           struct stat stat_buf;
73           char buf[PASSWD_BUFSIZE];
74           uid_t euid;
75           int rc;
76 
77           if ((file_name = getenv("TSS_USER_PS_FILE"))) {
78                     *file = strdup(file_name);
79                     return (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY);
80           }
81 #if (defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__))
82           MUTEX_LOCK(user_ps_path);
83 #endif
84 
85           euid = geteuid();
86 
87 #if defined (SOLARIS)
88           /*
89          * Solaris keeps user PS in a local directory instead of
90          * in the user's home directory, which may be shared
91          * by multiple systems.
92          *
93          * The directory path on Solaris is /var/tpm/userps/[EUID]/
94          */
95         rc = snprintf(buf, sizeof (buf), "%s/%d", TSS_USER_PS_DIR, euid);
96 #else
97           setpwent();
98           while (1) {
99 #if (defined (__linux) || defined (linux) || defined(__GLIBC__))
100                     rc = getpwent_r(&pw, buf, PASSWD_BUFSIZE, &pwp);
101                     if (rc) {
102                               LogDebugFn("USER PS: Error getting path to home directory: getpwent_r: %s",
103                                            strerror(rc));
104                               endpwent();
105                               return TSPERR(TSS_E_INTERNAL_ERROR);
106                     }
107 
108 #elif (defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__))
109                     if ((pwp = getpwent()) == NULL) {
110                               LogDebugFn("USER PS: Error getting path to home directory: getpwent: %s",
111                                    strerror(rc));
112                               endpwent();
113                               MUTEX_UNLOCK(user_ps_path);
114                               return TSPERR(TSS_E_INTERNAL_ERROR);
115                     }
116 #endif
117                     if (euid == pwp->pw_uid) {
118                         home_dir = strdup(pwp->pw_dir);
119                         break;
120                 }
121         }
122         endpwent();
123 
124           if (!home_dir)
125                     return TSPERR(TSS_E_OUTOFMEMORY);
126 
127           /* Tack on TSS_USER_PS_DIR and see if it exists */
128           rc = snprintf(buf, sizeof (buf), "%s/%s", home_dir, TSS_USER_PS_DIR);
129 #endif /* SOLARIS */
130           if (rc == sizeof (buf)) {
131                     LogDebugFn("USER PS: Path to file too long! (> %d bytes)", PASSWD_BUFSIZE);
132                     result = TSPERR(TSS_E_INTERNAL_ERROR);
133                     goto done;
134           }
135 
136           errno = 0;
137           if ((rc = stat(buf, &stat_buf)) == -1) {
138                     if (errno == ENOENT) {
139                               errno = 0;
140                               /* Create the user's ps directory if it is not there. */
141                               if ((rc = mkdir(buf, 0700)) == -1) {
142                                         LogDebugFn("USER PS: Error creating dir: %s: %s", buf,
143                                                      strerror(errno));
144                                         result = TSPERR(TSS_E_INTERNAL_ERROR);
145                                         goto done;
146                               }
147                     } else {
148                               LogDebugFn("USER PS: Error stating dir: %s: %s", buf, strerror(errno));
149                               result = TSPERR(TSS_E_INTERNAL_ERROR);
150                               goto done;
151                     }
152           }
153 
154           /* Directory exists or has been created, return the path to the file */
155 #if defined (SOLARIS)
156           rc = snprintf(buf, sizeof (buf), "%s/%d/%s", TSS_USER_PS_DIR, euid,
157                           TSS_USER_PS_FILE);
158 #else
159           rc = snprintf(buf, sizeof (buf), "%s/%s/%s", home_dir, TSS_USER_PS_DIR,
160                           TSS_USER_PS_FILE);
161 #endif
162           if (rc == sizeof (buf)) {
163                     LogDebugFn("USER PS: Path to file too long! (> %zd bytes)", sizeof (buf));
164           } else
165                     *file = strdup(buf);
166 
167           result = (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY);
168 done:
169           free(home_dir);
170           return result;
171 }
172 
173 TSS_RESULT
get_file(int * fd)174 get_file(int *fd)
175 {
176           TSS_RESULT result;
177           int rc = 0;
178           char *file_name = NULL;
179 
180           MUTEX_LOCK(user_ps_lock);
181 
182           /* check the global file handle first.  If it exists, lock it and return */
183           if (user_ps_fd != -1) {
184                     fl.l_type = F_WRLCK;
185                     if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) {
186                               LogDebug("USER PS: failed to lock file: %s", strerror(errno));
187                               MUTEX_UNLOCK(user_ps_lock);
188                               return TSPERR(TSS_E_INTERNAL_ERROR);
189                     }
190                     *fd = user_ps_fd;
191                     return TSS_SUCCESS;
192           }
193 
194           /* open and lock the file */
195           if ((result = get_user_ps_path(&file_name))) {
196                     LogDebugFn("USER PS: error getting file path");
197                     MUTEX_UNLOCK(user_ps_lock);
198                     return result;
199           }
200 
201           user_ps_fd = open(file_name, O_CREAT|O_RDWR, 0600);
202           if (user_ps_fd < 0) {
203                     LogDebug("USER PS: open of %s failed: %s", file_name, strerror(errno));
204                     free(file_name);
205                     MUTEX_UNLOCK(user_ps_lock);
206                     return TSPERR(TSS_E_INTERNAL_ERROR);
207           }
208           fl.l_type = F_WRLCK;
209           if ((rc = fcntl(user_ps_fd, F_SETLKW, &fl))) {
210                     LogDebug("USER PS: failed to get lock of %s: %s", file_name, strerror(errno));
211                     free(file_name);
212                     close(user_ps_fd);
213                     user_ps_fd = -1;
214                     MUTEX_UNLOCK(user_ps_lock);
215                     return TSPERR(TSS_E_INTERNAL_ERROR);
216           }
217 
218           *fd = user_ps_fd;
219           free(file_name);
220           return TSS_SUCCESS;
221 }
222 
223 int
put_file(int fd)224 put_file(int fd)
225 {
226           int rc = 0;
227 
228           fsync(fd);
229 
230           /* release the file lock */
231           fl.l_type = F_UNLCK;
232           if ((rc = fcntl(fd, F_SETLKW, &fl))) {
233                     LogDebug("USER PS: failed to unlock file: %s", strerror(errno));
234                     rc = -1;
235           }
236 
237           MUTEX_UNLOCK(user_ps_lock);
238           return rc;
239 }
240 
241 void
psfile_close(int fd)242 psfile_close(int fd)
243 {
244           close(fd);
245           user_ps_fd = -1;
246           MUTEX_UNLOCK(user_ps_lock);
247 }
248 
249 TSS_RESULT
psfile_is_key_registered(int fd,TSS_UUID * uuid,TSS_BOOL * answer)250 psfile_is_key_registered(int fd, TSS_UUID *uuid, TSS_BOOL *answer)
251 {
252         TSS_RESULT result;
253         struct key_disk_cache tmp;
254 
255           if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)) == TSS_SUCCESS)
256                     *answer = TRUE;
257           else if (result == (TSS_E_PS_KEY_NOTFOUND | TSS_LAYER_TSP))
258                     *answer = FALSE;
259         else
260                 return result;
261 
262         return TSS_SUCCESS;
263 }
264 
265 TSS_RESULT
psfile_get_parent_uuid_by_uuid(int fd,TSS_UUID * uuid,TSS_UUID * ret_uuid)266 psfile_get_parent_uuid_by_uuid(int fd, TSS_UUID *uuid, TSS_UUID *ret_uuid)
267 {
268           TSS_RESULT result;
269         struct key_disk_cache tmp;
270 
271           if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)))
272                     return result;
273 
274           memcpy(ret_uuid, &tmp.parent_uuid, sizeof(TSS_UUID));
275 
276         return TSS_SUCCESS;
277 }
278 
279 TSS_RESULT
psfile_get_parent_ps_type(int fd,TSS_UUID * uuid,UINT32 * type)280 psfile_get_parent_ps_type(int fd, TSS_UUID *uuid, UINT32 *type)
281 {
282           TSS_RESULT result;
283         struct key_disk_cache tmp;
284 
285           if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)))
286                     return result;
287 
288           if (tmp.flags & CACHE_FLAG_PARENT_PS_SYSTEM)
289                     *type = TSS_PS_TYPE_SYSTEM;
290           else
291                     *type = TSS_PS_TYPE_USER;
292 
293         return TSS_SUCCESS;
294 }
295 
296 /*
297  * return a key struct from PS given a uuid
298  */
299 TSS_RESULT
psfile_get_key_by_uuid(int fd,TSS_UUID * uuid,BYTE * key)300 psfile_get_key_by_uuid(int fd, TSS_UUID *uuid, BYTE *key)
301 {
302         int rc;
303           TSS_RESULT result;
304         off_t file_offset;
305         struct key_disk_cache tmp;
306           BYTE buf[4096];
307 
308           if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)))
309                     return result;
310 
311           /* jump to the location of the key blob */
312           file_offset = TSSPS_BLOB_DATA_OFFSET(&tmp);
313 
314           rc = lseek(fd, file_offset, SEEK_SET);
315           if (rc == ((off_t)-1)) {
316                     LogDebugFn("lseek: %s", strerror(errno));
317                     return TSPERR(TSS_E_INTERNAL_ERROR);
318           }
319 
320           if (tmp.blob_size > 4096) {
321                     LogError("Blob size greater than 4096! Size:  %d",
322                                 tmp.blob_size);
323                     return TSPERR(TSS_E_INTERNAL_ERROR);
324           }
325           if ((rc = read_data(fd, buf, tmp.blob_size))) {
326                     LogDebugFn("Blob read from disk failed.");
327                     return rc;
328           }
329 
330           memcpy(key, buf, tmp.blob_size);
331           return TSS_SUCCESS;
332 }
333 
334 /*
335  * return a key struct from PS given a public key
336  */
337 TSS_RESULT
psfile_get_key_by_pub(int fd,TSS_UUID * uuid,UINT32 pub_size,BYTE * pub,BYTE * key)338 psfile_get_key_by_pub(int fd, TSS_UUID *uuid, UINT32 pub_size, BYTE *pub, BYTE *key)
339 {
340         int rc;
341           TSS_RESULT result;
342         off_t file_offset;
343         struct key_disk_cache tmp;
344           BYTE buf[4096];
345 
346           if ((result = psfile_get_cache_entry_by_pub(fd, pub_size, pub, &tmp)))
347                     return result;
348 
349           /* jump to the location of the key blob */
350           file_offset = TSSPS_BLOB_DATA_OFFSET(&tmp);
351 
352           rc = lseek(fd, file_offset, SEEK_SET);
353           if (rc == ((off_t)-1)) {
354                     LogDebugFn("lseek: %s", strerror(errno));
355                     return TSPERR(TSS_E_INTERNAL_ERROR);
356           }
357 
358           if (tmp.blob_size > 4096) {
359                     LogError("Blob size greater than 4096! Size:  %d",
360                                 tmp.blob_size);
361                     return TSPERR(TSS_E_INTERNAL_ERROR);
362           }
363 
364           if ((result = read_data(fd, buf, tmp.blob_size))) {
365                     LogDebugFn("Blob read from disk failed.");
366                     return result;
367           }
368 
369           memcpy(key, buf, tmp.blob_size);
370           memcpy(uuid, &tmp.uuid, sizeof(TSS_UUID));
371 
372           return TSS_SUCCESS;
373 }
374 
375 TSS_RESULT
psfile_get_uuid_by_pub(int fd,UINT32 pub_size,BYTE * pub,TSS_UUID * uuid)376 psfile_get_uuid_by_pub(int fd, UINT32 pub_size, BYTE *pub, TSS_UUID *uuid)
377 {
378           TSS_RESULT result;
379         struct key_disk_cache tmp;
380 
381           if ((result = psfile_get_cache_entry_by_pub(fd, pub_size, pub, &tmp)))
382                     return result;
383 
384           memcpy(uuid, &tmp.uuid, sizeof(TSS_UUID));
385 
386         return TSS_SUCCESS;
387 }
388 
389 TSS_RESULT
psfile_change_num_keys(int fd,BYTE increment)390 psfile_change_num_keys(int fd, BYTE increment)
391 {
392           int rc;
393           TSS_RESULT result;
394           UINT32 num_keys;
395 
396           rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
397           if (rc == ((off_t)-1)) {
398                     LogDebug("lseek: %s", strerror(errno));
399                     return TSPERR(TSS_E_INTERNAL_ERROR);
400           }
401 
402           rc = read(fd, &num_keys, sizeof(UINT32));
403           if (rc != sizeof(UINT32)) {
404                     LogDebug("read of %zd bytes: %s", sizeof(UINT32), strerror(errno));
405                     return TSPERR(TSS_E_INTERNAL_ERROR);
406           }
407           num_keys = LE_32(num_keys);
408 
409           if (increment)
410                     num_keys++;
411           else
412                     num_keys--;
413 
414           rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
415           if (rc == ((off_t)-1)) {
416                     LogDebug("lseek: %s", strerror(errno));
417                     return TSPERR(TSS_E_INTERNAL_ERROR);
418           }
419 
420           num_keys = LE_32(num_keys);
421           if ((result = write_data(fd, (void *)&num_keys, sizeof(UINT32)))) {
422                     LogDebug("%s", __FUNCTION__);
423                     return result;
424           }
425 
426           return TSS_SUCCESS;
427 }
428 
429 /* Write the initial header (number of keys and PS version) to initialize a new file */
430 TSS_RESULT
psfile_write_key_header(int fd)431 psfile_write_key_header(int fd)
432 {
433           int rc;
434           TSS_RESULT result;
435           UINT32 i;
436 
437           rc = lseek(fd, TSSPS_VERSION_OFFSET, SEEK_SET);
438           if (rc == ((off_t)-1)) {
439                     LogDebug("lseek: %s", strerror(errno));
440                     return TSPERR(TSS_E_INTERNAL_ERROR);
441           }
442 
443           i = TSSPS_VERSION;
444         if ((result = write_data(fd, &i, sizeof(BYTE)))) {
445                     LogDebug("%s", __FUNCTION__);
446                     return result;
447           }
448 
449           rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
450           if (rc == ((off_t)-1)) {
451                     LogDebug("lseek: %s", strerror(errno));
452                     return TSPERR(TSS_E_INTERNAL_ERROR);
453           }
454 
455           i = 0;
456         if ((result = write_data(fd, &i, sizeof(UINT32)))) {
457                     LogDebug("%s", __FUNCTION__);
458                     return result;
459           }
460 
461           return TSS_SUCCESS;
462 }
463 
464 /*
465  * disk store format:
466  *
467  * TrouSerS 0.2.1+
468  * Version 1:                  cached?
469  * [BYTE     PS version = '\1']
470  * [UINT32   num_keys_on_disk ]
471  * [TSS_UUID uuid0            ] yes
472  * [TSS_UUID uuid_parent0     ] yes
473  * [UINT16   pub_data_size0   ] yes
474  * [UINT16   blob_size0       ] yes
475  * [UINT32   vendor_data_size0] yes
476  * [UINT16   cache_flags0     ] yes
477  * [BYTE[]   pub_data0        ]
478  * [BYTE[]   blob0            ]
479  * [BYTE[]   vendor_data0     ]
480  * [...]
481  *
482  */
483 TSS_RESULT
psfile_write_key(int fd,TSS_UUID * uuid,TSS_UUID * parent_uuid,UINT32 parent_ps,BYTE * key_blob,UINT16 key_blob_size)484 psfile_write_key(int fd,
485                      TSS_UUID *uuid,
486                      TSS_UUID *parent_uuid,
487                      UINT32 parent_ps,
488                      BYTE *key_blob,
489                      UINT16 key_blob_size)
490 {
491           TSS_RESULT result;
492           TSS_KEY key;
493           UINT32 zero = 0;
494           UINT64 offset;
495           UINT16 pub_key_size, cache_flags = 0;
496           struct stat stat_buf;
497           int rc, file_offset;
498 
499           /* leaving the cache flag for parent ps type as 0 implies TSS_PS_TYPE_USER */
500           if (parent_ps == TSS_PS_TYPE_SYSTEM)
501                     cache_flags |= CACHE_FLAG_PARENT_PS_SYSTEM;
502 
503           if ((rc = fstat(fd, &stat_buf)) == -1) {
504                     LogDebugFn("stat failed: %s", strerror(errno));
505                     return TSPERR(TSS_E_INTERNAL_ERROR);
506           }
507 
508           file_offset = stat_buf.st_size;
509 
510           if (file_offset < (int)TSSPS_KEYS_OFFSET) {
511                     if ((result = psfile_write_key_header(fd)))
512                               return result;
513                     file_offset = TSSPS_KEYS_OFFSET;
514           }
515 
516           rc = lseek(fd, file_offset, SEEK_SET);
517           if (rc == ((off_t)-1)) {
518                     LogDebug("lseek: %s", strerror(errno));
519                     return TSPERR(TSS_E_INTERNAL_ERROR);
520           }
521 
522           /* Unload the blob to get the public key */
523           offset = 0;
524           if ((result = UnloadBlob_TSS_KEY(&offset, key_blob, &key)))
525                     return result;
526 
527           pub_key_size = key.pubKey.keyLength;
528 
529           /* [TSS_UUID uuid0           ] yes */
530         if ((result = write_data(fd, (void *)uuid, sizeof(TSS_UUID)))) {
531                     LogDebug("%s", __FUNCTION__);
532                     goto done;
533           }
534 
535           /* [TSS_UUID uuid_parent0    ] yes */
536         if ((result = write_data(fd, (void *)parent_uuid, sizeof(TSS_UUID)))) {
537                     LogDebug("%s", __FUNCTION__);
538                     goto done;
539           }
540 
541           /* [UINT16   pub_data_size0  ] yes */
542           pub_key_size = LE_16(pub_key_size);
543         if ((result = write_data(fd, &pub_key_size, sizeof(UINT16)))) {
544                     LogDebug("%s", __FUNCTION__);
545                     goto done;
546           }
547           pub_key_size = LE_16(pub_key_size);
548 
549           /* [UINT16   blob_size0      ] yes */
550           key_blob_size = LE_16(key_blob_size);
551         if ((result = write_data(fd, &key_blob_size, sizeof(UINT16)))) {
552                     LogDebug("%s", __FUNCTION__);
553                     goto done;
554           }
555           key_blob_size = LE_16(key_blob_size);
556 
557           /* [UINT32   vendor_data_size0 ] yes */
558         if ((result = write_data(fd, &zero, sizeof(UINT32)))) {
559                     LogDebug("%s", __FUNCTION__);
560                     goto done;
561           }
562 
563           /* [UINT16   cache_flags0    ] yes */
564           cache_flags = LE_16(cache_flags);
565         if ((result = write_data(fd, &cache_flags, sizeof(UINT16)))) {
566                     LogDebug("%s", __FUNCTION__);
567                     goto done;
568           }
569           cache_flags = LE_16(cache_flags);
570 
571           /* [BYTE[]   pub_data0       ] no */
572         if ((result = write_data(fd, (void *)key.pubKey.key, pub_key_size))) {
573                     LogDebug("%s", __FUNCTION__);
574                     goto done;
575           }
576 
577           /* [BYTE[]   blob0           ] no */
578         if ((result = write_data(fd, (void *)key_blob, key_blob_size))) {
579                     LogDebug("%s", __FUNCTION__);
580                     goto done;
581           }
582 
583           if ((result = psfile_change_num_keys(fd, TSS_PSFILE_INCREMENT_NUM_KEYS))) {
584                     LogDebug("%s", __FUNCTION__);
585                     goto done;
586           }
587 
588 done:
589           free_key_refs(&key);
590         return result;
591 }
592 
593 TSS_RESULT
psfile_remove_key(int fd,TSS_UUID * uuid)594 psfile_remove_key(int fd, TSS_UUID *uuid)
595 {
596         TSS_RESULT result;
597         UINT32 head_offset = 0, tail_offset;
598           int rc, size = 0;
599           struct key_disk_cache c;
600           BYTE buf[4096];
601 
602           if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &c)))
603                     return result;
604 
605           /* head_offset is the offset the beginning of the key */
606           head_offset = TSSPS_UUID_OFFSET(&c);
607 
608           /* tail_offset is the offset the beginning of the next key */
609           tail_offset = TSSPS_VENDOR_DATA_OFFSET(&c) + c.vendor_data_size;
610 
611           rc = lseek(fd, tail_offset, SEEK_SET);
612           if (rc == ((off_t)-1)) {
613                     LogDebug("lseek: %s", strerror(errno));
614                     return TSPERR(TSS_E_INTERNAL_ERROR);
615           }
616 
617           /* read in from tail, write out to head to fill the gap */
618           while ((rc = read(fd, buf, sizeof(buf))) > 0) {
619                     size = rc;
620                     tail_offset += size;
621 
622                     /* set the file pointer to where we want to write */
623                     rc = lseek(fd, head_offset, SEEK_SET);
624                     if (rc == ((off_t)-1)) {
625                               LogDebug("lseek: %s", strerror(errno));
626                               return TSPERR(TSS_E_INTERNAL_ERROR);
627                     }
628 
629                     /* write the data */
630                     if ((result = write_data(fd, (void *)buf, size))) {
631                               LogDebug("%s", __FUNCTION__);
632                               return result;
633                     }
634                     head_offset += size;
635 
636                     /* set the file pointer to where we want to read in the next
637                      * loop */
638                     rc = lseek(fd, tail_offset, SEEK_SET);
639                     if (rc == ((off_t)-1)) {
640                               LogDebug("lseek: %s", strerror(errno));
641                               return TSPERR(TSS_E_INTERNAL_ERROR);
642                     }
643           }
644 
645           if (rc < 0) {
646                     LogDebug("read: %s", strerror(errno));
647                     return TSPERR(TSS_E_INTERNAL_ERROR);
648           }
649 
650           /* set the file pointer to where we want to write */
651           rc = lseek(fd, head_offset, SEEK_SET);
652           if (rc == ((off_t)-1)) {
653                     LogDebug("lseek: %s", strerror(errno));
654                     return TSPERR(TSS_E_INTERNAL_ERROR);
655           }
656 
657           /* head_offset now contains a pointer to where we want to truncate the
658            * file. Zero out the old tail end of the file and truncate it. */
659 
660           __tspi_memset(buf, 0, sizeof(buf));
661 
662           /* Zero out the old tail end of the file */
663           if ((result = write_data(fd, (void *)buf, tail_offset - head_offset))) {
664                     LogDebug("%s", __FUNCTION__);
665                     return result;
666           }
667 
668           if ((rc = ftruncate(fd, head_offset)) < 0) {
669                     LogDebug("ftruncate: %s", strerror(errno));
670                     return TSPERR(TSS_E_INTERNAL_ERROR);
671           }
672 
673           /* we succeeded in removing a key from the disk. Decrement the number
674            * of keys in the file */
675           if ((result = psfile_change_num_keys(fd, TSS_PSFILE_DECREMENT_NUM_KEYS)))
676                     return result;
677 
678           return TSS_SUCCESS;
679 }
680 
681 TSS_RESULT
psfile_get_all_cache_entries(int fd,UINT32 * size,struct key_disk_cache ** c)682 psfile_get_all_cache_entries(int fd, UINT32 *size, struct key_disk_cache **c)
683 {
684           UINT32 i, num_keys = psfile_get_num_keys(fd);
685           int offset;
686           TSS_RESULT result;
687           struct key_disk_cache *tmp = NULL;
688 
689           if (num_keys == 0) {
690                     *size = 0;
691                     *c = NULL;
692                     return TSS_SUCCESS;
693           }
694 
695           /* make sure the file pointer is where we expect, just after the number
696            * of keys on disk at the head of the file
697            */
698           offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
699           if (offset == ((off_t)-1)) {
700                     LogDebug("lseek: %s", strerror(errno));
701                     return TSPERR(TSS_E_INTERNAL_ERROR);
702           }
703 
704           if ((tmp = malloc(num_keys * sizeof(struct key_disk_cache))) == NULL) {
705                     LogDebug("malloc of %zu bytes failed.", num_keys * sizeof(struct key_disk_cache));
706                     return TSPERR(TSS_E_OUTOFMEMORY);
707           }
708 
709           for (i = 0; i < num_keys; i++) {
710                     offset = lseek(fd, 0, SEEK_CUR);
711                     if (offset == ((off_t)-1)) {
712                               LogDebug("lseek: %s", strerror(errno));
713                               result = TSPERR(TSS_E_INTERNAL_ERROR);
714                               goto err_exit;
715                     }
716                     tmp[i].offset = offset;
717 
718                     /* read UUID */
719                     if ((result = read_data(fd, &tmp[i].uuid, sizeof(TSS_UUID)))) {
720                               LogDebug("%s", __FUNCTION__);
721                               goto err_exit;
722                     }
723 
724                     /* read parent UUID */
725                     if ((result = read_data(fd, &tmp[i].parent_uuid, sizeof(TSS_UUID)))) {
726                               LogDebug("%s", __FUNCTION__);
727                               goto err_exit;
728                     }
729 
730                     /* pub data size */
731                     if ((result = read_data(fd, &tmp[i].pub_data_size, sizeof(UINT16)))) {
732                               LogDebug("%s", __FUNCTION__);
733                               goto err_exit;
734                     }
735                     tmp[i].pub_data_size = LE_16(tmp[i].pub_data_size);
736 
737                     DBG_ASSERT(tmp[i].pub_data_size <= 2048);
738 
739                     /* blob size */
740                     if ((result = read_data(fd, &tmp[i].blob_size, sizeof(UINT16)))) {
741                               LogDebug("%s", __FUNCTION__);
742                               goto err_exit;
743                     }
744                     tmp[i].blob_size = LE_16(tmp[i].blob_size);
745 
746                     DBG_ASSERT(tmp[i].blob_size <= 4096);
747 
748                     /* vendor data size */
749                     if ((result = read_data(fd, &tmp[i].vendor_data_size, sizeof(UINT32)))) {
750                               LogDebug("%s", __FUNCTION__);
751                               goto err_exit;
752                     }
753                     tmp[i].vendor_data_size = LE_32(tmp[i].vendor_data_size);
754 
755                     /* cache flags */
756                     if ((result = read_data(fd, &tmp[i].flags, sizeof(UINT16)))) {
757                               LogDebug("%s", __FUNCTION__);
758                               goto err_exit;
759                     }
760                     tmp[i].flags = LE_16(tmp[i].flags);
761 
762                     /* fast forward over the pub key */
763                     offset = lseek(fd, tmp[i].pub_data_size, SEEK_CUR);
764                     if (offset == ((off_t)-1)) {
765                               LogDebug("lseek: %s", strerror(errno));
766                               result = TSPERR(TSS_E_INTERNAL_ERROR);
767                               goto err_exit;
768                     }
769 
770                     /* fast forward over the blob */
771                     offset = lseek(fd, tmp[i].blob_size, SEEK_CUR);
772                     if (offset == ((off_t)-1)) {
773                               LogDebug("lseek: %s", strerror(errno));
774                               result = TSPERR(TSS_E_INTERNAL_ERROR);
775                               goto err_exit;
776                     }
777 
778                     /* ignore vendor data for user ps */
779           }
780 
781           *size = num_keys;
782           *c = tmp;
783 
784           return TSS_SUCCESS;
785 
786 err_exit:
787           free(tmp);
788           return result;
789 }
790 
791 TSS_RESULT
copy_key_info(int fd,TSS_KM_KEYINFO * ki,struct key_disk_cache * c)792 copy_key_info(int fd, TSS_KM_KEYINFO *ki, struct key_disk_cache *c)
793 {
794           TSS_KEY key;
795           BYTE blob[4096];
796           UINT64 offset;
797           TSS_RESULT result;
798           off_t off;
799 
800           /* Set the file pointer to the offset that the key blob is at */
801           off = lseek(fd, TSSPS_BLOB_DATA_OFFSET(c), SEEK_SET);
802           if (off == ((off_t)-1)) {
803                     LogDebug("lseek: %s", strerror(errno));
804                     return TSPERR(TSS_E_INTERNAL_ERROR);
805           }
806 
807           /* Read in the key blob */
808           if ((result = read_data(fd, (void *)blob, c->blob_size))) {
809                     LogDebug("%s", __FUNCTION__);
810                     return result;
811           }
812 
813           /* Expand the blob into a useable form */
814           offset = 0;
815           if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key)))
816                     return result;
817 
818           if (key.hdr.key12.tag == TPM_TAG_KEY12) {
819                     ki->versionInfo.bMajor = TSS_SPEC_MAJOR;
820                     ki->versionInfo.bMinor = TSS_SPEC_MINOR;
821                     ki->versionInfo.bRevMajor = 0;
822                     ki->versionInfo.bRevMinor = 0;
823           } else
824                     memcpy(&ki->versionInfo, &key.hdr.key11.ver, sizeof(TSS_VERSION));
825           memcpy(&ki->keyUUID, &c->uuid, sizeof(TSS_UUID));
826           memcpy(&ki->parentKeyUUID, &c->parent_uuid, sizeof(TSS_UUID));
827           ki->bAuthDataUsage = key.authDataUsage;
828 
829           free_key_refs(&key);
830 
831           return TSS_SUCCESS;
832 }
833 
834 TSS_RESULT
copy_key_info2(int fd,TSS_KM_KEYINFO2 * ki,struct key_disk_cache * c)835 copy_key_info2(int fd, TSS_KM_KEYINFO2 *ki, struct key_disk_cache *c)
836 {
837           TSS_KEY key;
838           BYTE blob[4096];
839           UINT64 offset;
840           TSS_RESULT result;
841           off_t off;
842 
843           /* Set the file pointer to the offset that the key blob is at */
844           off = lseek(fd, TSSPS_BLOB_DATA_OFFSET(c), SEEK_SET);
845           if (off == ((off_t)-1)) {
846                     LogDebug("lseek: %s", strerror(errno));
847                     return TSPERR(TSS_E_INTERNAL_ERROR);
848           }
849 
850           /* Read in the key blob */
851           if ((result = read_data(fd, (void *)blob, c->blob_size))) {
852                     LogDebug("%s", __FUNCTION__);
853                     return result;
854           }
855 
856           /* Expand the blob into a useable form */
857           offset = 0;
858           if ((result = UnloadBlob_TSS_KEY(&offset, blob, &key)))
859                     return result;
860 
861           if (key.hdr.key12.tag == TPM_TAG_KEY12) {
862                     ki->versionInfo.bMajor = TSS_SPEC_MAJOR;
863                     ki->versionInfo.bMinor = TSS_SPEC_MINOR;
864                     ki->versionInfo.bRevMajor = 0;
865                     ki->versionInfo.bRevMinor = 0;
866           } else
867                     memcpy(&ki->versionInfo, &key.hdr.key11.ver, sizeof(TSS_VERSION));
868           memcpy(&ki->keyUUID, &c->uuid, sizeof(TSS_UUID));
869           memcpy(&ki->parentKeyUUID, &c->parent_uuid, sizeof(TSS_UUID));
870 
871           /* CHECK: fill the two new fields of TSS_KM_KEYINFO2 */
872           ki->persistentStorageType = TSS_PS_TYPE_USER;
873           ki->persistentStorageTypeParent = c->flags & CACHE_FLAG_PARENT_PS_SYSTEM ?
874                                                     TSS_PS_TYPE_SYSTEM : TSS_PS_TYPE_USER;
875 
876           ki->bAuthDataUsage = key.authDataUsage;
877 
878           free_key_refs(&key);
879 
880           return TSS_SUCCESS;
881 }
882 
883 
884 TSS_RESULT
psfile_get_registered_keys(int fd,TSS_UUID * uuid,TSS_UUID * tcs_uuid,UINT32 * size,TSS_KM_KEYINFO ** keys)885 psfile_get_registered_keys(int fd,
886                                  TSS_UUID *uuid,
887                                  TSS_UUID *tcs_uuid,
888                                  UINT32 *size,
889                                  TSS_KM_KEYINFO **keys)
890 {
891           TSS_RESULT result;
892           struct key_disk_cache *cache_entries;
893           UINT32 cache_size, i, j;
894           TSS_KM_KEYINFO *keyinfos = NULL;
895           TSS_UUID *find_uuid;
896 
897         if ((result = psfile_get_all_cache_entries(fd, &cache_size, &cache_entries)))
898                 return result;
899 
900           if (cache_size == 0) {
901                     if (uuid)
902                               return TSPERR(TSS_E_PS_KEY_NOTFOUND);
903                     else {
904                               *size = 0;
905                               *keys = NULL;
906                               return TSS_SUCCESS;
907                     }
908           }
909 
910         if (uuid) {
911                     find_uuid = uuid;
912                     j = 0;
913 
914 restart_search:
915                     /* Search for the requested UUID.  When found, allocate new space for it, copy
916                      * it in, then change the uuid to be searched for it its parent and start over. */
917                     for (i = 0; i < cache_size; i++) {
918                               if (!memcmp(&cache_entries[i].uuid, find_uuid, sizeof(TSS_UUID))) {
919                                         if (!(keyinfos = realloc(keyinfos,
920                                                                        (j+1) * sizeof(TSS_KM_KEYINFO)))) {
921                                                   free(cache_entries);
922                                                   free(keyinfos);
923                                                   return TSPERR(TSS_E_OUTOFMEMORY);
924                                         }
925                                         __tspi_memset(&keyinfos[j], 0, sizeof(TSS_KM_KEYINFO));
926 
927                                         if ((result = copy_key_info(fd, &keyinfos[j], &cache_entries[i]))) {
928                                                   free(cache_entries);
929                                                   free(keyinfos);
930                                                   return result;
931                                         }
932 
933                                         find_uuid = &keyinfos[j].parentKeyUUID;
934                                         j++;
935                                         goto restart_search;
936                               }
937                     }
938 
939                     /* Searching for keys in the user PS will always lead us up to some key in the
940                      * system PS. Return that key's uuid so that the upper layers can call down to TCS
941                      * to search for it. */
942                     memcpy(tcs_uuid, find_uuid, sizeof(TSS_UUID));
943 
944                     *size = j;
945         } else {
946                     if ((keyinfos = calloc(cache_size, sizeof(TSS_KM_KEYINFO))) == NULL) {
947                               LogDebug("malloc of %zu bytes failed.",
948                                          cache_size * sizeof(TSS_KM_KEYINFO));
949                               free(cache_entries);
950                               return TSPERR(TSS_E_OUTOFMEMORY);
951                     }
952 
953                 for (i = 0; i < cache_size; i++) {
954                               if ((result = copy_key_info(fd, &keyinfos[i], &cache_entries[i]))) {
955                                         free(cache_entries);
956                                         free(keyinfos);
957                                         return result;
958                               }
959                 }
960 
961                     *size = cache_size;
962         }
963 
964           free(cache_entries);
965 
966           *keys = keyinfos;
967 
968           return TSS_SUCCESS;
969 }
970 
971 TSS_RESULT
psfile_get_registered_keys2(int fd,TSS_UUID * uuid,TSS_UUID * tcs_uuid,UINT32 * size,TSS_KM_KEYINFO2 ** keys)972 psfile_get_registered_keys2(int fd,
973                                  TSS_UUID *uuid,
974                                  TSS_UUID *tcs_uuid,
975                                  UINT32 *size,
976                                  TSS_KM_KEYINFO2 **keys)
977 {
978           TSS_RESULT result;
979           struct key_disk_cache *cache_entries;
980           UINT32 cache_size, i, j;
981           TSS_KM_KEYINFO2 *keyinfos = NULL;
982           TSS_UUID *find_uuid;
983 
984         if ((result = psfile_get_all_cache_entries(fd, &cache_size, &cache_entries)))
985                 return result;
986 
987           if (cache_size == 0) {
988                     if (uuid)
989                               return TSPERR(TSS_E_PS_KEY_NOTFOUND);
990                     else {
991                               *size = 0;
992                               *keys = NULL;
993                               return TSS_SUCCESS;
994                     }
995           }
996 
997           if (uuid) {
998                     find_uuid = uuid;
999                     j = 0;
1000 
1001                     restart_search:
1002                               /* Search for the requested UUID.  When found, allocate new space for it, copy
1003                                * it in, then change the uuid to be searched for it its parent and start over. */
1004                               for (i = 0; i < cache_size; i++) {
1005                                         /*Return 0 if normal finish*/
1006                                         if (!memcmp(&cache_entries[i].uuid, find_uuid, sizeof(TSS_UUID))) {
1007                                                   if (!(keyinfos = realloc(keyinfos,
1008                                                                       (j+1) * sizeof(TSS_KM_KEYINFO2)))) {
1009                                                             free(cache_entries);
1010                                                             free(keyinfos);
1011                                                             return TSPERR(TSS_E_OUTOFMEMORY);
1012                                                   }
1013                                                   /* Here the key UUID is found and needs to be copied for the array*/
1014                                                   /* Initializes the keyinfos with 0's*/
1015                                                   __tspi_memset(&keyinfos[j], 0, sizeof(TSS_KM_KEYINFO2));
1016 
1017                                                   if ((result = copy_key_info2(fd, &keyinfos[j], &cache_entries[i]))) {
1018                                                             free(cache_entries);
1019                                                             free(keyinfos);
1020                                                             return result;
1021                                                   }
1022 
1023                                                   find_uuid = &keyinfos[j].parentKeyUUID;
1024                                                   j++;
1025                                                   goto restart_search;
1026                                         }
1027                               }
1028 
1029                     /* Searching for keys in the user PS will always lead us up to some key in the
1030                      * system PS. Return that key's uuid so that the upper layers can call down to TCS
1031                      * to search for it. */
1032                     memcpy(tcs_uuid, find_uuid, sizeof(TSS_UUID));
1033 
1034                     *size = j;
1035           } else {
1036                     if ((keyinfos = calloc(cache_size, sizeof(TSS_KM_KEYINFO2))) == NULL) {
1037                               LogDebug("malloc of %zu bytes failed.",
1038                                                   cache_size * sizeof(TSS_KM_KEYINFO2));
1039                               free(cache_entries);
1040                               return TSPERR(TSS_E_OUTOFMEMORY);
1041                     }
1042 
1043                     for (i = 0; i < cache_size; i++) {
1044                               if ((result = copy_key_info2(fd, &keyinfos[i], &cache_entries[i]))) {
1045                                         free(cache_entries);
1046                                         free(keyinfos);
1047                                         return result;
1048                               }
1049                     }
1050 
1051                     *size = cache_size;
1052           }
1053 
1054           free(cache_entries);
1055 
1056           *keys = keyinfos;
1057 
1058           return TSS_SUCCESS;
1059 }
1060 
1061 /*
1062  * read into the PS file and return the number of keys
1063  */
1064 UINT32
psfile_get_num_keys(int fd)1065 psfile_get_num_keys(int fd)
1066 {
1067           UINT32 num_keys;
1068           int rc;
1069 
1070           /* go to the number of keys */
1071           rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
1072           if (rc == ((off_t)-1)) {
1073                     LogDebug("lseek: %s", strerror(errno));
1074                     return 0;
1075           }
1076 
1077           rc = read(fd, &num_keys, sizeof(UINT32));
1078           if (rc < 0) {
1079                     LogDebug("read of %zd bytes: %s", sizeof(UINT32), strerror(errno));
1080                     return 0;
1081           } else if ((unsigned)rc < sizeof(UINT32)) {
1082                     num_keys = 0;
1083           }
1084 
1085           /* The system PS file is written in little-endian */
1086           num_keys = LE_32(num_keys);
1087           return num_keys;
1088 }
1089 
1090 /*
1091  * disk store format:
1092  *
1093  * TrouSerS 0.2.1+
1094  * Version 1:                  cached?
1095  * [BYTE     PS version = '\1']
1096  * [UINT32   num_keys_on_disk ]
1097  * [TSS_UUID uuid0            ] yes
1098  * [TSS_UUID uuid_parent0     ] yes
1099  * [UINT16   pub_data_size0   ] yes
1100  * [UINT16   blob_size0       ] yes
1101  * [UINT32   vendor_data_size0] yes
1102  * [UINT16   cache_flags0     ] yes
1103  * [BYTE[]   pub_data0        ]
1104  * [BYTE[]   blob0            ]
1105  * [BYTE[]   vendor_data0     ]
1106  * [...]
1107  *
1108  */
1109 TSS_RESULT
psfile_get_cache_entry_by_uuid(int fd,TSS_UUID * uuid,struct key_disk_cache * c)1110 psfile_get_cache_entry_by_uuid(int fd, TSS_UUID *uuid, struct key_disk_cache *c)
1111 {
1112           UINT32 i, num_keys = psfile_get_num_keys(fd);
1113           int offset;
1114           TSS_RESULT result;
1115           BYTE found = 0;
1116 
1117           if (num_keys == 0)
1118                     return TSPERR(TSS_E_PS_KEY_NOTFOUND);
1119 
1120           /* make sure the file pointer is where we expect, just after the number
1121            * of keys on disk at the head of the file
1122            */
1123           offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
1124           if (offset == ((off_t)-1)) {
1125                     LogDebug("lseek: %s", strerror(errno));
1126                     return TSPERR(TSS_E_INTERNAL_ERROR);
1127           }
1128 
1129           for (i = 0; i < num_keys && !found; i++) {
1130                     offset = lseek(fd, 0, SEEK_CUR);
1131                     if (offset == ((off_t)-1)) {
1132                               LogDebug("lseek: %s", strerror(errno));
1133                               return TSPERR(TSS_E_INTERNAL_ERROR);
1134                     }
1135                     c->offset = offset;
1136 
1137                     /* read UUID */
1138                     if ((result = read_data(fd, (void *)&c->uuid, sizeof(TSS_UUID)))) {
1139                               LogDebug("%s", __FUNCTION__);
1140                               return result;
1141                     }
1142 
1143                     if (!memcmp(&c->uuid, uuid, sizeof(TSS_UUID))) {
1144                               found = 1;
1145 
1146                               /* read parent UUID */
1147                               if ((result = read_data(fd, (void *)&c->parent_uuid, sizeof(TSS_UUID)))) {
1148                                         LogDebug("%s", __FUNCTION__);
1149                                         return result;
1150                               }
1151                     } else {
1152                               /* fast forward over the parent UUID */
1153                               offset = lseek(fd, sizeof(TSS_UUID), SEEK_CUR);
1154                               if (offset == ((off_t)-1)) {
1155                                         LogDebug("lseek: %s", strerror(errno));
1156                                         return TSPERR(TSS_E_INTERNAL_ERROR);
1157                               }
1158                     }
1159 
1160                     /* pub data size */
1161                     if ((result = read_data(fd, &c->pub_data_size, sizeof(UINT16)))) {
1162                               LogDebug("%s", __FUNCTION__);
1163                               return result;
1164                     }
1165                     c->pub_data_size = LE_16(c->pub_data_size);
1166                     DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0);
1167 
1168                     /* blob size */
1169                     if ((result = read_data(fd, &c->blob_size, sizeof(UINT16)))) {
1170                               LogDebug("%s", __FUNCTION__);
1171                               return result;
1172                     }
1173                     c->blob_size = LE_16(c->blob_size);
1174                     DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0);
1175 
1176                     /* vendor data size */
1177                     if ((result = read_data(fd, &c->vendor_data_size, sizeof(UINT32)))) {
1178                               LogDebug("%s", __FUNCTION__);
1179                               return result;
1180                     }
1181                     c->vendor_data_size = LE_32(c->vendor_data_size);
1182 
1183                     /* cache flags */
1184                     if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) {
1185                               LogDebug("%s", __FUNCTION__);
1186                               return result;
1187                     }
1188                     c->flags = LE_16(c->flags);
1189 
1190                     /* fast forward over the pub key */
1191                     offset = lseek(fd, c->pub_data_size, SEEK_CUR);
1192                     if (offset == ((off_t)-1)) {
1193                               LogDebug("lseek: %s", strerror(errno));
1194                               return TSPERR(TSS_E_INTERNAL_ERROR);
1195                     }
1196 
1197                     /* fast forward over the blob */
1198                     offset = lseek(fd, c->blob_size, SEEK_CUR);
1199                     if (offset == ((off_t)-1)) {
1200                               LogDebug("lseek: %s", strerror(errno));
1201                               return TSPERR(TSS_E_INTERNAL_ERROR);
1202                     }
1203 
1204                     /* ignore vendor data in user ps */
1205           }
1206 
1207           return found ? TSS_SUCCESS : TSPERR(TSS_E_PS_KEY_NOTFOUND);
1208 }
1209 
1210 TSS_RESULT
psfile_get_cache_entry_by_pub(int fd,UINT32 pub_size,BYTE * pub,struct key_disk_cache * c)1211 psfile_get_cache_entry_by_pub(int fd, UINT32 pub_size, BYTE *pub, struct key_disk_cache *c)
1212 {
1213           BYTE blob[2048];
1214           UINT32 i, num_keys = psfile_get_num_keys(fd);
1215           int offset;
1216           TSS_RESULT result;
1217 
1218           if (num_keys == 0)
1219                     return TSPERR(TSS_E_PS_KEY_NOTFOUND);
1220 
1221           /* make sure the file pointer is where we expect, just after the number
1222            * of keys on disk at the head of the file
1223            */
1224           offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
1225           if (offset == ((off_t)-1)) {
1226                     LogDebug("lseek: %s", strerror(errno));
1227                     return TSPERR(TSS_E_INTERNAL_ERROR);
1228           }
1229 
1230           for (i = 0; i < num_keys; i++) {
1231                     offset = lseek(fd, 0, SEEK_CUR);
1232                     if (offset == ((off_t)-1)) {
1233                               LogDebug("lseek: %s", strerror(errno));
1234                               return TSPERR(TSS_E_INTERNAL_ERROR);
1235                     }
1236                     c->offset = offset;
1237 
1238                     /* read UUID */
1239                     if ((result = read_data(fd, (void *)&c->uuid, sizeof(TSS_UUID)))) {
1240                               LogDebug("%s", __FUNCTION__);
1241                               return result;
1242                     }
1243 
1244                     /* read parent UUID */
1245                     if ((result = read_data(fd, (void *)&c->parent_uuid, sizeof(TSS_UUID)))) {
1246                               LogDebug("%s", __FUNCTION__);
1247                               return result;
1248                     }
1249 
1250                     /* pub data size */
1251                     if ((result = read_data(fd, &c->pub_data_size, sizeof(UINT16)))) {
1252                               LogDebug("%s", __FUNCTION__);
1253                               return result;
1254                     }
1255 
1256                     c->pub_data_size = LE_16(c->pub_data_size);
1257                     DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0);
1258 
1259                     /* blob size */
1260                     if ((result = read_data(fd, &c->blob_size, sizeof(UINT16)))) {
1261                               LogDebug("%s", __FUNCTION__);
1262                               return result;
1263                     }
1264 
1265                     c->blob_size = LE_16(c->blob_size);
1266                     DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0);
1267 
1268                     /* vendor data size */
1269                     if ((result = read_data(fd, &c->vendor_data_size, sizeof(UINT32)))) {
1270                               LogDebug("%s", __FUNCTION__);
1271                               return result;
1272                     }
1273                     c->vendor_data_size = LE_32(c->vendor_data_size);
1274 
1275                     /* cache flags */
1276                     if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) {
1277                               LogDebug("%s", __FUNCTION__);
1278                               return result;
1279                     }
1280                     c->flags = LE_16(c->flags);
1281 
1282                     if (c->pub_data_size == pub_size) {
1283                               /* read in the pub key */
1284                               if ((result = read_data(fd, blob, c->pub_data_size))) {
1285                                         LogDebug("%s", __FUNCTION__);
1286                                         return result;
1287                               }
1288 
1289                               if (!memcmp(blob, pub, pub_size))
1290                                         break;
1291                     }
1292 
1293                     /* fast forward over the blob */
1294                     offset = lseek(fd, c->blob_size, SEEK_CUR);
1295                     if (offset == ((off_t)-1)) {
1296                               LogDebug("lseek: %s", strerror(errno));
1297                               return TSPERR(TSS_E_INTERNAL_ERROR);
1298                     }
1299 
1300                     /* ignore vendor data */
1301           }
1302 
1303           return TSS_SUCCESS;
1304 }
1305