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