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