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