Home | History | Annotate | Line # | Download | only in ps
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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