1 /*
2 * Licensed Materials - Property of IBM
3 *
4 * trousers - An open source TCG Software Stack
5 *
6 * (C) Copyright International Business Machines Corp. 2004
7 *
8 */
9
10
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #if defined(HAVE_BYTEORDER_H)
17 #include <sys/byteorder.h>
18 #elif defined(HTOLE_DEFINED)
19
20 #ifndef __APPLE__
21 #include <endian.h>
22 #else
23 #include "portable_endian.h"
24 #endif
25
26 #define LE_16 htole16
27 #define LE_32 htole32
28 #define LE_64 htole64
29 #else
30 #define LE_16(x) (x)
31 #define LE_32(x) (x)
32 #define LE_64(x) (x)
33 #endif
34 #include <fcntl.h>
35 #include <string.h>
36 #include <limits.h>
37 #include <assert.h>
38 #include <errno.h>
39
40 #include "trousers/tss.h"
41 #include "trousers_types.h"
42 #include "tcs_int_literals.h"
43 #include "tcsps.h"
44 #include "tcs_tsp.h"
45 #include "tcs_utils.h"
46 #include "tcslog.h"
47
48 struct key_disk_cache *key_disk_cache_head = NULL;
49
50
51 TSS_RESULT
read_data(int fd,void * data,UINT32 size)52 read_data(int fd, void *data, UINT32 size)
53 {
54 int rc;
55
56 rc = read(fd, data, size);
57 if (rc == -1) {
58 LogError("read of %d bytes: %s", size, strerror(errno));
59 return TCSERR(TSS_E_INTERNAL_ERROR);
60 } else if ((unsigned)rc != size) {
61 LogError("read of %d bytes (only %d read)", size, rc);
62 return TCSERR(TSS_E_INTERNAL_ERROR);
63 }
64
65 return TSS_SUCCESS;
66 }
67
68
69 TSS_RESULT
write_data(int fd,void * data,UINT32 size)70 write_data(int fd, void *data, UINT32 size)
71 {
72 int rc;
73
74 rc = write(fd, data, size);
75 if (rc == -1) {
76 LogError("write of %d bytes: %s", size, strerror(errno));
77 return TCSERR(TSS_E_INTERNAL_ERROR);
78 } else if ((unsigned)rc != size) {
79 LogError("write of %d bytes (only %d written)", size, rc);
80 return TCSERR(TSS_E_INTERNAL_ERROR);
81 }
82
83 return TSS_SUCCESS;
84 }
85
86 /*
87 * called by write_key_init to find the next available location in the PS file to
88 * write a new key to.
89 */
90 int
find_write_offset(UINT32 pub_data_size,UINT32 blob_size,UINT32 vendor_data_size)91 find_write_offset(UINT32 pub_data_size, UINT32 blob_size, UINT32 vendor_data_size)
92 {
93 struct key_disk_cache *tmp;
94 unsigned int offset;
95
96 MUTEX_LOCK(disk_cache_lock);
97
98 tmp = key_disk_cache_head;
99 while (tmp) {
100 /* if we find a deleted key of the right size, return its offset */
101 if (!(tmp->flags & CACHE_FLAG_VALID) &&
102 tmp->pub_data_size == pub_data_size &&
103 tmp->blob_size == blob_size &&
104 tmp->vendor_data_size == vendor_data_size) {
105 offset = tmp->offset;
106 MUTEX_UNLOCK(disk_cache_lock);
107 return offset;
108 }
109 tmp = tmp->next;
110 }
111
112 MUTEX_UNLOCK(disk_cache_lock);
113
114 /* no correctly sized holes */
115 return -1;
116 }
117
118 /*
119 * move the file pointer to the point where the next key can be written and return
120 * that offset
121 */
122 int
write_key_init(int fd,UINT32 pub_data_size,UINT32 blob_size,UINT32 vendor_data_size)123 write_key_init(int fd, UINT32 pub_data_size, UINT32 blob_size, UINT32 vendor_data_size)
124 {
125 UINT32 num_keys;
126 BYTE version;
127 int rc, offset;
128
129 /* seek to the PS version */
130 rc = lseek(fd, TSSPS_VERSION_OFFSET, SEEK_SET);
131 if (rc == ((off_t) - 1)) {
132 LogError("lseek: %s", strerror(errno));
133 return -1;
134 }
135
136 /* go to NUM_KEYS */
137 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
138 if (rc == ((off_t) - 1)) {
139 LogError("lseek: %s", strerror(errno));
140 return -1;
141 }
142
143 /* read the number of keys */
144 rc = read(fd, &num_keys, sizeof(UINT32));
145 num_keys = LE_32(num_keys);
146 if (rc == -1) {
147 LogError("read of %zd bytes: %s", sizeof(UINT32), strerror(errno));
148 return -1;
149 } else if (rc == 0) {
150 /* This is the first key being written */
151 num_keys = 1;
152 version = 1;
153
154 /* seek to the PS version */
155 rc = lseek(fd, TSSPS_VERSION_OFFSET, SEEK_SET);
156 if (rc == ((off_t) - 1)) {
157 LogError("lseek: %s", strerror(errno));
158 return -1;
159 }
160
161 /* write out the version info byte */
162 if ((rc = write_data(fd, &version, sizeof(BYTE)))) {
163 LogError("%s", __FUNCTION__);
164 return rc;
165 }
166
167 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
168 if (rc == ((off_t) - 1)) {
169 LogError("lseek: %s", strerror(errno));
170 return -1;
171 }
172
173 num_keys = LE_32(num_keys);
174 if ((rc = write_data(fd, &num_keys, sizeof(UINT32)))) {
175 LogError("%s", __FUNCTION__);
176 return rc;
177 }
178
179 /* return the offset */
180 return (TSSPS_NUM_KEYS_OFFSET + sizeof(UINT32));
181 }
182
183 /* if there is a hole in the file we can write to, find it */
184 offset = find_write_offset(pub_data_size, blob_size, vendor_data_size);
185
186 if (offset != -1) {
187 /* we found a hole, seek to it and don't increment the # of keys on disk */
188 rc = lseek(fd, offset, SEEK_SET);
189 } else {
190 /* we didn't find a hole, increment the number of keys on disk and seek
191 * to the end of the file
192 */
193 num_keys++;
194
195 /* go to the beginning */
196 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
197 if (rc == ((off_t) - 1)) {
198 LogError("lseek: %s", strerror(errno));
199 return -1;
200 }
201 num_keys = LE_32(num_keys);
202 if ((rc = write_data(fd, &num_keys, sizeof(UINT32)))) {
203 LogError("%s", __FUNCTION__);
204 return rc;
205 }
206
207 rc = lseek(fd, 0, SEEK_END);
208 }
209 if (rc == ((off_t) - 1)) {
210 LogError("lseek: %s", strerror(errno));
211 return -1;
212 }
213
214 /* lseek returns the number of bytes of offset from the beginning of the file */
215 return rc;
216 }
217
218 /*
219 * add a new cache entry for a written key
220 */
221 TSS_RESULT
cache_key(UINT32 offset,UINT16 flags,TSS_UUID * uuid,TSS_UUID * parent_uuid,UINT16 pub_data_size,UINT32 blob_size,UINT32 vendor_data_size)222 cache_key(UINT32 offset, UINT16 flags,
223 TSS_UUID *uuid, TSS_UUID *parent_uuid,
224 UINT16 pub_data_size, UINT32 blob_size,
225 UINT32 vendor_data_size)
226 {
227 struct key_disk_cache *tmp;
228
229 MUTEX_LOCK(disk_cache_lock);
230
231 tmp = key_disk_cache_head;
232
233 for (; tmp; tmp = tmp->next) {
234 /* reuse an invalidated key cache entry */
235 if (!(tmp->flags & CACHE_FLAG_VALID))
236 goto fill_cache_entry;
237 }
238
239 tmp = malloc(sizeof(struct key_disk_cache));
240 if (tmp == NULL) {
241 LogError("malloc of %zd bytes failed.", sizeof(struct key_disk_cache));
242 MUTEX_UNLOCK(disk_cache_lock);
243 return TCSERR(TSS_E_OUTOFMEMORY);
244 }
245 tmp->next = key_disk_cache_head;
246 key_disk_cache_head = tmp;
247
248 fill_cache_entry:
249 tmp->offset = offset;
250 #ifdef TSS_DEBUG
251 if (offset == 0)
252 LogDebug("Storing key with file offset==0!!!");
253 #endif
254 tmp->flags = flags;
255 tmp->blob_size = blob_size;
256 tmp->pub_data_size = pub_data_size;
257 tmp->vendor_data_size = vendor_data_size;
258 memcpy(&tmp->uuid, uuid, sizeof(TSS_UUID));
259 memcpy(&tmp->parent_uuid, parent_uuid, sizeof(TSS_UUID));
260
261 MUTEX_UNLOCK(disk_cache_lock);
262 return TSS_SUCCESS;
263 }
264
265 /*
266 * read into the PS file and return the number of keys
267 */
268 int
get_num_keys_in_file(int fd)269 get_num_keys_in_file(int fd)
270 {
271 UINT32 num_keys;
272 int rc;
273
274 /* go to the number of keys */
275 rc = lseek(fd, TSSPS_NUM_KEYS_OFFSET, SEEK_SET);
276 if (rc == ((off_t) - 1)) {
277 LogError("lseek: %s", strerror(errno));
278 return 0;
279 }
280
281 rc = read(fd, &num_keys, sizeof(UINT32));
282 if (rc < 0) {
283 LogError("read of %zd bytes: %s", sizeof(UINT32), strerror(errno));
284 return 0;
285 } else if ((unsigned)rc < sizeof(UINT32)) {
286 num_keys = 0;
287 }
288 num_keys = LE_32(num_keys);
289
290 return num_keys;
291 }
292
293 /*
294 * count the number of valid keys in the cache
295 */
296 int
get_num_keys()297 get_num_keys()
298 {
299 int num_keys = 0;
300 struct key_disk_cache *tmp;
301
302 MUTEX_LOCK(disk_cache_lock);
303
304 tmp = key_disk_cache_head;
305
306 for (; tmp; tmp = tmp->next) {
307 if (tmp->flags & CACHE_FLAG_VALID)
308 num_keys++;
309 }
310
311 MUTEX_UNLOCK(disk_cache_lock);
312 return num_keys;
313 }
314
315 /*
316 * disk store format:
317 *
318 * TrouSerS 0.2.0 and before:
319 * Version 0: cached?
320 * [UINT32 num_keys_on_disk]
321 * [TSS_UUID uuid0 ] yes
322 * [TSS_UUID uuid_parent0 ] yes
323 * [UINT16 pub_data_size0 ] yes
324 * [UINT16 blob_size0 ] yes
325 * [UINT16 cache_flags0 ] yes
326 * [BYTE[] pub_data0 ]
327 * [BYTE[] blob0 ]
328 * [...]
329 *
330 * TrouSerS 0.2.1+
331 * Version 1: cached?
332 * [BYTE PS version = '\1']
333 * [UINT32 num_keys_on_disk ]
334 * [TSS_UUID uuid0 ] yes
335 * [TSS_UUID uuid_parent0 ] yes
336 * [UINT16 pub_data_size0 ] yes
337 * [UINT16 blob_size0 ] yes
338 * [UINT32 vendor_data_size0] yes
339 * [UINT16 cache_flags0 ] yes
340 * [BYTE[] pub_data0 ]
341 * [BYTE[] blob0 ]
342 * [BYTE[] vendor_data0 ]
343 * [...]
344 *
345 */
346 /*
347 * read the PS file pointed to by fd and create a cache based on it
348 */
349 int
init_disk_cache(int fd)350 init_disk_cache(int fd)
351 {
352 UINT32 num_keys = get_num_keys_in_file(fd);
353 UINT16 i;
354 UINT64 tmp_offset;
355 int rc = 0, offset;
356 struct key_disk_cache *tmp, *prev = NULL;
357 BYTE srk_blob[2048];
358 TSS_KEY srk_key;
359 #ifdef TSS_DEBUG
360 int valid_keys = 0;
361 #endif
362
363 MUTEX_LOCK(disk_cache_lock);
364
365 if (num_keys == 0) {
366 key_disk_cache_head = NULL;
367 MUTEX_UNLOCK(disk_cache_lock);
368 return 0;
369 } else {
370 key_disk_cache_head = tmp = calloc(1, sizeof(struct key_disk_cache));
371 if (tmp == NULL) {
372 LogError("malloc of %zd bytes failed.",
373 sizeof(struct key_disk_cache));
374 rc = -1;
375 goto err_exit;
376 }
377 }
378
379 /* make sure the file pointer is where we expect, just after the number
380 * of keys on disk at the head of the file
381 */
382 offset = lseek(fd, TSSPS_KEYS_OFFSET, SEEK_SET);
383 if (offset == ((off_t) - 1)) {
384 LogError("lseek: %s", strerror(errno));
385 rc = -1;
386 goto err_exit;
387 }
388
389 for (i=0; i<num_keys; i++) {
390 offset = lseek(fd, 0, SEEK_CUR);
391 if (offset == ((off_t) - 1)) {
392 LogError("lseek: %s", strerror(errno));
393 rc = -1;
394 goto err_exit;
395 }
396 tmp->offset = offset;
397 #ifdef TSS_DEBUG
398 if (offset == 0)
399 LogDebug("Storing key with file offset==0!!!");
400 #endif
401 /* read UUID */
402 if ((rc = read_data(fd, (void *)&tmp->uuid, sizeof(TSS_UUID)))) {
403 LogError("%s", __FUNCTION__);
404 goto err_exit;
405 }
406
407 /* read parent UUID */
408 if ((rc = read_data(fd, (void *)&tmp->parent_uuid, sizeof(TSS_UUID)))) {
409 LogError("%s", __FUNCTION__);
410 goto err_exit;
411 }
412
413 /* pub data size */
414 if ((rc = read_data(fd, &tmp->pub_data_size, sizeof(UINT16)))) {
415 LogError("%s", __FUNCTION__);
416 goto err_exit;
417 }
418 tmp->pub_data_size = LE_16(tmp->pub_data_size);
419
420 DBG_ASSERT(tmp->pub_data_size <= 2048 && tmp->pub_data_size > 0);
421
422 /* blob size */
423 if ((rc = read_data(fd, &tmp->blob_size, sizeof(UINT16)))) {
424 LogError("%s", __FUNCTION__);
425 goto err_exit;
426 }
427 tmp->blob_size = LE_16(tmp->blob_size);
428 DBG_ASSERT(tmp->blob_size <= 4096 && tmp->blob_size > 0);
429
430 /* vendor data size */
431 if ((rc = read_data(fd, &tmp->vendor_data_size, sizeof(UINT32)))) {
432 LogError("%s", __FUNCTION__);
433 goto err_exit;
434 }
435 tmp->vendor_data_size = LE_32(tmp->vendor_data_size);
436
437 /* cache flags */
438 if ((rc = read_data(fd, &tmp->flags, sizeof(UINT16)))) {
439 LogError("%s", __FUNCTION__);
440 goto err_exit;
441 }
442 tmp->flags = LE_16(tmp->flags);
443
444 #ifdef TSS_DEBUG
445 if (tmp->flags & CACHE_FLAG_VALID)
446 valid_keys++;
447 #endif
448 /* fast forward over the pub key */
449 offset = lseek(fd, tmp->pub_data_size, SEEK_CUR);
450 if (offset == ((off_t) - 1)) {
451 LogError("lseek: %s", strerror(errno));
452 rc = -1;
453 goto err_exit;
454 }
455
456 /* if this is the SRK, load it into memory, since its already loaded in
457 * the chip */
458 if (!memcmp(&SRK_UUID, &tmp->uuid, sizeof(TSS_UUID))) {
459 /* read SRK blob from disk */
460 if ((rc = read_data(fd, srk_blob, tmp->blob_size))) {
461 LogError("%s", __FUNCTION__);
462 goto err_exit;
463 }
464
465 tmp_offset = 0;
466 if ((rc = UnloadBlob_TSS_KEY(&tmp_offset, srk_blob, &srk_key)))
467 goto err_exit;
468 /* add to the mem cache */
469 if ((rc = mc_add_entry_init(SRK_TPM_HANDLE, SRK_TPM_HANDLE, &srk_key,
470 &SRK_UUID))) {
471 LogError("Error adding SRK to mem cache.");
472 destroy_key_refs(&srk_key);
473 goto err_exit;
474 }
475 destroy_key_refs(&srk_key);
476 } else {
477 /* fast forward over the blob */
478 offset = lseek(fd, tmp->blob_size, SEEK_CUR);
479 if (offset == ((off_t) - 1)) {
480 LogError("lseek: %s", strerror(errno));
481 rc = -1;
482 goto err_exit;
483 }
484
485 /* fast forward over the vendor data */
486 offset = lseek(fd, tmp->vendor_data_size, SEEK_CUR);
487 if (offset == ((off_t) - 1)) {
488 LogError("lseek: %s", strerror(errno));
489 rc = -1;
490 goto err_exit;
491 }
492 }
493
494 tmp->next = calloc(1, sizeof(struct key_disk_cache));
495 if (tmp->next == NULL) {
496 LogError("malloc of %zd bytes failed.",
497 sizeof(struct key_disk_cache));
498 rc = -1;
499 goto err_exit;
500 }
501 prev = tmp;
502 tmp = tmp->next;
503 }
504
505 /* delete the dangling, unfilled cache entry */
506 free(tmp);
507 prev->next = NULL;
508 rc = 0;
509 LogDebug("%s: found %d valid key(s) on disk.\n", __FUNCTION__, valid_keys);
510
511 err_exit:
512 MUTEX_UNLOCK(disk_cache_lock);
513 return rc;
514 }
515
516 int
close_disk_cache(int fd)517 close_disk_cache(int fd)
518 {
519 struct key_disk_cache *tmp, *tmp_next;
520
521 if (key_disk_cache_head == NULL)
522 return 0;
523
524 MUTEX_LOCK(disk_cache_lock);
525 tmp = key_disk_cache_head;
526
527 do {
528 tmp_next = tmp->next;
529 free(tmp);
530 tmp = tmp_next;
531 } while (tmp);
532
533 MUTEX_UNLOCK(disk_cache_lock);
534
535 return 0;
536 }
537