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