2 * Copyright (C) 2011 Andreas Steffen
4 * HSR Hochschule fuer Technik Rapperswil
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 "ita_comp_tboot.h"
18 #include "ita_comp_func_name.h"
21 #include "pts/components/pts_component.h"
26 typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t
;
29 * Private data of a pts_ita_comp_tboot_t object.
32 struct pts_ita_comp_tboot_t
{
35 * Public pts_component_t interface.
37 pts_component_t
public;
40 * Component Functional Name
42 pts_comp_func_name_t
*name
;
55 * PTS measurement database
57 pts_database_t
*pts_db
;
60 * Primary key for Component Functional Name database entry
65 * Primary key for AIK database entry
70 * Component is registering measurements
75 * Time of TBOOT measurement
77 time_t measurement_time
;
80 * Expected measurement count
85 * Measurement sequence number
91 METHOD(pts_component_t
, get_comp_func_name
, pts_comp_func_name_t
*,
92 pts_ita_comp_tboot_t
*this)
97 METHOD(pts_component_t
, get_evidence_flags
, u_int8_t
,
98 pts_ita_comp_tboot_t
*this)
100 return PTS_REQ_FUNC_COMP_EVID_PCR
;
103 METHOD(pts_component_t
, get_depth
, u_int32_t
,
104 pts_ita_comp_tboot_t
*this)
109 METHOD(pts_component_t
, measure
, status_t
,
110 pts_ita_comp_tboot_t
*this, pts_t
*pts
, pts_comp_evidence_t
**evidence
)
112 pts_comp_evidence_t
*evid
;
113 char *meas_hex
, *pcr_before_hex
, *pcr_after_hex
;
114 chunk_t measurement
, pcr_before
, pcr_after
;
115 size_t hash_size
, pcr_len
;
116 u_int32_t extended_pcr
;
117 pts_pcr_transform_t pcr_transform
;
118 pts_meas_algorithms_t hash_algo
;
120 switch (this->seq_no
++)
123 /* dummy data since currently the TBOOT log is not retrieved */
124 time(&this->measurement_time
);
125 meas_hex
= lib
->settings
->get_str(lib
->settings
,
126 "libimcv.plugins.imc-attestation.pcr17_meas", NULL
);
127 pcr_before_hex
= lib
->settings
->get_str(lib
->settings
,
128 "libimcv.plugins.imc-attestation.pcr17_before", NULL
);
129 pcr_after_hex
= lib
->settings
->get_str(lib
->settings
,
130 "libimcv.plugins.imc-attestation.pcr17_after", NULL
);
131 extended_pcr
= PCR_TBOOT_POLICY
;
134 /* dummy data since currently the TBOOT log is not retrieved */
135 meas_hex
= lib
->settings
->get_str(lib
->settings
,
136 "libimcv.plugins.imc-attestation.pcr18_meas", NULL
);
137 pcr_before_hex
= lib
->settings
->get_str(lib
->settings
,
138 "libimcv.plugins.imc-attestation.pcr18_before", NULL
);
139 pcr_after_hex
= lib
->settings
->get_str(lib
->settings
,
140 "libimcv.plugins.imc-attestation.pcr18_after", NULL
);
141 extended_pcr
= PCR_TBOOT_MLE
;
147 if (meas_hex
== NULL
|| pcr_before_hex
== NULL
|| pcr_after_hex
== NULL
)
152 hash_algo
= pts
->get_meas_algorithm(pts
);
153 hash_size
= pts_meas_algo_hash_size(hash_algo
);
154 pcr_len
= pts
->get_pcr_len(pts
);
155 pcr_transform
= pts_meas_algo_to_pcr_transform(hash_algo
, pcr_len
);
157 /* get and check the measurement data */
158 measurement
= chunk_from_hex(
159 chunk_create(meas_hex
, strlen(meas_hex
)), NULL
);
160 pcr_before
= chunk_from_hex(
161 chunk_create(pcr_before_hex
, strlen(pcr_before_hex
)), NULL
);
162 pcr_after
= chunk_from_hex(
163 chunk_create(pcr_after_hex
, strlen(pcr_after_hex
)), NULL
);
164 if (pcr_before
.len
!= pcr_len
|| pcr_after
.len
!= pcr_len
||
165 measurement
.len
!= hash_size
)
167 DBG1(DBG_PTS
, "TBOOT measurement or pcr data have the wrong size");
168 free(measurement
.ptr
);
169 free(pcr_before
.ptr
);
174 evid
= *evidence
= pts_comp_evidence_create(this->name
->clone(this->name
),
175 this->depth
, extended_pcr
,
176 hash_algo
, pcr_transform
,
177 this->measurement_time
, measurement
);
178 evid
->set_pcr_info(evid
, pcr_before
, pcr_after
);
180 return (this->seq_no
< 2) ? NEED_MORE
: SUCCESS
;
183 METHOD(pts_component_t
, verify
, status_t
,
184 pts_ita_comp_tboot_t
*this, pts_t
*pts
, pts_comp_evidence_t
*evidence
)
187 u_int32_t extended_pcr
, vid
, name
;
189 pts_meas_algorithms_t algo
;
190 pts_pcr_transform_t transform
;
191 time_t measurement_time
;
192 chunk_t measurement
, pcr_before
, pcr_after
;
194 measurement
= evidence
->get_measurement(evidence
, &extended_pcr
,
195 &algo
, &transform
, &measurement_time
);
197 if (!this->keyid
.ptr
)
199 if (!pts
->get_aik_keyid(pts
, &this->keyid
))
203 this->keyid
= chunk_clone(this->keyid
);
207 DBG1(DBG_PTS
, "pts database not available");
210 if (this->pts_db
->get_comp_measurement_count(this->pts_db
,
211 this->name
, this->keyid
, algo
,
212 &this->cid
, &this->kid
, &this->count
) != SUCCESS
)
216 vid
= this->name
->get_vendor_id(this->name
);
217 name
= this->name
->get_name(this->name
);
218 names
= pts_components
->get_comp_func_names(pts_components
, vid
);
222 DBG1(DBG_PTS
, "checking %d %N '%N' functional component evidence "
223 "measurements", this->count
, pen_names
, vid
, names
, name
);
227 DBG1(DBG_PTS
, "registering %N '%N' functional component evidence "
228 "measurements", pen_names
, vid
, names
, name
);
229 this->is_registering
= TRUE
;
233 if (this->is_registering
)
235 if (this->pts_db
->insert_comp_measurement(this->pts_db
, measurement
,
236 this->cid
, this->kid
, ++this->seq_no
,
237 extended_pcr
, algo
) != SUCCESS
)
241 this->count
= this->seq_no
+ 1;
245 if (this->pts_db
->check_comp_measurement(this->pts_db
, measurement
,
246 this->cid
, this->kid
, ++this->seq_no
,
247 extended_pcr
, algo
) != SUCCESS
)
253 has_pcr_info
= evidence
->get_pcr_info(evidence
, &pcr_before
, &pcr_after
);
256 if (!pts
->add_pcr(pts
, extended_pcr
, pcr_before
, pcr_after
))
262 return (this->seq_no
< this->count
) ? NEED_MORE
: SUCCESS
;
265 METHOD(pts_component_t
, check_off_registrations
, bool,
266 pts_ita_comp_tboot_t
*this)
271 if (!this->is_registering
)
276 /* Finalize registration */
277 this->is_registering
= FALSE
;
279 vid
= this->name
->get_vendor_id(this->name
);
280 name
= this->name
->get_name(this->name
);
281 names
= pts_components
->get_comp_func_names(pts_components
, vid
);
282 DBG1(DBG_PTS
, "registered %d %N '%N' functional component evidence "
283 "measurements", this->seq_no
, pen_names
, vid
, names
, name
);
287 METHOD(pts_component_t
, destroy
, void,
288 pts_ita_comp_tboot_t
*this)
294 if (this->is_registering
)
296 count
= this->pts_db
->delete_comp_measurements(this->pts_db
,
297 this->cid
, this->kid
);
298 vid
= this->name
->get_vendor_id(this->name
);
299 name
= this->name
->get_name(this->name
);
300 names
= pts_components
->get_comp_func_names(pts_components
, vid
);
301 DBG1(DBG_PTS
, "deleted %d registered %N '%N' functional component "
302 "evidence measurements", count
, pen_names
, vid
, names
, name
);
304 this->name
->destroy(this->name
);
305 free(this->keyid
.ptr
);
312 pts_component_t
*pts_ita_comp_tboot_create(u_int8_t qualifier
, u_int32_t depth
,
313 pts_database_t
*pts_db
)
315 pts_ita_comp_tboot_t
*this;
319 .get_comp_func_name
= _get_comp_func_name
,
320 .get_evidence_flags
= _get_evidence_flags
,
321 .get_depth
= _get_depth
,
324 .check_off_registrations
= _check_off_registrations
,
327 .name
= pts_comp_func_name_create(PEN_ITA
, PTS_ITA_COMP_FUNC_NAME_TBOOT
,
333 return &this->public;