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