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