1/* Copyright (c) 2010 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 6/* This program mimicks the TPM usage from read-only firmware. It exercises 7 * the TPM functionality needed in the read-only firmware. It is meant to be 8 * integrated with the rest of the read-only firmware. It is also provided as 9 * a test. 10 */ 11 12#include <stdio.h> 13#include <stdint.h> 14#include <stdlib.h> 15 16#include "tlcl.h" 17#include "utility.h" 18 19/* These index values are used to create NVRAM spaces. They only need to be 20 * unique. 21 */ 22#define INDEX0 0xda70 23#define INDEX1 0xda71 24#define INDEX2 0xda72 25#define INDEX3 0xda73 26 27#define INDEX_INITIALIZED 0xda80 28 29/* This is called once at initialization time. It may be called again from 30 * recovery mode to rebuild the spaces if something incomprehensible happened 31 * and the spaces are gone or messed up. This is called after TPM_Startup and 32 * before the spaces are write-locked, so there is a chance that they can be 33 * recreated (but who knows---if anything can happen, there are plenty of ways 34 * of making this FUBAR). 35 */ 36void InitializeSpaces(void) { 37 uint32_t zero = 0; 38 uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; 39 40 printf("Initializing spaces\n"); 41 TlclSetNvLocked(); /* useful only the first time */ 42 43 TlclDefineSpace(INDEX0, perm, 4); 44 TlclWrite(INDEX0, (uint8_t *) &zero, 4); 45 TlclDefineSpace(INDEX1, perm, 4); 46 TlclWrite(INDEX1, (uint8_t *) &zero, 4); 47 TlclDefineSpace(INDEX2, perm, 4); 48 TlclWrite(INDEX2, (uint8_t *) &zero, 4); 49 TlclDefineSpace(INDEX3, perm, 4); 50 TlclWrite(INDEX3, (uint8_t *) &zero, 4); 51 52 perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR | 53 TPM_NV_PER_PPWRITE; 54 TlclDefineSpace(INDEX_INITIALIZED, perm, 1); 55} 56 57 58void EnterRecoveryMode(void) { 59 printf("entering recovery mode"); 60 exit(0); 61} 62 63 64int main(int argc, char** argv) { 65 uint8_t c; 66 uint32_t index_0, index_1, index_2, index_3; 67 68 TlclLibInit(); 69 70 TlclStartup(); 71 TlclSelfTestFull(); 72 73 TlclAssertPhysicalPresence(); 74 75 /* Checks if initialization has completed by trying to read-lock a space 76 * that's created at the end of initialization. 77 */ 78 if (TlclRead(INDEX_INITIALIZED, &c, 0) == TPM_E_BADINDEX) { 79 /* The initialization did not complete. 80 */ 81 InitializeSpaces(); 82 } 83 84 /* Checks if spaces are OK or messed up. 85 */ 86 if (TlclRead(INDEX0, (uint8_t*) &index_0, sizeof(index_0)) != TPM_SUCCESS || 87 TlclRead(INDEX1, (uint8_t*) &index_1, sizeof(index_1)) != TPM_SUCCESS || 88 TlclRead(INDEX2, (uint8_t*) &index_2, sizeof(index_2)) != TPM_SUCCESS || 89 TlclRead(INDEX3, (uint8_t*) &index_3, sizeof(index_3)) != TPM_SUCCESS) { 90 EnterRecoveryMode(); 91 } 92 93 /* Writes space, and locks it. Then attempts to write again. I really wish 94 * I could use the imperative. 95 */ 96 index_0 += 1; 97 if (TlclWrite(INDEX0, (uint8_t*) &index_0, sizeof(index_0) != TPM_SUCCESS)) { 98 error("could not write index 0\n"); 99 } 100 TlclWriteLock(INDEX0); 101 if (TlclWrite(INDEX0, (uint8_t*) &index_0, sizeof(index_0)) == TPM_SUCCESS) { 102 error("index 0 is not locked\n"); 103 } 104 105 /* Done for now. 106 */ 107 printf("TEST SUCCEEDED\n"); 108 exit(0); 109} 110