f904442edebe2c8a0a18049a01bc1273cfa33563
[strongswan.git] / src / libtpmtss / tpm_tss_tss2_v1.c
1 /*
2 * Copyright (C) 2018 Tobias Brunner
3 * Copyright (C) 2016-2018 Andreas Steffen
4 * HSR Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "tpm_tss_tss2.h"
18 #include "tpm_tss_tss2_names.h"
19
20 #ifdef TSS_TSS2_V1
21
22 #include <asn1/asn1.h>
23 #include <asn1/oid.h>
24 #include <bio/bio_reader.h>
25
26 #include <tpm20.h>
27
28 #ifdef TSS2_TCTI_TABRMD
29 #include <tcti/tcti-tabrmd.h>
30 #endif /* TSS2_TCTI_TABRMD */
31
32 #ifdef TSS2_TCTI_SOCKET
33 #include <tcti_socket.h>
34
35 #define TCTI_SOCKET_DEFAULT_ADDRESS "127.0.0.1"
36 #define TCTI_SOCKET_DEFAULT_PORT 2323
37 #endif /* TSS2_TCTI_SOCKET */
38
39 #define LABEL "TPM 2.0 -"
40
41 typedef struct private_tpm_tss_tss2_t private_tpm_tss_tss2_t;
42
43 /**
44 * Private data of an tpm_tss_tss2_t object.
45 */
46 struct private_tpm_tss_tss2_t {
47
48 /**
49 * Public tpm_tss_tss2_t interface.
50 */
51 tpm_tss_t public;
52
53 /**
54 * TCTI context
55 */
56 TSS2_TCTI_CONTEXT *tcti_context;
57
58 /**
59 * SYS context
60 */
61 TSS2_SYS_CONTEXT *sys_context;
62
63 /**
64 * Number of supported algorithms
65 */
66 size_t supported_algs_count;
67
68 /**
69 * List of supported algorithms
70 */
71 TPM_ALG_ID supported_algs[TPM_PT_ALGORITHM_SET];
72
73 /**
74 * Is TPM FIPS 186-4 compliant ?
75 */
76 bool fips_186_4;
77
78 };
79
80 /**
81 * Some symbols required by libtctisocket
82 */
83 FILE *outFp;
84 uint8_t simulator = 1;
85
86 int TpmClientPrintf (uint8_t type, const char *format, ...)
87 {
88 return 0;
89 }
90
91 /**
92 * Convert hash algorithm to TPM_ALG_ID
93 */
94 static TPM_ALG_ID hash_alg_to_tpm_alg_id(hash_algorithm_t alg)
95 {
96 switch (alg)
97 {
98 case HASH_SHA1:
99 return TPM_ALG_SHA1;
100 case HASH_SHA256:
101 return TPM_ALG_SHA256;
102 case HASH_SHA384:
103 return TPM_ALG_SHA384;
104 case HASH_SHA512:
105 return TPM_ALG_SHA512;
106 default:
107 return TPM_ALG_ERROR;
108 }
109 }
110
111 /**
112 * Convert TPM_ALG_ID to hash algorithm
113 */
114 static hash_algorithm_t hash_alg_from_tpm_alg_id(TPM_ALG_ID alg)
115 {
116 switch (alg)
117 {
118 case TPM_ALG_SHA1:
119 return HASH_SHA1;
120 case TPM_ALG_SHA256:
121 return HASH_SHA256;
122 case TPM_ALG_SHA384:
123 return HASH_SHA384;
124 case TPM_ALG_SHA512:
125 return HASH_SHA512;
126 default:
127 return HASH_UNKNOWN;
128 }
129 }
130
131 /**
132 * Check if an algorithm given by its TPM_ALG_ID is supported by the TPM
133 */
134 static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM_ALG_ID alg_id)
135 {
136 int i;
137
138 if (alg_id == TPM_ALG_ERROR)
139 {
140 return FALSE;
141 }
142
143 for (i = 0; i < this->supported_algs_count; i++)
144 {
145 if (this->supported_algs[i] == alg_id)
146 {
147 return TRUE;
148 }
149 }
150
151 return FALSE;
152 }
153
154 /**
155 * Get a list of supported algorithms
156 */
157 static bool get_algs_capability(private_tpm_tss_tss2_t *this)
158 {
159 TPMS_CAPABILITY_DATA cap_data;
160 TPMS_TAGGED_PROPERTY tp;
161 TPMI_YES_NO more_data;
162 TPM_ALG_ID alg;
163 bool fips_140_2 = FALSE;
164 uint32_t rval, i, offset, revision = 0, year = 0;
165 size_t len = BUF_LEN;
166 char buf[BUF_LEN], manufacturer[5], vendor_string[17];
167 char *pos = buf;
168 int written;
169
170 /* get fixed properties */
171 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_TPM_PROPERTIES,
172 PT_FIXED, MAX_TPM_PROPERTIES, &more_data, &cap_data, 0);
173 if (rval != TPM_RC_SUCCESS)
174 {
175 DBG1(DBG_PTS, "%s GetCapability failed for TPM_CAP_TPM_PROPERTIES: 0x%06x",
176 LABEL, rval);
177 return FALSE;
178 }
179 memset(manufacturer, '\0', sizeof(manufacturer));
180 memset(vendor_string, '\0', sizeof(vendor_string));
181
182 /* print fixed properties */
183 for (i = 0; i < cap_data.data.tpmProperties.count; i++)
184 {
185 tp = cap_data.data.tpmProperties.tpmProperty[i];
186 switch (tp.property)
187 {
188 case TPM_PT_REVISION:
189 revision = tp.value;
190 break;
191 case TPM_PT_YEAR:
192 year = tp.value;
193 break;
194 case TPM_PT_MANUFACTURER:
195 htoun32(manufacturer, tp.value);
196 break;
197 case TPM_PT_VENDOR_STRING_1:
198 case TPM_PT_VENDOR_STRING_2:
199 case TPM_PT_VENDOR_STRING_3:
200 case TPM_PT_VENDOR_STRING_4:
201 offset = 4 * (tp.property - TPM_PT_VENDOR_STRING_1);
202 htoun32(vendor_string + offset, tp.value);
203 break;
204 case TPM_PT_MODES:
205 if (tp.value & TPMA_MODES_FIPS_140_2)
206 {
207 this->fips_186_4 = fips_140_2 = TRUE;
208 }
209 break;
210 default:
211 break;
212 }
213 }
214
215 if (!fips_140_2)
216 {
217 this->fips_186_4 = lib->settings->get_bool(lib->settings,
218 "%s.plugins.tpm.fips_186_4", FALSE, lib->ns);
219 }
220 DBG2(DBG_PTS, "%s manufacturer: %s (%s) rev: %05.2f %u %s", LABEL,
221 manufacturer, vendor_string, (float)revision/100, year,
222 fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : ""));
223
224 /* get supported algorithms */
225 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ALGS,
226 0, TPM_PT_ALGORITHM_SET, &more_data, &cap_data, 0);
227 if (rval != TPM_RC_SUCCESS)
228 {
229 DBG1(DBG_PTS, "%s GetCapability failed for TPM_CAP_ALGS: 0x%06x",
230 LABEL, rval);
231 return FALSE;
232 }
233
234 /* Number of supported algorithms */
235 this->supported_algs_count = cap_data.data.algorithms.count;
236
237 /* store and print supported algorithms */
238 for (i = 0; i < this->supported_algs_count; i++)
239 {
240 alg = cap_data.data.algorithms.algProperties[i].alg;
241 this->supported_algs[i] = alg;
242
243 written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
244 if (written < 0 || written >= len)
245 {
246 break;
247 }
248 pos += written;
249 len -= written;
250 }
251 DBG2(DBG_PTS, "%s algorithms:%s", LABEL, buf);
252
253 /* get supported ECC curves */
254 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_ECC_CURVES,
255 0, TPM_PT_LOADED_CURVES, &more_data, &cap_data, 0);
256 if (rval != TPM_RC_SUCCESS)
257 {
258 DBG1(DBG_PTS, "%s GetCapability failed for TPM_ECC_CURVES: 0x%06x",
259 LABEL, rval);
260 return FALSE;
261 }
262
263 /* reset print buffer */
264 pos = buf;
265 len = BUF_LEN;
266
267 /* print supported ECC curves */
268 for (i = 0; i < cap_data.data.eccCurves.count; i++)
269 {
270 written = snprintf(pos, len, " %N", tpm_ecc_curve_names,
271 cap_data.data.eccCurves.eccCurves[i]);
272 if (written < 0 || written >= len)
273 {
274 break;
275 }
276 pos += written;
277 len -= written;
278 }
279 DBG2(DBG_PTS, "%s ECC curves:%s", LABEL, buf);
280
281 return TRUE;
282 }
283
284 /**
285 * Initialize TSS2 TCTI TABRMD context
286 */
287 static bool initialize_tcti_tabrmd_context(private_tpm_tss_tss2_t *this)
288 {
289 #ifdef TSS2_TCTI_TABRMD
290 size_t tcti_context_size;
291 uint32_t rval;
292
293 /* determine size of tcti context */
294 rval = tss2_tcti_tabrmd_init(NULL, &tcti_context_size);
295 if (rval != TSS2_RC_SUCCESS)
296 {
297 DBG1(DBG_PTS, "%s could not get tcti_context size: 0x%06x",
298 LABEL, rval);
299 return FALSE;
300 }
301
302 /* allocate and initialize memory for tcti context */
303 this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
304 memset(this->tcti_context, 0x00, tcti_context_size);
305
306 /* initialize tcti context */
307 rval = tss2_tcti_tabrmd_init(this->tcti_context, &tcti_context_size);
308 if (rval != TSS2_RC_SUCCESS)
309 {
310 DBG1(DBG_PTS, "%s could not get tcti_context: 0x%06x "
311 "via tabrmd interface", LABEL, rval);
312 return FALSE;
313 }
314 return TRUE;
315 #else /* TSS2_TCTI_TABRMD */
316 return FALSE;
317 #endif /* TSS2_TCTI_TABRMD */
318 }
319
320 /**
321 * Initialize TSS2 TCTI Socket context
322 */
323 static bool initialize_tcti_socket_context(private_tpm_tss_tss2_t *this)
324 {
325 #ifdef TSS2_TCTI_SOCKET
326 size_t tcti_context_size;
327 uint32_t rval;
328
329 TCTI_SOCKET_CONF rm_if_config = { TCTI_SOCKET_DEFAULT_ADDRESS,
330 TCTI_SOCKET_DEFAULT_PORT
331 };
332
333 /* determine size of tcti context */
334 rval = InitSocketTcti(NULL, &tcti_context_size, &rm_if_config, 0);
335 if (rval != TSS2_RC_SUCCESS)
336 {
337 DBG1(DBG_PTS, "%s could not get tcti_context size: 0x%06x",
338 LABEL, rval);
339 return FALSE;
340 }
341
342 /* allocate memory for tcti context */
343 this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
344
345 /* initialize tcti context */
346 rval = InitSocketTcti(this->tcti_context, &tcti_context_size,
347 &rm_if_config, 0);
348 if (rval != TSS2_RC_SUCCESS)
349 {
350 DBG1(DBG_PTS, "%s could not get tcti_context: 0x%06x "
351 "via socket interface", LABEL, rval);
352 return FALSE;
353 }
354 return TRUE;
355 #else /* TSS2_TCTI_SOCKET */
356 return FALSE;
357 #endif /* TSS2_TCTI_SOCKET */
358 }
359
360 /**
361 * Initialize TSS2 Sys context
362 */
363 static bool initialize_sys_context(private_tpm_tss_tss2_t *this)
364 {
365 uint32_t sys_context_size;
366 uint32_t rval;
367
368 TSS2_ABI_VERSION abi_version = { TSSWG_INTEROP,
369 TSS_SAPI_FIRST_FAMILY,
370 TSS_SAPI_FIRST_LEVEL,
371 TSS_SAPI_FIRST_VERSION
372 };
373
374 /* determine size of sys context */
375 sys_context_size = Tss2_Sys_GetContextSize(0);
376
377 /* allocate memory for sys context */
378 this->sys_context = malloc(sys_context_size);
379
380 /* initialize sys context */
381 rval = Tss2_Sys_Initialize(this->sys_context, sys_context_size,
382 this->tcti_context, &abi_version);
383 if (rval != TSS2_RC_SUCCESS)
384 {
385 DBG1(DBG_PTS, "%s could not get sys_context: 0x%06x",
386 LABEL, rval);
387 return FALSE;
388 }
389
390 /* get a list of supported algorithms and ECC curves */
391 return get_algs_capability(this);
392 }
393
394 /**
395 * Finalize TSS context
396 */
397 static void finalize_context(private_tpm_tss_tss2_t *this)
398 {
399 if (this->tcti_context)
400 {
401 tss2_tcti_finalize(this->tcti_context);
402 free(this->tcti_context);
403 }
404 if (this->sys_context)
405 {
406 Tss2_Sys_Finalize(this->sys_context);
407 free(this->sys_context);
408 }
409 }
410
411 METHOD(tpm_tss_t, get_version, tpm_version_t,
412 private_tpm_tss_tss2_t *this)
413 {
414 return TPM_VERSION_2_0;
415 }
416
417 METHOD(tpm_tss_t, get_version_info, chunk_t,
418 private_tpm_tss_tss2_t *this)
419 {
420 return chunk_empty;
421 }
422
423 /**
424 * read the public key portion of a TSS 2.0 key from NVRAM
425 */
426 bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
427 TPM2B_PUBLIC *public)
428 {
429 uint32_t rval;
430
431 TPM2B_NAME name = { { sizeof(TPM2B_NAME)-2, } };
432 TPM2B_NAME qualified_name = { { sizeof(TPM2B_NAME)-2, } };
433
434 TPMS_AUTH_RESPONSE session_data;
435 TSS2_SYS_RSP_AUTHS sessions_data;
436 TPMS_AUTH_RESPONSE *session_data_array[1];
437
438 session_data_array[0] = &session_data;
439 sessions_data.rspAuths = &session_data_array[0];
440 sessions_data.rspAuthsCount = 1;
441
442 /* read public key for a given object handle from TPM 2.0 NVRAM */
443 rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
444 &qualified_name, &sessions_data);
445 if (rval != TPM_RC_SUCCESS)
446 {
447 DBG1(DBG_PTS, "%s could not read public key from handle 0x%08x: 0x%06x",
448 LABEL, handle, rval);
449 return FALSE;
450 }
451 return TRUE;
452 }
453
454 METHOD(tpm_tss_t, generate_aik, bool,
455 private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
456 chunk_t *aik_pubkey, chunk_t *identity_req)
457 {
458 return FALSE;
459 }
460
461 METHOD(tpm_tss_t, get_public, chunk_t,
462 private_tpm_tss_tss2_t *this, uint32_t handle)
463 {
464 TPM2B_PUBLIC public = { { 0, } };
465 TPM_ALG_ID sig_alg, digest_alg;
466 chunk_t aik_blob, aik_pubkey = chunk_empty;
467
468 if (!read_public(this, handle, &public))
469 {
470 return chunk_empty;
471 }
472
473 aik_blob = chunk_create((u_char*)&public, sizeof(public));
474 DBG3(DBG_LIB, "%s public key blob: %B", LABEL, &aik_blob);
475
476 /* convert TSS 2.0 public key blot into PKCS#1 format */
477 switch (public.t.publicArea.type)
478 {
479 case TPM_ALG_RSA:
480 {
481 TPM2B_PUBLIC_KEY_RSA *rsa;
482 TPMT_RSA_SCHEME *scheme;
483 chunk_t aik_exponent, aik_modulus;
484
485 scheme = &public.t.publicArea.parameters.rsaDetail.scheme;
486 sig_alg = scheme->scheme;
487 digest_alg = scheme->details.anySig.hashAlg;
488
489 rsa = &public.t.publicArea.unique.rsa;
490 aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size);
491 aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
492
493 /* subjectPublicKeyInfo encoding of RSA public key */
494 if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
495 NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
496 CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
497 {
498 DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of public key "
499 "failed", LABEL);
500 return chunk_empty;
501 }
502 break;
503 }
504 case TPM_ALG_ECC:
505 {
506 TPMS_ECC_POINT *ecc;
507 TPMT_ECC_SCHEME *scheme;
508 chunk_t ecc_point;
509 uint8_t *pos;
510
511 scheme = &public.t.publicArea.parameters.eccDetail.scheme;
512 sig_alg = scheme->scheme;
513 digest_alg = scheme->details.anySig.hashAlg;
514
515 ecc = &public.t.publicArea.unique.ecc;
516
517 /* allocate space for bit string */
518 pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
519 2 + ecc->x.t.size + ecc->y.t.size);
520 /* bit string length is a multiple of octets */
521 *pos++ = 0x00;
522 /* uncompressed ECC point format */
523 *pos++ = 0x04;
524 /* copy x coordinate of ECC point */
525 memcpy(pos, ecc->x.t.buffer, ecc->x.t.size);
526 pos += ecc->x.t.size;
527 /* copy y coordinate of ECC point */
528 memcpy(pos, ecc->y.t.buffer, ecc->y.t.size);
529 /* subjectPublicKeyInfo encoding of ECC public key */
530 aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
531 asn1_wrap(ASN1_SEQUENCE, "mm",
532 asn1_build_known_oid(OID_EC_PUBLICKEY),
533 asn1_build_known_oid(ecc->x.t.size == 32 ?
534 OID_PRIME256V1 : OID_SECT384R1)),
535 ecc_point);
536 break;
537 }
538 default:
539 DBG1(DBG_PTS, "%s unsupported key type", LABEL);
540 return chunk_empty;
541 }
542 DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
543 tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
544 return aik_pubkey;
545 }
546
547 METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
548 private_tpm_tss_tss2_t *this, uint32_t handle)
549 {
550 TPM2B_PUBLIC public = { { 0, } };
551 hash_algorithm_t digest;
552 signature_params_t supported_scheme;
553
554 if (!read_public(this, handle, &public))
555 {
556 return enumerator_create_empty();
557 }
558
559 switch (public.t.publicArea.type)
560 {
561 case TPM_ALG_RSA:
562 {
563 TPMS_RSA_PARMS *rsa;
564 TPMT_RSA_SCHEME *scheme;
565
566 rsa = &public.t.publicArea.parameters.rsaDetail;
567 scheme = &rsa->scheme;
568 digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
569
570 switch (scheme->scheme)
571 {
572 case TPM_ALG_RSAPSS:
573 {
574 ssize_t salt_len;
575
576 salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
577 RSA_PSS_SALT_LEN_MAX;
578 rsa_pss_params_t pss_params = {
579 .hash = digest,
580 .mgf1_hash = digest,
581 .salt_len = salt_len,
582 };
583 supported_scheme = (signature_params_t){
584 .scheme = SIGN_RSA_EMSA_PSS,
585 .params = &pss_params,
586 };
587 if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits))
588 {
589 return enumerator_create_empty();
590 }
591 break;
592 }
593 case TPM_ALG_RSASSA:
594 supported_scheme = (signature_params_t){
595 .scheme = signature_scheme_from_oid(
596 hasher_signature_algorithm_to_oid(digest,
597 KEY_RSA)),
598 };
599 break;
600 default:
601 return enumerator_create_empty();
602 }
603 break;
604 }
605 case TPM_ALG_ECC:
606 {
607 TPMT_ECC_SCHEME *scheme;
608
609 scheme = &public.t.publicArea.parameters.eccDetail.scheme;
610 digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
611
612 switch (scheme->scheme)
613 {
614 case TPM_ALG_ECDSA:
615 supported_scheme = (signature_params_t){
616 .scheme = signature_scheme_from_oid(
617 hasher_signature_algorithm_to_oid(digest,
618 KEY_ECDSA)),
619 };
620 break;
621 default:
622 return enumerator_create_empty();
623 }
624 break;
625 }
626 default:
627 DBG1(DBG_PTS, "%s unsupported key type", LABEL);
628 return enumerator_create_empty();
629 }
630 return enumerator_create_single(signature_params_clone(&supported_scheme),
631 (void*)signature_params_destroy);
632 }
633
634 /**
635 * Configure a PCR Selection assuming a maximum of 24 registers
636 */
637 static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
638 hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
639 {
640 TPM_ALG_ID alg_id;
641 uint32_t pcr;
642
643 /* check if hash algorithm is supported by TPM */
644 alg_id = hash_alg_to_tpm_alg_id(alg);
645 if (!is_supported_alg(this, alg_id))
646 {
647 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
648 LABEL, hash_algorithm_short_names, alg);
649 return FALSE;
650 }
651
652 /* initialize the PCR Selection structure,*/
653 pcr_sel->count = 1;
654 pcr_sel->pcrSelections[0].hash = alg_id;
655 pcr_sel->pcrSelections[0].sizeofSelect = 3;
656 pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
657 pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
658 pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
659
660 /* set the selected PCRs */
661 for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
662 {
663 if (pcrs & (1 << pcr))
664 {
665 pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
666 }
667 }
668 return TRUE;
669 }
670
671 METHOD(tpm_tss_t, read_pcr, bool,
672 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
673 hash_algorithm_t alg)
674 {
675 TPML_PCR_SELECTION pcr_selection;
676 TPML_DIGEST pcr_values;
677
678 uint32_t pcr_update_counter, rval;
679 uint8_t *pcr_value_ptr;
680 size_t pcr_value_len;
681
682 if (pcr_num >= PLATFORM_PCR)
683 {
684 DBG1(DBG_PTS, "%s maximum number of supported PCR is %d",
685 LABEL, PLATFORM_PCR);
686 return FALSE;
687 }
688
689 if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
690 {
691 return FALSE;
692 }
693
694 /* initialize the PCR Digest structure */
695 memset(&pcr_values, 0, sizeof(TPML_DIGEST));
696
697 /* read the PCR value */
698 rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
699 &pcr_update_counter, &pcr_selection, &pcr_values, 0);
700 if (rval != TPM_RC_SUCCESS)
701 {
702 DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x",
703 LABEL, rval);
704 return FALSE;
705 }
706 pcr_value_ptr = (uint8_t *)pcr_values.digests[0].t.buffer;
707 pcr_value_len = (size_t) pcr_values.digests[0].t.size;
708
709 *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
710
711 return TRUE;
712 }
713
714 METHOD(tpm_tss_t, extend_pcr, bool,
715 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
716 chunk_t data, hash_algorithm_t alg)
717 {
718 uint32_t rval;
719 TPM_ALG_ID alg_id;
720 TPML_DIGEST_VALUES digest_values;
721 TPMS_AUTH_COMMAND session_data_cmd;
722 TPMS_AUTH_RESPONSE session_data_rsp;
723 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
724 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
725 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
726 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
727
728 session_data_cmd_array[0] = &session_data_cmd;
729 session_data_rsp_array[0] = &session_data_rsp;
730
731 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
732 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
733
734 sessions_data_cmd.cmdAuthsCount = 1;
735 sessions_data_rsp.rspAuthsCount = 1;
736
737 session_data_cmd.sessionHandle = TPM_RS_PW;
738 session_data_cmd.hmac.t.size = 0;
739 session_data_cmd.nonce.t.size = 0;
740
741 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
742
743 /* check if hash algorithm is supported by TPM */
744 alg_id = hash_alg_to_tpm_alg_id(alg);
745 if (!is_supported_alg(this, alg_id))
746 {
747 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
748 LABEL, hash_algorithm_short_names, alg);
749 return FALSE;
750 }
751
752 digest_values.count = 1;
753 digest_values.digests[0].hashAlg = alg_id;
754
755 switch (alg)
756 {
757 case HASH_SHA1:
758 if (data.len != HASH_SIZE_SHA1)
759 {
760 return FALSE;
761 }
762 memcpy(digest_values.digests[0].digest.sha1, data.ptr,
763 HASH_SIZE_SHA1);
764 break;
765 case HASH_SHA256:
766 if (data.len != HASH_SIZE_SHA256)
767 {
768 return FALSE;
769 }
770 memcpy(digest_values.digests[0].digest.sha256, data.ptr,
771 HASH_SIZE_SHA256);
772 break;
773 case HASH_SHA384:
774 if (data.len != HASH_SIZE_SHA384)
775 {
776 return FALSE;
777 }
778 memcpy(digest_values.digests[0].digest.sha384, data.ptr,
779 HASH_SIZE_SHA384);
780 break;
781 case HASH_SHA512:
782 if (data.len != HASH_SIZE_SHA512)
783 {
784 return FALSE;
785 }
786 memcpy(digest_values.digests[0].digest.sha512, data.ptr,
787 HASH_SIZE_SHA512);
788 break;
789 default:
790 return FALSE;
791 }
792
793 /* extend PCR */
794 rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &sessions_data_cmd,
795 &digest_values, &sessions_data_rsp);
796 if (rval != TPM_RC_SUCCESS)
797 {
798 DBG1(DBG_PTS, "%s PCR %02u could not be extended: 0x%06x",
799 LABEL, pcr_num, rval);
800 return FALSE;
801 }
802
803 /* get updated PCR value */
804 return read_pcr(this, pcr_num, pcr_value, alg);
805 }
806
807 METHOD(tpm_tss_t, quote, bool,
808 private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
809 hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
810 tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
811 {
812 chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
813 firmware_version, pcr_select, pcr_digest;
814 hash_algorithm_t pcr_digest_alg;
815 bio_reader_t *reader;
816 uint32_t rval;
817
818 TPM2B_DATA qualifying_data;
819 TPML_PCR_SELECTION pcr_selection;
820 TPM2B_ATTEST quoted = { { sizeof(TPM2B_ATTEST)-2, } };
821 TPMT_SIG_SCHEME scheme;
822 TPMT_SIGNATURE sig;
823 TPMI_ALG_HASH hash_alg;
824 TPMS_AUTH_COMMAND session_data_cmd;
825 TPMS_AUTH_RESPONSE session_data_rsp;
826 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
827 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
828 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
829 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
830
831 session_data_cmd_array[0] = &session_data_cmd;
832 session_data_rsp_array[0] = &session_data_rsp;
833
834 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
835 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
836
837 sessions_data_cmd.cmdAuthsCount = 1;
838 sessions_data_rsp.rspAuthsCount = 1;
839
840 session_data_cmd.sessionHandle = TPM_RS_PW;
841 session_data_cmd.hmac.t.size = 0;
842 session_data_cmd.nonce.t.size = 0;
843
844 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
845
846 qualifying_data.t.size = data.len;
847 memcpy(qualifying_data.t.buffer, data.ptr, data.len);
848
849 scheme.scheme = TPM_ALG_NULL;
850 memset(&sig, 0x00, sizeof(sig));
851
852 /* set Quote mode */
853 *quote_mode = TPM_QUOTE_TPM2;
854
855 if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
856 {
857 return FALSE;
858 }
859
860 rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &sessions_data_cmd,
861 &qualifying_data, &scheme, &pcr_selection, &quoted,
862 &sig, &sessions_data_rsp);
863 if (rval != TPM_RC_SUCCESS)
864 {
865 DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval);
866 return FALSE;
867 }
868 quoted_chunk = chunk_create(quoted.t.attestationData, quoted.t.size);
869
870 reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
871 if (!reader->read_data16(reader, &qualified_signer) ||
872 !reader->read_data16(reader, &extra_data) ||
873 !reader->read_data (reader, 17, &clock_info) ||
874 !reader->read_data (reader, 8, &firmware_version) ||
875 !reader->read_data (reader, 10, &pcr_select) ||
876 !reader->read_data16(reader, &pcr_digest))
877 {
878 DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL);
879 reader->destroy(reader);
880 return FALSE;
881 }
882 reader->destroy(reader);
883
884 DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
885 DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
886 DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
887 DBG2(DBG_PTS, "extraData: %B", &extra_data);
888 DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
889 DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
890 DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
891
892 /* extract signature */
893 switch (sig.sigAlg)
894 {
895 case TPM_ALG_RSASSA:
896 case TPM_ALG_RSAPSS:
897 *quote_sig = chunk_clone(
898 chunk_create(
899 sig.signature.rsassa.sig.t.buffer,
900 sig.signature.rsassa.sig.t.size));
901 hash_alg = sig.signature.rsassa.hash;
902 break;
903 case TPM_ALG_ECDSA:
904 case TPM_ALG_ECDAA:
905 case TPM_ALG_SM2:
906 case TPM_ALG_ECSCHNORR:
907 *quote_sig = chunk_cat("cc",
908 chunk_create(
909 sig.signature.ecdsa.signatureR.t.buffer,
910 sig.signature.ecdsa.signatureR.t.size),
911 chunk_create(
912 sig.signature.ecdsa.signatureS.t.buffer,
913 sig.signature.ecdsa.signatureS.t.size));
914 hash_alg = sig.signature.ecdsa.hash;
915 break;
916 default:
917 DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
918 LABEL, tpm_alg_id_names, sig.sigAlg);
919 return FALSE;
920 }
921
922 DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
923 pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
924
925 DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
926
927 /* Create and initialize Quote Info object */
928 *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
929 pcr_digest);
930 (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
931 pcr_select);
932 (*quote_info)->set_version_info(*quote_info, firmware_version);
933
934 return TRUE;
935 }
936
937 METHOD(tpm_tss_t, sign, bool,
938 private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
939 signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
940 chunk_t *signature)
941 {
942 key_type_t key_type;
943 hash_algorithm_t hash_alg;
944 rsa_pss_params_t *rsa_pss_params;
945 uint32_t rval;
946
947 TPM_ALG_ID alg_id;
948 TPM2B_MAX_BUFFER buffer;
949 TPM2B_DIGEST hash = { { sizeof(TPM2B_DIGEST)-2, } };
950 TPMT_TK_HASHCHECK validation;
951 TPM2B_PUBLIC public = { { 0, } };
952 TPMT_SIG_SCHEME sig_scheme;
953 TPMT_SIGNATURE sig;
954 TPMS_AUTH_COMMAND session_data_cmd;
955 TPMS_AUTH_RESPONSE session_data_rsp;
956 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
957 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
958 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
959 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
960
961 session_data_cmd_array[0] = &session_data_cmd;
962 session_data_rsp_array[0] = &session_data_rsp;
963
964 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
965 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
966
967 sessions_data_cmd.cmdAuthsCount = 1;
968 sessions_data_rsp.rspAuthsCount = 1;
969
970 session_data_cmd.sessionHandle = TPM_RS_PW;
971 session_data_cmd.nonce.t.size = 0;
972 session_data_cmd.hmac.t.size = 0;
973
974 if (pin.len > 0)
975 {
976 session_data_cmd.hmac.t.size = min(sizeof(session_data_cmd.hmac.t) - 2,
977 pin.len);
978 memcpy(session_data_cmd.hmac.t.buffer, pin.ptr,
979 session_data_cmd.hmac.t.size);
980 }
981 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
982
983 if (scheme == SIGN_RSA_EMSA_PSS)
984 {
985 key_type = KEY_RSA;
986 rsa_pss_params = (rsa_pss_params_t *)params;
987 hash_alg = rsa_pss_params->hash;
988 }
989 else
990 {
991 key_type = key_type_from_signature_scheme(scheme);
992 hash_alg = hasher_from_signature_scheme(scheme, NULL);
993 }
994
995 /* Check if hash algorithm is supported by TPM */
996 alg_id = hash_alg_to_tpm_alg_id(hash_alg);
997 if (!is_supported_alg(this, alg_id))
998 {
999 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
1000 LABEL, hash_algorithm_short_names, hash_alg);
1001 return FALSE;
1002 }
1003
1004 /* Get public key */
1005 if (!read_public(this, handle, &public))
1006 {
1007 return FALSE;
1008 }
1009
1010 if (key_type == KEY_RSA && public.t.publicArea.type == TPM_ALG_RSA)
1011 {
1012 if (scheme == SIGN_RSA_EMSA_PSS)
1013 {
1014 sig_scheme.scheme = TPM_ALG_RSAPSS;
1015 sig_scheme.details.rsapss.hashAlg = alg_id;
1016 }
1017 else
1018 {
1019 sig_scheme.scheme = TPM_ALG_RSASSA;
1020 sig_scheme.details.rsassa.hashAlg = alg_id;
1021 }
1022 }
1023 else if (key_type == KEY_ECDSA && public.t.publicArea.type == TPM_ALG_ECC)
1024 {
1025 sig_scheme.scheme = TPM_ALG_ECDSA;
1026 sig_scheme.details.ecdsa.hashAlg = alg_id;
1027
1028 }
1029 else
1030 {
1031 DBG1(DBG_PTS, "%s signature scheme %N not supported by TPM key",
1032 LABEL, signature_scheme_names, scheme);
1033 return FALSE;
1034 }
1035
1036 if (data.len <= MAX_DIGEST_BUFFER)
1037 {
1038 memcpy(buffer.t.buffer, data.ptr, data.len);
1039 buffer.t.size = data.len;
1040
1041 rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy,
1042 &hash, &validation, 0);
1043 if (rval != TPM_RC_SUCCESS)
1044 {
1045 DBG1(DBG_PTS,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL, rval);
1046 return FALSE;
1047 }
1048 }
1049 else
1050 {
1051 TPMI_DH_OBJECT sequence_handle;
1052 TPM2B_AUTH null_auth;
1053
1054 null_auth.t.size = 0;
1055 rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth,
1056 alg_id, &sequence_handle, 0);
1057 if (rval != TPM_RC_SUCCESS)
1058 {
1059 DBG1(DBG_PTS,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x",
1060 LABEL, rval);
1061 return FALSE;
1062 }
1063
1064 while (data.len > 0)
1065 {
1066 buffer.t.size = min(data.len, MAX_DIGEST_BUFFER);
1067 memcpy(buffer.t.buffer, data.ptr, buffer.t.size);
1068 data.ptr += buffer.t.size;
1069 data.len -= buffer.t.size;
1070
1071 rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle,
1072 &sessions_data_cmd, &buffer, 0);
1073 if (rval != TPM_RC_SUCCESS)
1074 {
1075 DBG1(DBG_PTS,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x",
1076 LABEL, rval);
1077 return FALSE;
1078 }
1079 }
1080 buffer.t.size = 0;
1081
1082 rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle,
1083 &sessions_data_cmd, &buffer, hierarchy,
1084 &hash, &validation, 0);
1085 if (rval != TPM_RC_SUCCESS)
1086 {
1087 DBG1(DBG_PTS,"%s Tss2_Sys_SequenceComplete failed: 0x%06x",
1088 LABEL, rval);
1089 return FALSE;
1090 }
1091 }
1092
1093 rval = Tss2_Sys_Sign(this->sys_context, handle, &sessions_data_cmd, &hash,
1094 &sig_scheme, &validation, &sig, &sessions_data_rsp);
1095 if (rval != TPM_RC_SUCCESS)
1096 {
1097 DBG1(DBG_PTS,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL, rval);
1098 return FALSE;
1099 }
1100
1101 /* extract signature */
1102 switch (scheme)
1103 {
1104 case SIGN_RSA_EMSA_PKCS1_SHA1:
1105 case SIGN_RSA_EMSA_PKCS1_SHA2_256:
1106 case SIGN_RSA_EMSA_PKCS1_SHA2_384:
1107 case SIGN_RSA_EMSA_PKCS1_SHA2_512:
1108 *signature = chunk_clone(
1109 chunk_create(
1110 sig.signature.rsassa.sig.t.buffer,
1111 sig.signature.rsassa.sig.t.size));
1112 break;
1113 case SIGN_RSA_EMSA_PSS:
1114 *signature = chunk_clone(
1115 chunk_create(
1116 sig.signature.rsapss.sig.t.buffer,
1117 sig.signature.rsapss.sig.t.size));
1118 break;
1119 case SIGN_ECDSA_256:
1120 case SIGN_ECDSA_384:
1121 case SIGN_ECDSA_521:
1122 *signature = chunk_cat("cc",
1123 chunk_create(
1124 sig.signature.ecdsa.signatureR.t.buffer,
1125 sig.signature.ecdsa.signatureR.t.size),
1126 chunk_create(
1127 sig.signature.ecdsa.signatureS.t.buffer,
1128 sig.signature.ecdsa.signatureS.t.size));
1129 break;
1130 case SIGN_ECDSA_WITH_SHA256_DER:
1131 case SIGN_ECDSA_WITH_SHA384_DER:
1132 case SIGN_ECDSA_WITH_SHA512_DER:
1133 *signature = asn1_wrap(ASN1_SEQUENCE, "mm",
1134 asn1_integer("c",
1135 chunk_create(
1136 sig.signature.ecdsa.signatureR.t.buffer,
1137 sig.signature.ecdsa.signatureR.t.size)),
1138 asn1_integer("c",
1139 chunk_create(
1140 sig.signature.ecdsa.signatureS.t.buffer,
1141 sig.signature.ecdsa.signatureS.t.size)));
1142 break;
1143 default:
1144 DBG1(DBG_PTS, "%s unsupported %N signature scheme",
1145 LABEL, signature_scheme_names, scheme);
1146 return FALSE;
1147 }
1148
1149 return TRUE;
1150 }
1151
1152 METHOD(tpm_tss_t, get_random, bool,
1153 private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer)
1154 {
1155 size_t len, random_len= sizeof(TPM2B_DIGEST)-2;
1156 TPM2B_DIGEST random = { { random_len, } };
1157 uint8_t *pos = buffer;
1158 uint32_t rval;
1159
1160 while (bytes > 0)
1161 {
1162 len = min(bytes, random_len);
1163
1164 rval = Tss2_Sys_GetRandom(this->sys_context, NULL, len, &random, NULL);
1165 if (rval != TSS2_RC_SUCCESS)
1166 {
1167 DBG1(DBG_PTS,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL, rval);
1168 return FALSE;
1169 }
1170 memcpy(pos, random.t.buffer, random.t.size);
1171 pos += random.t.size;
1172 bytes -= random.t.size;
1173 }
1174
1175 return TRUE;
1176 }
1177
1178 METHOD(tpm_tss_t, get_data, bool,
1179 private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
1180 chunk_t pin, chunk_t *data)
1181 {
1182 uint16_t max_data_size, nv_size, nv_offset = 0;
1183 uint32_t rval;
1184
1185 TPMS_CAPABILITY_DATA cap_data;
1186 TPMI_YES_NO more_data;
1187 TPM2B_NAME nv_name = { { sizeof(TPM2B_NAME)-2, } };
1188 TPM2B_NV_PUBLIC nv_public = { { 0, } };
1189 TPM2B_MAX_NV_BUFFER nv_data = { { MAX_NV_BUFFER_SIZE, } };
1190 TPMS_AUTH_COMMAND session_data_cmd;
1191 TPMS_AUTH_RESPONSE session_data_rsp;
1192 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
1193 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
1194 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
1195 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
1196
1197 /* query maximum TPM data transmission size */
1198 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_TPM_PROPERTIES,
1199 TPM_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0);
1200 if (rval != TPM_RC_SUCCESS)
1201 {
1202 DBG1(DBG_PTS,"%s Tss2_Sys_GetCapability failed for "
1203 "TPM_CAP_TPM_PROPERTIES: 0x%06x", LABEL, rval);
1204 return FALSE;
1205 }
1206 max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value,
1207 MAX_NV_BUFFER_SIZE);
1208
1209 /* get size of NV object */
1210 rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public,
1211 &nv_name, 0);
1212 if (rval != TPM_RC_SUCCESS)
1213 {
1214 DBG1(DBG_PTS,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL, rval);
1215 return FALSE;
1216 }
1217 nv_size = nv_public.t.nvPublic.dataSize;
1218 *data = chunk_alloc(nv_size);
1219
1220 /*prepare NV read session */
1221 session_data_cmd_array[0] = &session_data_cmd;
1222 session_data_rsp_array[0] = &session_data_rsp;
1223
1224 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
1225 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
1226
1227 sessions_data_cmd.cmdAuthsCount = 1;
1228 sessions_data_rsp.rspAuthsCount = 1;
1229
1230 session_data_cmd.sessionHandle = TPM_RS_PW;
1231 session_data_cmd.nonce.t.size = 0;
1232 session_data_cmd.hmac.t.size = 0;
1233
1234 if (pin.len > 0)
1235 {
1236 session_data_cmd.hmac.t.size = min(sizeof(session_data_cmd.hmac.t) - 2,
1237 pin.len);
1238 memcpy(session_data_cmd.hmac.t.buffer, pin.ptr,
1239 session_data_cmd.hmac.t.size);
1240 }
1241 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
1242
1243 /* read NV data a maximum data size block at a time */
1244 while (nv_size > 0)
1245 {
1246 rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle,
1247 &sessions_data_cmd, min(nv_size, max_data_size),
1248 nv_offset, &nv_data, &sessions_data_rsp);
1249
1250 if (rval != TPM_RC_SUCCESS)
1251 {
1252 DBG1(DBG_PTS,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL, rval);
1253 chunk_free(data);
1254 return FALSE;
1255 }
1256 memcpy(data->ptr + nv_offset, nv_data.t.buffer, nv_data.t.size);
1257 nv_offset += nv_data.t.size;
1258 nv_size -= nv_data.t.size;
1259 }
1260
1261 return TRUE;
1262 }
1263
1264 METHOD(tpm_tss_t, destroy, void,
1265 private_tpm_tss_tss2_t *this)
1266 {
1267 finalize_context(this);
1268 free(this);
1269 }
1270
1271 /**
1272 * See header
1273 */
1274 tpm_tss_t *tpm_tss_tss2_create()
1275 {
1276 private_tpm_tss_tss2_t *this;
1277 bool available;
1278
1279 INIT(this,
1280 .public = {
1281 .get_version = _get_version,
1282 .get_version_info = _get_version_info,
1283 .generate_aik = _generate_aik,
1284 .get_public = _get_public,
1285 .supported_signature_schemes = _supported_signature_schemes,
1286 .read_pcr = _read_pcr,
1287 .extend_pcr = _extend_pcr,
1288 .quote = _quote,
1289 .sign = _sign,
1290 .get_random = _get_random,
1291 .get_data = _get_data,
1292 .destroy = _destroy,
1293 },
1294 );
1295
1296 available = initialize_tcti_tabrmd_context(this);
1297 if (!available)
1298 {
1299 available = initialize_tcti_socket_context(this);
1300 }
1301 if (available)
1302 {
1303 available = initialize_sys_context(this);
1304 }
1305 DBG1(DBG_PTS, "TPM 2.0 via TSS2 v1 %savailable", available ? "" : "not ");
1306
1307 if (!available)
1308 {
1309 destroy(this);
1310 return NULL;
1311 }
1312 return &this->public;
1313 }
1314
1315 #else /* TSS_TSS2_V1 */
1316
1317 #ifndef TSS_TSS2_V2
1318 tpm_tss_t *tpm_tss_tss2_create(void)
1319 {
1320 return NULL;
1321 }
1322 #endif /* !TSS_TSS2_V2 */
1323
1324 #endif /* TSS_TSS2_V1 */
1325
1326