]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libtpmtss/tpm_tss_tss2_v2.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libtpmtss / tpm_tss_tss2_v2.c
1 /*
2 * Copyright (C) 2018-2021 Andreas Steffen
3 * Copyright (C) 2018 Tobias Brunner
4 *
5 * Copyright (C) secunet Security Networks AG
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "tpm_tss_tss2.h"
19 #include "tpm_tss_tss2_names.h"
20
21 #ifdef TSS_TSS2_V2
22
23 #include "tpm_tss_tss2_session.h"
24
25 #include <asn1/asn1.h>
26 #include <asn1/oid.h>
27 #include <bio/bio_reader.h>
28 #include <bio/bio_writer.h>
29 #include <threading/mutex.h>
30
31 #include <dlfcn.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35
36 #define LABEL "TPM 2.0 - "
37
38 #define PLATFORM_PCR 24
39 #define MAX_PCR_BANKS 4
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 * TPM version info
65 */
66 chunk_t version_info;
67
68 /**
69 * Number of supported algorithms
70 */
71 size_t supported_algs_count;
72
73 /**
74 * List of supported algorithms
75 */
76 TPM2_ALG_ID supported_algs[TPM2_PT_ALGORITHM_SET];
77
78 /**
79 * Number of assigned PCR banks
80 */
81 size_t assigned_pcrs_count;
82
83 /**
84 * List of assigned PCR banks
85 */
86 TPM2_ALG_ID assigned_pcrs[MAX_PCR_BANKS];
87
88 /**
89 * Is TPM FIPS 186-4 compliant ?
90 */
91 bool fips_186_4;
92
93 /**
94 * Does the TPM use the old TCG SHA1-only event digest format
95 */
96 bool old_event_digest_format;
97
98 /**
99 * TSS2 session used for protected communication with TPM 2.0
100 */
101 tpm_tss_tss2_session_t *session;
102
103 /**
104 * Mutex controlling access to the TPM 2.0 context
105 */
106 mutex_t *mutex;
107
108 };
109
110 /**
111 * Global TCTI dynamic library handle and init function
112 */
113 static void *tcti_handle;
114
115 static TSS2_TCTI_INIT_FUNC tcti_init;
116
117 static char *tcti_opts;
118
119 /**
120 * Empty AUTH_COMMAND
121 */
122 static const TPMS_AUTH_COMMAND auth_cmd_empty;
123
124 /**
125 * Convert hash algorithm to TPM2_ALG_ID
126 */
127 static TPM2_ALG_ID hash_alg_to_tpm_alg_id(hash_algorithm_t alg)
128 {
129 switch (alg)
130 {
131 case HASH_SHA1:
132 return TPM2_ALG_SHA1;
133 case HASH_SHA256:
134 return TPM2_ALG_SHA256;
135 case HASH_SHA384:
136 return TPM2_ALG_SHA384;
137 case HASH_SHA512:
138 return TPM2_ALG_SHA512;
139 case HASH_SHA3_256:
140 return TPM2_ALG_SHA3_256;
141 case HASH_SHA3_384:
142 return TPM2_ALG_SHA3_384;
143 case HASH_SHA3_512:
144 return TPM2_ALG_SHA3_512;
145 default:
146 return TPM2_ALG_ERROR;
147 }
148 }
149
150 /**
151 * Convert TPM2_ALG_ID to hash algorithm
152 */
153 hash_algorithm_t hash_alg_from_tpm_alg_id(TPM2_ALG_ID alg)
154 {
155 switch (alg)
156 {
157 case TPM2_ALG_SHA1:
158 return HASH_SHA1;
159 case TPM2_ALG_SHA256:
160 return HASH_SHA256;
161 case TPM2_ALG_SHA384:
162 return HASH_SHA384;
163 case TPM2_ALG_SHA512:
164 return HASH_SHA512;
165 case TPM2_ALG_SHA3_256:
166 return HASH_SHA3_256;
167 case TPM2_ALG_SHA3_384:
168 return HASH_SHA3_384;
169 case TPM2_ALG_SHA3_512:
170 return HASH_SHA3_512;
171 default:
172 return HASH_UNKNOWN;
173 }
174 }
175
176 /**
177 * Return hash length of TPM2_ALG_ID algorithm
178 */
179 size_t hash_len_from_tpm_alg_id(TPM2_ALG_ID alg)
180 {
181 switch (alg)
182 {
183 case TPM2_ALG_SHA1:
184 return TPM2_SHA1_DIGEST_SIZE;
185 case TPM2_ALG_SHA256:
186 case TPM2_ALG_SHA3_256:
187 return TPM2_SHA256_DIGEST_SIZE;
188 case TPM2_ALG_SHA384:
189 case TPM2_ALG_SHA3_384:
190 return TPM2_SHA384_DIGEST_SIZE;
191 case TPM2_ALG_SHA512:
192 case TPM2_ALG_SHA3_512:
193 return TPM2_SHA512_DIGEST_SIZE;
194 case TPM2_ALG_SM3_256:
195 return TPM2_SM3_256_DIGEST_SIZE;
196 default:
197 return 0;
198 }
199 }
200
201 /**
202 * Check if an algorithm given by its TPM2_ALG_ID is supported by the TPM
203 */
204 static bool is_supported_alg(private_tpm_tss_tss2_t *this, TPM2_ALG_ID alg_id)
205 {
206 int i;
207
208 if (alg_id == TPM2_ALG_ERROR)
209 {
210 return FALSE;
211 }
212
213 for (i = 0; i < this->supported_algs_count; i++)
214 {
215 if (this->supported_algs[i] == alg_id)
216 {
217 return TRUE;
218 }
219 }
220
221 return FALSE;
222 }
223
224 /**
225 * Get the TPM version_info and a list of supported algorithms
226 *
227 * 1 2 3
228 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
229 *
230 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
231 * | TPM 2.0 Version_Info Tag | Reserved | Locality |
232 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
233 * | Revision |
234 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
235 * | Year |
236 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
237 * | Vendor |
238 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
239 */
240 #define TPM2_VERSION_INFO_TAG 0x0200
241 #define TPM2_VERSION_INFO_RESERVED 0x00
242 #define TPM2_VERSION_INFO_SIZE 16
243 #define TPM2_DEFAULT_LOCALITY 3
244
245 static bool get_algs_capability(private_tpm_tss_tss2_t *this)
246 {
247 TPMS_CAPABILITY_DATA cap_data;
248 TPMS_TAGGED_PROPERTY tp;
249 TPMI_YES_NO more_data;
250 TPM2_ALG_ID alg;
251 bio_writer_t *writer;
252 bool fips_140_2 = FALSE;
253 uint32_t rval, i, offset, revision = 0, year = 0, vendor = 0;
254 uint8_t locality = TPM2_DEFAULT_LOCALITY;
255 size_t len = BUF_LEN;
256 char buf[BUF_LEN], manufacturer[5], vendor_string[17];
257 char *pos = buf;
258 int written;
259
260 /* get fixed properties */
261 this->mutex->lock(this->mutex);
262 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
263 TPM2_PT_FIXED, TPM2_MAX_TPM_PROPERTIES,
264 &more_data, &cap_data, 0);
265 this->mutex->unlock(this->mutex);
266 if (rval != TPM2_RC_SUCCESS)
267 {
268 DBG1(DBG_PTS, LABEL "GetCapability failed for TPM2_CAP_TPM_PROPERTIES: 0x%06x",
269 rval);
270 return FALSE;
271 }
272 memset(manufacturer, '\0', sizeof(manufacturer));
273 memset(vendor_string, '\0', sizeof(vendor_string));
274
275 /* print fixed properties */
276 for (i = 0; i < cap_data.data.tpmProperties.count; i++)
277 {
278 tp = cap_data.data.tpmProperties.tpmProperty[i];
279 switch (tp.property)
280 {
281 case TPM2_PT_REVISION:
282 revision = tp.value;
283 break;
284 case TPM2_PT_YEAR:
285 year = tp.value;
286 break;
287 case TPM2_PT_MANUFACTURER:
288 vendor = tp.value;
289 htoun32(manufacturer, tp.value);
290 break;
291 case TPM2_PT_VENDOR_STRING_1:
292 case TPM2_PT_VENDOR_STRING_2:
293 case TPM2_PT_VENDOR_STRING_3:
294 case TPM2_PT_VENDOR_STRING_4:
295 offset = 4 * (tp.property - TPM2_PT_VENDOR_STRING_1);
296 htoun32(vendor_string + offset, tp.value);
297 break;
298 case TPM2_PT_MODES:
299 if (tp.value & TPMA_MODES_FIPS_140_2)
300 {
301 this->fips_186_4 = fips_140_2 = TRUE;
302 }
303 break;
304 default:
305 break;
306 }
307 }
308
309 if (!fips_140_2)
310 {
311 this->fips_186_4 = lib->settings->get_bool(lib->settings,
312 "%s.plugins.tpm.fips_186_4", FALSE, lib->ns);
313 }
314 DBG2(DBG_PTS, LABEL "manufacturer: %s (%s) rev: %05.2f %u %s",
315 manufacturer, vendor_string, (float)revision/100, year,
316 fips_140_2 ? "FIPS 140-2" : (this->fips_186_4 ? "FIPS 186-4" : ""));
317
318 /* determine if TPM uses old event digest format and a different locality */
319 if (streq(manufacturer, "INTC"))
320 {
321 locality = 0;
322
323 if (revision == 116 && year == 2016)
324 {
325 this->old_event_digest_format = TRUE;
326 }
327 }
328
329 /* construct TPM 2.0 version_info object */
330 writer = bio_writer_create( TPM2_VERSION_INFO_SIZE);
331 writer->write_uint16(writer, TPM2_VERSION_INFO_TAG);
332 writer->write_uint8(writer, TPM2_VERSION_INFO_RESERVED);
333 writer->write_uint8(writer, locality);
334 writer->write_uint32(writer, revision);
335 writer->write_uint32(writer, year);
336 writer->write_uint32(writer, vendor);
337 this->version_info = writer->extract_buf(writer);
338 writer->destroy(writer);
339
340 /* get supported algorithms */
341 this->mutex->lock(this->mutex);
342 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ALGS,
343 0, TPM2_PT_ALGORITHM_SET, &more_data, &cap_data, 0);
344 this->mutex->unlock(this->mutex);
345 if (rval != TPM2_RC_SUCCESS)
346 {
347 DBG1(DBG_PTS, LABEL "GetCapability failed for TPM2_CAP_ALGS: 0x%06x",
348 rval);
349 return FALSE;
350 }
351
352 /* Number of supported algorithms */
353 this->supported_algs_count = cap_data.data.algorithms.count;
354
355 /* store and print supported algorithms */
356 for (i = 0; i < this->supported_algs_count; i++)
357 {
358 alg = cap_data.data.algorithms.algProperties[i].alg;
359 this->supported_algs[i] = alg;
360
361 written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
362 if (written < 0 || written >= len)
363 {
364 break;
365 }
366 pos += written;
367 len -= written;
368 }
369 DBG2(DBG_PTS, LABEL "algorithms:%s", buf);
370
371 /* get supported ECC curves */
372 this->mutex->lock(this->mutex);
373 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_ECC_CURVES,
374 0, TPM2_PT_LOADED_CURVES, &more_data, &cap_data, 0);
375 this->mutex->unlock(this->mutex);
376 if (rval != TPM2_RC_SUCCESS)
377 {
378 DBG1(DBG_PTS, LABEL "GetCapability failed for TPM2_CAP_ECC_CURVES: 0x%06x",
379 rval);
380 return FALSE;
381 }
382
383 /* reset print buffer */
384 pos = buf;
385 len = BUF_LEN;
386
387 /* print supported ECC curves */
388 for (i = 0; i < cap_data.data.eccCurves.count; i++)
389 {
390 written = snprintf(pos, len, " %N", tpm_ecc_curve_names,
391 cap_data.data.eccCurves.eccCurves[i]);
392 if (written < 0 || written >= len)
393 {
394 break;
395 }
396 pos += written;
397 len -= written;
398 }
399 DBG2(DBG_PTS, LABEL "ECC curves:%s", buf);
400
401 /* get assigned PCR banks */
402 this->mutex->lock(this->mutex);
403 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_PCRS,
404 0, MAX_PCR_BANKS, &more_data, &cap_data, 0);
405 this->mutex->unlock(this->mutex);
406 if (rval != TPM2_RC_SUCCESS)
407 {
408 DBG1(DBG_PTS, LABEL "GetCapability failed for TPM2_CAP_PCRS: 0x%06x",
409 rval);
410 return FALSE;
411 }
412
413 /* Number of assigned PCR banks */
414 this->assigned_pcrs_count = cap_data.data.assignedPCR.count;
415
416 /* reset print buffer */
417 pos = buf;
418 len = BUF_LEN;
419
420 /* store and print assigned PCR banks */
421 for (i = 0; i < cap_data.data.assignedPCR.count; i++)
422 {
423 alg = cap_data.data.assignedPCR.pcrSelections[i].hash;
424 this->assigned_pcrs[i] = alg;
425 written = snprintf(pos, len, " %N", tpm_alg_id_names, alg);
426 if (written < 0 || written >= len)
427 {
428 break;
429 }
430 pos += written;
431 len -= written;
432 }
433 DBG2(DBG_PTS, LABEL "PCR banks:%s", buf);
434
435 return TRUE;
436 }
437
438 /**
439 * Initialize TSS2 TCTI context
440 */
441 static bool initialize_tcti_context(private_tpm_tss_tss2_t *this)
442 {
443 size_t tcti_context_size;
444 uint32_t rval;
445
446 if (!tcti_init)
447 {
448 return FALSE;
449 }
450
451 /* determine size of tcti context */
452 rval = tcti_init(NULL, &tcti_context_size, tcti_opts);
453 if (rval != TSS2_RC_SUCCESS)
454 {
455 DBG1(DBG_PTS, LABEL "tcti init setup failed: 0x%06x", rval);
456 return FALSE;
457 }
458
459 /* allocate and initialize memory for tcti context */
460 this->tcti_context = (TSS2_TCTI_CONTEXT*)malloc(tcti_context_size);
461 memset(this->tcti_context, 0x00, tcti_context_size);
462
463 /* initialize tcti context */
464 rval = tcti_init(this->tcti_context, &tcti_context_size, tcti_opts);
465 if (rval != TSS2_RC_SUCCESS)
466 {
467 DBG1(DBG_PTS, LABEL "tcti init allocation failed: 0x%06x", rval);
468 return FALSE;
469 }
470 return TRUE;
471 }
472
473 /**
474 * Initialize TSS2 Sys context
475 */
476 static bool initialize_sys_context(private_tpm_tss_tss2_t *this)
477 {
478 uint32_t sys_context_size;
479 uint32_t rval;
480
481 TSS2_ABI_VERSION abi_version = {
482 .tssCreator = 1,
483 .tssFamily = 2,
484 .tssLevel = 1,
485 .tssVersion = 108
486 };
487
488 /* determine size of sys context */
489 sys_context_size = Tss2_Sys_GetContextSize(0);
490
491 /* allocate memory for sys context */
492 this->sys_context = (TSS2_SYS_CONTEXT*)malloc(sys_context_size);
493
494 /* initialize sys context */
495 rval = Tss2_Sys_Initialize(this->sys_context, sys_context_size,
496 this->tcti_context, &abi_version);
497 if (rval != TSS2_RC_SUCCESS)
498 {
499 DBG1(DBG_PTS, LABEL "could not get sys_context: 0x%06x", rval);
500 return FALSE;
501 }
502
503 /* get a list of supported algorithms and ECC curves */
504 return get_algs_capability(this);
505 }
506
507 /**
508 * Finalize TSS context
509 */
510 static void finalize_context(private_tpm_tss_tss2_t *this)
511 {
512 if (this->tcti_context)
513 {
514 Tss2_Tcti_Finalize(this->tcti_context);
515 free(this->tcti_context);
516 }
517 if (this->sys_context)
518 {
519 Tss2_Sys_Finalize(this->sys_context);
520 free(this->sys_context);
521 }
522 }
523
524 METHOD(tpm_tss_t, get_version, tpm_version_t,
525 private_tpm_tss_tss2_t *this)
526 {
527 return TPM_VERSION_2_0;
528 }
529
530 METHOD(tpm_tss_t, get_version_info, chunk_t,
531 private_tpm_tss_tss2_t *this)
532 {
533 return this->version_info;
534 }
535
536 /**
537 * read the public key portion of a TSS 2.0 key from NVRAM
538 */
539 bool read_public(private_tpm_tss_tss2_t *this, TPMI_DH_OBJECT handle,
540 TPM2B_PUBLIC *public)
541 {
542 uint32_t rval;
543
544 TPM2B_NAME name = { sizeof(TPM2B_NAME)-2, };
545 TPM2B_NAME qualified_name = { sizeof(TPM2B_NAME)-2, };
546 TSS2L_SYS_AUTH_RESPONSE auth_rsp;
547
548
549 /* read public key for a given object handle from TPM 2.0 NVRAM */
550 this->mutex->lock(this->mutex);
551 rval = Tss2_Sys_ReadPublic(this->sys_context, handle, 0, public, &name,
552 &qualified_name, &auth_rsp);
553 this->mutex->unlock(this->mutex);
554 if (rval != TPM2_RC_SUCCESS)
555 {
556 DBG1(DBG_PTS, LABEL "could not read public key from handle 0x%08x: 0x%06x",
557 handle, rval);
558 return FALSE;
559 }
560 return TRUE;
561 }
562
563 METHOD(tpm_tss_t, generate_aik, bool,
564 private_tpm_tss_tss2_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
565 chunk_t *aik_pubkey, chunk_t *identity_req)
566 {
567 return FALSE;
568 }
569
570 METHOD(tpm_tss_t, get_public, chunk_t,
571 private_tpm_tss_tss2_t *this, uint32_t handle)
572 {
573 TPM2B_PUBLIC public = { 0, };
574 chunk_t aik_pubkey = chunk_empty;
575
576 if (!read_public(this, handle, &public))
577 {
578 return chunk_empty;
579 }
580
581 /* convert TSS 2.0 public key blot into PKCS#1 format */
582 switch (public.publicArea.type)
583 {
584 case TPM2_ALG_RSA:
585 {
586 TPM2B_PUBLIC_KEY_RSA *rsa;
587 chunk_t aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
588 chunk_t aik_modulus;
589 uint32_t exponent;
590
591 rsa = &public.publicArea.unique.rsa;
592 aik_modulus = chunk_create(rsa->buffer, rsa->size);
593 exponent = htonl(public.publicArea.parameters.rsaDetail.exponent);
594 if (exponent)
595 {
596 aik_exponent = chunk_from_thing(exponent);
597 }
598
599 /* subjectPublicKeyInfo encoding of RSA public key */
600 if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
601 NULL, &aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
602 CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
603 {
604 DBG1(DBG_PTS, LABEL "subjectPublicKeyInfo encoding of public key "
605 "failed");
606 return chunk_empty;
607 }
608 break;
609 }
610 case TPM2_ALG_ECC:
611 {
612 TPMS_ECC_POINT *ecc;
613 chunk_t ecc_point;
614 int curve_oid;
615 uint8_t *pos;
616
617 /* determine ECC curveID */
618 switch (public.publicArea.parameters.eccDetail.curveID)
619 {
620 case TPM2_ECC_NIST_P192:
621 curve_oid = OID_PRIME192V1;
622 break;
623 case TPM2_ECC_NIST_P224:
624 curve_oid = OID_SECT224R1;
625 break;
626 case TPM2_ECC_NIST_P256:
627 curve_oid = OID_PRIME256V1;
628 break;
629 case TPM2_ECC_NIST_P384:
630 curve_oid = OID_SECT384R1;
631 break;
632 case TPM2_ECC_NIST_P521:
633 curve_oid = OID_SECT521R1;
634 break;
635 default:
636 DBG1(DBG_PTS, "ECC curve type not supported");
637 return chunk_empty;
638 }
639
640 ecc = &public.publicArea.unique.ecc;
641
642 /* allocate space for bit string */
643 pos = asn1_build_object(&ecc_point, ASN1_BIT_STRING,
644 2 + ecc->x.size + ecc->y.size);
645 /* bit string length is a multiple of octets */
646 *pos++ = 0x00;
647 /* uncompressed ECC point format */
648 *pos++ = 0x04;
649 /* copy x coordinate of ECC point */
650 memcpy(pos, ecc->x.buffer, ecc->x.size);
651 pos += ecc->x.size;
652 /* copy y coordinate of ECC point */
653 memcpy(pos, ecc->y.buffer, ecc->y.size);
654
655 /* subjectPublicKeyInfo encoding of ECC public key */
656 aik_pubkey = asn1_wrap(ASN1_SEQUENCE, "mm",
657 asn1_wrap(ASN1_SEQUENCE, "mm",
658 asn1_build_known_oid(OID_EC_PUBLICKEY),
659 asn1_build_known_oid(curve_oid)),
660 ecc_point);
661 break;
662 }
663 default:
664 DBG1(DBG_PTS, LABEL "unsupported key type");
665 return chunk_empty;
666 }
667 if (public.publicArea.objectAttributes & TPMA_OBJECT_SIGN_ENCRYPT)
668 {
669 TPMT_ASYM_SCHEME *s;
670
671 s = &public.publicArea.parameters.asymDetail.scheme;
672 DBG1(DBG_PTS, "signature algorithm is %N with %N hash",
673 tpm_alg_id_names, s->scheme,
674 tpm_alg_id_names, s->details.anySig.hashAlg);
675 }
676 if (public.publicArea.objectAttributes & TPMA_OBJECT_DECRYPT)
677 {
678 TPMT_SYM_DEF_OBJECT *s;
679
680 s = &public.publicArea.parameters.asymDetail.symmetric;
681 DBG1(DBG_PTS, "encryption algorithm is %N-%N with %u bits",
682 tpm_alg_id_names, s->algorithm,
683 tpm_alg_id_names, s->mode, s->keyBits.sym);
684 }
685
686 return aik_pubkey;
687 }
688
689 METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
690 private_tpm_tss_tss2_t *this, uint32_t handle)
691 {
692 TPM2B_PUBLIC public = { 0, };
693 hash_algorithm_t digest;
694 signature_params_t supported_scheme;
695
696 if (!read_public(this, handle, &public))
697 {
698 return enumerator_create_empty();
699 }
700
701 switch (public.publicArea.type)
702 {
703 case TPM2_ALG_RSA:
704 {
705 TPMS_RSA_PARMS *rsa;
706 TPMT_RSA_SCHEME *scheme;
707
708 rsa = &public.publicArea.parameters.rsaDetail;
709 scheme = &rsa->scheme;
710 digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
711
712 switch (scheme->scheme)
713 {
714 case TPM2_ALG_RSAPSS:
715 {
716 ssize_t salt_len;
717
718 salt_len = this->fips_186_4 ? RSA_PSS_SALT_LEN_DEFAULT :
719 RSA_PSS_SALT_LEN_MAX;
720 rsa_pss_params_t pss_params = {
721 .hash = digest,
722 .mgf1_hash = digest,
723 .salt_len = salt_len,
724 };
725 supported_scheme = (signature_params_t){
726 .scheme = SIGN_RSA_EMSA_PSS,
727 .params = &pss_params,
728 };
729 if (!rsa_pss_params_set_salt_len(&pss_params, rsa->keyBits))
730 {
731 return enumerator_create_empty();
732 }
733 break;
734 }
735 case TPM2_ALG_RSASSA:
736 supported_scheme = (signature_params_t){
737 .scheme = signature_scheme_from_oid(
738 hasher_signature_algorithm_to_oid(digest,
739 KEY_RSA)),
740 };
741 break;
742 default:
743 return enumerator_create_empty();
744 }
745 break;
746 }
747 case TPM2_ALG_ECC:
748 {
749 TPMT_ECC_SCHEME *scheme;
750
751 scheme = &public.publicArea.parameters.eccDetail.scheme;
752 digest = hash_alg_from_tpm_alg_id(scheme->details.anySig.hashAlg);
753
754 switch (scheme->scheme)
755 {
756 case TPM2_ALG_ECDSA:
757 supported_scheme = (signature_params_t){
758 .scheme = signature_scheme_from_oid(
759 hasher_signature_algorithm_to_oid(digest,
760 KEY_ECDSA)),
761 };
762 break;
763 default:
764 return enumerator_create_empty();
765 }
766 break;
767 }
768 default:
769 DBG1(DBG_PTS, LABEL "unsupported key type");
770 return enumerator_create_empty();
771 }
772 return enumerator_create_single(signature_params_clone(&supported_scheme),
773 (void*)signature_params_destroy);
774 }
775
776 METHOD(tpm_tss_t, has_pcr_bank, bool,
777 private_tpm_tss_tss2_t *this, hash_algorithm_t alg)
778 {
779 TPM2_ALG_ID alg_id;
780 int i;
781
782 alg_id = hash_alg_to_tpm_alg_id(alg);
783
784 for (i = 0; i < this->assigned_pcrs_count; i++)
785 {
786 if (this->assigned_pcrs[i] == alg_id)
787 {
788 return TRUE;
789 }
790 }
791
792 return FALSE;
793 }
794
795 /**
796 * Configure a PCR Selection assuming a maximum of 24 registers
797 */
798 static bool init_pcr_selection(private_tpm_tss_tss2_t *this, uint32_t pcrs,
799 hash_algorithm_t alg, TPML_PCR_SELECTION *pcr_sel)
800 {
801 uint32_t pcr;
802
803 /* check if there is an assigned PCR bank for this hash algorithm */
804 if (!has_pcr_bank(this, alg))
805 {
806 DBG1(DBG_PTS, LABEL "%N hash algorithm not supported by any PCR bank",
807 hash_algorithm_short_names, alg);
808 return FALSE;
809 }
810
811 /* initialize the PCR Selection structure,*/
812 pcr_sel->count = 1;
813 pcr_sel->pcrSelections[0].hash = hash_alg_to_tpm_alg_id(alg);
814 ;
815 pcr_sel->pcrSelections[0].sizeofSelect = 3;
816 pcr_sel->pcrSelections[0].pcrSelect[0] = 0;
817 pcr_sel->pcrSelections[0].pcrSelect[1] = 0;
818 pcr_sel->pcrSelections[0].pcrSelect[2] = 0;
819
820 /* set the selected PCRs */
821 for (pcr = 0; pcr < PLATFORM_PCR; pcr++)
822 {
823 if (pcrs & (1 << pcr))
824 {
825 pcr_sel->pcrSelections[0].pcrSelect[pcr / 8] |= ( 1 << (pcr % 8) );
826 }
827 }
828 return TRUE;
829 }
830
831 METHOD(tpm_tss_t, read_pcr, bool,
832 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
833 hash_algorithm_t alg)
834 {
835 TPML_PCR_SELECTION pcr_selection;
836 TPML_DIGEST pcr_values;
837
838 uint32_t pcr_update_counter, rval;
839 uint8_t *pcr_value_ptr;
840 size_t pcr_value_len;
841
842 if (pcr_num >= PLATFORM_PCR)
843 {
844 DBG1(DBG_PTS, LABEL "maximum number of supported PCR is %d",
845 PLATFORM_PCR);
846 return FALSE;
847 }
848
849 if (!init_pcr_selection(this, (1 << pcr_num), alg, &pcr_selection))
850 {
851 return FALSE;
852 }
853
854 /* initialize the PCR Digest structure */
855 memset(&pcr_values, 0, sizeof(TPML_DIGEST));
856
857 /* read the PCR value */
858 this->mutex->lock(this->mutex);
859 rval = Tss2_Sys_PCR_Read(this->sys_context, 0, &pcr_selection,
860 &pcr_update_counter, &pcr_selection, &pcr_values, 0);
861 this->mutex->unlock(this->mutex);
862 if (rval != TPM2_RC_SUCCESS)
863 {
864 DBG1(DBG_PTS, LABEL "PCR bank could not be read: 0x%60x", rval);
865 return FALSE;
866 }
867 pcr_value_ptr = (uint8_t *)pcr_values.digests[0].buffer;
868 pcr_value_len = (size_t) pcr_values.digests[0].size;
869
870 *pcr_value = chunk_clone(chunk_create(pcr_value_ptr, pcr_value_len));
871
872 return TRUE;
873 }
874
875 METHOD(tpm_tss_t, extend_pcr, bool,
876 private_tpm_tss_tss2_t *this, uint32_t pcr_num, chunk_t *pcr_value,
877 chunk_t data, hash_algorithm_t alg)
878 {
879 uint32_t rval;
880 TPML_DIGEST_VALUES digest_values;
881 TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
882 TSS2L_SYS_AUTH_RESPONSE auth_rsp;
883
884 auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
885
886 /* check if there is an assigned PCR bank for this hash algorithm */
887 if (!has_pcr_bank(this, alg))
888 {
889 DBG1(DBG_PTS, LABEL "%N hash algorithm not supported by any PCR bank",
890 hash_algorithm_short_names, alg);
891 return FALSE;
892 }
893
894 digest_values.count = 1;
895 digest_values.digests[0].hashAlg = hash_alg_to_tpm_alg_id(alg);
896
897 switch (alg)
898 {
899 case HASH_SHA1:
900 if (data.len != HASH_SIZE_SHA1)
901 {
902 return FALSE;
903 }
904 memcpy(digest_values.digests[0].digest.sha1, data.ptr,
905 HASH_SIZE_SHA1);
906 break;
907 case HASH_SHA256:
908 case HASH_SHA3_256:
909 if (data.len != HASH_SIZE_SHA256)
910 {
911 return FALSE;
912 }
913 memcpy(digest_values.digests[0].digest.sha256, data.ptr,
914 HASH_SIZE_SHA256);
915 break;
916 case HASH_SHA384:
917 case HASH_SHA3_384:
918 if (data.len != HASH_SIZE_SHA384)
919 {
920 return FALSE;
921 }
922 memcpy(digest_values.digests[0].digest.sha384, data.ptr,
923 HASH_SIZE_SHA384);
924 break;
925 case HASH_SHA512:
926 case HASH_SHA3_512:
927 if (data.len != HASH_SIZE_SHA512)
928 {
929 return FALSE;
930 }
931 memcpy(digest_values.digests[0].digest.sha512, data.ptr,
932 HASH_SIZE_SHA512);
933 break;
934 default:
935 return FALSE;
936 }
937
938 /* extend PCR */
939 this->mutex->lock(this->mutex);
940 rval = Tss2_Sys_PCR_Extend(this->sys_context, pcr_num, &auth_cmd,
941 &digest_values, &auth_rsp);
942 this->mutex->unlock(this->mutex);
943 if (rval != TPM2_RC_SUCCESS)
944 {
945 DBG1(DBG_PTS, LABEL "PCR %02u could not be extended: 0x%06x",
946 pcr_num, rval);
947 return FALSE;
948 }
949
950 /* get updated PCR value */
951 return read_pcr(this, pcr_num, pcr_value, alg);
952 }
953
954 METHOD(tpm_tss_t, quote, bool,
955 private_tpm_tss_tss2_t *this, uint32_t aik_handle, uint32_t pcr_sel,
956 hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
957 tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
958 {
959 chunk_t quoted_chunk, qualified_signer, extra_data, clock_info,
960 firmware_version, pcr_select, pcr_digest;
961 hash_algorithm_t pcr_digest_alg;
962 bio_reader_t *reader;
963 uint32_t rval;
964
965 TPM2B_DATA qualifying_data;
966 TPML_PCR_SELECTION pcr_selection;
967 TPM2B_ATTEST quoted = { sizeof(TPM2B_ATTEST)-2, };
968 TPMT_SIG_SCHEME scheme;
969 TPMT_SIGNATURE sig;
970 TPMI_ALG_HASH hash_alg;
971 TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
972 TSS2L_SYS_AUTH_RESPONSE auth_rsp;
973
974 auth_cmd.auths[0].sessionHandle = TPM2_RS_PW;
975
976 qualifying_data.size = data.len;
977 memcpy(qualifying_data.buffer, data.ptr, data.len);
978
979 scheme.scheme = TPM2_ALG_NULL;
980 memset(&sig, 0x00, sizeof(sig));
981
982 /* set Quote mode */
983 *quote_mode = TPM_QUOTE_TPM2;
984
985 if (!init_pcr_selection(this, pcr_sel, alg, &pcr_selection))
986 {
987 return FALSE;
988 }
989
990 this->mutex->lock(this->mutex);
991 rval = Tss2_Sys_Quote(this->sys_context, aik_handle, &auth_cmd,
992 &qualifying_data, &scheme, &pcr_selection, &quoted,
993 &sig, &auth_rsp);
994 this->mutex->unlock(this->mutex);
995 if (rval != TPM2_RC_SUCCESS)
996 {
997 DBG1(DBG_PTS, LABEL "Tss2_Sys_Quote failed: 0x%06x", rval);
998 return FALSE;
999 }
1000 quoted_chunk = chunk_create(quoted.attestationData, quoted.size);
1001
1002 reader = bio_reader_create(chunk_skip(quoted_chunk, 6));
1003 if (!reader->read_data16(reader, &qualified_signer) ||
1004 !reader->read_data16(reader, &extra_data) ||
1005 !reader->read_data (reader, 17, &clock_info) ||
1006 !reader->read_data (reader, 8, &firmware_version) ||
1007 !reader->read_data (reader, 10, &pcr_select) ||
1008 !reader->read_data16(reader, &pcr_digest))
1009 {
1010 DBG1(DBG_PTS, LABEL "parsing of quoted struct failed");
1011 reader->destroy(reader);
1012 return FALSE;
1013 }
1014 reader->destroy(reader);
1015
1016 DBG2(DBG_PTS, "PCR Composite digest: %B", &pcr_digest);
1017 DBG2(DBG_PTS, "TPM Quote Info: %B", &quoted_chunk);
1018 DBG2(DBG_PTS, "qualifiedSigner: %B", &qualified_signer);
1019 DBG2(DBG_PTS, "extraData: %B", &extra_data);
1020 DBG2(DBG_PTS, "clockInfo: %B", &clock_info);
1021 DBG2(DBG_PTS, "firmwareVersion: %B", &firmware_version);
1022 DBG2(DBG_PTS, "pcrSelect: %B", &pcr_select);
1023
1024 /* extract signature */
1025 switch (sig.sigAlg)
1026 {
1027 case TPM2_ALG_RSASSA:
1028 case TPM2_ALG_RSAPSS:
1029 *quote_sig = chunk_clone(
1030 chunk_create(
1031 sig.signature.rsassa.sig.buffer,
1032 sig.signature.rsassa.sig.size));
1033 hash_alg = sig.signature.rsassa.hash;
1034 break;
1035 case TPM2_ALG_ECDSA:
1036 case TPM2_ALG_ECDAA:
1037 case TPM2_ALG_SM2:
1038 case TPM2_ALG_ECSCHNORR:
1039 *quote_sig = chunk_cat("cc",
1040 chunk_create(
1041 sig.signature.ecdsa.signatureR.buffer,
1042 sig.signature.ecdsa.signatureR.size),
1043 chunk_create(
1044 sig.signature.ecdsa.signatureS.buffer,
1045 sig.signature.ecdsa.signatureS.size));
1046 hash_alg = sig.signature.ecdsa.hash;
1047 break;
1048 default:
1049 DBG1(DBG_PTS, LABEL "unsupported %N signature algorithm",
1050 tpm_alg_id_names, sig.sigAlg);
1051 return FALSE;
1052 }
1053
1054 DBG2(DBG_PTS, "PCR digest algorithm is %N", tpm_alg_id_names, hash_alg);
1055 pcr_digest_alg = hash_alg_from_tpm_alg_id(hash_alg);
1056
1057 DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
1058
1059 /* Create and initialize Quote Info object */
1060 *quote_info = tpm_tss_quote_info_create(*quote_mode, pcr_digest_alg,
1061 pcr_digest);
1062 (*quote_info)->set_tpm2_info(*quote_info, qualified_signer, clock_info,
1063 pcr_select);
1064 (*quote_info)->set_version_info(*quote_info, firmware_version);
1065
1066 return TRUE;
1067 }
1068
1069 METHOD(tpm_tss_t, sign, bool,
1070 private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
1071 signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
1072 chunk_t *signature)
1073 {
1074 key_type_t key_type;
1075 hash_algorithm_t hash_alg;
1076 rsa_pss_params_t *rsa_pss_params;
1077 uint32_t rval;
1078
1079 TPM2_ALG_ID alg_id;
1080 TPM2B_MAX_BUFFER buffer;
1081 TPM2B_DIGEST hash = { sizeof(TPM2B_DIGEST)-2, };
1082 TPMT_TK_HASHCHECK validation;
1083 TPM2B_PUBLIC public = { 0, };
1084 TPMT_SIG_SCHEME sig_scheme;
1085 TPMT_SIGNATURE sig;
1086 TPMS_AUTH_COMMAND *cmd;
1087 TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
1088 TSS2L_SYS_AUTH_RESPONSE auth_rsp;
1089
1090 cmd = &auth_cmd.auths[0];
1091 cmd->sessionHandle = TPM2_RS_PW;
1092
1093 if (pin.len > 0)
1094 {
1095 cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
1096 memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
1097 }
1098
1099 if (scheme == SIGN_RSA_EMSA_PSS)
1100 {
1101 key_type = KEY_RSA;
1102 rsa_pss_params = (rsa_pss_params_t *)params;
1103 hash_alg = rsa_pss_params->hash;
1104 }
1105 else
1106 {
1107 key_type = key_type_from_signature_scheme(scheme);
1108 hash_alg = hasher_from_signature_scheme(scheme, NULL);
1109 }
1110
1111 /* Check if hash algorithm is supported by TPM */
1112 alg_id = hash_alg_to_tpm_alg_id(hash_alg);
1113 if (!is_supported_alg(this, alg_id))
1114 {
1115 DBG1(DBG_PTS, LABEL "%N hash algorithm not supported by TPM",
1116 hash_algorithm_short_names, hash_alg);
1117 return FALSE;
1118 }
1119
1120 /* Get public key */
1121 if (!read_public(this, handle, &public))
1122 {
1123 return FALSE;
1124 }
1125
1126 if (key_type == KEY_RSA && public.publicArea.type == TPM2_ALG_RSA)
1127 {
1128 if (scheme == SIGN_RSA_EMSA_PSS)
1129 {
1130 sig_scheme.scheme = TPM2_ALG_RSAPSS;
1131 sig_scheme.details.rsapss.hashAlg = alg_id;
1132 }
1133 else
1134 {
1135 sig_scheme.scheme = TPM2_ALG_RSASSA;
1136 sig_scheme.details.rsassa.hashAlg = alg_id;
1137 }
1138 }
1139 else if (key_type == KEY_ECDSA && public.publicArea.type == TPM2_ALG_ECC)
1140 {
1141 sig_scheme.scheme = TPM2_ALG_ECDSA;
1142 sig_scheme.details.ecdsa.hashAlg = alg_id;
1143
1144 }
1145 else
1146 {
1147 DBG1(DBG_PTS, LABEL "signature scheme %N not supported by TPM key",
1148 signature_scheme_names, scheme);
1149 return FALSE;
1150 }
1151
1152 if (data.len <= TPM2_MAX_DIGEST_BUFFER)
1153 {
1154 memcpy(buffer.buffer, data.ptr, data.len);
1155 buffer.size = data.len;
1156
1157 this->mutex->lock(this->mutex);
1158 rval = Tss2_Sys_Hash(this->sys_context, 0, &buffer, alg_id, hierarchy,
1159 &hash, &validation, 0);
1160 this->mutex->unlock(this->mutex);
1161 if (rval != TPM2_RC_SUCCESS)
1162 {
1163 DBG1(DBG_PTS,LABEL "Tss2_Sys_Hash failed: 0x%06x", rval);
1164 return FALSE;
1165 }
1166 }
1167 else
1168 {
1169 TPMI_DH_OBJECT sequence_handle;
1170 TPM2B_AUTH null_auth;
1171
1172 null_auth.size = 0;
1173 this->mutex->lock(this->mutex);
1174 rval = Tss2_Sys_HashSequenceStart(this->sys_context, 0, &null_auth,
1175 alg_id, &sequence_handle, 0);
1176 if (rval != TPM2_RC_SUCCESS)
1177 {
1178 DBG1(DBG_PTS, LABEL "Tss2_Sys_HashSequenceStart failed: 0x%06x",
1179 rval);
1180 this->mutex->unlock(this->mutex);
1181 return FALSE;
1182 }
1183
1184 while (data.len > 0)
1185 {
1186 buffer.size = min(data.len, TPM2_MAX_DIGEST_BUFFER);
1187 memcpy(buffer.buffer, data.ptr, buffer.size);
1188 data.ptr += buffer.size;
1189 data.len -= buffer.size;
1190
1191 rval = Tss2_Sys_SequenceUpdate(this->sys_context, sequence_handle,
1192 &auth_cmd, &buffer, 0);
1193 if (rval != TPM2_RC_SUCCESS)
1194 {
1195 DBG1(DBG_PTS, LABEL "Tss2_Sys_SequenceUpdate failed: 0x%06x",
1196 rval);
1197 this->mutex->unlock(this->mutex);
1198 return FALSE;
1199 }
1200 }
1201 buffer.size = 0;
1202
1203 rval = Tss2_Sys_SequenceComplete(this->sys_context, sequence_handle,
1204 &auth_cmd, &buffer, hierarchy,
1205 &hash, &validation, 0);
1206 this->mutex->unlock(this->mutex);
1207 if (rval != TPM2_RC_SUCCESS)
1208 {
1209 DBG1(DBG_PTS, LABEL "Tss2_Sys_SequenceComplete failed: 0x%06x",
1210 rval);
1211 return FALSE;
1212 }
1213 }
1214
1215 this->mutex->lock(this->mutex);
1216 rval = Tss2_Sys_Sign(this->sys_context, handle, &auth_cmd, &hash,
1217 &sig_scheme, &validation, &sig, &auth_rsp);
1218 this->mutex->unlock(this->mutex);
1219 if (rval != TPM2_RC_SUCCESS)
1220 {
1221 DBG1(DBG_PTS, LABEL "Tss2_Sys_Sign failed: 0x%06x", rval);
1222 return FALSE;
1223 }
1224
1225 /* extract signature */
1226 switch (scheme)
1227 {
1228 case SIGN_RSA_EMSA_PKCS1_SHA1:
1229 case SIGN_RSA_EMSA_PKCS1_SHA2_256:
1230 case SIGN_RSA_EMSA_PKCS1_SHA2_384:
1231 case SIGN_RSA_EMSA_PKCS1_SHA2_512:
1232 *signature = chunk_clone(
1233 chunk_create(
1234 sig.signature.rsassa.sig.buffer,
1235 sig.signature.rsassa.sig.size));
1236 break;
1237 case SIGN_RSA_EMSA_PSS:
1238 *signature = chunk_clone(
1239 chunk_create(
1240 sig.signature.rsapss.sig.buffer,
1241 sig.signature.rsapss.sig.size));
1242 break;
1243 case SIGN_ECDSA_256:
1244 case SIGN_ECDSA_384:
1245 case SIGN_ECDSA_521:
1246 *signature = chunk_cat("cc",
1247 chunk_create(
1248 sig.signature.ecdsa.signatureR.buffer,
1249 sig.signature.ecdsa.signatureR.size),
1250 chunk_create(
1251 sig.signature.ecdsa.signatureS.buffer,
1252 sig.signature.ecdsa.signatureS.size));
1253 break;
1254 case SIGN_ECDSA_WITH_SHA256_DER:
1255 case SIGN_ECDSA_WITH_SHA384_DER:
1256 case SIGN_ECDSA_WITH_SHA512_DER:
1257 *signature = asn1_wrap(ASN1_SEQUENCE, "mm",
1258 asn1_integer("c",
1259 chunk_create(
1260 sig.signature.ecdsa.signatureR.buffer,
1261 sig.signature.ecdsa.signatureR.size)),
1262 asn1_integer("c",
1263 chunk_create(
1264 sig.signature.ecdsa.signatureS.buffer,
1265 sig.signature.ecdsa.signatureS.size)));
1266 break;
1267 default:
1268 DBG1(DBG_PTS, LABEL "unsupported %N signature scheme",
1269 signature_scheme_names, scheme);
1270 return FALSE;
1271 }
1272
1273 return TRUE;
1274 }
1275
1276 /**
1277 * Check if an authenticated session with the TPM 2.0 can be started
1278 * The handle of the RSA Endorsement Key (EK) is required
1279 */
1280 static void try_session_start(private_tpm_tss_tss2_t *this)
1281 {
1282 uint32_t ek_handle = 0;
1283 chunk_t handle_chunk;
1284 char *handle_str;
1285
1286 TPM2B_PUBLIC public = { 0, };
1287
1288 /* get Endorsement Key (EK) handle from settings */
1289 handle_str = lib->settings->get_str(lib->settings,
1290 "%s.plugins.tpm.ek_handle", NULL, lib->ns);
1291 if (handle_str)
1292 {
1293 handle_chunk = chunk_from_hex(chunk_from_str(handle_str),
1294 (char *)&ek_handle);
1295 ek_handle = (handle_chunk.len == 4) ? htonl(ek_handle) : 0;
1296
1297 /* establish protected auth session if ek_handle is set */
1298 if (ek_handle && read_public(this, ek_handle, &public))
1299 {
1300 this->mutex->lock(this->mutex);
1301 this->session = tpm_tss_tss2_session_create(ek_handle, &public,
1302 this->sys_context);
1303 this->mutex->unlock(this->mutex);
1304 }
1305 }
1306 }
1307
1308 METHOD(tpm_tss_t, get_random, bool,
1309 private_tpm_tss_tss2_t *this, size_t bytes, uint8_t *buffer)
1310 {
1311 size_t len, random_len = sizeof(TPM2B_DIGEST)-2;
1312 TPM2B_DIGEST random = { random_len, };
1313 uint8_t *pos = buffer;
1314 uint32_t rval;
1315
1316 if (!this->session)
1317 {
1318 try_session_start(this);
1319 }
1320
1321 while (bytes > 0)
1322 {
1323 bool success = FALSE;
1324
1325 len = min(bytes, random_len);
1326 this->mutex->lock(this->mutex);
1327
1328 rval = Tss2_Sys_GetRandom_Prepare(this->sys_context, len);
1329 if (rval != TSS2_RC_SUCCESS)
1330 {
1331 DBG1(DBG_PTS, "%s Tss2_Sys_GetRandom_Prepare failed: 0x%06x",
1332 LABEL, rval);
1333 goto error;
1334 }
1335
1336 if (this->session && !this->session->set_cmd_auths(this->session))
1337 {
1338 goto error;
1339 }
1340
1341 rval = Tss2_Sys_Execute(this->sys_context);
1342 if (rval != TSS2_RC_SUCCESS)
1343 {
1344 DBG1(DBG_PTS, LABEL "Tss2_Sys_Execute failed: 0x%06x", rval);
1345 goto error;
1346 }
1347
1348 if (this->session && !this->session->get_rsp_auths(this->session))
1349 {
1350 goto error;
1351 }
1352
1353 rval = Tss2_Sys_GetRandom_Complete(this->sys_context, &random);
1354 if (rval != TSS2_RC_SUCCESS)
1355 {
1356 DBG1(DBG_PTS, LABEL "Tss2_Sys_GetRandom_Complete failed: 0x%06x",
1357 rval);
1358 goto error;
1359 }
1360 success = TRUE;
1361
1362 error:
1363 this->mutex->unlock(this->mutex);
1364 if (!success)
1365 {
1366 return FALSE;
1367 }
1368
1369 memcpy(pos, random.buffer, random.size);
1370 pos += random.size;
1371 bytes -= random.size;
1372 }
1373
1374 return TRUE;
1375 }
1376
1377 METHOD(tpm_tss_t, get_data, bool,
1378 private_tpm_tss_tss2_t *this, uint32_t hierarchy, uint32_t handle,
1379 chunk_t pin, chunk_t *data)
1380 {
1381 uint16_t max_data_size, nv_size, nv_offset = 0;
1382 uint32_t rval;
1383
1384 TPMS_CAPABILITY_DATA cap_data;
1385 TPMI_YES_NO more_data;
1386 TPM2B_NAME nv_name = { sizeof(TPM2B_NAME)-2, };
1387 TPM2B_NV_PUBLIC nv_public = { 0, };
1388 TPM2B_MAX_NV_BUFFER nv_data = { TPM2_MAX_NV_BUFFER_SIZE, };
1389 TPMS_AUTH_COMMAND *cmd;
1390 TSS2L_SYS_AUTH_COMMAND auth_cmd = { 1, { auth_cmd_empty } };
1391 TSS2L_SYS_AUTH_RESPONSE auth_rsp;
1392
1393 /* query maximum TPM data transmission size */
1394 this->mutex->lock(this->mutex);
1395 rval = Tss2_Sys_GetCapability(this->sys_context, 0, TPM2_CAP_TPM_PROPERTIES,
1396 TPM2_PT_NV_BUFFER_MAX, 1, &more_data, &cap_data, 0);
1397 this->mutex->unlock(this->mutex);
1398 if (rval != TPM2_RC_SUCCESS)
1399 {
1400 DBG1(DBG_PTS, LABEL "Tss2_Sys_GetCapability failed for "
1401 "TPM2_CAP_TPM_PROPERTIES: 0x%06x", rval);
1402 return FALSE;
1403 }
1404 max_data_size = min(cap_data.data.tpmProperties.tpmProperty[0].value,
1405 TPM2_MAX_NV_BUFFER_SIZE);
1406
1407 /* get size of NV object */
1408 this->mutex->lock(this->mutex);
1409 rval = Tss2_Sys_NV_ReadPublic(this->sys_context, handle, 0, &nv_public,
1410 &nv_name, 0);
1411 this->mutex->unlock(this->mutex);
1412 if (rval != TPM2_RC_SUCCESS)
1413 {
1414 DBG1(DBG_PTS, LABEL "Tss2_Sys_NV_ReadPublic failed: 0x%06x", rval);
1415 return FALSE;
1416 }
1417 nv_size = nv_public.nvPublic.dataSize;
1418 *data = chunk_alloc(nv_size);
1419
1420 /* prepare NV read session */
1421 cmd = &auth_cmd.auths[0];
1422 cmd->sessionHandle = TPM2_RS_PW;
1423
1424 if (pin.len > 0)
1425 {
1426 cmd->hmac.size = min(sizeof(cmd->hmac)-2, pin.len);
1427 memcpy(cmd->hmac.buffer, pin.ptr, cmd->hmac.size);
1428 }
1429
1430 /* read NV data a maximum data size block at a time */
1431 while (nv_size > 0)
1432 {
1433 this->mutex->lock(this->mutex);
1434 rval = Tss2_Sys_NV_Read(this->sys_context, hierarchy, handle, &auth_cmd,
1435 min(nv_size, max_data_size), nv_offset, &nv_data, &auth_rsp);
1436 this->mutex->unlock(this->mutex);
1437 if (rval != TPM2_RC_SUCCESS)
1438 {
1439 DBG1(DBG_PTS, LABEL "Tss2_Sys_NV_Read failed: 0x%06x", rval);
1440 chunk_free(data);
1441 return FALSE;
1442 }
1443 memcpy(data->ptr + nv_offset, nv_data.buffer, nv_data.size);
1444 nv_offset += nv_data.size;
1445 nv_size -= nv_data.size;
1446 }
1447
1448 return TRUE;
1449 }
1450
1451 METHOD(tpm_tss_t, get_event_digest, bool,
1452 private_tpm_tss_tss2_t *this, int fd, hash_algorithm_t alg, chunk_t *digest)
1453 {
1454 uint8_t digest_buf[HASH_SIZE_SHA512];
1455 uint32_t digest_count;
1456 size_t digest_len = 0;
1457 hash_algorithm_t hash_alg;
1458 TPM2_ALG_ID alg_id;
1459
1460 if (this->old_event_digest_format)
1461 {
1462 if (alg != HASH_SHA1)
1463 {
1464 return FALSE;
1465 }
1466 digest_len = HASH_SIZE_SHA1;
1467
1468 *digest = chunk_alloc(digest_len);
1469
1470 if (read(fd, digest->ptr, digest_len) != digest_len)
1471 {
1472 return FALSE;
1473 }
1474 }
1475 else
1476 {
1477 if (read(fd, &digest_count, 4) != 4)
1478 {
1479 return FALSE;
1480 }
1481 while (digest_count--)
1482 {
1483 if (read(fd, &alg_id, 2) != 2)
1484 {
1485 return FALSE;
1486 }
1487 hash_alg = hash_alg_from_tpm_alg_id(alg_id);
1488 digest_len = hash_len_from_tpm_alg_id(alg_id);
1489
1490 if (hash_alg == alg)
1491 {
1492 *digest = chunk_alloc(digest_len);
1493 if (read(fd, digest->ptr, digest_len) != digest_len)
1494 {
1495 return FALSE;
1496 }
1497 }
1498 else
1499 {
1500 /* read without storing */
1501 if (read(fd, digest_buf, digest_len) != digest_len)
1502 {
1503 return FALSE;
1504 }
1505 }
1506 }
1507 }
1508
1509 return TRUE;
1510 }
1511
1512 METHOD(tpm_tss_t, destroy, void,
1513 private_tpm_tss_tss2_t *this)
1514 {
1515 DESTROY_IF(this->session);
1516 finalize_context(this);
1517 this->mutex->destroy(this->mutex);
1518 free(this->version_info.ptr);
1519 free(this);
1520 }
1521
1522 /**
1523 * See header
1524 */
1525 tpm_tss_t *tpm_tss_tss2_create()
1526 {
1527 private_tpm_tss_tss2_t *this;
1528 bool available;
1529
1530 INIT(this,
1531 .public = {
1532 .get_version = _get_version,
1533 .get_version_info = _get_version_info,
1534 .generate_aik = _generate_aik,
1535 .get_public = _get_public,
1536 .supported_signature_schemes = _supported_signature_schemes,
1537 .has_pcr_bank = _has_pcr_bank,
1538 .read_pcr = _read_pcr,
1539 .extend_pcr = _extend_pcr,
1540 .quote = _quote,
1541 .sign = _sign,
1542 .get_random = _get_random,
1543 .get_data = _get_data,
1544 .get_event_digest = _get_event_digest,
1545 .destroy = _destroy,
1546 },
1547 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
1548 );
1549
1550 available = initialize_tcti_context(this);
1551 if (available)
1552 {
1553 available = initialize_sys_context(this);
1554 }
1555 DBG1(DBG_PTS, "TPM 2.0 via TSS2 v2 %savailable", available ? "" : "not ");
1556
1557 if (!available)
1558 {
1559 destroy(this);
1560 return NULL;
1561 }
1562
1563 return &this->public;
1564 }
1565
1566 /**
1567 * See header
1568 */
1569 bool tpm_tss_tss2_init(void)
1570 {
1571 TSS2_TCTI_INFO_FUNC infofn;
1572 const TSS2_TCTI_INFO *info;
1573 char tcti_lib_format[] = "libtss2-tcti-%s.so.0";
1574 char tcti_lib[BUF_LEN];
1575 char *tcti_names[] = { "device", "tabrmd", "mssim" };
1576 char *tcti_options[] = { "/dev/tpmrm0", "", "" };
1577 char *tcti_name;
1578 bool match = FALSE;
1579 struct stat st;
1580 int i = 0;
1581
1582 /* check for the existence of an in-kernel TPM resource manager */
1583 if (stat(tcti_options[i], &st))
1584 {
1585 i = 1;
1586 }
1587 DBG2(DBG_PTS, LABEL "\"%s\" in-kernel resource manager is %spresent",
1588 tcti_options[0], i ? "not " : "");
1589
1590 /* select a dynamic TCTI library (device, tabrmd or mssim) */
1591 tcti_name = lib->settings->get_str(lib->settings,
1592 "%s.plugins.tpm.tcti.name", tcti_names[i], lib->ns);
1593 snprintf(tcti_lib, BUF_LEN, tcti_lib_format, tcti_name);
1594
1595 for (i = 0; i < countof(tcti_names); i++)
1596 {
1597 if (streq(tcti_name, tcti_names[i]))
1598 {
1599 match = TRUE;
1600 break;
1601 }
1602 }
1603 if (!match)
1604 {
1605 DBG1(DBG_PTS, LABEL "\"%s\" is not a valid TCTI library name", tcti_lib);
1606 return FALSE;
1607 }
1608
1609 tcti_opts = lib->settings->get_str(lib->settings,
1610 "%s.plugins.tpm.tcti.opts", tcti_options[i], lib->ns);
1611
1612 /* open the selected dynamic TCTI library */
1613 tcti_handle = dlopen(tcti_lib, RTLD_LAZY);
1614 if (!tcti_handle)
1615 {
1616 DBG1(DBG_PTS, LABEL "could not load \"%s\"", tcti_lib);
1617 return FALSE;
1618 }
1619
1620 infofn = (TSS2_TCTI_INFO_FUNC)dlsym(tcti_handle, TSS2_TCTI_INFO_SYMBOL);
1621 if (!infofn)
1622 {
1623 DBG1(DBG_PTS, LABEL "symbol \"%s\" not found in \"%s\"",
1624 TSS2_TCTI_INFO_SYMBOL, tcti_lib);
1625 tpm_tss_tss2_deinit();
1626
1627 return FALSE;
1628 }
1629 DBG2(DBG_PTS, LABEL "\"%s\" successfully loaded", tcti_lib);
1630 info = infofn();
1631 tcti_init = info->init;
1632
1633 return TRUE;
1634 }
1635
1636 /**
1637 * See header
1638 */
1639 void tpm_tss_tss2_deinit(void)
1640 {
1641 dlclose(tcti_handle);
1642 tcti_handle = NULL;
1643 tcti_init = NULL;
1644 tcti_opts = NULL;
1645 }
1646
1647 #else /* TSS_TSS2_V2 */
1648
1649 /**
1650 * See header
1651 */
1652 bool tpm_tss_tss2_init(void)
1653 {
1654 return TRUE;
1655 }
1656
1657 /**
1658 * See header
1659 */
1660 void tpm_tss_tss2_deinit(void)
1661 {
1662 /* empty */
1663 }
1664
1665 #endif /* TSS_TSS2_V2 */
1666