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