| 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 |