| /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| /* This program mimicks the TPM usage from read-only firmware. It exercises |
| * the TPM functionality needed in the read-only firmware. It is meant to be |
| * integrated with the rest of the read-only firmware. It is also provided as |
| * a test. |
| */ |
| |
| #include <stdio.h> |
| #include <stdint.h> |
| #include <stdlib.h> |
| |
| #include "tlcl.h" |
| #include "utility.h" |
| |
| /* These index values are used to create NVRAM spaces. They only need to be |
| * unique. |
| */ |
| #define INDEX0 0xda70 |
| #define INDEX1 0xda71 |
| #define INDEX2 0xda72 |
| #define INDEX3 0xda73 |
| |
| #define INDEX_INITIALIZED 0xda80 |
| |
| /* This is called once at initialization time. It may be called again from |
| * recovery mode to rebuild the spaces if something incomprehensible happened |
| * and the spaces are gone or messed up. This is called after TPM_Startup and |
| * before the spaces are write-locked, so there is a chance that they can be |
| * recreated (but who knows---if anything can happen, there are plenty of ways |
| * of making this FUBAR). |
| */ |
| void InitializeSpaces(void) { |
| uint32_t zero = 0; |
| uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; |
| |
| printf("Initializing spaces\n"); |
| TlclSetNvLocked(); /* useful only the first time */ |
| |
| TlclDefineSpace(INDEX0, perm, 4); |
| TlclWrite(INDEX0, (uint8_t *) &zero, 4); |
| TlclDefineSpace(INDEX1, perm, 4); |
| TlclWrite(INDEX1, (uint8_t *) &zero, 4); |
| TlclDefineSpace(INDEX2, perm, 4); |
| TlclWrite(INDEX2, (uint8_t *) &zero, 4); |
| TlclDefineSpace(INDEX3, perm, 4); |
| TlclWrite(INDEX3, (uint8_t *) &zero, 4); |
| |
| perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR | |
| TPM_NV_PER_PPWRITE; |
| TlclDefineSpace(INDEX_INITIALIZED, perm, 1); |
| } |
| |
| |
| void EnterRecoveryMode(void) { |
| printf("entering recovery mode"); |
| exit(0); |
| } |
| |
| |
| int main(int argc, char** argv) { |
| uint8_t c; |
| uint32_t index_0, index_1, index_2, index_3; |
| |
| TlclLibInit(); |
| |
| TlclStartup(); |
| TlclSelfTestFull(); |
| |
| TlclAssertPhysicalPresence(); |
| |
| /* Checks if initialization has completed by trying to read-lock a space |
| * that's created at the end of initialization. |
| */ |
| if (TlclRead(INDEX_INITIALIZED, &c, 0) == TPM_E_BADINDEX) { |
| /* The initialization did not complete. |
| */ |
| InitializeSpaces(); |
| } |
| |
| /* Checks if spaces are OK or messed up. |
| */ |
| if (TlclRead(INDEX0, (uint8_t*) &index_0, sizeof(index_0)) != TPM_SUCCESS || |
| TlclRead(INDEX1, (uint8_t*) &index_1, sizeof(index_1)) != TPM_SUCCESS || |
| TlclRead(INDEX2, (uint8_t*) &index_2, sizeof(index_2)) != TPM_SUCCESS || |
| TlclRead(INDEX3, (uint8_t*) &index_3, sizeof(index_3)) != TPM_SUCCESS) { |
| EnterRecoveryMode(); |
| } |
| |
| /* Writes space, and locks it. Then attempts to write again. I really wish |
| * I could use the imperative. |
| */ |
| index_0 += 1; |
| if (TlclWrite(INDEX0, (uint8_t*) &index_0, sizeof(index_0) != TPM_SUCCESS)) { |
| error("could not write index 0\n"); |
| } |
| TlclWriteLock(INDEX0); |
| if (TlclWrite(INDEX0, (uint8_t*) &index_0, sizeof(index_0)) == TPM_SUCCESS) { |
| error("index 0 is not locked\n"); |
| } |
| |
| /* Done for now. |
| */ |
| printf("TEST SUCCEEDED\n"); |
| exit(0); |
| } |