trunks_client_test.cc revision 9caf492818a4cc51ba471534d3fcaa84c9ce0278
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 = 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
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 = 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
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(),
164                                     key_authorization,
165                                     session.get());
166}
167
168bool 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
198bool 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
240bool 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
297bool 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
363bool 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
400bool 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
511bool 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
675bool 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
821bool 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
888bool 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
923bool 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
957bool 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
988void 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
1016bool 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
1032bool 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
1061bool 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