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