OLD | NEW |
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 | 17 |
18 const char* kWellKnownSrkTmp = "1234567890"; | 18 const char* kWellKnownSrkTmp = "1234567890"; |
19 const int kOwnerPasswordLength = 12; | 19 const int kOwnerPasswordLength = 12; |
20 const int kMaxTimeoutRetries = 5; | 20 const int kMaxTimeoutRetries = 5; |
21 const char* kTpmCheckEnabledFile = "/sys/class/misc/tpm0/device/enabled"; | 21 const char* kTpmCheckEnabledFile = "/sys/class/misc/tpm0/device/enabled"; |
22 const char* kTpmCheckOwnedFile = "/sys/class/misc/tpm0/device/owned"; | 22 const char* kTpmCheckOwnedFile = "/sys/class/misc/tpm0/device/owned"; |
23 const char* kTpmOwnedFile = "/var/lib/.tpm_owned"; | 23 const char* kTpmOwnedFile = "/var/lib/.tpm_owned"; |
24 const char* kOpenCryptokiPath = "/var/lib/opencryptoki"; | 24 const char* kOpenCryptokiPath = "/var/lib/opencryptoki"; |
25 const int kTpmConnectRetries = 10; | 25 const int kTpmConnectRetries = 10; |
26 const int kTpmConnectIntervalMs = 100; | 26 const int kTpmConnectIntervalMs = 100; |
| 27 const char kTpmWellKnownPassword[] = TSS_WELL_KNOWN_SECRET; |
27 | 28 |
28 Tpm::Tpm() | 29 Tpm::Tpm() |
29 : context_handle_(0), | 30 : context_handle_(0), |
30 default_crypto_(new Crypto()), | 31 default_crypto_(new Crypto()), |
31 crypto_(default_crypto_.get()), | 32 crypto_(default_crypto_.get()), |
32 owner_password_(), | 33 owner_password_(), |
33 password_sync_lock_(), | 34 password_sync_lock_(), |
34 is_disabled_(true), | 35 is_disabled_(true), |
35 is_owned_(false) { | 36 is_owned_(false), |
| 37 is_srk_available_(false) { |
36 } | 38 } |
37 | 39 |
38 Tpm::~Tpm() { | 40 Tpm::~Tpm() { |
39 Disconnect(); | 41 Disconnect(); |
40 } | 42 } |
41 | 43 |
42 bool Tpm::Init() { | 44 bool Tpm::Init() { |
43 // Checking disabled and owned either via sysfs or via TSS calls will block if | 45 // Checking disabled and owned either via sysfs or via TSS calls will block if |
44 // ownership is being taken by another thread or process. So for this to work | 46 // ownership is being taken by another thread or process. So for this to work |
45 // well, Tpm::Init() needs to be called before InitializeTpm() is called. At | 47 // well, Tpm::Init() needs to be called before InitializeTpm() is called. At |
46 // that point, the public API for Tpm only checks these booleans, so other | 48 // that point, the public API for Tpm only checks these booleans, so other |
47 // threads can check without being blocked. InitializeTpm() will reset the | 49 // threads can check without being blocked. InitializeTpm() will reset the |
48 // is_owned_ bit on success. | 50 // is_owned_ bit on success. |
49 if (file_util::PathExists(FilePath(kTpmCheckEnabledFile))) { | 51 if (file_util::PathExists(FilePath(kTpmCheckEnabledFile))) { |
50 is_disabled_ = IsDisabledCheckViaSysfs(); | 52 is_disabled_ = IsDisabledCheckViaSysfs(); |
51 is_owned_ = IsOwnedCheckViaSysfs(); | 53 is_owned_ = IsOwnedCheckViaSysfs(); |
| 54 } else { |
| 55 TSS_HCONTEXT context_handle; |
| 56 if (OpenAndConnectTpm(&context_handle)) { |
| 57 bool enabled = false; |
| 58 bool owned = false; |
| 59 IsEnabledOwnedCheckViaContext(context_handle, &enabled, &owned); |
| 60 is_disabled_ = !enabled; |
| 61 is_owned_ = owned; |
| 62 Tspi_Context_Close(context_handle); |
| 63 } else { |
| 64 } |
52 } | 65 } |
53 return true; | 66 return true; |
54 } | 67 } |
55 | 68 |
56 bool Tpm::Connect() { | 69 bool Tpm::Connect() { |
57 if (context_handle_ == 0) { | 70 if (context_handle_ == 0) { |
58 TSS_HCONTEXT context_handle; | 71 TSS_HCONTEXT context_handle; |
59 if (!OpenAndConnectTpm(&context_handle)) { | 72 if (!OpenAndConnectTpm(&context_handle)) { |
60 return false; | 73 return false; |
61 } | 74 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 std::string contents; | 170 std::string contents; |
158 if (!file_util::ReadFileToString(FilePath(kTpmCheckOwnedFile), &contents)) { | 171 if (!file_util::ReadFileToString(FilePath(kTpmCheckOwnedFile), &contents)) { |
159 return false; | 172 return false; |
160 } | 173 } |
161 if (contents.size() < 1) { | 174 if (contents.size() < 1) { |
162 return false; | 175 return false; |
163 } | 176 } |
164 return (contents[0] != '0'); | 177 return (contents[0] != '0'); |
165 } | 178 } |
166 | 179 |
167 bool Tpm::IsDisabledCheckViaContext(TSS_HCONTEXT context_handle) { | 180 void Tpm::IsEnabledOwnedCheckViaContext(TSS_HCONTEXT context_handle, |
168 bool value = true; | 181 bool* enabled, bool* owned) { |
| 182 *enabled = false; |
| 183 *owned = false; |
| 184 |
169 TSS_RESULT result; | 185 TSS_RESULT result; |
170 TSS_HTPM tpm_handle; | 186 TSS_HTPM tpm_handle; |
171 if (!GetTpm(context_handle, &tpm_handle)) { | 187 if (!GetTpm(context_handle, &tpm_handle)) { |
172 return value; | 188 return; |
173 } | 189 } |
174 | 190 |
| 191 UINT32 sub_cap = TSS_TPMCAP_PROP_OWNER; |
175 UINT32 cap_length = 0; | 192 UINT32 cap_length = 0; |
176 BYTE* cap = NULL; | 193 BYTE* cap = NULL; |
177 if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_FLAG, | 194 if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_PROPERTY, |
178 0, NULL, &cap_length, &cap))) { | 195 sizeof(sub_cap), |
179 LOG(ERROR) << "Error calling Tspi_TPM_GetCapability: " << result; | 196 reinterpret_cast<BYTE*>(&sub_cap), |
180 return value; | 197 &cap_length, &cap)) == 0) { |
| 198 if (cap_length >= (sizeof(TSS_BOOL))) { |
| 199 *enabled = true; |
| 200 *owned = ((*(reinterpret_cast<TSS_BOOL*>(cap))) != 0); |
| 201 } |
| 202 Tspi_Context_FreeMemory(context_handle, cap); |
| 203 } else if(ERROR_CODE(result) == TPM_E_DISABLED) { |
| 204 *enabled = false; |
181 } | 205 } |
182 if (cap_length >= (2 * sizeof(int))) { | |
183 value = (((*(reinterpret_cast<int*>(cap))) & TPM_PF_DISABLE) != 0); | |
184 } | |
185 Tspi_Context_FreeMemory(context_handle, cap); | |
186 return value; | |
187 } | |
188 | |
189 bool Tpm::IsOwnedCheckViaContext(TSS_HCONTEXT context_handle) { | |
190 bool value = true; | |
191 TSS_RESULT result; | |
192 TSS_HTPM tpm_handle; | |
193 if (!GetTpm(context_handle, &tpm_handle)) { | |
194 LOG(ERROR) << "Error calling Tspi_Context_GetTpmObject: " << result; | |
195 return value; | |
196 } | |
197 | |
198 UINT32 cap_length = 0; | |
199 BYTE* cap = NULL; | |
200 if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_FLAG, | |
201 0, NULL, &cap_length, &cap))) { | |
202 LOG(ERROR) << "Error calling Tspi_TPM_GetCapability: " << result; | |
203 return value; | |
204 } | |
205 if (cap_length >= (2 * sizeof(int))) { | |
206 value = (((*(reinterpret_cast<int*>(cap))) & TPM_PF_OWNERSHIP) != 0); | |
207 } | |
208 Tspi_Context_FreeMemory(context_handle, cap); | |
209 return value; | |
210 } | 206 } |
211 | 207 |
212 bool Tpm::CreateEndorsementKey(TSS_HCONTEXT context_handle) { | 208 bool Tpm::CreateEndorsementKey(TSS_HCONTEXT context_handle) { |
213 TSS_RESULT result; | 209 TSS_RESULT result; |
214 TSS_HTPM tpm_handle; | 210 TSS_HTPM tpm_handle; |
215 if (!GetTpm(context_handle, &tpm_handle)) { | 211 if (!GetTpm(context_handle, &tpm_handle)) { |
216 return false; | 212 return false; |
217 } | 213 } |
218 | 214 |
219 TSS_HKEY local_key_handle; | 215 TSS_HKEY local_key_handle; |
(...skipping 18 matching lines...) Expand all Loading... |
238 bool Tpm::IsEndorsementKeyAvailable(TSS_HCONTEXT context_handle) { | 234 bool Tpm::IsEndorsementKeyAvailable(TSS_HCONTEXT context_handle) { |
239 TSS_RESULT result; | 235 TSS_RESULT result; |
240 TSS_HTPM tpm_handle; | 236 TSS_HTPM tpm_handle; |
241 if (!GetTpm(context_handle, &tpm_handle)) { | 237 if (!GetTpm(context_handle, &tpm_handle)) { |
242 return false; | 238 return false; |
243 } | 239 } |
244 | 240 |
245 TSS_HKEY local_key_handle; | 241 TSS_HKEY local_key_handle; |
246 if ((result = Tspi_TPM_GetPubEndorsementKey(tpm_handle, false, NULL, | 242 if ((result = Tspi_TPM_GetPubEndorsementKey(tpm_handle, false, NULL, |
247 &local_key_handle))) { | 243 &local_key_handle))) { |
248 LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result; | 244 LOG(ERROR) << "Error calling Tspi_TPM_GetPubEndorsementKey: " << result; |
249 return false; | 245 return false; |
250 } | 246 } |
251 | 247 |
252 Tspi_Context_CloseObject(context_handle, local_key_handle); | 248 Tspi_Context_CloseObject(context_handle, local_key_handle); |
253 | 249 |
254 return true; | 250 return true; |
255 } | 251 } |
256 | 252 |
257 void Tpm::CreateOwnerPassword(SecureBlob* password) { | 253 void Tpm::CreateOwnerPassword(SecureBlob* password) { |
258 SecureBlob random(kOwnerPasswordLength); | 254 SecureBlob random(kOwnerPasswordLength); |
259 crypto_->GetSecureRandom(static_cast<unsigned char*>(random.data()), | 255 crypto_->GetSecureRandom(static_cast<unsigned char*>(random.data()), |
260 random.size()); | 256 random.size()); |
261 SecureBlob tpm_password(kOwnerPasswordLength); | 257 SecureBlob tpm_password(kOwnerPasswordLength); |
262 crypto_->AsciiEncodeToBuffer(random, static_cast<char*>(tpm_password.data()), | 258 crypto_->AsciiEncodeToBuffer(random, static_cast<char*>(tpm_password.data()), |
263 tpm_password.size()); | 259 tpm_password.size()); |
264 password->swap(tpm_password); | 260 password->swap(tpm_password); |
265 } | 261 } |
266 | 262 |
267 bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries) { | 263 bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries, |
268 SecureBlob owner_password; | 264 const SecureBlob& owner_password) { |
269 CreateOwnerPassword(&owner_password); | |
270 | |
271 TSS_RESULT result; | 265 TSS_RESULT result; |
272 TSS_HTPM tpm_handle; | 266 TSS_HTPM tpm_handle; |
273 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) { | 267 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) { |
274 return false; | 268 return false; |
275 } | 269 } |
276 | 270 |
277 TSS_HKEY srk_handle; | 271 TSS_HKEY srk_handle; |
278 TSS_FLAG init_flags = TSS_KEY_TSP_SRK | TSS_KEY_AUTHORIZATION; | 272 TSS_FLAG init_flags = TSS_KEY_TSP_SRK | TSS_KEY_AUTHORIZATION; |
279 if ((result = Tspi_Context_CreateObject(context_handle, | 273 if ((result = Tspi_Context_CreateObject(context_handle, |
280 TSS_OBJECT_TYPE_RSAKEY, | 274 TSS_OBJECT_TYPE_RSAKEY, |
(...skipping 30 matching lines...) Expand all Loading... |
311 | 305 |
312 if (result) { | 306 if (result) { |
313 LOG(ERROR) << "Error calling Tspi_TPM_TakeOwnership: " << result | 307 LOG(ERROR) << "Error calling Tspi_TPM_TakeOwnership: " << result |
314 << ", attempts: " << retry_count; | 308 << ", attempts: " << retry_count; |
315 Tspi_Context_CloseObject(context_handle, srk_handle); | 309 Tspi_Context_CloseObject(context_handle, srk_handle); |
316 return false; | 310 return false; |
317 } | 311 } |
318 | 312 |
319 Tspi_Context_CloseObject(context_handle, srk_handle); | 313 Tspi_Context_CloseObject(context_handle, srk_handle); |
320 | 314 |
321 password_sync_lock_.Acquire(); | |
322 owner_password_.swap(owner_password); | |
323 password_sync_lock_.Release(); | |
324 | |
325 return true; | 315 return true; |
326 } | 316 } |
327 | 317 |
328 bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle, | 318 bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle, |
329 const SecureBlob& owner_password) { | 319 const SecureBlob& owner_password) { |
330 TSS_RESULT result; | 320 TSS_RESULT result; |
331 TSS_HTPM tpm_handle; | 321 TSS_HTPM tpm_handle; |
332 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) { | 322 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) { |
333 return false; | 323 return false; |
334 } | 324 } |
335 | 325 |
336 TSS_HKEY srk_handle; | 326 TSS_HKEY srk_handle; |
337 TSS_UUID SRK_UUID = TSS_UUID_SRK; | 327 TSS_UUID SRK_UUID = TSS_UUID_SRK; |
338 if ((result = Tspi_Context_LoadKeyByUUID(context_handle, TSS_PS_TYPE_SYSTEM, | 328 if ((result = Tspi_Context_LoadKeyByUUID(context_handle, TSS_PS_TYPE_SYSTEM, |
339 SRK_UUID, &srk_handle))) { | 329 SRK_UUID, &srk_handle))) { |
340 LOG(ERROR) << "Couldn't load SRK: " << result; | 330 LOG(ERROR) << "Error calling Tspi_Context_LoadKeyByUUID: " << result; |
341 return false; | 331 return false; |
342 } | 332 } |
343 | 333 |
344 TSS_HPOLICY policy_handle; | 334 TSS_HPOLICY policy_handle; |
345 if ((result = Tspi_Context_CreateObject(context_handle, | 335 if ((result = Tspi_Context_CreateObject(context_handle, |
346 TSS_OBJECT_TYPE_POLICY, | 336 TSS_OBJECT_TYPE_POLICY, |
347 TSS_POLICY_USAGE, | 337 TSS_POLICY_USAGE, |
348 &policy_handle))) { | 338 &policy_handle))) { |
349 LOG(ERROR) << "Error creating policy object: " << result; | 339 LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result; |
350 Tspi_Context_CloseObject(context_handle, srk_handle); | 340 Tspi_Context_CloseObject(context_handle, srk_handle); |
351 return false; | 341 return false; |
352 } | 342 } |
353 | 343 |
354 BYTE new_password[0]; | 344 BYTE new_password[0]; |
355 if ((result = Tspi_Policy_SetSecret(policy_handle, TSS_SECRET_MODE_PLAIN, | 345 if ((result = Tspi_Policy_SetSecret(policy_handle, TSS_SECRET_MODE_PLAIN, |
356 0, new_password))) { | 346 0, new_password))) { |
357 LOG(ERROR) << "Error setting srk password: " << result; | 347 LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result; |
358 Tspi_Context_CloseObject(context_handle, policy_handle); | 348 Tspi_Context_CloseObject(context_handle, policy_handle); |
359 Tspi_Context_CloseObject(context_handle, srk_handle); | 349 Tspi_Context_CloseObject(context_handle, srk_handle); |
360 return false; | 350 return false; |
361 } | 351 } |
362 | 352 |
363 if ((result = Tspi_ChangeAuth(srk_handle, | 353 if ((result = Tspi_ChangeAuth(srk_handle, |
364 tpm_handle, | 354 tpm_handle, |
365 policy_handle))) { | 355 policy_handle))) { |
366 LOG(ERROR) << "Error creating policy object: " << result; | 356 LOG(ERROR) << "Error calling Tspi_ChangeAuth: " << result; |
367 Tspi_Context_CloseObject(context_handle, policy_handle); | 357 Tspi_Context_CloseObject(context_handle, policy_handle); |
368 Tspi_Context_CloseObject(context_handle, srk_handle); | 358 Tspi_Context_CloseObject(context_handle, srk_handle); |
369 return false; | 359 return false; |
370 } | 360 } |
371 | 361 |
372 Tspi_Context_CloseObject(context_handle, policy_handle); | 362 Tspi_Context_CloseObject(context_handle, policy_handle); |
373 Tspi_Context_CloseObject(context_handle, srk_handle); | 363 Tspi_Context_CloseObject(context_handle, srk_handle); |
374 return true; | 364 return true; |
375 } | 365 } |
376 | 366 |
377 bool Tpm::UnrestrictSrk(TSS_HCONTEXT context_handle, | 367 bool Tpm::UnrestrictSrk(TSS_HCONTEXT context_handle, |
378 const SecureBlob& owner_password) { | 368 const SecureBlob& owner_password) { |
379 TSS_RESULT result; | 369 TSS_RESULT result; |
380 TSS_HTPM tpm_handle; | 370 TSS_HTPM tpm_handle; |
381 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) { | 371 if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) { |
382 return false; | 372 return false; |
383 } | 373 } |
384 | 374 |
385 if ((result = Tspi_TPM_SetStatus(tpm_handle, | 375 TSS_BOOL current_status = false; |
| 376 |
| 377 if ((result = Tspi_TPM_GetStatus(tpm_handle, |
386 TSS_TPMSTATUS_DISABLEPUBSRKREAD, | 378 TSS_TPMSTATUS_DISABLEPUBSRKREAD, |
387 false))) { | 379 ¤t_status))) { |
388 LOG(ERROR) << "Error calling Tspi_TPM_SetStatus: " << result; | 380 LOG(ERROR) << "Error calling Tspi_TPM_GetStatus: " << result; |
389 return false; | 381 return false; |
390 } | 382 } |
391 | 383 |
| 384 // If it is currently owner auth (true), set it to SRK auth |
| 385 if (current_status) { |
| 386 if ((result = Tspi_TPM_SetStatus(tpm_handle, |
| 387 TSS_TPMSTATUS_DISABLEPUBSRKREAD, |
| 388 false))) { |
| 389 LOG(ERROR) << "Error calling Tspi_TPM_SetStatus: " << result; |
| 390 return false; |
| 391 } |
| 392 } |
| 393 |
| 394 return true; |
| 395 } |
| 396 |
| 397 bool Tpm::ChangeOwnerPassword(TSS_HCONTEXT context_handle, |
| 398 const SecureBlob& previous_owner_password, |
| 399 const SecureBlob& owner_password) { |
| 400 TSS_RESULT result; |
| 401 TSS_HTPM tpm_handle; |
| 402 if (!GetTpmWithAuth(context_handle, previous_owner_password, &tpm_handle)) { |
| 403 return false; |
| 404 } |
| 405 |
| 406 TSS_HPOLICY policy_handle; |
| 407 if ((result = Tspi_Context_CreateObject(context_handle, |
| 408 TSS_OBJECT_TYPE_POLICY, |
| 409 TSS_POLICY_USAGE, |
| 410 &policy_handle))) { |
| 411 LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result; |
| 412 return false; |
| 413 } |
| 414 |
| 415 if ((result = Tspi_Policy_SetSecret(policy_handle, |
| 416 TSS_SECRET_MODE_PLAIN, |
| 417 owner_password.size(), |
| 418 const_cast<BYTE *>(static_cast<const BYTE *>( |
| 419 owner_password.const_data()))))) { |
| 420 LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result; |
| 421 Tspi_Context_CloseObject(context_handle, policy_handle); |
| 422 return false; |
| 423 } |
| 424 |
| 425 if ((result = Tspi_ChangeAuth(tpm_handle, 0, policy_handle))) { |
| 426 LOG(ERROR) << "Error calling Tspi_ChangeAuth: " << result; |
| 427 Tspi_Context_CloseObject(context_handle, policy_handle); |
| 428 return false; |
| 429 } |
| 430 |
392 return true; | 431 return true; |
393 } | 432 } |
394 | 433 |
395 bool Tpm::GetTpm(TSS_HCONTEXT context_handle, TSS_HTPM* tpm_handle) { | 434 bool Tpm::GetTpm(TSS_HCONTEXT context_handle, TSS_HTPM* tpm_handle) { |
396 TSS_RESULT result; | 435 TSS_RESULT result; |
397 TSS_HTPM local_tpm_handle; | 436 TSS_HTPM local_tpm_handle; |
398 if ((result = Tspi_Context_GetTpmObject(context_handle, &local_tpm_handle))) { | 437 if ((result = Tspi_Context_GetTpmObject(context_handle, &local_tpm_handle))) { |
399 LOG(ERROR) << "Error calling Tspi_Context_GetTpmObject: " << result; | 438 LOG(ERROR) << "Error calling Tspi_Context_GetTpmObject: " << result; |
400 return false; | 439 return false; |
401 } | 440 } |
402 | 441 |
403 *tpm_handle = local_tpm_handle; | 442 *tpm_handle = local_tpm_handle; |
404 return true; | 443 return true; |
405 } | 444 } |
406 | 445 |
407 bool Tpm::GetTpmWithAuth(TSS_HCONTEXT context_handle, | 446 bool Tpm::GetTpmWithAuth(TSS_HCONTEXT context_handle, |
408 const SecureBlob& owner_password, | 447 const SecureBlob& owner_password, |
409 TSS_HTPM* tpm_handle) { | 448 TSS_HTPM* tpm_handle) { |
410 TSS_RESULT result; | 449 TSS_RESULT result; |
411 TSS_HTPM local_tpm_handle; | 450 TSS_HTPM local_tpm_handle; |
412 if (!GetTpm(context_handle, &local_tpm_handle)) { | 451 if (!GetTpm(context_handle, &local_tpm_handle)) { |
413 LOG(ERROR) << "Error getting TPM handle"; | |
414 return false; | 452 return false; |
415 } | 453 } |
416 | 454 |
417 TSS_HPOLICY tpm_usage_policy; | 455 TSS_HPOLICY tpm_usage_policy; |
418 if ((result = Tspi_GetPolicyObject(local_tpm_handle, TSS_POLICY_USAGE, | 456 if ((result = Tspi_GetPolicyObject(local_tpm_handle, TSS_POLICY_USAGE, |
419 &tpm_usage_policy))) { | 457 &tpm_usage_policy))) { |
420 LOG(ERROR) << "Error calling Tspi_GetPolicyObject: " << result; | 458 LOG(ERROR) << "Error calling Tspi_GetPolicyObject: " << result; |
421 return false; | 459 return false; |
422 } | 460 } |
423 | 461 |
424 if ((result = Tspi_Policy_SetSecret(tpm_usage_policy, TSS_SECRET_MODE_PLAIN, | 462 if ((result = Tspi_Policy_SetSecret(tpm_usage_policy, TSS_SECRET_MODE_PLAIN, |
425 owner_password.size(), | 463 owner_password.size(), |
426 const_cast<BYTE *>(static_cast<const BYTE *>( | 464 const_cast<BYTE *>(static_cast<const BYTE *>( |
427 owner_password.const_data()))))) { | 465 owner_password.const_data()))))) { |
428 LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result; | 466 LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result; |
429 return false; | 467 return false; |
430 } | 468 } |
431 | 469 |
432 *tpm_handle = local_tpm_handle; | 470 *tpm_handle = local_tpm_handle; |
433 return true; | 471 return true; |
434 } | 472 } |
435 | 473 |
| 474 bool Tpm::TestTpmAuth(TSS_HTPM tpm_handle) { |
| 475 // Call Tspi_TPM_GetStatus to test the authentication |
| 476 TSS_RESULT result; |
| 477 TSS_BOOL current_status = false; |
| 478 if ((result = Tspi_TPM_GetStatus(tpm_handle, |
| 479 TSS_TPMSTATUS_DISABLED, |
| 480 ¤t_status))) { |
| 481 return false; |
| 482 } |
| 483 return true; |
| 484 } |
| 485 |
436 bool Tpm::GetOwnerPassword(chromeos::Blob* owner_password) { | 486 bool Tpm::GetOwnerPassword(chromeos::Blob* owner_password) { |
437 bool result = false; | 487 bool result = false; |
438 if (password_sync_lock_.Try()) { | 488 if (password_sync_lock_.Try()) { |
439 if (owner_password_.size() != 0) { | 489 if (owner_password_.size() != 0) { |
440 owner_password->assign(owner_password_.begin(), owner_password_.end()); | 490 owner_password->assign(owner_password_.begin(), owner_password_.end()); |
441 result = true; | 491 result = true; |
442 } | 492 } |
443 password_sync_lock_.Release(); | 493 password_sync_lock_.Release(); |
444 } | 494 } |
445 return result; | 495 return result; |
446 } | 496 } |
447 | 497 |
448 bool Tpm::InitializeTpm() { | 498 bool Tpm::InitializeTpm() { |
449 if (!IsConnected()) { | 499 if (!IsConnected()) { |
450 Connect(); | 500 Connect(); |
451 } | 501 } |
452 | 502 |
453 if (!IsConnected()) { | 503 if (!IsConnected()) { |
454 LOG(ERROR) << "Failed to connect to TPM"; | 504 LOG(ERROR) << "Failed to connect to TPM"; |
455 return false; | 505 return false; |
456 } | 506 } |
457 | 507 |
458 if (is_disabled_) { | 508 if (is_disabled_) { |
459 return false; | 509 return false; |
460 } | 510 } |
461 | 511 |
462 if (is_owned_) { | 512 SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword)); |
463 return false; | 513 memcpy(default_owner_password.data(), kTpmWellKnownPassword, |
| 514 sizeof(kTpmWellKnownPassword)); |
| 515 |
| 516 bool took_ownership = false; |
| 517 if (!is_owned_) { |
| 518 file_util::Delete(FilePath(kOpenCryptokiPath), true); |
| 519 file_util::Delete(FilePath(kTpmOwnedFile), false); |
| 520 |
| 521 if (!IsEndorsementKeyAvailable(context_handle_)) { |
| 522 if (!CreateEndorsementKey(context_handle_)) { |
| 523 LOG(ERROR) << "Failed to create endorsement key"; |
| 524 return false; |
| 525 } |
| 526 } |
| 527 |
| 528 if (!IsEndorsementKeyAvailable(context_handle_)) { |
| 529 LOG(ERROR) << "Endorsement key is not available"; |
| 530 return false; |
| 531 } |
| 532 |
| 533 if (!TakeOwnership(context_handle_, kMaxTimeoutRetries, |
| 534 default_owner_password)) { |
| 535 LOG(ERROR) << "Take Ownership failed"; |
| 536 return false; |
| 537 } |
| 538 |
| 539 is_owned_ = true; |
| 540 took_ownership = true; |
464 } | 541 } |
465 | 542 |
466 file_util::Delete(FilePath(kOpenCryptokiPath), true); | 543 // Ensure the SRK is available |
467 file_util::Delete(FilePath(kTpmOwnedFile), false); | 544 TSS_HKEY srk_handle; |
| 545 TSS_UUID SRK_UUID = TSS_UUID_SRK; |
| 546 if ((result = Tspi_Context_LoadKeyByUUID(context_handle, TSS_PS_TYPE_SYSTEM, |
| 547 SRK_UUID, &srk_handle))) { |
| 548 is_srk_available_ = false; |
| 549 } else { |
| 550 Tspi_Context_CloseObject(context_handle, srk_handle); |
| 551 is_srk_available_ = true; |
| 552 } |
468 | 553 |
469 if (!IsEndorsementKeyAvailable(context_handle_)) { | 554 // If we can open the TPM with the default password, then we still need to |
470 if (!CreateEndorsementKey(context_handle_)) { | 555 // zero the SRK password and unrestrict it, then change the owner password. |
471 LOG(ERROR) << "Failed to create endorsement key"; | 556 TSS_HTPM tpm_handle; |
| 557 if (GetTpmWithAuth(context_handle_, default_owner_password, &tpm_handle) && |
| 558 TestTpmAuth(tpm_handle)) { |
| 559 if (!ZeroSrkPassword(context_handle_, default_owner_password)) { |
| 560 LOG(ERROR) << "Couldn't zero SRK password"; |
472 return false; | 561 return false; |
473 } | 562 } |
| 563 |
| 564 if (!UnrestrictSrk(context_handle_, default_owner_password)) { |
| 565 LOG(ERROR) << "Couldn't unrestrict the SRK"; |
| 566 return false; |
| 567 } |
| 568 SecureBlob owner_password; |
| 569 CreateOwnerPassword(&owner_password); |
| 570 |
| 571 if (!ChangeOwnerPassword(context_handle_, default_owner_password, |
| 572 owner_password)) { |
| 573 LOG(ERROR) << "Couldn't set the owner password"; |
| 574 return false; |
| 575 } |
| 576 |
| 577 password_sync_lock_.Acquire(); |
| 578 owner_password_.assign(owner_password.begin(), owner_password.end()); |
| 579 password_sync_lock_.Release(); |
| 580 |
| 581 file_util::WriteFile(FilePath(kTpmOwnedFile), NULL, 0); |
474 } | 582 } |
475 | 583 |
476 if (!IsEndorsementKeyAvailable(context_handle_)) { | 584 return took_ownership; |
477 LOG(ERROR) << "Endorsement key is not available"; | |
478 return false; | |
479 } | |
480 | |
481 if (!TakeOwnership(context_handle_, kMaxTimeoutRetries)) { | |
482 LOG(ERROR) << "Take Ownership failed"; | |
483 return false; | |
484 } | |
485 | |
486 SecureBlob owner_password; | |
487 password_sync_lock_.Acquire(); | |
488 owner_password.assign(owner_password_.begin(), owner_password_.end()); | |
489 password_sync_lock_.Release(); | |
490 | |
491 if (!ZeroSrkPassword(context_handle_, owner_password)) { | |
492 LOG(ERROR) << "Couldn't zero SRK password"; | |
493 return false; | |
494 } | |
495 | |
496 if (!UnrestrictSrk(context_handle_, owner_password)) { | |
497 LOG(ERROR) << "Couldn't unrestrict the SRK"; | |
498 return false; | |
499 } | |
500 | |
501 is_owned_ = true; | |
502 | |
503 file_util::WriteFile(FilePath(kTpmOwnedFile), NULL, 0); | |
504 | |
505 return true; | |
506 } | 585 } |
507 | 586 |
508 } // namespace tpm_init | 587 } // namespace tpm_init |
OLD | NEW |