d0f76ac45b36a58cb748a7f64deca9c7d616d70b
[strongswan.git] / src / libtpmtss / tpm_tss_tss2.c
1 /*
2 * Copyright (C) 2016 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "tpm_tss_tss2.h"
17 #include "tpm_tss_tss2_names.h"
18
19 #ifdef TSS_TSS2
20
21 #include <asn1/asn1.h>
22 #include <asn1/oid.h>
23 #include <bio/bio_reader.h>
24
25 #include <tpm20.h>
26 #include <tcti_socket.h>
27
28 #define LABEL "TPM 2.0 -"
29
30 typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t;
31
32 /**
33 * Private data of an tpm_tss_tss2_t object.
34 */
35 struct private_tpm_tss_tss2_t {
36
37 /**
38 * Public tpm_tss_tss2_t interface.
39 */
40 tpm_tss_t public;
41
42 /**
43 * TCTI context
44 */
45 TSS2_TCTI_CONTEXT *tcti_context;
46
47 /**
48 * SYS context
49 */
50 TSS2_SYS_CONTEXT *sys_context;
51
52 /**
53 * Number of supported algorithms
54 */
55 size_t supported_algs_count;
56
57 /**
58 * List of supported algorithms
59 */
60 TPM_ALG_ID supported_algs[TPM_PT_ALGORITHM_SET];
61 };
62
63 /**
64 * Some symbols required by libtctisocket
65 */
66 FILE *outFp;
67 uint8_t simulator = 1;
68
69 int TpmClientPrintf (uint8_t type, const char *format, ...)
70 {
71 return 0;
72 }
73
74 /**
75 * Convert hash algorithm to TPM_ALG_ID
76 */
77 static TPM_ALG_ID hash_alg_to_tpm_alg_id(hash_algorithm_t alg)
78 {
79 switch (alg)
80 {
81 case HASH_SHA1:
82 return TPM_ALG_SHA1;
83 case HASH_SHA256:
84 return TPM_ALG_SHA256;
85 case HASH_SHA384:
86 return TPM_ALG_SHA384;
87 case HASH_SHA512:
88 return TPM_ALG_SHA512;
89 default:
90 return TPM_ALG_ERROR;
91 }
92 }
93
94 /**
95 * Convert TPM_ALG_ID to hash algorithm
96 */
97 static hash_algorithm_t hash_alg_from_tpm_alg_id(TPM_ALG_ID alg)
98 {
99 switch (alg)
100 {
101 case TPM_ALG_SHA1:
102 return HASH_SHA1;
103 case TPM_ALG_SHA256:
104 return HASH_SHA256;
105 case TPM_ALG_SHA384:
106 return HASH_SHA384;
107 case TPM_ALG_SHA512:
108 return HASH_SHA512;
109 default:
110 return HASH_UNKNOWN;
111 }
112 }
113
114 /**
115 * Check if an algorithm given by its TPM_ALG_ID is supported by the TPM
116 */
117 static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM_ALG_ID alg_id)
118 {
119 int i;
120
121 if (alg_id == TPM_ALG_ERROR)
122 {
123 return FALSE;
124 }
125
126 for (i = 0; i < this->supported_algs_count; i++)
127 {
128 if (this->supported_algs[i] == alg_id)
129 {
130 return TRUE;
131 }
132 }
133
134 return FALSE;
135 }
136
137 /**
138 * Get a list of supported algorithms
139 */
140 static bool get_algs_capability(private_tpm_tss_tss2_t *this)
141 {
142 TPMS_CAPABILITY_DATA cap_data;
143 TPMI_YES_NO more_data;
144 TPM_ALG_ID alg;
145 uint32_t rval, i;
146 size_t len = BUF_LEN;
147 char buf[BUF_LEN];
148 char *pos = buf;
149 int written;
150
151 /* get supported algorithms */
152 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ALGS,
153 0, TPM_PT_ALGORITHM_SET, &more_data, &cap_data, 0);
154 if (rval != TPM_RC_SUCCESS)
155 {
156 DBG1(DBG_PTS, "%s GetCapability failed for TPM_CAP_ALGS: 0x%06x",
157 LABEL, rval);
158 return FALSE;
159 }
160
161 /* Number of supported algorithms */
162 this->supported_algs_count = cap_data.data.algorithms.count;
163
164 /* store and print supported algorithms */
165 for (i = 0; i < this->supported_algs_count; i++)
166 {
167 alg = cap_data.data.algorithms.algProperties[i].alg;
168 this->supported_algs[i] = alg;
169
170 written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
171 if (written < 0 || written >= len)
172 {
173 break;
174 }
175 pos += written;
176 len -= written;
177 }
178 DBG2(DBG_PTS, "%s algorithms:%s", LABEL, buf);
179
180 /* get supported ECC curves */
181 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ECC_CURVES,
182 0, TPM_PT_LOADED_CURVES, &more_data, &cap_data, 0);
183 if (rval != TPM_RC_SUCCESS)
184 {
185 DBG1(DBG_PTS, "%s GetCapability failed for TPM_ECC_CURVES: 0x%06x",
186 LABEL, rval);
187 return FALSE;
188 }
189
190 /* reset print buffer */
191 pos = buf;
192 len = BUF_LEN;
193
194 /* print supported ECC curves */
195 for (i = 0; i < cap_data.data.eccCurves.count; i++)
196 {
197 written = snprintf(pos, len, " %N", tpm_ecc_curve_names,
198 cap_data.data.eccCurves.eccCurves[i]);
199 if (written < 0 || written >= len)
200 {
201 break;
202 }
203 pos += written;
204 len -= written;
205 }
206 DBG2(DBG_PTS, "%s ECC curves:%s", LABEL, buf);
207
208 return TRUE;
209 }
210
211 /**
212 * Initialize TSS context
213 */
214 static bool initialize_context(private_tpm_tss_tss2_t *this)
215 {
216 size_t tcti_context_size;
217 uint32_t sys_context_size;
218 uint32_t rval;
219
220 TCTI_SOCKET_CONF rm_if_config = { DEFAULT_HOSTNAME,
221 DEFAULT_RESMGR_TPM_PORT
222 };
223
224 TSS2_ABI_VERSION abi_version = { TSSWG_INTEROP,
225 TSS_SAPI_FIRST_FAMILY,
226 TSS_SAPI_FIRST_LEVEL,
227 TSS_SAPI_FIRST_VERSION
228 };
229
230 /* determine size of tcti context */
231 rval = InitSocketTcti(NULL, &tcti_context_size, &rm_if_config, 0);
232 if (rval != TSS2_RC_SUCCESS)
233 {
234 DBG1(DBG_PTS, "%s could not get tcti_context size: 0x%06x",
235 LABEL, rval);
236 return FALSE;
237 }
238
239 /* allocate memory for tcti context */
240 this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
241
242 /* initialize tcti context */
243 rval = InitSocketTcti(this->tcti_context, &tcti_context_size,
244 &rm_if_config, 0);
245 if (rval != TSS2_RC_SUCCESS)
246 {
247 DBG1(DBG_PTS, "%s could not get tcti_context: 0x%06x",
248 LABEL, rval);
249 return FALSE;
250 }
251
252 /* determine size of sys context */
253 sys_context_size = Tss2_Sys_GetContextSize(0);
254
255 /* allocate memory for sys context */
256 this->sys_context = malloc(sys_context_size);
257
258 /* initialize sys context */
259 rval = Tss2_Sys_Initialize(this->sys_context, sys_context_size,
260 this->tcti_context, &abi_version);
261 if (rval != TSS2_RC_SUCCESS)
262 {
263 DBG1(DBG_PTS, "%s could not get sys_context: 0x%06x",
264 LABEL, rval);
265 return FALSE;
266 }
267
268 /* get a list of supported algorithms and ECC curves */
269 return get_algs_capability(this);
270 }
271
272 /**
273 * Finalize TSS context
274 */
275 static void finalize_context(private_tpm_tss_tss2_t *this)
276 {
277 if (this->tcti_context)
278 {
279 tss2_tcti_finalize(this->tcti_context);
280 free(this->tcti_context);
281 }
282 if (this->sys_context)
283 {
284 Tss2_Sys_Finalize(this->sys_context);
285 free(this->sys_context);
286 }
287 }
288
289 METHOD(tpm_tss_t, get_version, tpm_version_t,
290 private_tpm_tss_tss2_t *this)
291 {
292 return TPM_VERSION_2_0;
293 }
294
295 METHOD(tpm_tss_t, get_version_info, chunk_t,
296 private_tpm_tss_tss2_t *this)
297 {
298 return chunk_empty;
299 }
300
301 /**
302 * read the public key portion of a TSS 2.0 AIK key from NVRAM
303 */
304 bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
305 TPM2B_PUBLIC *public)
306 {
307 uint32_t rval;
308
309 TPM2B_NAME name = { { sizeof(TPM2B_NAME)-2, } };
310 TPM2B_NAME qualified_name = { { sizeof(TPM2B_NAME)-2, } };
311
312 TPMS_AUTH_RESPONSE session_data;
313 TSS2_SYS_RSP_AUTHS sessions_data;
314 TPMS_AUTH_RESPONSE *session_data_array[1];
315
316 session_data_array[0] = &session_data;
317 sessions_data.rspAuths = &session_data_array[0];
318 sessions_data.rspAuthsCount = 1;
319
320 /* always send simulator platform command, ignored by true RM */
321 PlatformCommand(this->tcti_context ,MS_SIM_POWER_ON );
322 PlatformCommand(this->tcti_context, MS_SIM_NV_ON );
323
324 /* read public key for a given object handle from TPM 2.0 NVRAM */
325 rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
326 &qualified_name, &sessions_data);
327
328 PlatformCommand(this->tcti_context, MS_SIM_POWER_OFF);
329
330 if (rval != TPM_RC_SUCCESS)
331 {
332 DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x",
333 LABEL, handle, rval);
334 return FALSE;
335 }
336 return TRUE;
337 }
338
339 METHOD(tpm_tss_t, generate_aik, bool,
340 private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
341 chunk_t *aik_pubkey, chunk_t *identity_req)
342 {
343 return FALSE;
344 }
345
346 METHOD(tpm_tss_t, get_public, chunk_t,
347 private_tpm_tss_tss2_t *this, uint32_t handle)
348 {
349 TPM2B_PUBLIC public = { { 0, } };
350 TPM_ALG_ID sig_alg, digest_alg;
351 chunk_t aik_blob, aik_pubkey = chunk_empty;
352
353 if (!read_public(this, handle, &public))
354 {
355 return chunk_empty;
356 }
357
358 aik_blob = chunk_create((u_char*)&public, sizeof(public));
359 DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_blob);
360
361 /* convert TSS 2.0 AIK public key blot into PKCS#1 format */
362 switch (public.t.publicArea.type)
363 {
364 case TPM_ALG_RSA:
365 {
366 TPM2B_PUBLIC_KEY_RSA *rsa;
367 TPMT_RSA_SCHEME *scheme;
368 chunk_t aik_exponent, aik_modulus;
369
370 scheme = &public.t.publicArea.parameters.rsaDetail.scheme;
371 sig_alg = scheme->scheme;
372 digest_alg = scheme->details.anySig.hashAlg;
373
374 rsa = &public.t.publicArea.unique.rsa;
375 aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size);
376 aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
377
378 /* subjectPublicKeyInfo encoding of AIK RSA key */
379 if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
380 NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
381 CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
382 {
383 DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key "
384 "failed", LABEL);
385 }
386 break;
387 }
388 case TPM_ALG_ECC:
389 {
390 TPMS_ECC_POINT *ecc;
391 TPMT_ECC_SCHEME *scheme;
392 chunk_t ecc_point;
393 uint8_t *pos;
394
395 scheme = &public.t.publicArea.parameters.eccDetail.scheme;
396 sig_alg = scheme->scheme;
397 digest_alg = scheme->details.anySig.hashAlg;
398
399 ecc = &public.t.publicArea.unique.ecc;
400
401 /* allocate space for bit string */
402 pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
403 2 + ecc->x.t.size + ecc->y.t.size);
404 /* bit string length is a multiple of octets */
405 *pos++ = 0x00;
406 /* uncompressed ECC point format */
407 *pos++ = 0x04;
408 /* copy x coordinate of ECC point */
409 memcpy(pos, ecc->x.t.buffer, ecc->x.t.size);
410 pos += ecc->x.t.size;
411 /* copy y coordinate of ECC point */
412 memcpy(pos, ecc->y.t.buffer, ecc->y.t.size);
413 /* subjectPublicKeyInfo encoding of AIK ECC key */
414 aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
415 asn1_wrap(ASN1_SEQUENCE, "mm",
416 asn1_build_known_oid(OID_EC_PUBLICKEY),
417 asn1_build_known_oid(ecc->x.t.size == 32 ?
418 OID_PRIME256V1 : OID_SECT384R1)),
419 ecc_point);
420 break;
421 }
422 default:
423 DBG1(DBG_PTS, "%s unsupported AIK key type", LABEL);
424 return chunk_empty;
425 }
426 DBG1(DBG_PTS, "AIK signature algorithm is %N with %N hash",
427 tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
428 return aik_pubkey;
429 }
430
431 /**
432 * Configure a PCR Selection assuming a maximum of 24 registers
433 */
434 static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
435 hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
436 {
437 TPM_ALG_ID alg_id;
438 uint32_t pcr;
439
440 /* check if hash algorithm is supported by TPM */
441 alg_id = hash_alg_to_tpm_alg_id(alg);
442 if (!is_supported_alg(this, alg_id))
443 {
444 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
445 LABEL, hash_algorithm_short_names, alg);
446 return FALSE;
447 }
448
449 /* initialize the PCR Selection structure,*/
450 pcr_sel->count = 1;
451 pcr_sel->pcrSelections[0].hash = alg_id;
452 pcr_sel->pcrSelections[0].sizeofSelect = 3;
453 pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
454 pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
455 pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
456
457 /* set the selected PCRs */
458 for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
459 {
460 if (pcrs & (1 << pcr))
461 {
462 pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
463 }
464 }
465 return TRUE;
466 }
467
468 METHOD(tpm_tss_t, read_pcr, bool,
469 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
470 hash_algorithm_t alg)
471 {
472 TPML_PCR_SELECTION pcr_selection;
473 TPML_DIGEST pcr_values;
474
475 uint32_t pcr_update_counter, rval;
476 uint8_t *pcr_value_ptr;
477 size_t pcr_value_len;
478
479 if (pcr_num >= PLATFORM_PCR)
480 {
481 DBG1(DBG_PTS, "%s maximum number of supported PCR is %d",
482 LABEL, PLATFORM_PCR);
483 return FALSE;
484 }
485
486 if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
487 {
488 return FALSE;
489 }
490
491 /* initialize the PCR Digest structure */
492 memset(&pcr_values, 0, sizeof(TPML_DIGEST));
493
494 /* read the PCR value */
495 rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
496 &pcr_update_counter, &pcr_selection, &pcr_values, 0);
497 if (rval != TPM_RC_SUCCESS)
498 {
499 DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x",
500 LABEL, rval);
501 return FALSE;
502 }
503 pcr_value_ptr = (uint8_t *)pcr_values.digests[0].t.buffer;
504 pcr_value_len = (size_t) pcr_values.digests[0].t.size;
505
506 *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
507
508 return TRUE;
509 }
510
511 METHOD(tpm_tss_t, extend_pcr, bool,
512 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
513 chunk_t data, hash_algorithm_t alg)
514 {
515 /* TODO */
516 return FALSE;
517 }
518
519 METHOD(tpm_tss_t, quote, bool,
520 private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
521 hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
522 tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
523 {
524 chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
525 firmware_version, pcr_select, pcr_digest;
526 hash_algorithm_t pcr_digest_alg;
527 bio_reader_t *reader;
528 uint32_t rval;
529
530 TPM2B_DATA qualifying_data;
531 TPML_PCR_SELECTION pcr_selection;
532 TPM2B_ATTEST quoted = { { sizeof(TPM2B_ATTEST)-2, } };
533 TPMT_SIG_SCHEME scheme;
534 TPMT_SIGNATURE sig;
535 TPMI_ALG_HASH hash_alg;
536 TPMS_AUTH_COMMAND session_data_cmd;
537 TPMS_AUTH_RESPONSE session_data_rsp;
538 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
539 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
540 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
541 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
542
543 session_data_cmd_array[0] = &session_data_cmd;
544 session_data_rsp_array[0] = &session_data_rsp;
545
546 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
547 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
548
549 sessions_data_cmd.cmdAuthsCount = 1;
550 sessions_data_rsp.rspAuthsCount = 1;
551
552 session_data_cmd.sessionHandle = TPM_RS_PW;
553 session_data_cmd.hmac.t.size = 0;
554 session_data_cmd.nonce.t.size = 0;
555
556 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
557
558 qualifying_data.t.size = data.len;
559 memcpy(qualifying_data.t.buffer, data.ptr, data.len);
560
561 scheme.scheme = TPM_ALG_NULL;
562 memset(&sig, 0x00, sizeof(sig));
563
564 /* set Quote mode */
565 *quote_mode = TPM_QUOTE_TPM2;
566
567 if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
568 {
569 return FALSE;
570 }
571
572 rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &sessions_data_cmd,
573 &qualifying_data, &scheme, &pcr_selection, &quoted,
574 &sig, &sessions_data_rsp);
575 if (rval != TPM_RC_SUCCESS)
576 {
577 DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval);
578 return FALSE;
579 }
580 quoted_chunk = chunk_create(quoted.t.attestationData, quoted.t.size);
581
582 reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
583 if (!reader->read_data16(reader, &qualified_signer) ||
584 !reader->read_data16(reader, &extra_data) ||
585 !reader->read_data (reader, 17, &clock_info) ||
586 !reader->read_data (reader, 8, &firmware_version) ||
587 !reader->read_data (reader, 10, &pcr_select) ||
588 !reader->read_data16(reader, &pcr_digest))
589 {
590 DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL);
591 reader->destroy(reader);
592 return FALSE;
593 }
594 reader->destroy(reader);
595
596 DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
597 DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
598 DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
599 DBG2(DBG_PTS, "extraData: %B", &extra_data);
600 DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
601 DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
602 DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
603
604 /* extract signature */
605 switch (sig.sigAlg)
606 {
607 case TPM_ALG_RSASSA:
608 case TPM_ALG_RSAPSS:
609 *quote_sig = chunk_clone(
610 chunk_create(
611 sig.signature.rsassa.sig.t.buffer,
612 sig.signature.rsassa.sig.t.size));
613 hash_alg = sig.signature.rsassa.hash;
614 break;
615 case TPM_ALG_ECDSA:
616 case TPM_ALG_ECDAA:
617 case TPM_ALG_SM2:
618 case TPM_ALG_ECSCHNORR:
619 *quote_sig = chunk_cat("cc",
620 chunk_create(
621 sig.signature.ecdsa.signatureR.t.buffer,
622 sig.signature.ecdsa.signatureR.t.size),
623 chunk_create(
624 sig.signature.ecdsa.signatureS.t.buffer,
625 sig.signature.ecdsa.signatureS.t.size));
626 hash_alg = sig.signature.ecdsa.hash;
627 break;
628 default:
629 DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
630 LABEL, tpm_alg_id_names, sig.sigAlg);
631 return FALSE;
632 };
633
634 DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
635 pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
636
637 DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
638
639 /* Create and initialize Quote Info object */
640 *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
641 pcr_digest);
642 (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
643 pcr_select);
644 (*quote_info)->set_version_info(*quote_info, firmware_version);
645
646 return TRUE;
647 }
648
649 METHOD(tpm_tss_t, destroy, void,
650 private_tpm_tss_tss2_t *this)
651 {
652 finalize_context(this);
653 free(this);
654 }
655
656 /**
657 * See header
658 */
659 tpm_tss_t *tpm_tss_tss2_create()
660 {
661 private_tpm_tss_tss2_t *this;
662 bool available;
663
664 INIT(this,
665 .public = {
666 .get_version = _get_version,
667 .get_version_info = _get_version_info,
668 .generate_aik = _generate_aik,
669 .get_public = _get_public,
670 .read_pcr = _read_pcr,
671 .extend_pcr = _extend_pcr,
672 .quote = _quote,
673 .destroy = _destroy,
674 },
675 );
676
677 available = initialize_context(this);
678 DBG1(DBG_PTS, "TPM 2.0 via TSS2 %savailable", available ? "" : "not ");
679
680 if (!available)
681 {
682 destroy(this);
683 return NULL;
684 }
685 return &this->public;
686 }
687
688 #else /* TSS_TSS2 */
689
690 tpm_tss_t *tpm_tss_tss2_create()
691 {
692 return NULL;
693 }
694
695 #endif /* TSS_TSS2 */
696
697