fixed memory leak in tcg_pts_attr_simple_comp_evid.c
[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 static char *utc_undefined_time_str = "0000-00-00T00:00:00Z";
91
92 /**
93 * Private data of an tcg_pts_attr_simple_comp_evid_t object.
94 */
95 struct private_tcg_pts_attr_simple_comp_evid_t {
96
97 /**
98 * Public members of tcg_pts_attr_simple_comp_evid_t
99 */
100 tcg_pts_attr_simple_comp_evid_t public;
101
102 /**
103 * Attribute vendor ID
104 */
105 pen_t vendor_id;
106
107 /**
108 * Attribute type
109 */
110 u_int32_t type;
111
112 /**
113 * Attribute value
114 */
115 chunk_t value;
116
117 /**
118 * Noskip flag
119 */
120 bool noskip_flag;
121
122 /**
123 * PTS Component Evidence
124 */
125 pts_comp_evidence_t *evidence;
126
127 };
128
129 METHOD(pa_tnc_attr_t, get_vendor_id, pen_t,
130 private_tcg_pts_attr_simple_comp_evid_t *this)
131 {
132 return this->vendor_id;
133 }
134
135 METHOD(pa_tnc_attr_t, get_type, u_int32_t,
136 private_tcg_pts_attr_simple_comp_evid_t *this)
137 {
138 return this->type;
139 }
140
141 METHOD(pa_tnc_attr_t, get_value, chunk_t,
142 private_tcg_pts_attr_simple_comp_evid_t *this)
143 {
144 return this->value;
145 }
146
147 METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
148 private_tcg_pts_attr_simple_comp_evid_t *this)
149 {
150 return this->noskip_flag;
151 }
152
153 METHOD(pa_tnc_attr_t, set_noskip_flag,void,
154 private_tcg_pts_attr_simple_comp_evid_t *this, bool noskip)
155 {
156 this->noskip_flag = noskip;
157 }
158
159 /**
160 * Convert time_t to Simple Component Evidence UTS string format
161 */
162 void measurement_time_to_utc(time_t measurement_time, chunk_t *utc_time)
163 {
164 struct tm t;
165
166 if (measurement_time == UNDEFINED_TIME)
167 {
168 utc_time->ptr = utc_undefined_time_str;
169 }
170 else
171 {
172 gmtime_r(&measurement_time, &t);
173 sprintf(utc_time->ptr, "%04d-%02d-%02dT%02d:%02d:%02dZ",
174 t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
175 t.tm_hour, t.tm_min, t.tm_sec);
176 }
177 }
178
179 METHOD(pa_tnc_attr_t, build, void,
180 private_tcg_pts_attr_simple_comp_evid_t *this)
181 {
182 bio_writer_t *writer;
183 bool has_pcr_info;
184 char utc_time_buf[25];
185 u_int8_t flags;
186 u_int32_t depth, extended_pcr;
187 pts_comp_func_name_t *name;
188 pts_meas_algorithms_t hash_algorithm;
189 pts_pcr_transform_t transform;
190 pts_comp_evid_validation_t validation;
191 time_t measurement_time;
192 chunk_t measurement, utc_time, pcr_before, pcr_after, policy_uri;
193
194 /* Extract parameters from comp_evidence_t object */
195 name = this->evidence->get_comp_func_name(this->evidence,
196 &depth);
197 measurement = this->evidence->get_measurement(this->evidence,
198 &extended_pcr, &hash_algorithm, &transform,
199 &measurement_time);
200 has_pcr_info = this->evidence->get_pcr_info(this->evidence,
201 &pcr_before, &pcr_after);
202 validation = this->evidence->get_validation(this->evidence,
203 &policy_uri);
204
205 /* Determine the flags to set*/
206 flags = validation;
207 if (has_pcr_info)
208 {
209 flags |= PTS_SIMPLE_COMP_EVID_FLAG_PCR;
210 }
211
212 utc_time = chunk_create(utc_time_buf, PTS_SIMPLE_COMP_EVID_MEAS_TIME_SIZE);
213 measurement_time_to_utc(measurement_time, &utc_time);
214
215 writer = bio_writer_create(PTS_SIMPLE_COMP_EVID_SIZE);
216
217 writer->write_uint8 (writer, flags);
218 writer->write_uint24(writer, depth);
219 writer->write_uint24(writer, name->get_vendor_id(name));
220 writer->write_uint8 (writer, name->get_qualifier(name));
221 writer->write_uint32(writer, name->get_name(name));
222 writer->write_uint8 (writer, PTS_SIMPLE_COMP_EVID_MEAS_TYPE);
223 writer->write_uint24(writer, extended_pcr);
224 writer->write_uint16(writer, hash_algorithm);
225 writer->write_uint8 (writer, transform);
226 writer->write_uint8 (writer, PTS_SIMPLE_COMP_EVID_RESERVED);
227 writer->write_data (writer, utc_time);
228
229 /* Optional fields */
230 if (validation == PTS_COMP_EVID_VALIDATION_FAILED ||
231 validation == PTS_COMP_EVID_VALIDATION_PASSED)
232 {
233 writer->write_uint16(writer, policy_uri.len);
234 writer->write_data (writer, policy_uri);
235 }
236 if (has_pcr_info)
237 {
238 writer->write_uint16(writer, pcr_before.len);
239 writer->write_data (writer, pcr_before);
240 writer->write_data (writer, pcr_after);
241 }
242
243 writer->write_data(writer, measurement);
244
245 this->value = chunk_clone(writer->get_buf(writer));
246 writer->destroy(writer);
247 }
248
249 static const int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
250 static const int tm_leap_1970 = 477;
251
252 /**
253 * Convert Simple Component Evidence UTS string format to time_t
254 */
255 bool measurement_time_from_utc(time_t *measurement_time, chunk_t utc_time)
256 {
257 int tm_year, tm_mon, tm_day, tm_days, tm_hour, tm_min, tm_sec, tm_secs;
258 int tm_leap_4, tm_leap_100, tm_leap_400, tm_leap;
259
260 if (memeq(utc_undefined_time_str, utc_time.ptr, utc_time.len))
261 {
262 *measurement_time = 0;
263 return TRUE;
264 }
265 if (sscanf(utc_time.ptr, "%4d-%2d-%2dT%2d:%2d:%2dZ",
266 &tm_year, &tm_mon, &tm_day, &tm_hour, &tm_min, &tm_sec) != 6)
267 {
268 return FALSE;
269 }
270
271 /* representation of months as 0..11 */
272 tm_mon--;
273
274 /* representation of days as 0..30 */
275 tm_day--;
276
277 /* number of leap years between last year and 1970? */
278 tm_leap_4 = (tm_year - 1) / 4;
279 tm_leap_100 = tm_leap_4 / 25;
280 tm_leap_400 = tm_leap_100 / 4;
281 tm_leap = tm_leap_4 - tm_leap_100 + tm_leap_400 - tm_leap_1970;
282
283 /* if date later then February, is the current year a leap year? */
284 if (tm_mon > 1 && (tm_year % 4 == 0) &&
285 (tm_year % 100 != 0 || tm_year % 400 == 0))
286 {
287 tm_leap++;
288 }
289 tm_days = 365 * (tm_year - 1970) + days[tm_mon] + tm_day + tm_leap;
290 tm_secs = 60 * (60 * (24 * tm_days + tm_hour) + tm_min) + tm_sec;
291
292 *measurement_time = tm_secs;
293 return TRUE;
294 }
295
296 METHOD(pa_tnc_attr_t, process, status_t,
297 private_tcg_pts_attr_simple_comp_evid_t *this, u_int32_t *offset)
298 {
299 bio_reader_t *reader;
300 pts_comp_func_name_t *name;
301 u_int8_t flags, fam_and_qualifier, qualifier, reserved;
302 u_int8_t measurement_type, transform, validation;
303 u_int16_t hash_algorithm, len;
304 u_int32_t depth, vendor_id, comp_name, extended_pcr;
305 chunk_t measurement, utc_time, policy_uri, pcr_before, pcr_after;
306 time_t measurement_time;
307 bool has_pcr_info = FALSE, has_validation = FALSE;
308
309 if (this->value.len < PTS_SIMPLE_COMP_EVID_SIZE)
310 {
311 DBG1(DBG_TNC, "insufficient data for Simple Component Evidence");
312 *offset = 0;
313 return FAILED;
314 }
315 reader = bio_reader_create(this->value);
316
317 reader->read_uint8 (reader, &flags);
318 reader->read_uint24(reader, &depth);
319 reader->read_uint24(reader, &vendor_id);
320 reader->read_uint8 (reader, &fam_and_qualifier);
321 reader->read_uint32(reader, &comp_name);
322 reader->read_uint8 (reader, &measurement_type);
323 reader->read_uint24(reader, &extended_pcr);
324 reader->read_uint16(reader, &hash_algorithm);
325 reader->read_uint8 (reader, &transform);
326 reader->read_uint8 (reader, &reserved);
327 reader->read_data (reader, PTS_SIMPLE_COMP_EVID_MEAS_TIME_SIZE, &utc_time);
328
329 if (measurement_type != PTS_SIMPLE_COMP_EVID_MEAS_TYPE)
330 {
331 DBG1(DBG_TNC, "unsupported Measurement Type in "
332 "Simple Component Evidence");
333 *offset = 12;
334 reader->destroy(reader);
335 return FAILED;
336 }
337 if (!measurement_time_from_utc(&measurement_time, utc_time))
338 {
339 DBG1(DBG_TNC, "invalid Measurement Time field in "
340 "Simple Component Evidence");
341 *offset = 20;
342 reader->destroy(reader);
343 return FAILED;
344 }
345 validation = flags & PTS_SIMPLE_COMP_EVID_VALIDATION_MASK;
346 qualifier = fam_and_qualifier & ~PTS_SIMPLE_COMP_EVID_FAMILY_MASK;
347
348 /* Is optional Policy URI field included? */
349 if (validation == PTS_COMP_EVID_VALIDATION_FAILED ||
350 validation == PTS_COMP_EVID_VALIDATION_PASSED)
351 {
352 reader->read_uint16(reader, &len);
353 reader->read_data(reader, len, &policy_uri);
354 has_validation = TRUE;
355 }
356
357 /* Are optional PCR value fields included? */
358 if (flags & PTS_SIMPLE_COMP_EVID_FLAG_PCR)
359 {
360 reader->read_uint16(reader, &len);
361 reader->read_data(reader, len, &pcr_before);
362 reader->read_data(reader, len, &pcr_after);
363 has_pcr_info = TRUE;
364 }
365
366 /* Measurement field comes at the very end */
367 reader->read_data(reader,reader->remaining(reader), &measurement);
368 reader->destroy(reader);
369
370 /* Create Component Functional Name object */
371 name = pts_comp_func_name_create(vendor_id, comp_name, qualifier);
372
373 /* Create Component Evidence object */
374 measurement = chunk_clone(measurement);
375 this->evidence = pts_comp_evidence_create(name, depth, extended_pcr,
376 hash_algorithm, transform,
377 measurement_time, measurement);
378
379 /* Add options */
380 if (has_validation)
381 {
382 policy_uri = chunk_clone(policy_uri);
383 this->evidence->set_validation(this->evidence, validation, policy_uri);
384 }
385 if (has_pcr_info)
386 {
387 pcr_before = chunk_clone(pcr_before);
388 pcr_after = chunk_clone(pcr_after);
389 this->evidence->set_pcr_info(this->evidence, pcr_before, pcr_after);
390 }
391
392 return SUCCESS;
393 }
394
395 METHOD(pa_tnc_attr_t, destroy, void,
396 private_tcg_pts_attr_simple_comp_evid_t *this)
397 {
398 this->evidence->destroy(this->evidence);
399 free(this->value.ptr);
400 free(this);
401 }
402
403 METHOD(tcg_pts_attr_simple_comp_evid_t, get_comp_evidence, pts_comp_evidence_t*,
404 private_tcg_pts_attr_simple_comp_evid_t *this)
405 {
406 return this->evidence;
407 }
408
409 /**
410 * Described in header.
411 */
412 pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create(pts_comp_evidence_t *evid)
413 {
414 private_tcg_pts_attr_simple_comp_evid_t *this;
415
416 INIT(this,
417 .public = {
418 .pa_tnc_attribute = {
419 .get_vendor_id = _get_vendor_id,
420 .get_type = _get_type,
421 .get_value = _get_value,
422 .get_noskip_flag = _get_noskip_flag,
423 .set_noskip_flag = _set_noskip_flag,
424 .build = _build,
425 .process = _process,
426 .destroy = _destroy,
427 },
428 .get_comp_evidence = _get_comp_evidence,
429 },
430 .vendor_id = PEN_TCG,
431 .type = TCG_PTS_SIMPLE_COMP_EVID,
432 .evidence = evid,
433 );
434
435 return &this->public.pa_tnc_attribute;
436 }
437
438
439 /**
440 * Described in header.
441 */
442 pa_tnc_attr_t *tcg_pts_attr_simple_comp_evid_create_from_data(chunk_t data)
443 {
444 private_tcg_pts_attr_simple_comp_evid_t *this;
445
446 INIT(this,
447 .public = {
448 .pa_tnc_attribute = {
449 .get_vendor_id = _get_vendor_id,
450 .get_type = _get_type,
451 .get_value = _get_value,
452 .get_noskip_flag = _get_noskip_flag,
453 .set_noskip_flag = _set_noskip_flag,
454 .build = _build,
455 .process = _process,
456 .destroy = _destroy,
457 },
458 .get_comp_evidence = _get_comp_evidence,
459 },
460 .vendor_id = PEN_TCG,
461 .type = TCG_PTS_SIMPLE_COMP_EVID,
462 .value = chunk_clone(data),
463 );
464
465 return &this->public.pa_tnc_attribute;
466 }