]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libimcv/pts/components/ita/ita_comp_tboot.c
pts: Parse TPM 2.0 BIOS/EFI event log
[people/ms/strongswan.git] / src / libimcv / pts / components / ita / ita_comp_tboot.c
CommitLineData
051dfbd6 1/*
d647a8f9 2 * Copyright (C) 2011-2020 Andreas Steffen
051dfbd6
AS
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 "ita_comp_tboot.h"
17#include "ita_comp_func_name.h"
18
d6fb2cc6 19#include "imcv.h"
051dfbd6
AS
20#include "pts/components/pts_component.h"
21
f05b4272 22#include <utils/debug.h>
051dfbd6
AS
23#include <pen/pen.h>
24
25typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t;
26
27/**
28 * Private data of a pts_ita_comp_tboot_t object.
29 *
30 */
31struct pts_ita_comp_tboot_t {
32
33 /**
cb3ecd5a 34 * Public pts_component_t interface.
051dfbd6
AS
35 */
36 pts_component_t public;
37
38 /**
39 * Component Functional Name
40 */
41 pts_comp_func_name_t *name;
cb3ecd5a 42
824a7824
SC
43 /**
44 * Sub-component depth
45 */
b12c53ce 46 uint32_t depth;
824a7824 47
db087023
AS
48 /**
49 * PTS measurement database
50 */
51 pts_database_t *pts_db;
52
b138bbee
AS
53 /**
54 * Primary key for AIK database entry
55 */
56 int aik_id;
57
f2a521e7 58 /**
4932278e 59 * Primary key for Component Functional Name database entry
f2a521e7 60 */
4932278e
AS
61 int cid;
62
db087023 63 /**
f05b4272 64 * Component is registering measurements
db087023
AS
65 */
66 bool is_registering;
67
cb3ecd5a 68 /**
86a6f698 69 * Time of TBOOT measurement
cb3ecd5a 70 */
86a6f698 71 time_t measurement_time;
cb3ecd5a 72
f2a521e7
AS
73 /**
74 * Expected measurement count
75 */
76 int count;
77
cb3ecd5a 78 /**
86a6f698 79 * Measurement sequence number
cb3ecd5a 80 */
86a6f698 81 int seq_no;
cb3ecd5a 82
af8354da
AS
83 /**
84 * Reference count
85 */
86 refcount_t ref;
87
051dfbd6
AS
88};
89
90METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
91 pts_ita_comp_tboot_t *this)
92{
93 return this->name;
94}
95
b12c53ce 96METHOD(pts_component_t, get_evidence_flags, uint8_t,
a1ac4d5e
AS
97 pts_ita_comp_tboot_t *this)
98{
8d851141 99 return PTS_REQ_FUNC_COMP_EVID_PCR;
a1ac4d5e
AS
100}
101
b12c53ce 102METHOD(pts_component_t, get_depth, uint32_t,
824a7824
SC
103 pts_ita_comp_tboot_t *this)
104{
105 return this->depth;
106}
107
cb3ecd5a 108METHOD(pts_component_t, measure, status_t,
b12c53ce 109 pts_ita_comp_tboot_t *this, uint8_t qualifier, pts_t *pts,
af8354da 110 pts_comp_evidence_t **evidence)
e0bfc4d6 111
051dfbd6 112{
4c020862
AS
113 size_t pcr_len;
114 pts_pcr_t *pcrs;
115 pts_pcr_transform_t pcr_transform;
116 pts_meas_algorithms_t hash_algo;
cb3ecd5a
AS
117 pts_comp_evidence_t *evid;
118 char *meas_hex, *pcr_before_hex, *pcr_after_hex;
119 chunk_t measurement, pcr_before, pcr_after;
b12c53ce 120 uint32_t extended_pcr;
f05b4272 121
86a6f698 122 switch (this->seq_no++)
cb3ecd5a
AS
123 {
124 case 0:
125 /* dummy data since currently the TBOOT log is not retrieved */
126 time(&this->measurement_time);
127 meas_hex = lib->settings->get_str(lib->settings,
50fdff70 128 "%s.plugins.imc-attestation.pcr17_meas", NULL, lib->ns);
cb3ecd5a 129 pcr_before_hex = lib->settings->get_str(lib->settings,
50fdff70 130 "%s.plugins.imc-attestation.pcr17_before", NULL, lib->ns);
cb3ecd5a 131 pcr_after_hex = lib->settings->get_str(lib->settings,
50fdff70 132 "%s.plugins.imc-attestation.pcr17_after", NULL, lib->ns);
86a6f698 133 extended_pcr = PCR_TBOOT_POLICY;
cb3ecd5a 134 break;
86a6f698 135 case 1:
cb3ecd5a
AS
136 /* dummy data since currently the TBOOT log is not retrieved */
137 meas_hex = lib->settings->get_str(lib->settings,
50fdff70 138 "%s.plugins.imc-attestation.pcr18_meas", NULL, lib->ns);
cb3ecd5a 139 pcr_before_hex = lib->settings->get_str(lib->settings,
50fdff70 140 "%s.plugins.imc-attestation.pcr18_before", NULL, lib->ns);
cb3ecd5a 141 pcr_after_hex = lib->settings->get_str(lib->settings,
50fdff70 142 "%s.plugins.imc-attestation.pcr18_after", NULL, lib->ns);
86a6f698 143 extended_pcr = PCR_TBOOT_MLE;
cb3ecd5a
AS
144 break;
145 default:
146 return FAILED;
147 }
148
3092bf10
AS
149 if (meas_hex == NULL || pcr_before_hex == NULL || pcr_after_hex == NULL)
150 {
151 return FAILED;
152 }
153
4c020862
AS
154 hash_algo = PTS_MEAS_ALGO_SHA1;
155 pcr_len = HASH_SIZE_SHA1;
eeefca6b 156 pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
51b00052 157
eeefca6b 158 /* get and check the measurement data */
cb3ecd5a
AS
159 measurement = chunk_from_hex(
160 chunk_create(meas_hex, strlen(meas_hex)), NULL);
161 pcr_before = chunk_from_hex(
162 chunk_create(pcr_before_hex, strlen(pcr_before_hex)), NULL);
163 pcr_after = chunk_from_hex(
164 chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
eeefca6b 165 if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
4c020862 166 measurement.len != pcr_len)
eeefca6b 167 {
ab957aac 168 DBG1(DBG_PTS, "TBOOT measurement or PCR data have the wrong size");
eeefca6b
AS
169 free(measurement.ptr);
170 free(pcr_before.ptr);
171 free(pcr_after.ptr);
172 return FAILED;
173 }
cb3ecd5a 174
4c020862 175 pcrs = pts->get_pcrs(pts);
d647a8f9
AS
176 if (!pcrs)
177 {
178 return FAILED;
179 }
4c020862 180 pcrs->set(pcrs, extended_pcr, pcr_after);
56fd3baa 181 evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
4c020862
AS
182 this->depth, extended_pcr, hash_algo, pcr_transform,
183 this->measurement_time, measurement);
cb3ecd5a
AS
184 evid->set_pcr_info(evid, pcr_before, pcr_after);
185
f2a521e7 186 return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
051dfbd6
AS
187}
188
cb3ecd5a 189METHOD(pts_component_t, verify, status_t,
b12c53ce 190 pts_ita_comp_tboot_t *this, uint8_t qualifier,pts_t *pts,
af8354da 191 pts_comp_evidence_t *evidence)
051dfbd6 192{
cb3ecd5a 193 bool has_pcr_info;
b12c53ce 194 uint32_t extended_pcr, vid, name;
f2a521e7 195 enum_name_t *names;
cb3ecd5a
AS
196 pts_meas_algorithms_t algo;
197 pts_pcr_transform_t transform;
4c020862 198 pts_pcr_t *pcrs;
cb3ecd5a 199 time_t measurement_time;
f2a521e7 200 chunk_t measurement, pcr_before, pcr_after;
ddafcda4 201 status_t status;
824a7824 202
b138bbee 203 this->aik_id = pts->get_aik_id(pts);
4c020862 204 pcrs = pts->get_pcrs(pts);
d647a8f9
AS
205 if (!pcrs)
206 {
207 return FAILED;
208 }
cb3ecd5a 209 measurement = evidence->get_measurement(evidence, &extended_pcr,
86a6f698 210 &algo, &transform, &measurement_time);
cb3ecd5a 211
b138bbee
AS
212 status = this->pts_db->get_comp_measurement_count(this->pts_db,
213 this->name, this->aik_id, algo,
214 &this->cid, &this->count);
215 if (status != SUCCESS)
f2a521e7 216 {
b138bbee
AS
217 return status;
218 }
219 vid = this->name->get_vendor_id(this->name);
220 name = this->name->get_name(this->name);
d6fb2cc6 221 names = imcv_pts_components->get_comp_func_names(imcv_pts_components, vid);
f2a521e7 222
b138bbee
AS
223 if (this->count)
224 {
225 DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
226 "measurements", this->count, pen_names, vid, names, name);
227 }
228 else
229 {
230 DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
231 "measurements", pen_names, vid, names, name);
232 this->is_registering = TRUE;
db087023 233 }
f2a521e7 234
db087023 235 if (this->is_registering)
f275b543 236 {
ddafcda4 237 status = this->pts_db->insert_comp_measurement(this->pts_db,
b138bbee 238 measurement, this->cid, this->aik_id,
ddafcda4
AS
239 ++this->seq_no, extended_pcr, algo);
240 if (status != SUCCESS)
db087023 241 {
ddafcda4 242 return status;
db087023
AS
243 }
244 this->count = this->seq_no + 1;
245 }
246 else
247 {
ddafcda4 248 status = this->pts_db->check_comp_measurement(this->pts_db,
08feb454 249 measurement, this->cid, this->aik_id,
ddafcda4
AS
250 ++this->seq_no, extended_pcr, algo);
251 if (status != SUCCESS)
db087023 252 {
ddafcda4 253 return status;
db087023 254 }
f275b543
AS
255 }
256
cb3ecd5a
AS
257 has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
258 if (has_pcr_info)
259 {
161a0157 260 if (!chunk_equals_const(pcr_before, pcrs->get(pcrs, extended_pcr)))
19c956b6 261 {
ab957aac 262 DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
4c020862
AS
263 extended_pcr);
264 }
265 if (pcrs->set(pcrs, extended_pcr, pcr_after))
266 {
267 return SUCCESS;
19c956b6 268 }
cb3ecd5a
AS
269 }
270
ddafcda4 271 return SUCCESS;
051dfbd6
AS
272}
273
ddafcda4 274METHOD(pts_component_t, finalize, bool,
b12c53ce 275 pts_ita_comp_tboot_t *this, uint8_t qualifier, bio_writer_t *result)
db087023 276{
975472e4 277 char result_buf[BUF_LEN];
ddafcda4
AS
278
279 if (this->is_registering)
db087023 280 {
ddafcda4
AS
281 /* close registration */
282 this->is_registering = FALSE;
283
975472e4
AS
284 snprintf(result_buf, BUF_LEN, "registered %d evidence measurements",
285 this->seq_no);
ddafcda4
AS
286 }
287 else if (this->seq_no < this->count)
288 {
975472e4
AS
289 snprintf(result_buf, BUF_LEN, "%d of %d evidence measurements "
290 "missing", this->count - this->seq_no, this->count);
db087023
AS
291 return FALSE;
292 }
975472e4
AS
293 else
294 {
295 snprintf(result_buf, BUF_LEN, "%d evidence measurements are ok",
296 this->count);
297 }
298 DBG1(DBG_PTS, "%s", result_buf);
299 result->write_data(result, chunk_from_str(result_buf));
db087023 300
db087023
AS
301 return TRUE;
302}
303
af8354da
AS
304METHOD(pts_component_t, get_ref, pts_component_t*,
305 pts_ita_comp_tboot_t *this)
306{
307 ref_get(&this->ref);
308 return &this->public;
309}
310
051dfbd6 311METHOD(pts_component_t, destroy, void,
824a7824 312 pts_ita_comp_tboot_t *this)
051dfbd6 313{
db087023 314 int count;
b12c53ce 315 uint32_t vid, name;
64d4be9b 316 enum_name_t *names;
db087023 317
af8354da 318 if (ref_put(&this->ref))
db087023 319 {
af8354da
AS
320 if (this->is_registering)
321 {
322 count = this->pts_db->delete_comp_measurements(this->pts_db,
b138bbee 323 this->cid, this->aik_id);
af8354da
AS
324 vid = this->name->get_vendor_id(this->name);
325 name = this->name->get_name(this->name);
d6fb2cc6
AS
326 names = imcv_pts_components->get_comp_func_names(imcv_pts_components,
327 vid);
af8354da
AS
328 DBG1(DBG_PTS, "deleted %d registered %N '%N' functional component "
329 "evidence measurements", count, pen_names, vid, names, name);
330 }
331 this->name->destroy(this->name);
af8354da 332 free(this);
db087023 333 }
051dfbd6
AS
334}
335
336/**
337 * See header
338 */
b12c53ce 339pts_component_t *pts_ita_comp_tboot_create(uint32_t depth,
db087023 340 pts_database_t *pts_db)
051dfbd6
AS
341{
342 pts_ita_comp_tboot_t *this;
343
344 INIT(this,
345 .public = {
346 .get_comp_func_name = _get_comp_func_name,
a1ac4d5e 347 .get_evidence_flags = _get_evidence_flags,
824a7824 348 .get_depth = _get_depth,
051dfbd6
AS
349 .measure = _measure,
350 .verify = _verify,
ddafcda4 351 .finalize = _finalize,
af8354da 352 .get_ref = _get_ref,
051dfbd6
AS
353 .destroy = _destroy,
354 },
355 .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
af8354da
AS
356 PTS_ITA_QUALIFIER_FLAG_KERNEL |
357 PTS_ITA_QUALIFIER_TYPE_TRUSTED),
824a7824 358 .depth = depth,
db087023 359 .pts_db = pts_db,
af8354da 360 .ref = 1,
051dfbd6
AS
361 );
362
363 return &this->public;
364}