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