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