2 * Copyright (C) 2016 Andreas Steffen
4 * Copyright (C) secunet Security Networks AG
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include <tpm_tss_quote_info.h>
19 #include <bio/bio_writer.h>
21 #ifndef TPM_TAG_QUOTE_INFO2
22 #define TPM_TAG_QUOTE_INFO2 0x0036
25 #define TPM_LOC_ZERO 0x01
28 typedef struct private_tpm_tss_quote_info_t private_tpm_tss_quote_info_t
;
31 * Private data of an tpm_tss_quote_info_t object.
33 struct private_tpm_tss_quote_info_t
{
36 * Public tpm_tss_quote_info_t interface.
38 tpm_tss_quote_info_t
public;
43 tpm_quote_mode_t quote_mode
;
46 * TPM Qualified Signer
48 chunk_t qualified_signer
;
66 * TPM PCR Composite Hash
71 * TPM PCR Composite Hash algorithm
73 hash_algorithm_t pcr_digest_alg
;
82 METHOD(tpm_tss_quote_info_t
, get_quote_mode
, tpm_quote_mode_t
,
83 private_tpm_tss_quote_info_t
*this)
85 return this->quote_mode
;
88 METHOD(tpm_tss_quote_info_t
, get_pcr_digest_alg
, hash_algorithm_t
,
89 private_tpm_tss_quote_info_t
*this)
91 return this->pcr_digest_alg
;
94 METHOD(tpm_tss_quote_info_t
, get_pcr_digest
, chunk_t
,
95 private_tpm_tss_quote_info_t
*this)
97 return this->pcr_digest
;
100 METHOD(tpm_tss_quote_info_t
, get_quote
, bool,
101 private_tpm_tss_quote_info_t
*this, chunk_t nonce
,
102 tpm_tss_pcr_composite_t
*composite
, chunk_t
*quoted
)
104 chunk_t pcr_composite
, pcr_digest
;
105 bio_writer_t
*writer
;
109 /* Construct PCR Composite */
110 writer
= bio_writer_create(32);
112 switch (this->quote_mode
)
116 case TPM_QUOTE2_VERSION_INFO
:
117 writer
->write_data16(writer
, composite
->pcr_select
);
118 writer
->write_data32(writer
, composite
->pcr_composite
);
122 writer
->write_data(writer
, composite
->pcr_composite
);
128 pcr_composite
= writer
->extract_buf(writer
);
129 writer
->destroy(writer
);
131 DBG2(DBG_PTS
, "constructed PCR Composite: %B", &pcr_composite
);
133 /* Compute PCR Composite Hash */
134 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, this->pcr_digest_alg
);
135 if (!hasher
|| !hasher
->allocate_hash(hasher
, pcr_composite
, &pcr_digest
))
138 chunk_free(&pcr_composite
);
141 hasher
->destroy(hasher
);
142 chunk_free(&pcr_composite
);
144 DBG2(DBG_PTS
, "constructed PCR Composite digest: %B", &pcr_digest
);
146 equal_digests
= chunk_equals(pcr_digest
, this->pcr_digest
);
148 /* Construct Quote Info */
149 writer
= bio_writer_create(32);
151 switch (this->quote_mode
)
155 writer
->write_data(writer
, chunk_from_chars(1, 1, 0, 0));
157 /* Magic QUOT value */
158 writer
->write_data(writer
, chunk_from_str("QUOT"));
160 /* PCR Composite Hash */
161 writer
->write_data(writer
, pcr_digest
);
163 /* Secret assessment value 20 bytes (nonce) */
164 writer
->write_data(writer
, nonce
);
167 case TPM_QUOTE2_VERSION_INFO
:
168 /* TPM Structure Tag */
169 writer
->write_uint16(writer
, TPM_TAG_QUOTE_INFO2
);
171 /* Magic QUT2 value */
172 writer
->write_data(writer
, chunk_from_str("QUT2"));
174 /* Secret assessment value 20 bytes (nonce) */
175 writer
->write_data(writer
, nonce
);
178 writer
->write_data16(writer
, composite
->pcr_select
);
180 /* TPM Locality Selection */
181 writer
->write_uint8(writer
, TPM_LOC_ZERO
);
183 /* PCR Composite Hash */
184 writer
->write_data(writer
, pcr_digest
);
186 if (this->quote_mode
== TPM_QUOTE2_VERSION_INFO
)
188 /* TPM version Info */
189 writer
->write_data(writer
, this->version_info
);
194 writer
->write_data(writer
, chunk_from_chars(0xff,0x54,0x43,0x47));
197 writer
->write_uint16(writer
, 0x8018);
199 /* Qualified Signer */
200 writer
->write_data16(writer
, this->qualified_signer
);
203 writer
->write_data16(writer
, nonce
);
206 writer
->write_data(writer
, this->clock_info
);
208 /* Firmware Version */
209 writer
->write_data(writer
, this->version_info
);
212 writer
->write_data(writer
, this->pcr_select
);
214 /* PCR Composite Hash */
215 writer
->write_data16(writer
, pcr_digest
);
220 chunk_free(&pcr_digest
);
221 *quoted
= writer
->extract_buf(writer
);
222 writer
->destroy(writer
);
224 DBG2(DBG_PTS
, "constructed TPM Quote Info: %B", quoted
);
228 DBG1(DBG_IMV
, "received PCR Composite digest does not match "
232 return equal_digests
;
235 METHOD(tpm_tss_quote_info_t
, set_version_info
, void,
236 private_tpm_tss_quote_info_t
*this, chunk_t version_info
)
238 chunk_free(&this->version_info
);
239 this->version_info
= chunk_clone(version_info
);
242 METHOD(tpm_tss_quote_info_t
, get_version_info
, chunk_t
,
243 private_tpm_tss_quote_info_t
*this)
245 return this->version_info
;
248 METHOD(tpm_tss_quote_info_t
, set_tpm2_info
, void,
249 private_tpm_tss_quote_info_t
*this, chunk_t qualified_signer
,
250 chunk_t clock_info
, chunk_t pcr_select
)
252 chunk_free(&this->qualified_signer
);
253 this->qualified_signer
= chunk_clone(qualified_signer
);
255 chunk_free(&this->clock_info
);
256 this->clock_info
= chunk_clone(clock_info
);
258 chunk_free(&this->pcr_select
);
259 this->pcr_select
= chunk_clone(pcr_select
);
262 METHOD(tpm_tss_quote_info_t
, get_tpm2_info
, void,
263 private_tpm_tss_quote_info_t
*this, chunk_t
*qualified_signer
,
264 chunk_t
*clock_info
, chunk_t
*pcr_select
)
266 if (qualified_signer
)
268 *qualified_signer
= this->qualified_signer
;
272 *clock_info
= this->clock_info
;
276 *pcr_select
= this->pcr_select
;
280 METHOD(tpm_tss_quote_info_t
, get_ref
, tpm_tss_quote_info_t
*,
281 private_tpm_tss_quote_info_t
*this)
285 return &this->public;
288 METHOD(tpm_tss_quote_info_t
, destroy
, void,
289 private_tpm_tss_quote_info_t
*this)
291 if (ref_put(&this->ref
))
293 chunk_free(&this->qualified_signer
);
294 chunk_free(&this->clock_info
);
295 chunk_free(&this->version_info
);
296 chunk_free(&this->pcr_select
);
297 chunk_free(&this->pcr_digest
);
305 tpm_tss_quote_info_t
*tpm_tss_quote_info_create(tpm_quote_mode_t quote_mode
,
306 hash_algorithm_t pcr_digest_alg
, chunk_t pcr_digest
)
309 private_tpm_tss_quote_info_t
*this;
313 .get_quote_mode
= _get_quote_mode
,
314 .get_pcr_digest_alg
= _get_pcr_digest_alg
,
315 .get_pcr_digest
= _get_pcr_digest
,
316 .get_quote
= _get_quote
,
317 .set_version_info
= _set_version_info
,
318 .get_version_info
= _get_version_info
,
319 .set_tpm2_info
= _set_tpm2_info
,
320 .get_tpm2_info
= _get_tpm2_info
,
324 .quote_mode
= quote_mode
,
325 .pcr_digest_alg
= pcr_digest_alg
,
326 .pcr_digest
= chunk_clone(pcr_digest
),
330 return &this->public;