8be3ad8778b7ec93db7e0c071609651ef1fccfd1
[strongswan.git] / src / libtpmtss / tpm_tss_trousers.c
1 /*
2 * Copyright (C) 2016 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (c) 2008 Hal Finney
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26 #include "tpm_tss_trousers.h"
27
28 #ifdef TSS_TROUSERS
29
30 #ifdef _BASETSD_H_
31 /* MinGW defines _BASETSD_H_, but TSS checks for _BASETSD_H */
32 # define _BASETSD_H
33 #endif
34
35 #include <trousers/tss.h>
36 #include <trousers/trousers.h>
37
38 #define LABEL "TPM 1.2 -"
39
40 /* size in bytes of a TSS AIK public key blob */
41 #define AIK_PUBKEY_BLOB_SIZE 284
42
43 /* maximum number of PCR registers */
44 #define PCR_NUM_MAX 24
45
46 typedef struct private_tpm_tss_trousers_t private_tpm_tss_trousers_t;
47 typedef struct aik_t aik_t;
48
49 /**
50 * Private data of an tpm_tss_trousers_t object.
51 */
52 struct private_tpm_tss_trousers_t {
53
54 /**
55 * Public tpm_tss_trousers_t interface.
56 */
57 tpm_tss_trousers_t interface;
58
59 /**
60 * TSS context
61 */
62 TSS_HCONTEXT hContext;
63
64 /**
65 * TPM handle
66 */
67 TSS_HTPM hTPM;
68
69 /**
70 * TPM version info
71 */
72 chunk_t version_info;
73
74 /**
75 * List of AIKs retrievable by an object handle
76 */
77 linked_list_t *aik_list;
78
79 };
80
81 struct aik_t {
82 /** AIK object handle */
83 uint32_t handle;
84
85 /** AIK private key blob */
86 chunk_t blob;
87
88 /** AIK public key */
89 chunk_t pubkey;
90 };
91
92 static void free_aik(aik_t *this)
93 {
94 free(this->blob.ptr);
95 free(this->pubkey.ptr);
96 free(this);
97 }
98
99 /**
100 * Initialize TSS context
101 *
102 * TPM 1.2 Specification, Part 2 TPM Structures, 21.6 TPM_CAP_VERSION_INFO
103 *
104 * typedef struct tdTPM_VERSION {
105 * TPM_VERSION_BYTE major;
106 * TPM_VERSION_BYTE minor;
107 * BYTE revMajor;
108 * BYTE revMinor;
109 * } TPM_VERSION;
110 *
111 * typedef struct tdTPM_CAP_VERSION_INFO {
112 * TPM_STRUCTURE_TAG tag;
113 * TPM_VERSION version;
114 * UINT16 specLevel;
115 * BYTE errataRev;
116 * BYTE tpmVendorID[4];
117 * UINT16 vendorSpecificSize;
118 * [size_is(vendorSpecificSize)] BYTE* vendorSpecific;
119 * } TPM_CAP_VERSION_INFO;
120 */
121 static bool initialize_context(private_tpm_tss_trousers_t *this)
122 {
123 uint8_t *version_ptr;
124 uint32_t version_len;
125
126 TSS_RESULT result;
127 TPM_CAP_VERSION_INFO *info;
128
129 result = Tspi_Context_Create(&this->hContext);
130 if (result != TSS_SUCCESS)
131 {
132 DBG1(DBG_PTS, "%s could not created context: 0x%x",
133 LABEL, result);
134 return FALSE;
135 }
136
137 result = Tspi_Context_Connect(this->hContext, NULL);
138 if (result != TSS_SUCCESS)
139 {
140 DBG1(DBG_PTS, "%s could not connect with context: 0x%x",
141 LABEL, result);
142 return FALSE;
143 }
144
145 result = Tspi_Context_GetTpmObject (this->hContext, &this->hTPM);
146 if (result != TSS_SUCCESS)
147 {
148 DBG1(DBG_PTS, "%s could not get TPM object: 0x%x",
149 LABEL, result);
150 return FALSE;
151 }
152
153 result = Tspi_TPM_GetCapability(this->hTPM, TSS_TPMCAP_VERSION_VAL, 0,
154 NULL, &version_len, &version_ptr);
155 if (result != TSS_SUCCESS)
156 {
157 DBG1(DBG_PTS, "%s Tspi_TPM_GetCapability failed: 0x%x",
158 LABEL, result);
159 return FALSE;
160 }
161
162 info = (TPM_CAP_VERSION_INFO *)version_ptr;
163 DBG2(DBG_PTS, "TPM Version Info: Chip Version: %u.%u.%u.%u, "
164 "Spec Level: %u, Errata Rev: %u, Vendor ID: %.4s",
165 info->version.major, info->version.minor,
166 info->version.revMajor, info->version.revMinor,
167 untoh16(&info->specLevel), info->errataRev, info->tpmVendorID);
168
169 this->version_info = chunk_clone(chunk_create(version_ptr, version_len));
170
171 return TRUE;
172 }
173
174 /**
175 * Finalize TSS context
176 */
177 static void finalize_context(private_tpm_tss_trousers_t *this)
178 {
179 if (this->hContext)
180 {
181 Tspi_Context_FreeMemory(this->hContext, NULL);
182 Tspi_Context_Close(this->hContext);
183 }
184 }
185
186 METHOD(tpm_tss_t, get_version, tpm_version_t,
187 private_tpm_tss_trousers_t *this)
188 {
189 return TPM_VERSION_1_2;
190 }
191
192 METHOD(tpm_tss_t, get_version_info, chunk_t,
193 private_tpm_tss_trousers_t *this)
194 {
195 return this->version_info;
196 }
197
198 METHOD(tpm_tss_t, generate_aik, bool,
199 private_tpm_tss_trousers_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
200 chunk_t *aik_pubkey, chunk_t *identity_req)
201 {
202 chunk_t aik_pubkey_blob;
203 chunk_t aik_modulus;
204 chunk_t aik_exponent;
205
206 TSS_RESULT result;
207 TSS_HKEY hSRK;
208 TSS_HKEY hPCAKey;
209 TSS_HPOLICY hSrkPolicy;
210 TSS_HPOLICY hTPMPolicy;
211 TSS_HKEY hIdentKey;
212 TSS_UUID SRK_UUID = TSS_UUID_SRK;
213 BYTE secret[] = TSS_WELL_KNOWN_SECRET;
214 BYTE *IdentityReq;
215 UINT32 IdentityReqLen;
216 BYTE *blob;
217 UINT32 blobLen;
218
219 /* get SRK plus SRK policy and set SRK secret */
220 result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM,
221 SRK_UUID, &hSRK);
222 if (result != TSS_SUCCESS)
223 {
224 DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByUUID for SRK failed: 0x%x",
225 LABEL, result);
226 return FALSE;
227 }
228 result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSrkPolicy);
229 if (result != TSS_SUCCESS)
230 {
231 DBG1(DBG_PTS, "%s Tspi_GetPolicyObject or SRK failed: 0x%x ",
232 LABEL, result);
233 return FALSE;
234 }
235 result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
236 if (result != TSS_SUCCESS)
237 {
238 DBG1(DBG_PTS, "%s Tspi_Policy_SetSecret for SRK failed: 0x%x ",
239 LABEL, result);
240 return FALSE;
241 }
242
243 /* get TPM plus TPM policy and set TPM secret */
244 result = Tspi_Context_GetTpmObject (this->hContext, &this->hTPM);
245 if (result != TSS_SUCCESS)
246 {
247 DBG1(DBG_PTS, "%s Tspi_Context_GetTpmObject failed: 0x%x",
248 LABEL, result);
249 return FALSE;
250 }
251 result = Tspi_GetPolicyObject(this->hTPM, TSS_POLICY_USAGE, &hTPMPolicy);
252 if (result != TSS_SUCCESS)
253 {
254 DBG1(DBG_PTS, "%s Tspi_GetPolicyObject for TPM failed: 0x%x",
255 LABEL, result);
256 return FALSE;
257 }
258 result = Tspi_Policy_SetSecret(hTPMPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
259 if (result != TSS_SUCCESS)
260 {
261 DBG1(DBG_PTS,"%s Tspi_Policy_SetSecret for TPM failed: 0x%x",
262 LABEL, result);
263 return FALSE;
264 }
265
266 /* create context for a 2048 bit AIK */
267 result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY,
268 TSS_KEY_TYPE_IDENTITY | TSS_KEY_SIZE_2048 |
269 TSS_KEY_VOLATILE | TSS_KEY_NOT_MIGRATABLE, &hIdentKey);
270 if (result != TSS_SUCCESS)
271 {
272 DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for key failed: 0x%x",
273 LABEL, result);
274 return FALSE;
275 }
276
277 /* create context for the Privacy CA public key and assign modulus */
278 result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY,
279 TSS_KEY_TYPE_LEGACY|TSS_KEY_SIZE_2048, &hPCAKey);
280 if (result != TSS_SUCCESS)
281 {
282 DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for PCA failed: 0x%x",
283 LABEL, result);
284 return FALSE;
285 }
286 result = Tspi_SetAttribData (hPCAKey, TSS_TSPATTRIB_RSAKEY_INFO,
287 TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, ca_modulus.len,
288 ca_modulus.ptr);
289 if (result != TSS_SUCCESS)
290 {
291 DBG1(DBG_PTS, "%s Tspi_SetAttribData for PCA modulus failed: 0x%x",
292 LABEL, result);
293 return FALSE;
294 }
295 result = Tspi_SetAttribUint32(hPCAKey, TSS_TSPATTRIB_KEY_INFO,
296 TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15);
297 if (result != TSS_SUCCESS)
298 {
299 DBG1(DBG_PTS,"%s Tspi_SetAttribUint32 for PCA encryption scheme "
300 "failed: 0x%x", LABEL, result);
301 return FALSE;
302 }
303
304 /* generate AIK */
305 DBG1(DBG_LIB, "Generating identity key...");
306 result = Tspi_TPM_CollateIdentityRequest(this->hTPM, hSRK, hPCAKey, 0, NULL,
307 hIdentKey, TSS_ALG_AES, &IdentityReqLen, &IdentityReq);
308 if (result != TSS_SUCCESS)
309 {
310 DBG1(DBG_PTS, "%s Tspi_TPM_CollateIdentityRequest failed: 0x%x",
311 LABEL, result);
312 return FALSE;
313 }
314 *identity_req = chunk_create(IdentityReq, IdentityReqLen);
315 DBG3(DBG_LIB, "%s Identity Request: %B", LABEL, identity_req);
316
317 /* load identity key */
318 result = Tspi_Key_LoadKey (hIdentKey, hSRK);
319 if (result != TSS_SUCCESS)
320 {
321 DBG1(DBG_PTS, "%s Tspi_Key_LoadKey for AIK failed: 0x%x",
322 LABEL, result);
323 return FALSE;
324 }
325
326 /* output AIK private key in TSS blob format */
327 result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
328 TSS_TSPATTRIB_KEYBLOB_BLOB, &blobLen, &blob);
329 if (result != TSS_SUCCESS)
330 {
331 DBG1(DBG_PTS, "%s Tspi_GetAttribData for private key blob failed: 0x%x",
332 LABEL, result);
333 return FALSE;
334 }
335 *aik_blob = chunk_create(blob, blobLen);
336 DBG3(DBG_LIB, "%s AIK private key blob: %B", LABEL, aik_blob);
337
338 /* output AIK Public Key in TSS blob format */
339 result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
340 TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blobLen, &blob);
341 if (result != TSS_SUCCESS)
342 {
343 DBG1(DBG_PTS, "%s Tspi_GetAttribData for public key blob failed: 0x%x",
344 LABEL, result);
345 return FALSE;
346 }
347 aik_pubkey_blob = chunk_create(blob, blobLen);
348 DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_pubkey_blob);
349
350 /* create a trusted AIK public key */
351 if (aik_pubkey_blob.len != AIK_PUBKEY_BLOB_SIZE)
352 {
353 DBG1(DBG_PTS, "%s AIK public key is not in TSS blob format",
354 LABEL);
355 return FALSE;
356 }
357 aik_modulus = chunk_skip(aik_pubkey_blob, AIK_PUBKEY_BLOB_SIZE - 256);
358 aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
359
360 /* output subjectPublicKeyInfo encoding of AIK public key */
361 if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, NULL,
362 aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
363 CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
364 {
365 DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key failed",
366 LABEL);
367 return FALSE;
368 }
369 return TRUE;
370 }
371
372 METHOD(tpm_tss_t, get_public, chunk_t,
373 private_tpm_tss_trousers_t *this, uint32_t handle)
374 {
375 enumerator_t *enumerator;
376 chunk_t aik_pubkey = chunk_empty;
377 aik_t *aik;
378
379 enumerator = this->aik_list->create_enumerator(this->aik_list);
380 while (enumerator->enumerate(enumerator, &aik))
381 {
382 if (aik->handle == handle)
383 {
384 aik_pubkey = chunk_clone(aik->pubkey);
385 break;
386 }
387 }
388 enumerator->destroy(enumerator);
389
390 return aik_pubkey;
391 }
392
393 METHOD(tpm_tss_t, read_pcr, bool,
394 private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value,
395 hash_algorithm_t alg)
396 {
397 TSS_RESULT result;
398 uint8_t *value;
399 uint32_t len;
400
401 result = Tspi_TPM_PcrRead(this->hTPM, pcr_num, &len, &value);
402 if (result != TSS_SUCCESS)
403 {
404 DBG1(DBG_PTS, "%s Tspi_TPM_PcrRead failed: 0x%x", LABEL, result);
405 return FALSE;
406 }
407 *pcr_value = chunk_clone(chunk_create(value, len));
408
409 return TRUE;
410 }
411
412 METHOD(tpm_tss_t, extend_pcr, bool,
413 private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value,
414 chunk_t data, hash_algorithm_t alg)
415 {
416 TSS_RESULT result;
417 uint32_t pcr_len;
418 uint8_t *pcr_ptr;
419
420 result = Tspi_TPM_PcrExtend(this->hTPM, pcr_num, data.len, data.ptr,
421 NULL, &pcr_len, &pcr_ptr);
422 if (result != TSS_SUCCESS)
423 {
424 DBG1(DBG_PTS, "%s Tspi_TPM_PcrExtend failed: 0x%x", LABEL, result);
425 return FALSE;
426 }
427 *pcr_value = chunk_clone(chunk_create(pcr_ptr, pcr_len));
428
429 return TRUE;
430 }
431
432 METHOD(tpm_tss_t, quote, bool,
433 private_tpm_tss_trousers_t *this, uint32_t aik_handle, uint32_t pcr_sel,
434 hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
435 tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
436 {
437 TSS_HKEY hAIK;
438 TSS_HKEY hSRK;
439 TSS_HPOLICY srkUsagePolicy;
440 TSS_UUID SRK_UUID = TSS_UUID_SRK;
441 TSS_HPCRS hPcrComposite;
442 TSS_VALIDATION valData;
443 TSS_RESULT result;
444 uint8_t secret[] = TSS_WELL_KNOWN_SECRET;
445 uint8_t *version_info, *comp_hash;
446 uint32_t version_info_size, pcr;
447 aik_t *aik;
448 chunk_t aik_blob = chunk_empty;
449 chunk_t quote_chunk, pcr_digest;
450 enumerator_t *enumerator;
451 bool success = FALSE;
452
453 /* Retrieve SRK from TPM and set the authentication to well known secret*/
454 result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM,
455 SRK_UUID, &hSRK);
456 if (result != TSS_SUCCESS)
457 {
458 DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByUUID for SRK failed: 0x%x",
459 LABEL, result);
460 return FALSE;
461 }
462 result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &srkUsagePolicy);
463 if (result != TSS_SUCCESS)
464 {
465 DBG1(DBG_PTS, "%s Tspi_GetPolicyObject for SRK failed: 0x%x",
466 LABEL, result);
467 return FALSE;
468 }
469 result = Tspi_Policy_SetSecret(srkUsagePolicy, TSS_SECRET_MODE_SHA1,
470 20, secret);
471 if (result != TSS_SUCCESS)
472 {
473 DBG1(DBG_PTS, "%s Tspi_Policy_SetSecret for SRK failed: 0x%x",
474 LABEL, result);
475 return FALSE;
476 }
477
478 /* Retrieve AIK using its handle and load private key into TPM 1.2 */
479 enumerator = this->aik_list->create_enumerator(this->aik_list);
480 while (enumerator->enumerate(enumerator, &aik))
481 {
482 if (aik->handle == aik_handle)
483 {
484 aik_blob = aik->blob;
485 break;
486 }
487 }
488 enumerator->destroy(enumerator);
489
490 if (aik_blob.len == 0)
491 {
492 DBG1(DBG_PTS, "%s AIK private key for handle 0x%80x not found", LABEL);
493 return FALSE;
494 }
495 result = Tspi_Context_LoadKeyByBlob(this->hContext, hSRK, aik_blob.len,
496 aik_blob.ptr, &hAIK);
497 if (result != TSS_SUCCESS)
498 {
499 DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByBlob for AIK failed: 0x%x",
500 LABEL, result);
501 return FALSE;
502 }
503
504 /* Create PCR composite object */
505 result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_PCRS,
506 (*quote_mode == TPM_QUOTE) ? TSS_PCRS_STRUCT_INFO :
507 TSS_PCRS_STRUCT_INFO_SHORT,
508 &hPcrComposite);
509 if (result != TSS_SUCCESS)
510 {
511 DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for pcrComposite failed: "
512 "0x%x", LABEL, result);
513 goto err1;
514 }
515
516 /* Select PCRs */
517 for (pcr = 0; pcr < PCR_NUM_MAX; pcr++)
518 {
519 if (pcr_sel & (1 << pcr))
520 {
521 result = (*quote_mode == TPM_QUOTE) ?
522 Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr) :
523 Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
524 TSS_PCRS_DIRECTION_RELEASE);
525 if (result != TSS_SUCCESS)
526 {
527 DBG1(DBG_PTS, "%s Tspi_PcrComposite_SelectPcrIndex failed: "
528 "0x%x", LABEL, result);
529 goto err2;
530 }
531 }
532 }
533
534 /* Set the Validation Data */
535 valData.ulExternalDataLength = data.len;
536 valData.rgbExternalData = data.ptr;
537
538 /* TPM Quote */
539 result = (*quote_mode == TPM_QUOTE) ?
540 Tspi_TPM_Quote (this->hTPM, hAIK, hPcrComposite, &valData) :
541 Tspi_TPM_Quote2(this->hTPM, hAIK,
542 *quote_mode == TPM_QUOTE2_VERSION_INFO,
543 hPcrComposite, &valData, &version_info_size,
544 &version_info);
545 if (result != TSS_SUCCESS)
546 {
547 DBG1(DBG_PTS, "%s Tspi_TPM_Quote%s failed: 0x%x", LABEL,
548 (*quote_mode == TPM_QUOTE) ? "" : "2", result);
549 goto err2;
550 }
551
552 if (*quote_mode == TPM_QUOTE)
553 {
554 /* TPM_Composite_Hash starts at byte 8 of TPM_Quote_Info structure */
555 comp_hash = valData.rgbData + 8;
556 }
557 else
558 {
559 /* TPM_Composite_Hash is last 20 bytes of TPM_Quote_Info2 structure */
560 comp_hash = valData.rgbData + valData.ulDataLength - version_info_size -
561 HASH_SIZE_SHA1;
562 }
563 pcr_digest = chunk_create(comp_hash, HASH_SIZE_SHA1);
564 DBG2(DBG_PTS, "PCR composite digest: %B", &pcr_digest);
565
566 quote_chunk = chunk_create(valData.rgbData, valData.ulDataLength);
567 DBG2(DBG_PTS, "TPM Quote Info: %B", &quote_chunk);
568
569 *quote_info = tpm_tss_quote_info_create(*quote_mode, HASH_SHA1, pcr_digest);
570
571 *quote_sig = chunk_clone(chunk_create(valData.rgbValidationData,
572 valData.ulValidationDataLength));
573 DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
574
575 success = TRUE;
576
577 err2:
578 Tspi_Context_CloseObject(this->hContext, hPcrComposite);
579 err1:
580 Tspi_Context_CloseObject(this->hContext, hAIK);
581
582 return success;
583 }
584
585 METHOD(tpm_tss_t, destroy, void,
586 private_tpm_tss_trousers_t *this)
587 {
588 finalize_context(this);
589 this->aik_list->destroy_function(this->aik_list, (void*)free_aik);
590 free(this->version_info.ptr);
591 free(this);
592 }
593
594 METHOD(tpm_tss_trousers_t, load_aik, void,
595 private_tpm_tss_trousers_t *this, chunk_t blob, chunk_t pubkey,
596 uint32_t handle)
597 {
598 aik_t *item;
599
600 INIT(item,
601 .handle = handle,
602 .blob = blob,
603 .pubkey = pubkey,
604 );
605
606 this->aik_list->insert_last(this->aik_list, item);
607 }
608
609 /**
610 * See header
611 */
612 tpm_tss_t *tpm_tss_trousers_create()
613 {
614 private_tpm_tss_trousers_t *this;
615 bool available;
616
617 INIT(this,
618 .interface = {
619 .public = {
620 .get_version = _get_version,
621 .get_version_info = _get_version_info,
622 .generate_aik = _generate_aik,
623 .get_public = _get_public,
624 .read_pcr = _read_pcr,
625 .quote = _quote,
626 .extend_pcr = _extend_pcr,
627 .destroy = _destroy,
628 },
629 .load_aik = _load_aik,
630 },
631 .aik_list = linked_list_create(),
632 );
633
634 available = initialize_context(this);
635 DBG1(DBG_PTS, "TPM 1.2 via TrouSerS %savailable", available ? "" : "not ");
636
637 if (!available)
638 {
639 destroy(this);
640 return NULL;
641 }
642 return &this->interface.public;
643 }
644
645 #else /* TSS_TROUSERS */
646
647 tpm_tss_t *tpm_tss_trousers_create()
648 {
649 return NULL;
650 }
651
652 #endif /* TSS_TROUSERS */
653
654
655