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

Side by Side Diff: tpm.cc

Issue 3475009: Adds the necessary changes to tpm_init to allow triggered initialization. (Closed) Base URL: http://git.chromium.org/git/tpm_init.git
Patch Set: Address feedback. Created 10 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « tpm.h ('k') | tpm_init.h » ('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) 2009-2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2009-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 // Contains the implementation of class Tpm 5 // Contains the implementation of class Tpm
6 6
7 #include "tpm.h" 7 #include "tpm.h"
8 8
9 #include <base/file_util.h> 9 #include <base/file_util.h>
10 #include <base/platform_thread.h> 10 #include <base/platform_thread.h>
11 #include <base/time.h> 11 #include <base/time.h>
12 #include <openssl/rsa.h> 12 #include <openssl/rsa.h>
13 #include <trousers/tss.h> 13 #include <trousers/tss.h>
14 #include <trousers/trousers.h> 14 #include <trousers/trousers.h>
15 15
16 namespace tpm_init { 16 namespace tpm_init {
17 #define TPM_LOG(severity, result) \
18 LOG(severity) << "TPM error 0x" << std::hex << result \
19 << " (" << Trspi_Error_String(result) << "): "
20
17 21
18 const char* kWellKnownSrkTmp = "1234567890"; 22 const char* kWellKnownSrkTmp = "1234567890";
19 const int kOwnerPasswordLength = 12; 23 const int kOwnerPasswordLength = 12;
20 const int kMaxTimeoutRetries = 5; 24 const int kMaxTimeoutRetries = 5;
21 const char* kTpmCheckEnabledFile = "/sys/class/misc/tpm0/device/enabled"; 25 const char* kTpmCheckEnabledFile = "/sys/class/misc/tpm0/device/enabled";
22 const char* kTpmCheckOwnedFile = "/sys/class/misc/tpm0/device/owned"; 26 const char* kTpmCheckOwnedFile = "/sys/class/misc/tpm0/device/owned";
23 const char* kTpmOwnedFile = "/var/lib/.tpm_owned"; 27 const char* kTpmOwnedFile = "/var/lib/.tpm_owned";
28 const char* kTpmStatusFile = "/var/lib/.tpm_status";
24 const char* kOpenCryptokiPath = "/var/lib/opencryptoki"; 29 const char* kOpenCryptokiPath = "/var/lib/opencryptoki";
25 const int kTpmConnectRetries = 10; 30 const int kTpmConnectRetries = 10;
26 const int kTpmConnectIntervalMs = 100; 31 const int kTpmConnectIntervalMs = 100;
27 const char kTpmWellKnownPassword[] = TSS_WELL_KNOWN_SECRET; 32 const char kTpmWellKnownPassword[] = TSS_WELL_KNOWN_SECRET;
33 const char kTpmOwnedWithWellKnown = 'W';
34 const char kTpmOwnedWithRandom = 'R';
28 35
29 Tpm::Tpm() 36 Tpm::Tpm()
30 : context_handle_(0), 37 : default_crypto_(new Crypto()),
31 default_crypto_(new Crypto()),
32 crypto_(default_crypto_.get()), 38 crypto_(default_crypto_.get()),
39 default_platform_(new Platform()),
40 platform_(default_platform_.get()),
33 owner_password_(), 41 owner_password_(),
34 password_sync_lock_(), 42 password_sync_lock_(),
35 is_disabled_(true), 43 is_disabled_(true),
36 is_owned_(false), 44 is_owned_(false),
37 is_srk_available_(false), 45 is_srk_available_(false),
38 is_being_owned_(false) { 46 is_being_owned_(false) {
39 } 47 }
40 48
41 Tpm::~Tpm() { 49 Tpm::~Tpm() {
42 Disconnect();
43 } 50 }
44 51
45 bool Tpm::Init() { 52 bool Tpm::Init() {
46 // Checking disabled and owned either via sysfs or via TSS calls will block if 53 // Checking disabled and owned either via sysfs or via TSS calls will block if
47 // ownership is being taken by another thread or process. So for this to work 54 // ownership is being taken by another thread or process. So for this to work
48 // well, Tpm::Init() needs to be called before InitializeTpm() is called. At 55 // well, Tpm::Init() needs to be called before InitializeTpm() is called. At
49 // that point, the public API for Tpm only checks these booleans, so other 56 // that point, the public API for Tpm only checks these booleans, so other
50 // threads can check without being blocked. InitializeTpm() will reset the 57 // threads can check without being blocked. InitializeTpm() will reset the
51 // is_owned_ bit on success. 58 // is_owned_ bit on success.
59 bool successful_check = false;
52 if (file_util::PathExists(FilePath(kTpmCheckEnabledFile))) { 60 if (file_util::PathExists(FilePath(kTpmCheckEnabledFile))) {
53 is_disabled_ = IsDisabledCheckViaSysfs(); 61 is_disabled_ = IsDisabledCheckViaSysfs();
54 is_owned_ = IsOwnedCheckViaSysfs(); 62 is_owned_ = IsOwnedCheckViaSysfs();
63 successful_check = true;
55 } else { 64 } else {
56 TSS_HCONTEXT context_handle; 65 TSS_HCONTEXT context_handle;
57 if (OpenAndConnectTpm(&context_handle)) { 66 if (OpenAndConnectTpm(&context_handle)) {
58 bool enabled = false; 67 bool enabled = false;
59 bool owned = false; 68 bool owned = false;
60 IsEnabledOwnedCheckViaContext(context_handle, &enabled, &owned); 69 IsEnabledOwnedCheckViaContext(context_handle, &enabled, &owned);
61 is_disabled_ = !enabled; 70 is_disabled_ = !enabled;
62 is_owned_ = owned; 71 is_owned_ = owned;
63 Tspi_Context_Close(context_handle); 72 Tspi_Context_Close(context_handle);
64 } else { 73 successful_check = true;
65 } 74 }
66 } 75 }
67 return true; 76 if (successful_check && !is_owned_) {
68 } 77 file_util::Delete(FilePath(kOpenCryptokiPath), true);
69 78 file_util::Delete(FilePath(kTpmOwnedFile), false);
70 bool Tpm::Connect() { 79 file_util::Delete(FilePath(kTpmStatusFile), false);
71 if (context_handle_ == 0) { 80 }
72 TSS_HCONTEXT context_handle; 81 TpmStatus tpm_status;
73 if (!OpenAndConnectTpm(&context_handle)) { 82 if (LoadTpmStatus(&tpm_status)) {
74 return false; 83 if (tpm_status.has_owner_password()) {
84 SecureBlob local_owner_password;
85 if (LoadOwnerPassword(tpm_status, &local_owner_password)) {
86 password_sync_lock_.Acquire();
87 owner_password_.assign(local_owner_password.begin(),
88 local_owner_password.end());
89 password_sync_lock_.Release();
90 }
75 } 91 }
76
77 context_handle_ = context_handle;
78 } 92 }
79 93
80 return true; 94 return true;
81 } 95 }
82 96
83 bool Tpm::IsConnected() { 97 TSS_HCONTEXT Tpm::Connect() {
84 return (context_handle_ != 0); 98 TSS_HCONTEXT context_handle;
99 if (!OpenAndConnectTpm(&context_handle)) {
100 return NULL;
101 }
102
103 return context_handle;
85 } 104 }
86 105
87 void Tpm::Disconnect() { 106 void Tpm::Disconnect(TSS_HCONTEXT context_handle) {
88 if (context_handle_) { 107 if (context_handle) {
89 Tspi_Context_Close(context_handle_); 108 Tspi_Context_Close(context_handle);
90 context_handle_ = 0;
91 } 109 }
92 } 110 }
93 111
94 int Tpm::GetMaxRsaKeyCount() { 112 int Tpm::GetMaxRsaKeyCount() {
95 if (context_handle_ == 0) { 113 TSS_HCONTEXT context_handle = Connect();
114 if (!context_handle) {
96 return -1; 115 return -1;
97 } 116 }
117 int count = GetMaxRsaKeyCountForContext(context_handle);
118 Disconnect(context_handle);
119 return count;
120 }
98 121
99 return GetMaxRsaKeyCountForContext(context_handle_); 122 bool Tpm::IsDisabledCheckViaSysfs() {
123 std::string contents;
124 if (!file_util::ReadFileToString(FilePath(kTpmCheckEnabledFile), &contents)) {
125 return false;
126 }
127 if (contents.size() < 1) {
128 return false;
129 }
130 return (contents[0] == '0');
131 }
132
133 bool Tpm::IsOwnedCheckViaSysfs() {
134 std::string contents;
135 if (!file_util::ReadFileToString(FilePath(kTpmCheckOwnedFile), &contents)) {
136 return false;
137 }
138 if (contents.size() < 1) {
139 return false;
140 }
141 return (contents[0] != '0');
100 } 142 }
101 143
102 int Tpm::GetMaxRsaKeyCountForContext(TSS_HCONTEXT context_handle) { 144 int Tpm::GetMaxRsaKeyCountForContext(TSS_HCONTEXT context_handle) {
103 int count = -1; 145 int count = -1;
104 TSS_RESULT result; 146 TSS_RESULT result;
105 TSS_HTPM tpm_handle; 147 TSS_HTPM tpm_handle;
106 if (!GetTpm(context_handle, &tpm_handle)) { 148 if (!GetTpm(context_handle, &tpm_handle)) {
107 return count; 149 return count;
108 } 150 }
109 151
110 UINT32 cap_length = 0; 152 UINT32 cap_length = 0;
111 BYTE* cap = NULL; 153 BYTE* cap = NULL;
112 UINT32 subcap = TSS_TPMCAP_PROP_MAXKEYS; 154 UINT32 subcap = TSS_TPMCAP_PROP_MAXKEYS;
113 if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_PROPERTY, 155 if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_PROPERTY,
114 sizeof(subcap), 156 sizeof(subcap),
115 reinterpret_cast<BYTE*>(&subcap), 157 reinterpret_cast<BYTE*>(&subcap),
116 &cap_length, &cap))) { 158 &cap_length, &cap))) {
117 LOG(ERROR) << "Error calling Tspi_TPM_GetCapability: " << result; 159 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
118 return count; 160 return count;
119 } 161 }
120 if (cap_length == sizeof(int)) { 162 if (cap_length == sizeof(int)) {
121 count = *(reinterpret_cast<int*>(cap)); 163 count = *(reinterpret_cast<int*>(cap));
122 } 164 }
123 Tspi_Context_FreeMemory(context_handle, cap); 165 Tspi_Context_FreeMemory(context_handle, cap);
124 return count; 166 return count;
125 } 167 }
126 168
127 bool Tpm::OpenAndConnectTpm(TSS_HCONTEXT* context_handle) { 169 bool Tpm::OpenAndConnectTpm(TSS_HCONTEXT* context_handle) {
128 TSS_RESULT result; 170 TSS_RESULT result;
129 TSS_HCONTEXT local_context_handle; 171 TSS_HCONTEXT local_context_handle;
130 if ((result = Tspi_Context_Create(&local_context_handle))) { 172 if ((result = Tspi_Context_Create(&local_context_handle))) {
131 LOG(ERROR) << "Error calling Tspi_Context_Create"; 173 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_Create";
132 return false; 174 return false;
133 } 175 }
134 176
135 for (int i = 0; i < kTpmConnectRetries; i++) { 177 for (int i = 0; i < kTpmConnectRetries; i++) {
136 if ((result = Tspi_Context_Connect(local_context_handle, NULL))) { 178 if ((result = Tspi_Context_Connect(local_context_handle, NULL))) {
137 if (result == TSS_E_COMM_FAILURE) { 179 if (result == TSS_E_COMM_FAILURE) {
138 PlatformThread::Sleep(kTpmConnectIntervalMs); 180 PlatformThread::Sleep(kTpmConnectIntervalMs);
139 } else { 181 } else {
140 LOG(ERROR) << "Error calling Tspi_Context_Connect: " << result; 182 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_Connect";
141 Tspi_Context_Close(local_context_handle); 183 Tspi_Context_Close(local_context_handle);
142 return false; 184 return false;
143 } 185 }
144 } else { 186 } else {
145 break; 187 break;
146 } 188 }
147 } 189 }
148 190
149 if (result) { 191 if (result) {
150 LOG(ERROR) << "Error calling Tspi_Context_Connect: " << result; 192 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_Connect";
151 Tspi_Context_Close(local_context_handle); 193 Tspi_Context_Close(local_context_handle);
152 return false; 194 return false;
153 } 195 }
154 196
155 *context_handle = local_context_handle; 197 *context_handle = local_context_handle;
156 return true; 198 return true;
157 } 199 }
158 200
159 bool Tpm::IsDisabledCheckViaSysfs() {
160 std::string contents;
161 if (!file_util::ReadFileToString(FilePath(kTpmCheckEnabledFile), &contents)) {
162 return false;
163 }
164 if (contents.size() < 1) {
165 return false;
166 }
167 return (contents[0] == '0');
168 }
169
170 bool Tpm::IsOwnedCheckViaSysfs() {
171 std::string contents;
172 if (!file_util::ReadFileToString(FilePath(kTpmCheckOwnedFile), &contents)) {
173 return false;
174 }
175 if (contents.size() < 1) {
176 return false;
177 }
178 return (contents[0] != '0');
179 }
180
181 void Tpm::IsEnabledOwnedCheckViaContext(TSS_HCONTEXT context_handle, 201 void Tpm::IsEnabledOwnedCheckViaContext(TSS_HCONTEXT context_handle,
182 bool* enabled, bool* owned) { 202 bool* enabled, bool* owned) {
183 *enabled = false; 203 *enabled = false;
184 *owned = false; 204 *owned = false;
185 205
186 TSS_RESULT result; 206 TSS_RESULT result;
187 TSS_HTPM tpm_handle; 207 TSS_HTPM tpm_handle;
188 if (!GetTpm(context_handle, &tpm_handle)) { 208 if (!GetTpm(context_handle, &tpm_handle)) {
189 return; 209 return;
190 } 210 }
(...skipping 20 matching lines...) Expand all
211 TSS_HTPM tpm_handle; 231 TSS_HTPM tpm_handle;
212 if (!GetTpm(context_handle, &tpm_handle)) { 232 if (!GetTpm(context_handle, &tpm_handle)) {
213 return false; 233 return false;
214 } 234 }
215 235
216 TSS_HKEY local_key_handle; 236 TSS_HKEY local_key_handle;
217 TSS_FLAG init_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_SIZE_2048; 237 TSS_FLAG init_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_SIZE_2048;
218 if ((result = Tspi_Context_CreateObject(context_handle, 238 if ((result = Tspi_Context_CreateObject(context_handle,
219 TSS_OBJECT_TYPE_RSAKEY, 239 TSS_OBJECT_TYPE_RSAKEY,
220 init_flags, &local_key_handle))) { 240 init_flags, &local_key_handle))) {
221 LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result; 241 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
222 return false; 242 return false;
223 } 243 }
224 244
225 if ((result = Tspi_TPM_CreateEndorsementKey(tpm_handle, local_key_handle, 245 if ((result = Tspi_TPM_CreateEndorsementKey(tpm_handle, local_key_handle,
226 NULL))) { 246 NULL))) {
227 LOG(ERROR) << "Error calling Tspi_TPM_CreateEndorsementKey: " << result; 247 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_CreateEndorsementKey";
228 Tspi_Context_CloseObject(context_handle, local_key_handle); 248 Tspi_Context_CloseObject(context_handle, local_key_handle);
229 return false; 249 return false;
230 } 250 }
231 251
232 return true; 252 return true;
233 } 253 }
234 254
235 bool Tpm::IsEndorsementKeyAvailable(TSS_HCONTEXT context_handle) { 255 bool Tpm::IsEndorsementKeyAvailable(TSS_HCONTEXT context_handle) {
236 TSS_RESULT result; 256 TSS_RESULT result;
237 TSS_HTPM tpm_handle; 257 TSS_HTPM tpm_handle;
238 if (!GetTpm(context_handle, &tpm_handle)) { 258 if (!GetTpm(context_handle, &tpm_handle)) {
239 return false; 259 return false;
240 } 260 }
241 261
242 TSS_HKEY local_key_handle; 262 TSS_HKEY local_key_handle;
243 if ((result = Tspi_TPM_GetPubEndorsementKey(tpm_handle, false, NULL, 263 if ((result = Tspi_TPM_GetPubEndorsementKey(tpm_handle, false, NULL,
244 &local_key_handle))) { 264 &local_key_handle))) {
245 LOG(ERROR) << "Error calling Tspi_TPM_GetPubEndorsementKey: " << result; 265 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetPubEndorsementKey";
246 return false; 266 return false;
247 } 267 }
248 268
249 Tspi_Context_CloseObject(context_handle, local_key_handle); 269 Tspi_Context_CloseObject(context_handle, local_key_handle);
250 270
251 return true; 271 return true;
252 } 272 }
253 273
254 void Tpm::CreateOwnerPassword(SecureBlob* password) { 274 void Tpm::CreateOwnerPassword(SecureBlob* password) {
255 SecureBlob random(kOwnerPasswordLength); 275 // Generate a random owner password. The default is a 12-character,
276 // hex-encoded password created from 6 bytes of random data.
277 SecureBlob random(kOwnerPasswordLength / 2);
256 crypto_->GetSecureRandom(static_cast<unsigned char*>(random.data()), 278 crypto_->GetSecureRandom(static_cast<unsigned char*>(random.data()),
257 random.size()); 279 random.size());
258 SecureBlob tpm_password(kOwnerPasswordLength); 280 SecureBlob tpm_password(kOwnerPasswordLength);
259 crypto_->AsciiEncodeToBuffer(random, static_cast<char*>(tpm_password.data()), 281 crypto_->AsciiEncodeToBuffer(random, static_cast<char*>(tpm_password.data()),
260 tpm_password.size()); 282 tpm_password.size());
261 password->swap(tpm_password); 283 password->swap(tpm_password);
262 } 284 }
263 285
264 bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries, 286 bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries,
265 const SecureBlob& owner_password) { 287 const SecureBlob& owner_password) {
266 TSS_RESULT result; 288 TSS_RESULT result;
267 TSS_HTPM tpm_handle; 289 TSS_HTPM tpm_handle;
268 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) { 290 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) {
269 return false; 291 return false;
270 } 292 }
271 293
272 TSS_HKEY srk_handle; 294 TSS_HKEY srk_handle;
273 TSS_FLAG init_flags = TSS_KEY_TSP_SRK | TSS_KEY_AUTHORIZATION; 295 TSS_FLAG init_flags = TSS_KEY_TSP_SRK | TSS_KEY_AUTHORIZATION;
274 if ((result = Tspi_Context_CreateObject(context_handle, 296 if ((result = Tspi_Context_CreateObject(context_handle,
275 TSS_OBJECT_TYPE_RSAKEY, 297 TSS_OBJECT_TYPE_RSAKEY,
276 init_flags, &srk_handle))) { 298 init_flags, &srk_handle))) {
277 LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result; 299 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
278 return false; 300 return false;
279 } 301 }
280 302
281 TSS_HPOLICY srk_usage_policy; 303 TSS_HPOLICY srk_usage_policy;
282 if ((result = Tspi_GetPolicyObject(srk_handle, TSS_POLICY_USAGE, 304 if ((result = Tspi_GetPolicyObject(srk_handle, TSS_POLICY_USAGE,
283 &srk_usage_policy))) { 305 &srk_usage_policy))) {
284 LOG(ERROR) << "Error calling Tspi_GetPolicyObject: " << result; 306 TPM_LOG(ERROR, result) << "Error calling Tspi_GetPolicyObject";
285 Tspi_Context_CloseObject(context_handle, srk_handle); 307 Tspi_Context_CloseObject(context_handle, srk_handle);
286 return false; 308 return false;
287 } 309 }
288 310
289 if ((result = Tspi_Policy_SetSecret(srk_usage_policy, 311 if ((result = Tspi_Policy_SetSecret(srk_usage_policy,
290 TSS_SECRET_MODE_PLAIN, 312 TSS_SECRET_MODE_PLAIN,
291 strlen(kWellKnownSrkTmp), 313 strlen(kWellKnownSrkTmp),
292 const_cast<BYTE *>(reinterpret_cast<const BYTE *>(kWellKnownSrkTmp))))) { 314 const_cast<BYTE *>(reinterpret_cast<const BYTE *>(kWellKnownSrkTmp))))) {
293 LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result; 315 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
294 Tspi_Context_CloseObject(context_handle, srk_handle); 316 Tspi_Context_CloseObject(context_handle, srk_handle);
295 return false; 317 return false;
296 } 318 }
297 319
298 int retry_count = 0; 320 int retry_count = 0;
299 do { 321 do {
300 result = Tspi_TPM_TakeOwnership(tpm_handle, srk_handle, 0); 322 result = Tspi_TPM_TakeOwnership(tpm_handle, srk_handle, 0);
301 retry_count++; 323 retry_count++;
302 } while(((result == TDDL_E_TIMEOUT) || 324 } while(((result == TDDL_E_TIMEOUT) ||
303 (result == (TSS_LAYER_TDDL | TDDL_E_TIMEOUT)) || 325 (result == (TSS_LAYER_TDDL | TDDL_E_TIMEOUT)) ||
304 (result == (TSS_LAYER_TDDL | TDDL_E_IOERROR))) && 326 (result == (TSS_LAYER_TDDL | TDDL_E_IOERROR))) &&
305 (retry_count < max_timeout_tries)); 327 (retry_count < max_timeout_tries));
306 328
307 if (result) { 329 if (result) {
308 LOG(ERROR) << "Error calling Tspi_TPM_TakeOwnership: " << result 330 TPM_LOG(ERROR, result)
309 << ", attempts: " << retry_count; 331 << "Error calling Tspi_TPM_TakeOwnership, attempts: " << retry_count;
310 Tspi_Context_CloseObject(context_handle, srk_handle); 332 Tspi_Context_CloseObject(context_handle, srk_handle);
311 return false; 333 return false;
312 } 334 }
313 335
314 Tspi_Context_CloseObject(context_handle, srk_handle); 336 Tspi_Context_CloseObject(context_handle, srk_handle);
315 337
316 return true; 338 return true;
317 } 339 }
318 340
319 bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle, 341 bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle,
320 const SecureBlob& owner_password) { 342 const SecureBlob& owner_password) {
321 TSS_RESULT result; 343 TSS_RESULT result;
322 TSS_HTPM tpm_handle; 344 TSS_HTPM tpm_handle;
323 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) { 345 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) {
324 return false; 346 return false;
325 } 347 }
326 348
327 TSS_HKEY srk_handle; 349 TSS_HKEY srk_handle;
328 TSS_UUID SRK_UUID = TSS_UUID_SRK; 350 TSS_UUID SRK_UUID = TSS_UUID_SRK;
329 if ((result = Tspi_Context_LoadKeyByUUID(context_handle, TSS_PS_TYPE_SYSTEM, 351 if ((result = Tspi_Context_LoadKeyByUUID(context_handle, TSS_PS_TYPE_SYSTEM,
330 SRK_UUID, &srk_handle))) { 352 SRK_UUID, &srk_handle))) {
331 LOG(ERROR) << "Error calling Tspi_Context_LoadKeyByUUID: " << result; 353 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_LoadKeyByUUID";
332 return false; 354 return false;
333 } 355 }
334 356
335 TSS_HPOLICY policy_handle; 357 TSS_HPOLICY policy_handle;
336 if ((result = Tspi_Context_CreateObject(context_handle, 358 if ((result = Tspi_Context_CreateObject(context_handle,
337 TSS_OBJECT_TYPE_POLICY, 359 TSS_OBJECT_TYPE_POLICY,
338 TSS_POLICY_USAGE, 360 TSS_POLICY_USAGE,
339 &policy_handle))) { 361 &policy_handle))) {
340 LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result; 362 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
341 Tspi_Context_CloseObject(context_handle, srk_handle); 363 Tspi_Context_CloseObject(context_handle, srk_handle);
342 return false; 364 return false;
343 } 365 }
344 366
345 BYTE new_password[0]; 367 BYTE new_password[0];
346 if ((result = Tspi_Policy_SetSecret(policy_handle, TSS_SECRET_MODE_PLAIN, 368 if ((result = Tspi_Policy_SetSecret(policy_handle, TSS_SECRET_MODE_PLAIN,
347 0, new_password))) { 369 0, new_password))) {
348 LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result; 370 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
349 Tspi_Context_CloseObject(context_handle, policy_handle); 371 Tspi_Context_CloseObject(context_handle, policy_handle);
350 Tspi_Context_CloseObject(context_handle, srk_handle); 372 Tspi_Context_CloseObject(context_handle, srk_handle);
351 return false; 373 return false;
352 } 374 }
353 375
354 if ((result = Tspi_ChangeAuth(srk_handle, 376 if ((result = Tspi_ChangeAuth(srk_handle,
355 tpm_handle, 377 tpm_handle,
356 policy_handle))) { 378 policy_handle))) {
357 LOG(ERROR) << "Error calling Tspi_ChangeAuth: " << result; 379 TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
358 Tspi_Context_CloseObject(context_handle, policy_handle); 380 Tspi_Context_CloseObject(context_handle, policy_handle);
359 Tspi_Context_CloseObject(context_handle, srk_handle); 381 Tspi_Context_CloseObject(context_handle, srk_handle);
360 return false; 382 return false;
361 } 383 }
362 384
363 Tspi_Context_CloseObject(context_handle, policy_handle); 385 Tspi_Context_CloseObject(context_handle, policy_handle);
364 Tspi_Context_CloseObject(context_handle, srk_handle); 386 Tspi_Context_CloseObject(context_handle, srk_handle);
365 return true; 387 return true;
366 } 388 }
367 389
368 bool Tpm::UnrestrictSrk(TSS_HCONTEXT context_handle, 390 bool Tpm::UnrestrictSrk(TSS_HCONTEXT context_handle,
369 const SecureBlob& owner_password) { 391 const SecureBlob& owner_password) {
370 TSS_RESULT result; 392 TSS_RESULT result;
371 TSS_HTPM tpm_handle; 393 TSS_HTPM tpm_handle;
372 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) { 394 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) {
373 return false; 395 return false;
374 } 396 }
375 397
376 TSS_BOOL current_status = false; 398 TSS_BOOL current_status = false;
377 399
378 if ((result = Tspi_TPM_GetStatus(tpm_handle, 400 if ((result = Tspi_TPM_GetStatus(tpm_handle,
379 TSS_TPMSTATUS_DISABLEPUBSRKREAD, 401 TSS_TPMSTATUS_DISABLEPUBSRKREAD,
380 &current_status))) { 402 &current_status))) {
381 LOG(ERROR) << "Error calling Tspi_TPM_GetStatus: " << result; 403 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetStatus";
382 return false; 404 return false;
383 } 405 }
384 406
385 // If it is currently owner auth (true), set it to SRK auth 407 // If it is currently owner auth (true), set it to SRK auth
386 if (current_status) { 408 if (current_status) {
387 if ((result = Tspi_TPM_SetStatus(tpm_handle, 409 if ((result = Tspi_TPM_SetStatus(tpm_handle,
388 TSS_TPMSTATUS_DISABLEPUBSRKREAD, 410 TSS_TPMSTATUS_DISABLEPUBSRKREAD,
389 false))) { 411 false))) {
390 LOG(ERROR) << "Error calling Tspi_TPM_SetStatus: " << result; 412 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_SetStatus";
391 return false; 413 return false;
392 } 414 }
393 } 415 }
394 416
395 return true; 417 return true;
396 } 418 }
397 419
398 bool Tpm::ChangeOwnerPassword(TSS_HCONTEXT context_handle, 420 bool Tpm::ChangeOwnerPassword(TSS_HCONTEXT context_handle,
399 const SecureBlob& previous_owner_password, 421 const SecureBlob& previous_owner_password,
400 const SecureBlob& owner_password) { 422 const SecureBlob& owner_password) {
401 TSS_RESULT result; 423 TSS_RESULT result;
402 TSS_HTPM tpm_handle; 424 TSS_HTPM tpm_handle;
403 if (!GetTpmWithAuth(context_handle, previous_owner_password, &tpm_handle)) { 425 if (!GetTpmWithAuth(context_handle, previous_owner_password, &tpm_handle)) {
404 return false; 426 return false;
405 } 427 }
406 428
407 TSS_HPOLICY policy_handle; 429 TSS_HPOLICY policy_handle;
408 if ((result = Tspi_Context_CreateObject(context_handle, 430 if ((result = Tspi_Context_CreateObject(context_handle,
409 TSS_OBJECT_TYPE_POLICY, 431 TSS_OBJECT_TYPE_POLICY,
410 TSS_POLICY_USAGE, 432 TSS_POLICY_USAGE,
411 &policy_handle))) { 433 &policy_handle))) {
412 LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result; 434 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
413 return false; 435 return false;
414 } 436 }
415 437
416 if ((result = Tspi_Policy_SetSecret(policy_handle, 438 if ((result = Tspi_Policy_SetSecret(policy_handle,
417 TSS_SECRET_MODE_PLAIN, 439 TSS_SECRET_MODE_PLAIN,
418 owner_password.size(), 440 owner_password.size(),
419 const_cast<BYTE *>(static_cast<const BYTE *>( 441 const_cast<BYTE *>(static_cast<const BYTE *>(
420 owner_password.const_data()))))) { 442 owner_password.const_data()))))) {
421 LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result; 443 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
422 Tspi_Context_CloseObject(context_handle, policy_handle); 444 Tspi_Context_CloseObject(context_handle, policy_handle);
423 return false; 445 return false;
424 } 446 }
425 447
426 if ((result = Tspi_ChangeAuth(tpm_handle, 0, policy_handle))) { 448 if ((result = Tspi_ChangeAuth(tpm_handle, 0, policy_handle))) {
427 LOG(ERROR) << "Error calling Tspi_ChangeAuth: " << result; 449 TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
428 Tspi_Context_CloseObject(context_handle, policy_handle); 450 Tspi_Context_CloseObject(context_handle, policy_handle);
429 return false; 451 return false;
430 } 452 }
431 453
432 return true; 454 Tspi_Context_CloseObject(context_handle, policy_handle);
433 } 455 return true;
434 456 }
457
458 // TODO(fes): This method is borrowed from cryptohome. When the tpm_init
459 // library is merged into cryptohome, these duplicate methods need to be
460 // removed. Either that, or they should be moved into a separate library.
461 bool Tpm::LoadFileBytes(const FilePath& path, chromeos::Blob* blob) {
462 int64 file_size;
463 if (!file_util::PathExists(path)) {
464 return false;
465 }
466 if (!file_util::GetFileSize(path, &file_size)) {
467 LOG(ERROR) << "Could not get size of " << path.value();
468 return false;
469 }
470 // Compare to the max of a 32-bit signed integer
471 if (file_size > static_cast<int64>(INT_MAX)) {
472 LOG(ERROR) << "File " << path.value() << " is too large: " << file_size;
473 return false;
474 }
475 SecureBlob buf(file_size);
476 int data_read = file_util::ReadFile(path, reinterpret_cast<char*>(&buf[0]),
477 file_size);
478 // Cast is okay because of comparison to INT_MAX above
479 if (data_read != static_cast<int>(file_size)) {
480 LOG(ERROR) << "Could not read entire file " << file_size;
481 return false;
482 }
483 blob->swap(buf);
484 return true;
485 }
486
487 bool Tpm::LoadOwnerPassword(const TpmStatus& tpm_status,
488 chromeos::Blob* owner_password) {
489 if (!(tpm_status.flags() & TpmStatus::OWNED_BY_THIS_INSTALL)) {
490 return false;
491 }
492 if ((tpm_status.flags() & TpmStatus::USES_WELL_KNOWN_OWNER)) {
493 SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword));
494 memcpy(default_owner_password.data(), kTpmWellKnownPassword,
495 sizeof(kTpmWellKnownPassword));
496 owner_password->swap(default_owner_password);
497 return true;
498 }
499 if (!(tpm_status.flags() & TpmStatus::USES_RANDOM_OWNER) ||
500 !tpm_status.has_owner_password()) {
501 return false;
502 }
503
504 TSS_HCONTEXT context_handle;
505 if (!OpenAndConnectTpm(&context_handle)) {
506 return false;
507 }
508
509 TSS_RESULT result;
510 TSS_HKEY srk_handle;
511 if (!LoadSrk(context_handle, &srk_handle, &result)) {
512 LOG(ERROR) << "Error loading the SRK";
513 Tspi_Context_Close(context_handle);
514 return false;
515 }
516
517 TSS_FLAG init_flags = TSS_ENCDATA_SEAL;
518 TSS_HKEY enc_handle;
519 if ((result = Tspi_Context_CreateObject(context_handle,
520 TSS_OBJECT_TYPE_ENCDATA,
521 init_flags, &enc_handle))) {
522 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
523 Tspi_Context_CloseObject(context_handle, srk_handle);
524 Tspi_Context_Close(context_handle);
525 return false;
526 }
527
528 SecureBlob local_owner_password(tpm_status.owner_password().length());
529 tpm_status.owner_password().copy(
530 static_cast<char*>(local_owner_password.data()),
531 tpm_status.owner_password().length(), 0);
532
533 if ((result = Tspi_SetAttribData(enc_handle,
534 TSS_TSPATTRIB_ENCDATA_BLOB,
535 TSS_TSPATTRIB_ENCDATABLOB_BLOB,
536 local_owner_password.size(),
537 static_cast<BYTE *>(local_owner_password.data())))) {
538 TPM_LOG(ERROR, result) << "Error calling Tspi_SetAttribData";
539 Tspi_Context_CloseObject(context_handle, enc_handle);
540 Tspi_Context_CloseObject(context_handle, srk_handle);
541 Tspi_Context_Close(context_handle);
542 return false;
543 }
544
545 unsigned char* dec_data = NULL;
546 UINT32 dec_data_length = 0;
547 if ((result = Tspi_Data_Unseal(enc_handle, srk_handle, &dec_data_length,
548 &dec_data))) {
549 TPM_LOG(ERROR, result) << "Error calling Tspi_Data_Unseal";
550 Tspi_Context_CloseObject(context_handle, enc_handle);
551 Tspi_Context_CloseObject(context_handle, srk_handle);
552 Tspi_Context_Close(context_handle);
553 return false;
554 }
555
556 Tspi_Context_CloseObject(context_handle, enc_handle);
557
558 SecureBlob local_data(dec_data_length);
559 memcpy(static_cast<char*>(local_data.data()), dec_data, dec_data_length);
560 Tspi_Context_FreeMemory(context_handle, dec_data);
561
562 Tspi_Context_CloseObject(context_handle, srk_handle);
563 Tspi_Context_Close(context_handle);
564
565 owner_password->swap(local_data);
566
567 return true;
568 }
569
570 bool Tpm::StoreOwnerPassword(const chromeos::Blob& owner_password,
571 TpmStatus* tpm_status) {
572 TSS_HCONTEXT context_handle;
573 if (!OpenAndConnectTpm(&context_handle)) {
574 return false;
575 }
576
577 TSS_RESULT result;
578 TSS_HKEY srk_handle;
579 if (!LoadSrk(context_handle, &srk_handle, &result)) {
580 LOG(ERROR) << "Error loading the SRK";
581 Tspi_Context_Close(context_handle);
582 return false;
583 }
584
585 // Check the SRK public key
586 unsigned int size_n;
587 BYTE *public_srk;
588 if ((result = Tspi_Key_GetPubKey(srk_handle, &size_n, &public_srk))) {
589 TPM_LOG(ERROR, result) << "Unable to get the SRK public key";
590 Tspi_Context_CloseObject(context_handle, srk_handle);
591 Tspi_Context_Close(context_handle);
592 return false;
593 }
594 Tspi_Context_FreeMemory(context_handle, public_srk);
595
596 TSS_HTPM tpm_handle;
597 if (!GetTpm(context_handle, &tpm_handle)) {
598 LOG(ERROR) << "Unable to get a handle to the TPM";
599 Tspi_Context_CloseObject(context_handle, srk_handle);
600 Tspi_Context_Close(context_handle);
601 return false;
602 }
603
604 // Use PCR0 when sealing the data so that the owner password is only
605 // available in the current boot mode. This helps protect the password from
606 // offline attacks until it has been presented and cleared.
607 TSS_HPCRS pcrs_handle;
608 if ((result = Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_PCRS,
609 0, &pcrs_handle))) {
610 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
611 Tspi_Context_CloseObject(context_handle, srk_handle);
612 Tspi_Context_Close(context_handle);
613 return false;
614 }
615
616 UINT32 pcr_len;
617 BYTE* pcr_value;
618 Tspi_TPM_PcrRead(tpm_handle, 0, &pcr_len, &pcr_value);
619 Tspi_PcrComposite_SetPcrValue(pcrs_handle, 0, pcr_len, pcr_value);
620 Tspi_Context_FreeMemory(context_handle, pcr_value);
621
622 TSS_FLAG init_flags = TSS_ENCDATA_SEAL;
623 TSS_HKEY enc_handle;
624 if ((result = Tspi_Context_CreateObject(context_handle,
625 TSS_OBJECT_TYPE_ENCDATA,
626 init_flags, &enc_handle))) {
627 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
628 Tspi_Context_CloseObject(context_handle, pcrs_handle);
629 Tspi_Context_CloseObject(context_handle, srk_handle);
630 Tspi_Context_Close(context_handle);
631 return false;
632 }
633
634 if ((result = Tspi_Data_Seal(enc_handle, srk_handle, owner_password.size(),
635 const_cast<BYTE *>(&owner_password[0]),
636 pcrs_handle))) {
637 TPM_LOG(ERROR, result) << "Error calling Tspi_Data_Seal";
638 Tspi_Context_CloseObject(context_handle, pcrs_handle);
639 Tspi_Context_CloseObject(context_handle, enc_handle);
640 Tspi_Context_CloseObject(context_handle, srk_handle);
641 Tspi_Context_Close(context_handle);
642 return false;
643 }
644 Tspi_Context_CloseObject(context_handle, pcrs_handle);
645
646 unsigned char* enc_data = NULL;
647 UINT32 enc_data_length = 0;
648 if ((result = Tspi_GetAttribData(enc_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
649 TSS_TSPATTRIB_ENCDATABLOB_BLOB,
650 &enc_data_length, &enc_data))) {
651 TPM_LOG(ERROR, result) << "Error calling Tspi_GetAttribData";
652 Tspi_Context_CloseObject(context_handle, enc_handle);
653 Tspi_Context_CloseObject(context_handle, srk_handle);
654 Tspi_Context_Close(context_handle);
655 return false;
656 }
657 Tspi_Context_CloseObject(context_handle, enc_handle);
658
659 tpm_status->set_owner_password(enc_data, enc_data_length);
660
661 Tspi_Context_FreeMemory(context_handle, enc_data);
662 Tspi_Context_CloseObject(context_handle, srk_handle);
663 Tspi_Context_Close(context_handle);
664
665 return true;
666 }
667
435 bool Tpm::GetTpm(TSS_HCONTEXT context_handle, TSS_HTPM* tpm_handle) { 668 bool Tpm::GetTpm(TSS_HCONTEXT context_handle, TSS_HTPM* tpm_handle) {
436 TSS_RESULT result; 669 TSS_RESULT result;
437 TSS_HTPM local_tpm_handle; 670 TSS_HTPM local_tpm_handle;
438 if ((result = Tspi_Context_GetTpmObject(context_handle, &local_tpm_handle))) { 671 if ((result = Tspi_Context_GetTpmObject(context_handle, &local_tpm_handle))) {
439 LOG(ERROR) << "Error calling Tspi_Context_GetTpmObject: " << result; 672 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_GetTpmObject";
440 return false; 673 return false;
441 } 674 }
442 675
443 *tpm_handle = local_tpm_handle; 676 *tpm_handle = local_tpm_handle;
444 return true; 677 return true;
445 } 678 }
446 679
447 bool Tpm::GetTpmWithAuth(TSS_HCONTEXT context_handle, 680 bool Tpm::GetTpmWithAuth(TSS_HCONTEXT context_handle,
448 const SecureBlob& owner_password, 681 const SecureBlob& owner_password,
449 TSS_HTPM* tpm_handle) { 682 TSS_HTPM* tpm_handle) {
450 TSS_RESULT result; 683 TSS_RESULT result;
451 TSS_HTPM local_tpm_handle; 684 TSS_HTPM local_tpm_handle;
452 if (!GetTpm(context_handle, &local_tpm_handle)) { 685 if (!GetTpm(context_handle, &local_tpm_handle)) {
453 return false; 686 return false;
454 } 687 }
455 688
456 TSS_HPOLICY tpm_usage_policy; 689 TSS_HPOLICY tpm_usage_policy;
457 if ((result = Tspi_GetPolicyObject(local_tpm_handle, TSS_POLICY_USAGE, 690 if ((result = Tspi_GetPolicyObject(local_tpm_handle, TSS_POLICY_USAGE,
458 &tpm_usage_policy))) { 691 &tpm_usage_policy))) {
459 LOG(ERROR) << "Error calling Tspi_GetPolicyObject: " << result; 692 TPM_LOG(ERROR, result) << "Error calling Tspi_GetPolicyObject";
460 return false; 693 return false;
461 } 694 }
462 695
463 if ((result = Tspi_Policy_SetSecret(tpm_usage_policy, TSS_SECRET_MODE_PLAIN, 696 if ((result = Tspi_Policy_SetSecret(tpm_usage_policy, TSS_SECRET_MODE_PLAIN,
464 owner_password.size(), 697 owner_password.size(),
465 const_cast<BYTE *>(static_cast<const BYTE *>( 698 const_cast<BYTE *>(static_cast<const BYTE *>(
466 owner_password.const_data()))))) { 699 owner_password.const_data()))))) {
467 LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result; 700 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
468 return false; 701 return false;
469 } 702 }
470 703
471 *tpm_handle = local_tpm_handle; 704 *tpm_handle = local_tpm_handle;
472 return true; 705 return true;
473 } 706 }
474 707
475 bool Tpm::TestTpmAuth(TSS_HTPM tpm_handle) { 708 bool Tpm::TestTpmAuth(TSS_HTPM tpm_handle) {
476 // Call Tspi_TPM_GetStatus to test the authentication 709 // Call Tspi_TPM_GetStatus to test the authentication
477 TSS_RESULT result; 710 TSS_RESULT result;
(...skipping 12 matching lines...) Expand all
490 if (owner_password_.size() != 0) { 723 if (owner_password_.size() != 0) {
491 owner_password->assign(owner_password_.begin(), owner_password_.end()); 724 owner_password->assign(owner_password_.begin(), owner_password_.end());
492 result = true; 725 result = true;
493 } 726 }
494 password_sync_lock_.Release(); 727 password_sync_lock_.Release();
495 } 728 }
496 return result; 729 return result;
497 } 730 }
498 731
499 bool Tpm::InitializeTpm(bool* OUT_took_ownership) { 732 bool Tpm::InitializeTpm(bool* OUT_took_ownership) {
733 TpmStatus tpm_status;
734
735 if (!LoadTpmStatus(&tpm_status)) {
736 tpm_status.Clear();
737 tpm_status.set_flags(TpmStatus::NONE);
738 }
739
500 if (OUT_took_ownership) { 740 if (OUT_took_ownership) {
501 *OUT_took_ownership = false; 741 *OUT_took_ownership = false;
502 } 742 }
503 743
504 if (!IsConnected()) {
505 Connect();
506 }
507
508 if (!IsConnected()) {
509 LOG(ERROR) << "Failed to connect to TPM";
510 return false;
511 }
512
513 if (is_disabled_) { 744 if (is_disabled_) {
514 return false; 745 return false;
515 } 746 }
516 747
748 TSS_HCONTEXT context_handle = Connect();
749
750 if (!context_handle) {
751 LOG(ERROR) << "Failed to connect to TPM";
752 return false;
753 }
754
517 SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword)); 755 SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword));
518 memcpy(default_owner_password.data(), kTpmWellKnownPassword, 756 memcpy(default_owner_password.data(), kTpmWellKnownPassword,
519 sizeof(kTpmWellKnownPassword)); 757 sizeof(kTpmWellKnownPassword));
520 758
521 bool took_ownership = false; 759 bool took_ownership = false;
522 if (!is_owned_) { 760 if (!is_owned_) {
523 is_being_owned_ = true; 761 is_being_owned_ = true;
524 file_util::Delete(FilePath(kOpenCryptokiPath), true); 762 file_util::Delete(FilePath(kOpenCryptokiPath), true);
525 file_util::Delete(FilePath(kTpmOwnedFile), false); 763 file_util::Delete(FilePath(kTpmOwnedFile), false);
764 file_util::Delete(FilePath(kTpmStatusFile), false);
526 765
527 if (!IsEndorsementKeyAvailable(context_handle_)) { 766 if (!IsEndorsementKeyAvailable(context_handle)) {
528 if (!CreateEndorsementKey(context_handle_)) { 767 if (!CreateEndorsementKey(context_handle)) {
529 LOG(ERROR) << "Failed to create endorsement key"; 768 LOG(ERROR) << "Failed to create endorsement key";
530 is_being_owned_ = false; 769 is_being_owned_ = false;
770 Disconnect(context_handle);
531 return false; 771 return false;
532 } 772 }
533 } 773 }
534 774
535 if (!IsEndorsementKeyAvailable(context_handle_)) { 775 if (!IsEndorsementKeyAvailable(context_handle)) {
536 LOG(ERROR) << "Endorsement key is not available"; 776 LOG(ERROR) << "Endorsement key is not available";
537 is_being_owned_ = false; 777 is_being_owned_ = false;
778 Disconnect(context_handle);
538 return false; 779 return false;
539 } 780 }
540 781
541 if (!TakeOwnership(context_handle_, kMaxTimeoutRetries, 782 if (!TakeOwnership(context_handle, kMaxTimeoutRetries,
542 default_owner_password)) { 783 default_owner_password)) {
543 LOG(ERROR) << "Take Ownership failed"; 784 LOG(ERROR) << "Take Ownership failed";
544 is_being_owned_ = false; 785 is_being_owned_ = false;
786 Disconnect(context_handle);
545 return false; 787 return false;
546 } 788 }
547 789
548 is_owned_ = true; 790 is_owned_ = true;
549 took_ownership = true; 791 took_ownership = true;
792
793 tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
794 TpmStatus::USES_WELL_KNOWN_OWNER);
795 tpm_status.clear_owner_password();
796 StoreTpmStatus(tpm_status);
550 } 797 }
551 798
552 if (OUT_took_ownership) { 799 if (OUT_took_ownership) {
553 *OUT_took_ownership = took_ownership; 800 *OUT_took_ownership = took_ownership;
554 } 801 }
555 802
556 // Ensure the SRK is available 803 // Ensure the SRK is available
557 TSS_RESULT result; 804 TSS_RESULT result;
558 TSS_HKEY srk_handle; 805 TSS_HKEY srk_handle;
559 TSS_UUID SRK_UUID = TSS_UUID_SRK; 806 TSS_UUID SRK_UUID = TSS_UUID_SRK;
560 if ((result = Tspi_Context_LoadKeyByUUID(context_handle_, TSS_PS_TYPE_SYSTEM, 807 if ((result = Tspi_Context_LoadKeyByUUID(context_handle, TSS_PS_TYPE_SYSTEM,
561 SRK_UUID, &srk_handle))) { 808 SRK_UUID, &srk_handle))) {
562 is_srk_available_ = false; 809 is_srk_available_ = false;
563 } else { 810 } else {
564 Tspi_Context_CloseObject(context_handle_, srk_handle); 811 Tspi_Context_CloseObject(context_handle, srk_handle);
565 is_srk_available_ = true; 812 is_srk_available_ = true;
566 } 813 }
567 814
568 // If we can open the TPM with the default password, then we still need to 815 // If we can open the TPM with the default password, then we still need to
569 // zero the SRK password and unrestrict it, then change the owner password. 816 // zero the SRK password and unrestrict it, then change the owner password.
570 TSS_HTPM tpm_handle; 817 TSS_HTPM tpm_handle;
571 if (!file_util::PathExists(FilePath(kTpmOwnedFile)) && 818 if (!file_util::PathExists(FilePath(kTpmOwnedFile)) &&
572 GetTpmWithAuth(context_handle_, default_owner_password, &tpm_handle) && 819 GetTpmWithAuth(context_handle, default_owner_password, &tpm_handle) &&
573 TestTpmAuth(tpm_handle)) { 820 TestTpmAuth(tpm_handle)) {
574 if (!ZeroSrkPassword(context_handle_, default_owner_password)) { 821 if (!ZeroSrkPassword(context_handle, default_owner_password)) {
575 LOG(ERROR) << "Couldn't zero SRK password"; 822 LOG(ERROR) << "Couldn't zero SRK password";
576 is_being_owned_ = false; 823 is_being_owned_ = false;
824 Disconnect(context_handle);
577 return false; 825 return false;
578 } 826 }
579 827
580 if (!UnrestrictSrk(context_handle_, default_owner_password)) { 828 if (!UnrestrictSrk(context_handle, default_owner_password)) {
581 LOG(ERROR) << "Couldn't unrestrict the SRK"; 829 LOG(ERROR) << "Couldn't unrestrict the SRK";
582 is_being_owned_ = false; 830 is_being_owned_ = false;
831 Disconnect(context_handle);
583 return false; 832 return false;
584 } 833 }
834
585 SecureBlob owner_password; 835 SecureBlob owner_password;
586 CreateOwnerPassword(&owner_password); 836 CreateOwnerPassword(&owner_password);
587 837
588 if (!ChangeOwnerPassword(context_handle_, default_owner_password, 838 tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
589 owner_password)) { 839 TpmStatus::USES_RANDOM_OWNER);
590 LOG(ERROR) << "Couldn't set the owner password"; 840 if (!StoreOwnerPassword(owner_password, &tpm_status)) {
591 is_being_owned_ = false; 841 tpm_status.clear_owner_password();
592 return false; 842 }
843 StoreTpmStatus(tpm_status);
844
845 if ((result = ChangeOwnerPassword(context_handle, default_owner_password,
846 owner_password))) {
847 password_sync_lock_.Acquire();
848 owner_password_.assign(owner_password.begin(), owner_password.end());
849 password_sync_lock_.Release();
593 } 850 }
594 851
595 password_sync_lock_.Acquire();
596 owner_password_.assign(owner_password.begin(), owner_password.end());
597 password_sync_lock_.Release();
598
599 file_util::WriteFile(FilePath(kTpmOwnedFile), NULL, 0); 852 file_util::WriteFile(FilePath(kTpmOwnedFile), NULL, 0);
853 } else {
854 // If we fall through here, then the TPM owned file doesn't exist, but we
855 // couldn't auth with the well-known password. In this case, we must assume
856 // that the TPM has already been owned and set to a random password, so
857 // touch the TPM owned file.
858 if (!file_util::PathExists(FilePath(kTpmOwnedFile))) {
859 file_util::WriteFile(FilePath(kTpmOwnedFile), NULL, 0);
860 }
600 } 861 }
601 862
602 is_being_owned_ = false; 863 is_being_owned_ = false;
603 864 Disconnect(context_handle);
604 return true; 865 return true;
605 } 866 }
606 867
607 bool Tpm::GetRandomData(size_t length, chromeos::Blob* data) { 868 bool Tpm::GetRandomData(size_t length, chromeos::Blob* data) {
608 TSS_HCONTEXT context_handle; 869 TSS_HCONTEXT context_handle;
609 if (!OpenAndConnectTpm(&context_handle)) { 870 if (!OpenAndConnectTpm(&context_handle)) {
610 LOG(ERROR) << "Could not open the TPM"; 871 LOG(ERROR) << "Could not open the TPM";
611 return false; 872 return false;
612 } 873 }
613 874
614 TSS_HTPM tpm_handle; 875 TSS_HTPM tpm_handle;
615 if (!GetTpm(context_handle, &tpm_handle)) { 876 if (!GetTpm(context_handle, &tpm_handle)) {
616 LOG(ERROR) << "Could not get a handle to the TPM."; 877 LOG(ERROR) << "Could not get a handle to the TPM.";
617 Tspi_Context_Close(context_handle); 878 Tspi_Context_Close(context_handle);
618 return false; 879 return false;
619 } 880 }
620 881
621 TSS_RESULT result; 882 TSS_RESULT result;
622 SecureBlob random(length); 883 SecureBlob random(length);
623 BYTE* tpm_data = NULL; 884 BYTE* tpm_data = NULL;
624 if ((result = Tspi_TPM_GetRandom(tpm_handle, random.size(), &tpm_data))) { 885 if ((result = Tspi_TPM_GetRandom(tpm_handle, random.size(), &tpm_data))) {
625 LOG(ERROR) << "Could not get random data from the TPM: " << result; 886 TPM_LOG(ERROR, result) << "Could not get random data from the TPM";
626 Tspi_Context_Close(context_handle); 887 Tspi_Context_Close(context_handle);
627 return false; 888 return false;
628 } 889 }
629 memcpy(random.data(), tpm_data, random.size()); 890 memcpy(random.data(), tpm_data, random.size());
630 Tspi_Context_FreeMemory(context_handle, tpm_data); 891 Tspi_Context_FreeMemory(context_handle, tpm_data);
631 chromeos::SecureMemset(tpm_data, 0, random.size()); 892 chromeos::SecureMemset(tpm_data, 0, random.size());
632 Tspi_Context_Close(context_handle); 893 Tspi_Context_Close(context_handle);
633 data->swap(random); 894 data->swap(random);
634 return true; 895 return true;
635 } 896 }
636 897
898 bool Tpm::LoadSrk(TSS_HCONTEXT context_handle, TSS_HKEY* srk_handle,
899 TSS_RESULT* result) {
900 *result = TSS_SUCCESS;
901
902 // Load the Storage Root Key
903 TSS_UUID SRK_UUID = TSS_UUID_SRK;
904 TSS_HKEY local_srk_handle;
905 if ((*result = Tspi_Context_LoadKeyByUUID(context_handle,
906 TSS_PS_TYPE_SYSTEM,
907 SRK_UUID,
908 &local_srk_handle))) {
909 return false;
910 }
911
912 // Check if the SRK wants a password
913 UINT32 srk_authusage;
914 if ((*result = Tspi_GetAttribUint32(local_srk_handle,
915 TSS_TSPATTRIB_KEY_INFO,
916 TSS_TSPATTRIB_KEYINFO_AUTHUSAGE,
917 &srk_authusage))) {
918 Tspi_Context_CloseObject(context_handle,
919 local_srk_handle);
920 return false;
921 }
922
923 // Give it the password if needed
924 if (srk_authusage) {
925 TSS_HPOLICY srk_usage_policy;
926 if ((*result = Tspi_GetPolicyObject(local_srk_handle,
927 TSS_POLICY_USAGE,
928 &srk_usage_policy))) {
929 Tspi_Context_CloseObject(context_handle, local_srk_handle);
930 return false;
931 }
932
933 BYTE new_password[0];
934 if ((*result = Tspi_Policy_SetSecret(srk_usage_policy,
935 TSS_SECRET_MODE_PLAIN,
936 0, new_password))) {
937 Tspi_Context_CloseObject(context_handle, local_srk_handle);
938 return false;
939 }
940 }
941
942 *srk_handle = local_srk_handle;
943 return true;
944 }
945
946 void Tpm::ClearStoredOwnerPassword() {
947 TpmStatus tpm_status;
948 if (LoadTpmStatus(&tpm_status)) {
949 if (tpm_status.has_owner_password()) {
950 tpm_status.clear_owner_password();
951 StoreTpmStatus(tpm_status);
952 }
953 }
954 password_sync_lock_.Acquire();
955 owner_password_.resize(0);
956 password_sync_lock_.Release();
957 }
958
959 bool Tpm::LoadTpmStatus(TpmStatus* serialized) {
960 FilePath tpm_status_file(kTpmStatusFile);
961 if (!file_util::PathExists(tpm_status_file)) {
962 return false;
963 }
964 SecureBlob file_data;
965 if (!LoadFileBytes(tpm_status_file, &file_data)) {
966 return false;
967 }
968 if (!serialized->ParseFromArray(
969 static_cast<const unsigned char*>(file_data.data()),
970 file_data.size())) {
971 return false;
972 }
973 return true;
974 }
975
976 bool Tpm::StoreTpmStatus(const TpmStatus& serialized) {
977 int old_mask = platform_->SetMask(kDefaultUmask);
978 FilePath tpm_status_file(kTpmStatusFile);
979 if (file_util::PathExists(tpm_status_file)) {
980 do {
981 int64 file_size;
982 if (!file_util::GetFileSize(tpm_status_file, &file_size)) {
983 break;
984 }
985 SecureBlob random;
986 if (!GetRandomData(file_size, &random)) {
987 break;
988 }
989 FILE* file = file_util::OpenFile(tpm_status_file, "wb+");
990 if (!file) {
991 break;
992 }
993 if (fwrite(random.const_data(), 1, random.size(), file) !=
994 random.size()) {
995 file_util::CloseFile(file);
996 break;
997 }
998 file_util::CloseFile(file);
999 } while(false);
1000 file_util::Delete(tpm_status_file, false);
1001 }
1002 SecureBlob final_blob(serialized.ByteSize());
1003 serialized.SerializeWithCachedSizesToArray(
1004 static_cast<google::protobuf::uint8*>(final_blob.data()));
1005 unsigned int data_written = file_util::WriteFile(
1006 tpm_status_file,
1007 static_cast<const char*>(final_blob.const_data()),
1008 final_blob.size());
1009
1010 if (data_written != final_blob.size()) {
1011 platform_->SetMask(old_mask);
1012 return false;
1013 }
1014 platform_->SetMask(old_mask);
1015 return true;
1016 }
1017
637 } // namespace tpm_init 1018 } // namespace tpm_init
OLDNEW
« no previous file with comments | « tpm.h ('k') | tpm_init.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698