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