~ubuntu-branches/ubuntu/precise/trousers/precise-proposed

« back to all changes in this revision

Viewing changes to src/tspi/ps/tspps.c

  • Committer: Bazaar Package Importer
  • Author(s): William Lima
  • Date: 2007-04-18 16:39:38 UTC
  • Revision ID: james.westby@ubuntu.com-20070418163938-opscl2mvvi76jiec
Tags: upstream-0.2.9.1
ImportĀ upstreamĀ versionĀ 0.2.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <pthread.h>
 
22
#include <assert.h>
 
23
 
 
24
#include "trousers/tss.h"
 
25
#include "trousers/trousers.h"
 
26
#include "trousers_types.h"
 
27
#include "tcs_tsp.h"
 
28
#include "spi_utils.h"
 
29
#include "tspps.h"
 
30
#include "tsplog.h"
 
31
 
 
32
static int user_ps_fd = -1;
 
33
static pthread_mutex_t user_ps_lock = PTHREAD_MUTEX_INITIALIZER;
 
34
 
 
35
/*
 
36
 * Determine the default path to the persistent storage file and create it if it doesn't exist.
 
37
 */
 
38
TSS_RESULT
 
39
get_user_ps_path(char **file)
 
40
{
 
41
        TSS_RESULT result = TSPERR(TSS_E_INTERNAL_ERROR);
 
42
        char *file_name = NULL, *home_dir = NULL;
 
43
        struct passwd pw, *pwp;
 
44
        struct stat stat_buf;
 
45
        char buf[PASSWD_BUFSIZE];
 
46
        uid_t euid;
 
47
        int rc;
 
48
 
 
49
        if ((file_name = getenv("TSS_USER_PS_FILE"))) {
 
50
                *file = strdup(file_name);
 
51
                return (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY);
 
52
        }
 
53
 
 
54
        euid = geteuid();
 
55
 
 
56
        setpwent();
 
57
        while (1) {
 
58
                rc = getpwent_r(&pw, buf, PASSWD_BUFSIZE, &pwp);
 
59
                if (rc) {
 
60
                        LogDebugFn("USER PS: Error getting path to home directory: getpwent_r: %s",
 
61
                                   strerror(rc));
 
62
                        endpwent();
 
63
                        return TSPERR(TSS_E_INTERNAL_ERROR);
 
64
                }
 
65
 
 
66
                if (euid == pwp->pw_uid) {
 
67
                        home_dir = strdup(pwp->pw_dir);
 
68
                        break;
 
69
                }
 
70
        }
 
71
        endpwent();
 
72
 
 
73
        if (!home_dir)
 
74
                return TSPERR(TSS_E_OUTOFMEMORY);
 
75
 
 
76
        /* Tack on TSS_USER_PS_DIR and see if it exists */
 
77
        rc = snprintf(buf, PASSWD_BUFSIZE, "%s/%s", home_dir, TSS_USER_PS_DIR);
 
78
        if (rc == PASSWD_BUFSIZE) {
 
79
                LogDebugFn("USER PS: Path to file too long! (> %d bytes)", PASSWD_BUFSIZE);
 
80
                goto done;
 
81
        }
 
82
 
 
83
        errno = 0;
 
84
        if ((rc = stat(buf, &stat_buf)) == -1) {
 
85
                if (errno == ENOENT) {
 
86
                        errno = 0;
 
87
                        /* Create the base directory, $HOME/.trousers */
 
88
                        if ((rc = mkdir(buf, 0700)) == -1) {
 
89
                                LogDebugFn("USER PS: Error creating dir: %s: %s", buf,
 
90
                                           strerror(errno));
 
91
                                goto done;
 
92
                        }
 
93
                } else {
 
94
                        LogDebugFn("USER PS: Error stating dir: %s: %s", buf, strerror(errno));
 
95
                        goto done;
 
96
                }
 
97
        }
 
98
 
 
99
        /* Directory exists or has been created, return the path to the file */
 
100
        rc = snprintf(buf, PASSWD_BUFSIZE, "%s/%s/%s", home_dir, TSS_USER_PS_DIR,
 
101
                      TSS_USER_PS_FILE);
 
102
        if (rc == PASSWD_BUFSIZE) {
 
103
                LogDebugFn("USER PS: Path to file too long! (> %d bytes)", PASSWD_BUFSIZE);
 
104
        } else
 
105
                *file = strdup(buf);
 
106
 
 
107
        result = (*file) ? TSS_SUCCESS : TSPERR(TSS_E_OUTOFMEMORY);
 
108
done:
 
109
        free(home_dir);
 
110
        return result;
 
111
}
 
112
 
 
113
TSS_RESULT
 
114
get_file(int *fd)
 
