OLD | NEW |
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 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 | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 * | 4 * |
5 * Functions for querying, manipulating and locking rollback indices | 5 * Functions for querying, manipulating and locking rollback indices |
6 * stored in the TPM NVRAM. | 6 * stored in the TPM NVRAM. |
7 */ | 7 */ |
8 | 8 |
9 #include "rollback_index.h" | 9 #include "rollback_index.h" |
10 | 10 |
11 #include <stdint.h> | 11 #include <stdint.h> |
12 | 12 |
13 #include "utility.h" | 13 #include "utility.h" |
14 #include "tlcl.h" | 14 #include "tlcl.h" |
15 #include "tss_constants.h" | 15 #include "tss_constants.h" |
16 | 16 |
17 uint16_t g_firmware_key_version = 0; | 17 uint16_t g_firmware_key_version = 0; |
18 uint16_t g_firmware_version = 0; | 18 uint16_t g_firmware_version = 0; |
19 uint16_t g_kernel_key_version = 0; | 19 uint16_t g_kernel_key_version = 0; |
20 uint16_t g_kernel_version = 0; | 20 uint16_t g_kernel_version = 0; |
21 | 21 |
22 #define RETURN_ON_FAILURE(tpm_command) do { \ | 22 #define RETURN_ON_FAILURE(tpm_command) do { \ |
23 uint32_t result; \ | 23 uint32_t result; \ |
24 if ((result = tpm_command) != TPM_SUCCESS) {\ | 24 if ((result = (tpm_command)) != TPM_SUCCESS) { \ |
25 return result; \ | 25 return result; \ |
26 } \ | 26 } \ |
27 } while (0) | 27 } while (0) |
28 | 28 |
| 29 static uint32_t InitializeKernelVersionsSpaces(void) { |
| 30 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, |
| 31 TPM_NV_PER_PPWRITE, KERNEL_SPACE_SIZE)); |
| 32 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, KERNEL_SPACE_INIT_DATA, |
| 33 KERNEL_SPACE_SIZE)); |
| 34 return TPM_SUCCESS; |
| 35 } |
| 36 |
| 37 static uint32_t GetSpacesInitialized(int* initialized) { |
| 38 uint32_t space_holder; |
| 39 uint32_t result; |
| 40 result = TlclRead(TPM_IS_INITIALIZED_NV_INDEX, |
| 41 (uint8_t*) &space_holder, sizeof(space_holder)); |
| 42 switch (result) { |
| 43 case TPM_SUCCESS: |
| 44 *initialized = 1; |
| 45 break; |
| 46 case TPM_E_BADINDEX: |
| 47 *initialized = 0; |
| 48 result = TPM_SUCCESS; |
| 49 break; |
| 50 } |
| 51 return result; |
| 52 } |
| 53 |
29 static uint32_t InitializeSpaces(void) { | 54 static uint32_t InitializeSpaces(void) { |
30 uint32_t zero = 0; | 55 uint32_t zero = 0; |
31 uint32_t space_holder; | |
32 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE; | 56 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE; |
33 uint32_t kernel_perm = TPM_NV_PER_PPWRITE; | |
34 | 57 |
35 debug("Initializing spaces\n"); | 58 debug("Initializing spaces\n"); |
36 | 59 |
37 if (TlclRead(TPM_IS_INITIALIZED_NV_INDEX, | |
38 (uint8_t*) &space_holder, sizeof(space_holder)) == TPM_SUCCESS) { | |
39 /* Spaces are already initialized, so this is an error */ | |
40 return 0; | |
41 } | |
42 | |
43 RETURN_ON_FAILURE(TlclSetNvLocked()); | 60 RETURN_ON_FAILURE(TlclSetNvLocked()); |
44 | 61 |
45 RETURN_ON_FAILURE(TlclDefineSpace(FIRMWARE_VERSIONS_NV_INDEX, | 62 RETURN_ON_FAILURE(TlclDefineSpace(FIRMWARE_VERSIONS_NV_INDEX, |
46 firmware_perm, sizeof(uint32_t))); | 63 firmware_perm, sizeof(uint32_t))); |
47 RETURN_ON_FAILURE(TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, | 64 RETURN_ON_FAILURE(TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, |
48 (uint8_t*) &zero, sizeof(uint32_t))); | 65 (uint8_t*) &zero, sizeof(uint32_t))); |
49 | 66 |
50 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, | 67 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces()); |
51 kernel_perm, sizeof(uint32_t))); | |
52 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &zero, | |
53 sizeof(uint32_t))); | |
54 | 68 |
55 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel | 69 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel |
56 * versions when entering recovery mode. The content of space | 70 * versions when entering recovery mode. The content of space |
57 * KERNEL_BACKUP_IS_VALID determines whether the backup value (1) or the | 71 * KERNEL_MUST_USE_BACKUP determines whether the backup value (1) or the |
58 * regular value (0) should be trusted. | 72 * regular value (0) should be trusted. |
59 */ | 73 */ |
60 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_BACKUP_NV_INDEX, | 74 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
61 firmware_perm, sizeof(uint32_t))); | 75 firmware_perm, sizeof(uint32_t))); |
62 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, | 76 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
63 (uint8_t*) &zero, sizeof(uint32_t))); | 77 (uint8_t*) &zero, sizeof(uint32_t))); |
64 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_BACKUP_IS_VALID_NV_INDEX, | 78 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_MUST_USE_BACKUP_NV_INDEX, |
65 firmware_perm, sizeof(uint32_t))); | 79 firmware_perm, sizeof(uint32_t))); |
66 RETURN_ON_FAILURE(TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX, | 80 RETURN_ON_FAILURE(TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, |
67 (uint8_t*) &zero, sizeof(uint32_t))); | 81 (uint8_t*) &zero, sizeof(uint32_t))); |
68 | 82 |
69 /* The space TPM_IS_INITIALIZED_NV_INDEX is used to indicate that the TPM | 83 /* The space TPM_IS_INITIALIZED_NV_INDEX is used to indicate that the TPM |
70 * initialization has completed. Without it we cannot be sure that the last | 84 * initialization has completed. Without it we cannot be sure that the last |
71 * space to be created was also initialized (power could have been lost right | 85 * space to be created was also initialized (power could have been lost right |
72 * after its creation). | 86 * after its creation). |
73 */ | 87 */ |
74 RETURN_ON_FAILURE(TlclDefineSpace(TPM_IS_INITIALIZED_NV_INDEX, | 88 RETURN_ON_FAILURE(TlclDefineSpace(TPM_IS_INITIALIZED_NV_INDEX, |
75 firmware_perm, sizeof(uint32_t))); | 89 firmware_perm, sizeof(uint32_t))); |
76 return TPM_SUCCESS; | 90 return TPM_SUCCESS; |
77 } | 91 } |
78 | 92 |
79 /* Enters the recovery mode. If |unlocked| is true, there is some problem with | 93 /* Enters the recovery mode. If |unlocked| is true, there is some problem with |
80 * the TPM, so do not attempt to do any more TPM operations, and particularly | 94 * the TPM, so do not attempt to do any more TPM operations, and particularly |
81 * do not set bGlobalLock. | 95 * do not set bGlobalLock. |
82 */ | 96 */ |
83 static void EnterRecovery(int unlocked) { | 97 void EnterRecovery(int unlocked) { |
84 uint32_t combined_versions; | 98 uint32_t combined_versions; |
85 uint32_t backup_versions; | 99 uint32_t backup_versions; |
86 uint32_t backup_is_valid; | 100 uint32_t must_use_backup; |
| 101 uint32_t result; |
87 | 102 |
88 if (!unlocked) { | 103 if (!unlocked) { |
89 /* Saves the kernel versions and indicates that we should trust the saved | 104 /* Saves the kernel versions and indicates that we should trust the saved |
90 * ones. | 105 * ones. |
91 */ | 106 */ |
92 TlclRead(KERNEL_VERSIONS_NV_INDEX, | 107 if (TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &combined_versions, |
93 (uint8_t*) &combined_versions, sizeof(uint32_t)); | 108 sizeof(uint32_t)) != TPM_SUCCESS) |
94 TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, | 109 goto recovery_mode; |
95 (uint8_t*) &backup_versions, sizeof(uint32_t)); | 110 if (TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, (uint8_t*) &backup_versions, |
96 /* We could unconditional writes of both KERNEL_VERSIONS_BACKUP and | 111 sizeof(uint32_t)) != TPM_SUCCESS) |
97 * KERNEL_BACKUP_IS_VALID, but this is more robust. | 112 goto recovery_mode; |
98 */ | 113 /* Avoids idempotent writes. */ |
99 if (combined_versions != backup_versions) { | 114 if (combined_versions != backup_versions) { |
100 TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, | 115 result = TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
101 (uint8_t*) &combined_versions, sizeof(uint32_t)); | 116 (uint8_t*) &combined_versions, sizeof(uint32_t)); |
| 117 if (result == TPM_E_MAXNVWRITES) { |
| 118 goto forceclear_and_reboot; |
| 119 } else if (result != TPM_SUCCESS) { |
| 120 goto recovery_mode; |
| 121 } |
102 } | 122 } |
103 | 123 |
104 TlclRead(KERNEL_BACKUP_IS_VALID_NV_INDEX, | 124 if (TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX, (uint8_t*) &must_use_backup, |
105 (uint8_t*) &backup_is_valid, sizeof(uint32_t)); | 125 sizeof(uint32_t)) != TPM_SUCCESS) |
106 if (backup_is_valid != 1) { | 126 goto recovery_mode; |
107 backup_is_valid = 1; | 127 if (must_use_backup != 1) { |
108 TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &backup_is_valid, | 128 must_use_backup = 1; |
109 sizeof(uint32_t)); | 129 result = TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, |
| 130 (uint8_t*) &must_use_backup, sizeof(uint32_t)); |
| 131 if (result == TPM_E_MAXNVWRITES) { |
| 132 goto forceclear_and_reboot; |
| 133 } else if (result != TPM_SUCCESS) { |
| 134 goto recovery_mode; |
| 135 } |
110 } | 136 } |
111 /* Protects the firmware and backup kernel versions. */ | 137 /* Protects the firmware and backup kernel versions. */ |
112 LockFirmwareVersions(); | 138 if (LockFirmwareVersions() != TPM_SUCCESS) |
| 139 goto recovery_mode; |
113 } | 140 } |
| 141 |
| 142 recovery_mode: |
114 debug("entering recovery mode"); | 143 debug("entering recovery mode"); |
115 | 144 |
116 /* TODO(nelson): code for entering recovery mode. */ | 145 /* TODO(nelson): code for entering recovery mode. */ |
| 146 |
| 147 forceclear_and_reboot: |
| 148 if (TlclForceClear() != TPM_SUCCESS) { |
| 149 goto recovery_mode; |
| 150 } |
| 151 /* TODO: reboot */ |
117 } | 152 } |
118 | 153 |
119 static uint32_t GetTPMRollbackIndices(void) { | 154 static uint32_t GetTPMRollbackIndices(void) { |
120 uint32_t backup_is_valid; | |
121 uint32_t firmware_versions; | 155 uint32_t firmware_versions; |
122 uint32_t kernel_versions; | 156 uint32_t kernel_versions; |
123 | 157 |
124 if (TlclRead(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &backup_is_valid, | |
125 sizeof(uint32_t)) != TPM_SUCCESS) { | |
126 EnterRecovery(1); | |
127 } | |
128 if (backup_is_valid) { | |
129 /* We reach this path if the previous boot went into recovery mode and we | |
130 * made a copy of the kernel versions to protect them. | |
131 */ | |
132 uint32_t protected_combined_versions; | |
133 uint32_t unsafe_combined_versions; | |
134 uint32_t result; | |
135 uint32_t zero = 0; | |
136 if (TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, | |
137 (uint8_t*) &protected_combined_versions, | |
138 sizeof(uint32_t)) != TPM_SUCCESS) { | |
139 EnterRecovery(1); | |
140 } | |
141 result = TlclRead(KERNEL_VERSIONS_NV_INDEX, | |
142 (uint8_t*) &unsafe_combined_versions, sizeof(uint32_t)); | |
143 if (result == TPM_E_BADINDEX) { | |
144 /* Jeez, someone removed the space. This is either hostile or extremely | |
145 * incompetent. Foo to them. Politeness and lack of an adequate | |
146 * character set prevent me from expressing my true feelings. | |
147 */ | |
148 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, | |
149 TPM_NV_PER_PPWRITE, | |
150 sizeof(uint32_t))); | |
151 } else if (result != TPM_SUCCESS) { | |
152 EnterRecovery(1); | |
153 } | |
154 if (result == TPM_E_BADINDEX || | |
155 protected_combined_versions != unsafe_combined_versions) { | |
156 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, | |
157 (uint8_t*) &protected_combined_versions, | |
158 sizeof(uint32_t))); | |
159 } | |
160 /* We recovered the backed-up versions and now we can reset the | |
161 * BACKUP_IS_VALID flag. | |
162 */ | |
163 RETURN_ON_FAILURE(TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX, | |
164 (uint8_t*) &zero, 0)); | |
165 | |
166 if (!TlclIsOwned()) { | |
167 /* Must ForceClear and reboot to prevent from running into the 64-write | |
168 * limit. | |
169 */ | |
170 RETURN_ON_FAILURE(TlclForceClear()); | |
171 /* Reboot! No return */ | |
172 return 9999; | |
173 } | |
174 } | |
175 | |
176 /* We perform the reads, making sure they succeed. A failure means that the | 158 /* We perform the reads, making sure they succeed. A failure means that the |
177 * rollback index locations are missing or somehow messed up. We let the | 159 * rollback index locations are missing or somehow messed up. We let the |
178 * caller deal with that. | 160 * caller deal with that. |
179 */ | 161 */ |
180 RETURN_ON_FAILURE(TlclRead(FIRMWARE_VERSIONS_NV_INDEX, | 162 RETURN_ON_FAILURE(TlclRead(FIRMWARE_VERSIONS_NV_INDEX, |
181 (uint8_t*) &firmware_versions, | 163 (uint8_t*) &firmware_versions, |
182 sizeof(firmware_versions))); | 164 sizeof(firmware_versions))); |
183 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, | 165 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, |
184 (uint8_t*) &kernel_versions, | 166 (uint8_t*) &kernel_versions, |
185 sizeof(kernel_versions))); | 167 sizeof(kernel_versions))); |
186 | 168 |
187 g_firmware_key_version = firmware_versions >> 16; | 169 g_firmware_key_version = firmware_versions >> 16; |
188 g_firmware_version = firmware_versions && 0xffff; | 170 g_firmware_version = firmware_versions && 0xffff; |
189 g_kernel_key_version = kernel_versions >> 16; | 171 g_kernel_key_version = kernel_versions >> 16; |
190 g_kernel_version = kernel_versions && 0xffff; | 172 g_kernel_version = kernel_versions && 0xffff; |
191 | 173 |
192 return TPM_SUCCESS; | 174 return TPM_SUCCESS; |
193 } | 175 } |
194 | 176 |
| 177 /* Checks if the kernel version space has been mucked with. If it has, |
| 178 * reconstructs it using the backup value. |
| 179 */ |
| 180 uint32_t RecoverKernelSpace(void) { |
| 181 uint32_t perms = 0; |
| 182 uint8_t buffer[KERNEL_SPACE_SIZE]; |
| 183 int read_OK = 0; |
| 184 int perms_OK = 0; |
| 185 uint32_t backup_combined_versions; |
| 186 uint32_t must_use_backup; |
195 | 187 |
196 uint32_t SetupTPM(void) { | 188 RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX, |
| 189 (uint8_t*) &must_use_backup, sizeof(uint32_t))); |
| 190 /* must_use_backup is true if the previous boot entered recovery mode. */ |
| 191 |
| 192 read_OK = TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer, |
| 193 KERNEL_SPACE_SIZE) == TPM_SUCCESS; |
| 194 if (read_OK) { |
| 195 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms)); |
| 196 perms_OK = perms == TPM_NV_PER_PPWRITE; |
| 197 } |
| 198 if (!must_use_backup && read_OK && perms_OK && |
| 199 !Memcmp(buffer + sizeof(uint32_t), KERNEL_SPACE_UID, |
| 200 KERNEL_SPACE_UID_SIZE)) { |
| 201 /* Everything is fine. This is the normal, frequent path. */ |
| 202 return TPM_SUCCESS; |
| 203 } |
| 204 |
| 205 /* Either we detected that something went wrong, or we cannot trust the |
| 206 * PP-protected kernel space. Attempts to fix. It is not always necessary |
| 207 * to redefine the space, but we might as well, since this path should be |
| 208 * taken quite seldom (after recovery mode and after an attack). |
| 209 */ |
| 210 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces()); |
| 211 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
| 212 (uint8_t*) &backup_combined_versions, |
| 213 sizeof(uint32_t))); |
| 214 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, |
| 215 (uint8_t*) &backup_combined_versions, |
| 216 sizeof(uint32_t))); |
| 217 if (must_use_backup) { |
| 218 uint32_t zero = 0; |
| 219 RETURN_ON_FAILURE(TlclWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, |
| 220 (uint8_t*) &zero, 0)); |
| 221 |
| 222 } |
| 223 return TPM_SUCCESS; |
| 224 } |
| 225 |
| 226 static uint32_t BackupKernelSpace(void) { |
| 227 uint32_t kernel_versions; |
| 228 uint32_t backup_versions; |
| 229 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, |
| 230 (uint8_t*) &kernel_versions, sizeof(uint32_t))); |
| 231 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
| 232 (uint8_t*) &backup_versions, sizeof(uint32_t))); |
| 233 if (kernel_versions == backup_versions) { |
| 234 return TPM_SUCCESS; |
| 235 } else if (kernel_versions < backup_versions) { |
| 236 /* This cannot happen. We're screwed. */ |
| 237 return TPM_E_INTERNAL_INCONSISTENCY; |
| 238 } |
| 239 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
| 240 (uint8_t*) &kernel_versions, sizeof(uint32_t))); |
| 241 return TPM_SUCCESS; |
| 242 } |
| 243 |
| 244 static uint32_t SetupTPM_(void) { |
197 uint8_t disable; | 245 uint8_t disable; |
198 uint8_t deactivated; | 246 uint8_t deactivated; |
199 TlclLibInit(); | 247 TlclLibInit(); |
200 RETURN_ON_FAILURE(TlclStartup()); | 248 RETURN_ON_FAILURE(TlclStartup()); |
201 RETURN_ON_FAILURE(TlclContinueSelfTest()); | 249 RETURN_ON_FAILURE(TlclContinueSelfTest()); |
202 RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); | 250 RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); |
203 /* Check that the TPM is enabled and activated. */ | 251 /* Checks that the TPM is enabled and activated. */ |
204 RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated)); | 252 RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated)); |
205 if (disable || deactivated) { | 253 if (disable || deactivated) { |
206 RETURN_ON_FAILURE(TlclSetEnable()); | 254 RETURN_ON_FAILURE(TlclSetEnable()); |
207 RETURN_ON_FAILURE(TlclSetDeactivated(0)); | 255 RETURN_ON_FAILURE(TlclSetDeactivated(0)); |
208 /* TODO: Reboot now */ | 256 /* TODO: Reboot */ |
209 return 9999; | 257 return 9999; |
210 } | 258 } |
211 /* We expect this to fail the first time we run on a device, indicating that | 259 /* We expect this to fail the first time we run on a device, indicating that |
212 * the TPM has not been initialized yet. */ | 260 * the TPM has not been initialized yet. */ |
213 if (GetTPMRollbackIndices() != TPM_SUCCESS) { | 261 if (RecoverKernelSpace() != TPM_SUCCESS) { |
214 /* If InitializeSpaces() fails (possibly because it had been executed | 262 int initialized = 0; |
215 * already), something is wrong. */ | 263 RETURN_ON_FAILURE(GetSpacesInitialized(&initialized)); |
216 RETURN_ON_FAILURE(InitializeSpaces()); | 264 if (initialized) { |
217 /* Try again. */ | 265 return TPM_E_ALREADY_INITIALIZED; |
218 RETURN_ON_FAILURE(GetTPMRollbackIndices()); | 266 } else { |
| 267 RETURN_ON_FAILURE(InitializeSpaces()); |
| 268 RETURN_ON_FAILURE(RecoverKernelSpace()); |
| 269 } |
219 } | 270 } |
| 271 RETURN_ON_FAILURE(BackupKernelSpace()); |
| 272 RETURN_ON_FAILURE(GetTPMRollbackIndices()); |
220 | 273 |
221 return TPM_SUCCESS; | 274 return TPM_SUCCESS; |
222 } | 275 } |
223 | 276 |
| 277 uint32_t SetupTPM(void) { |
| 278 uint32_t result = SetupTPM_(); |
| 279 if (result == TPM_E_MAXNVWRITES) { |
| 280 /* ForceClears and reboots */ |
| 281 RETURN_ON_FAILURE(TlclForceClear()); |
| 282 /* TODO: reboot */ |
| 283 return 9999; |
| 284 } else { |
| 285 return result; |
| 286 } |
| 287 } |
| 288 |
224 uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version) { | 289 uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version) { |
225 | 290 |
226 /* TODO: should verify that SetupTPM() has been called. Note that | 291 /* TODO: should verify that SetupTPM() has been called. Note that |
227 * SetupTPM() does hardware setup AND sets global variables. When we | 292 * SetupTPM() does hardware setup AND sets global variables. When we |
228 * get down into kernel verification, the hardware setup persists, but | 293 * get down into kernel verification, the hardware setup persists, but |
229 * we don't have access to the global variables. So I guess we DO need | 294 * we don't have access to the global variables. So I guess we DO need |
230 * to call SetupTPM() there, and have it be smart enough not to redo the | 295 * to call SetupTPM() there, and have it be smart enough not to redo the |
231 * hardware init, but it still needs to re-read the flags... */ | 296 * hardware init, but it still needs to re-read the flags... */ |
232 | 297 |
233 switch (type) { | 298 switch (type) { |
(...skipping 16 matching lines...) Expand all Loading... |
250 case FIRMWARE_VERSIONS: | 315 case FIRMWARE_VERSIONS: |
251 RETURN_ON_FAILURE(TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, | 316 RETURN_ON_FAILURE(TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, |
252 (uint8_t*) &combined_version, | 317 (uint8_t*) &combined_version, |
253 sizeof(uint32_t))); | 318 sizeof(uint32_t))); |
254 break; | 319 break; |
255 | 320 |
256 case KERNEL_VERSIONS: | 321 case KERNEL_VERSIONS: |
257 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, | 322 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, |
258 (uint8_t*) &combined_version, | 323 (uint8_t*) &combined_version, |
259 sizeof(uint32_t))); | 324 sizeof(uint32_t))); |
260 break; | |
261 } | |
262 /* TODO(semenzato): change TlclIsOwned to return a TPM status directly and | |
263 * the "owned" value by reference. | |
264 */ | |
265 if (!TlclIsOwned()) { | |
266 RETURN_ON_FAILURE(TlclForceClear()); | |
267 /* TODO: Reboot here. No return. */ | |
268 return 9999; | |
269 } | 325 } |
270 return TPM_SUCCESS; | 326 return TPM_SUCCESS; |
271 } | 327 } |
272 | 328 |
273 uint32_t LockFirmwareVersions() { | 329 uint32_t LockFirmwareVersions() { |
274 return TlclSetGlobalLock(); | 330 return TlclSetGlobalLock(); |
275 } | 331 } |
276 | 332 |
277 uint32_t LockKernelVersionsByLockingPP() { | 333 uint32_t LockKernelVersionsByLockingPP() { |
278 return TlclLockPhysicalPresence(); | 334 return TlclLockPhysicalPresence(); |
279 } | 335 } |
OLD | NEW |