aikpub2: Output AIK signature algorithm
[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 <tss2/tpm20.h>
26 #include <tcti/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 TeardownSocketTcti(this->tcti_context);
280 }
281 if (this->sys_context)
282 {
283 Tss2_Sys_Finalize(this->sys_context);
284 free(this->sys_context);
285 }
286 }
287
288 METHOD(tpm_tss_t, get_version, tpm_version_t,
289 private_tpm_tss_tss2_t *this)
290 {
291 return TPM_VERSION_2_0;
292 }
293
294 METHOD(tpm_tss_t, get_version_info, chunk_t,
295 private_tpm_tss_tss2_t *this)
296 {
297 return chunk_empty;
298 }
299
300 /**
301 * read the public key portion of a TSS 2.0 AIK key from NVRAM
302 */
303 bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
304 TPM2B_PUBLIC *public)
305 {
306 uint32_t rval;
307
308 TPM2B_NAME name = { { sizeof(TPM2B_NAME)-2, } };
309 TPM2B_NAME qualified_name = { { sizeof(TPM2B_NAME)-2, } };
310
311 TPMS_AUTH_RESPONSE session_data;
312 TSS2_SYS_RSP_AUTHS sessions_data;
313 TPMS_AUTH_RESPONSE *session_data_array[1];
314
315 session_data_array[0] = &session_data;
316 sessions_data.rspAuths = &session_data_array[0];
317 sessions_data.rspAuthsCount = 1;
318
319 /* always send simulator platform command, ignored by true RM */
320 PlatformCommand(this->tcti_context ,MS_SIM_POWER_ON );
321 PlatformCommand(this->tcti_context, MS_SIM_NV_ON );
322
323 /* read public key for a given object handle from TPM 2.0 NVRAM */
324 rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
325 &qualified_name, &sessions_data);
326
327 PlatformCommand(this->tcti_context, MS_SIM_POWER_OFF);
328
329 if (rval != TPM_RC_SUCCESS)
330 {
331 DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x",
332 LABEL, handle, rval);
333 return FALSE;
334 }
335 return TRUE;
336 }
337
338 METHOD(tpm_tss_t, generate_aik, bool,
339 private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
340 chunk_t *aik_pubkey, chunk_t *identity_req)
341 {
342 return FALSE;
343 }
344
345 METHOD(tpm_tss_t, get_public, chunk_t,
346 private_tpm_tss_tss2_t *this, uint32_t handle)
347 {
348 TPM2B_PUBLIC public = { { 0, } };
349 TPM_ALG_ID sig_alg, digest_alg;
350 chunk_t aik_blob, aik_pubkey = chunk_empty;
351
352 if (!read_public(this, handle, &public))
353 {
354 return chunk_empty;
355 }
356
357 aik_blob = chunk_create((u_char*)&public, sizeof(public));
358 DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_blob);
359
360 /* convert TSS 2.0 AIK public key blot into PKCS#1 format */
361 switch (public.t.publicArea.type)
362 {
363 case TPM_ALG_RSA:
364 {
365 TPM2B_PUBLIC_KEY_RSA *rsa;
366 TPMT_RSA_SCHEME *scheme;
367 chunk_t aik_exponent, aik_modulus;
368
369 scheme = &public.t.publicArea.parameters.rsaDetail.scheme;
370 sig_alg = scheme->scheme;
371 digest_alg = scheme->details.anySig.hashAlg;
372
373 rsa = &public.t.publicArea.unique.rsa;
374 aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size);
375 aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
376
377 /* subjectPublicKeyInfo encoding of AIK RSA key */
378 if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
379 NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
380 CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
381 {
382 DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key "
383 "failed", LABEL);
384 }
385 break;
386 }
387 case TPM_ALG_ECC:
388 {
389 TPMS_ECC_POINT *ecc;
390 TPMT_ECC_SCHEME *scheme;
391 chunk_t ecc_point;
392 uint8_t *pos;
393
394 scheme = &public.t.publicArea.parameters.eccDetail.scheme;
395 sig_alg = scheme->scheme;
396 digest_alg = scheme->details.anySig.hashAlg;
397
398 ecc = &public.t.publicArea.unique.ecc;
399
400 /* allocate space for bit string */
401 pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
402 2 + ecc->x.t.size + ecc->y.t.size);
403 /* bit string length is a multiple of octets */
404 *pos++ = 0x00;
405 /* uncompressed ECC point format */
406 *pos++ = 0x04;
407 /* copy x coordinate of ECC point */
408 memcpy(pos, ecc->x.t.buffer, ecc->x.t.size);
409 pos += ecc->x.t.size;
410 /* copy y coordinate of ECC point */
411 memcpy(pos, ecc->y.t.buffer, ecc->y.t.size);
412 /* subjectPublicKeyInfo encoding of AIK ECC key */
413 aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
414 asn1_wrap(ASN1_SEQUENCE, "mm",
415 asn1_build_known_oid(OID_EC_PUBLICKEY),
416 asn1_build_known_oid(ecc->x.t.size == 32 ?
417 OID_PRIME256V1 : OID_SECT384R1)),
418 ecc_point);
419 break;
420 }
421 default:
422 DBG1(DBG_PTS, "%s unsupported AIK key type", LABEL);
423 return chunk_empty;
424 }
425 DBG1(DBG_PTS, "AIK signature algorithm is %N with %N hash",
426 tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
427 return aik_pubkey;
428 }
429
430 /**
431 * Configure a PCR Selection assuming a maximum of 24 registers
432 */
433 static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
434 hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
435 {
436 TPM_ALG_ID alg_id;
437 uint32_t pcr;
438
439 /* check if hash algorithm is supported by TPM */
440 alg_id = hash_alg_to_tpm_alg_id(alg);
441 if (!is_supported_alg(this, alg_id))
442 {
443 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
444 LABEL, hash_algorithm_short_names, alg);
445 return FALSE;
446 }
447
448 /* initialize the PCR Selection structure,*/
449 pcr_sel->count = 1;
450 pcr_sel->pcrSelections[0].hash = alg_id;
451 pcr_sel->pcrSelections[0].sizeofSelect = 3;
452 pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
453 pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
454 pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
455
456 /* set the selected PCRs */
457 for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
458 {
459 if (pcrs & (1 << pcr))
460 {
461 pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
462 }
463 }
464 return TRUE;
465 }
466
467 METHOD(tpm_tss_t, read_pcr, bool,
468 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
469 hash_algorithm_t alg)
470 {
471 TPML_PCR_SELECTION pcr_selection;
472 TPML_DIGEST pcr_values;
473
474 uint32_t pcr_update_counter, rval;
475 uint8_t *pcr_value_ptr;
476 size_t pcr_value_len;
477
478 if (pcr_num >= PLATFORM_PCR)
479 {
480 DBG1(DBG_PTS, "%s maximum number of supported PCR is %d",
481 LABEL, PLATFORM_PCR);
482 return FALSE;
483 }
484
485 if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
486 {
487 return FALSE;
488 }
489
490 /* initialize the PCR Digest structure */
491 memset(&pcr_values, 0, sizeof(TPML_DIGEST));
492
493 /* read the PCR value */
494 rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
495 &pcr_update_counter, &pcr_selection, &pcr_values, 0);
496 if (rval != TPM_RC_SUCCESS)
497 {
498 DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x",
499 LABEL, rval);
500 return FALSE;
501 }
502 pcr_value_ptr = (uint8_t *)pcr_values.digests[0].t.buffer;
503 pcr_value_len = (size_t) pcr_values.digests[0].t.size;
504
505 *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
506
507 return TRUE;
508 }
509
510 METHOD(tpm_tss_t, extend_pcr, bool,
511 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
512 chunk_t data, hash_algorithm_t alg)
513 {
514 /* TODO */
515 return FALSE;
516 }
517
518 METHOD(tpm_tss_t, quote, bool,
519 private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
520 hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
521 tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
522 {
523 chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
524 firmware_version, pcr_select, pcr_digest;
525 hash_algorithm_t pcr_digest_alg;
526 bio_reader_t *reader;
527 uint32_t rval;
528
529 TPM2B_DATA qualifying_data;
530 TPML_PCR_SELECTION pcr_selection;
531 TPM2B_ATTEST quoted = { { sizeof(TPM2B_ATTEST)-2, } };
532 TPMT_SIG_SCHEME scheme;
533 TPMT_SIGNATURE sig;
534 TPMI_ALG_HASH hash_alg;
535 TPMS_AUTH_COMMAND session_data_cmd;
536 TPMS_AUTH_RESPONSE session_data_rsp;
537 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
538 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
539 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
540 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
541
542 session_data_cmd_array[0] = &session_data_cmd;
543 session_data_rsp_array[0] = &session_data_rsp;
544
545 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
546 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
547
548 sessions_data_cmd.cmdAuthsCount = 1;
549 sessions_data_rsp.rspAuthsCount = 1;
550
551 session_data_cmd.sessionHandle = TPM_RS_PW;
552 session_data_cmd.hmac.t.size = 0;
553 session_data_cmd.nonce.t.size = 0;
554
555 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
556
557 qualifying_data.t.size = data.len;
558 memcpy(qualifying_data.t.buffer, data.ptr, data.len);
559
560 scheme.scheme = TPM_ALG_NULL;
561 memset(&sig, 0x00, sizeof(sig));
562
563 /* set Quote mode */
564 *quote_mode = TPM_QUOTE_TPM2;
565
566 if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
567 {
568 return FALSE;
569 }
570
571 rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &sessions_data_cmd,
572 &qualifying_data, &scheme, &pcr_selection, &quoted,
573 &sig, &sessions_data_rsp);
574 if (rval != TPM_RC_SUCCESS)
575 {
576 DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval);
577 return FALSE;
578 }
579 quoted_chunk = chunk_create(quoted.t.attestationData, quoted.t.size);
580
581 reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
582 if (!reader->read_data16(reader, &qualified_signer) ||
583 !reader->read_data16(reader, &extra_data) ||
584 !reader->read_data (reader, 17, &clock_info) ||
585 !reader->read_data (reader, 8, &firmware_version) ||
586 !reader->read_data (reader, 10, &pcr_select) ||
587 !reader->read_data16(reader, &pcr_digest))
588 {
589 DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL);
590 reader->destroy(reader);
591 return FALSE;
592 }
593 reader->destroy(reader);
594
595 DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
596 DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
597 DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
598 DBG2(DBG_PTS, "extraData: %B", &extra_data);
599 DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
600 DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
601 DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
602
603 /* extract signature */
604 switch (sig.sigAlg)
605 {
606 case TPM_ALG_RSASSA:
607 case TPM_ALG_RSAPSS:
608 *quote_sig = chunk_clone(
609 chunk_create(
610 sig.signature.rsassa.sig.t.buffer,
611 sig.signature.rsassa.sig.t.size));
612 hash_alg = sig.signature.rsassa.hash;
613 break;
614 case TPM_ALG_ECDSA:
615 case TPM_ALG_ECDAA:
616 case TPM_ALG_SM2:
617 case TPM_ALG_ECSCHNORR:
618 *quote_sig = chunk_cat("cc",
619 chunk_create(
620 sig.signature.ecdsa.signatureR.t.buffer,
621 sig.signature.ecdsa.signatureR.t.size),
622 chunk_create(
623 sig.signature.ecdsa.signatureS.t.buffer,
624 sig.signature.ecdsa.signatureS.t.size));
625 hash_alg = sig.signature.ecdsa.hash;
626 break;
627 default:
628 DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
629 LABEL, tpm_alg_id_names, sig.sigAlg);
630 return FALSE;
631 };
632
633 DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
634 pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
635
636 DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
637
638 /* Create and initialize Quote Info object */
639 *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
640 pcr_digest);
641 (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
642 pcr_select);
643 (*quote_info)->set_version_info(*quote_info, firmware_version);
644
645 return TRUE;
646 }
647
648 METHOD(tpm_tss_t, destroy, void,
649 private_tpm_tss_tss2_t *this)
650 {
651 finalize_context(this);
652 free(this);
653 }
654
655 /**
656 * See header
657 */
658 tpm_tss_t *tpm_tss_tss2_create()
659 {
660 private_tpm_tss_tss2_t *this;
661 bool available;
662
663 INIT(this,
664 .public = {
665 .get_version = _get_version,
666 .get_version_info = _get_version_info,
667 .generate_aik = _generate_aik,
668 .get_public = _get_public,
669 .read_pcr = _read_pcr,
670 .extend_pcr = _extend_pcr,
671 .quote = _quote,
672 .destroy = _destroy,
673 },
674 );
675
676 available = initialize_context(this);
677 DBG1(DBG_PTS, "TPM 2.0 via TSS2 %savailable", available ? "" : "not ");
678
679 if (!available)
680 {
681 destroy(this);
682 return NULL;
683 }
684 return &this->public;
685 }
686
687 #else /* TSS_TSS2 */
688
689 tpm_tss_t *tpm_tss_tss2_create()
690 {
691 return NULL;
692 }
693
694 #endif /* TSS_TSS2 */
695
696