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 "attestation/common/tpm_utility_v1.h"
18
19 #include <base/files/file_path.h>
20 #include <base/files/file_util.h>
21 #include <base/logging.h>
22 #include <base/memory/scoped_ptr.h>
23 #include <base/stl_util.h>
24 #include <crypto/scoped_openssl_types.h>
25 #include <crypto/sha2.h>
26 #include <openssl/rsa.h>
27 #include <openssl/sha.h>
28 #include <trousers/scoped_tss_type.h>
29 #include <trousers/trousers.h>
30 #include <trousers/tss.h>
31
32 #define TPM_LOG(severity, result) \
33 LOG(severity) << "TPM error 0x" << std::hex << result \
34 << " (" << Trspi_Error_String(result) << "): "
35
36 using trousers::ScopedTssContext;
37 using trousers::ScopedTssKey;
38 using trousers::ScopedTssMemory;
39 using trousers::ScopedTssPcrs;
40
41 namespace {
42
43 using ScopedByteArray = scoped_ptr<BYTE, base::FreeDeleter>;
44 using ScopedTssEncryptedData = trousers::ScopedTssObject<TSS_HENCDATA>;
45 using ScopedTssHash = trousers::ScopedTssObject<TSS_HHASH>;
46
47 const char* kTpmTpmEnabledFile = "/sys/class/tpm/tpm0/device/enabled";
48 const char* kMscTpmEnabledFile = "/sys/class/misc/tpm0/device/enabled";
49 const char* kTpmTpmOwnedFile = "/sys/class/tpm/tpm0/device/owned";
50 const char* kMscTpmOwnedFile = "/sys/class/misc/tpm0/device/owned";
51 const unsigned int kWellKnownExponent = 65537;
52 const unsigned char kSha256DigestInfo[] = {
53 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
54 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
55 };
56
GetFirstByte(const char * file_name)57 std::string GetFirstByte(const char* file_name) {
58 std::string content;
59 base::ReadFileToString(base::FilePath(file_name), &content);
60 if (content.size() > 1) {
61 content.resize(1);
62 }
63 return content;
64 }
65
StringAsTSSBuffer(std::string * s)66 BYTE* StringAsTSSBuffer(std::string* s) {
67 return reinterpret_cast<BYTE*>(string_as_array(s));
68 }
69
TSSBufferAsString(const BYTE * buffer,size_t length)70 std::string TSSBufferAsString(const BYTE* buffer, size_t length) {
71 return std::string(reinterpret_cast<const char*>(buffer), length);
72 }
73
74 } // namespace
75
76 namespace attestation {
77
~TpmUtilityV1()78 TpmUtilityV1::~TpmUtilityV1() {}
79
Initialize()80 bool TpmUtilityV1::Initialize() {
81 if (!ConnectContext(&context_handle_, &tpm_handle_)) {
82 LOG(ERROR) << __func__ << ": Failed to connect to the TPM.";
83 return false;
84 }
85 if (!IsTpmReady()) {
86 LOG(WARNING) << __func__ << ": TPM is not owned; attestation services will "
87 << "not be available until ownership is taken.";
88 }
89 return true;
90 }
91
IsTpmReady()92 bool TpmUtilityV1::IsTpmReady() {
93 if (!is_ready_) {
94 if (base::PathExists(base::FilePath(kMscTpmEnabledFile))) {
95 is_ready_ = (GetFirstByte(kMscTpmEnabledFile) == "1" &&
96 GetFirstByte(kMscTpmOwnedFile) == "1");
97 } else {
98 is_ready_ = (GetFirstByte(kTpmTpmEnabledFile) == "1" &&
99 GetFirstByte(kTpmTpmOwnedFile) == "1");
100 }
101 }
102 return is_ready_;
103 }
104
ActivateIdentity(const std::string & delegate_blob,const std::string & delegate_secret,const std::string & identity_key_blob,const std::string & asym_ca_contents,const std::string & sym_ca_attestation,std::string * credential)105 bool TpmUtilityV1::ActivateIdentity(const std::string& delegate_blob,
106 const std::string& delegate_secret,
107 const std::string& identity_key_blob,
108 const std::string& asym_ca_contents,
109 const std::string& sym_ca_attestation,
110 std::string* credential) {
111 CHECK(credential);
112 if (!SetupSrk()) {
113 LOG(ERROR) << "SRK is not ready.";
114 return false;
115 }
116
117 // Connect to the TPM as the owner delegate.
118 ScopedTssContext context_handle;
119 TSS_HTPM tpm_handle;
120 if (!ConnectContextAsDelegate(delegate_blob, delegate_secret,
121 &context_handle, &tpm_handle)) {
122 LOG(ERROR) << __func__ << ": Could not connect to the TPM.";
123 return false;
124 }
125 // Load the Storage Root Key.
126 TSS_RESULT result;
127 ScopedTssKey srk_handle(context_handle);
128 if (!LoadSrk(context_handle, &srk_handle)) {
129 LOG(ERROR) << __func__ << ": Failed to load SRK.";
130 return false;
131 }
132 // Load the AIK (which is wrapped by the SRK).
133 std::string mutable_identity_key_blob(identity_key_blob);
134 BYTE* identity_key_blob_buffer = StringAsTSSBuffer(
135 &mutable_identity_key_blob);
136 ScopedTssKey identity_key(context_handle);
137 result = Tspi_Context_LoadKeyByBlob(
138 context_handle,
139 srk_handle,
140 identity_key_blob.size(),
141 identity_key_blob_buffer,
142 identity_key.ptr());
143 if (TPM_ERROR(result)) {
144 TPM_LOG(ERROR, result) << __func__ << ": Failed to load AIK.";
145 return false;
146 }
147 std::string mutable_asym_ca_contents(asym_ca_contents);
148 BYTE* asym_ca_contents_buffer = StringAsTSSBuffer(&mutable_asym_ca_contents);
149 std::string mutable_sym_ca_attestation(sym_ca_attestation);
150 BYTE* sym_ca_attestation_buffer = StringAsTSSBuffer(
151 &mutable_sym_ca_attestation);
152 UINT32 credential_length = 0;
153 ScopedTssMemory credential_buffer(context_handle);
154 result = Tspi_TPM_ActivateIdentity(tpm_handle, identity_key,
155 asym_ca_contents.size(),
156 asym_ca_contents_buffer,
157 sym_ca_attestation.size(),
158 sym_ca_attestation_buffer,
159 &credential_length,
160 credential_buffer.ptr());
161 if (TPM_ERROR(result)) {
162 TPM_LOG(ERROR, result) << __func__ << ": Failed to activate identity.";
163 return false;
164 }
165 credential->assign(TSSBufferAsString(credential_buffer.value(),
166 credential_length));
167 return true;
168 }
169
CreateCertifiedKey(KeyType key_type,KeyUsage key_usage,const std::string & identity_key_blob,const std::string & external_data,std::string * key_blob,std::string * public_key,std::string * public_key_tpm_format,std::string * key_info,std::string * proof)170 bool TpmUtilityV1::CreateCertifiedKey(KeyType key_type,
171 KeyUsage key_usage,
172 const std::string& identity_key_blob,
173 const std::string& external_data,
174 std::string* key_blob,
175 std::string* public_key,
176 std::string* public_key_tpm_format,
177 std::string* key_info,
178 std::string* proof) {
179 CHECK(key_blob && public_key && public_key_tpm_format && key_info && proof);
180 if (!SetupSrk()) {
181 LOG(ERROR) << "SRK is not ready.";
182 return false;
183 }
184 if (key_type != KEY_TYPE_RSA) {
185 LOG(ERROR) << "Only RSA supported on TPM v1.2.";
186 return false;
187 }
188
189 // Load the AIK (which is wrapped by the SRK).
190 ScopedTssKey identity_key(context_handle_);
191 if (!LoadKeyFromBlob(identity_key_blob, context_handle_, srk_handle_,
192 &identity_key)) {
193 LOG(ERROR) << __func__ << "Failed to load AIK.";
194 return false;
195 }
196
197 // Create a non-migratable RSA key.
198 ScopedTssKey key(context_handle_);
199 UINT32 tss_key_type = (key_usage == KEY_USAGE_SIGN) ? TSS_KEY_TYPE_SIGNING :
200 TSS_KEY_TYPE_BIND;
201 UINT32 init_flags = tss_key_type |
202 TSS_KEY_NOT_MIGRATABLE |
203 TSS_KEY_VOLATILE |
204 TSS_KEY_NO_AUTHORIZATION |
205 TSS_KEY_SIZE_2048;
206 TSS_RESULT result = Tspi_Context_CreateObject(context_handle_,
207 TSS_OBJECT_TYPE_RSAKEY,
208 init_flags, key.ptr());
209 if (TPM_ERROR(result)) {
210 TPM_LOG(ERROR, result) << __func__ << ": Failed to create object.";
211 return false;
212 }
213 if (key_usage == KEY_USAGE_SIGN) {
214 result = Tspi_SetAttribUint32(key,
215 TSS_TSPATTRIB_KEY_INFO,
216 TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
217 TSS_SS_RSASSAPKCS1V15_DER);
218 } else {
219 result = Tspi_SetAttribUint32(key,
220 TSS_TSPATTRIB_KEY_INFO,
221 TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
222 TSS_ES_RSAESOAEP_SHA1_MGF1);
223 }
224 if (TPM_ERROR(result)) {
225 TPM_LOG(ERROR, result) << __func__ << ": Failed to set scheme.";
226 return false;
227 }
228 result = Tspi_Key_CreateKey(key, srk_handle_, 0);
229 if (TPM_ERROR(result)) {
230 TPM_LOG(ERROR, result) << __func__ << ": Failed to create key.";
231 return false;
232 }
233 result = Tspi_Key_LoadKey(key, srk_handle_);
234 if (TPM_ERROR(result)) {
235 TPM_LOG(ERROR, result) << __func__ << ": Failed to load key.";
236 return false;
237 }
238
239 // Certify the key.
240 TSS_VALIDATION validation;
241 memset(&validation, 0, sizeof(validation));
242 validation.ulExternalDataLength = external_data.size();
243 std::string mutable_external_data(external_data);
244 validation.rgbExternalData = StringAsTSSBuffer(&mutable_external_data);
245 result = Tspi_Key_CertifyKey(key, identity_key, &validation);
246 if (TPM_ERROR(result)) {
247 TPM_LOG(ERROR, result) << __func__ << ": Failed to certify key.";
248 return false;
249 }
250 ScopedTssMemory scoped_certified_data(0, validation.rgbData);
251 ScopedTssMemory scoped_proof(0, validation.rgbValidationData);
252
253 // Get the certified public key.
254 if (!GetDataAttribute(context_handle_,
255 key,
256 TSS_TSPATTRIB_KEY_BLOB,
257 TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY,
258 public_key_tpm_format)) {
259 LOG(ERROR) << __func__ << ": Failed to read public key.";
260 return false;
261 }
262 if (!ConvertPublicKeyToDER(*public_key_tpm_format, public_key)) {
263 return false;
264 }
265
266 // Get the certified key blob so we can load it later.
267 if (!GetDataAttribute(context_handle_,
268 key,
269 TSS_TSPATTRIB_KEY_BLOB,
270 TSS_TSPATTRIB_KEYBLOB_BLOB,
271 key_blob)) {
272 LOG(ERROR) << __func__ << ": Failed to read key blob.";
273 return false;
274 }
275
276 // Get the data that was certified.
277 key_info->assign(TSSBufferAsString(validation.rgbData,
278 validation.ulDataLength));
279
280 // Get the certification proof.
281 proof->assign(TSSBufferAsString(validation.rgbValidationData,
282 validation.ulValidationDataLength));
283 return true;
284 }
285
SealToPCR0(const std::string & data,std::string * sealed_data)286 bool TpmUtilityV1::SealToPCR0(const std::string& data,
287 std::string* sealed_data) {
288 CHECK(sealed_data);
289 if (!SetupSrk()) {
290 LOG(ERROR) << "SRK is not ready.";
291 return false;
292 }
293
294 // Create a PCRS object which holds the value of PCR0.
295 ScopedTssPcrs pcrs_handle(context_handle_);
296 TSS_RESULT result;
297 if (TPM_ERROR(result = Tspi_Context_CreateObject(context_handle_,
298 TSS_OBJECT_TYPE_PCRS,
299 TSS_PCRS_STRUCT_INFO,
300 pcrs_handle.ptr()))) {
301 TPM_LOG(ERROR, result)
302 << __func__ << ": Error calling Tspi_Context_CreateObject";
303 return false;
304 }
305 UINT32 pcr_length = 0;
306 ScopedTssMemory pcr_value(context_handle_);
307 Tspi_TPM_PcrRead(tpm_handle_, 0, &pcr_length, pcr_value.ptr());
308 Tspi_PcrComposite_SetPcrValue(pcrs_handle, 0, pcr_length, pcr_value.value());
309
310 // Create a ENCDATA object to receive the sealed data.
311 ScopedTssKey encrypted_data_handle(context_handle_);
312 if (TPM_ERROR(result = Tspi_Context_CreateObject(
313 context_handle_,
314 TSS_OBJECT_TYPE_ENCDATA,
315 TSS_ENCDATA_SEAL,
316 encrypted_data_handle.ptr()))) {
317 TPM_LOG(ERROR, result)
318 << __func__ << ": Error calling Tspi_Context_CreateObject";
319 return false;
320 }
321
322 // Seal the given value with the SRK.
323 std::string mutable_data(data);
324 BYTE* data_buffer = StringAsTSSBuffer(&mutable_data);
325 if (TPM_ERROR(result = Tspi_Data_Seal(
326 encrypted_data_handle,
327 srk_handle_,
328 data.size(),
329 data_buffer,
330 pcrs_handle))) {
331 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Data_Seal";
332 return false;
333 }
334
335 // Extract the sealed value.
336 ScopedTssMemory encrypted_data(context_handle_);
337 UINT32 encrypted_data_length = 0;
338 if (TPM_ERROR(result = Tspi_GetAttribData(encrypted_data_handle,
339 TSS_TSPATTRIB_ENCDATA_BLOB,
340 TSS_TSPATTRIB_ENCDATABLOB_BLOB,
341 &encrypted_data_length,
342 encrypted_data.ptr()))) {
343 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_GetAttribData";
344 return false;
345 }
346 sealed_data->assign(TSSBufferAsString(encrypted_data.value(),
347 encrypted_data_length));
348 return true;
349 }
350
Unseal(const std::string & sealed_data,std::string * data)351 bool TpmUtilityV1::Unseal(const std::string& sealed_data, std::string* data) {
352 CHECK(data);
353 if (!SetupSrk()) {
354 LOG(ERROR) << "SRK is not ready.";
355 return false;
356 }
357
358 // Create an ENCDATA object with the sealed value.
359 ScopedTssKey encrypted_data_handle(context_handle_);
360 TSS_RESULT result;
361 if (TPM_ERROR(result = Tspi_Context_CreateObject(
362 context_handle_,
363 TSS_OBJECT_TYPE_ENCDATA,
364 TSS_ENCDATA_SEAL,
365 encrypted_data_handle.ptr()))) {
366 TPM_LOG(ERROR, result)
367 << __func__ << ": Error calling Tspi_Context_CreateObject";
368 return false;
369 }
370
371 std::string mutable_sealed_data(sealed_data);
372 BYTE* sealed_data_buffer = StringAsTSSBuffer(&mutable_sealed_data);
373 if (TPM_ERROR(result = Tspi_SetAttribData(encrypted_data_handle,
374 TSS_TSPATTRIB_ENCDATA_BLOB,
375 TSS_TSPATTRIB_ENCDATABLOB_BLOB,
376 sealed_data.size(),
377 sealed_data_buffer))) {
378 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_SetAttribData";
379 return false;
380 }
381
382 // Unseal using the SRK.
383 ScopedTssMemory decrypted_data(context_handle_);
384 UINT32 decrypted_data_length = 0;
385 if (TPM_ERROR(result = Tspi_Data_Unseal(encrypted_data_handle,
386 srk_handle_,
387 &decrypted_data_length,
388 decrypted_data.ptr()))) {
389 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Data_Unseal";
390 return false;
391 }
392 data->assign(TSSBufferAsString(decrypted_data.value(),
393 decrypted_data_length));
394 return true;
395 }
396
GetEndorsementPublicKey(std::string * public_key)397 bool TpmUtilityV1::GetEndorsementPublicKey(std::string* public_key) {
398 // Get a handle to the EK public key.
399 ScopedTssKey ek_public_key_object(context_handle_);
400 TSS_RESULT result = Tspi_TPM_GetPubEndorsementKey(tpm_handle_, false, nullptr,
401 ek_public_key_object.ptr());
402 if (TPM_ERROR(result)) {
403 TPM_LOG(ERROR, result) << __func__ << ": Failed to get key.";
404 return false;
405 }
406 // Get the public key in TPM_PUBKEY form.
407 std::string ek_public_key_blob;
408 if (!GetDataAttribute(context_handle_,
409 ek_public_key_object,
410 TSS_TSPATTRIB_KEY_BLOB,
411 TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY,
412 &ek_public_key_blob)) {
413 LOG(ERROR) << __func__ << ": Failed to read public key.";
414 return false;
415 }
416 // Get the public key in DER encoded form.
417 if (!ConvertPublicKeyToDER(ek_public_key_blob, public_key)) {
418 return false;
419 }
420 return true;
421 }
422
Unbind(const std::string & key_blob,const std::string & bound_data,std::string * data)423 bool TpmUtilityV1::Unbind(const std::string& key_blob,
424 const std::string& bound_data,
425 std::string* data) {
426 CHECK(data);
427 if (!SetupSrk()) {
428 LOG(ERROR) << "SRK is not ready.";
429 return false;
430 }
431 ScopedTssKey key_handle(context_handle_);
432 if (!LoadKeyFromBlob(key_blob, context_handle_, srk_handle_, &key_handle)) {
433 return false;
434 }
435 TSS_RESULT result;
436 ScopedTssEncryptedData data_handle(context_handle_);
437 if (TPM_ERROR(result = Tspi_Context_CreateObject(context_handle_,
438 TSS_OBJECT_TYPE_ENCDATA,
439 TSS_ENCDATA_BIND,
440 data_handle.ptr()))) {
441 TPM_LOG(ERROR, result) << __func__ << ": Tspi_Context_CreateObject failed.";
442 return false;
443 }
444 std::string mutable_bound_data(bound_data);
445 if (TPM_ERROR(result = Tspi_SetAttribData(
446 data_handle,
447 TSS_TSPATTRIB_ENCDATA_BLOB,
448 TSS_TSPATTRIB_ENCDATABLOB_BLOB,
449 bound_data.size(),
450 StringAsTSSBuffer(&mutable_bound_data)))) {
451 TPM_LOG(ERROR, result) << __func__ << ": Tspi_SetAttribData failed.";
452 return false;
453 }
454
455 ScopedTssMemory decrypted_data(context_handle_);
456 UINT32 length = 0;
457 if (TPM_ERROR(result = Tspi_Data_Unbind(data_handle, key_handle,
458 &length, decrypted_data.ptr()))) {
459 TPM_LOG(ERROR, result) << __func__ << ": Tspi_Data_Unbind failed.";
460 return false;
461 }
462 data->assign(TSSBufferAsString(decrypted_data.value(), length));
463 return true;
464 }
465
Sign(const std::string & key_blob,const std::string & data_to_sign,std::string * signature)466 bool TpmUtilityV1::Sign(const std::string& key_blob,
467 const std::string& data_to_sign,
468 std::string* signature) {
469 CHECK(signature);
470 if (!SetupSrk()) {
471 LOG(ERROR) << "SRK is not ready.";
472 return false;
473 }
474 ScopedTssKey key_handle(context_handle_);
475 if (!LoadKeyFromBlob(key_blob, context_handle_, srk_handle_, &key_handle)) {
476 return false;
477 }
478 // Construct an ASN.1 DER DigestInfo.
479 std::string digest_to_sign(std::begin(kSha256DigestInfo),
480 std::end(kSha256DigestInfo));
481 digest_to_sign += crypto::SHA256HashString(data_to_sign);
482 // Create a hash object to hold the digest.
483 ScopedTssHash hash_handle(context_handle_);
484 TSS_RESULT result = Tspi_Context_CreateObject(context_handle_,
485 TSS_OBJECT_TYPE_HASH,
486 TSS_HASH_OTHER,
487 hash_handle.ptr());
488 if (TPM_ERROR(result)) {
489 TPM_LOG(ERROR, result) << __func__ << ": Failed to create hash object.";
490 return false;
491 }
492 result = Tspi_Hash_SetHashValue(hash_handle,
493 digest_to_sign.size(),
494 StringAsTSSBuffer(&digest_to_sign));
495 if (TPM_ERROR(result)) {
496 TPM_LOG(ERROR, result) << __func__ << ": Failed to set hash data.";
497 return false;
498 }
499 UINT32 length = 0;
500 ScopedTssMemory buffer(context_handle_);
501 result = Tspi_Hash_Sign(hash_handle, key_handle, &length, buffer.ptr());
502 if (TPM_ERROR(result)) {
503 TPM_LOG(ERROR, result) << __func__ << ": Failed to generate signature.";
504 return false;
505 }
506 signature->assign(TSSBufferAsString(buffer.value(), length));
507 return true;
508 }
509
ConnectContext(ScopedTssContext * context,TSS_HTPM * tpm)510 bool TpmUtilityV1::ConnectContext(ScopedTssContext* context, TSS_HTPM* tpm) {
511 *tpm = 0;
512 TSS_RESULT result;
513 if (TPM_ERROR(result = Tspi_Context_Create(context->ptr()))) {
514 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Context_Create";
515 return false;
516 }
517 if (TPM_ERROR(result = Tspi_Context_Connect(*context, nullptr))) {
518 TPM_LOG(ERROR, result) << __func__
519 << ": Error calling Tspi_Context_Connect";
520 return false;
521 }
522 if (TPM_ERROR(result = Tspi_Context_GetTpmObject(*context, tpm))) {
523 TPM_LOG(ERROR, result) << __func__
524 << ": Error calling Tspi_Context_GetTpmObject";
525 return false;
526 }
527 return true;
528 }
529
ConnectContextAsDelegate(const std::string & delegate_blob,const std::string & delegate_secret,ScopedTssContext * context,TSS_HTPM * tpm)530 bool TpmUtilityV1::ConnectContextAsDelegate(const std::string& delegate_blob,
531 const std::string& delegate_secret,
532 ScopedTssContext* context,
533 TSS_HTPM* tpm) {
534 *tpm = 0;
535 if (!ConnectContext(context, tpm)) {
536 return false;
537 }
538 TSS_RESULT result;
539 TSS_HPOLICY tpm_usage_policy;
540 if (TPM_ERROR(result = Tspi_GetPolicyObject(*tpm,
541 TSS_POLICY_USAGE,
542 &tpm_usage_policy))) {
543 TPM_LOG(ERROR, result) << __func__
544 << ": Error calling Tspi_GetPolicyObject";
545 return false;
546 }
547 std::string mutable_delegate_secret(delegate_secret);
548 BYTE* secret_buffer = StringAsTSSBuffer(&mutable_delegate_secret);
549 if (TPM_ERROR(result = Tspi_Policy_SetSecret(tpm_usage_policy,
550 TSS_SECRET_MODE_PLAIN,
551 delegate_secret.size(),
552 secret_buffer))) {
553 TPM_LOG(ERROR, result) << __func__
554 << ": Error calling Tspi_Policy_SetSecret";
555 return false;
556 }
557 std::string mutable_delegate_blob(delegate_blob);
558 BYTE* blob_buffer = StringAsTSSBuffer(&mutable_delegate_blob);
559 if (TPM_ERROR(result = Tspi_SetAttribData(
560 tpm_usage_policy,
561 TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
562 TSS_TSPATTRIB_POLDEL_OWNERBLOB,
563 delegate_blob.size(),
564 blob_buffer))) {
565 TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_SetAttribData";
566 return false;
567 }
568 return true;
569 }
570
SetupSrk()571 bool TpmUtilityV1::SetupSrk() {
572 if (!IsTpmReady()) {
573 return false;
574 }
575 if (srk_handle_) {
576 return true;
577 }
578 srk_handle_.reset(context_handle_, 0);
579 if (!LoadSrk(context_handle_, &srk_handle_)) {
580 LOG(ERROR) << __func__ << ": Failed to load SRK.";
581 return false;
582 }
583 // In order to wrap a key with the SRK we need access to the SRK public key
584 // and we need to get it manually. Once it's in the key object, we don't need
585 // to do this again.
586 UINT32 length = 0;
587 ScopedTssMemory buffer(context_handle_);
588 TSS_RESULT result;
589 result = Tspi_Key_GetPubKey(srk_handle_, &length, buffer.ptr());
590 if (result != TSS_SUCCESS) {
591 TPM_LOG(INFO, result) << __func__ << ": Failed to read SRK public key.";
592 return false;
593 }
594 return true;
595 }
596
LoadSrk(TSS_HCONTEXT context_handle,ScopedTssKey * srk_handle)597 bool TpmUtilityV1::LoadSrk(TSS_HCONTEXT context_handle,
598 ScopedTssKey* srk_handle) {
599 TSS_RESULT result;
600 TSS_UUID uuid = TSS_UUID_SRK;
601 if (TPM_ERROR(result = Tspi_Context_LoadKeyByUUID(context_handle,
602 TSS_PS_TYPE_SYSTEM,
603 uuid,
604 srk_handle->ptr()))) {
605 TPM_LOG(ERROR, result) << __func__
606 << ": Error calling Tspi_Context_LoadKeyByUUID";
607 return false;
608 }
609 // Check if the SRK wants a password.
610 UINT32 auth_usage;
611 if (TPM_ERROR(result = Tspi_GetAttribUint32(*srk_handle,
612 TSS_TSPATTRIB_KEY_INFO,
613 TSS_TSPATTRIB_KEYINFO_AUTHUSAGE,
614 &auth_usage))) {
615 TPM_LOG(ERROR, result) << __func__
616 << ": Error calling Tspi_GetAttribUint32";
617 return false;
618 }
619 if (auth_usage) {
620 // Give it an empty password if needed.
621 TSS_HPOLICY usage_policy;
622 if (TPM_ERROR(result = Tspi_GetPolicyObject(*srk_handle,
623 TSS_POLICY_USAGE,
624 &usage_policy))) {
625 TPM_LOG(ERROR, result) << __func__
626 << ": Error calling Tspi_GetPolicyObject";
627 return false;
628 }
629
630 BYTE empty_password[] = {};
631 if (TPM_ERROR(result = Tspi_Policy_SetSecret(usage_policy,
632 TSS_SECRET_MODE_PLAIN,
633 0, empty_password))) {
634 TPM_LOG(ERROR, result) << __func__
635 << ": Error calling Tspi_Policy_SetSecret";
636 return false;
637 }
638 }
639 return true;
640 }
641
LoadKeyFromBlob(const std::string & key_blob,TSS_HCONTEXT context_handle,TSS_HKEY parent_key_handle,ScopedTssKey * key_handle)642 bool TpmUtilityV1::LoadKeyFromBlob(const std::string& key_blob,
643 TSS_HCONTEXT context_handle,
644 TSS_HKEY parent_key_handle,
645 ScopedTssKey* key_handle) {
646 std::string mutable_key_blob(key_blob);
647 BYTE* key_blob_buffer = StringAsTSSBuffer(&mutable_key_blob);
648 TSS_RESULT result = Tspi_Context_LoadKeyByBlob(
649 context_handle,
650 parent_key_handle,
651 key_blob.size(),
652 key_blob_buffer,
653 key_handle->ptr());
654 if (TPM_ERROR(result)) {
655 TPM_LOG(ERROR, result) << __func__ << ": Failed to load key by blob.";
656 return false;
657 }
658 return true;
659 }
660
GetDataAttribute(TSS_HCONTEXT context,TSS_HOBJECT object,TSS_FLAG flag,TSS_FLAG sub_flag,std::string * data)661 bool TpmUtilityV1::GetDataAttribute(TSS_HCONTEXT context,
662 TSS_HOBJECT object,
663 TSS_FLAG flag,
664 TSS_FLAG sub_flag,
665 std::string* data) {
666 UINT32 length = 0;
667 ScopedTssMemory buffer(context);
668 TSS_RESULT result = Tspi_GetAttribData(object, flag, sub_flag, &length,
669 buffer.ptr());
670 if (TPM_ERROR(result)) {
671 TPM_LOG(ERROR, result) << __func__ << "Failed to read object attribute.";
672 return false;
673 }
674 data->assign(TSSBufferAsString(buffer.value(), length));
675 return true;
676 }
677
ConvertPublicKeyToDER(const std::string & public_key,std::string * public_key_der)678 bool TpmUtilityV1::ConvertPublicKeyToDER(const std::string& public_key,
679 std::string* public_key_der) {
680 // Parse the serialized TPM_PUBKEY.
681 UINT64 offset = 0;
682 std::string mutable_public_key(public_key);
683 BYTE* buffer = StringAsTSSBuffer(&mutable_public_key);
684 TPM_PUBKEY parsed;
685 TSS_RESULT result = Trspi_UnloadBlob_PUBKEY(&offset, buffer, &parsed);
686 if (TPM_ERROR(result)) {
687 TPM_LOG(ERROR, result) << "Failed to parse TPM_PUBKEY.";
688 return false;
689 }
690 ScopedByteArray scoped_key(parsed.pubKey.key);
691 ScopedByteArray scoped_parms(parsed.algorithmParms.parms);
692 TPM_RSA_KEY_PARMS* parms =
693 reinterpret_cast<TPM_RSA_KEY_PARMS*>(parsed.algorithmParms.parms);
694 crypto::ScopedRSA rsa(RSA_new());
695 CHECK(rsa.get());
696 // Get the public exponent.
697 if (parms->exponentSize == 0) {
698 rsa.get()->e = BN_new();
699 CHECK(rsa.get()->e);
700 BN_set_word(rsa.get()->e, kWellKnownExponent);
701 } else {
702 rsa.get()->e = BN_bin2bn(parms->exponent, parms->exponentSize, nullptr);
703 CHECK(rsa.get()->e);
704 }
705 // Get the modulus.
706 rsa.get()->n = BN_bin2bn(parsed.pubKey.key, parsed.pubKey.keyLength, nullptr);
707 CHECK(rsa.get()->n);
708
709 // DER encode.
710 int der_length = i2d_RSAPublicKey(rsa.get(), nullptr);
711 if (der_length < 0) {
712 LOG(ERROR) << "Failed to DER-encode public key.";
713 return false;
714 }
715 public_key_der->resize(der_length);
716 unsigned char* der_buffer = reinterpret_cast<unsigned char*>(
717 string_as_array(public_key_der));
718 der_length = i2d_RSAPublicKey(rsa.get(), &der_buffer);
719 if (der_length < 0) {
720 LOG(ERROR) << "Failed to DER-encode public key.";
721 return false;
722 }
723 public_key_der->resize(der_length);
724 return true;
725 }
726
727 } // namespace attestation
728