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