115
{
 
116
        TSS_RESULT result;
 
117
        int rc = 0;
 
118
        char *file_name = NULL;
 
119
 
 
120
        pthread_mutex_lock(&user_ps_lock);
 
121
 
 
122
        /* check the global file handle first.  If it exists, lock it and return */
 
123
        if (user_ps_fd != -1) {
 
124
                if ((rc = flock(user_ps_fd, LOCK_EX))) {
 
125
                        LogDebug("USER PS: failed to lock file: %s", strerror(errno));
 
126
                        pthread_mutex_unlock(&user_ps_lock);
 
127
                        return TSPERR(TSS_E_INTERNAL_ERROR);
 
128
                }
 
129
 
 
130
                *fd = user_ps_fd;
 
131
                return TSS_SUCCESS;
 
132
        }
 
133
 
 
134
        /* open and lock the file */
 
135
        if ((result = get_user_ps_path(&file_name))) {
 
136
                LogDebugFn("USER PS: error getting file path");
 
137
                pthread_mutex_unlock(&user_ps_lock);
 
138
                return result;
 
139
        }
 
140
 
 
141
        user_ps_fd = open(file_name, O_CREAT|O_RDWR, 0600);
 
142
        if (user_ps_fd < 0) {
 
143
                LogDebug("USER PS: open of %s failed: %s", file_name, strerror(errno));
 
144
                free(file_name);
 
145
                pthread_mutex_unlock(&user_ps_lock);
 
146
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
147
        }
 
148
 
 
149
        if ((rc = flock(user_ps_fd, LOCK_EX))) {
 
150
                LogDebug("USER PS: failed to get lock of %s: %s", file_name, strerror(errno));
 
151
                free(file_name);
 
152
                close(user_ps_fd);
 
153
                user_ps_fd = -1;
 
154
                pthread_mutex_unlock(&user_ps_lock);
 
155
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
156
        }
 
157
 
 
158
        *fd = user_ps_fd;
 
159
        free(file_name);
 
160
        return TSS_SUCCESS;
 
161
}
 
162
 
 
163
int
 
164
put_file(int fd)
 
165
{
 
166
        int rc = 0;
 
167
 
 
168
        fsync(fd);
 
169
 
 
170
        /* release the file lock */
 
171
        if ((rc = flock(fd, LOCK_UN))) {
 
172
                LogDebug("USER PS: failed to unlock file: %s", strerror(errno));
 
173
                rc = -1;
 
174
        }
 
175
 
 
176
        pthread_mutex_unlock(&user_ps_lock);
 
177
        return rc;
 
178
}
 
179
 
 
180
void
 
181
psfile_close(int fd)
 
182
{
 
183
        close(fd);
 
184
        user_ps_fd = -1;
 
185
        pthread_mutex_unlock(&user_ps_lock);
 
186
}
 
187
 
 
188
TSS_RESULT
 
189
psfile_is_key_registered(int fd, TSS_UUID *uuid, TSS_BOOL *answer)
 
190
{
 
191
        TSS_RESULT result;
 
192
        struct key_disk_cache tmp;
 
193
 
 
194
        if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)) == TSS_SUCCESS)
 
195
                *answer = TRUE;
 
196
        else if (result == TSPERR(TSS_E_PS_KEY_NOTFOUND))
 
197
                *answer = FALSE;
 
198
        else
 
199
                return result;
 
200
 
 
201
        return TSS_SUCCESS;
 
202
}
 
203
 
 
204
TSS_RESULT
 
205
psfile_get_parent_uuid_by_uuid(int fd, TSS_UUID *uuid, TSS_UUID *ret_uuid)
 
206
{
 
207
        TSS_RESULT result;
 
208
        struct key_disk_cache tmp;
 
209
 
 
210
        if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)))
 
211
                return result;
 
212
 
 
213
        memcpy(ret_uuid, &tmp.parent_uuid, sizeof(TSS_UUID));
 
214
 
 
215
        return TSS_SUCCESS;
 
216
}
 
217
 
 
218
TSS_RESULT
 
219
psfile_get_parent_ps_type(int fd, TSS_UUID *uuid, UINT32 *type)
 
220
{
 
221
        TSS_RESULT result;
 
222
        struct key_disk_cache tmp;
 
223
 
 
224
        if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)))
 
225
                return result;
 
226
 
 
227
        if (tmp.flags & CACHE_FLAG_PARENT_PS_SYSTEM)
 
228
                *type = TSS_PS_TYPE_SYSTEM;
 
229
        else
 
230
                *type = TSS_PS_TYPE_USER;
 
231
 
 
232
        return TSS_SUCCESS;
 
233
}
 
234
 
 
235
/*
 
236
 * return a key struct from PS given a uuid
 
237
 */
 
238
TSS_RESULT
 
239
psfile_get_key_by_uuid(int fd, TSS_UUID *uuid, BYTE *key)
 
240
{
 
241
        int rc;
 
242
        TSS_RESULT result;
 
243
        off_t file_offset;
 
244
        struct key_disk_cache tmp;
 
245
        BYTE buf[4096];
 
246
 
 
247
        if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &tmp)))
 
248
                return result;
 
249
 
 
250
        /* jump to the location of the key blob */
 
251
        file_offset = TSSPS_BLOB_DATA_OFFSET(&tmp);
 
252
 
 
253
        rc = lseek(fd, file_offset, SEEK_SET);
 
254
        if (rc == ((off_t)-1)) {
 
255
                LogDebugFn("lseek: %s", strerror(errno));
 
256
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
257
        }
 
258
 
 
259
        if ((rc = read_data(fd, buf, tmp.blob_size))) {
 
260
                LogDebugFn("Blob read from disk failed.");
 
261
                return rc;
 
262
        }
 
263
 
 
264
        memcpy(key, buf, tmp.blob_size);
 
265
        return TSS_SUCCESS;
 
266
}
 
267
 
 
268
/*
 
269
 * return a key struct from PS given a public key
 
270
 */
 
271
TSS_RESULT
 
272
psfile_get_key_by_pub(int fd, TSS_UUID *uuid, UINT32 pub_size, BYTE *pub, BYTE *key)
 
