2 * Copyright (C) 2011 Sansar Choinyambuu
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "tcg_pts_attr_simple_comp_evid.h"
18 #include <pa_tnc/pa_tnc_msg.h>
19 #include <bio/bio_writer.h>
20 #include <bio/bio_reader.h>
25 typedef struct private_tcg_pts_attr_simple_comp_evid_t private_tcg_pts_attr_simple_comp_evid_t
;
28 * Simple Component Evidence
29 * see section 3.15.1 of PTS Protocol: Binding to TNC IF-M Specification
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 * Specific Functional Component -> Component Functional Name Structure
70 * see section 5.1 of PTS Protocol: Binding to TNC IF-M Specification
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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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)
90 static char *utc_undefined_time_str
= "0000-00-00T00:00:00Z";
93 * Private data of an tcg_pts_attr_simple_comp_evid_t object.
95 struct private_tcg_pts_attr_simple_comp_evid_t
{
98 * Public members of tcg_pts_attr_simple_comp_evid_t
100 tcg_pts_attr_simple_comp_evid_t
public;
103 * Attribute vendor ID
123 * PTS Component Evidence
125 pts_comp_evidence_t
*evidence
;
129 METHOD(pa_tnc_attr_t
, get_vendor_id
, pen_t
,
130 private_tcg_pts_attr_simple_comp_evid_t
*this)
132 return this->vendor_id
;
135 METHOD(pa_tnc_attr_t
, get_type
, u_int32_t
,
136 private_tcg_pts_attr_simple_comp_evid_t
*this)
141 METHOD(pa_tnc_attr_t
, get_value
, chunk_t
,
142 private_tcg_pts_attr_simple_comp_evid_t
*this)
147 METHOD(pa_tnc_attr_t
, get_noskip_flag
, bool,
148 private_tcg_pts_attr_simple_comp_evid_t
*this)
150 return this->noskip_flag
;
153 METHOD(pa_tnc_attr_t
, set_noskip_flag
,void,
154 private_tcg_pts_attr_simple_comp_evid_t
*this, bool noskip
)
156 this->noskip_flag
= noskip
;
160 * Convert time_t to Simple Component Evidence UTS string format
162 void measurement_time_to_utc(time_t measurement_time
, chunk_t
*utc_time
)
166 if (measurement_time
== UNDEFINED_TIME
)
168 utc_time
->ptr
= utc_undefined_time_str
;
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
);
179 METHOD(pa_tnc_attr_t
, build
, void,
180 private_tcg_pts_attr_simple_comp_evid_t
*this)
182 bio_writer_t
*writer
;
184 char utc_time_buf
[25];
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
;
194 /* Extract parameters from comp_evidence_t object */
195 name
= this->evidence
->get_comp_func_name(this->evidence
,
197 measurement
= this->evidence
->get_measurement(this->evidence
,
198 &extended_pcr
, &hash_algorithm
, &transform
,
200 has_pcr_info
= this->evidence
->get_pcr_info(this->evidence
,
201 &pcr_before
, &pcr_after
);
202 validation
= this->evidence
->get_validation(this->evidence
,
205 /* Determine the flags to set*/
209 flags
|= PTS_SIMPLE_COMP_EVID_FLAG_PCR
;
212 utc_time
= chunk_create(utc_time_buf
, PTS_SIMPLE_COMP_EVID_MEAS_TIME_SIZE
);
213 measurement_time_to_utc(measurement_time
, &utc_time
);
215 writer
= bio_writer_create(PTS_SIMPLE_COMP_EVID_SIZE
);
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
);
229 /* Optional fields */
230 if (validation
== PTS_COMP_EVID_VALIDATION_FAILED
||
231 validation
== PTS_COMP_EVID_VALIDATION_PASSED
)
233 writer
->write_uint16(writer
, policy_uri
.len
);
234 writer
->write_data (writer
, policy_uri
);
238 writer
->write_uint16(writer
, pcr_before
.len
);
239 writer
->write_data (writer
, pcr_before
);
240 writer
->write_data (writer
, pcr_after
);
243 writer
->write_data(writer
, measurement
);
245 this->value
= chunk_clone(writer
->get_buf(writer
));
246 writer
->destroy(writer
);
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;
253 * Convert Simple Component Evidence UTS string format to time_t
255 bool measurement_time_from_utc(time_t *measurement_time
, chunk_t utc_time
)
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
;
260 if (memeq(utc_undefined_time_str
, utc_time
.ptr
, utc_time
.len
))
262 *measurement_time
= 0;
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)
271 /* representation of months as 0..11 */
274 /* representation of days as 0..30 */
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
;
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))
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
;
292 *measurement_time
= tm_secs
;
296 METHOD(pa_tnc_attr_t
, process
, status_t
,
297 private_tcg_pts_attr_simple_comp_evid_t
*this, u_int32_t
*offset
)
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
;
309 if (this->value
.len
< PTS_SIMPLE_COMP_EVID_SIZE
)
311 DBG1(DBG_TNC
, "insufficient data for Simple Component Evidence");
315 reader
= bio_reader_create(this->value
);
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
);
329 if (measurement_type
!= PTS_SIMPLE_COMP_EVID_MEAS_TYPE
)
331 DBG1(DBG_TNC
, "unsupported Measurement Type in "
332 "Simple Component Evidence");
334 reader
->destroy(reader
);
337 if (!measurement_time_from_utc(&measurement_time
, utc_time
))
339 DBG1(DBG_TNC
, "invalid Measurement Time field in "
340 "Simple Component Evidence");
342 reader
->destroy(reader
);
345 validation
= flags
& PTS_SIMPLE_COMP_EVID_VALIDATION_MASK
;
346 qualifier
= fam_and_qualifier
& ~PTS_SIMPLE_COMP_EVID_FAMILY_MASK
;
348 /* Is optional Policy URI field included? */
349 if (validation
== PTS_COMP_EVID_VALIDATION_FAILED
||
350 validation
== PTS_COMP_EVID_VALIDATION_PASSED
)
352 reader
->read_uint16(reader
, &len
);
353 reader
->read_data(reader
, len
, &policy_uri
);
354 has_validation
= TRUE
;
357 /* Are optional PCR value fields included? */
358 if (flags
& PTS_SIMPLE_COMP_EVID_FLAG_PCR
)
360 reader
->read_uint16(reader
, &len
);
361 reader
->read_data(reader
, len
, &pcr_before
);
362 reader
->read_data(reader
, len
, &pcr_after
);
366 /* Measurement field comes at the very end */
367 reader
->read_data(reader
,reader
->remaining(reader
), &measurement
);
368 reader
->destroy(reader
);
370 /* Create Component Functional Name object */
371 name
= pts_comp_func_name_create(vendor_id
, comp_name
, qualifier
);
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
);
382 policy_uri
= chunk_clone(policy_uri
);
383 this->evidence
->set_validation(this->evidence
, validation
, policy_uri
);
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
);
395 METHOD(pa_tnc_attr_t
, destroy
, void,
396 private_tcg_pts_attr_simple_comp_evid_t
*this)
398 this->evidence
->destroy(this->evidence
);
402 METHOD(tcg_pts_attr_simple_comp_evid_t
, get_comp_evidence
, pts_comp_evidence_t
*,
403 private_tcg_pts_attr_simple_comp_evid_t
*this)
405 return this->evidence
;
409 * Described in header.
411 pa_tnc_attr_t
*tcg_pts_attr_simple_comp_evid_create(pts_comp_evidence_t
*evid
)
413 private_tcg_pts_attr_simple_comp_evid_t
*this;
417 .pa_tnc_attribute
= {
418 .get_vendor_id
= _get_vendor_id
,
419 .get_type
= _get_type
,
420 .get_value
= _get_value
,
421 .get_noskip_flag
= _get_noskip_flag
,
422 .set_noskip_flag
= _set_noskip_flag
,
427 .get_comp_evidence
= _get_comp_evidence
,
429 .vendor_id
= PEN_TCG
,
430 .type
= TCG_PTS_SIMPLE_COMP_EVID
,
434 return &this->public.pa_tnc_attribute
;
439 * Described in header.
441 pa_tnc_attr_t
*tcg_pts_attr_simple_comp_evid_create_from_data(chunk_t data
)
443 private_tcg_pts_attr_simple_comp_evid_t
*this;
447 .pa_tnc_attribute
= {
448 .get_vendor_id
= _get_vendor_id
,
449 .get_type
= _get_type
,
450 .get_value
= _get_value
,
451 .get_noskip_flag
= _get_noskip_flag
,
452 .set_noskip_flag
= _set_noskip_flag
,
457 .get_comp_evidence
= _get_comp_evidence
,
459 .vendor_id
= PEN_TCG
,
460 .type
= TCG_PTS_SIMPLE_COMP_EVID
,
461 .value
= chunk_clone(data
),
464 return &this->public.pa_tnc_attribute
;