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