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