273
{
 
274
        int rc;
 
275
        TSS_RESULT result;
 
276
        off_t file_offset;
 
277
        struct key_disk_cache tmp;
 
278
        BYTE buf[4096];
 
279
 
 
280
        if ((result = psfile_get_cache_entry_by_pub(fd, pub_size, pub, &tmp)))
 
281
                return result;
 
282
 
 
283
        /* jump to the location of the key blob */
 
284
        file_offset = TSSPS_BLOB_DATA_OFFSET(&tmp);
 
285
 
 
286
        rc = lseek(fd, file_offset, SEEK_SET);
 
287
        if (rc == ((off_t)-1)) {
 
288
                LogDebugFn("lseek: %s", strerror(errno));
 
289
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
290
        }
 
291
 
 
292
        if ((result = read_data(fd, buf, tmp.blob_size))) {
 
293
                LogDebugFn("Blob read from disk failed.");
 
294
                return result;
 
295
        }
 
296
 
 
297
        memcpy(key, buf, tmp.blob_size);
 
298
        memcpy(uuid, &tmp.uuid, sizeof(TSS_UUID));
 
299
 
 
300
        return TSS_SUCCESS;
 
301
}
 
302
 
 
303
TSS_RESULT
 
304
psfile_get_uuid_by_pub(int fd, UINT32 pub_size, BYTE *pub, TSS_UUID *uuid)
 
305
{
 
306
        TSS_RESULT result;
 
307
        struct key_disk_cache tmp;
 
308
 
 
309
        if ((result = psfile_get_cache_entry_by_pub(fd, pub_size, pub, &tmp)))
 
310
                return result;
 
311
 
 
312
        memcpy(uuid, &tmp.uuid, sizeof(TSS_UUID));
 
313
 
 
314
        return TSS_SUCCESS;
 
315
}
 
316
 
 
317
TSS_RESULT
 
318
psfile_change_num_keys(int fd, BYTE increment)
 
319
{
 
320
        int rc;
 
321
        TSS_RESULT result;
 
322
        UINT32 num_keys;
 
323
 
 
324
        rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
 
325
        if (rc == ((off_t)-1)) {
 
326
                LogDebug("lseek: %s", strerror(errno));
 
327
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
328
        }
 
329
 
 
330
        rc = read(fd, &num_keys, sizeof(UINT32));
 
331
        if (rc != sizeof(UINT32)) {
 
332
                LogDebug("read of %zd bytes: %s", sizeof(UINT32), strerror(errno));
 
333
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
334
        }
 
335
 
 
336
        if (increment)
 
337
                num_keys++;
 
338
        else
 
339
                num_keys--;
 
340
 
 
341
        rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
 
342
        if (rc == ((off_t)-1)) {
 
343
                LogDebug("lseek: %s", strerror(errno));
 
344
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
345
        }
 
346
 
 
347
        if ((result = write_data(fd, (void *)&num_keys, sizeof(UINT32)))) {
 
348
                LogDebug("%s", __FUNCTION__);
 
349
                return result;
 
350
        }
 
351
 
 
352
        return TSS_SUCCESS;
 
353
}
 
354
 
 
355
/* Write the initial header (number of keys and PS version) to initialize a new file */
 
356
TSS_RESULT
 
357
psfile_write_key_header(int fd)
 
358
{
 
359
        int rc;
 
360
        TSS_RESULT result;
 
361
        UINT32 i;
 
362
 
 
363
        rc = lseek(fd, TSSPS_VERSION_OFFSET, SEEK_SET);
 
364
        if (rc == ((off_t)-1)) {
 
365
                LogDebug("lseek: %s", strerror(errno));
 
366
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
367
        }
 
368
 
 
369
        i = TSSPS_VERSION;
 
370
        if ((result = write_data(fd, &i, sizeof(BYTE)))) {
 
371
                LogDebug("%s", __FUNCTION__);
 
372
                return result;
 
373
        }
 
374
 
 
375
        rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
 
376
        if (rc == ((off_t)-1)) {
 
377
                LogDebug("lseek: %s", strerror(errno));
 
378
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
379
        }
 
380
 
 
381
        i = 0;
 
382
        if ((result = write_data(fd, &i, sizeof(UINT32)))) {
 
383
                LogDebug("%s", __FUNCTION__);
 
384
                return result;
 
385
        }
 
386
 
 
387
        return TSS_SUCCESS;
 
388
}
 
389
 
 
390
/*
 
391
 * disk store format:
 
392
 *
 
393
 * TrouSerS 0.2.1+
 
394
 * Version 1:                  cached?
 
395
 * [BYTE     PS version = '\1']
 
396
 * [UINT32   num_keys_on_disk ]
 
397
 * [TSS_UUID uuid0            ] yes
 
398
 * [TSS_UUID uuid_parent0     ] yes
 
399
 * [UINT16   pub_data_size0   ] yes
 
400
 * [UINT16   blob_size0       ] yes
 
401
 * [UINT32   vendor_data_size0] yes
 
402
 * [UINT16   cache_flags0     ] yes
 
403
 * [BYTE[]   pub_data0        ]
 
404
 * [BYTE[]   blob0            ]
 
405
 * [BYTE[]   vendor_data0     ]
 
406
 * [...]
 
407
 *
 
408
 */
 
409
TSS_RESULT
 
410
psfile_write_key(int fd,
 
411
                 TSS_UUID *uuid,
 
412
                 TSS_UUID *parent_uuid,
 
413
                 UINT32 parent_ps,
 
414
                 BYTE *key_blob,
 
415
                 UINT16 key_blob_size)
 
