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