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 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 } | 129 } |
130 return TPM_SUCCESS; | 130 return TPM_SUCCESS; |
131 } | 131 } |
132 | 132 |
133 /* Checks if the kernel version space has been mucked with. If it has, | 133 /* Checks if the kernel version space has been mucked with. If it has, |
134 * reconstructs it using the backup value. | 134 * reconstructs it using the backup value. |
135 */ | 135 */ |
136 uint32_t RecoverKernelSpace(void) { | 136 uint32_t RecoverKernelSpace(void) { |
137 uint32_t perms = 0; | 137 uint32_t perms = 0; |
138 uint8_t buffer[KERNEL_SPACE_SIZE]; | 138 uint8_t buffer[KERNEL_SPACE_SIZE]; |
139 int read_OK = 0; | |
140 int perms_OK = 0; | |
141 uint32_t backup_combined_versions; | 139 uint32_t backup_combined_versions; |
142 uint32_t must_use_backup; | 140 uint32_t must_use_backup; |
| 141 uint32_t zero = 0; |
143 | 142 |
144 RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX, | 143 RETURN_ON_FAILURE(TlclRead(KERNEL_MUST_USE_BACKUP_NV_INDEX, |
145 (uint8_t*) &must_use_backup, sizeof(uint32_t))); | 144 (uint8_t*) &must_use_backup, sizeof(uint32_t))); |
146 /* must_use_backup is true if the previous boot entered recovery mode. */ | 145 /* must_use_backup is true if the previous boot entered recovery mode. */ |
147 | 146 |
148 read_OK = TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer, | 147 /* If we can't read the kernel space, or it has the wrong permission, or it |
149 KERNEL_SPACE_SIZE) == TPM_SUCCESS; | 148 * doesn't contain the right identifier, we give up. This will need to be |
150 if (read_OK) { | 149 * fixed by the recovery kernel. We have to worry about this because at any |
151 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms)); | 150 * time (even with PP turned off) the TPM owner can remove and redefine a |
152 perms_OK = perms == TPM_NV_PER_PPWRITE; | 151 * PP-protected space (but not write to it). |
153 } | 152 */ |
154 if (!must_use_backup && read_OK && perms_OK && | 153 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &buffer, |
| 154 KERNEL_SPACE_SIZE)); |
| 155 RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_VERSIONS_NV_INDEX, &perms)); |
| 156 if (perms != TPM_NV_PER_PPWRITE || |
155 !Memcmp(buffer + sizeof(uint32_t), KERNEL_SPACE_UID, | 157 !Memcmp(buffer + sizeof(uint32_t), KERNEL_SPACE_UID, |
156 KERNEL_SPACE_UID_SIZE)) { | 158 KERNEL_SPACE_UID_SIZE)) { |
157 /* Everything is fine. This is the normal, frequent path. */ | 159 return TPM_E_CORRUPTED_STATE; |
158 return TPM_SUCCESS; | |
159 } | 160 } |
160 | 161 |
161 /* Either we detected that something went wrong, or we cannot trust the | |
162 * PP-protected kernel space. Attempts to fix. It is not always necessary | |
163 * to redefine the space, but we might as well, since this path should be | |
164 * taken quite seldom (after recovery mode and after an attack). | |
165 */ | |
166 RETURN_ON_FAILURE(InitializeKernelVersionsSpaces()); | |
167 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, | |
168 (uint8_t*) &backup_combined_versions, | |
169 sizeof(uint32_t))); | |
170 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX, | |
171 (uint8_t*) &backup_combined_versions, | |
172 sizeof(uint32_t))); | |
173 if (must_use_backup) { | 162 if (must_use_backup) { |
174 uint32_t zero = 0; | 163 /* We must use the backup space because in the preceding boot cycle the |
| 164 * primary space was left unlocked and cannot be trusted. |
| 165 */ |
| 166 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
| 167 (uint8_t*) &backup_combined_versions, |
| 168 sizeof(uint32_t))); |
| 169 RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX, |
| 170 (uint8_t*) &backup_combined_versions, |
| 171 sizeof(uint32_t))); |
175 RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, | 172 RETURN_ON_FAILURE(SafeWrite(KERNEL_MUST_USE_BACKUP_NV_INDEX, |
176 (uint8_t*) &zero, 0)); | 173 (uint8_t*) &zero, 0)); |
177 } | 174 } |
178 return TPM_SUCCESS; | 175 return TPM_SUCCESS; |
179 } | 176 } |
180 | 177 |
181 static uint32_t BackupKernelSpace(void) { | 178 static uint32_t BackupKernelSpace(void) { |
182 uint32_t kernel_versions; | 179 uint32_t kernel_versions; |
183 uint32_t backup_versions; | 180 uint32_t backup_versions; |
184 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, | 181 RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX, |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 return SafeWrite(FIRMWARE_VERSIONS_NV_INDEX, | 292 return SafeWrite(FIRMWARE_VERSIONS_NV_INDEX, |
296 (uint8_t*) &combined_version, | 293 (uint8_t*) &combined_version, |
297 sizeof(uint32_t)); | 294 sizeof(uint32_t)); |
298 } | 295 } |
299 | 296 |
300 uint32_t RollbackFirmwareLock(void) { | 297 uint32_t RollbackFirmwareLock(void) { |
301 return TlclSetGlobalLock(); | 298 return TlclSetGlobalLock(); |
302 } | 299 } |
303 | 300 |
304 uint32_t RollbackKernelRecovery(int developer_mode) { | 301 uint32_t RollbackKernelRecovery(int developer_mode) { |
305 uint32_t result = SetupTPM(1, developer_mode); | 302 (void) SetupTPM(1, developer_mode); |
306 if (result == TPM_SUCCESS) { | 303 /* In recovery mode we ignore TPM malfunctions or corruptions, and leave the |
| 304 * TPM completely unlocked if and only if the dev mode switch is ON. The |
| 305 * recovery kernel will fix the TPM (if needed) and lock it ASAP. We leave |
| 306 * Physical Presence on in either case. |
| 307 */ |
| 308 if (!developer_mode) { |
307 RETURN_ON_FAILURE(TlclSetGlobalLock()); | 309 RETURN_ON_FAILURE(TlclSetGlobalLock()); |
308 } | 310 } |
309 return TPM_SUCCESS; | 311 return TPM_SUCCESS; |
310 } | 312 } |
311 | 313 |
312 uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) { | 314 uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) { |
313 uint32_t kernel_versions; | 315 uint32_t kernel_versions; |
314 if (g_rollback_recovery_mode) { | 316 if (g_rollback_recovery_mode) { |
315 *key_version = 0; | 317 *key_version = 0; |
316 *version = 0; | 318 *version = 0; |
(...skipping 18 matching lines...) Expand all Loading... |
335 return TPM_SUCCESS; | 337 return TPM_SUCCESS; |
336 } | 338 } |
337 | 339 |
338 uint32_t RollbackKernelLock(void) { | 340 uint32_t RollbackKernelLock(void) { |
339 if (!g_rollback_recovery_mode) { | 341 if (!g_rollback_recovery_mode) { |
340 return TlclLockPhysicalPresence(); | 342 return TlclLockPhysicalPresence(); |
341 } else { | 343 } else { |
342 return TPM_SUCCESS; | 344 return TPM_SUCCESS; |
343 } | 345 } |
344 } | 346 } |
OLD | NEW |