416
{
 
417
        TSS_RESULT result;
 
418
        TCPA_KEY key;
 
419
        UINT32 zero = 0;
 
420
        UINT16 pub_key_size, cache_flags = 0;
 
421
        UINT64 offset;
 
422
        struct stat stat_buf;
 
423
        int rc, file_offset;
 
424
 
 
425
        /* leaving the cache flag for parent ps type as 0 implies TSS_PS_TYPE_USER */
 
426
        if (parent_ps == TSS_PS_TYPE_SYSTEM)
 
427
                cache_flags |= CACHE_FLAG_PARENT_PS_SYSTEM;
 
428
 
 
429
        if ((rc = fstat(fd, &stat_buf)) == -1) {
 
430
                LogDebugFn("stat failed: %s", strerror(errno));
 
431
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
432
        }
 
433
 
 
434
        file_offset = stat_buf.st_size;
 
435
 
 
436
        if (file_offset < (int)TSSPS_KEYS_OFFSET) {
 
437
                if ((result = psfile_write_key_header(fd)))
 
438
                        return result;
 
439
                file_offset = TSSPS_KEYS_OFFSET;
 
440
        }
 
441
 
 
442
        rc = lseek(fd, file_offset, SEEK_SET);
 
443
        if (rc == ((off_t)-1)) {
 
444
                LogDebug("lseek: %s", strerror(errno));
 
445
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
446
        }
 
447
 
 
448
        /* Unload the blob to get the public key */
 
449
        offset = 0;
 
450
        if ((result = Trspi_UnloadBlob_KEY(&offset, key_blob, &key)))
 
451
                return result;
 
452
 
 
453
        pub_key_size = key.pubKey.keyLength;
 
454
 
 
455
        /* [TSS_UUID uuid0           ] yes */
 
456
        if ((result = write_data(fd, (void *)uuid, sizeof(TSS_UUID)))) {
 
457
                LogDebug("%s", __FUNCTION__);
 
458
                goto done;
 
459
        }
 
460
 
 
461
        /* [TSS_UUID uuid_parent0    ] yes */
 
462
        if ((result = write_data(fd, (void *)parent_uuid, sizeof(TSS_UUID)))) {
 
463
                LogDebug("%s", __FUNCTION__);
 
464
                goto done;
 
465
        }
 
466
 
 
467
        /* [UINT16   pub_data_size0  ] yes */
 
468
        if ((result = write_data(fd, &pub_key_size, sizeof(UINT16)))) {
 
469
                LogDebug("%s", __FUNCTION__);
 
470
                goto done;
 
471
        }
 
472
 
 
473
        /* [UINT16   blob_size0      ] yes */
 
474
        if ((result = write_data(fd, &key_blob_size, sizeof(UINT16)))) {
 
475
                LogDebug("%s", __FUNCTION__);
 
476
                goto done;
 
477
        }
 
478
 
 
479
        /* [UINT32   vendor_data_size0 ] yes */
 
480
        if ((result = write_data(fd, &zero, sizeof(UINT32)))) {
 
481
                LogDebug("%s", __FUNCTION__);
 
482
                goto done;
 
483
        }
 
484
 
 
485
        /* [UINT16   cache_flags0    ] yes */
 
486
        if ((result = write_data(fd, &cache_flags, sizeof(UINT16)))) {
 
487
                LogDebug("%s", __FUNCTION__);
 
488
                goto done;
 
489
        }
 
490
 
 
491
        /* [BYTE[]   pub_data0       ] no */
 
492
        if ((result = write_data(fd, (void *)key.pubKey.key, pub_key_size))) {
 
493
                LogDebug("%s", __FUNCTION__);
 
494
                goto done;
 
495
        }
 
496
 
 
497
        /* [BYTE[]   blob0           ] no */
 
498
        if ((result = write_data(fd, (void *)key_blob, key_blob_size))) {
 
499
                LogDebug("%s", __FUNCTION__);
 
500
                goto done;
 
501
        }
 
502
 
 
503
        if ((result = psfile_change_num_keys(fd, INCREMENT))) {
 
504
                LogDebug("%s", __FUNCTION__);
 
505
                goto done;
 
506
        }
 
507
 
 
508
done:
 
509
        free_key_refs(&key);
 
510
        return result;
 
511
}
 
512
 
 
513
TSS_RESULT
 
514
psfile_remove_key(int fd, TSS_UUID *uuid)
 
