1/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 * 5 * Tests for rollback_index functions 6 */ 7 8#include <stdint.h> 9#include <stdio.h> 10#include <stdlib.h> 11#include <string.h> 12 13#define _STUB_IMPLEMENTATION_ /* So we can use memset() ourselves */ 14 15#include "crc8.h" 16#include "rollback_index.h" 17#include "test_common.h" 18#include "tlcl.h" 19#include "utility.h" 20#include "vboot_common.h" 21 22/* 23 * Buffer to hold accumulated list of calls to mocked Tlcl functions. 24 * Each function appends itself to the buffer and updates mock_cnext. 25 * 26 * Size of mock_calls[] should be big enough to handle all expected 27 * call sequences; 16KB should be plenty since none of the sequences 28 * below is more than a few hundred bytes. We could be more clever 29 * and use snprintf() with length checking below, at the expense of 30 * making all the mock implementations bigger. If this were code used 31 * outside of unit tests we'd want to do that, but here if we did 32 * overrun the buffer the worst that's likely to happen is we'll crash 33 * the test, and crash = failure anyway. 34 */ 35static char mock_calls[16384]; 36static char *mock_cnext = mock_calls; 37 38/* 39 * Variables to support mocked error values from Tlcl functions. Each 40 * call, mock_count is incremented. If mock_count==fail_at_count, return 41 * fail_with_error instead of the normal return value. 42 */ 43static int mock_count = 0; 44static int fail_at_count = 0; 45static uint32_t fail_with_error = TPM_SUCCESS; 46 47/* Similar, to determine when to inject noise during reads & writes */ 48#define MAX_NOISE_COUNT 64 /* no noise after this many */ 49static int noise_count = 0; /* read/write attempt (zero-based) */ 50static int noise_on[MAX_NOISE_COUNT]; /* calls to inject noise on */ 51 52/* Params / backing store for mocked Tlcl functions. */ 53static TPM_PERMANENT_FLAGS mock_pflags; 54static RollbackSpaceFirmware mock_rsf; 55static RollbackSpaceKernel mock_rsk; 56static uint32_t mock_permissions; 57 58/* Reset the variables for the Tlcl mock functions. */ 59static void ResetMocks(int fail_on_call, uint32_t fail_with_err) 60{ 61 *mock_calls = 0; 62 mock_cnext = mock_calls; 63 mock_count = 0; 64 fail_at_count = fail_on_call; 65 fail_with_error = fail_with_err; 66 noise_count = 0; 67 Memset(&noise_on, 0, sizeof(noise_on)); 68 69 Memset(&mock_pflags, 0, sizeof(mock_pflags)); 70 Memset(&mock_rsf, 0, sizeof(mock_rsf)); 71 Memset(&mock_rsk, 0, sizeof(mock_rsk)); 72 mock_permissions = 0; 73} 74 75/****************************************************************************/ 76/* Function to garble data on its way to or from the TPM */ 77static void MaybeInjectNoise(void *data, uint32_t length) 78{ 79 if (noise_count < MAX_NOISE_COUNT && noise_on[noise_count]) { 80 uint8_t *val = data; 81 val[length - 1]++; 82 } 83 noise_count++; 84} 85 86/****************************************************************************/ 87/* Mocks for tlcl functions which log the calls made to mock_calls[]. */ 88 89uint32_t TlclLibInit(void) 90{ 91 mock_cnext += sprintf(mock_cnext, "TlclLibInit()\n"); 92 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 93} 94 95uint32_t TlclStartup(void) 96{ 97 mock_cnext += sprintf(mock_cnext, "TlclStartup()\n"); 98 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 99} 100 101uint32_t TlclResume(void) 102{ 103 mock_cnext += sprintf(mock_cnext, "TlclResume()\n"); 104 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 105} 106 107uint32_t TlclForceClear(void) 108{ 109 mock_cnext += sprintf(mock_cnext, "TlclForceClear()\n"); 110 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 111} 112 113uint32_t TlclSetEnable(void) 114{ 115 mock_cnext += sprintf(mock_cnext, "TlclSetEnable()\n"); 116 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 117} 118 119uint32_t TlclSetDeactivated(uint8_t flag) 120{ 121 mock_cnext += sprintf(mock_cnext, "TlclSetDeactivated(%d)\n", flag); 122 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 123} 124 125uint32_t TlclRead(uint32_t index, void* data, uint32_t length) 126{ 127 mock_cnext += sprintf(mock_cnext, "TlclRead(0x%x, %d)\n", 128 index, length); 129 130 if (FIRMWARE_NV_INDEX == index) { 131 TEST_EQ(length, sizeof(mock_rsf), "TlclRead rsf size"); 132 Memcpy(data, &mock_rsf, length); 133 MaybeInjectNoise(data, length); 134 } else if (KERNEL_NV_INDEX == index) { 135 TEST_EQ(length, sizeof(mock_rsk), "TlclRead rsk size"); 136 Memcpy(data, &mock_rsk, length); 137 MaybeInjectNoise(data, length); 138 } else { 139 Memset(data, 0, length); 140 } 141 142 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 143} 144 145uint32_t TlclWrite(uint32_t index, const void *data, uint32_t length) 146{ 147 mock_cnext += sprintf(mock_cnext, "TlclWrite(0x%x, %d)\n", 148 index, length); 149 150 if (FIRMWARE_NV_INDEX == index) { 151 TEST_EQ(length, sizeof(mock_rsf), "TlclWrite rsf size"); 152 Memcpy(&mock_rsf, data, length); 153 MaybeInjectNoise(&mock_rsf, length); 154 } else if (KERNEL_NV_INDEX == index) { 155 TEST_EQ(length, sizeof(mock_rsk), "TlclWrite rsk size"); 156 Memcpy(&mock_rsk, data, length); 157 MaybeInjectNoise(&mock_rsk, length); 158 } 159 160 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 161} 162 163uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) 164{ 165 mock_cnext += sprintf(mock_cnext, "TlclDefineSpace(0x%x, 0x%x, %d)\n", 166 index, perm, size); 167 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 168} 169 170uint32_t TlclSelfTestFull(void) 171{ 172 mock_cnext += sprintf(mock_cnext, "TlclSelfTestFull()\n"); 173 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 174} 175 176uint32_t TlclContinueSelfTest(void) 177{ 178 mock_cnext += sprintf(mock_cnext, "TlclContinueSelfTest()\n"); 179 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 180} 181 182uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags) 183{ 184 mock_cnext += sprintf(mock_cnext, "TlclGetPermanentFlags()\n"); 185 Memcpy(pflags, &mock_pflags, sizeof(mock_pflags)); 186 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 187} 188 189/* TlclGetFlags() doesn't need mocking; it calls TlclGetPermanentFlags() */ 190 191uint32_t TlclAssertPhysicalPresence(void) 192{ 193 mock_cnext += sprintf(mock_cnext, "TlclAssertPhysicalPresence()\n"); 194 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 195} 196 197uint32_t TlclFinalizePhysicalPresence(void) 198{ 199 mock_cnext += sprintf(mock_cnext, "TlclFinalizePhysicalPresence()\n"); 200 mock_pflags.physicalPresenceLifetimeLock = 1; 201 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 202} 203 204uint32_t TlclPhysicalPresenceCMDEnable(void) 205{ 206 mock_cnext += sprintf(mock_cnext, "TlclPhysicalPresenceCMDEnable()\n"); 207 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 208} 209 210uint32_t TlclSetNvLocked(void) 211{ 212 mock_cnext += sprintf(mock_cnext, "TlclSetNvLocked()\n"); 213 mock_pflags.nvLocked = 1; 214 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 215} 216 217uint32_t TlclSetGlobalLock(void) 218{ 219 mock_cnext += sprintf(mock_cnext, "TlclSetGlobalLock()\n"); 220 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 221} 222 223uint32_t TlclLockPhysicalPresence(void) 224{ 225 mock_cnext += sprintf(mock_cnext, "TlclLockPhysicalPresence()\n"); 226 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 227} 228 229uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) 230{ 231 mock_cnext += sprintf(mock_cnext, "TlclGetPermissions(0x%x)\n", index); 232 *permissions = mock_permissions; 233 return (++mock_count == fail_at_count) ? fail_with_error : TPM_SUCCESS; 234} 235 236/****************************************************************************/ 237/* Tests for CRC errors */ 238 239extern uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf); 240extern uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf); 241 242static void CrcTestFirmware(void) 243{ 244 RollbackSpaceFirmware rsf; 245 246 /* Noise on reading, shouldn't matter here because version == 0 */ 247 ResetMocks(0, 0); 248 noise_on[0] = 1; 249 TEST_EQ(ReadSpaceFirmware(&rsf), 0, "ReadSpaceFirmware(), v0"); 250 TEST_STR_EQ(mock_calls, 251 "TlclRead(0x1007, 10)\n", 252 "tlcl calls"); 253 254 /* 255 * But if the version >= 2, it will try three times and fail because 256 * the CRC is no good. 257 */ 258 ResetMocks(0, 0); 259 mock_rsf.struct_version = 2; 260 TEST_EQ(ReadSpaceFirmware(&rsf), TPM_E_CORRUPTED_STATE, 261 "ReadSpaceFirmware(), v2, bad CRC"); 262 TEST_STR_EQ(mock_calls, 263 "TlclRead(0x1007, 10)\n" 264 "TlclRead(0x1007, 10)\n" 265 "TlclRead(0x1007, 10)\n", 266 "tlcl calls"); 267 268 /* If the CRC is good and some noise happens, it should recover. */ 269 ResetMocks(0, 0); 270 mock_rsf.struct_version = 2; 271 mock_rsf.crc8 = Crc8(&mock_rsf, offsetof(RollbackSpaceFirmware, crc8)); 272 noise_on[0] = 1; 273 TEST_EQ(ReadSpaceFirmware(&rsf), 0, 274 "ReadSpaceFirmware(), v2, good CRC"); 275 TEST_STR_EQ(mock_calls, 276 "TlclRead(0x1007, 10)\n" 277 "TlclRead(0x1007, 10)\n", 278 "tlcl calls"); 279 280 /* A write with version < 2 should convert to v2 and create the CRC */ 281 ResetMocks(0, 0); 282 Memset(&rsf, 0, sizeof(rsf)); 283 TEST_EQ(WriteSpaceFirmware(&rsf), 0, "WriteSpaceFirmware(), v0"); 284 TEST_EQ(mock_rsf.struct_version, 2, "WriteSpaceFirmware(), check v2"); 285 TEST_STR_EQ(mock_calls, 286 "TlclWrite(0x1007, 10)\n" 287 "TlclRead(0x1007, 10)\n", 288 "tlcl calls"); 289 290 /* Same as above, but with some noise during the readback */ 291 ResetMocks(0, 0); 292 Memset(&rsf, 0, sizeof(rsf)); 293 noise_on[1] = 1; 294 noise_on[2] = 1; 295 TEST_EQ(WriteSpaceFirmware(&rsf), 0, 296 "WriteSpaceFirmware(), read noise"); 297 TEST_STR_EQ(mock_calls, 298 "TlclWrite(0x1007, 10)\n" 299 "TlclRead(0x1007, 10)\n" 300 "TlclRead(0x1007, 10)\n" 301 "TlclRead(0x1007, 10)\n", 302 "tlcl calls"); 303 304 /* With noise during the write, we'll try the write again */ 305 ResetMocks(0, 0); 306 Memset(&rsf, 0, sizeof(rsf)); 307 noise_on[0] = 1; 308 TEST_EQ(WriteSpaceFirmware(&rsf), 0, 309 "WriteSpaceFirmware(), write noise"); 310 TEST_EQ(mock_rsf.struct_version, 2, "WriteSpaceFirmware(), check v2"); 311 TEST_STR_EQ(mock_calls, 312 "TlclWrite(0x1007, 10)\n" 313 "TlclRead(0x1007, 10)\n" 314 "TlclRead(0x1007, 10)\n" 315 "TlclRead(0x1007, 10)\n" 316 "TlclWrite(0x1007, 10)\n" 317 "TlclRead(0x1007, 10)\n", 318 "tlcl calls"); 319 320 /* Only if it just keeps on failing forever do we eventually give up */ 321 ResetMocks(0, 0); 322 Memset(&rsf, 0, sizeof(rsf)); 323 Memset(noise_on, 1, sizeof(noise_on)); 324 TEST_EQ(WriteSpaceFirmware(&rsf), TPM_E_CORRUPTED_STATE, 325 "WriteSpaceFirmware(), always noise"); 326 TEST_STR_EQ(mock_calls, 327 "TlclWrite(0x1007, 10)\n" 328 "TlclRead(0x1007, 10)\n" 329 "TlclRead(0x1007, 10)\n" 330 "TlclRead(0x1007, 10)\n" 331 "TlclWrite(0x1007, 10)\n" 332 "TlclRead(0x1007, 10)\n" 333 "TlclRead(0x1007, 10)\n" 334 "TlclRead(0x1007, 10)\n" 335 "TlclWrite(0x1007, 10)\n" 336 "TlclRead(0x1007, 10)\n" 337 "TlclRead(0x1007, 10)\n" 338 "TlclRead(0x1007, 10)\n", 339 "tlcl calls"); 340} 341 342extern uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk); 343extern uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk); 344 345static void CrcTestKernel(void) 346{ 347 RollbackSpaceKernel rsk; 348 349 /* Noise on reading shouldn't matter here because version == 0 */ 350 ResetMocks(0, 0); 351 noise_on[0] = 1; 352 TEST_EQ(ReadSpaceKernel(&rsk), 0, "ReadSpaceKernel(), v0"); 353 TEST_STR_EQ(mock_calls, 354 "TlclRead(0x1008, 13)\n", 355 "tlcl calls"); 356 357 /* 358 * But if the version >= 2, it will try three times and fail because 359 * the CRC is no good. 360 */ 361 ResetMocks(0, 0); 362 mock_rsk.struct_version = 2; 363 TEST_EQ(ReadSpaceKernel(&rsk), TPM_E_CORRUPTED_STATE, 364 "ReadSpaceKernel(), v2, bad CRC"); 365 TEST_STR_EQ(mock_calls, 366 "TlclRead(0x1008, 13)\n" 367 "TlclRead(0x1008, 13)\n" 368 "TlclRead(0x1008, 13)\n", 369 "tlcl calls"); 370 371 /* If the CRC is good and some noise happens, it should recover. */ 372 ResetMocks(0, 0); 373 mock_rsk.struct_version = 2; 374 mock_rsk.crc8 = Crc8(&mock_rsk, offsetof(RollbackSpaceKernel, crc8)); 375 noise_on[0] = 1; 376 TEST_EQ(ReadSpaceKernel(&rsk), 0, "ReadSpaceKernel(), v2, good CRC"); 377 TEST_STR_EQ(mock_calls, 378 "TlclRead(0x1008, 13)\n" 379 "TlclRead(0x1008, 13)\n", 380 "tlcl calls"); 381 382 /* A write with version < 2 should convert to v2 and create the CRC */ 383 ResetMocks(0, 0); 384 Memset(&rsk, 0, sizeof(rsk)); 385 TEST_EQ(WriteSpaceKernel(&rsk), 0, "WriteSpaceKernel(), v0"); 386 TEST_EQ(mock_rsk.struct_version, 2, "WriteSpaceKernel(), check v2"); 387 TEST_STR_EQ(mock_calls, 388 "TlclWrite(0x1008, 13)\n" 389 "TlclRead(0x1008, 13)\n", 390 "tlcl calls"); 391 392 /* Same as above, but with some noise during the readback */ 393 ResetMocks(0, 0); 394 Memset(&rsk, 0, sizeof(rsk)); 395 noise_on[1] = 1; 396 noise_on[2] = 1; 397 TEST_EQ(WriteSpaceKernel(&rsk), 0, "WriteSpaceKernel(), read noise"); 398 TEST_STR_EQ(mock_calls, 399 "TlclWrite(0x1008, 13)\n" 400 "TlclRead(0x1008, 13)\n" 401 "TlclRead(0x1008, 13)\n" 402 "TlclRead(0x1008, 13)\n", 403 "tlcl calls"); 404 405 /* With noise during the write, we'll try the write again */ 406 ResetMocks(0, 0); 407 Memset(&rsk, 0, sizeof(rsk)); 408 noise_on[0] = 1; 409 TEST_EQ(WriteSpaceKernel(&rsk), 0, "WriteSpaceKernel(), write noise"); 410 TEST_EQ(mock_rsk.struct_version, 2, "WriteSpaceKernel(), check v2"); 411 TEST_STR_EQ(mock_calls, 412 "TlclWrite(0x1008, 13)\n" 413 "TlclRead(0x1008, 13)\n" 414 "TlclRead(0x1008, 13)\n" 415 "TlclRead(0x1008, 13)\n" 416 "TlclWrite(0x1008, 13)\n" 417 "TlclRead(0x1008, 13)\n", 418 "tlcl calls"); 419 420 /* Only if it just keeps on failing forever do we eventually give up */ 421 ResetMocks(0, 0); 422 Memset(&rsk, 0, sizeof(rsk)); 423 Memset(noise_on, 1, sizeof(noise_on)); 424 TEST_EQ(WriteSpaceKernel(&rsk), TPM_E_CORRUPTED_STATE, 425 "WriteSpaceKernel(), always noise"); 426 TEST_STR_EQ(mock_calls, 427 "TlclWrite(0x1008, 13)\n" 428 "TlclRead(0x1008, 13)\n" 429 "TlclRead(0x1008, 13)\n" 430 "TlclRead(0x1008, 13)\n" 431 "TlclWrite(0x1008, 13)\n" 432 "TlclRead(0x1008, 13)\n" 433 "TlclRead(0x1008, 13)\n" 434 "TlclRead(0x1008, 13)\n" 435 "TlclWrite(0x1008, 13)\n" 436 "TlclRead(0x1008, 13)\n" 437 "TlclRead(0x1008, 13)\n" 438 "TlclRead(0x1008, 13)\n", 439 "tlcl calls"); 440} 441 442/****************************************************************************/ 443/* Tests for misc helper functions */ 444 445static void MiscTest(void) 446{ 447 uint8_t buf[8]; 448 449 ResetMocks(0, 0); 450 TEST_EQ(TPMClearAndReenable(), 0, "TPMClearAndReenable()"); 451 TEST_STR_EQ(mock_calls, 452 "TlclForceClear()\n" 453 "TlclSetEnable()\n" 454 "TlclSetDeactivated(0)\n", 455 "tlcl calls"); 456 457 ResetMocks(0, 0); 458 TEST_EQ(SafeWrite(0x123, buf, 8), 0, "SafeWrite()"); 459 TEST_STR_EQ(mock_calls, 460 "TlclWrite(0x123, 8)\n", 461 "tlcl calls"); 462 463 ResetMocks(1, TPM_E_BADINDEX); 464 TEST_EQ(SafeWrite(0x123, buf, 8), TPM_E_BADINDEX, "SafeWrite() bad"); 465 TEST_STR_EQ(mock_calls, 466 "TlclWrite(0x123, 8)\n", 467 "tlcl calls"); 468 469 ResetMocks(1, TPM_E_MAXNVWRITES); 470 TEST_EQ(SafeWrite(0x123, buf, 8), 0, "SafeWrite() retry max writes"); 471 TEST_STR_EQ(mock_calls, 472 "TlclWrite(0x123, 8)\n" 473 "TlclForceClear()\n" 474 "TlclSetEnable()\n" 475 "TlclSetDeactivated(0)\n" 476 "TlclWrite(0x123, 8)\n", 477 "tlcl calls"); 478 479 ResetMocks(0, 0); 480 TEST_EQ(SafeDefineSpace(0x123, 6, 8), 0, "SafeDefineSpace()"); 481 TEST_STR_EQ(mock_calls, 482 "TlclDefineSpace(0x123, 0x6, 8)\n", 483 "tlcl calls"); 484 485 ResetMocks(1, TPM_E_BADINDEX); 486 TEST_EQ(SafeDefineSpace(0x123, 6, 8), TPM_E_BADINDEX, 487 "SafeDefineSpace() bad"); 488 TEST_STR_EQ(mock_calls, 489 "TlclDefineSpace(0x123, 0x6, 8)\n", 490 "tlcl calls"); 491 492 ResetMocks(1, TPM_E_MAXNVWRITES); 493 TEST_EQ(SafeDefineSpace(0x123, 6, 8), 0, 494 "SafeDefineSpace() retry max writes"); 495 TEST_STR_EQ(mock_calls, 496 "TlclDefineSpace(0x123, 0x6, 8)\n" 497 "TlclForceClear()\n" 498 "TlclSetEnable()\n" 499 "TlclSetDeactivated(0)\n" 500 "TlclDefineSpace(0x123, 0x6, 8)\n", 501 "tlcl calls"); 502} 503 504/****************************************************************************/ 505 506/* Tests for one-time initialization */ 507static void OneTimeInitTest(void) 508{ 509 RollbackSpaceFirmware rsf; 510 RollbackSpaceKernel rsk; 511 512 /* Complete initialization */ 513 ResetMocks(0, 0); 514 TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()"); 515 TEST_STR_EQ(mock_calls, 516 "TlclSelfTestFull()\n" 517 "TlclGetPermanentFlags()\n" 518 "TlclFinalizePhysicalPresence()\n" 519 "TlclSetNvLocked()\n" 520 "TlclForceClear()\n" 521 "TlclSetEnable()\n" 522 "TlclSetDeactivated(0)\n" 523 /* backup space */ 524 "TlclDefineSpace(0x1009, 0x1, 16)\n" 525 /* kernel space */ 526 "TlclDefineSpace(0x1008, 0x1, 13)\n" 527 "TlclWrite(0x1008, 13)\n" 528 "TlclRead(0x1008, 13)\n" 529 /* firmware space */ 530 "TlclDefineSpace(0x1007, 0x8001, 10)\n" 531 "TlclWrite(0x1007, 10)\n" 532 "TlclRead(0x1007, 10)\n", 533 "tlcl calls"); 534 TEST_EQ(mock_rsf.struct_version, ROLLBACK_SPACE_FIRMWARE_VERSION, 535 "rsf ver"); 536 TEST_EQ(mock_rsf.flags, 0, "rsf flags"); 537 TEST_EQ(mock_rsf.fw_versions, 0, "rsf fw_versions"); 538 TEST_EQ(mock_rsk.struct_version, ROLLBACK_SPACE_KERNEL_VERSION, 539 "rsk ver"); 540 TEST_EQ(mock_rsk.uid, ROLLBACK_SPACE_KERNEL_UID, "rsk uid"); 541 TEST_EQ(mock_rsk.kernel_versions, 0, "rsk kernel_versions"); 542 543 /* Physical presence already initialized */ 544 ResetMocks(0, 0); 545 mock_pflags.physicalPresenceLifetimeLock = 1; 546 TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()"); 547 TEST_STR_EQ(mock_calls, 548 "TlclSelfTestFull()\n" 549 "TlclGetPermanentFlags()\n" 550 "TlclSetNvLocked()\n" 551 "TlclForceClear()\n" 552 "TlclSetEnable()\n" 553 "TlclSetDeactivated(0)\n" 554 /* backup space */ 555 "TlclDefineSpace(0x1009, 0x1, 16)\n" 556 /* kernel space */ 557 "TlclDefineSpace(0x1008, 0x1, 13)\n" 558 "TlclWrite(0x1008, 13)\n" 559 "TlclRead(0x1008, 13)\n" 560 /* firmware space */ 561 "TlclDefineSpace(0x1007, 0x8001, 10)\n" 562 "TlclWrite(0x1007, 10)\n" 563 "TlclRead(0x1007, 10)\n", 564 "tlcl calls"); 565 566 /* NV locking already initialized */ 567 ResetMocks(0, 0); 568 mock_pflags.nvLocked = 1; 569 TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()"); 570 TEST_STR_EQ(mock_calls, 571 "TlclSelfTestFull()\n" 572 "TlclGetPermanentFlags()\n" 573 "TlclFinalizePhysicalPresence()\n" 574 "TlclForceClear()\n" 575 "TlclSetEnable()\n" 576 "TlclSetDeactivated(0)\n" 577 /* backup space */ 578 "TlclDefineSpace(0x1009, 0x1, 16)\n" 579 /* kernel space */ 580 "TlclDefineSpace(0x1008, 0x1, 13)\n" 581 "TlclWrite(0x1008, 13)\n" 582 "TlclRead(0x1008, 13)\n" 583 /* firmware space */ 584 "TlclDefineSpace(0x1007, 0x8001, 10)\n" 585 "TlclWrite(0x1007, 10)\n" 586 "TlclRead(0x1007, 10)\n", 587 "tlcl calls"); 588 589 /* Self test error */ 590 ResetMocks(1, TPM_E_IOERROR); 591 TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), TPM_E_IOERROR, 592 "OneTimeInitializeTPM() selftest"); 593 TEST_STR_EQ(mock_calls, 594 "TlclSelfTestFull()\n", 595 "tlcl calls"); 596} 597 598/****************************************************************************/ 599/* Tests for TPM setup */ 600 601static void SetupTpmTest(void) 602{ 603 RollbackSpaceFirmware rsf; 604 605 /* Complete setup */ 606 ResetMocks(0, 0); 607 TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM()"); 608 TEST_STR_EQ(mock_calls, 609 "TlclLibInit()\n" 610 "TlclStartup()\n" 611 "TlclAssertPhysicalPresence()\n" 612 "TlclGetPermanentFlags()\n" 613 "TlclRead(0x1007, 10)\n", 614 "tlcl calls"); 615 616 /* If TPM is disabled or deactivated, must enable it */ 617 ResetMocks(0, 0); 618 mock_pflags.disable = 1; 619 TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_MUST_REBOOT, 620 "SetupTPM() disabled"); 621 TEST_STR_EQ(mock_calls, 622 "TlclLibInit()\n" 623 "TlclStartup()\n" 624 "TlclAssertPhysicalPresence()\n" 625 "TlclGetPermanentFlags()\n" 626 "TlclSetEnable()\n" 627 "TlclSetDeactivated(0)\n", 628 "tlcl calls"); 629 630 ResetMocks(0, 0); 631 mock_pflags.deactivated = 1; 632 TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_MUST_REBOOT, 633 "SetupTPM() deactivated"); 634 TEST_STR_EQ(mock_calls, 635 "TlclLibInit()\n" 636 "TlclStartup()\n" 637 "TlclAssertPhysicalPresence()\n" 638 "TlclGetPermanentFlags()\n" 639 "TlclSetEnable()\n" 640 "TlclSetDeactivated(0)\n", 641 "tlcl calls"); 642 643 /* If physical presence command isn't enabled, try to enable it */ 644 ResetMocks(3, TPM_E_IOERROR); 645 TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() pp cmd"); 646 TEST_STR_EQ(mock_calls, 647 "TlclLibInit()\n" 648 "TlclStartup()\n" 649 "TlclAssertPhysicalPresence()\n" 650 "TlclPhysicalPresenceCMDEnable()\n" 651 "TlclAssertPhysicalPresence()\n" 652 "TlclGetPermanentFlags()\n" 653 "TlclRead(0x1007, 10)\n", 654 "tlcl calls"); 655 656 /* If firmware space is missing, do one-time init */ 657 ResetMocks(5, TPM_E_BADINDEX); 658 mock_pflags.physicalPresenceLifetimeLock = 1; 659 mock_pflags.nvLocked = 1; 660 TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() no firmware space"); 661 TEST_STR_EQ(mock_calls, 662 "TlclLibInit()\n" 663 "TlclStartup()\n" 664 "TlclAssertPhysicalPresence()\n" 665 "TlclGetPermanentFlags()\n" 666 "TlclRead(0x1007, 10)\n" 667 /* Calls from one-time init */ 668 "TlclSelfTestFull()\n" 669 "TlclGetPermanentFlags()\n" 670 "TlclForceClear()\n" 671 "TlclSetEnable()\n" 672 "TlclSetDeactivated(0)\n" 673 /* backup space */ 674 "TlclDefineSpace(0x1009, 0x1, 16)\n" 675 "TlclDefineSpace(0x1008, 0x1, 13)\n" 676 "TlclWrite(0x1008, 13)\n" 677 "TlclRead(0x1008, 13)\n" 678 "TlclDefineSpace(0x1007, 0x8001, 10)\n" 679 "TlclWrite(0x1007, 10)\n" 680 "TlclRead(0x1007, 10)\n", 681 "tlcl calls"); 682 683 /* Other firmware space error is passed through */ 684 ResetMocks(5, TPM_E_IOERROR); 685 TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_CORRUPTED_STATE, 686 "SetupTPM() bad firmware space"); 687 TEST_STR_EQ(mock_calls, 688 "TlclLibInit()\n" 689 "TlclStartup()\n" 690 "TlclAssertPhysicalPresence()\n" 691 "TlclGetPermanentFlags()\n" 692 "TlclRead(0x1007, 10)\n", 693 "tlcl calls"); 694 695 /* If developer flag has toggled, clear ownership and write new flag */ 696 ResetMocks(0, 0); 697 TEST_EQ(SetupTPM(1, 0, 0, &rsf), 0, "SetupTPM() to dev"); 698 TEST_STR_EQ(mock_calls, 699 "TlclLibInit()\n" 700 "TlclStartup()\n" 701 "TlclAssertPhysicalPresence()\n" 702 "TlclGetPermanentFlags()\n" 703 "TlclRead(0x1007, 10)\n" 704 "TlclForceClear()\n" 705 "TlclSetEnable()\n" 706 "TlclSetDeactivated(0)\n" 707 "TlclWrite(0x1007, 10)\n" 708 "TlclRead(0x1007, 10)\n", 709 "tlcl calls"); 710 TEST_EQ(mock_rsf.flags, FLAG_LAST_BOOT_DEVELOPER, 711 "fw space flags to dev 1"); 712 713 ResetMocks(0, 0); 714 mock_rsf.flags = FLAG_LAST_BOOT_DEVELOPER; 715 TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() from dev"); 716 TEST_STR_EQ(mock_calls, 717 "TlclLibInit()\n" 718 "TlclStartup()\n" 719 "TlclAssertPhysicalPresence()\n" 720 "TlclGetPermanentFlags()\n" 721 "TlclRead(0x1007, 10)\n" 722 "TlclForceClear()\n" 723 "TlclSetEnable()\n" 724 "TlclSetDeactivated(0)\n" 725 "TlclWrite(0x1007, 10)\n" 726 "TlclRead(0x1007, 10)\n", 727 "tlcl calls"); 728 TEST_EQ(mock_rsf.flags, 0, "fw space flags from dev 1"); 729 730 /* If TPM clear request, clear ownership also */ 731 ResetMocks(0, 0); 732 TEST_EQ(SetupTPM(0, 0, 1, &rsf), 0, "SetupTPM() clear owner"); 733 TEST_STR_EQ(mock_calls, 734 "TlclLibInit()\n" 735 "TlclStartup()\n" 736 "TlclAssertPhysicalPresence()\n" 737 "TlclGetPermanentFlags()\n" 738 "TlclRead(0x1007, 10)\n" 739 "TlclForceClear()\n" 740 "TlclSetEnable()\n" 741 "TlclSetDeactivated(0)\n", 742 "tlcl calls"); 743 744 /* Handle request to clear virtual dev switch */ 745 ResetMocks(0, 0); 746 mock_rsf.flags = FLAG_VIRTUAL_DEV_MODE_ON | FLAG_LAST_BOOT_DEVELOPER; 747 TEST_EQ(SetupTPM(0, 1, 0, &rsf), 0, "SetupTPM() clear virtual dev"); 748 TEST_EQ(mock_rsf.flags, 0, "Clear virtual dev"); 749 750 /* If virtual dev switch is on, that should set last boot developer */ 751 ResetMocks(0, 0); 752 mock_rsf.flags = FLAG_VIRTUAL_DEV_MODE_ON; 753 SetupTPM(0, 0, 0, &rsf); 754 TEST_EQ(mock_rsf.flags, 755 FLAG_VIRTUAL_DEV_MODE_ON | FLAG_LAST_BOOT_DEVELOPER, 756 "virtual dev sets last boot"); 757 758 /* 759 * Note: SetupTPM() recovery_mode parameter sets a global flag in 760 * rollback_index.c; this is tested along with RollbackKernelLock() 761 * below. 762 */ 763} 764 765/****************************************************************************/ 766/* Tests for RollbackFirmware() calls */ 767 768static void RollbackFirmwareTest(void) 769{ 770 uint32_t version; 771 int dev_mode; 772 773 /* Normal setup */ 774 ResetMocks(0, 0); 775 dev_mode = 0; 776 version = 123; 777 mock_rsf.fw_versions = 0x12345678; 778 TEST_EQ(RollbackFirmwareSetup(0, dev_mode, 0, &dev_mode, &version), 779 0, "RollbackFirmwareSetup()"); 780 TEST_STR_EQ(mock_calls, 781 "TlclLibInit()\n" 782 "TlclStartup()\n" 783 "TlclAssertPhysicalPresence()\n" 784 "TlclGetPermanentFlags()\n" 785 "TlclRead(0x1007, 10)\n", 786 "tlcl calls"); 787 TEST_EQ(version, 0x12345678, "RollbackFirmwareSetup() version"); 788 789 /* Error during setup should clear version */ 790 ResetMocks(1, TPM_E_IOERROR); 791 dev_mode = 0; 792 version = 123; 793 mock_rsf.fw_versions = 0x12345678; 794 TEST_EQ(RollbackFirmwareSetup(0, dev_mode, 0, &dev_mode, &version), 795 TPM_E_IOERROR, 796 "RollbackFirmwareSetup() error"); 797 TEST_STR_EQ(mock_calls, 798 "TlclLibInit()\n", 799 "tlcl calls"); 800 TEST_EQ(version, 0, "RollbackFirmwareSetup() version on error"); 801 802 /* Developer mode flag gets passed properly */ 803 ResetMocks(0, 0); 804 dev_mode = 1; 805 TEST_EQ(RollbackFirmwareSetup(dev_mode, 0, 0, &dev_mode, &version), 806 0, "RollbackFirmwareSetup() to dev"); 807 TEST_STR_EQ(mock_calls, 808 "TlclLibInit()\n" 809 "TlclStartup()\n" 810 "TlclAssertPhysicalPresence()\n" 811 "TlclGetPermanentFlags()\n" 812 "TlclRead(0x1007, 10)\n" 813 "TlclForceClear()\n" 814 "TlclSetEnable()\n" 815 "TlclSetDeactivated(0)\n" 816 "TlclWrite(0x1007, 10)\n" 817 "TlclRead(0x1007, 10)\n", 818 "tlcl calls"); 819 TEST_EQ(mock_rsf.flags, FLAG_LAST_BOOT_DEVELOPER, 820 "fw space flags to dev 2"); 821 822 /* So does clear-TPM request */ 823 ResetMocks(0, 0); 824 dev_mode = 0; 825 TEST_EQ(RollbackFirmwareSetup(dev_mode, 0, 1, &dev_mode, &version), 826 0, "RollbackFirmwareSetup() clear owner"); 827 TEST_STR_EQ(mock_calls, 828 "TlclLibInit()\n" 829 "TlclStartup()\n" 830 "TlclAssertPhysicalPresence()\n" 831 "TlclGetPermanentFlags()\n" 832 "TlclRead(0x1007, 10)\n" 833 "TlclForceClear()\n" 834 "TlclSetEnable()\n" 835 "TlclSetDeactivated(0)\n", 836 "tlcl calls"); 837 838 /* Test write */ 839 ResetMocks(0, 0); 840 TEST_EQ(RollbackFirmwareWrite(0xBEAD1234), 0, 841 "RollbackFirmwareWrite()"); 842 TEST_EQ(mock_rsf.fw_versions, 0xBEAD1234, 843 "RollbackFirmwareWrite() version"); 844 TEST_STR_EQ(mock_calls, 845 "TlclRead(0x1007, 10)\n" 846 "TlclWrite(0x1007, 10)\n" 847 "TlclRead(0x1007, 10)\n", 848 "tlcl calls"); 849 850 ResetMocks(1, TPM_E_IOERROR); 851 TEST_EQ(RollbackFirmwareWrite(123), TPM_E_IOERROR, 852 "RollbackFirmwareWrite() error"); 853 854 /* Test setting virtual dev mode */ 855 ResetMocks(0, 0); 856 TEST_EQ(SetVirtualDevMode(1), 0, "SetVirtualDevMode(1)"); 857 TEST_EQ(mock_rsf.flags, FLAG_VIRTUAL_DEV_MODE_ON, "Virtual dev on"); 858 TEST_STR_EQ(mock_calls, 859 "TlclRead(0x1007, 10)\n" 860 "TlclWrite(0x1007, 10)\n" 861 "TlclRead(0x1007, 10)\n", 862 "tlcl calls"); 863 ResetMocks(0, 0); 864 TEST_EQ(SetVirtualDevMode(0), 0, "SetVirtualDevMode(0)"); 865 TEST_EQ(mock_rsf.flags, 0, "Virtual dev off"); 866 TEST_STR_EQ(mock_calls, 867 "TlclRead(0x1007, 10)\n" 868 "TlclWrite(0x1007, 10)\n" 869 "TlclRead(0x1007, 10)\n", 870 "tlcl calls"); 871 872 /* Test lock */ 873 ResetMocks(0, 0); 874 TEST_EQ(RollbackFirmwareLock(), 0, "RollbackFirmwareLock()"); 875 TEST_STR_EQ(mock_calls, 876 "TlclSetGlobalLock()\n", 877 "tlcl calls"); 878 879 ResetMocks(1, TPM_E_IOERROR); 880 TEST_EQ(RollbackFirmwareLock(), TPM_E_IOERROR, 881 "RollbackFirmwareLock() error"); 882} 883 884/****************************************************************************/ 885/* Tests for RollbackKernel() calls */ 886 887static void RollbackKernelTest(void) 888{ 889 RollbackSpaceFirmware rsf; 890 uint32_t version = 0; 891 892 /* 893 * RollbackKernel*() functions use a global flag inside 894 * rollback_index.c based on recovery mode, which is set by SetupTPM(). 895 * Clear the flag for the first set of tests. 896 */ 897 TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM()"); 898 899 /* Normal read */ 900 ResetMocks(0, 0); 901 mock_rsk.uid = ROLLBACK_SPACE_KERNEL_UID; 902 mock_permissions = TPM_NV_PER_PPWRITE; 903 mock_rsk.kernel_versions = 0x87654321; 904 TEST_EQ(RollbackKernelRead(&version), 0, "RollbackKernelRead()"); 905 TEST_STR_EQ(mock_calls, 906 "TlclRead(0x1008, 13)\n" 907 "TlclGetPermissions(0x1008)\n", 908 "tlcl calls"); 909 TEST_EQ(version, 0x87654321, "RollbackKernelRead() version"); 910 911 /* Read error */ 912 ResetMocks(1, TPM_E_IOERROR); 913 TEST_EQ(RollbackKernelRead(&version), TPM_E_IOERROR, 914 "RollbackKernelRead() error"); 915 TEST_STR_EQ(mock_calls, 916 "TlclRead(0x1008, 13)\n", 917 "tlcl calls"); 918 919 /* Wrong permission or UID will return error */ 920 ResetMocks(0, 0); 921 mock_rsk.uid = ROLLBACK_SPACE_KERNEL_UID + 1; 922 mock_permissions = TPM_NV_PER_PPWRITE; 923 TEST_EQ(RollbackKernelRead(&version), TPM_E_CORRUPTED_STATE, 924 "RollbackKernelRead() bad uid"); 925 926 ResetMocks(0, 0); 927 mock_rsk.uid = ROLLBACK_SPACE_KERNEL_UID; 928 mock_permissions = TPM_NV_PER_PPWRITE + 1; 929 TEST_EQ(RollbackKernelRead(&version), TPM_E_CORRUPTED_STATE, 930 "RollbackKernelRead() bad permissions"); 931 932 /* Test write */ 933 ResetMocks(0, 0); 934 TEST_EQ(RollbackKernelWrite(0xBEAD4321), 0, "RollbackKernelWrite()"); 935 TEST_EQ(mock_rsk.kernel_versions, 0xBEAD4321, 936 "RollbackKernelWrite() version"); 937 TEST_STR_EQ(mock_calls, 938 "TlclRead(0x1008, 13)\n" 939 "TlclWrite(0x1008, 13)\n" 940 "TlclRead(0x1008, 13)\n", 941 "tlcl calls"); 942 943 ResetMocks(1, TPM_E_IOERROR); 944 TEST_EQ(RollbackKernelWrite(123), TPM_E_IOERROR, 945 "RollbackKernelWrite() error"); 946 947 /* Test lock (recovery off) */ 948 ResetMocks(0, 0); 949 TEST_EQ(RollbackKernelLock(0), 0, "RollbackKernelLock()"); 950 TEST_STR_EQ(mock_calls, 951 "TlclLockPhysicalPresence()\n", 952 "tlcl calls"); 953 954 ResetMocks(1, TPM_E_IOERROR); 955 TEST_EQ(RollbackKernelLock(0), TPM_E_IOERROR, 956 "RollbackKernelLock() error"); 957 958 /* Test lock with recovery on; shouldn't lock PP */ 959 SetupTPM(0, 0, 0, &rsf); 960 ResetMocks(0, 0); 961 TEST_EQ(RollbackKernelLock(1), 0, "RollbackKernelLock() in recovery"); 962 TEST_STR_EQ(mock_calls, "", "no tlcl calls"); 963} 964 965/* Tests for RollbackS3Resume() */ 966static void RollbackS3ResumeTest(void) 967{ 968 ResetMocks(0, 0); 969 TEST_EQ(RollbackS3Resume(), 0, "RollbackS3Resume()"); 970 TEST_STR_EQ(mock_calls, 971 "TlclLibInit()\n" 972 "TlclResume()\n", 973 "tlcl calls"); 974 975 /* Should ignore postinit error */ 976 ResetMocks(2, TPM_E_INVALID_POSTINIT); 977 TEST_EQ(RollbackS3Resume(), 0, "RollbackS3Resume() postinit"); 978 979 /* Resume with other error */ 980 ResetMocks(2, TPM_E_IOERROR); 981 TEST_EQ(RollbackS3Resume(), TPM_E_IOERROR, 982 "RollbackS3Resume() other error"); 983} 984 985int main(int argc, char* argv[]) 986{ 987 CrcTestFirmware(); 988 CrcTestKernel(); 989 MiscTest(); 990 OneTimeInitTest(); 991 SetupTpmTest(); 992 RollbackFirmwareTest(); 993 RollbackKernelTest(); 994 RollbackS3ResumeTest(); 995 996 return gTestSuccess ? 0 : 255; 997} 998