]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libtpmtss/tpm_tss_trousers.c
pts: Parse TPM 2.0 BIOS/EFI event log
[thirdparty/strongswan.git] / src / libtpmtss / tpm_tss_trousers.c
CommitLineData
c08753bd 1/*
d647a8f9 2 * Copyright (C) 2016-2020 Andreas Steffen
c08753bd
AS
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (c) 2008 Hal Finney
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26#include "tpm_tss_trousers.h"
27
28#ifdef TSS_TROUSERS
29
30d4989a
AS
30#ifdef _BASETSD_H_
31/* MinGW defines _BASETSD_H_, but TSS checks for _BASETSD_H */
32# define _BASETSD_H
33#endif
34
c08753bd
AS
35#include <trousers/tss.h>
36#include <trousers/trousers.h>
37
d647a8f9
AS
38#include <unistd.h>
39
c08753bd
AS
40#define LABEL "TPM 1.2 -"
41
42/* size in bytes of a TSS AIK public key blob */
30d4989a
AS
43#define AIK_PUBKEY_BLOB_SIZE 284
44
45/* maximum number of PCR registers */
46#define PCR_NUM_MAX 24
c08753bd
AS
47
48typedef struct private_tpm_tss_trousers_t private_tpm_tss_trousers_t;
30d4989a 49typedef struct aik_t aik_t;
c08753bd
AS
50
51/**
52 * Private data of an tpm_tss_trousers_t object.
53 */
54struct private_tpm_tss_trousers_t {
55
56 /**
57 * Public tpm_tss_trousers_t interface.
58 */
30d4989a 59 tpm_tss_trousers_t interface;
c08753bd
AS
60
61 /**
62 * TSS context
63 */
64 TSS_HCONTEXT hContext;
65
30d4989a
AS
66 /**
67 * TPM handle
68 */
69 TSS_HTPM hTPM;
70
fedc6769
AS
71 /**
72 * TPM version info
73 */
74 chunk_t version_info;
75
30d4989a
AS
76 /**
77 * List of AIKs retrievable by an object handle
78 */
79 linked_list_t *aik_list;
80
c08753bd
AS
81};
82
30d4989a
AS
83struct aik_t {
84 /** AIK object handle */
85 uint32_t handle;
86
87 /** AIK private key blob */
88 chunk_t blob;
89
90 /** AIK public key */
91 chunk_t pubkey;
92};
93
94static void free_aik(aik_t *this)
95{
96 free(this->blob.ptr);
97 free(this->pubkey.ptr);
98 free(this);
99}
100
c08753bd
AS
101/**
102 * Initialize TSS context
fedc6769
AS
103 *
104 * TPM 1.2 Specification, Part 2 TPM Structures, 21.6 TPM_CAP_VERSION_INFO
105 *
106 * typedef struct tdTPM_VERSION {
107 * TPM_VERSION_BYTE major;
108 * TPM_VERSION_BYTE minor;
109 * BYTE revMajor;
110 * BYTE revMinor;
111 * } TPM_VERSION;
112 *
113 * typedef struct tdTPM_CAP_VERSION_INFO {
114 * TPM_STRUCTURE_TAG tag;
115 * TPM_VERSION version;
116 * UINT16 specLevel;
117 * BYTE errataRev;
118 * BYTE tpmVendorID[4];
119 * UINT16 vendorSpecificSize;
120 * [size_is(vendorSpecificSize)] BYTE* vendorSpecific;
121 * } TPM_CAP_VERSION_INFO;
c08753bd
AS
122 */
123static bool initialize_context(private_tpm_tss_trousers_t *this)
124{
fedc6769
AS
125 uint8_t *version_ptr;
126 uint32_t version_len;
127
c08753bd 128 TSS_RESULT result;
fedc6769 129 TPM_CAP_VERSION_INFO *info;
c08753bd
AS
130
131 result = Tspi_Context_Create(&this->hContext);
132 if (result != TSS_SUCCESS)
133 {
fedc6769
AS
134 DBG1(DBG_PTS, "%s could not created context: 0x%x",
135 LABEL, result);
c08753bd
AS
136 return FALSE;
137 }
138
139 result = Tspi_Context_Connect(this->hContext, NULL);
140 if (result != TSS_SUCCESS)
141 {
fedc6769
AS
142 DBG1(DBG_PTS, "%s could not connect with context: 0x%x",
143 LABEL, result);
c08753bd
AS
144 return FALSE;
145 }
146
30d4989a 147 result = Tspi_Context_GetTpmObject (this->hContext, &this->hTPM);
c08753bd
AS
148 if (result != TSS_SUCCESS)
149 {
fedc6769
AS
150 DBG1(DBG_PTS, "%s could not get TPM object: 0x%x",
151 LABEL, result);
152 return FALSE;
153 }
154
30d4989a
AS
155 result = Tspi_TPM_GetCapability(this->hTPM, TSS_TPMCAP_VERSION_VAL, 0,
156 NULL, &version_len, &version_ptr);
fedc6769
AS
157 if (result != TSS_SUCCESS)
158 {
159 DBG1(DBG_PTS, "%s Tspi_TPM_GetCapability failed: 0x%x",
160 LABEL, result);
c08753bd
AS
161 return FALSE;
162 }
fedc6769
AS
163
164 info = (TPM_CAP_VERSION_INFO *)version_ptr;
165 DBG2(DBG_PTS, "TPM Version Info: Chip Version: %u.%u.%u.%u, "
166 "Spec Level: %u, Errata Rev: %u, Vendor ID: %.4s",
167 info->version.major, info->version.minor,
168 info->version.revMajor, info->version.revMinor,
169 untoh16(&info->specLevel), info->errataRev, info->tpmVendorID);
170
171 this->version_info = chunk_clone(chunk_create(version_ptr, version_len));
172
c08753bd
AS
173 return TRUE;
174}
175
176/**
177 * Finalize TSS context
178 */
179static void finalize_context(private_tpm_tss_trousers_t *this)
180{
181 if (this->hContext)
182 {
183 Tspi_Context_FreeMemory(this->hContext, NULL);
184 Tspi_Context_Close(this->hContext);
185 }
186}
187
188METHOD(tpm_tss_t, get_version, tpm_version_t,
189 private_tpm_tss_trousers_t *this)
190{
191 return TPM_VERSION_1_2;
192}
193
fedc6769
AS
194METHOD(tpm_tss_t, get_version_info, chunk_t,
195 private_tpm_tss_trousers_t *this)
196{
197 return this->version_info;
198}
199
c08753bd
AS
200METHOD(tpm_tss_t, generate_aik, bool,
201 private_tpm_tss_trousers_t *this, chunk_t ca_modulus, chunk_t *aik_blob,
202 chunk_t *aik_pubkey, chunk_t *identity_req)
203{
204 chunk_t aik_pubkey_blob;
205 chunk_t aik_modulus;
206 chunk_t aik_exponent;
207
208 TSS_RESULT result;
c08753bd
AS
209 TSS_HKEY hSRK;
210 TSS_HKEY hPCAKey;
211 TSS_HPOLICY hSrkPolicy;
212 TSS_HPOLICY hTPMPolicy;
213 TSS_HKEY hIdentKey;
214 TSS_UUID SRK_UUID = TSS_UUID_SRK;
215 BYTE secret[] = TSS_WELL_KNOWN_SECRET;
216 BYTE *IdentityReq;
217 UINT32 IdentityReqLen;
218 BYTE *blob;
219 UINT32 blobLen;
220
221 /* get SRK plus SRK policy and set SRK secret */
222 result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM,
223 SRK_UUID, &hSRK);
224 if (result != TSS_SUCCESS)
225 {
226 DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByUUID for SRK failed: 0x%x",
227 LABEL, result);
228 return FALSE;
229 }
230 result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &hSrkPolicy);
231 if (result != TSS_SUCCESS)
232 {
233 DBG1(DBG_PTS, "%s Tspi_GetPolicyObject or SRK failed: 0x%x ",
234 LABEL, result);
235 return FALSE;
236 }
237 result = Tspi_Policy_SetSecret(hSrkPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
238 if (result != TSS_SUCCESS)
239 {
240 DBG1(DBG_PTS, "%s Tspi_Policy_SetSecret for SRK failed: 0x%x ",
241 LABEL, result);
242 return FALSE;
243 }
244
245 /* get TPM plus TPM policy and set TPM secret */
30d4989a 246 result = Tspi_Context_GetTpmObject (this->hContext, &this->hTPM);
c08753bd
AS
247 if (result != TSS_SUCCESS)
248 {
249 DBG1(DBG_PTS, "%s Tspi_Context_GetTpmObject failed: 0x%x",
250 LABEL, result);
251 return FALSE;
252 }
30d4989a 253 result = Tspi_GetPolicyObject(this->hTPM, TSS_POLICY_USAGE, &hTPMPolicy);
c08753bd
AS
254 if (result != TSS_SUCCESS)
255 {
256 DBG1(DBG_PTS, "%s Tspi_GetPolicyObject for TPM failed: 0x%x",
257 LABEL, result);
258 return FALSE;
259 }
260 result = Tspi_Policy_SetSecret(hTPMPolicy, TSS_SECRET_MODE_SHA1, 20, secret);
261 if (result != TSS_SUCCESS)
262 {
263 DBG1(DBG_PTS,"%s Tspi_Policy_SetSecret for TPM failed: 0x%x",
264 LABEL, result);
265 return FALSE;
266 }
267
268 /* create context for a 2048 bit AIK */
269 result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY,
270 TSS_KEY_TYPE_IDENTITY | TSS_KEY_SIZE_2048 |
271 TSS_KEY_VOLATILE | TSS_KEY_NOT_MIGRATABLE, &hIdentKey);
272 if (result != TSS_SUCCESS)
273 {
274 DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for key failed: 0x%x",
275 LABEL, result);
276 return FALSE;
277 }
278
279 /* create context for the Privacy CA public key and assign modulus */
280 result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_RSAKEY,
281 TSS_KEY_TYPE_LEGACY|TSS_KEY_SIZE_2048, &hPCAKey);
282 if (result != TSS_SUCCESS)
283 {
284 DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for PCA failed: 0x%x",
285 LABEL, result);
286 return FALSE;
287 }
288 result = Tspi_SetAttribData (hPCAKey, TSS_TSPATTRIB_RSAKEY_INFO,
289 TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, ca_modulus.len,
290 ca_modulus.ptr);
291 if (result != TSS_SUCCESS)
292 {
293 DBG1(DBG_PTS, "%s Tspi_SetAttribData for PCA modulus failed: 0x%x",
294 LABEL, result);
295 return FALSE;
296 }
297 result = Tspi_SetAttribUint32(hPCAKey, TSS_TSPATTRIB_KEY_INFO,
298 TSS_TSPATTRIB_KEYINFO_ENCSCHEME, TSS_ES_RSAESPKCSV15);
299 if (result != TSS_SUCCESS)
300 {
301 DBG1(DBG_PTS,"%s Tspi_SetAttribUint32 for PCA encryption scheme "
302 "failed: 0x%x", LABEL, result);
303 return FALSE;
304 }
305
306 /* generate AIK */
307 DBG1(DBG_LIB, "Generating identity key...");
30d4989a 308 result = Tspi_TPM_CollateIdentityRequest(this->hTPM, hSRK, hPCAKey, 0, NULL,
c08753bd
AS
309 hIdentKey, TSS_ALG_AES, &IdentityReqLen, &IdentityReq);
310 if (result != TSS_SUCCESS)
311 {
312 DBG1(DBG_PTS, "%s Tspi_TPM_CollateIdentityRequest failed: 0x%x",
313 LABEL, result);
314 return FALSE;
315 }
316 *identity_req = chunk_create(IdentityReq, IdentityReqLen);
317 DBG3(DBG_LIB, "%s Identity Request: %B", LABEL, identity_req);
318
319 /* load identity key */
320 result = Tspi_Key_LoadKey (hIdentKey, hSRK);
321 if (result != TSS_SUCCESS)
322 {
323 DBG1(DBG_PTS, "%s Tspi_Key_LoadKey for AIK failed: 0x%x",
324 LABEL, result);
325 return FALSE;
326 }
327
328 /* output AIK private key in TSS blob format */
329 result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
330 TSS_TSPATTRIB_KEYBLOB_BLOB, &blobLen, &blob);
331 if (result != TSS_SUCCESS)
332 {
333 DBG1(DBG_PTS, "%s Tspi_GetAttribData for private key blob failed: 0x%x",
334 LABEL, result);
335 return FALSE;
336 }
337 *aik_blob = chunk_create(blob, blobLen);
338 DBG3(DBG_LIB, "%s AIK private key blob: %B", LABEL, aik_blob);
339
340 /* output AIK Public Key in TSS blob format */
341 result = Tspi_GetAttribData (hIdentKey, TSS_TSPATTRIB_KEY_BLOB,
342 TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blobLen, &blob);
343 if (result != TSS_SUCCESS)
344 {
345 DBG1(DBG_PTS, "%s Tspi_GetAttribData for public key blob failed: 0x%x",
346 LABEL, result);
347 return FALSE;
348 }
349 aik_pubkey_blob = chunk_create(blob, blobLen);
350 DBG3(DBG_LIB, "%s AIK public key blob: %B", LABEL, &aik_pubkey_blob);
351
352 /* create a trusted AIK public key */
353 if (aik_pubkey_blob.len != AIK_PUBKEY_BLOB_SIZE)
354 {
355 DBG1(DBG_PTS, "%s AIK public key is not in TSS blob format",
356 LABEL);
357 return FALSE;
358 }
359 aik_modulus = chunk_skip(aik_pubkey_blob, AIK_PUBKEY_BLOB_SIZE - 256);
360 aik_exponent = chunk_from_chars(0x01, 0x00, 0x01);
361
362 /* output subjectPublicKeyInfo encoding of AIK public key */
363 if (!lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER, NULL,
364 aik_pubkey, CRED_PART_RSA_MODULUS, aik_modulus,
365 CRED_PART_RSA_PUB_EXP, aik_exponent, CRED_PART_END))
366 {
367 DBG1(DBG_PTS, "%s subjectPublicKeyInfo encoding of AIK key failed",
368 LABEL);
369 return FALSE;
370 }
371 return TRUE;
372}
373
374METHOD(tpm_tss_t, get_public, chunk_t,
375 private_tpm_tss_trousers_t *this, uint32_t handle)
376{
30d4989a
AS
377 enumerator_t *enumerator;
378 chunk_t aik_pubkey = chunk_empty;
379 aik_t *aik;
380
381 enumerator = this->aik_list->create_enumerator(this->aik_list);
382 while (enumerator->enumerate(enumerator, &aik))
383 {
384 if (aik->handle == handle)
385 {
386 aik_pubkey = chunk_clone(aik->pubkey);
387 break;
388 }
389 }
390 enumerator->destroy(enumerator);
391
392 return aik_pubkey;
393}
394
7ca3b3da
TB
395METHOD(tpm_tss_t, supported_signature_schemes, enumerator_t*,
396 private_tpm_tss_trousers_t *this, uint32_t handle)
397{
398 return enumerator_create_empty();
399}
400
30d4989a
AS
401METHOD(tpm_tss_t, read_pcr, bool,
402 private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value,
403 hash_algorithm_t alg)
404{
405 TSS_RESULT result;
406 uint8_t *value;
407 uint32_t len;
408
409 result = Tspi_TPM_PcrRead(this->hTPM, pcr_num, &len, &value);
410 if (result != TSS_SUCCESS)
411 {
412 DBG1(DBG_PTS, "%s Tspi_TPM_PcrRead failed: 0x%x", LABEL, result);
413 return FALSE;
414 }
415 *pcr_value = chunk_clone(chunk_create(value, len));
416
417 return TRUE;
418}
419
420METHOD(tpm_tss_t, extend_pcr, bool,
421 private_tpm_tss_trousers_t *this, uint32_t pcr_num, chunk_t *pcr_value,
422 chunk_t data, hash_algorithm_t alg)
423{
424 TSS_RESULT result;
425 uint32_t pcr_len;
426 uint8_t *pcr_ptr;
427
428 result = Tspi_TPM_PcrExtend(this->hTPM, pcr_num, data.len, data.ptr,
429 NULL, &pcr_len, &pcr_ptr);
430 if (result != TSS_SUCCESS)
431 {
432 DBG1(DBG_PTS, "%s Tspi_TPM_PcrExtend failed: 0x%x", LABEL, result);
433 return FALSE;
434 }
435 *pcr_value = chunk_clone(chunk_create(pcr_ptr, pcr_len));
436
437 return TRUE;
438}
439
440METHOD(tpm_tss_t, quote, bool,
441 private_tpm_tss_trousers_t *this, uint32_t aik_handle, uint32_t pcr_sel,
721ed31b
AS
442 hash_algorithm_t alg, chunk_t data, tpm_quote_mode_t *quote_mode,
443 tpm_tss_quote_info_t **quote_info, chunk_t *quote_sig)
30d4989a
AS
444{
445 TSS_HKEY hAIK;
446 TSS_HKEY hSRK;
447 TSS_HPOLICY srkUsagePolicy;
448 TSS_UUID SRK_UUID = TSS_UUID_SRK;
449 TSS_HPCRS hPcrComposite;
450 TSS_VALIDATION valData;
451 TSS_RESULT result;
452 uint8_t secret[] = TSS_WELL_KNOWN_SECRET;
453 uint8_t *version_info, *comp_hash;
454 uint32_t version_info_size, pcr;
455 aik_t *aik;
456 chunk_t aik_blob = chunk_empty;
721ed31b 457 chunk_t quote_chunk, pcr_digest;
30d4989a
AS
458 enumerator_t *enumerator;
459 bool success = FALSE;
460
461 /* Retrieve SRK from TPM and set the authentication to well known secret*/
462 result = Tspi_Context_LoadKeyByUUID(this->hContext, TSS_PS_TYPE_SYSTEM,
463 SRK_UUID, &hSRK);
464 if (result != TSS_SUCCESS)
465 {
466 DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByUUID for SRK failed: 0x%x",
467 LABEL, result);
468 return FALSE;
469 }
470 result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &srkUsagePolicy);
471 if (result != TSS_SUCCESS)
472 {
473 DBG1(DBG_PTS, "%s Tspi_GetPolicyObject for SRK failed: 0x%x",
474 LABEL, result);
475 return FALSE;
476 }
477 result = Tspi_Policy_SetSecret(srkUsagePolicy, TSS_SECRET_MODE_SHA1,
478 20, secret);
479 if (result != TSS_SUCCESS)
480 {
481 DBG1(DBG_PTS, "%s Tspi_Policy_SetSecret for SRK failed: 0x%x",
482 LABEL, result);
483 return FALSE;
484 }
485
486 /* Retrieve AIK using its handle and load private key into TPM 1.2 */
487 enumerator = this->aik_list->create_enumerator(this->aik_list);
488 while (enumerator->enumerate(enumerator, &aik))
489 {
490 if (aik->handle == aik_handle)
491 {
492 aik_blob = aik->blob;
493 break;
494 }
495 }
496 enumerator->destroy(enumerator);
497
498 if (aik_blob.len == 0)
499 {
500 DBG1(DBG_PTS, "%s AIK private key for handle 0x%80x not found", LABEL);
501 return FALSE;
502 }
503 result = Tspi_Context_LoadKeyByBlob(this->hContext, hSRK, aik_blob.len,
504 aik_blob.ptr, &hAIK);
505 if (result != TSS_SUCCESS)
506 {
507 DBG1(DBG_PTS, "%s Tspi_Context_LoadKeyByBlob for AIK failed: 0x%x",
508 LABEL, result);
509 return FALSE;
510 }
511
512 /* Create PCR composite object */
513 result = Tspi_Context_CreateObject(this->hContext, TSS_OBJECT_TYPE_PCRS,
721ed31b
AS
514 (*quote_mode == TPM_QUOTE) ? TSS_PCRS_STRUCT_INFO :
515 TSS_PCRS_STRUCT_INFO_SHORT,
30d4989a
AS
516 &hPcrComposite);
517 if (result != TSS_SUCCESS)
518 {
519 DBG1(DBG_PTS, "%s Tspi_Context_CreateObject for pcrComposite failed: "
520 "0x%x", LABEL, result);
521 goto err1;
522 }
523
524 /* Select PCRs */
525 for (pcr = 0; pcr < PCR_NUM_MAX; pcr++)
526 {
527 if (pcr_sel & (1 << pcr))
528 {
721ed31b 529 result = (*quote_mode == TPM_QUOTE) ?
30d4989a
AS
530 Tspi_PcrComposite_SelectPcrIndex(hPcrComposite, pcr) :
531 Tspi_PcrComposite_SelectPcrIndexEx(hPcrComposite, pcr,
532 TSS_PCRS_DIRECTION_RELEASE);
533 if (result != TSS_SUCCESS)
534 {
535 DBG1(DBG_PTS, "%s Tspi_PcrComposite_SelectPcrIndex failed: "
536 "0x%x", LABEL, result);
537 goto err2;
538 }
539 }
540 }
541
542 /* Set the Validation Data */
543 valData.ulExternalDataLength = data.len;
544 valData.rgbExternalData = data.ptr;
545
546 /* TPM Quote */
721ed31b 547 result = (*quote_mode == TPM_QUOTE) ?
30d4989a 548 Tspi_TPM_Quote (this->hTPM, hAIK, hPcrComposite, &valData) :
721ed31b
AS
549 Tspi_TPM_Quote2(this->hTPM, hAIK,
550 *quote_mode == TPM_QUOTE2_VERSION_INFO,
30d4989a
AS
551 hPcrComposite, &valData, &version_info_size,
552 &version_info);
553 if (result != TSS_SUCCESS)
554 {
555 DBG1(DBG_PTS, "%s Tspi_TPM_Quote%s failed: 0x%x", LABEL,
721ed31b 556 (*quote_mode == TPM_QUOTE) ? "" : "2", result);
30d4989a
AS
557 goto err2;
558 }
559
721ed31b 560 if (*quote_mode == TPM_QUOTE)
30d4989a
AS
561 {
562 /* TPM_Composite_Hash starts at byte 8 of TPM_Quote_Info structure */
563 comp_hash = valData.rgbData + 8;
564 }
565 else
566 {
567 /* TPM_Composite_Hash is last 20 bytes of TPM_Quote_Info2 structure */
568 comp_hash = valData.rgbData + valData.ulDataLength - version_info_size -
569 HASH_SIZE_SHA1;
570 }
721ed31b
AS
571 pcr_digest = chunk_create(comp_hash, HASH_SIZE_SHA1);
572 DBG2(DBG_PTS, "PCR composite digest: %B", &pcr_digest);
573
574 quote_chunk = chunk_create(valData.rgbData, valData.ulDataLength);
575 DBG2(DBG_PTS, "TPM Quote Info: %B", &quote_chunk);
30d4989a 576
721ed31b 577 *quote_info = tpm_tss_quote_info_create(*quote_mode, HASH_SHA1, pcr_digest);
30d4989a
AS
578
579 *quote_sig = chunk_clone(chunk_create(valData.rgbValidationData,
580 valData.ulValidationDataLength));
721ed31b 581 DBG2(DBG_PTS, "TPM Quote Signature: %B", quote_sig);
30d4989a
AS
582
583 success = TRUE;
584
585err2:
586 Tspi_Context_CloseObject(this->hContext, hPcrComposite);
587err1:
588 Tspi_Context_CloseObject(this->hContext, hAIK);
589
590 return success;
c08753bd
AS
591}
592
e8736028
AS
593METHOD(tpm_tss_t, sign, bool,
594 private_tpm_tss_trousers_t *this, uint32_t hierarchy, uint32_t handle,
fd21c40b
AS
595 signature_scheme_t scheme, void *params, chunk_t data, chunk_t pin,
596 chunk_t *signature)
e8736028
AS
597{
598 return FALSE;
599}
600
2b233c8a
AS
601METHOD(tpm_tss_t, get_random, bool,
602 private_tpm_tss_trousers_t *this, size_t bytes, uint8_t *buffer)
603{
604 return FALSE;
605}
606
e850d000
AS
607METHOD(tpm_tss_t, get_data, bool,
608 private_tpm_tss_trousers_t *this, uint32_t hierarchy, uint32_t handle,
609 chunk_t pin, chunk_t *data)
610{
611 return FALSE;
612}
613
d647a8f9
AS
614METHOD(tpm_tss_t, get_event_digest, bool,
615 private_tpm_tss_trousers_t *this, int fd, chunk_t *digest)
616{
617 *digest = chunk_alloc(HASH_SIZE_SHA1);
618
619 return read(fd, digest->ptr, digest->len) == digest->len;
620}
621
c08753bd
AS
622METHOD(tpm_tss_t, destroy, void,
623 private_tpm_tss_trousers_t *this)
624{
625 finalize_context(this);
30d4989a 626 this->aik_list->destroy_function(this->aik_list, (void*)free_aik);
fedc6769 627 free(this->version_info.ptr);
c08753bd
AS
628 free(this);
629}
630
30d4989a
AS
631METHOD(tpm_tss_trousers_t, load_aik, void,
632 private_tpm_tss_trousers_t *this, chunk_t blob, chunk_t pubkey,
633 uint32_t handle)
634{
635 aik_t *item;
636
637 INIT(item,
638 .handle = handle,
639 .blob = blob,
640 .pubkey = pubkey,
641 );
642
643 this->aik_list->insert_last(this->aik_list, item);
644}
645
c08753bd
AS
646/**
647 * See header
648 */
649tpm_tss_t *tpm_tss_trousers_create()
650{
651 private_tpm_tss_trousers_t *this;
652 bool available;
653
654 INIT(this,
30d4989a
AS
655 .interface = {
656 .public = {
657 .get_version = _get_version,
658 .get_version_info = _get_version_info,
659 .generate_aik = _generate_aik,
660 .get_public = _get_public,
7ca3b3da 661 .supported_signature_schemes = _supported_signature_schemes,
30d4989a 662 .read_pcr = _read_pcr,
30d4989a 663 .extend_pcr = _extend_pcr,
e8736028
AS
664 .quote = _quote,
665 .sign = _sign,
2b233c8a 666 .get_random = _get_random,
e850d000 667 .get_data = _get_data,
d647a8f9 668 .get_event_digest = _get_event_digest,
30d4989a
AS
669 .destroy = _destroy,
670 },
671 .load_aik = _load_aik,
c08753bd 672 },
30d4989a 673 .aik_list = linked_list_create(),
c08753bd
AS
674 );
675
676 available = initialize_context(this);
677 DBG1(DBG_PTS, "TPM 1.2 via TrouSerS %savailable", available ? "" : "not ");
678
679 if (!available)
680 {
681 destroy(this);
682 return NULL;
683 }
30d4989a 684 return &this->interface.public;
c08753bd
AS
685}
686
687#else /* TSS_TROUSERS */
688
689tpm_tss_t *tpm_tss_trousers_create()
690{
691 return NULL;
692}
693
694#endif /* TSS_TROUSERS */
695
696
697