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 "trunks/trunks_client_test.h" 18 19 #include <algorithm> 20 #include <map> 21 #include <memory> 22 #include <string> 23 #include <vector> 24 25 #include <base/logging.h> 26 #include <base/stl_util.h> 27 #include <crypto/openssl_util.h> 28 #include <crypto/scoped_openssl_types.h> 29 #include <crypto/sha2.h> 30 #include <openssl/bn.h> 31 #include <openssl/err.h> 32 #include <openssl/rsa.h> 33 34 #include "trunks/authorization_delegate.h" 35 #include "trunks/error_codes.h" 36 #include "trunks/hmac_session.h" 37 #include "trunks/policy_session.h" 38 #include "trunks/scoped_key_handle.h" 39 #include "trunks/tpm_generated.h" 40 #include "trunks/tpm_state.h" 41 #include "trunks/tpm_utility.h" 42 #include "trunks/trunks_factory_impl.h" 43 44 namespace { 45 46 std::string GetOpenSSLError() { 47 BIO* bio = BIO_new(BIO_s_mem()); 48 ERR_print_errors(bio); 49 char* data = nullptr; 50 int data_len = BIO_get_mem_data(bio, &data); 51 std::string error_string(data, data_len); 52 BIO_free(bio); 53 return error_string; 54 } 55 56 } // namespace 57 58 namespace trunks { 59 60 TrunksClientTest::TrunksClientTest() 61 : factory_(new TrunksFactoryImpl(true /* failure_is_fatal */)) { 62 crypto::EnsureOpenSSLInit(); 63 } 64 65 TrunksClientTest::TrunksClientTest(scoped_ptr<TrunksFactory> factory) 66 : factory_(std::move(factory)) {} 67 68 TrunksClientTest::~TrunksClientTest() {} 69 70 bool TrunksClientTest::RNGTest() { 71 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 72 scoped_ptr<HmacSession> session = factory_->GetHmacSession(); 73 if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { 74 LOG(ERROR) << "Error starting hmac session."; 75 return false; 76 } 77 std::string entropy_data("entropy_data"); 78 std::string random_data; 79 size_t num_bytes = 70; 80 TPM_RC result = utility->StirRandom(entropy_data, session->GetDelegate()); 81 if (result != TPM_RC_SUCCESS) { 82 LOG(ERROR) << "Error stirring TPM RNG: " << GetErrorString(result); 83 return false; 84 } 85 result = utility->GenerateRandom(num_bytes, session->GetDelegate(), 86 &random_data); 87 if (result != TPM_RC_SUCCESS) { 88 LOG(ERROR) << "Error getting random bytes from TPM: " 89 << GetErrorString(result); 90 return false; 91 } 92 if (num_bytes != random_data.size()) { 93 LOG(ERROR) << "Error not enough random bytes received."; 94 return false; 95 } 96 return true; 97 } 98 99 bool TrunksClientTest::SignTest() { 100 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 101 scoped_ptr<HmacSession> session = factory_->GetHmacSession(); 102 if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { 103 LOG(ERROR) << "Error starting hmac session."; 104 return false; 105 } 106 std::string key_authorization("sign"); 107 std::string key_blob; 108 TPM_RC result = utility->CreateRSAKeyPair( 109 TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001, 110 key_authorization, "", false, // use_only_policy_authorization 111 kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr); 112 if (result != TPM_RC_SUCCESS) { 113 LOG(ERROR) << "Error creating signing key: " << GetErrorString(result); 114 return false; 115 } 116 TPM_HANDLE signing_key; 117 result = utility->LoadKey(key_blob, session->GetDelegate(), &signing_key); 118 if (result != TPM_RC_SUCCESS) { 119 LOG(ERROR) << "Error loading signing key: " << GetErrorString(result); 120 } 121 ScopedKeyHandle scoped_key(*factory_.get(), signing_key); 122 session->SetEntityAuthorizationValue(key_authorization); 123 std::string signature; 124 result = utility->Sign(signing_key, TPM_ALG_NULL, TPM_ALG_NULL, 125 std::string(32, 'a'), session->GetDelegate(), 126 &signature); 127 if (result != TPM_RC_SUCCESS) { 128 LOG(ERROR) << "Error using key to sign: " << GetErrorString(result); 129 return false; 130 } 131 result = utility->Verify(signing_key, TPM_ALG_NULL, TPM_ALG_NULL, 132 std::string(32, 'a'), signature, nullptr); 133 if (result != TPM_RC_SUCCESS) { 134 LOG(ERROR) << "Error using key to verify: " << GetErrorString(result); 135 return false; 136 } 137 return true; 138 } 139 140 bool TrunksClientTest::DecryptTest() { 141 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 142 scoped_ptr<HmacSession> session = factory_->GetHmacSession(); 143 if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { 144 LOG(ERROR) << "Error starting hmac session."; 145 return false; 146 } 147 std::string key_authorization("decrypt"); 148 std::string key_blob; 149 TPM_RC result = utility->CreateRSAKeyPair( 150 TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, 151 key_authorization, "", false, // use_only_policy_authorization 152 kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr); 153 if (result != TPM_RC_SUCCESS) { 154 LOG(ERROR) << "Error creating decrypt key: " << GetErrorString(result); 155 return false; 156 } 157 TPM_HANDLE decrypt_key; 158 result = utility->LoadKey(key_blob, session->GetDelegate(), &decrypt_key); 159 if (result != TPM_RC_SUCCESS) { 160 LOG(ERROR) << "Error loading decrypt key: " << GetErrorString(result); 161 } 162 ScopedKeyHandle scoped_key(*factory_.get(), decrypt_key); 163 return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), 164 key_authorization, 165 session.get()); 166 } 167 168 bool TrunksClientTest::ImportTest() { 169 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 170 scoped_ptr<HmacSession> session = factory_->GetHmacSession(); 171 if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { 172 LOG(ERROR) << "Error starting hmac session."; 173 return false; 174 } 175 std::string modulus; 176 std::string prime_factor; 177 GenerateRSAKeyPair(&modulus, &prime_factor, nullptr); 178 std::string key_blob; 179 std::string key_authorization("import"); 180 TPM_RC result = utility->ImportRSAKey( 181 TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, modulus, 0x10001, 182 prime_factor, key_authorization, session->GetDelegate(), &key_blob); 183 if (result != TPM_RC_SUCCESS) { 184 LOG(ERROR) << "Error importing key into TPM: " << GetErrorString(result); 185 return false; 186 } 187 TPM_HANDLE key_handle; 188 result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle); 189 if (result != TPM_RC_SUCCESS) { 190 LOG(ERROR) << "Error loading key into TPM: " << GetErrorString(result); 191 return false; 192 } 193 ScopedKeyHandle scoped_key(*factory_.get(), key_handle); 194 return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization, 195 session.get()); 196 } 197 198 bool TrunksClientTest::AuthChangeTest() { 199 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 200 scoped_ptr<HmacSession> session = factory_->GetHmacSession(); 201 if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { 202 LOG(ERROR) << "Error starting hmac session."; 203 return false; 204 } 205 std::string key_authorization("new_pass"); 206 std::string key_blob; 207 TPM_RC result = utility->CreateRSAKeyPair( 208 TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, 209 "old_pass", "", false, // use_only_policy_authorization 210 kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr); 211 if (result != TPM_RC_SUCCESS) { 212 LOG(ERROR) << "Error creating change auth key: " << GetErrorString(result); 213 return false; 214 } 215 TPM_HANDLE key_handle; 216 result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle); 217 if (result != TPM_RC_SUCCESS) { 218 LOG(ERROR) << "Error loading change auth key: " << GetErrorString(result); 219 } 220 ScopedKeyHandle scoped_key(*factory_.get(), key_handle); 221 session->SetEntityAuthorizationValue("old_pass"); 222 result = utility->ChangeKeyAuthorizationData(key_handle, key_authorization, 223 session->GetDelegate(), 224 &key_blob); 225 if (result != TPM_RC_SUCCESS) { 226 LOG(ERROR) << "Error changing auth data: " << GetErrorString(result); 227 return false; 228 } 229 session->SetEntityAuthorizationValue(""); 230 result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle); 231 if (result != TPM_RC_SUCCESS) { 232 LOG(ERROR) << "Error reloading key: " << GetErrorString(result); 233 return false; 234 } 235 scoped_key.reset(key_handle); 236 return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization, 237 session.get()); 238 } 239 240 bool TrunksClientTest::VerifyKeyCreationTest() { 241 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 242 scoped_ptr<HmacSession> session = factory_->GetHmacSession(); 243 if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { 244 LOG(ERROR) << "Error starting hmac session."; 245 return false; 246 } 247 std::string key_blob; 248 std::string creation_blob; 249 session->SetEntityAuthorizationValue(""); 250 TPM_RC result = utility->CreateRSAKeyPair( 251 TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, 252 "", "", false, // use_only_policy_authorization 253 kNoCreationPCR, session->GetDelegate(), &key_blob, &creation_blob); 254 if (result != TPM_RC_SUCCESS) { 255 LOG(ERROR) << "Error creating certify key: " << GetErrorString(result); 256 return false; 257 } 258 std::string alternate_key_blob; 259 result = utility->CreateRSAKeyPair( 260 TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, 261 "", "", false, // use_only_policy_authorization 262 kNoCreationPCR, session->GetDelegate(), &alternate_key_blob, 263 nullptr); 264 if (result != TPM_RC_SUCCESS) { 265 LOG(ERROR) << "Error creating alternate key: " << GetErrorString(result); 266 return false; 267 } 268 TPM_HANDLE key_handle; 269 result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle); 270 if (result != TPM_RC_SUCCESS) { 271 LOG(ERROR) << "Error loading certify key: " << GetErrorString(result); 272 return false; 273 } 274 TPM_HANDLE alternate_key_handle; 275 result = utility->LoadKey(alternate_key_blob, 276 session->GetDelegate(), 277 &alternate_key_handle); 278 if (result != TPM_RC_SUCCESS) { 279 LOG(ERROR) << "Error loading alternate key: " << GetErrorString(result); 280 return false; 281 } 282 ScopedKeyHandle certify_key(*factory_.get(), key_handle); 283 ScopedKeyHandle alternate_key(*factory_.get(), alternate_key_handle); 284 result = utility->CertifyCreation(certify_key.get(), creation_blob); 285 if (result != TPM_RC_SUCCESS) { 286 LOG(ERROR) << "Error certifying key: " << GetErrorString(result); 287 return false; 288 } 289 result = utility->CertifyCreation(alternate_key.get(), creation_blob); 290 if (result == TPM_RC_SUCCESS) { 291 LOG(ERROR) << "Error alternate key certified with wrong creation data."; 292 return false; 293 } 294 return true; 295 } 296 297 bool TrunksClientTest::SealedDataTest() { 298 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 299 scoped_ptr<HmacSession> session = factory_->GetHmacSession(); 300 if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { 301 LOG(ERROR) << "Error starting hmac session."; 302 return false; 303 } 304 int pcr_index = 5; 305 std::string policy_digest; 306 TPM_RC result = utility->GetPolicyDigestForPcrValue(pcr_index, "", 307 &policy_digest); 308 if (result != TPM_RC_SUCCESS) { 309 LOG(ERROR) << "Error getting policy_digest: " << GetErrorString(result); 310 return false; 311 } 312 std::string data_to_seal("seal_data"); 313 std::string sealed_data; 314 result = utility->SealData(data_to_seal, policy_digest, 315 session->GetDelegate(), &sealed_data); 316 if (result != TPM_RC_SUCCESS) { 317 LOG(ERROR) << "Error creating Sealed Object: " << GetErrorString(result); 318 return false; 319 } 320 scoped_ptr<PolicySession> policy_session = factory_->GetPolicySession(); 321 result = policy_session->StartUnboundSession(false); 322 if (result != TPM_RC_SUCCESS) { 323 LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); 324 return false; 325 } 326 result = policy_session->PolicyPCR(pcr_index, ""); 327 if (result != TPM_RC_SUCCESS) { 328 LOG(ERROR) << "Error restricting policy to pcr value: " 329 << GetErrorString(result); 330 return false; 331 } 332 std::string unsealed_data; 333 result = utility->UnsealData(sealed_data, policy_session->GetDelegate(), 334 &unsealed_data); 335 if (result != TPM_RC_SUCCESS) { 336 LOG(ERROR) << "Error unsealing object: " << GetErrorString(result); 337 return false; 338 } 339 if (data_to_seal != unsealed_data) { 340 LOG(ERROR) << "Error unsealed data from TPM does not match original data."; 341 return false; 342 } 343 result = utility->ExtendPCR(pcr_index, "extend", session->GetDelegate()); 344 if (result != TPM_RC_SUCCESS) { 345 LOG(ERROR) << "Error extending pcr: " << GetErrorString(result); 346 return false; 347 } 348 result = policy_session->PolicyPCR(pcr_index, ""); 349 if (result != TPM_RC_SUCCESS) { 350 LOG(ERROR) << "Error restricting policy to pcr value: " 351 << GetErrorString(result); 352 return false; 353 } 354 result = utility->UnsealData(sealed_data, policy_session->GetDelegate(), 355 &unsealed_data); 356 if (result == TPM_RC_SUCCESS) { 357 LOG(ERROR) << "Error object was unsealed with wrong policy_digest."; 358 return false; 359 } 360 return true; 361 } 362 363 bool TrunksClientTest::PCRTest() { 364 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 365 scoped_ptr<HmacSession> session = factory_->GetHmacSession(); 366 if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { 367 LOG(ERROR) << "Error starting hmac session."; 368 return false; 369 } 370 // We are using PCR 2 because it is currently not used by ChromeOS. 371 uint32_t pcr_index = 2; 372 std::string extend_data("data"); 373 std::string old_data; 374 TPM_RC result = utility->ReadPCR(pcr_index, &old_data); 375 if (result != TPM_RC_SUCCESS) { 376 LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result); 377 return false; 378 } 379 result = utility->ExtendPCR(pcr_index, extend_data, session->GetDelegate()); 380 if (result != TPM_RC_SUCCESS) { 381 LOG(ERROR) << "Error extending PCR value: " << GetErrorString(result); 382 return false; 383 } 384 std::string pcr_data; 385 result = utility->ReadPCR(pcr_index, &pcr_data); 386 if (result != TPM_RC_SUCCESS) { 387 LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result); 388 return false; 389 } 390 std::string hashed_extend_data = crypto::SHA256HashString(extend_data); 391 std::string expected_pcr_data = 392 crypto::SHA256HashString(old_data + hashed_extend_data); 393 if (pcr_data.compare(expected_pcr_data) != 0) { 394 LOG(ERROR) << "PCR data does not match expected value."; 395 return false; 396 } 397 return true; 398 } 399 400 bool TrunksClientTest::PolicyAuthValueTest() { 401 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 402 scoped_ptr<PolicySession> trial_session = factory_->GetTrialSession(); 403 TPM_RC result; 404 result = trial_session->StartUnboundSession(true); 405 if (result != TPM_RC_SUCCESS) { 406 LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); 407 return false; 408 } 409 result = trial_session->PolicyAuthValue(); 410 if (result != TPM_RC_SUCCESS) { 411 LOG(ERROR) << "Error restricting policy to auth value knowledge: " 412 << GetErrorString(result); 413 return false; 414 } 415 std::string policy_digest; 416 result = trial_session->GetDigest(&policy_digest); 417 if (result != TPM_RC_SUCCESS) { 418 LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); 419 return false; 420 } 421 // Now that we have the digest, we can close the trial session and use hmac. 422 trial_session.reset(); 423 424 scoped_ptr<HmacSession> hmac_session = factory_->GetHmacSession(); 425 result = hmac_session->StartUnboundSession(true); 426 if (result != TPM_RC_SUCCESS) { 427 LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result); 428 return false; 429 } 430 431 std::string key_blob; 432 result = utility->CreateRSAKeyPair( 433 TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001, 434 "password", policy_digest, true, // use_only_policy_authorization 435 kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr); 436 if (result != TPM_RC_SUCCESS) { 437 LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result); 438 return false; 439 } 440 441 TPM_HANDLE key_handle; 442 result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle); 443 if (result != TPM_RC_SUCCESS) { 444 LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result); 445 return false; 446 } 447 ScopedKeyHandle scoped_key(*factory_.get(), key_handle); 448 449 // Now we can reset the hmac_session. 450 hmac_session.reset(); 451 452 scoped_ptr<PolicySession> policy_session = factory_->GetPolicySession(); 453 result = policy_session->StartUnboundSession(false); 454 if (result != TPM_RC_SUCCESS) { 455 LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); 456 return false; 457 } 458 result = policy_session->PolicyAuthValue(); 459 if (result != TPM_RC_SUCCESS) { 460 LOG(ERROR) << "Error restricting policy to auth value knowledge: " 461 << GetErrorString(result); 462 return false; 463 } 464 std::string signature; 465 policy_session->SetEntityAuthorizationValue("password"); 466 result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, 467 std::string(32, 0), policy_session->GetDelegate(), 468 &signature); 469 if (result != TPM_RC_SUCCESS) { 470 LOG(ERROR) << "Error signing using RSA key: " << GetErrorString(result); 471 return false; 472 } 473 result = utility->Verify(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, 474 std::string(32, 0), signature, nullptr); 475 if (result != TPM_RC_SUCCESS) { 476 LOG(ERROR) << "Error verifying using RSA key: " << GetErrorString(result); 477 return false; 478 } 479 std::string ciphertext; 480 result = utility->AsymmetricEncrypt(scoped_key.get(), TPM_ALG_NULL, 481 TPM_ALG_NULL, "plaintext", 482 nullptr, 483 &ciphertext); 484 if (result != TPM_RC_SUCCESS) { 485 LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result); 486 return false; 487 } 488 result = policy_session->PolicyAuthValue(); 489 if (result != TPM_RC_SUCCESS) { 490 LOG(ERROR) << "Error restricting policy to auth value knowledge: " 491 << GetErrorString(result); 492 return false; 493 } 494 std::string plaintext; 495 policy_session->SetEntityAuthorizationValue("password"); 496 result = utility->AsymmetricDecrypt(scoped_key.get(), TPM_ALG_NULL, 497 TPM_ALG_NULL, ciphertext, 498 policy_session->GetDelegate(), 499 &plaintext); 500 if (result != TPM_RC_SUCCESS) { 501 LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result); 502 return false; 503 } 504 if (plaintext.compare("plaintext") != 0) { 505 LOG(ERROR) << "Plaintext changed after encrypt + decrypt."; 506 return false; 507 } 508 return true; 509 } 510 511 bool TrunksClientTest::PolicyAndTest() { 512 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 513 scoped_ptr<PolicySession> trial_session = factory_->GetTrialSession(); 514 TPM_RC result; 515 result = trial_session->StartUnboundSession(true); 516 if (result != TPM_RC_SUCCESS) { 517 LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); 518 return false; 519 } 520 result = trial_session->PolicyCommandCode(TPM_CC_Sign); 521 if (result != TPM_RC_SUCCESS) { 522 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 523 return false; 524 } 525 uint32_t pcr_index = 2; 526 std::string pcr_value; 527 result = utility->ReadPCR(pcr_index, &pcr_value); 528 if (result != TPM_RC_SUCCESS) { 529 LOG(ERROR) << "Error reading pcr: " << GetErrorString(result); 530 return false; 531 } 532 std::string pcr_extend_data("extend"); 533 std::string next_pcr_value; 534 std::string hashed_extend_data = crypto::SHA256HashString(pcr_extend_data); 535 next_pcr_value = crypto::SHA256HashString(pcr_value + hashed_extend_data); 536 537 result = trial_session->PolicyPCR(pcr_index, next_pcr_value); 538 if (result != TPM_RC_SUCCESS) { 539 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 540 return false; 541 } 542 std::string policy_digest; 543 result = trial_session->GetDigest(&policy_digest); 544 if (result != TPM_RC_SUCCESS) { 545 LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); 546 return false; 547 } 548 // Now that we have the digest, we can close the trial session and use hmac. 549 trial_session.reset(); 550 551 scoped_ptr<HmacSession> hmac_session = factory_->GetHmacSession(); 552 result = hmac_session->StartUnboundSession(true); 553 if (result != TPM_RC_SUCCESS) { 554 LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result); 555 return false; 556 } 557 std::string key_authorization("password"); 558 std::string key_blob; 559 // This key is created with a policy that dictates it can only be used 560 // when pcr 2 remains unchanged, and when the command is TPM2_Sign. 561 result = utility->CreateRSAKeyPair( 562 TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001, 563 key_authorization, policy_digest, true, // use_only_policy_authorization 564 kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr); 565 if (result != TPM_RC_SUCCESS) { 566 LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result); 567 return false; 568 } 569 TPM_HANDLE key_handle; 570 result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle); 571 if (result != TPM_RC_SUCCESS) { 572 LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result); 573 return false; 574 } 575 ScopedKeyHandle scoped_key(*factory_.get(), key_handle); 576 577 // Now we can reset the hmac_session. 578 hmac_session.reset(); 579 580 scoped_ptr<PolicySession> policy_session = factory_->GetPolicySession(); 581 result = policy_session->StartUnboundSession(false); 582 if (result != TPM_RC_SUCCESS) { 583 LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); 584 return false; 585 } 586 result = policy_session->PolicyCommandCode(TPM_CC_Sign); 587 if (result != TPM_RC_SUCCESS) { 588 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 589 return false; 590 } 591 result = policy_session->PolicyPCR(pcr_index, ""); 592 if (result != TPM_RC_SUCCESS) { 593 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 594 return false; 595 } 596 std::string signature; 597 policy_session->SetEntityAuthorizationValue(key_authorization); 598 // Signing with this key when pcr 2 is unchanged fails. 599 result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, 600 std::string(32, 'a'), policy_session->GetDelegate(), 601 &signature); 602 if (GetFormatOneError(result) != TPM_RC_POLICY_FAIL) { 603 LOG(ERROR) << "Error using key to sign: " << GetErrorString(result); 604 return false; 605 } 606 scoped_ptr<AuthorizationDelegate> delegate = 607 factory_->GetPasswordAuthorization(""); 608 result = utility->ExtendPCR(pcr_index, pcr_extend_data, delegate.get()); 609 if (result != TPM_RC_SUCCESS) { 610 LOG(ERROR) << "Error extending pcr: " << GetErrorString(result); 611 return false; 612 } 613 // we have to restart the session because we changed the pcr values. 614 result = policy_session->StartUnboundSession(false); 615 if (result != TPM_RC_SUCCESS) { 616 LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); 617 return false; 618 } 619 result = policy_session->PolicyCommandCode(TPM_CC_Sign); 620 if (result != TPM_RC_SUCCESS) { 621 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 622 return false; 623 } 624 result = policy_session->PolicyPCR(pcr_index, ""); 625 if (result != TPM_RC_SUCCESS) { 626 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 627 return false; 628 } 629 policy_session->SetEntityAuthorizationValue(key_authorization); 630 // Signing with this key when pcr 2 is changed succeeds. 631 result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, 632 std::string(32, 'a'), policy_session->GetDelegate(), 633 &signature); 634 if (result != TPM_RC_SUCCESS) { 635 LOG(ERROR) << "Error using key to sign: " << GetErrorString(result); 636 return false; 637 } 638 result = utility->Verify(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, 639 std::string(32, 'a'), signature, nullptr); 640 if (result != TPM_RC_SUCCESS) { 641 LOG(ERROR) << "Error using key to verify: " << GetErrorString(result); 642 return false; 643 } 644 std::string ciphertext; 645 result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL, 646 "plaintext", nullptr, &ciphertext); 647 if (result != TPM_RC_SUCCESS) { 648 LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result); 649 return false; 650 } 651 result = policy_session->PolicyCommandCode(TPM_CC_Sign); 652 if (result != TPM_RC_SUCCESS) { 653 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 654 return false; 655 } 656 result = policy_session->PolicyPCR(pcr_index, ""); 657 if (result != TPM_RC_SUCCESS) { 658 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 659 return false; 660 } 661 std::string plaintext; 662 policy_session->SetEntityAuthorizationValue(key_authorization); 663 // This call is not authorized with the policy, because its command code 664 // is not TPM_CC_SIGN. It should fail with TPM_RC_POLICY_CC. 665 result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL, 666 ciphertext, policy_session->GetDelegate(), 667 &plaintext); 668 if (GetFormatOneError(result) != TPM_RC_POLICY_CC) { 669 LOG(ERROR) << "Error: " << GetErrorString(result); 670 return false; 671 } 672 return true; 673 } 674 675 bool TrunksClientTest::PolicyOrTest() { 676 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 677 scoped_ptr<PolicySession> trial_session = factory_->GetTrialSession(); 678 TPM_RC result; 679 // Specify a policy that asserts either TPM_CC_RSA_Encrypt or 680 // TPM_CC_RSA_Decrypt. A key created under this policy can only be used 681 // to encrypt or decrypt. 682 result = trial_session->StartUnboundSession(true); 683 if (result != TPM_RC_SUCCESS) { 684 LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); 685 return false; 686 } 687 result = trial_session->PolicyCommandCode(TPM_CC_Sign); 688 if (result != TPM_RC_SUCCESS) { 689 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 690 return false; 691 } 692 std::string sign_digest; 693 result = trial_session->GetDigest(&sign_digest); 694 if (result != TPM_RC_SUCCESS) { 695 LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); 696 return false; 697 } 698 result = trial_session->StartUnboundSession(true); 699 if (result != TPM_RC_SUCCESS) { 700 LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); 701 return false; 702 } 703 result = trial_session->PolicyCommandCode(TPM_CC_RSA_Decrypt); 704 if (result != TPM_RC_SUCCESS) { 705 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 706 return false; 707 } 708 std::string decrypt_digest; 709 result = trial_session->GetDigest(&decrypt_digest); 710 if (result != TPM_RC_SUCCESS) { 711 LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); 712 return false; 713 } 714 std::vector<std::string> digests; 715 digests.push_back(sign_digest); 716 digests.push_back(decrypt_digest); 717 result = trial_session->PolicyOR(digests); 718 if (result != TPM_RC_SUCCESS) { 719 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 720 return false; 721 } 722 std::string policy_digest; 723 result = trial_session->GetDigest(&policy_digest); 724 if (result != TPM_RC_SUCCESS) { 725 LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); 726 return false; 727 } 728 // Now that we have the digest, we can close the trial session and use hmac. 729 trial_session.reset(); 730 731 scoped_ptr<HmacSession> hmac_session = factory_->GetHmacSession(); 732 result = hmac_session->StartUnboundSession(true); 733 if (result != TPM_RC_SUCCESS) { 734 LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result); 735 return false; 736 } 737 std::string key_authorization("password"); 738 std::string key_blob; 739 // This key is created with a policy that specifies that it can only be used 740 // for encrypt and decrypt operations. 741 result = utility->CreateRSAKeyPair( 742 TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001, 743 key_authorization, policy_digest, true, // use_only_policy_authorization 744 kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr); 745 if (result != TPM_RC_SUCCESS) { 746 LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result); 747 return false; 748 } 749 TPM_HANDLE key_handle; 750 result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle); 751 if (result != TPM_RC_SUCCESS) { 752 LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result); 753 return false; 754 } 755 ScopedKeyHandle scoped_key(*factory_.get(), key_handle); 756 757 // Now we can reset the hmac_session. 758 hmac_session.reset(); 759 760 scoped_ptr<PolicySession> policy_session = factory_->GetPolicySession(); 761 result = policy_session->StartUnboundSession(false); 762 if (result != TPM_RC_SUCCESS) { 763 LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); 764 return false; 765 } 766 std::string ciphertext; 767 result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL, 768 "plaintext", nullptr, &ciphertext); 769 if (result != TPM_RC_SUCCESS) { 770 LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result); 771 return false; 772 } 773 result = policy_session->PolicyCommandCode(TPM_CC_RSA_Decrypt); 774 if (result != TPM_RC_SUCCESS) { 775 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 776 return false; 777 } 778 result = policy_session->PolicyOR(digests); 779 if (result != TPM_RC_SUCCESS) { 780 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 781 return false; 782 } 783 std::string plaintext; 784 policy_session->SetEntityAuthorizationValue(key_authorization); 785 // We can freely use the key for decryption. 786 result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL, 787 ciphertext, policy_session->GetDelegate(), 788 &plaintext); 789 if (result != TPM_RC_SUCCESS) { 790 LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result); 791 return false; 792 } 793 if (plaintext.compare("plaintext") != 0) { 794 LOG(ERROR) << "Plaintext changed after encrypt + decrypt."; 795 return false; 796 } 797 result = policy_session->PolicyCommandCode(TPM_CC_Sign); 798 if (result != TPM_RC_SUCCESS) { 799 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 800 return false; 801 } 802 result = policy_session->PolicyOR(digests); 803 if (result != TPM_RC_SUCCESS) { 804 LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); 805 return false; 806 } 807 std::string signature; 808 policy_session->SetEntityAuthorizationValue(key_authorization); 809 // However signing with a key only authorized for encrypt/decrypt should 810 // fail with TPM_RC_POLICY_CC. 811 result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, 812 std::string(32, 'a'), policy_session->GetDelegate(), 813 &signature); 814 if (result != TPM_RC_SUCCESS) { 815 LOG(ERROR) << "Error using key to sign: " << GetErrorString(result); 816 return false; 817 } 818 return true; 819 } 820 821 bool TrunksClientTest::NvramTest(const std::string& owner_password) { 822 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 823 scoped_ptr<HmacSession> session = factory_->GetHmacSession(); 824 TPM_RC result = session->StartUnboundSession(true /* enable encryption */); 825 if (result != TPM_RC_SUCCESS) { 826 LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result); 827 return false; 828 } 829 uint32_t index = 1; 830 session->SetEntityAuthorizationValue(owner_password); 831 std::string nv_data("nv_data"); 832 result = utility->DefineNVSpace(index, nv_data.size(), 833 session->GetDelegate()); 834 if (result != TPM_RC_SUCCESS) { 835 LOG(ERROR) << "Error defining nvram: " << GetErrorString(result); 836 return false; 837 } 838 session->SetEntityAuthorizationValue(owner_password); 839 result = utility->WriteNVSpace(index, 0, nv_data, session->GetDelegate()); 840 if (result != TPM_RC_SUCCESS) { 841 LOG(ERROR) << "Error writing nvram: " << GetErrorString(result); 842 return false; 843 } 844 std::string new_nvdata; 845 session->SetEntityAuthorizationValue(""); 846 result = utility->ReadNVSpace(index, 0, nv_data.size(), 847 &new_nvdata, session->GetDelegate()); 848 if (result != TPM_RC_SUCCESS) { 849 LOG(ERROR) << "Error reading nvram: " << GetErrorString(result); 850 return false; 851 } 852 if (nv_data.compare(new_nvdata) != 0) { 853 LOG(ERROR) << "NV space had different data than was written."; 854 return false; 855 } 856 session->SetEntityAuthorizationValue(owner_password); 857 result = utility->LockNVSpace(index, session->GetDelegate()); 858 if (result != TPM_RC_SUCCESS) { 859 LOG(ERROR) << "Error locking nvram: " << GetErrorString(result); 860 return false; 861 } 862 session->SetEntityAuthorizationValue(""); 863 result = utility->ReadNVSpace(index, 0, nv_data.size(), 864 &new_nvdata, session->GetDelegate()); 865 if (result != TPM_RC_SUCCESS) { 866 LOG(ERROR) << "Error reading nvram: " << GetErrorString(result); 867 return false; 868 } 869 if (nv_data.compare(new_nvdata) != 0) { 870 LOG(ERROR) << "NV space had different data than was written."; 871 return false; 872 } 873 session->SetEntityAuthorizationValue(owner_password); 874 result = utility->WriteNVSpace(index, 0, nv_data, session->GetDelegate()); 875 if (result == TPM_RC_SUCCESS) { 876 LOG(ERROR) << "Wrote nvram after locking: " << GetErrorString(result); 877 return false; 878 } 879 session->SetEntityAuthorizationValue(owner_password); 880 result = utility->DestroyNVSpace(index, session->GetDelegate()); 881 if (result != TPM_RC_SUCCESS) { 882 LOG(ERROR) << "Error destroying nvram: " << GetErrorString(result); 883 return false; 884 } 885 return true; 886 } 887 888 bool TrunksClientTest::ManyKeysTest() { 889 const size_t kNumKeys = 20; 890 std::vector<std::unique_ptr<ScopedKeyHandle>> key_handles; 891 std::map<TPM_HANDLE, std::string> public_key_map; 892 for (size_t i = 0; i < kNumKeys; ++i) { 893 std::unique_ptr<ScopedKeyHandle> key_handle(new ScopedKeyHandle(*factory_)); 894 std::string public_key; 895 if (!LoadSigningKey(key_handle.get(), &public_key)) { 896 LOG(ERROR) << "Error loading key " << i << " into TPM."; 897 } 898 public_key_map[key_handle->get()] = public_key; 899 key_handles.push_back(std::move(key_handle)); 900 } 901 CHECK_EQ(key_handles.size(), kNumKeys); 902 CHECK_EQ(public_key_map.size(), kNumKeys); 903 scoped_ptr<AuthorizationDelegate> delegate = 904 factory_->GetPasswordAuthorization(""); 905 for (size_t i = 0; i < kNumKeys; ++i) { 906 const ScopedKeyHandle& key_handle = *key_handles[i]; 907 const std::string& public_key = public_key_map[key_handle.get()]; 908 if (!SignAndVerify(key_handle, public_key, delegate.get())) { 909 LOG(ERROR) << "Error signing with key " << i; 910 } 911 } 912 std::random_shuffle(key_handles.begin(), key_handles.end()); 913 for (size_t i = 0; i < kNumKeys; ++i) { 914 const ScopedKeyHandle& key_handle = *key_handles[i]; 915 const std::string& public_key = public_key_map[key_handle.get()]; 916 if (!SignAndVerify(key_handle, public_key, delegate.get())) { 917 LOG(ERROR) << "Error signing with shuffled key " << i; 918 } 919 } 920 return true; 921 } 922 923 bool TrunksClientTest::ManySessionsTest() { 924 const size_t kNumSessions = 20; 925 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 926 std::vector<std::unique_ptr<HmacSession>> sessions; 927 for (size_t i = 0; i < kNumSessions; ++i) { 928 std::unique_ptr<HmacSession> session(factory_->GetHmacSession().release()); 929 TPM_RC result = session->StartUnboundSession(true /* enable encryption */); 930 if (result != TPM_RC_SUCCESS) { 931 LOG(ERROR) << "Error starting hmac session " << i << ": " 932 << GetErrorString(result); 933 return false; 934 } 935 sessions.push_back(std::move(session)); 936 } 937 CHECK_EQ(sessions.size(), kNumSessions); 938 ScopedKeyHandle key_handle(*factory_); 939 std::string public_key; 940 if (!LoadSigningKey(&key_handle, &public_key)) { 941 return false; 942 } 943 for (size_t i = 0; i < kNumSessions; ++i) { 944 if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) { 945 LOG(ERROR) << "Error signing with hmac session " << i; 946 } 947 } 948 std::random_shuffle(sessions.begin(), sessions.end()); 949 for (size_t i = 0; i < kNumSessions; ++i) { 950 if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) { 951 LOG(ERROR) << "Error signing with shuffled hmac session " << i; 952 } 953 } 954 return true; 955 } 956 957 bool TrunksClientTest::PerformRSAEncrpytAndDecrpyt( 958 TPM_HANDLE key_handle, 959 const std::string& key_authorization, 960 HmacSession* session) { 961 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 962 std::string ciphertext; 963 session->SetEntityAuthorizationValue(""); 964 TPM_RC result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL, 965 TPM_ALG_NULL, "plaintext", 966 session->GetDelegate(), 967 &ciphertext); 968 if (result != TPM_RC_SUCCESS) { 969 LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result); 970 return false; 971 } 972 std::string plaintext; 973 session->SetEntityAuthorizationValue(key_authorization); 974 result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, 975 TPM_ALG_NULL, ciphertext, 976 session->GetDelegate(), &plaintext); 977 if (result != TPM_RC_SUCCESS) { 978 LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result); 979 return false; 980 } 981 if (plaintext.compare("plaintext") != 0) { 982 LOG(ERROR) << "Plaintext changed after encrypt + decrypt."; 983 return false; 984 } 985 return true; 986 } 987 988 void TrunksClientTest::GenerateRSAKeyPair(std::string* modulus, 989 std::string* prime_factor, 990 std::string* public_key) { 991 #if defined(OPENSSL_IS_BORINGSSL) 992 crypto::ScopedRSA rsa(RSA_new()); 993 crypto::ScopedBIGNUM exponent(BN_new()); 994 CHECK(BN_set_word(exponent.get(), RSA_F4)); 995 CHECK(RSA_generate_key_ex(rsa.get(), 2048, exponent.get(), nullptr)) 996 << "Failed to generate RSA key: " << GetOpenSSLError(); 997 #else 998 crypto::ScopedRSA rsa(RSA_generate_key(2048, 0x10001, nullptr, nullptr)); 999 CHECK(rsa.get()); 1000 #endif 1001 modulus->resize(BN_num_bytes(rsa.get()->n), 0); 1002 BN_bn2bin(rsa.get()->n, 1003 reinterpret_cast<unsigned char*>(string_as_array(modulus))); 1004 prime_factor->resize(BN_num_bytes(rsa.get()->p), 0); 1005 BN_bn2bin(rsa.get()->p, 1006 reinterpret_cast<unsigned char*>(string_as_array(prime_factor))); 1007 if (public_key) { 1008 unsigned char* buffer = NULL; 1009 int length = i2d_RSAPublicKey(rsa.get(), &buffer); 1010 CHECK_GT(length, 0); 1011 crypto::ScopedOpenSSLBytes scoped_buffer(buffer); 1012 public_key->assign(reinterpret_cast<char*>(buffer), length); 1013 } 1014 } 1015 1016 bool TrunksClientTest::VerifyRSASignature(const std::string& public_key, 1017 const std::string& data, 1018 const std::string& signature) { 1019 auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data()); 1020 crypto::ScopedRSA rsa(d2i_RSAPublicKey(nullptr, &asn1_ptr, 1021 public_key.size())); 1022 CHECK(rsa.get()); 1023 std::string digest = crypto::SHA256HashString(data); 1024 auto digest_buffer = reinterpret_cast<const unsigned char*>(digest.data()); 1025 std::string mutable_signature(signature); 1026 unsigned char* signature_buffer = 1027 reinterpret_cast<unsigned char*>(string_as_array(&mutable_signature)); 1028 return (RSA_verify(NID_sha256, digest_buffer, digest.size(), 1029 signature_buffer, signature.size(), rsa.get()) == 1); 1030 } 1031 1032 bool TrunksClientTest::LoadSigningKey(ScopedKeyHandle* key_handle, 1033 std::string* public_key) { 1034 std::string modulus; 1035 std::string prime_factor; 1036 GenerateRSAKeyPair(&modulus, &prime_factor, public_key); 1037 std::string key_blob; 1038 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 1039 TPM_RC result = utility->ImportRSAKey( 1040 TpmUtility::AsymmetricKeyUsage::kSignKey, 1041 modulus, 0x10001, prime_factor, 1042 "", // password 1043 factory_->GetPasswordAuthorization("").get(), 1044 &key_blob); 1045 if (result != TPM_RC_SUCCESS) { 1046 LOG(ERROR) << "ImportRSAKey: " << GetErrorString(result); 1047 return false; 1048 } 1049 TPM_HANDLE raw_key_handle; 1050 result = utility->LoadKey(key_blob, 1051 factory_->GetPasswordAuthorization("").get(), 1052 &raw_key_handle); 1053 if (result != TPM_RC_SUCCESS) { 1054 LOG(ERROR) << "LoadKey: " << GetErrorString(result); 1055 return false; 1056 } 1057 key_handle->reset(raw_key_handle); 1058 return true; 1059 } 1060 1061 bool TrunksClientTest::SignAndVerify(const ScopedKeyHandle& key_handle, 1062 const std::string& public_key, 1063 AuthorizationDelegate* delegate) { 1064 std::string signature; 1065 std::string data_to_sign("sign_this"); 1066 scoped_ptr<TpmUtility> utility = factory_->GetTpmUtility(); 1067 TPM_RC result = utility->Sign(key_handle.get(), 1068 TPM_ALG_RSASSA, 1069 TPM_ALG_SHA256, 1070 data_to_sign, 1071 delegate, 1072 &signature); 1073 if (result != TPM_RC_SUCCESS) { 1074 LOG(ERROR) << "Sign: " << GetErrorString(result); 1075 return false; 1076 } 1077 if (!VerifyRSASignature(public_key, data_to_sign, signature)) { 1078 LOG(ERROR) << "Signature verification failed: " << GetOpenSSLError(); 1079 return false; 1080 } 1081 return true; 1082 } 1083 1084 } // namespace trunks 1085