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