a621164bf86e2beaa3eea422ebe7368516722da6
[strongswan.git] / src / libpts / tcg / tcg_pts_attr_simple_evid_final.c
1 /*
2 * Copyright (C) 2011 Sansar Choinyambuu
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 "tcg_pts_attr_simple_evid_final.h"
17 #include "pts/pts_simple_evid_final.h"
18
19 #include <pa_tnc/pa_tnc_msg.h>
20 #include <bio/bio_writer.h>
21 #include <bio/bio_reader.h>
22 #include <debug.h>
23
24 typedef struct private_tcg_pts_attr_simple_evid_final_t private_tcg_pts_attr_simple_evid_final_t;
25
26 /**
27 * Simple Evidence Final
28 * see section 3.15.2 of PTS Protocol: Binding to TNC IF-M Specification
29 *
30 * 1 2 3
31 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
32 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 * | Flags | Reserved | Optional Composite Hash Alg |
34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 * | Optional TPM PCR Composite Length |
36 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * ~ Optional TPM PCR Composite (Variable Length) ~
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * | Optional TPM Quote Signature Length |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * ~ Optional TPM Quote Signature (Variable Length) ~
42 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43 * ~ Optional Evidence Signature (Variable Length) ~
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 */
46
47 #define PTS_SIMPLE_EVID_FINAL_SIZE 2
48 #define PTS_SIMPLE_EVID_FINAL_RESERVED 0x00
49 #define PTS_SIMPLE_EVID_FINAL_FLAG_MASK 0xC0
50 /**
51 * Private data of an tcg_pts_attr_simple_evid_final_t object.
52 */
53 struct private_tcg_pts_attr_simple_evid_final_t {
54
55 /**
56 * Public members of tcg_pts_attr_simple_evid_final_t
57 */
58 tcg_pts_attr_simple_evid_final_t public;
59
60 /**
61 * Attribute vendor ID
62 */
63 pen_t vendor_id;
64
65 /**
66 * Attribute type
67 */
68 u_int32_t type;
69
70 /**
71 * Attribute value
72 */
73 chunk_t value;
74
75 /**
76 * Noskip flag
77 */
78 bool noskip_flag;
79
80 /**
81 * Set of flags for Simple Evidence Final
82 */
83 u_int8_t flags;
84
85 /**
86 * Optional Composite Hash Algorithm
87 */
88 pts_meas_algorithms_t comp_hash_algorithm;
89
90 /**
91 * Optional TPM PCR Composite
92 */
93 chunk_t pcr_comp;
94
95 /**
96 * Optional TPM Quote Signature
97 */
98 chunk_t tpm_quote_sig;
99
100 /**
101 * Is Evidence Signature included?
102 */
103 bool has_evid_sig;
104
105 /**
106 * Optional Evidence Signature
107 */
108 chunk_t evid_sig;
109
110 };
111
112 METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
113 private_tcg_pts_attr_simple_evid_final_t *this)
114 {
115 return this->vendor_id;
116 }
117
118 METHOD(pa_tnc_attr_t, get_type, u_int32_t,
119 private_tcg_pts_attr_simple_evid_final_t *this)
120 {
121 return this->type;
122 }
123
124 METHOD(pa_tnc_attr_t, get_value, chunk_t,
125 private_tcg_pts_attr_simple_evid_final_t *this)
126 {
127 return this->value;
128 }
129
130 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
131 private_tcg_pts_attr_simple_evid_final_t *this)
132 {
133 return this->noskip_flag;
134 }
135
136 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
137 private_tcg_pts_attr_simple_evid_final_t *this, bool noskip)
138 {
139 this->noskip_flag = noskip;
140 }
141
142 METHOD(pa_tnc_attr_t, destroy, void,
143 private_tcg_pts_attr_simple_evid_final_t *this)
144 {
145 free(this->value.ptr);
146 free(this->pcr_comp.ptr);
147 free(this->tpm_quote_sig.ptr);
148 free(this->evid_sig.ptr);
149 free(this);
150 }
151
152 METHOD(pa_tnc_attr_t, build, void,
153 private_tcg_pts_attr_simple_evid_final_t *this)
154 {
155 bio_writer_t *writer;
156 u_int8_t flags;
157
158 flags = this->flags & PTS_SIMPLE_EVID_FINAL_FLAG_MASK;
159
160 if (this->has_evid_sig)
161 {
162 flags |= PTS_SIMPLE_EVID_FINAL_EVID_SIG;
163 }
164
165 writer = bio_writer_create(PTS_SIMPLE_EVID_FINAL_SIZE);
166 writer->write_uint8 (writer, flags);
167 writer->write_uint8 (writer, PTS_SIMPLE_EVID_FINAL_RESERVED);
168
169 /** Optional Composite Hash Algorithm field is always present
170 * Field has value of all zeroes if not used.
171 * Implemented adhering the suggestion of Paul Sangster 28.Oct.2011
172 */
173 writer->write_uint16(writer, this->comp_hash_algorithm);
174
175 /* Optional fields */
176 if (this->flags != PTS_SIMPLE_EVID_FINAL_NO)
177 {
178 writer->write_uint32 (writer, this->pcr_comp.len);
179 writer->write_data (writer, this->pcr_comp);
180
181 writer->write_uint32 (writer, this->tpm_quote_sig.len);
182 writer->write_data (writer, this->tpm_quote_sig);
183 }
184
185 if (this->has_evid_sig)
186 {
187 writer->write_data (writer, this->evid_sig);
188 }
189
190 this->value = chunk_clone(writer->get_buf(writer));
191 writer->destroy(writer);
192 }
193
194 METHOD(pa_tnc_attr_t, process, status_t,
195 private_tcg_pts_attr_simple_evid_final_t *this, u_int32_t *offset)
196 {
197 bio_reader_t *reader;
198 u_int8_t flags, reserved;
199 u_int16_t algorithm;
200 u_int32_t pcr_comp_len, tpm_quote_sig_len, evid_sig_len;
201
202
203 if (this->value.len < PTS_SIMPLE_EVID_FINAL_SIZE)
204 {
205 DBG1(DBG_TNC, "insufficient data for Simple Evidence Final");
206 *offset = 0;
207 return FAILED;
208 }
209 reader = bio_reader_create(this->value);
210
211 reader->read_uint8(reader, &flags);
212 reader->read_uint8(reader, &reserved);
213
214 this->flags = flags & PTS_SIMPLE_EVID_FINAL_FLAG_MASK;
215
216 this->has_evid_sig = (flags & PTS_SIMPLE_EVID_FINAL_EVID_SIG) != 0;
217
218 /** Optional Composite Hash Algorithm field is always present
219 * Field has value of all zeroes if not used.
220 * Implemented adhering the suggestion of Paul Sangster 28.Oct.2011
221 */
222
223 reader->read_uint16(reader, &algorithm);
224 this->comp_hash_algorithm = algorithm;
225
226 /* Optional Composite Hash Algorithm and TPM PCR Composite fields */
227 if (this->flags != PTS_SIMPLE_EVID_FINAL_NO)
228 {
229 u_int32_t pcr_comp_len, tpm_quote_sign_len;
230
231 /** TODO: Ignoring Hashing algorithm field
232 * There is no flag defined which indicates the precense of it
233 * reader->read_uint16(reader, &algorithm);
234 * this->comp_hash_algorithm = algorithm;
235 */
236 reader->read_uint32(reader, &pcr_comp_len);
237 reader->read_data(reader, pcr_comp_len, &this->pcr_comp);
238 this->pcr_comp = chunk_clone(this->pcr_comp);
239
240 /* TODO check if enough message data is available */
241 reader->read_uint32(reader, &tpm_quote_sig_len);
242 reader->read_data(reader, tpm_quote_sig_len, &this->tpm_quote_sig);
243 this->tpm_quote_sig = chunk_clone(this->tpm_quote_sig);
244 }
245
246 /* Optional Evidence Signature field */
247 if (this->has_evid_sig)
248 {
249 evid_sig_len = reader->remaining(reader);
250 reader->read_data(reader, evid_sig_len, &this->evid_sig);
251 this->evid_sig = chunk_clone(this->evid_sig);
252 }
253
254 reader->destroy(reader);
255 return SUCCESS;
256 }
257
258 METHOD(tcg_pts_attr_simple_evid_final_t, get_quote_info, u_int8_t,
259 private_tcg_pts_attr_simple_evid_final_t *this,
260 pts_meas_algorithms_t *comp_hash_algo, chunk_t *pcr_comp, chunk_t *tpm_quote_sig)
261 {
262 if (comp_hash_algo)
263 {
264 *comp_hash_algo = this->comp_hash_algorithm;
265 }
266 if (pcr_comp)
267 {
268 *pcr_comp = this->pcr_comp;
269 }
270 if (tpm_quote_sig)
271 {
272 *tpm_quote_sig = this->tpm_quote_sig;
273 }
274 return this->flags;
275 }
276
277 METHOD(tcg_pts_attr_simple_evid_final_t, get_evid_sig, bool,
278 private_tcg_pts_attr_simple_evid_final_t *this, chunk_t *evid_sig)
279 {
280 if (evid_sig)
281 {
282 *evid_sig = this->evid_sig;
283 }
284 return this->has_evid_sig;
285 }
286
287 METHOD(tcg_pts_attr_simple_evid_final_t, set_evid_sig, void,
288 private_tcg_pts_attr_simple_evid_final_t *this, chunk_t evid_sig)
289 {
290 this->evid_sig = chunk_clone(evid_sig);
291 this->has_evid_sig = TRUE;
292 }
293
294 /**
295 * Described in header.
296 */
297 pa_tnc_attr_t *tcg_pts_attr_simple_evid_final_create(u_int8_t flags,
298 pts_meas_algorithms_t comp_hash_algorithm,
299 chunk_t pcr_comp, chunk_t tpm_quote_sig)
300 {
301 private_tcg_pts_attr_simple_evid_final_t *this;
302
303 INIT(this,
304 .public = {
305 .pa_tnc_attribute = {
306 .get_vendor_id = _get_vendor_id,
307 .get_type = _get_type,
308 .get_value = _get_value,
309 .get_noskip_flag = _get_noskip_flag,
310 .set_noskip_flag = _set_noskip_flag,
311 .build = _build,
312 .process = _process,
313 .destroy = _destroy,
314 },
315 .get_quote_info = _get_quote_info,
316 .get_evid_sig = _get_evid_sig,
317 .set_evid_sig = _set_evid_sig,
318 },
319 .vendor_id = PEN_TCG,
320 .type = TCG_PTS_SIMPLE_EVID_FINAL,
321 .flags = flags,
322 .comp_hash_algorithm = comp_hash_algorithm,
323 .pcr_comp = chunk_clone(pcr_comp),
324 .tpm_quote_sig = chunk_clone(tpm_quote_sig),
325 );
326
327 return &this->public.pa_tnc_attribute;
328 }
329
330
331 /**
332 * Described in header.
333 */
334 pa_tnc_attr_t *tcg_pts_attr_simple_evid_final_create_from_data(chunk_t data)
335 {
336 private_tcg_pts_attr_simple_evid_final_t *this;
337
338 INIT(this,
339 .public = {
340 .pa_tnc_attribute = {
341 .get_vendor_id = _get_vendor_id,
342 .get_type = _get_type,
343 .get_value = _get_value,
344 .get_noskip_flag = _get_noskip_flag,
345 .set_noskip_flag = _set_noskip_flag,
346 .build = _build,
347 .process = _process,
348 .destroy = _destroy,
349 },
350 .get_quote_info = _get_quote_info,
351 .get_evid_sig = _get_evid_sig,
352 .set_evid_sig = _set_evid_sig,
353 },
354 .vendor_id = PEN_TCG,
355 .type = TCG_PTS_SIMPLE_EVID_FINAL,
356 .value = chunk_clone(data),
357 );
358
359 return &this->public.pa_tnc_attribute;
360 }