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