refactored simple component evidence
[strongswan.git] / src / libpts / tcg / tcg_pts_attr_simple_comp_evid.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_comp_evid.h"
17
18 #include <pa_tnc/pa_tnc_msg.h>
19 #include <bio/bio_writer.h>
20 #include <bio/bio_reader.h>
21 #include <debug.h>
22
23 #include <time.h>
24
25 typedef struct private_tcg_pts_attr_simple_comp_evid_t private_tcg_pts_attr_simple_comp_evid_t;
26
27 /**
28 * Simple Component Evidence
29 * see section 3.15.1 of PTS Protocol: Binding to TNC IF-M Specification
30 *
31 * 1 2 3
32 * 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
33 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 * | Flags | Sub-Component Depth |
35 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 * | Specific Functional Component |
37 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38 * | Specific Functional Component |
39 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 * | Measure. Type | Extended into PCR |
41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 * | Hash Algorithm | PCR Transform | Reserved |
43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 * | Measurement Date/Time |
45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 * | Measurement Date/Time |
47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 * | Measurement Date/Time |
49 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 * | Measurement Date/Time |
51 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 * | Measurement Date/Time |
53 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 * | Optional Policy URI Length | Opt. Verification Policy URI ~
55 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 * ~ Optional Verification Policy URI ~
57 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 * | Optional PCR Length | Optional PCR Before Value ~
59 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 * ~ Optional PCR Before Value (Variable Length) ~
61 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 * ~ Optional PCR After Value (Variable Length) ~
63 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64 * ~ Component Measurement (Variable Length) ~
65 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 */
67
68 /**
69 * Specific Functional Component -> Component Functional Name Structure
70 * see section 5.1 of PTS Protocol: Binding to TNC IF-M Specification
71 *
72 * 1 2 3
73 * 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
74 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75 * | Component Functional Name Vendor ID |Fam| Qualifier |
76 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 * | Component Functional Name |
78 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79 *
80 */
81
82 #define PTS_SIMPLE_COMP_EVID_SIZE 40
83 #define PTS_SIMPLE_COMP_EVID_MEAS_TIME_SIZE 20
84 #define PTS_SIMPLE_COMP_EVID_RESERVED 0x00
85 #define PTS_SIMPLE_COMP_EVID_FAMILY_MASK 0xC0
86 #define PTS_SIMPLE_COMP_EVID_VALIDATION_MASK 0x60
87 #define PTS_SIMPLE_COMP_EVID_MEAS_TYPE (1<<7)
88 #define PTS_SIMPLE_COMP_EVID_FLAG_PCR (1<<7)
89
90 /**
91 * Private data of an tcg_pts_attr_simple_comp_evid_t object.
92 */
93 struct private_tcg_pts_attr_simple_comp_evid_t {
94
95 /**
96 * Public members of tcg_pts_attr_simple_comp_evid_t
97 */
98 tcg_pts_attr_simple_comp_evid_t public;
99
100 /**
101 * Attribute vendor ID
102 */
103 pen_t vendor_id;
104
105 /**
106 * Attribute type
107 */
108 u_int32_t type;
109
110 /**
111 * Attribute value
112 */
113 chunk_t value;
114
115 /**
116 * Noskip flag
117 */
118 bool noskip_flag;
119
120 /**
121 * PTS Component Evidence
122 */
123 pts_comp_evidence_t *evidence;
124
125 };
126
127 METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
128 private_tcg_pts_attr_simple_comp_evid_t *this)
129 {
130 return this->vendor_id;
131 }
132
133 METHOD(pa_tnc_attr_t, get_type, u_int32_t,
134 private_tcg_pts_attr_simple_comp_evid_t *this)
135 {
136 return this->type;
137 }
138
139 METHOD(pa_tnc_attr_t, get_value, chunk_t,
140 private_tcg_pts_attr_simple_comp_evid_t *this)
141 {
142 return this->value;
143 }
144
145 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
146 private_tcg_pts_attr_simple_comp_evid_t *this)
147 {
148 return this->noskip_flag;
149 }
150
151 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
152 private_tcg_pts_attr_simple_comp_evid_t *this, bool noskip)
153 {
154 this->noskip_flag = noskip;
155 }
156
157 METHOD(pa_tnc_attr_t, build, void,
158 private_tcg_pts_attr_simple_comp_evid_t *this)
159 {
160 bio_writer_t *writer;
161 bool has_pcr_info;
162 char *utc_time_str, utc_time_buf[25];
163 u_int8_t flags;
164 u_int32_t depth, extended_pcr;
165 pts_comp_func_name_t *name;
166 pts_meas_algorithms_t hash_algorithm;
167 pts_pcr_transform_t transform;
168 pts_comp_evid_validation_t validation;
169 time_t measurement_time;
170 chunk_t measurement, utc_time, pcr_before, pcr_after, policy_uri;
171
172 /* Extract parameters from comp_evidence_t object */
173 name = this->evidence->get_comp_func_name(this->evidence,
174 &depth);
175 measurement = this->evidence->get_measurement(this->evidence,
176 &extended_pcr, &hash_algorithm, &transform,
177 &measurement_time);
178 has_pcr_info = this->evidence->get_pcr_info(this->evidence,
179 &pcr_before, &pcr_after);
180 validation = this->evidence->get_validation(this->evidence,
181 &policy_uri);
182
183 /* Determine the flags to set*/
184 flags = validation;
185 if (has_pcr_info)
186 {
187 flags |= PTS_SIMPLE_COMP_EVID_FLAG_PCR;
188 }
189
190 /* Form the UTC measurement time string */
191 if (measurement_time == UNDEFINED_TIME)
192 {
193 utc_time_str = "0000-00-00T00:00:00Z";
194 }
195 else
196 {
197 struct tm t;
198
199 gmtime_r(&measurement_time, &t);
200 utc_time_str = utc_time_buf;
201 sprintf(utc_time_str, "%04d-%.02d-%.02dT%.02d:%.02d:%.02dZ",
202 t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
203 t.tm_hour, t.tm_min, t.tm_sec);
204 }
205 utc_time = chunk_create(utc_time_str, PTS_SIMPLE_COMP_EVID_MEAS_TIME_SIZE);
206
207 writer = bio_writer_create(PTS_SIMPLE_COMP_EVID_SIZE);
208
209 writer->write_uint8 (writer, flags);
210 writer->write_uint24(writer, depth);
211 writer->write_uint24(writer, name->get_vendor_id(name));
212 writer->write_uint8 (writer, name->get_qualifier(name));
213 writer->write_uint32(writer, name->get_name(name));
214 writer->write_uint8 (writer, PTS_SIMPLE_COMP_EVID_MEAS_TYPE);
215 writer->write_uint24(writer, extended_pcr);
216 writer->write_uint16(writer, hash_algorithm);
217 writer->write_uint8 (writer, transform);
218 writer->write_uint8 (writer, PTS_SIMPLE_COMP_EVID_RESERVED);
219 writer->write_data (writer, utc_time);
220
221 /* Optional fields */
222 if (validation == PTS_COMP_EVID_VALIDATION_FAILED ||
223 validation == PTS_COMP_EVID_VALIDATION_PASSED)
224 {
225 writer->write_uint16(writer, policy_uri.len);
226 writer->write_data (writer, policy_uri);
227 }
228 if (has_pcr_info)
229 {
230 writer->write_uint16(writer, pcr_before.len);
231 writer->write_data (writer, pcr_before);
232 writer->write_data (writer, pcr_after);
233 }
234
235 writer->write_data(writer, measurement);
236
237 this->value = chunk_clone(writer->get_buf(writer));
238 writer->destroy(writer);
239 }
240
241 METHOD(pa_tnc_attr_t, process, status_t,
242 private_tcg_pts_attr_simple_comp_evid_t *this, u_int32_t *offset)
243 {
244 bio_reader_t *reader;
245 pts_comp_func_name_t *name;
246 u_int8_t flags, fam_and_qualifier, qualifier, reserved;
247 u_int8_t measurement_type, transform, validation;
248 u_int16_t hash_algorithm, len;
249 u_int32_t depth, vendor_id, comp_name, extended_pcr;
250 chunk_t measurement, utc_time, policy_uri, pcr_before, pcr_after;
251 time_t measurement_time;
252 bool has_pcr_info = FALSE, has_validation = FALSE;
253
254 if (this->value.len < PTS_SIMPLE_COMP_EVID_SIZE)
255 {
256 DBG1(DBG_TNC, "insufficient data for Simple Component Evidence");
257 *offset = 0;
258 return FAILED;
259 }
260 reader = bio_reader_create(this->value);
261
262 reader->read_uint8 (reader, &flags);
263 reader->read_uint24(reader, &depth);
264 reader->read_uint24(reader, &vendor_id);
265 reader->read_uint8 (reader, &fam_and_qualifier);
266 reader->read_uint32(reader, &comp_name);
267 reader->read_uint8 (reader, &measurement_type);
268 reader->read_uint24(reader, &extended_pcr);
269 reader->read_uint16(reader, &hash_algorithm);
270 reader->read_uint8 (reader, &transform);
271 reader->read_uint8 (reader, &reserved);
272 reader->read_data (reader, PTS_SIMPLE_COMP_EVID_MEAS_TIME_SIZE, &utc_time);
273
274 if (measurement_type != PTS_SIMPLE_COMP_EVID_MEAS_TYPE)
275 {
276 DBG1(DBG_TNC, "unsupported Measurement Type in Simple Component Evidence");
277 *offset = 12;
278 reader->destroy(reader);
279 return FAILED;
280 }
281
282 validation = flags & PTS_SIMPLE_COMP_EVID_VALIDATION_MASK;
283 qualifier = fam_and_qualifier & ~PTS_SIMPLE_COMP_EVID_FAMILY_MASK;
284
285 /* TODO Parse the UTC time string */
286 measurement_time = 0;
287
288 /* Is optional Policy URI field included? */
289 if (validation == PTS_COMP_EVID_VALIDATION_FAILED ||
290 validation == PTS_COMP_EVID_VALIDATION_PASSED)
291 {
292 reader->read_uint16(reader, &len);
293 reader->read_data(reader, len, &policy_uri);
294 has_validation = TRUE;
295 }
296
297 /* Are optional PCR value fields included? */
298 if (flags & PTS_SIMPLE_COMP_EVID_FLAG_PCR)
299 {
300 reader->read_uint16(reader, &len);
301 reader->read_data(reader, len, &pcr_before);
302 reader->read_data(reader, len, &pcr_after);
303 has_pcr_info = TRUE;
304 }
305
306 /* Measurement field comes at the very end */
307 reader->read_data(reader,reader->remaining(reader), &measurement);
308 reader->destroy(reader);
309
310 /* Create Component Functional Name object */
311 name = pts_comp_func_name_create(vendor_id, comp_name, qualifier);
312
313 /* Create Component Evidence object */
314 measurement = chunk_clone(measurement);
315 this->evidence = pts_comp_evidence_create(name, depth, extended_pcr,
316 hash_algorithm, transform,
317 measurement_time, measurement);
318
319 /* Add options */
320 if (has_validation)
321 {
322 policy_uri = chunk_clone(policy_uri);
323 this->evidence->set_validation(this->evidence, validation, policy_uri);
324 }
325 if (has_pcr_info)
326 {
327 pcr_before = chunk_clone(pcr_before);
328 pcr_after = chunk_clone(pcr_after);
329 this->evidence->set_pcr_info(this->evidence, pcr_before, pcr_after);
330 }
331
332 return SUCCESS;
333 }
334
335 METHOD(pa_tnc_attr_t, destroy, void,
336 private_tcg_pts_attr_simple_comp_evid_t *this)
337 {
338 this->evidence->destroy(this->evidence);
339 free(this);
340 }
341
342 METHOD(tcg_pts_attr_simple_comp_evid_t, get_comp_evidence, pts_comp_evidence_t*,
343 private_tcg_pts_attr_simple_comp_evid_t *this)
344 {
345 return this->evidence;
346 }
347
348 /**
349 * Described in header.
350 */
351 pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create(pts_comp_evidence_t *evid)
352 {
353 private_tcg_pts_attr_simple_comp_evid_t *this;
354
355 INIT(this,
356 .public = {
357 .pa_tnc_attribute = {
358 .get_vendor_id = _get_vendor_id,
359 .get_type = _get_type,
360 .get_value = _get_value,
361 .get_noskip_flag = _get_noskip_flag,
362 .set_noskip_flag = _set_noskip_flag,
363 .build = _build,
364 .process = _process,
365 .destroy = _destroy,
366 },
367 .get_comp_evidence = _get_comp_evidence,
368 },
369 .vendor_id = PEN_TCG,
370 .type = TCG_PTS_SIMPLE_COMP_EVID,
371 .evidence = evid,
372 );
373
374 return &this->public.pa_tnc_attribute;
375 }
376
377
378 /**
379 * Described in header.
380 */
381 pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create_from_data(chunk_t data)
382 {
383 private_tcg_pts_attr_simple_comp_evid_t *this;
384
385 INIT(this,
386 .public = {
387 .pa_tnc_attribute = {
388 .get_vendor_id = _get_vendor_id,
389 .get_type = _get_type,
390 .get_value = _get_value,
391 .get_noskip_flag = _get_noskip_flag,
392 .set_noskip_flag = _set_noskip_flag,
393 .build = _build,
394 .process = _process,
395 .destroy = _destroy,
396 },
397 .get_comp_evidence = _get_comp_evidence,
398 },
399 .vendor_id = PEN_TCG,
400 .type = TCG_PTS_SIMPLE_COMP_EVID,
401 .value = chunk_clone(data),
402 );
403
404 return &this->public.pa_tnc_attribute;
405 }