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