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