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 14 matching lines...) Expand all Loading... |
25 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE; | 25 uint32_t firmware_perm = TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE; |
26 uint32_t kernel_perm = TPM_NV_PER_PPWRITE; | 26 uint32_t kernel_perm = TPM_NV_PER_PPWRITE; |
27 | 27 |
28 debug("Initializing spaces\n"); | 28 debug("Initializing spaces\n"); |
29 | 29 |
30 if (TlclRead(TPM_IS_INITIALIZED_NV_INDEX, | 30 if (TlclRead(TPM_IS_INITIALIZED_NV_INDEX, |
31 (uint8_t*) &space_holder, sizeof(space_holder)) == TPM_SUCCESS) { | 31 (uint8_t*) &space_holder, sizeof(space_holder)) == TPM_SUCCESS) { |
32 /* Spaces are already initialized, so this is an error */ | 32 /* Spaces are already initialized, so this is an error */ |
33 return 0; | 33 return 0; |
34 } | 34 } |
35 | 35 |
36 TlclSetNvLocked(); | 36 TlclSetNvLocked(); |
37 | 37 |
38 TlclDefineSpace(FIRMWARE_VERSIONS_NV_INDEX, firmware_perm, sizeof(uint32_t)); | 38 TlclDefineSpace(FIRMWARE_VERSIONS_NV_INDEX, firmware_perm, sizeof(uint32_t)); |
39 TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, (uint8_t*) &zero, sizeof(uint32_t)); | 39 TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, (uint8_t*) &zero, sizeof(uint32_t)); |
40 | 40 |
41 TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, kernel_perm, sizeof(uint32_t)); | 41 TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, kernel_perm, sizeof(uint32_t)); |
42 TlclWrite(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &zero, sizeof(uint32_t)); | 42 TlclWrite(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &zero, sizeof(uint32_t)); |
43 | 43 |
44 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel | 44 /* The space KERNEL_VERSIONS_BACKUP_NV_INDEX is used to protect the kernel |
45 * versions when entering recovery mode. The content of space | 45 * versions when entering recovery mode. The content of space |
(...skipping 17 matching lines...) Expand all Loading... |
63 TlclDefineSpace(TPM_IS_INITIALIZED_NV_INDEX, firmware_perm, sizeof(uint32_t)); | 63 TlclDefineSpace(TPM_IS_INITIALIZED_NV_INDEX, firmware_perm, sizeof(uint32_t)); |
64 return 1; | 64 return 1; |
65 } | 65 } |
66 | 66 |
67 /* Enters the recovery mode. If |unlocked| is true, there is some problem with | 67 /* 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 | 68 * the TPM, so do not attempt to do any more TPM operations, and particularly |
69 * do not set bGlobalLock. | 69 * do not set bGlobalLock. |
70 */ | 70 */ |
71 static void EnterRecovery(int unlocked) { | 71 static void EnterRecovery(int unlocked) { |
72 uint32_t combined_versions; | 72 uint32_t combined_versions; |
73 uint32_t one = 1; | 73 uint32_t backup_versions; |
| 74 uint32_t backup_is_valid; |
74 | 75 |
75 if (!unlocked) { | 76 if (!unlocked) { |
76 /* Saves the kernel versions and indicates that we should trust the saved | 77 /* Saves the kernel versions and indicates that we should trust the saved |
77 * ones. | 78 * ones. |
78 */ | 79 */ |
79 TlclRead(KERNEL_VERSIONS_NV_INDEX, (uint8_t*) &combined_versions, | 80 TlclRead(KERNEL_VERSIONS_NV_INDEX, |
80 sizeof(uint32_t)); | 81 (uint8_t*) &combined_versions, sizeof(uint32_t)); |
81 TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, (uint8_t*) &combined_versions, | 82 TlclRead(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
82 sizeof(uint32_t)); | 83 (uint8_t*) &backup_versions, sizeof(uint32_t)); |
83 TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &one, | 84 /* We could unconditional writes of both KERNEL_VERSIONS_BACKUP and |
84 sizeof(uint32_t)); | 85 * KERNEL_BACKUP_IS_VALID, but this is more robust. |
| 86 */ |
| 87 if (combined_versions != backup_versions) { |
| 88 TlclWrite(KERNEL_VERSIONS_BACKUP_NV_INDEX, |
| 89 (uint8_t*) &combined_versions, sizeof(uint32_t)); |
| 90 } |
| 91 |
| 92 TlclRead(KERNEL_BACKUP_IS_VALID_NV_INDEX, |
| 93 (uint8_t*) &backup_is_valid, sizeof(uint32_t)); |
| 94 if (backup_is_valid != 1) { |
| 95 backup_is_valid = 1; |
| 96 TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &backup_is_valid, |
| 97 sizeof(uint32_t)); |
| 98 } |
85 /* Protects the firmware and backup kernel versions. */ | 99 /* Protects the firmware and backup kernel versions. */ |
86 LockFirmwareVersions(); | 100 LockFirmwareVersions(); |
87 } | 101 } |
88 debug("entering recovery mode"); | 102 debug("entering recovery mode"); |
89 | 103 |
90 /* and then what? */ | 104 /* TODO(nelson): code for entering recovery mode. */ |
91 } | 105 } |
92 | 106 |
93 static int GetTPMRollbackIndices(void) { | 107 static int GetTPMRollbackIndices(void) { |
94 uint32_t backup_is_valid; | 108 uint32_t backup_is_valid; |
95 uint32_t firmware_versions; | 109 uint32_t firmware_versions; |
96 uint32_t kernel_versions; | 110 uint32_t kernel_versions; |
97 | 111 |
98 if (TlclRead(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &backup_is_valid, | 112 if (TlclRead(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &backup_is_valid, |
99 sizeof(uint32_t)) != TPM_SUCCESS) { | 113 sizeof(uint32_t)) != TPM_SUCCESS) { |
100 EnterRecovery(1); | 114 EnterRecovery(1); |
(...skipping 21 matching lines...) Expand all Loading... |
122 TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, TPM_NV_PER_PPWRITE, | 136 TlclDefineSpace(KERNEL_VERSIONS_NV_INDEX, TPM_NV_PER_PPWRITE, |
123 sizeof(uint32_t)); | 137 sizeof(uint32_t)); |
124 } else if (result != TPM_SUCCESS) { | 138 } else if (result != TPM_SUCCESS) { |
125 EnterRecovery(1); | 139 EnterRecovery(1); |
126 } | 140 } |
127 if (result == TPM_E_BADINDEX || | 141 if (result == TPM_E_BADINDEX || |
128 protected_combined_versions != unsafe_combined_versions) { | 142 protected_combined_versions != unsafe_combined_versions) { |
129 TlclWrite(KERNEL_VERSIONS_NV_INDEX, | 143 TlclWrite(KERNEL_VERSIONS_NV_INDEX, |
130 (uint8_t*) &protected_combined_versions, sizeof(uint32_t)); | 144 (uint8_t*) &protected_combined_versions, sizeof(uint32_t)); |
131 } | 145 } |
132 /* We recovered and now we can reset the BACKUP_IS_VALID flag. | 146 /* We recovered the backed-up versions and now we can reset the |
| 147 * BACKUP_IS_VALID flag. |
133 */ | 148 */ |
134 TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &zero, 0); | 149 TlclWrite(KERNEL_BACKUP_IS_VALID_NV_INDEX, (uint8_t*) &zero, 0); |
| 150 |
| 151 /* TODO(nelson): ForceClear and reboot if unowned. */ |
135 } | 152 } |
136 | 153 |
137 /* We perform the reads, making sure they succeed. A failure means that the | 154 /* We perform the reads, making sure they succeed. A failure means that the |
138 * rollback index locations are missing or somehow messed up. We let the | 155 * rollback index locations are missing or somehow messed up. We let the |
139 * caller deal with that. | 156 * caller deal with that. |
140 */ | 157 */ |
141 if (TPM_SUCCESS != TlclRead(FIRMWARE_VERSIONS_NV_INDEX, | 158 if (TPM_SUCCESS != TlclRead(FIRMWARE_VERSIONS_NV_INDEX, |
142 (uint8_t*) &firmware_versions, | 159 (uint8_t*) &firmware_versions, |
143 sizeof(firmware_versions)) || | 160 sizeof(firmware_versions)) || |
144 TPM_SUCCESS != TlclRead(KERNEL_VERSIONS_NV_INDEX, | 161 TPM_SUCCESS != TlclRead(KERNEL_VERSIONS_NV_INDEX, |
145 (uint8_t*) &kernel_versions, | 162 (uint8_t*) &kernel_versions, |
146 sizeof(kernel_versions))) | 163 sizeof(kernel_versions))) |
147 return 0; | 164 return 0; |
148 | 165 |
149 g_firmware_key_version = firmware_versions >> 16; | 166 g_firmware_key_version = firmware_versions >> 16; |
150 g_firmware_version = firmware_versions && 0xffff; | 167 g_firmware_version = firmware_versions && 0xffff; |
151 g_kernel_key_version = kernel_versions >> 16; | 168 g_kernel_key_version = kernel_versions >> 16; |
152 g_kernel_version = kernel_versions && 0xffff; | 169 g_kernel_version = kernel_versions && 0xffff; |
153 | 170 |
154 return 1; | 171 return 1; |
155 } | 172 } |
156 | 173 |
157 | 174 |
158 void SetupTPM(void) { | 175 void SetupTPM(void) { |
159 uint8_t disable; | 176 uint8_t disable; |
160 uint8_t deactivated; | 177 uint8_t deactivated; |
161 TlclLibinit(); | 178 TlclLibinit(); |
162 TlclStartup(); | 179 TlclStartup(); |
163 /* TODO(gauravsh): The call to self test should probably be deferred. | 180 /* TODO(gauravsh): The call to self test should probably be deferred. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 return (TPM_SUCCESS == TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, | 230 return (TPM_SUCCESS == TlclWrite(FIRMWARE_VERSIONS_NV_INDEX, |
214 (uint8_t*) &combined_version, | 231 (uint8_t*) &combined_version, |
215 sizeof(uint32_t))); | 232 sizeof(uint32_t))); |
216 break; | 233 break; |
217 case KERNEL_VERSIONS: | 234 case KERNEL_VERSIONS: |
218 return (TPM_SUCCESS == TlclWrite(KERNEL_VERSIONS_NV_INDEX, | 235 return (TPM_SUCCESS == TlclWrite(KERNEL_VERSIONS_NV_INDEX, |
219 (uint8_t*) &combined_version, | 236 (uint8_t*) &combined_version, |
220 sizeof(uint32_t))); | 237 sizeof(uint32_t))); |
221 break; | 238 break; |
222 } | 239 } |
| 240 /* TODO(nelson): ForceClear and reboot if unowned. */ |
| 241 |
223 return 0; | 242 return 0; |
224 } | 243 } |
225 | 244 |
226 void LockFirmwareVersions() { | 245 void LockFirmwareVersions() { |
227 if (TlclSetGlobalLock() != TPM_SUCCESS) { | 246 if (TlclSetGlobalLock() != TPM_SUCCESS) { |
228 debug("failed to set global lock"); | 247 debug("failed to set global lock"); |
229 EnterRecovery(1); | 248 EnterRecovery(1); |
230 } | 249 } |
231 } | 250 } |
232 | 251 |
233 void LockKernelVersionsByLockingPP() { | 252 void LockKernelVersionsByLockingPP() { |
234 if (TlclLockPhysicalPresence() != TPM_SUCCESS) { | 253 if (TlclLockPhysicalPresence() != TPM_SUCCESS) { |
235 debug("failed to turn off PP"); | 254 debug("failed to turn off PP"); |
236 EnterRecovery(1); | 255 EnterRecovery(1); |
237 } | 256 } |
238 } | 257 } |
OLD | NEW |