libtpmtss: Read RSA public key exponent instead of assuming its value
[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 uint32_t exponent;
485
486 scheme = &public.t.publicArea.parameters.rsaDetail.scheme;
487 sig_alg = scheme->scheme;
488 digest_alg = scheme->details.anySig.hashAlg;
489
490 rsa = &public.t.publicArea.unique.rsa;
491 aik_modulus = chunk_create(rsa->t.buffer, rsa->t.size);
492 exponent = public.t.publicArea.parameters.rsaDetail.exponent;
493 if (!exponent)
494 {
495 aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
496 }
497 else
498 {
499 aik_exponent = chunk_from_thing(exponent);
500 }
501
502 /* subjectPublicKeyInfo encoding of RSA public key */
503 if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
504 NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
505 CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
506 {
507 DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of public key "
508 "failed", LABEL);
509 return chunk_empty;
510 }
511 break;
512 }
513 case TPM_ALG_ECC:
514 {
515 TPMS_ECC_POINT *ecc;
516 TPMT_ECC_SCHEME *scheme;
517 chunk_t ecc_point;
518 uint8_t *pos;
519
520 scheme = &public.t.publicArea.parameters.eccDetail.scheme;
521 sig_alg = scheme->scheme;
522 digest_alg = scheme->details.anySig.hashAlg;
523
524 ecc = &public.t.publicArea.unique.ecc;
525
526 /* allocate space for bit string */
527 pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
528 2 + ecc->x.t.size + ecc->y.t.size);
529 /* bit string length is a multiple of octets */
530 *pos++ = 0x00;
531 /* uncompressed ECC point format */
532 *pos++ = 0x04;
533 /* copy x coordinate of ECC point */
534 memcpy(pos, ecc->x.t.buffer, ecc->x.t.size);
535 pos += ecc->x.t.size;
536 /* copy y coordinate of ECC point */
537 memcpy(pos, ecc->y.t.buffer, ecc->y.t.size);
538 /* subjectPublicKeyInfo encoding of ECC public key */
539 aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
540 asn1_wrap(ASN1_SEQUENCE, "mm",
541 asn1_build_known_oid(OID_EC_PUBLICKEY),
542 asn1_build_known_oid(ecc->x.t.size == 32 ?
543 OID_PRIME256V1 : OID_SECT384R1)),
544 ecc_point);
545 break;
546 }
547 default:
548 DBG1(DBG_PTS, "%s unsupported key type", LABEL);
549 return chunk_empty;
550 }
551 DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
552 tpm_alg_id_names, sig_alg, tpm_alg_id_names, digest_alg);
553 return aik_pubkey;
554 }
555
556 METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
557 private_tpm_tss_tss2_t *this, uint32_t handle)
558 {
559 TPM2B_PUBLIC public = { { 0, } };
560 hash_algorithm_t digest;
561 signature_params_t supported_scheme;
562
563 if (!read_public(this, handle, &public))
564 {
565 return enumerator_create_empty();
566 }
567
568 switch (public.t.publicArea.type)
569 {
570 case TPM_ALG_RSA:
571 {
572 TPMS_RSA_PARMS *rsa;
573 TPMT_RSA_SCHEME *scheme;
574
575 rsa = &public.t.publicArea.parameters.rsaDetail;
576 scheme = &rsa->scheme;
577 digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
578
579 switch (scheme->scheme)
580 {
581 case TPM_ALG_RSAPSS:
582 {
583 ssize_t salt_len;
584
585 salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
586 RSA_PSS_SALT_LEN_MAX;
587 rsa_pss_params_t pss_params = {
588 .hash = digest,
589 .mgf1_hash = digest,
590 .salt_len = salt_len,
591 };
592 supported_scheme = (signature_params_t){
593 .scheme = SIGN_RSA_EMSA_PSS,
594 .params = &pss_params,
595 };
596 if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits))
597 {
598 return enumerator_create_empty();
599 }
600 break;
601 }
602 case TPM_ALG_RSASSA:
603 supported_scheme = (signature_params_t){
604 .scheme = signature_scheme_from_oid(
605 hasher_signature_algorithm_to_oid(digest,
606 KEY_RSA)),
607 };
608 break;
609 default:
610 return enumerator_create_empty();
611 }
612 break;
613 }
614 case TPM_ALG_ECC:
615 {
616 TPMT_ECC_SCHEME *scheme;
617
618 scheme = &public.t.publicArea.parameters.eccDetail.scheme;
619 digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
620
621 switch (scheme->scheme)
622 {
623 case TPM_ALG_ECDSA:
624 supported_scheme = (signature_params_t){
625 .scheme = signature_scheme_from_oid(
626 hasher_signature_algorithm_to_oid(digest,
627 KEY_ECDSA)),
628 };
629 break;
630 default:
631 return enumerator_create_empty();
632 }
633 break;
634 }
635 default:
636 DBG1(DBG_PTS, "%s unsupported key type", LABEL);
637 return enumerator_create_empty();
638 }
639 return enumerator_create_single(signature_params_clone(&supported_scheme),
640 (void*)signature_params_destroy);
641 }
642
643 /**
644 * Configure a PCR Selection assuming a maximum of 24 registers
645 */
646 static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
647 hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
648 {
649 TPM_ALG_ID alg_id;
650 uint32_t pcr;
651
652 /* check if hash algorithm is supported by TPM */
653 alg_id = hash_alg_to_tpm_alg_id(alg);
654 if (!is_supported_alg(this, alg_id))
655 {
656 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
657 LABEL, hash_algorithm_short_names, alg);
658 return FALSE;
659 }
660
661 /* initialize the PCR Selection structure,*/
662 pcr_sel->count = 1;
663 pcr_sel->pcrSelections[0].hash = alg_id;
664 pcr_sel->pcrSelections[0].sizeofSelect = 3;
665 pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
666 pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
667 pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
668
669 /* set the selected PCRs */
670 for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
671 {
672 if (pcrs & (1 << pcr))
673 {
674 pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
675 }
676 }
677 return TRUE;
678 }
679
680 METHOD(tpm_tss_t, read_pcr, bool,
681 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
682 hash_algorithm_t alg)
683 {
684 TPML_PCR_SELECTION pcr_selection;
685 TPML_DIGEST pcr_values;
686
687 uint32_t pcr_update_counter, rval;
688 uint8_t *pcr_value_ptr;
689 size_t pcr_value_len;
690
691 if (pcr_num >= PLATFORM_PCR)
692 {
693 DBG1(DBG_PTS, "%s maximum number of supported PCR is %d",
694 LABEL, PLATFORM_PCR);
695 return FALSE;
696 }
697
698 if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
699 {
700 return FALSE;
701 }
702
703 /* initialize the PCR Digest structure */
704 memset(&pcr_values, 0, sizeof(TPML_DIGEST));
705
706 /* read the PCR value */
707 rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
708 &pcr_update_counter, &pcr_selection, &pcr_values, 0);
709 if (rval != TPM_RC_SUCCESS)
710 {
711 DBG1(DBG_PTS, "%s PCR bank could not be read: 0x%60x",
712 LABEL, rval);
713 return FALSE;
714 }
715 pcr_value_ptr = (uint8_t *)pcr_values.digests[0].t.buffer;
716 pcr_value_len = (size_t) pcr_values.digests[0].t.size;
717
718 *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
719
720 return TRUE;
721 }
722
723 METHOD(tpm_tss_t, extend_pcr, bool,
724 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
725 chunk_t data, hash_algorithm_t alg)
726 {
727 uint32_t rval;
728 TPM_ALG_ID alg_id;
729 TPML_DIGEST_VALUES digest_values;
730 TPMS_AUTH_COMMAND session_data_cmd;
731 TPMS_AUTH_RESPONSE session_data_rsp;
732 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
733 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
734 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
735 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
736
737 session_data_cmd_array[0] = &session_data_cmd;
738 session_data_rsp_array[0] = &session_data_rsp;
739
740 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
741 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
742
743 sessions_data_cmd.cmdAuthsCount = 1;
744 sessions_data_rsp.rspAuthsCount = 1;
745
746 session_data_cmd.sessionHandle = TPM_RS_PW;
747 session_data_cmd.hmac.t.size = 0;
748 session_data_cmd.nonce.t.size = 0;
749
750 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
751
752 /* check if hash algorithm is supported by TPM */
753 alg_id = hash_alg_to_tpm_alg_id(alg);
754 if (!is_supported_alg(this, alg_id))
755 {
756 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
757 LABEL, hash_algorithm_short_names, alg);
758 return FALSE;
759 }
760
761 digest_values.count = 1;
762 digest_values.digests[0].hashAlg = alg_id;
763
764 switch (alg)
765 {
766 case HASH_SHA1:
767 if (data.len != HASH_SIZE_SHA1)
768 {
769 return FALSE;
770 }
771 memcpy(digest_values.digests[0].digest.sha1, data.ptr,
772 HASH_SIZE_SHA1);
773 break;
774 case HASH_SHA256:
775 if (data.len != HASH_SIZE_SHA256)
776 {
777 return FALSE;
778 }
779 memcpy(digest_values.digests[0].digest.sha256, data.ptr,
780 HASH_SIZE_SHA256);
781 break;
782 case HASH_SHA384:
783 if (data.len != HASH_SIZE_SHA384)
784 {
785 return FALSE;
786 }
787 memcpy(digest_values.digests[0].digest.sha384, data.ptr,
788 HASH_SIZE_SHA384);
789 break;
790 case HASH_SHA512:
791 if (data.len != HASH_SIZE_SHA512)
792 {
793 return FALSE;
794 }
795 memcpy(digest_values.digests[0].digest.sha512, data.ptr,
796 HASH_SIZE_SHA512);
797 break;
798 default:
799 return FALSE;
800 }
801
802 /* extend PCR */
803 rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &sessions_data_cmd,
804 &digest_values, &sessions_data_rsp);
805 if (rval != TPM_RC_SUCCESS)
806 {
807 DBG1(DBG_PTS, "%s PCR %02u could not be extended: 0x%06x",
808 LABEL, pcr_num, rval);
809 return FALSE;
810 }
811
812 /* get updated PCR value */
813 return read_pcr(this, pcr_num, pcr_value, alg);
814 }
815
816 METHOD(tpm_tss_t, quote, bool,
817 private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
818 hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
819 tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
820 {
821 chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
822 firmware_version, pcr_select, pcr_digest;
823 hash_algorithm_t pcr_digest_alg;
824 bio_reader_t *reader;
825 uint32_t rval;
826
827 TPM2B_DATA qualifying_data;
828 TPML_PCR_SELECTION pcr_selection;
829 TPM2B_ATTEST quoted = { { sizeof(TPM2B_ATTEST)-2, } };
830 TPMT_SIG_SCHEME scheme;
831 TPMT_SIGNATURE sig;
832 TPMI_ALG_HASH hash_alg;
833 TPMS_AUTH_COMMAND session_data_cmd;
834 TPMS_AUTH_RESPONSE session_data_rsp;
835 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
836 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
837 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
838 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
839
840 session_data_cmd_array[0] = &session_data_cmd;
841 session_data_rsp_array[0] = &session_data_rsp;
842
843 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
844 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
845
846 sessions_data_cmd.cmdAuthsCount = 1;
847 sessions_data_rsp.rspAuthsCount = 1;
848
849 session_data_cmd.sessionHandle = TPM_RS_PW;
850 session_data_cmd.hmac.t.size = 0;
851 session_data_cmd.nonce.t.size = 0;
852
853 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
854
855 qualifying_data.t.size = data.len;
856 memcpy(qualifying_data.t.buffer, data.ptr, data.len);
857
858 scheme.scheme = TPM_ALG_NULL;
859 memset(&sig, 0x00, sizeof(sig));
860
861 /* set Quote mode */
862 *quote_mode = TPM_QUOTE_TPM2;
863
864 if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
865 {
866 return FALSE;
867 }
868
869 rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &sessions_data_cmd,
870 &qualifying_data, &scheme, &pcr_selection, &quoted,
871 &sig, &sessions_data_rsp);
872 if (rval != TPM_RC_SUCCESS)
873 {
874 DBG1(DBG_PTS,"%s Tss2_Sys_Quote failed: 0x%06x", LABEL, rval);
875 return FALSE;
876 }
877 quoted_chunk = chunk_create(quoted.t.attestationData, quoted.t.size);
878
879 reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
880 if (!reader->read_data16(reader, &qualified_signer) ||
881 !reader->read_data16(reader, &extra_data) ||
882 !reader->read_data (reader, 17, &clock_info) ||
883 !reader->read_data (reader, 8, &firmware_version) ||
884 !reader->read_data (reader, 10, &pcr_select) ||
885 !reader->read_data16(reader, &pcr_digest))
886 {
887 DBG1(DBG_PTS, "%s parsing of quoted struct failed", LABEL);
888 reader->destroy(reader);
889 return FALSE;
890 }
891 reader->destroy(reader);
892
893 DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
894 DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
895 DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
896 DBG2(DBG_PTS, "extraData: %B", &extra_data);
897 DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
898 DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
899 DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
900
901 /* extract signature */
902 switch (sig.sigAlg)
903 {
904 case TPM_ALG_RSASSA:
905 case TPM_ALG_RSAPSS:
906 *quote_sig = chunk_clone(
907 chunk_create(
908 sig.signature.rsassa.sig.t.buffer,
909 sig.signature.rsassa.sig.t.size));
910 hash_alg = sig.signature.rsassa.hash;
911 break;
912 case TPM_ALG_ECDSA:
913 case TPM_ALG_ECDAA:
914 case TPM_ALG_SM2:
915 case TPM_ALG_ECSCHNORR:
916 *quote_sig = chunk_cat("cc",
917 chunk_create(
918 sig.signature.ecdsa.signatureR.t.buffer,
919 sig.signature.ecdsa.signatureR.t.size),
920 chunk_create(
921 sig.signature.ecdsa.signatureS.t.buffer,
922 sig.signature.ecdsa.signatureS.t.size));
923 hash_alg = sig.signature.ecdsa.hash;
924 break;
925 default:
926 DBG1(DBG_PTS, "%s unsupported %N signature algorithm",
927 LABEL, tpm_alg_id_names, sig.sigAlg);
928 return FALSE;
929 }
930
931 DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
932 pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
933
934 DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
935
936 /* Create and initialize Quote Info object */
937 *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
938 pcr_digest);
939 (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
940 pcr_select);
941 (*quote_info)->set_version_info(*quote_info, firmware_version);
942
943 return TRUE;
944 }
945
946 METHOD(tpm_tss_t, sign, bool,
947 private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
948 signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
949 chunk_t *signature)
950 {
951 key_type_t key_type;
952 hash_algorithm_t hash_alg;
953 rsa_pss_params_t *rsa_pss_params;
954 uint32_t rval;
955
956 TPM_ALG_ID alg_id;
957 TPM2B_MAX_BUFFER buffer;
958 TPM2B_DIGEST hash = { { sizeof(TPM2B_DIGEST)-2, } };
959 TPMT_TK_HASHCHECK validation;
960 TPM2B_PUBLIC public = { { 0, } };
961 TPMT_SIG_SCHEME sig_scheme;
962 TPMT_SIGNATURE sig;
963 TPMS_AUTH_COMMAND session_data_cmd;
964 TPMS_AUTH_RESPONSE session_data_rsp;
965 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
966 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
967 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
968 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
969
970 session_data_cmd_array[0] = &session_data_cmd;
971 session_data_rsp_array[0] = &session_data_rsp;
972
973 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
974 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
975
976 sessions_data_cmd.cmdAuthsCount = 1;
977 sessions_data_rsp.rspAuthsCount = 1;
978
979 session_data_cmd.sessionHandle = TPM_RS_PW;
980 session_data_cmd.nonce.t.size = 0;
981 session_data_cmd.hmac.t.size = 0;
982
983 if (pin.len > 0)
984 {
985 session_data_cmd.hmac.t.size = min(sizeof(session_data_cmd.hmac.t) - 2,
986 pin.len);
987 memcpy(session_data_cmd.hmac.t.buffer, pin.ptr,
988 session_data_cmd.hmac.t.size);
989 }
990 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
991
992 if (scheme == SIGN_RSA_EMSA_PSS)
993 {
994 key_type = KEY_RSA;
995 rsa_pss_params = (rsa_pss_params_t *)params;
996 hash_alg = rsa_pss_params->hash;
997 }
998 else
999 {
1000 key_type = key_type_from_signature_scheme(scheme);
1001 hash_alg = hasher_from_signature_scheme(scheme, NULL);
1002 }
1003
1004 /* Check if hash algorithm is supported by TPM */
1005 alg_id = hash_alg_to_tpm_alg_id(hash_alg);
1006 if (!is_supported_alg(this, alg_id))
1007 {
1008 DBG1(DBG_PTS, "%s %N hash algorithm not supported by TPM",
1009 LABEL, hash_algorithm_short_names, hash_alg);
1010 return FALSE;
1011 }
1012
1013 /* Get public key */
1014 if (!read_public(this, handle, &public))
1015 {
1016 return FALSE;
1017 }
1018
1019 if (key_type == KEY_RSA && public.t.publicArea.type == TPM_ALG_RSA)
1020 {
1021 if (scheme == SIGN_RSA_EMSA_PSS)
1022 {
1023 sig_scheme.scheme = TPM_ALG_RSAPSS;
1024 sig_scheme.details.rsapss.hashAlg = alg_id;
1025 }
1026 else
1027 {
1028 sig_scheme.scheme = TPM_ALG_RSASSA;
1029 sig_scheme.details.rsassa.hashAlg = alg_id;
1030 }
1031 }
1032 else if (key_type == KEY_ECDSA && public.t.publicArea.type == TPM_ALG_ECC)
1033 {
1034 sig_scheme.scheme = TPM_ALG_ECDSA;
1035 sig_scheme.details.ecdsa.hashAlg = alg_id;
1036
1037 }
1038 else
1039 {
1040 DBG1(DBG_PTS, "%s signature scheme %N not supported by TPM key",
1041 LABEL, signature_scheme_names, scheme);
1042 return FALSE;
1043 }
1044
1045 if (data.len <= MAX_DIGEST_BUFFER)
1046 {
1047 memcpy(buffer.t.buffer, data.ptr, data.len);
1048 buffer.t.size = data.len;
1049
1050 rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy,
1051 &hash, &validation, 0);
1052 if (rval != TPM_RC_SUCCESS)
1053 {
1054 DBG1(DBG_PTS,"%s Tss2_Sys_Hash failed: 0x%06x", LABEL, rval);
1055 return FALSE;
1056 }
1057 }
1058 else
1059 {
1060 TPMI_DH_OBJECT sequence_handle;
1061 TPM2B_AUTH null_auth;
1062
1063 null_auth.t.size = 0;
1064 rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth,
1065 alg_id, &sequence_handle, 0);
1066 if (rval != TPM_RC_SUCCESS)
1067 {
1068 DBG1(DBG_PTS,"%s Tss2_Sys_HashSequenceStart failed: 0x%06x",
1069 LABEL, rval);
1070 return FALSE;
1071 }
1072
1073 while (data.len > 0)
1074 {
1075 buffer.t.size = min(data.len, MAX_DIGEST_BUFFER);
1076 memcpy(buffer.t.buffer, data.ptr, buffer.t.size);
1077 data.ptr += buffer.t.size;
1078 data.len -= buffer.t.size;
1079
1080 rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle,
1081 &sessions_data_cmd, &buffer, 0);
1082 if (rval != TPM_RC_SUCCESS)
1083 {
1084 DBG1(DBG_PTS,"%s Tss2_Sys_SequenceUpdate failed: 0x%06x",
1085 LABEL, rval);
1086 return FALSE;
1087 }
1088 }
1089 buffer.t.size = 0;
1090
1091 rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle,
1092 &sessions_data_cmd, &buffer, hierarchy,
1093 &hash, &validation, 0);
1094 if (rval != TPM_RC_SUCCESS)
1095 {
1096 DBG1(DBG_PTS,"%s Tss2_Sys_SequenceComplete failed: 0x%06x",
1097 LABEL, rval);
1098 return FALSE;
1099 }
1100 }
1101
1102 rval = Tss2_Sys_Sign(this->sys_context, handle, &sessions_data_cmd, &hash,
1103 &sig_scheme, &validation, &sig, &sessions_data_rsp);
1104 if (rval != TPM_RC_SUCCESS)
1105 {
1106 DBG1(DBG_PTS,"%s Tss2_Sys_Sign failed: 0x%06x", LABEL, rval);
1107 return FALSE;
1108 }
1109
1110 /* extract signature */
1111 switch (scheme)
1112 {
1113 case SIGN_RSA_EMSA_PKCS1_SHA1:
1114 case SIGN_RSA_EMSA_PKCS1_SHA2_256:
1115 case SIGN_RSA_EMSA_PKCS1_SHA2_384:
1116 case SIGN_RSA_EMSA_PKCS1_SHA2_512:
1117 *signature = chunk_clone(
1118 chunk_create(
1119 sig.signature.rsassa.sig.t.buffer,
1120 sig.signature.rsassa.sig.t.size));
1121 break;
1122 case SIGN_RSA_EMSA_PSS:
1123 *signature = chunk_clone(
1124 chunk_create(
1125 sig.signature.rsapss.sig.t.buffer,
1126 sig.signature.rsapss.sig.t.size));
1127 break;
1128 case SIGN_ECDSA_256:
1129 case SIGN_ECDSA_384:
1130 case SIGN_ECDSA_521:
1131 *signature = chunk_cat("cc",
1132 chunk_create(
1133 sig.signature.ecdsa.signatureR.t.buffer,
1134 sig.signature.ecdsa.signatureR.t.size),
1135 chunk_create(
1136 sig.signature.ecdsa.signatureS.t.buffer,
1137 sig.signature.ecdsa.signatureS.t.size));
1138 break;
1139 case SIGN_ECDSA_WITH_SHA256_DER:
1140 case SIGN_ECDSA_WITH_SHA384_DER:
1141 case SIGN_ECDSA_WITH_SHA512_DER:
1142 *signature = asn1_wrap(ASN1_SEQUENCE, "mm",
1143 asn1_integer("c",
1144 chunk_create(
1145 sig.signature.ecdsa.signatureR.t.buffer,
1146 sig.signature.ecdsa.signatureR.t.size)),
1147 asn1_integer("c",
1148 chunk_create(
1149 sig.signature.ecdsa.signatureS.t.buffer,
1150 sig.signature.ecdsa.signatureS.t.size)));
1151 break;
1152 default:
1153 DBG1(DBG_PTS, "%s unsupported %N signature scheme",
1154 LABEL, signature_scheme_names, scheme);
1155 return FALSE;
1156 }
1157
1158 return TRUE;
1159 }
1160
1161 METHOD(tpm_tss_t, get_random, bool,
1162 private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer)
1163 {
1164 size_t len, random_len= sizeof(TPM2B_DIGEST)-2;
1165 TPM2B_DIGEST random = { { random_len, } };
1166 uint8_t *pos = buffer;
1167 uint32_t rval;
1168
1169 while (bytes > 0)
1170 {
1171 len = min(bytes, random_len);
1172
1173 rval = Tss2_Sys_GetRandom(this->sys_context, NULL, len, &random, NULL);
1174 if (rval != TSS2_RC_SUCCESS)
1175 {
1176 DBG1(DBG_PTS,"%s Tss2_Sys_GetRandom failed: 0x%06x", LABEL, rval);
1177 return FALSE;
1178 }
1179 memcpy(pos, random.t.buffer, random.t.size);
1180 pos += random.t.size;
1181 bytes -= random.t.size;
1182 }
1183
1184 return TRUE;
1185 }
1186
1187 METHOD(tpm_tss_t, get_data, bool,
1188 private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
1189 chunk_t pin, chunk_t *data)
1190 {
1191 uint16_t max_data_size, nv_size, nv_offset = 0;
1192 uint32_t rval;
1193
1194 TPMS_CAPABILITY_DATA cap_data;
1195 TPMI_YES_NO more_data;
1196 TPM2B_NAME nv_name = { { sizeof(TPM2B_NAME)-2, } };
1197 TPM2B_NV_PUBLIC nv_public = { { 0, } };
1198 TPM2B_MAX_NV_BUFFER nv_data = { { MAX_NV_BUFFER_SIZE, } };
1199 TPMS_AUTH_COMMAND session_data_cmd;
1200 TPMS_AUTH_RESPONSE session_data_rsp;
1201 TSS2_SYS_CMD_AUTHS sessions_data_cmd;
1202 TSS2_SYS_RSP_AUTHS sessions_data_rsp;
1203 TPMS_AUTH_COMMAND *session_data_cmd_array[1];
1204 TPMS_AUTH_RESPONSE *session_data_rsp_array[1];
1205
1206 /* query maximum TPM data transmission size */
1207 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM_CAP_TPM_PROPERTIES,
1208 TPM_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0);
1209 if (rval != TPM_RC_SUCCESS)
1210 {
1211 DBG1(DBG_PTS,"%s Tss2_Sys_GetCapability failed for "
1212 "TPM_CAP_TPM_PROPERTIES: 0x%06x", LABEL, rval);
1213 return FALSE;
1214 }
1215 max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value,
1216 MAX_NV_BUFFER_SIZE);
1217
1218 /* get size of NV object */
1219 rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public,
1220 &nv_name, 0);
1221 if (rval != TPM_RC_SUCCESS)
1222 {
1223 DBG1(DBG_PTS,"%s Tss2_Sys_NV_ReadPublic failed: 0x%06x", LABEL, rval);
1224 return FALSE;
1225 }
1226 nv_size = nv_public.t.nvPublic.dataSize;
1227 *data = chunk_alloc(nv_size);
1228
1229 /*prepare NV read session */
1230 session_data_cmd_array[0] = &session_data_cmd;
1231 session_data_rsp_array[0] = &session_data_rsp;
1232
1233 sessions_data_cmd.cmdAuths = &session_data_cmd_array[0];
1234 sessions_data_rsp.rspAuths = &session_data_rsp_array[0];
1235
1236 sessions_data_cmd.cmdAuthsCount = 1;
1237 sessions_data_rsp.rspAuthsCount = 1;
1238
1239 session_data_cmd.sessionHandle = TPM_RS_PW;
1240 session_data_cmd.nonce.t.size = 0;
1241 session_data_cmd.hmac.t.size = 0;
1242
1243 if (pin.len > 0)
1244 {
1245 session_data_cmd.hmac.t.size = min(sizeof(session_data_cmd.hmac.t) - 2,
1246 pin.len);
1247 memcpy(session_data_cmd.hmac.t.buffer, pin.ptr,
1248 session_data_cmd.hmac.t.size);
1249 }
1250 *( (uint8_t *)((void *)&session_data_cmd.sessionAttributes ) ) = 0;
1251
1252 /* read NV data a maximum data size block at a time */
1253 while (nv_size > 0)
1254 {
1255 rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle,
1256 &sessions_data_cmd, min(nv_size, max_data_size),
1257 nv_offset, &nv_data, &sessions_data_rsp);
1258
1259 if (rval != TPM_RC_SUCCESS)
1260 {
1261 DBG1(DBG_PTS,"%s Tss2_Sys_NV_Read failed: 0x%06x", LABEL, rval);
1262 chunk_free(data);
1263 return FALSE;
1264 }
1265 memcpy(data->ptr + nv_offset, nv_data.t.buffer, nv_data.t.size);
1266 nv_offset += nv_data.t.size;
1267 nv_size -= nv_data.t.size;
1268 }
1269
1270 return TRUE;
1271 }
1272
1273 METHOD(tpm_tss_t, destroy, void,
1274 private_tpm_tss_tss2_t *this)
1275 {
1276 finalize_context(this);
1277 free(this);
1278 }
1279
1280 /**
1281 * See header
1282 */
1283 tpm_tss_t *tpm_tss_tss2_create()
1284 {
1285 private_tpm_tss_tss2_t *this;
1286 bool available;
1287
1288 INIT(this,
1289 .public = {
1290 .get_version = _get_version,
1291 .get_version_info = _get_version_info,
1292 .generate_aik = _generate_aik,
1293 .get_public = _get_public,
1294 .supported_signature_schemes = _supported_signature_schemes,
1295 .read_pcr = _read_pcr,
1296 .extend_pcr = _extend_pcr,
1297 .quote = _quote,
1298 .sign = _sign,
1299 .get_random = _get_random,
1300 .get_data = _get_data,
1301 .destroy = _destroy,
1302 },
1303 );
1304
1305 available = initialize_tcti_tabrmd_context(this);
1306 if (!available)
1307 {
1308 available = initialize_tcti_socket_context(this);
1309 }
1310 if (available)
1311 {
1312 available = initialize_sys_context(this);
1313 }
1314 DBG1(DBG_PTS, "TPM 2.0 via TSS2 v1 %savailable", available ? "" : "not ");
1315
1316 if (!available)
1317 {
1318 destroy(this);
1319 return NULL;
1320 }
1321 return &this->public;
1322 }
1323
1324 #else /* TSS_TSS2_V1 */
1325
1326 #ifndef TSS_TSS2_V2
1327 tpm_tss_t *tpm_tss_tss2_create(void)
1328 {
1329 return NULL;
1330 }
1331 #endif /* !TSS_TSS2_V2 */
1332
1333 #endif /* TSS_TSS2_V1 */
1334
1335