515
{
 
516
        TSS_RESULT result;
 
517
        UINT32 head_offset = 0, tail_offset;
 
518
        int rc, size = 0;
 
519
        struct key_disk_cache c;
 
520
        BYTE buf[4096];
 
521
 
 
522
        if ((result = psfile_get_cache_entry_by_uuid(fd, uuid, &c)))
 
523
                return result;
 
524
 
 
525
        /* head_offset is the offset the beginning of the key */
 
526
        head_offset = TSSPS_UUID_OFFSET(&c);
 
527
 
 
528
        /* tail_offset is the offset the beginning of the next key */
 
529
        tail_offset = TSSPS_VENDOR_DATA_OFFSET(&c) + c.vendor_data_size;
 
530
 
 
531
        rc = lseek(fd, tail_offset, SEEK_SET);
 
532
        if (rc == ((off_t)-1)) {
 
533
                LogDebug("lseek: %s", strerror(errno));
 
534
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
535
        }
 
536
 
 
537
        /* read in from tail, write out to head to fill the gap */
 
538
        while ((rc = read(fd, buf, sizeof(buf))) > 0) {
 
539
                size = rc;
 
540
                tail_offset += size;
 
541
 
 
542
                /* set the file pointer to where we want to write */
 
543
                rc = lseek(fd, head_offset, SEEK_SET);
 
544
                if (rc == ((off_t)-1)) {
 
545
                        LogDebug("lseek: %s", strerror(errno));
 
546
                        return TSPERR(TSS_E_INTERNAL_ERROR);
 
547
                }
 
548
 
 
549
                /* write the data */
 
550
                if ((result = write_data(fd, (void *)buf, size))) {
 
551
                        LogDebug("%s", __FUNCTION__);
 
552
                        return result;
 
553
                }
 
554
                head_offset += size;
 
555
 
 
556
                /* set the file pointer to where we want to read in the next
 
557
                 * loop */
 
558
                rc = lseek(fd, tail_offset, SEEK_SET);
 
559
                if (rc == ((off_t)-1)) {
 
560
                        LogDebug("lseek: %s", strerror(errno));
 
561
                        return TSPERR(TSS_E_INTERNAL_ERROR);
 
562
                }
 
563
        }
 
564
 
 
565
        if (rc < 0) {
 
566
                LogDebug("read: %s", strerror(errno));
 
567
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
568
        }
 
569
 
 
570
        /* set the file pointer to where we want to write */
 
571
        rc = lseek(fd, head_offset, SEEK_SET);
 
572
        if (rc == ((off_t)-1)) {
 
573
                LogDebug("lseek: %s", strerror(errno));
 
574
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
575
        }
 
576
 
 
577
        /* head_offset now contains a pointer to where we want to truncate the
 
578
         * file. Zero out the old tail end of the file and truncate it. */
 
579
 
 
580
        memset(buf, 0, sizeof(buf));
 
581
 
 
582
        /* Zero out the old tail end of the file */
 
583
        if ((result = write_data(fd, (void *)buf, tail_offset - head_offset))) {
 
584
                LogDebug("%s", __FUNCTION__);
 
585
                return result;
 
586
        }
 
587
 
 
588
        if ((rc = ftruncate(fd, head_offset)) < 0) {
 
589
                LogDebug("ftruncate: %s", strerror(errno));
 
590
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
591
        }
 
592
 
 
593
        /* we succeeded in removing a key from the disk. Decrement the number
 
594
         * of keys in the file */
 
595
        if ((result = psfile_change_num_keys(fd, DECREMENT)))
 
596
                return result;
 
597
 
 
598
        return TSS_SUCCESS;
 
599
}
 
600
 
 
601
TSS_RESULT
 
602
psfile_get_all_cache_entries(int fd, UINT32 *size, struct key_disk_cache **c)
 
603
{
 
604
        UINT32 i, num_keys = psfile_get_num_keys(fd);
 
605
        int offset;
 
606
        TSS_RESULT result;
 
607
        struct key_disk_cache *tmp = NULL;
 
608
 
 
609
        if (num_keys == 0) {
 
610
                *size = 0;
 
611
                *c = NULL;
 
612
                return TSS_SUCCESS;
 
613
        }
 
614
 
 
615
        /* make sure the file pointer is where we expect, just after the number
 
616
         * of keys on disk at the head of the file
 
617
         */
 
618
        offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
 
619
        if (offset == ((off_t)-1)) {
 
620
                LogDebug("lseek: %s", strerror(errno));
 
621
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
622
        }
 
623
 
 
624
        if ((tmp = malloc(num_keys * sizeof(struct key_disk_cache))) == NULL) {
 
625
                LogDebug("malloc of %zu bytes failed.", num_keys * sizeof(struct key_disk_cache));
 
626
                return TSPERR(TSS_E_OUTOFMEMORY);
 
627
        }
 
628
 
 
629
        for (i = 0; i < num_keys; i++) {
 
630
                offset = lseek(fd, 0, SEEK_CUR);
 
631
                if (offset == ((off_t)-1)) {
 
632
                        LogDebug("lseek: %s", strerror(errno));
 
633
                        result = TSPERR(TSS_E_INTERNAL_ERROR);
 
634
                        goto err_exit;
 
635
                }
 
636
                tmp[i].offset = offset;
 
637
 
 
638
                /* read UUID */
 
639
                if ((result = read_data(fd, &tmp[i].uuid, sizeof(TSS_UUID)))) {
 
640
                        LogDebug("%s", __FUNCTION__);
 
641
                        goto err_exit;
 
642
                }
 
643
 
 
644
                /* read parent UUID */
 
645
                if ((result = read_data(fd, &tmp[i].parent_uuid, sizeof(TSS_UUID)))) {
 
646
                        LogDebug("%s", __FUNCTION__);
 
647
                        goto err_exit;
 
648
                }
 
649
 
 
650
                /* pub data size */
 
651
                if ((result = read_data(fd, &tmp[i].pub_data_size, sizeof(UINT16)))) {
 
652
                        LogDebug("%s", __FUNCTION__);
 
653
                        goto err_exit;
 
654
                }
 
655
 
 
656
                DBG_ASSERT(tmp[i].pub_data_size <= 2048);
 
657
 
 
658
                /* blob size */
 
659
                if ((result = read_data(fd, &tmp[i].blob_size, sizeof(UINT16)))) {
 
660
                        LogDebug("%s", __FUNCTION__);
 
661
                        goto err_exit;
 
662
                }
 
663
 
 
664
                DBG_ASSERT(tmp[i].blob_size <= 4096);
 
665
 
 
666
                /* vendor data size */
 
667
                if ((result = read_data(fd, &tmp[i].vendor_data_size, sizeof(UINT32)))) {
 
668
                        LogDebug("%s", __FUNCTION__);
 
669
                        goto err_exit;
 
670
                }
 
671
 
 
672
                /* cache flags */
 
673
                if ((result = read_data(fd, &tmp[i].flags, sizeof(UINT16)))) {
 
674
                        LogDebug("%s", __FUNCTION__);
 
675
                        goto err_exit;
 
676
                }
 
677
 
 
678
                /* fast forward over the pub key */
 
679
                offset = lseek(fd, tmp[i].pub_data_size, SEEK_CUR);
 
680
                if (offset == ((off_t)-1)) {
 
681
                        LogDebug("lseek: %s", strerror(errno));
 
682
                        result = TSPERR(TSS_E_INTERNAL_ERROR);
 
683
                        goto err_exit;
 
684
                }
 
685
 
 
686
                /* fast forward over the blob */
 
687
                offset = lseek(fd, tmp[i].blob_size, SEEK_CUR);
 
688
                if (offset == ((off_t)-1)) {
 
689
                        LogDebug("lseek: %s", strerror(errno));
 
690
                        result = TSPERR(TSS_E_INTERNAL_ERROR);
 
691
                        goto err_exit;
 
692
                }
 
693
 
 
694
                /* ignore vendor data for user ps */
 
695
        }
 
696
 
 
697
        *size = num_keys;
 
698
        *c = tmp;
 
699
 
 
700
        return TSS_SUCCESS;
 
701
 
 
702
err_exit:
 
703
        free(tmp);
 
704
        return result;
 
705
}
 
