1 // 2 // Copyright (C) 2015 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "attestation/common/tpm_utility_v1.h" 18 19 #include <base/files/file_path.h> 20 #include <base/files/file_util.h> 21 #include <base/logging.h> 22 #include <base/memory/scoped_ptr.h> 23 #include <base/stl_util.h> 24 #include <crypto/scoped_openssl_types.h> 25 #include <crypto/sha2.h> 26 #include <openssl/rsa.h> 27 #include <openssl/sha.h> 28 #include <trousers/scoped_tss_type.h> 29 #include <trousers/trousers.h> 30 #include <trousers/tss.h> 31 32 #define TPM_LOG(severity, result) \ 33 LOG(severity) << "TPM error 0x" << std::hex << result << " (" \ 34 << Trspi_Error_String(result) << "): " 35 36 using trousers::ScopedTssContext; 37 using trousers::ScopedTssKey; 38 using trousers::ScopedTssMemory; 39 using trousers::ScopedTssPcrs; 40 41 namespace { 42 43 using ScopedByteArray = scoped_ptr<BYTE, base::FreeDeleter>; 44 using ScopedTssEncryptedData = trousers::ScopedTssObject<TSS_HENCDATA>; 45 using ScopedTssHash = trousers::ScopedTssObject<TSS_HHASH>; 46 47 const char* kTpmTpmEnabledFile = "/sys/class/tpm/tpm0/device/enabled"; 48 const char* kMscTpmEnabledFile = "/sys/class/misc/tpm0/device/enabled"; 49 const char* kTpmTpmOwnedFile = "/sys/class/tpm/tpm0/device/owned"; 50 const char* kMscTpmOwnedFile = "/sys/class/misc/tpm0/device/owned"; 51 const unsigned int kWellKnownExponent = 65537; 52 const unsigned char kSha256DigestInfo[] = { 53 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 54 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; 55 56 std::string GetFirstByte(const char* file_name) { 57 std::string content; 58 base::ReadFileToString(base::FilePath(file_name), &content); 59 if (content.size() > 1) { 60 content.resize(1); 61 } 62 return content; 63 } 64 65 BYTE* StringAsTSSBuffer(std::string* s) { 66 return reinterpret_cast<BYTE*>(string_as_array(s)); 67 } 68 69 std::string TSSBufferAsString(const BYTE* buffer, size_t length) { 70 return std::string(reinterpret_cast<const char*>(buffer), length); 71 } 72 73 } // namespace 74 75 namespace attestation { 76 77 TpmUtilityV1::~TpmUtilityV1() {} 78 79 bool TpmUtilityV1::Initialize() { 80 if (!ConnectContext(&context_handle_, &tpm_handle_)) { 81 LOG(ERROR) << __func__ << ": Failed to connect to the TPM."; 82 return false; 83 } 84 if (!IsTpmReady()) { 85 LOG(WARNING) << __func__ << ": TPM is not owned; attestation services will " 86 << "not be available until ownership is taken."; 87 } 88 return true; 89 } 90 91 bool TpmUtilityV1::IsTpmReady() { 92 if (!is_ready_) { 93 if (base::PathExists(base::FilePath(kMscTpmEnabledFile))) { 94 is_ready_ = (GetFirstByte(kMscTpmEnabledFile) == "1" && 95 GetFirstByte(kMscTpmOwnedFile) == "1"); 96 } else { 97 is_ready_ = (GetFirstByte(kTpmTpmEnabledFile) == "1" && 98 GetFirstByte(kTpmTpmOwnedFile) == "1"); 99 } 100 } 101 return is_ready_; 102 } 103 104 bool TpmUtilityV1::ActivateIdentity(const std::string& delegate_blob, 105 const std::string& delegate_secret, 106 const std::string& identity_key_blob, 107 const std::string& asym_ca_contents, 108 const std::string& sym_ca_attestation, 109 std::string* credential) { 110 CHECK(credential); 111 if (!SetupSrk()) { 112 LOG(ERROR) << "SRK is not ready."; 113 return false; 114 } 115 116 // Connect to the TPM as the owner delegate. 117 ScopedTssContext context_handle; 118 TSS_HTPM tpm_handle; 119 if (!ConnectContextAsDelegate(delegate_blob, delegate_secret, &context_handle, 120 &tpm_handle)) { 121 LOG(ERROR) << __func__ << ": Could not connect to the TPM."; 122 return false; 123 } 124 // Load the Storage Root Key. 125 TSS_RESULT result; 126 ScopedTssKey srk_handle(context_handle); 127 if (!LoadSrk(context_handle, &srk_handle)) { 128 LOG(ERROR) << __func__ << ": Failed to load SRK."; 129 return false; 130 } 131 // Load the AIK (which is wrapped by the SRK). 132 std::string mutable_identity_key_blob(identity_key_blob); 133 BYTE* identity_key_blob_buffer = 134 StringAsTSSBuffer(&mutable_identity_key_blob); 135 ScopedTssKey identity_key(context_handle); 136 result = Tspi_Context_LoadKeyByBlob( 137 context_handle, srk_handle, identity_key_blob.size(), 138 identity_key_blob_buffer, identity_key.ptr()); 139 if (TPM_ERROR(result)) { 140 TPM_LOG(ERROR, result) << __func__ << ": Failed to load AIK."; 141 return false; 142 } 143 std::string mutable_asym_ca_contents(asym_ca_contents); 144 BYTE* asym_ca_contents_buffer = StringAsTSSBuffer(&mutable_asym_ca_contents); 145 std::string mutable_sym_ca_attestation(sym_ca_attestation); 146 BYTE* sym_ca_attestation_buffer = 147 StringAsTSSBuffer(&mutable_sym_ca_attestation); 148 UINT32 credential_length = 0; 149 ScopedTssMemory credential_buffer(context_handle); 150 result = Tspi_TPM_ActivateIdentity( 151 tpm_handle, identity_key, asym_ca_contents.size(), 152 asym_ca_contents_buffer, sym_ca_attestation.size(), 153 sym_ca_attestation_buffer, &credential_length, credential_buffer.ptr()); 154 if (TPM_ERROR(result)) { 155 TPM_LOG(ERROR, result) << __func__ << ": Failed to activate identity."; 156 return false; 157 } 158 credential->assign( 159 TSSBufferAsString(credential_buffer.value(), credential_length)); 160 return true; 161 } 162 163 bool TpmUtilityV1::CreateCertifiedKey(KeyType key_type, 164 KeyUsage key_usage, 165 const std::string& identity_key_blob, 166 const std::string& external_data, 167 std::string* key_blob, 168 std::string* public_key, 169 std::string* public_key_tpm_format, 170 std::string* key_info, 171 std::string* proof) { 172 CHECK(key_blob && public_key && public_key_tpm_format && key_info && proof); 173 if (!SetupSrk()) { 174 LOG(ERROR) << "SRK is not ready."; 175 return false; 176 } 177 if (key_type != KEY_TYPE_RSA) { 178 LOG(ERROR) << "Only RSA supported on TPM v1.2."; 179 return false; 180 } 181 182 // Load the AIK (which is wrapped by the SRK). 183 ScopedTssKey identity_key(context_handle_); 184 if (!LoadKeyFromBlob(identity_key_blob, context_handle_, srk_handle_, 185 &identity_key)) { 186 LOG(ERROR) << __func__ << "Failed to load AIK."; 187 return false; 188 } 189 190 // Create a non-migratable RSA key. 191 ScopedTssKey key(context_handle_); 192 UINT32 tss_key_type = 193 (key_usage == KEY_USAGE_SIGN) ? TSS_KEY_TYPE_SIGNING : TSS_KEY_TYPE_BIND; 194 UINT32 init_flags = tss_key_type | TSS_KEY_NOT_MIGRATABLE | TSS_KEY_VOLATILE | 195 TSS_KEY_NO_AUTHORIZATION | TSS_KEY_SIZE_2048; 196 TSS_RESULT result = Tspi_Context_CreateObject( 197 context_handle_, TSS_OBJECT_TYPE_RSAKEY, init_flags, key.ptr()); 198 if (TPM_ERROR(result)) { 199 TPM_LOG(ERROR, result) << __func__ << ": Failed to create object."; 200 return false; 201 } 202 if (key_usage == KEY_USAGE_SIGN) { 203 result = Tspi_SetAttribUint32(key, TSS_TSPATTRIB_KEY_INFO, 204 TSS_TSPATTRIB_KEYINFO_SIGSCHEME, 205 TSS_SS_RSASSAPKCS1V15_DER); 206 } else { 207 result = Tspi_SetAttribUint32(key, TSS_TSPATTRIB_KEY_INFO, 208 TSS_TSPATTRIB_KEYINFO_ENCSCHEME, 209 TSS_ES_RSAESOAEP_SHA1_MGF1); 210 } 211 if (TPM_ERROR(result)) { 212 TPM_LOG(ERROR, result) << __func__ << ": Failed to set scheme."; 213 return false; 214 } 215 result = Tspi_Key_CreateKey(key, srk_handle_, 0); 216 if (TPM_ERROR(result)) { 217 TPM_LOG(ERROR, result) << __func__ << ": Failed to create key."; 218 return false; 219 } 220 result = Tspi_Key_LoadKey(key, srk_handle_); 221 if (TPM_ERROR(result)) { 222 TPM_LOG(ERROR, result) << __func__ << ": Failed to load key."; 223 return false; 224 } 225 226 // Certify the key. 227 TSS_VALIDATION validation; 228 memset(&validation, 0, sizeof(validation)); 229 validation.ulExternalDataLength = external_data.size(); 230 std::string mutable_external_data(external_data); 231 validation.rgbExternalData = StringAsTSSBuffer(&mutable_external_data); 232 result = Tspi_Key_CertifyKey(key, identity_key, &validation); 233 if (TPM_ERROR(result)) { 234 TPM_LOG(ERROR, result) << __func__ << ": Failed to certify key."; 235 return false; 236 } 237 ScopedTssMemory scoped_certified_data(0, validation.rgbData); 238 ScopedTssMemory scoped_proof(0, validation.rgbValidationData); 239 240 // Get the certified public key. 241 if (!GetDataAttribute(context_handle_, key, TSS_TSPATTRIB_KEY_BLOB, 242 TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, 243 public_key_tpm_format)) { 244 LOG(ERROR) << __func__ << ": Failed to read public key."; 245 return false; 246 } 247 if (!ConvertPublicKeyToDER(*public_key_tpm_format, public_key)) { 248 return false; 249 } 250 251 // Get the certified key blob so we can load it later. 252 if (!GetDataAttribute(context_handle_, key, TSS_TSPATTRIB_KEY_BLOB, 253 TSS_TSPATTRIB_KEYBLOB_BLOB, key_blob)) { 254 LOG(ERROR) << __func__ << ": Failed to read key blob."; 255 return false; 256 } 257 258 // Get the data that was certified. 259 key_info->assign( 260 TSSBufferAsString(validation.rgbData, validation.ulDataLength)); 261 262 // Get the certification proof. 263 proof->assign(TSSBufferAsString(validation.rgbValidationData, 264 validation.ulValidationDataLength)); 265 return true; 266 } 267 268 bool TpmUtilityV1::SealToPCR0(const std::string& data, 269 std::string* sealed_data) { 270 CHECK(sealed_data); 271 if (!SetupSrk()) { 272 LOG(ERROR) << "SRK is not ready."; 273 return false; 274 } 275 276 // Create a PCRS object which holds the value of PCR0. 277 ScopedTssPcrs pcrs_handle(context_handle_); 278 TSS_RESULT result; 279 if (TPM_ERROR(result = Tspi_Context_CreateObject( 280 context_handle_, TSS_OBJECT_TYPE_PCRS, TSS_PCRS_STRUCT_INFO, 281 pcrs_handle.ptr()))) { 282 TPM_LOG(ERROR, result) << __func__ 283 << ": Error calling Tspi_Context_CreateObject"; 284 return false; 285 } 286 UINT32 pcr_length = 0; 287 ScopedTssMemory pcr_value(context_handle_); 288 Tspi_TPM_PcrRead(tpm_handle_, 0, &pcr_length, pcr_value.ptr()); 289 Tspi_PcrComposite_SetPcrValue(pcrs_handle, 0, pcr_length, pcr_value.value()); 290 291 // Create a ENCDATA object to receive the sealed data. 292 ScopedTssKey encrypted_data_handle(context_handle_); 293 if (TPM_ERROR(result = Tspi_Context_CreateObject( 294 context_handle_, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_SEAL, 295 encrypted_data_handle.ptr()))) { 296 TPM_LOG(ERROR, result) << __func__ 297 << ": Error calling Tspi_Context_CreateObject"; 298 return false; 299 } 300 301 // Seal the given value with the SRK. 302 std::string mutable_data(data); 303 BYTE* data_buffer = StringAsTSSBuffer(&mutable_data); 304 if (TPM_ERROR(result = 305 Tspi_Data_Seal(encrypted_data_handle, srk_handle_, 306 data.size(), data_buffer, pcrs_handle))) { 307 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Data_Seal"; 308 return false; 309 } 310 311 // Extract the sealed value. 312 ScopedTssMemory encrypted_data(context_handle_); 313 UINT32 encrypted_data_length = 0; 314 if (TPM_ERROR(result = Tspi_GetAttribData( 315 encrypted_data_handle, TSS_TSPATTRIB_ENCDATA_BLOB, 316 TSS_TSPATTRIB_ENCDATABLOB_BLOB, &encrypted_data_length, 317 encrypted_data.ptr()))) { 318 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_GetAttribData"; 319 return false; 320 } 321 sealed_data->assign( 322 TSSBufferAsString(encrypted_data.value(), encrypted_data_length)); 323 return true; 324 } 325 326 bool TpmUtilityV1::Unseal(const std::string& sealed_data, std::string* data) { 327 CHECK(data); 328 if (!SetupSrk()) { 329 LOG(ERROR) << "SRK is not ready."; 330 return false; 331 } 332 333 // Create an ENCDATA object with the sealed value. 334 ScopedTssKey encrypted_data_handle(context_handle_); 335 TSS_RESULT result; 336 if (TPM_ERROR(result = Tspi_Context_CreateObject( 337 context_handle_, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_SEAL, 338 encrypted_data_handle.ptr()))) { 339 TPM_LOG(ERROR, result) << __func__ 340 << ": Error calling Tspi_Context_CreateObject"; 341 return false; 342 } 343 344 std::string mutable_sealed_data(sealed_data); 345 BYTE* sealed_data_buffer = StringAsTSSBuffer(&mutable_sealed_data); 346 if (TPM_ERROR(result = Tspi_SetAttribData( 347 encrypted_data_handle, TSS_TSPATTRIB_ENCDATA_BLOB, 348 TSS_TSPATTRIB_ENCDATABLOB_BLOB, sealed_data.size(), 349 sealed_data_buffer))) { 350 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_SetAttribData"; 351 return false; 352 } 353 354 // Unseal using the SRK. 355 ScopedTssMemory decrypted_data(context_handle_); 356 UINT32 decrypted_data_length = 0; 357 if (TPM_ERROR(result = Tspi_Data_Unseal(encrypted_data_handle, srk_handle_, 358 &decrypted_data_length, 359 decrypted_data.ptr()))) { 360 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Data_Unseal"; 361 return false; 362 } 363 data->assign( 364 TSSBufferAsString(decrypted_data.value(), decrypted_data_length)); 365 return true; 366 } 367 368 bool TpmUtilityV1::GetEndorsementPublicKey(std::string* public_key) { 369 // Get a handle to the EK public key. 370 ScopedTssKey ek_public_key_object(context_handle_); 371 TSS_RESULT result = Tspi_TPM_GetPubEndorsementKey(tpm_handle_, false, nullptr, 372 ek_public_key_object.ptr()); 373 if (TPM_ERROR(result)) { 374 TPM_LOG(ERROR, result) << __func__ << ": Failed to get key."; 375 return false; 376 } 377 // Get the public key in TPM_PUBKEY form. 378 std::string ek_public_key_blob; 379 if (!GetDataAttribute( 380 context_handle_, ek_public_key_object, TSS_TSPATTRIB_KEY_BLOB, 381 TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &ek_public_key_blob)) { 382 LOG(ERROR) << __func__ << ": Failed to read public key."; 383 return false; 384 } 385 // Get the public key in DER encoded form. 386 if (!ConvertPublicKeyToDER(ek_public_key_blob, public_key)) { 387 return false; 388 } 389 return true; 390 } 391 392 bool TpmUtilityV1::Unbind(const std::string& key_blob, 393 const std::string& bound_data, 394 std::string* data) { 395 CHECK(data); 396 if (!SetupSrk()) { 397 LOG(ERROR) << "SRK is not ready."; 398 return false; 399 } 400 ScopedTssKey key_handle(context_handle_); 401 if (!LoadKeyFromBlob(key_blob, context_handle_, srk_handle_, &key_handle)) { 402 return false; 403 } 404 TSS_RESULT result; 405 ScopedTssEncryptedData data_handle(context_handle_); 406 if (TPM_ERROR(result = Tspi_Context_CreateObject( 407 context_handle_, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, 408 data_handle.ptr()))) { 409 TPM_LOG(ERROR, result) << __func__ << ": Tspi_Context_CreateObject failed."; 410 return false; 411 } 412 std::string mutable_bound_data(bound_data); 413 if (TPM_ERROR(result = Tspi_SetAttribData( 414 data_handle, TSS_TSPATTRIB_ENCDATA_BLOB, 415 TSS_TSPATTRIB_ENCDATABLOB_BLOB, bound_data.size(), 416 StringAsTSSBuffer(&mutable_bound_data)))) { 417 TPM_LOG(ERROR, result) << __func__ << ": Tspi_SetAttribData failed."; 418 return false; 419 } 420 421 ScopedTssMemory decrypted_data(context_handle_); 422 UINT32 length = 0; 423 if (TPM_ERROR(result = Tspi_Data_Unbind(data_handle, key_handle, &length, 424 decrypted_data.ptr()))) { 425 TPM_LOG(ERROR, result) << __func__ << ": Tspi_Data_Unbind failed."; 426 return false; 427 } 428 data->assign(TSSBufferAsString(decrypted_data.value(), length)); 429 return true; 430 } 431 432 bool TpmUtilityV1::Sign(const std::string& key_blob, 433 const std::string& data_to_sign, 434 std::string* signature) { 435 CHECK(signature); 436 if (!SetupSrk()) { 437 LOG(ERROR) << "SRK is not ready."; 438 return false; 439 } 440 ScopedTssKey key_handle(context_handle_); 441 if (!LoadKeyFromBlob(key_blob, context_handle_, srk_handle_, &key_handle)) { 442 return false; 443 } 444 // Construct an ASN.1 DER DigestInfo. 445 std::string digest_to_sign(std::begin(kSha256DigestInfo), 446 std::end(kSha256DigestInfo)); 447 digest_to_sign += crypto::SHA256HashString(data_to_sign); 448 // Create a hash object to hold the digest. 449 ScopedTssHash hash_handle(context_handle_); 450 TSS_RESULT result = Tspi_Context_CreateObject( 451 context_handle_, TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, hash_handle.ptr()); 452 if (TPM_ERROR(result)) { 453 TPM_LOG(ERROR, result) << __func__ << ": Failed to create hash object."; 454 return false; 455 } 456 result = Tspi_Hash_SetHashValue(hash_handle, digest_to_sign.size(), 457 StringAsTSSBuffer(&digest_to_sign)); 458 if (TPM_ERROR(result)) { 459 TPM_LOG(ERROR, result) << __func__ << ": Failed to set hash data."; 460 return false; 461 } 462 UINT32 length = 0; 463 ScopedTssMemory buffer(context_handle_); 464 result = Tspi_Hash_Sign(hash_handle, key_handle, &length, buffer.ptr()); 465 if (TPM_ERROR(result)) { 466 TPM_LOG(ERROR, result) << __func__ << ": Failed to generate signature."; 467 return false; 468 } 469 signature->assign(TSSBufferAsString(buffer.value(), length)); 470 return true; 471 } 472 473 bool TpmUtilityV1::ConnectContext(ScopedTssContext* context, TSS_HTPM* tpm) { 474 *tpm = 0; 475 TSS_RESULT result; 476 if (TPM_ERROR(result = Tspi_Context_Create(context->ptr()))) { 477 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Context_Create"; 478 return false; 479 } 480 if (TPM_ERROR(result = Tspi_Context_Connect(*context, nullptr))) { 481 TPM_LOG(ERROR, result) << __func__ 482 << ": Error calling Tspi_Context_Connect"; 483 return false; 484 } 485 if (TPM_ERROR(result = Tspi_Context_GetTpmObject(*context, tpm))) { 486 TPM_LOG(ERROR, result) << __func__ 487 << ": Error calling Tspi_Context_GetTpmObject"; 488 return false; 489 } 490 return true; 491 } 492 493 bool TpmUtilityV1::ConnectContextAsDelegate(const std::string& delegate_blob, 494 const std::string& delegate_secret, 495 ScopedTssContext* context, 496 TSS_HTPM* tpm) { 497 *tpm = 0; 498 if (!ConnectContext(context, tpm)) { 499 return false; 500 } 501 TSS_RESULT result; 502 TSS_HPOLICY tpm_usage_policy; 503 if (TPM_ERROR(result = Tspi_GetPolicyObject(*tpm, TSS_POLICY_USAGE, 504 &tpm_usage_policy))) { 505 TPM_LOG(ERROR, result) << __func__ 506 << ": Error calling Tspi_GetPolicyObject"; 507 return false; 508 } 509 std::string mutable_delegate_secret(delegate_secret); 510 BYTE* secret_buffer = StringAsTSSBuffer(&mutable_delegate_secret); 511 if (TPM_ERROR(result = Tspi_Policy_SetSecret( 512 tpm_usage_policy, TSS_SECRET_MODE_PLAIN, 513 delegate_secret.size(), secret_buffer))) { 514 TPM_LOG(ERROR, result) << __func__ 515 << ": Error calling Tspi_Policy_SetSecret"; 516 return false; 517 } 518 std::string mutable_delegate_blob(delegate_blob); 519 BYTE* blob_buffer = StringAsTSSBuffer(&mutable_delegate_blob); 520 if (TPM_ERROR(result = Tspi_SetAttribData( 521 tpm_usage_policy, TSS_TSPATTRIB_POLICY_DELEGATION_INFO, 522 TSS_TSPATTRIB_POLDEL_OWNERBLOB, delegate_blob.size(), 523 blob_buffer))) { 524 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_SetAttribData"; 525 return false; 526 } 527 return true; 528 } 529 530 bool TpmUtilityV1::SetupSrk() { 531 if (!IsTpmReady()) { 532 return false; 533 } 534 if (srk_handle_) { 535 return true; 536 } 537 srk_handle_.reset(context_handle_, 0); 538 if (!LoadSrk(context_handle_, &srk_handle_)) { 539 LOG(ERROR) << __func__ << ": Failed to load SRK."; 540 return false; 541 } 542 // In order to wrap a key with the SRK we need access to the SRK public key 543 // and we need to get it manually. Once it's in the key object, we don't need 544 // to do this again. 545 UINT32 length = 0; 546 ScopedTssMemory buffer(context_handle_); 547 TSS_RESULT result; 548 result = Tspi_Key_GetPubKey(srk_handle_, &length, buffer.ptr()); 549 if (result != TSS_SUCCESS) { 550 TPM_LOG(INFO, result) << __func__ << ": Failed to read SRK public key."; 551 return false; 552 } 553 return true; 554 } 555 556 bool TpmUtilityV1::LoadSrk(TSS_HCONTEXT context_handle, 557 ScopedTssKey* srk_handle) { 558 TSS_RESULT result; 559 TSS_UUID uuid = TSS_UUID_SRK; 560 if (TPM_ERROR(result = Tspi_Context_LoadKeyByUUID(context_handle, 561 TSS_PS_TYPE_SYSTEM, uuid, 562 srk_handle->ptr()))) { 563 TPM_LOG(ERROR, result) << __func__ 564 << ": Error calling Tspi_Context_LoadKeyByUUID"; 565 return false; 566 } 567 // Check if the SRK wants a password. 568 UINT32 auth_usage; 569 if (TPM_ERROR(result = Tspi_GetAttribUint32( 570 *srk_handle, TSS_TSPATTRIB_KEY_INFO, 571 TSS_TSPATTRIB_KEYINFO_AUTHUSAGE, &auth_usage))) { 572 TPM_LOG(ERROR, result) << __func__ 573 << ": Error calling Tspi_GetAttribUint32"; 574 return false; 575 } 576 if (auth_usage) { 577 // Give it an empty password if needed. 578 TSS_HPOLICY usage_policy; 579 if (TPM_ERROR(result = Tspi_GetPolicyObject(*srk_handle, TSS_POLICY_USAGE, 580 &usage_policy))) { 581 TPM_LOG(ERROR, result) << __func__ 582 << ": Error calling Tspi_GetPolicyObject"; 583 return false; 584 } 585 586 BYTE empty_password[] = {}; 587 if (TPM_ERROR(result = 588 Tspi_Policy_SetSecret(usage_policy, TSS_SECRET_MODE_PLAIN, 589 0, empty_password))) { 590 TPM_LOG(ERROR, result) << __func__ 591 << ": Error calling Tspi_Policy_SetSecret"; 592 return false; 593 } 594 } 595 return true; 596 } 597 598 bool TpmUtilityV1::LoadKeyFromBlob(const std::string& key_blob, 599 TSS_HCONTEXT context_handle, 600 TSS_HKEY parent_key_handle, 601 ScopedTssKey* key_handle) { 602 std::string mutable_key_blob(key_blob); 603 BYTE* key_blob_buffer = StringAsTSSBuffer(&mutable_key_blob); 604 TSS_RESULT result = Tspi_Context_LoadKeyByBlob( 605 context_handle, parent_key_handle, key_blob.size(), key_blob_buffer, 606 key_handle->ptr()); 607 if (TPM_ERROR(result)) { 608 TPM_LOG(ERROR, result) << __func__ << ": Failed to load key by blob."; 609 return false; 610 } 611 return true; 612 } 613 614 bool TpmUtilityV1::GetDataAttribute(TSS_HCONTEXT context, 615 TSS_HOBJECT object, 616 TSS_FLAG flag, 617 TSS_FLAG sub_flag, 618 std::string* data) { 619 UINT32 length = 0; 620 ScopedTssMemory buffer(context); 621 TSS_RESULT result = 622 Tspi_GetAttribData(object, flag, sub_flag, &length, buffer.ptr()); 623 if (TPM_ERROR(result)) { 624 TPM_LOG(ERROR, result) << __func__ << "Failed to read object attribute."; 625 return false; 626 } 627 data->assign(TSSBufferAsString(buffer.value(), length)); 628 return true; 629 } 630 631 bool TpmUtilityV1::ConvertPublicKeyToDER(const std::string& public_key, 632 std::string* public_key_der) { 633 // Parse the serialized TPM_PUBKEY. 634 UINT64 offset = 0; 635 std::string mutable_public_key(public_key); 636 BYTE* buffer = StringAsTSSBuffer(&mutable_public_key); 637 TPM_PUBKEY parsed; 638 TSS_RESULT result = Trspi_UnloadBlob_PUBKEY(&offset, buffer, &parsed); 639 if (TPM_ERROR(result)) { 640 TPM_LOG(ERROR, result) << "Failed to parse TPM_PUBKEY."; 641 return false; 642 } 643 ScopedByteArray scoped_key(parsed.pubKey.key); 644 ScopedByteArray scoped_parms(parsed.algorithmParms.parms); 645 TPM_RSA_KEY_PARMS* parms = 646 reinterpret_cast<TPM_RSA_KEY_PARMS*>(parsed.algorithmParms.parms); 647 crypto::ScopedRSA rsa(RSA_new()); 648 CHECK(rsa.get()); 649 // Get the public exponent. 650 if (parms->exponentSize == 0) { 651 rsa.get()->e = BN_new(); 652 CHECK(rsa.get()->e); 653 BN_set_word(rsa.get()->e, kWellKnownExponent); 654 } else { 655 rsa.get()->e = BN_bin2bn(parms->exponent, parms->exponentSize, nullptr); 656 CHECK(rsa.get()->e); 657 } 658 // Get the modulus. 659 rsa.get()->n = BN_bin2bn(parsed.pubKey.key, parsed.pubKey.keyLength, nullptr); 660 CHECK(rsa.get()->n); 661 662 // DER encode. 663 int der_length = i2d_RSAPublicKey(rsa.get(), nullptr); 664 if (der_length < 0) { 665 LOG(ERROR) << "Failed to DER-encode public key."; 666 return false; 667 } 668 public_key_der->resize(der_length); 669 unsigned char* der_buffer = 670 reinterpret_cast<unsigned char*>(string_as_array(public_key_der)); 671 der_length = i2d_RSAPublicKey(rsa.get(), &der_buffer); 672 if (der_length < 0) { 673 LOG(ERROR) << "Failed to DER-encode public key."; 674 return false; 675 } 676 public_key_der->resize(der_length); 677 return true; 678 } 679 680 } // namespace attestation 681