Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(514)

Side by Side Diff: vboot_firmware/lib/rollback_index.c

Issue 2711006: Import recent tpm_lite changes that make all TPM commands return a status. (Closed) Base URL: ssh://git@chromiumos-git/vboot_reference.git
Patch Set: cleanup from gauravsh's feedback Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « vboot_firmware/lib/firmware_image_fw.c ('k') | vboot_firmware/linktest/main.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 static int InitializeSpaces(void) { 22 #define RETURN_ON_FAILURE(tpm_command) do { \
23 uint32_t result; \
24 if ((result = tpm_command) != TPM_SUCCESS) {\
25 return result; \
26 } \
27 } while (0)
28
29 static uint32_t InitializeSpaces(void) {
23 uint32_t zero = 0; 30 uint32_t zero = 0;
24 uint32_t space_holder; 31 uint32_t space_holder;
25 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE; 32 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE;
26 uint32_t kernel_perm = TPM_NV_PER_PPWRITE; 33 uint32_t kernel_perm = TPM_NV_PER_PPWRITE;
27 34
28 debug("Initializing spaces\n"); 35 debug("Initializing spaces\n");
29 36
30 if (TlclRead(TPM_IS_INITIALIZED_NV_INDEX, 37 if (TlclRead(TPM_IS_INITIALIZED_NV_INDEX,
31 (uint8_t*) &space_holder, sizeof(space_holder)) == TPM_SUCCESS) { 38 (uint8_t*) &space_holder, sizeof(space_holder)) == TPM_SUCCESS) {
32 /* Spaces are already initialized, so this is an error */ 39 /* Spaces are already initialized, so this is an error */
33 return 0; 40 return 0;
34 } 41 }
35 42
36 TlclSetNvLocked(); 43 RETURN_ON_FAILURE(TlclSetNvLocked());
37 44
38 TlclDefineSpace(FIRMWARE_VERSIONS_NV_INDEX, firmware_perm, sizeof(uint32_t)); 45 RETURN_ON_FAILURE(TlclDefineSpace(FIRMWARE_VERSIONS_NV_INDEX,
39 TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, (uint8_t*) &zero, sizeof(uint32_t)); 46 firmware_perm, sizeof(uint32_t)));
47 RETURN_ON_FAILURE(TlclWrite(FIRMWARE_VERSIONS_NV_INDEX,
48 (uint8_t*) &zero, sizeof(uint32_t)));
40 49
41 TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, kernel_perm, sizeof(uint32_t)); 50 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX,
42 TlclWrite(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &zero, sizeof(uint32_t)); 51 kernel_perm, sizeof(uint32_t)));
52 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &zero,
53 sizeof(uint32_t)));
43 54
44 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel 55 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel
45 * versions when entering recovery mode. The content of space 56 * versions when entering recovery mode. The content of space
46 * KERNEL_BACKUP_IS_VALID determines whether the backup value (1) or the 57 * KERNEL_BACKUP_IS_VALID determines whether the backup value (1) or the
47 * regular value (0) should be trusted. 58 * regular value (0) should be trusted.
48 */ 59 */
49 TlclDefineSpace(KERNEL_VERSIONS_BACKUP_NV_INDEX, 60 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_BACKUP_NV_INDEX,
50 firmware_perm, sizeof(uint32_t)); 61 firmware_perm, sizeof(uint32_t)));
51 TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, 62 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX,
52 (uint8_t*) &zero, sizeof(uint32_t)); 63 (uint8_t*) &zero, sizeof(uint32_t)));
53 TlclDefineSpace(KERNEL_BACKUP_IS_VALID_NV_INDEX, 64 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_BACKUP_IS_VALID_NV_INDEX,
54 firmware_perm, sizeof(uint32_t)); 65 firmware_perm, sizeof(uint32_t)));
55 TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX, 66 RETURN_ON_FAILURE(TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX,
56 (uint8_t*) &zero, sizeof(uint32_t)); 67 (uint8_t*) &zero, sizeof(uint32_t)));
57 68
58 /* The space TPM_IS_INITIALIZED_NV_INDEX is used to indicate that the TPM 69 /* The space TPM_IS_INITIALIZED_NV_INDEX is used to indicate that the TPM
59 * initialization has completed. Without it we cannot be sure that the last 70 * initialization has completed. Without it we cannot be sure that the last
60 * space to be created was also initialized (power could have been lost right 71 * space to be created was also initialized (power could have been lost right
61 * after its creation). 72 * after its creation).
62 */ 73 */
63 TlclDefineSpace(TPM_IS_INITIALIZED_NV_INDEX, firmware_perm, sizeof(uint32_t)); 74 RETURN_ON_FAILURE(TlclDefineSpace(TPM_IS_INITIALIZED_NV_INDEX,
64 return 1; 75 firmware_perm, sizeof(uint32_t)));
76 return TPM_SUCCESS;
65 } 77 }
66 78
67 /* Enters the recovery mode. If |unlocked| is true, there is some problem with 79 /* Enters the recovery mode. If |unlocked| is true, there is some problem with
68 * the TPM, so do not attempt to do any more TPM operations, and particularly 80 * the TPM, so do not attempt to do any more TPM operations, and particularly
69 * do not set bGlobalLock. 81 * do not set bGlobalLock.
70 */ 82 */
71 static void EnterRecovery(int unlocked) { 83 static void EnterRecovery(int unlocked) {
72 uint32_t combined_versions; 84 uint32_t combined_versions;
73 uint32_t backup_versions; 85 uint32_t backup_versions;
74 uint32_t backup_is_valid; 86 uint32_t backup_is_valid;
(...skipping 22 matching lines...) Expand all
97 sizeof(uint32_t)); 109 sizeof(uint32_t));
98 } 110 }
99 /* Protects the firmware and backup kernel versions. */ 111 /* Protects the firmware and backup kernel versions. */
100 LockFirmwareVersions(); 112 LockFirmwareVersions();
101 } 113 }
102 debug("entering recovery mode"); 114 debug("entering recovery mode");
103 115
104 /* TODO(nelson): code for entering recovery mode. */ 116 /* TODO(nelson): code for entering recovery mode. */
105 } 117 }
106 118
107 static int GetTPMRollbackIndices(void) { 119 static uint32_t GetTPMRollbackIndices(void) {
108 uint32_t backup_is_valid; 120 uint32_t backup_is_valid;
109 uint32_t firmware_versions; 121 uint32_t firmware_versions;
110 uint32_t kernel_versions; 122 uint32_t kernel_versions;
111 123
112 if (TlclRead(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &backup_is_valid, 124 if (TlclRead(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &backup_is_valid,
113 sizeof(uint32_t)) != TPM_SUCCESS) { 125 sizeof(uint32_t)) != TPM_SUCCESS) {
114 EnterRecovery(1); 126 EnterRecovery(1);
115 } 127 }
116 if (backup_is_valid) { 128 if (backup_is_valid) {
117 /* We reach this path if the previous boot went into recovery mode and we 129 /* We reach this path if the previous boot went into recovery mode and we
118 * made a copy of the kernel versions to protect them. 130 * made a copy of the kernel versions to protect them.
119 */ 131 */
120 uint32_t protected_combined_versions; 132 uint32_t protected_combined_versions;
121 uint32_t unsafe_combined_versions; 133 uint32_t unsafe_combined_versions;
122 uint32_t result; 134 uint32_t result;
123 uint32_t zero = 0; 135 uint32_t zero = 0;
124 if (TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, 136 if (TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX,
125 (uint8_t*) &protected_combined_versions, 137 (uint8_t*) &protected_combined_versions,
126 sizeof(uint32_t)) != TPM_SUCCESS) { 138 sizeof(uint32_t)) != TPM_SUCCESS) {
127 EnterRecovery(1); 139 EnterRecovery(1);
128 } 140 }
129 result = TlclRead(KERNEL_VERSIONS_NV_INDEX, 141 result = TlclRead(KERNEL_VERSIONS_NV_INDEX,
130 (uint8_t*) &unsafe_combined_versions, sizeof(uint32_t)); 142 (uint8_t*) &unsafe_combined_versions, sizeof(uint32_t));
131 if (result == TPM_E_BADINDEX) { 143 if (result == TPM_E_BADINDEX) {
132 /* Jeez, someone removed the space. This is either hostile or extremely 144 /* Jeez, someone removed the space. This is either hostile or extremely
133 * incompetent. Foo to them. Politeness and lack of an adequate 145 * incompetent. Foo to them. Politeness and lack of an adequate
134 * character set prevent me from expressing my true feelings. 146 * character set prevent me from expressing my true feelings.
135 */ 147 */
136 TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, TPM_NV_PER_PPWRITE, 148 RETURN_ON_FAILURE(TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX,
137 sizeof(uint32_t)); 149 TPM_NV_PER_PPWRITE,
150 sizeof(uint32_t)));
138 } else if (result != TPM_SUCCESS) { 151 } else if (result != TPM_SUCCESS) {
139 EnterRecovery(1); 152 EnterRecovery(1);
140 } 153 }
141 if (result == TPM_E_BADINDEX || 154 if (result == TPM_E_BADINDEX ||
142 protected_combined_versions != unsafe_combined_versions) { 155 protected_combined_versions != unsafe_combined_versions) {
143 TlclWrite(KERNEL_VERSIONS_NV_INDEX, 156 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX,
144 (uint8_t*) &protected_combined_versions, sizeof(uint32_t)); 157 (uint8_t*) &protected_combined_versions,
158 sizeof(uint32_t)));
145 } 159 }
146 /* We recovered the backed-up versions and now we can reset the 160 /* We recovered the backed-up versions and now we can reset the
147 * BACKUP_IS_VALID flag. 161 * BACKUP_IS_VALID flag.
148 */ 162 */
149 TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &zero, 0); 163 RETURN_ON_FAILURE(TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX,
164 (uint8_t*) &zero, 0));
150 165
151 /* TODO(nelson): ForceClear and reboot if unowned. */ 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 }
152 } 174 }
153 175
154 /* We perform the reads, making sure they succeed. A failure means that the 176 /* We perform the reads, making sure they succeed. A failure means that the
155 * rollback index locations are missing or somehow messed up. We let the 177 * rollback index locations are missing or somehow messed up. We let the
156 * caller deal with that. 178 * caller deal with that.
157 */ 179 */
158 if (TPM_SUCCESS != TlclRead(FIRMWARE_VERSIONS_NV_INDEX, 180 RETURN_ON_FAILURE(TlclRead(FIRMWARE_VERSIONS_NV_INDEX,
159 (uint8_t*) &firmware_versions, 181 (uint8_t*) &firmware_versions,
160 sizeof(firmware_versions)) || 182 sizeof(firmware_versions)));
161 TPM_SUCCESS != TlclRead(KERNEL_VERSIONS_NV_INDEX, 183 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX,
162 (uint8_t*) &kernel_versions, 184 (uint8_t*) &kernel_versions,
163 sizeof(kernel_versions))) 185 sizeof(kernel_versions)));
164 return 0;
165 186
166 g_firmware_key_version = firmware_versions >> 16; 187 g_firmware_key_version = firmware_versions >> 16;
167 g_firmware_version = firmware_versions && 0xffff; 188 g_firmware_version = firmware_versions && 0xffff;
168 g_kernel_key_version = kernel_versions >> 16; 189 g_kernel_key_version = kernel_versions >> 16;
169 g_kernel_version = kernel_versions && 0xffff; 190 g_kernel_version = kernel_versions && 0xffff;
170 191
171 return 1; 192 return TPM_SUCCESS;
172 } 193 }
173 194
174 195
175 int SetupTPM(void) { 196 uint32_t SetupTPM(void) {
176 uint8_t disable; 197 uint8_t disable;
177 uint8_t deactivated; 198 uint8_t deactivated;
178 TlclLibinit(); 199 TlclLibInit();
179 TlclStartup(); 200 RETURN_ON_FAILURE(TlclStartup());
180 /* TODO(gauravsh): The call to self test should probably be deferred. 201 RETURN_ON_FAILURE(TlclContinueSelfTest());
181 * As per semenzato@chromium.org - 202 RETURN_ON_FAILURE(TlclAssertPhysicalPresence());
182 * TlclStartup should be called before the firmware initializes the memory
183 * controller, so the selftest can run in parallel with that. Here we should
184 * just call TlclSelftestFull to make sure the self test has
185 * completed---unless we want to rely on the NVRAM operations being available
186 * before the selftest completes. */
187 TlclSelftestfull();
188 TlclAssertPhysicalPresence();
189 /* Check that the TPM is enabled and activated. */ 203 /* Check that the TPM is enabled and activated. */
190 if(TlclGetFlags(&disable, &deactivated) != TPM_SUCCESS) { 204 RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated));
191 debug("failed to get TPM flags");
192 return 1;
193 }
194 if (disable || deactivated) { 205 if (disable || deactivated) {
195 TlclSetEnable(); 206 RETURN_ON_FAILURE(TlclSetEnable());
196 if (TlclSetDeactivated(0) != TPM_SUCCESS) { 207 RETURN_ON_FAILURE(TlclSetDeactivated(0));
197 debug("failed to activate TPM"); 208 /* TODO: Reboot now */
198 return 1; 209 return 9999;
199 }
200 } 210 }
201 /* We expect this to fail the first time we run on a device, indicating that 211 /* We expect this to fail the first time we run on a device, indicating that
202 * the TPM has not been initialized yet. */ 212 * the TPM has not been initialized yet. */
203 if (!GetTPMRollbackIndices()) { 213 if (GetTPMRollbackIndices() != TPM_SUCCESS) {
204 debug("failed to get rollback indices"); 214 /* If InitializeSpaces() fails (possibly because it had been executed
205 if (!InitializeSpaces()) { 215 * already), something is wrong. */
206 /* If InitializeSpaces() fails (possibly because it had been executed 216 RETURN_ON_FAILURE(InitializeSpaces());
207 * already), something is wrong. */ 217 /* Try again. */
208 return 1; 218 RETURN_ON_FAILURE(GetTPMRollbackIndices());
209 }
210 } 219 }
211 220
212 return 0; 221 return TPM_SUCCESS;
213 } 222 }
214 223
215 int GetStoredVersions(int type, uint16_t* key_version, uint16_t* version) { 224 uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version) {
216 225
217 /* TODO: should verify that SetupTPM() has been called. Note that 226 /* TODO: should verify that SetupTPM() has been called. Note that
218 * SetupTPM() does hardware setup AND sets global variables. When we 227 * SetupTPM() does hardware setup AND sets global variables. When we
219 * get down into kernel verification, the hardware setup persists, but 228 * get down into kernel verification, the hardware setup persists, but
220 * we don't have access to the global variables. So I guess we DO need 229 * we don't have access to the global variables. So I guess we DO need
221 * to call SetupTPM() there, and have it be smart enough not to redo the 230 * to call SetupTPM() there, and have it be smart enough not to redo the
222 * hardware init, but it still needs to re-read the flags... */ 231 * hardware init, but it still needs to re-read the flags... */
223 232
224 switch (type) { 233 switch (type) {
225 case FIRMWARE_VERSIONS: 234 case FIRMWARE_VERSIONS:
226 *key_version = g_firmware_key_version; 235 *key_version = g_firmware_key_version;
227 *version = g_firmware_version; 236 *version = g_firmware_version;
228 break; 237 break;
229 case KERNEL_VERSIONS: 238 case KERNEL_VERSIONS:
230 *key_version = g_kernel_key_version; 239 *key_version = g_kernel_key_version;
231 *version = g_kernel_version; 240 *version = g_kernel_version;
232 break; 241 break;
233 } 242 }
234 243
235 return 0; 244 return TPM_SUCCESS;
236 } 245 }
237 246
238 int WriteStoredVersions(int type, uint16_t key_version, uint16_t version) { 247 uint32_t WriteStoredVersions(int type, uint16_t key_version, uint16_t version) {
239 uint32_t combined_version = (key_version << 16) & version; 248 uint32_t combined_version = (key_version << 16) & version;
240 switch (type) { 249 switch (type) {
241 case FIRMWARE_VERSIONS: 250 case FIRMWARE_VERSIONS:
242 return (TPM_SUCCESS != TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, 251 RETURN_ON_FAILURE(TlclWrite(FIRMWARE_VERSIONS_NV_INDEX,
243 (uint8_t*) &combined_version, 252 (uint8_t*) &combined_version,
244 sizeof(uint32_t))); 253 sizeof(uint32_t)));
254 break;
245 255
246 case KERNEL_VERSIONS: 256 case KERNEL_VERSIONS:
247 return (TPM_SUCCESS != TlclWrite(KERNEL_VERSIONS_NV_INDEX, 257 RETURN_ON_FAILURE(TlclWrite(KERNEL_VERSIONS_NV_INDEX,
248 (uint8_t*) &combined_version, 258 (uint8_t*) &combined_version,
249 sizeof(uint32_t))); 259 sizeof(uint32_t)));
260 break;
250 } 261 }
251 /* TODO(nelson): ForceClear and reboot if unowned. */ 262 if (!TlclIsOwned()) {
252 263 RETURN_ON_FAILURE(TlclForceClear());
253 return 1; 264 /* TODO: Reboot here. No return. */
265 return 9999;
266 }
267 return TPM_SUCCESS;
254 } 268 }
255 269
256 int LockFirmwareVersions() { 270 uint32_t LockFirmwareVersions() {
257 if (TlclSetGlobalLock() != TPM_SUCCESS) { 271 return TlclSetGlobalLock();
258 debug("failed to set global lock");
259 return 1;
260 }
261 return 0;
262 } 272 }
263 273
264 int LockKernelVersionsByLockingPP() { 274 uint32_t LockKernelVersionsByLockingPP() {
265 if (TlclLockPhysicalPresence() != TPM_SUCCESS) { 275 return TlclLockPhysicalPresence();
266 debug("failed to turn off PP");
267 return 1;
268 }
269 return 0;
270 } 276 }
OLDNEW
« no previous file with comments | « vboot_firmware/lib/firmware_image_fw.c ('k') | vboot_firmware/linktest/main.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698