706
 
 
707
TSS_RESULT
 
708
copy_key_info(int fd, TSS_KM_KEYINFO *ki, struct key_disk_cache *c)
 
709
{
 
710
        TCPA_KEY key;
 
711
        BYTE blob[4096];
 
712
        UINT64 offset;
 
713
        TSS_RESULT result;
 
714
        off_t off;
 
715
 
 
716
        /* Set the file pointer to the offset that the key blob is at */
 
717
        off = lseek(fd, TSSPS_BLOB_DATA_OFFSET(c), SEEK_SET);
 
718
        if (off == ((off_t)-1)) {
 
719
                LogDebug("lseek: %s", strerror(errno));
 
720
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
721
        }
 
722
 
 
723
        /* Read in the key blob */
 
724
        if ((result = read_data(fd, (void *)blob, c->blob_size))) {
 
725
                LogDebug("%s", __FUNCTION__);
 
726
                return result;
 
727
        }
 
728
 
 
729
        /* Expand the blob into a useable form */
 
730
        offset = 0;
 
731
        if ((result = Trspi_UnloadBlob_KEY(&offset, blob, &key)))
 
732
                return result;
 
733
 
 
734
        memcpy(&ki->versionInfo, &key.ver, sizeof(TSS_VERSION));
 
735
        memcpy(&ki->keyUUID, &c->uuid, sizeof(TSS_UUID));
 
736
        memcpy(&ki->parentKeyUUID, &c->parent_uuid, sizeof(TSS_UUID));
 
737
        ki->bAuthDataUsage = key.authDataUsage;
 
738
 
 
739
        free_key_refs(&key);
 
740
 
 
741
        return TSS_SUCCESS;
 
742
}
 
743
 
 
744
TSS_RESULT
 
745
psfile_get_registered_keys(int fd,
 
746
                           TSS_UUID *uuid,
 
747
                           TSS_UUID *tcs_uuid,
 
748
                           UINT32 *size,
 
749
                           TSS_KM_KEYINFO **keys)
 
750
{
 
751
        TSS_RESULT result;
 
752
        struct key_disk_cache *cache_entries;
 
753
        UINT32 cache_size, i, j;
 
754
        TSS_KM_KEYINFO *keyinfos = NULL;
 
755
        TSS_UUID *find_uuid;
 
756
 
 
757
        if ((result = psfile_get_all_cache_entries(fd, &cache_size, &cache_entries)))
 
758
                return result;
 
759
 
 
760
        if (cache_size == 0) {
 
761
                if (uuid)
 
762
                        return TSPERR(TSS_E_PS_KEY_NOTFOUND);
 
763
                else {
 
764
                        *size = 0;
 
765
                        *keys = NULL;
 
766
                        return TSS_SUCCESS;
 
767
                }
 
768
        }
 
769
 
 
770
        if (uuid) {
 
771
                find_uuid = uuid;
 
772
                j = 0;
 
773
 
 
774
restart_search:
 
775
                /* Search for the requested UUID.  When found, allocate new space for it, copy
 
776
                 * it in, then change the uuid to be searched for it its parent and start over. */
 
777
                for (i = 0; i < cache_size; i++) {
 
778
                        if (!memcmp(&cache_entries[i].uuid, find_uuid, sizeof(TSS_UUID))) {
 
779
                                if (!(keyinfos = realloc(keyinfos,
 
780
                                                         (j+1) * sizeof(TSS_KM_KEYINFO)))) {
 
781
                                        free(cache_entries);
 
782
                                        free(keyinfos);
 
783
                                        return TSPERR(TSS_E_OUTOFMEMORY);
 
784
                                }
 
785
                                memset(&keyinfos[j], 0, sizeof(TSS_KM_KEYINFO));
 
786
 
 
787
                                if ((result = copy_key_info(fd, &keyinfos[j], &cache_entries[i]))) {
 
788
                                        free(cache_entries);
 
789
                                        free(keyinfos);
 
790
                                        return result;
 
791
                                }
 
792
 
 
793
                                find_uuid = &keyinfos[j].parentKeyUUID;
 
794
                                j++;
 
795
                                goto restart_search;
 
796
                        }
 
797
                }
 
798
 
 
799
                /* Searching for keys in the user PS will always lead us up to some key in the
 
800
                 * system PS. Return that key's uuid so that the upper layers can call down to TCS
 
801
                 * to search for it. */
 
802
                memcpy(tcs_uuid, find_uuid, sizeof(TSS_UUID));
 
803
 
 
804
                *size = j;
 
805
        } else {
 
806
                if ((keyinfos = calloc(cache_size, sizeof(TSS_KM_KEYINFO))) == NULL) {
 
807
                        LogDebug("malloc of %zu bytes failed.",
 
808
                                 cache_size * sizeof(TSS_KM_KEYINFO));
 
809
                        free(cache_entries);
 
810
                        return TSPERR(TSS_E_OUTOFMEMORY);
 
811
                }
 
812
 
 
813
                for (i = 0; i < cache_size; i++) {
 
814
                        if ((result = copy_key_info(fd, &keyinfos[i], &cache_entries[i]))) {
 
815
                                free(cache_entries);
 
816
                                free(keyinfos);
 
817
                                return result;
 
818
                        }
 
819
                }
 
820
 
 
821
                *size = cache_size;
 
822
        }
 
823
 
 
824
        free(cache_entries);
 
825
 
 
826
        *keys = keyinfos;
 
827
 
 
828
        return TSS_SUCCESS;
 
829
}
 
