2 * Copyright (C) 2011-2012 Andreas Steffen
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 "ita_comp_tboot.h"
17 #include "ita_comp_func_name.h"
20 #include "pts/components/pts_component.h"
22 #include <utils/debug.h>
25 typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t
;
28 * Private data of a pts_ita_comp_tboot_t object.
31 struct pts_ita_comp_tboot_t
{
34 * Public pts_component_t interface.
36 pts_component_t
public;
39 * Component Functional Name
41 pts_comp_func_name_t
*name
;
54 * PTS measurement database
56 pts_database_t
*pts_db
;
59 * Primary key for Component Functional Name database entry
64 * Primary key for AIK database entry
69 * Component is registering measurements
74 * Time of TBOOT measurement
76 time_t measurement_time
;
79 * Expected measurement count
84 * Measurement sequence number
95 METHOD(pts_component_t
, get_comp_func_name
, pts_comp_func_name_t
*,
96 pts_ita_comp_tboot_t
*this)
101 METHOD(pts_component_t
, get_evidence_flags
, u_int8_t
,
102 pts_ita_comp_tboot_t
*this)
104 return PTS_REQ_FUNC_COMP_EVID_PCR
;
107 METHOD(pts_component_t
, get_depth
, u_int32_t
,
108 pts_ita_comp_tboot_t
*this)
113 METHOD(pts_component_t
, measure
, status_t
,
114 pts_ita_comp_tboot_t
*this, u_int8_t qualifier
, pts_t
*pts
,
115 pts_comp_evidence_t
**evidence
)
120 pts_pcr_transform_t pcr_transform
;
121 pts_meas_algorithms_t hash_algo
;
122 pts_comp_evidence_t
*evid
;
123 char *meas_hex
, *pcr_before_hex
, *pcr_after_hex
;
124 chunk_t measurement
, pcr_before
, pcr_after
;
125 u_int32_t extended_pcr
;
127 switch (this->seq_no
++)
130 /* dummy data since currently the TBOOT log is not retrieved */
131 time(&this->measurement_time
);
132 meas_hex
= lib
->settings
->get_str(lib
->settings
,
133 "%s.plugins.imc-attestation.pcr17_meas", NULL
, lib
->ns
);
134 pcr_before_hex
= lib
->settings
->get_str(lib
->settings
,
135 "%s.plugins.imc-attestation.pcr17_before", NULL
, lib
->ns
);
136 pcr_after_hex
= lib
->settings
->get_str(lib
->settings
,
137 "%s.plugins.imc-attestation.pcr17_after", NULL
, lib
->ns
);
138 extended_pcr
= PCR_TBOOT_POLICY
;
141 /* dummy data since currently the TBOOT log is not retrieved */
142 meas_hex
= lib
->settings
->get_str(lib
->settings
,
143 "%s.plugins.imc-attestation.pcr18_meas", NULL
, lib
->ns
);
144 pcr_before_hex
= lib
->settings
->get_str(lib
->settings
,
145 "%s.plugins.imc-attestation.pcr18_before", NULL
, lib
->ns
);
146 pcr_after_hex
= lib
->settings
->get_str(lib
->settings
,
147 "%s.plugins.imc-attestation.pcr18_after", NULL
, lib
->ns
);
148 extended_pcr
= PCR_TBOOT_MLE
;
154 if (meas_hex
== NULL
|| pcr_before_hex
== NULL
|| pcr_after_hex
== NULL
)
159 hash_algo
= PTS_MEAS_ALGO_SHA1
;
160 pcr_len
= HASH_SIZE_SHA1
;
161 pcr_transform
= pts_meas_algo_to_pcr_transform(hash_algo
, pcr_len
);
163 /* get and check the measurement data */
164 measurement
= chunk_from_hex(
165 chunk_create(meas_hex
, strlen(meas_hex
)), NULL
);
166 pcr_before
= chunk_from_hex(
167 chunk_create(pcr_before_hex
, strlen(pcr_before_hex
)), NULL
);
168 pcr_after
= chunk_from_hex(
169 chunk_create(pcr_after_hex
, strlen(pcr_after_hex
)), NULL
);
170 if (pcr_before
.len
!= pcr_len
|| pcr_after
.len
!= pcr_len
||
171 measurement
.len
!= pcr_len
)
173 DBG1(DBG_PTS
, "TBOOT measurement or PCR data have the wrong size");
174 free(measurement
.ptr
);
175 free(pcr_before
.ptr
);
180 pcrs
= pts
->get_pcrs(pts
);
181 pcrs
->set(pcrs
, extended_pcr
, pcr_after
);
182 evid
= *evidence
= pts_comp_evidence_create(this->name
->clone(this->name
),
183 this->depth
, extended_pcr
, hash_algo
, pcr_transform
,
184 this->measurement_time
, measurement
);
185 evid
->set_pcr_info(evid
, pcr_before
, pcr_after
);
187 return (this->seq_no
< 2) ? NEED_MORE
: SUCCESS
;
190 METHOD(pts_component_t
, verify
, status_t
,
191 pts_ita_comp_tboot_t
*this, u_int8_t qualifier
,pts_t
*pts
,
192 pts_comp_evidence_t
*evidence
)
195 u_int32_t extended_pcr
, vid
, name
;
197 pts_meas_algorithms_t algo
;
198 pts_pcr_transform_t transform
;
200 time_t measurement_time
;
201 chunk_t measurement
, pcr_before
, pcr_after
;
204 pcrs
= pts
->get_pcrs(pts
);
205 measurement
= evidence
->get_measurement(evidence
, &extended_pcr
,
206 &algo
, &transform
, &measurement_time
);
208 if (!this->keyid
.ptr
)
210 if (!pts
->get_aik_keyid(pts
, &this->keyid
))
214 this->keyid
= chunk_clone(this->keyid
);
218 DBG1(DBG_PTS
, "pts database not available");
221 status
= this->pts_db
->get_comp_measurement_count(this->pts_db
,
222 this->name
, this->keyid
, algo
, &this->cid
,
223 &this->kid
, &this->count
);
224 if (status
!= SUCCESS
)
228 vid
= this->name
->get_vendor_id(this->name
);
229 name
= this->name
->get_name(this->name
);
230 names
= pts_components
->get_comp_func_names(pts_components
, vid
);
234 DBG1(DBG_PTS
, "checking %d %N '%N' functional component evidence "
235 "measurements", this->count
, pen_names
, vid
, names
, name
);
239 DBG1(DBG_PTS
, "registering %N '%N' functional component evidence "
240 "measurements", pen_names
, vid
, names
, name
);
241 this->is_registering
= TRUE
;
245 if (this->is_registering
)
247 status
= this->pts_db
->insert_comp_measurement(this->pts_db
,
248 measurement
, this->cid
, this->kid
,
249 ++this->seq_no
, extended_pcr
, algo
);
250 if (status
!= SUCCESS
)
254 this->count
= this->seq_no
+ 1;
258 status
= this->pts_db
->check_comp_measurement(this->pts_db
,
259 measurement
, this->cid
, this->kid
,
260 ++this->seq_no
, extended_pcr
, algo
);
261 if (status
!= SUCCESS
)
267 has_pcr_info
= evidence
->get_pcr_info(evidence
, &pcr_before
, &pcr_after
);
270 if (!chunk_equals(pcr_before
, pcrs
->get(pcrs
, extended_pcr
)))
272 DBG1(DBG_PTS
, "PCR %2u: pcr_before is not equal to register value",
275 if (pcrs
->set(pcrs
, extended_pcr
, pcr_after
))
284 METHOD(pts_component_t
, finalize
, bool,
285 pts_ita_comp_tboot_t
*this, u_int8_t qualifier
)
290 vid
= this->name
->get_vendor_id(this->name
);
291 name
= this->name
->get_name(this->name
);
292 names
= pts_components
->get_comp_func_names(pts_components
, vid
);
294 if (this->is_registering
)
296 /* close registration */
297 this->is_registering
= FALSE
;
299 DBG1(DBG_PTS
, "registered %d %N '%N' functional component evidence "
300 "measurements", this->seq_no
, pen_names
, vid
, names
, name
);
302 else if (this->seq_no
< this->count
)
304 DBG1(DBG_PTS
, "%d of %d %N '%N' functional component evidence "
305 "measurements missing", this->count
- this->seq_no
,
306 this->count
, pen_names
, vid
, names
, name
);
313 METHOD(pts_component_t
, get_ref
, pts_component_t
*,
314 pts_ita_comp_tboot_t
*this)
317 return &this->public;
320 METHOD(pts_component_t
, destroy
, void,
321 pts_ita_comp_tboot_t
*this)
327 if (ref_put(&this->ref
))
329 if (this->is_registering
)
331 count
= this->pts_db
->delete_comp_measurements(this->pts_db
,
332 this->cid
, this->kid
);
333 vid
= this->name
->get_vendor_id(this->name
);
334 name
= this->name
->get_name(this->name
);
335 names
= pts_components
->get_comp_func_names(pts_components
, vid
);
336 DBG1(DBG_PTS
, "deleted %d registered %N '%N' functional component "
337 "evidence measurements", count
, pen_names
, vid
, names
, name
);
339 this->name
->destroy(this->name
);
340 free(this->keyid
.ptr
);
348 pts_component_t
*pts_ita_comp_tboot_create(u_int32_t depth
,
349 pts_database_t
*pts_db
)
351 pts_ita_comp_tboot_t
*this;
355 .get_comp_func_name
= _get_comp_func_name
,
356 .get_evidence_flags
= _get_evidence_flags
,
357 .get_depth
= _get_depth
,
360 .finalize
= _finalize
,
364 .name
= pts_comp_func_name_create(PEN_ITA
, PTS_ITA_COMP_FUNC_NAME_TBOOT
,
365 PTS_ITA_QUALIFIER_FLAG_KERNEL
|
366 PTS_ITA_QUALIFIER_TYPE_TRUSTED
),
372 return &this->public;