830
 
 
831
 
 
832
/*
 
833
 * read into the PS file and return the number of keys
 
834
 */
 
835
UINT32
 
836
psfile_get_num_keys(int fd)
 
837
{
 
838
        UINT32 num_keys;
 
839
        int rc;
 
840
 
 
841
        /* go to the number of keys */
 
842
        rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
 
843
        if (rc == ((off_t)-1)) {
 
844
                LogDebug("lseek: %s", strerror(errno));
 
845
                return 0;
 
846
        }
 
847
 
 
848
        rc = read(fd, &num_keys, sizeof(UINT32));
 
849
        if (rc < 0) {
 
850
                LogDebug("read of %zd bytes: %s", sizeof(UINT32), strerror(errno));
 
851
                return 0;
 
852
        } else if ((unsigned)rc < sizeof(UINT32)) {
 
853
                num_keys = 0;
 
854
        }
 
855
 
 
856
        return num_keys;
 
857
}
 
858
 
 
859
/*
 
860
 * disk store format:
 
861
 *
 
862
 * TrouSerS 0.2.1+
 
863
 * Version 1:                  cached?
 
864
 * [BYTE     PS version = '\1']
 
865
 * [UINT32   num_keys_on_disk ]
 
866
 * [TSS_UUID uuid0            ] yes
 
867
 * [TSS_UUID uuid_parent0     ] yes
 
868
 * [UINT16   pub_data_size0   ] yes
 
869
 * [UINT16   blob_size0       ] yes
 
870
 * [UINT32   vendor_data_size0] yes
 
871
 * [UINT16   cache_flags0     ] yes
 
872
 * [BYTE[]   pub_data0        ]
 
873
 * [BYTE[]   blob0            ]
 
874
 * [BYTE[]   vendor_data0     ]
 
875
 * [...]
 
876
 *
 
877
 */
 
878
TSS_RESULT
 
879
psfile_get_cache_entry_by_uuid(int fd, TSS_UUID *uuid, struct key_disk_cache *c)
 
880
{
 
881
        UINT32 i, num_keys = psfile_get_num_keys(fd);
 
882
        int offset;
 
883
        TSS_RESULT result;
 
884
        BYTE found = 0;
 
885
 
 
886
        if (num_keys == 0)
 
887
                return TSPERR(TSS_E_PS_KEY_NOTFOUND);
 
888
 
 
889
        /* make sure the file pointer is where we expect, just after the number
 
890
         * of keys on disk at the head of the file
 
891
         */
 
892
        offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
 
893
        if (offset == ((off_t)-1)) {
 
894
                LogDebug("lseek: %s", strerror(errno));
 
895
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
896
        }
 
897
 
 
898
        for (i = 0; i < num_keys && !found; i++) {
 
899
                offset = lseek(fd, 0, SEEK_CUR);
 
900
                if (offset == ((off_t)-1)) {
 
901
                        LogDebug("lseek: %s", strerror(errno));
 
902
                        return TSPERR(TSS_E_INTERNAL_ERROR);
 
903
                }
 
904
                c->offset = offset;
 
905
 
 
906
                /* read UUID */
 
907
                if ((result = read_data(fd, (void *)&c->uuid, sizeof(TSS_UUID)))) {
 
908
                        LogDebug("%s", __FUNCTION__);
 
909
                        return result;
 
910
                }
 
911
 
 
912
                if (!memcmp(&c->uuid, uuid, sizeof(TSS_UUID))) {
 
913
                        found = 1;
 
914
 
 
915
                        /* read parent UUID */
 
916
                        if ((result = read_data(fd, (void *)&c->parent_uuid, sizeof(TSS_UUID)))) {
 
917
                                LogDebug("%s", __FUNCTION__);
 
918
                                return result;
 
919
                        }
 
920
                } else {
 
921
                        /* fast forward over the parent UUID */
 
922
                        offset = lseek(fd, sizeof(TSS_UUID), SEEK_CUR);
 
923
                        if (offset == ((off_t)-1)) {
 
924
                                LogDebug("lseek: %s", strerror(errno));
 
925
                                return TSPERR(TSS_E_INTERNAL_ERROR);
 
926
                        }
 
927
                }
 
928
 
 
929
                /* pub data size */
 
930
                if ((result = read_data(fd, &c->pub_data_size, sizeof(UINT16)))) {
 
931
                        LogDebug("%s", __FUNCTION__);
 
932
                        return result;
 
933
                }
 
934
 
 
935
                DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0);
 
936
 
 
937
                /* blob size */
 
938
                if ((result = read_data(fd, &c->blob_size, sizeof(UINT16)))) {
 
939
                        LogDebug("%s", __FUNCTION__);
 
940
                        return result;
 
941
                }
 
942
 
 
943
                DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0);
 
944
 
 
945
                /* vendor data size */
 
946
                if ((result = read_data(fd, &c->vendor_data_size, sizeof(UINT32)))) {
 
947
                        LogDebug("%s", __FUNCTION__);
 
948
                        return result;
 
949
                }
 
950
 
 
951
                /* cache flags */
 
952
                if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) {
 
953
                        LogDebug("%s", __FUNCTION__);
 
954
                        return result;
 
955
                }
 
956
 
 
957
                /* fast forward over the pub key */
 
958
                offset = lseek(fd, c->pub_data_size, SEEK_CUR);
 
959
                if (offset == ((off_t)-1)) {
 
960
                        LogDebug("lseek: %s", strerror(errno));
 
961
                        return TSPERR(TSS_E_INTERNAL_ERROR);
 
962
                }
 
963
 
 
964
                /* fast forward over the blob */
 
965
                offset = lseek(fd, c->blob_size, SEEK_CUR);
 
966
                if (offset == ((off_t)-1)) {
 
967
                        LogDebug("lseek: %s", strerror(errno));
 
968
                        return TSPERR(TSS_E_INTERNAL_ERROR);
 
969
                }
 
970
 
 
971
                /* ignore vendor data in user ps */
 
972
        }
 
973
 
 
974
        return found ? TSS_SUCCESS : TSPERR(TSS_E_PS_KEY_NOTFOUND);
 
975
}
 
976
 
 
977
TSS_RESULT
 
978
psfile_get_cache_entry_by_pub(int fd, UINT32 pub_size, BYTE *pub, struct key_disk_cache *c)
 
979
{
 
980
        BYTE blob[2048];
 
981
        UINT32 i, num_keys = psfile_get_num_keys(fd);
 
982
        int offset;
 
983
        TSS_RESULT result;
 
984
 
 
985
        if (num_keys == 0)
 
986
                return TSPERR(TSS_E_PS_KEY_NOTFOUND);
 
987
 
 
988
        /* make sure the file pointer is where we expect, just after the number
 
989
         * of keys on disk at the head of the file
 
990
         */
 
991
        offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
 
992
        if (offset == ((off_t)-1)) {
 
993
                LogDebug("lseek: %s", strerror(errno));
 
994
                return TSPERR(TSS_E_INTERNAL_ERROR);
 
995
        }
 
996
 
 
997
        for (i = 0; i < num_keys; i++) {
 
998
                offset = lseek(fd, 0, SEEK_CUR);
 
999
                if (offset == ((off_t)-1)) {
 
1000
                        LogDebug("lseek: %s", strerror(errno));
 
1001
                        return TSPERR(TSS_E_INTERNAL_ERROR);
 
1002
                }
 
1003
                c->offset = offset;
 
1004
 
 
1005
                /* read UUID */
 
1006
                if ((result = read_data(fd, (void *)&c->uuid, sizeof(TSS_UUID)))) {
 
1007
                        LogDebug("%s", __FUNCTION__);
 
1008
                        return result;
 
1009
                }
 
1010
 
 
1011
                /* read parent UUID */
 
1012
                if ((result = read_data(fd, (void *)&c->parent_uuid, sizeof(TSS_UUID)))) {
 
1013
                        LogDebug("%s", __FUNCTION__);
 
1014
                        return result;
 
1015
                }
 
1016
 
 
1017
                /* pub data size */
 
1018
                if ((result = read_data(fd, &c->pub_data_size, sizeof(UINT16)))) {
 
1019
                        LogDebug("%s", __FUNCTION__);
 
1020
                        return result;
 
1021
                }
 
1022
 
 
1023
                DBG_ASSERT(c->pub_data_size <= 2048 && c->pub_data_size > 0);
 
1024
 
 
1025
                /* blob size */
 
1026
                if ((result = read_data(fd, &c->blob_size, sizeof(UINT16)))) {
 
1027
                        LogDebug("%s", __FUNCTION__);
 
1028
                        return result;
 
1029
                }
 
1030
 
 
1031
                DBG_ASSERT(c->blob_size <= 4096 && c->blob_size > 0);
 
1032
 
 
1033
                /* vendor data size */
 
1034
                if ((result = read_data(fd, &c->vendor_data_size, sizeof(UINT32)))) {
 
1035
                        LogDebug("%s", __FUNCTION__);
 
1036
                        return result;
 
1037
                }
 
1038
 
 
1039
                /* cache flags */
 
1040
                if ((result = read_data(fd, &c->flags, sizeof(UINT16)))) {
 
1041
                        LogDebug("%s", __FUNCTION__);
 
1042
                        return result;
 
1043
                }
 
1044
 
 
1045
                if (c->pub_data_size == pub_size) {
 
1046
                        /* read in the pub key */
 
1047
                        if ((result = read_data(fd, blob, c->pub_data_size))) {
 
1048
                                LogDebug("%s", __FUNCTION__);
 
1049
                                return result;
 
1050
                        }
 
1051
 
 
1052
                        if (!memcmp(blob, pub, pub_size))
 
1053
                                break;
 
1054
                }
 
1055
 
 
1056
                /* fast forward over the blob */
 
1057
                offset = lseek(fd, c->blob_size, SEEK_CUR);
 
1058
                if (offset == ((off_t)-1)) {
 
1059
                        LogDebug("lseek: %s", strerror(errno));
 
1060
                        return TSPERR(TSS_E_INTERNAL_ERROR);
 
1061
                }
 
1062
 
 
1063
                /* ignore vendor data */
 
1064
        }
 
1065
 
 
1066
        return TSS_SUCCESS;
 
1067
}