Annotation of embedaddon/strongswan/src/libimcv/pts/components/ita/ita_comp_tboot.c, revision 1.1.1.2
1.1 misho 1: /*
1.1.1.2 ! misho 2: * Copyright (C) 2011-2020 Andreas Steffen
1.1 misho 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:
19: #include "imcv.h"
20: #include "pts/components/pts_component.h"
21:
22: #include <utils/debug.h>
23: #include <pen/pen.h>
24:
25: typedef 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: */
31: struct pts_ita_comp_tboot_t {
32:
33: /**
34: * Public pts_component_t interface.
35: */
36: pts_component_t public;
37:
38: /**
39: * Component Functional Name
40: */
41: pts_comp_func_name_t *name;
42:
43: /**
44: * Sub-component depth
45: */
46: uint32_t depth;
47:
48: /**
49: * PTS measurement database
50: */
51: pts_database_t *pts_db;
52:
53: /**
54: * Primary key for AIK database entry
55: */
56: int aik_id;
57:
58: /**
59: * Primary key for Component Functional Name database entry
60: */
61: int cid;
62:
63: /**
64: * Component is registering measurements
65: */
66: bool is_registering;
67:
68: /**
69: * Time of TBOOT measurement
70: */
71: time_t measurement_time;
72:
73: /**
74: * Expected measurement count
75: */
76: int count;
77:
78: /**
79: * Measurement sequence number
80: */
81: int seq_no;
82:
83: /**
84: * Reference count
85: */
86: refcount_t ref;
87:
88: };
89:
90: METHOD(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:
96: METHOD(pts_component_t, get_evidence_flags, uint8_t,
97: pts_ita_comp_tboot_t *this)
98: {
99: return PTS_REQ_FUNC_COMP_EVID_PCR;
100: }
101:
102: METHOD(pts_component_t, get_depth, uint32_t,
103: pts_ita_comp_tboot_t *this)
104: {
105: return this->depth;
106: }
107:
108: METHOD(pts_component_t, measure, status_t,
109: pts_ita_comp_tboot_t *this, uint8_t qualifier, pts_t *pts,
110: pts_comp_evidence_t **evidence)
111:
112: {
113: size_t pcr_len;
114: pts_pcr_t *pcrs;
115: pts_pcr_transform_t pcr_transform;
116: pts_meas_algorithms_t hash_algo;
117: pts_comp_evidence_t *evid;
118: char *meas_hex, *pcr_before_hex, *pcr_after_hex;
119: chunk_t measurement, pcr_before, pcr_after;
120: uint32_t extended_pcr;
121:
122: switch (this->seq_no++)
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,
128: "%s.plugins.imc-attestation.pcr17_meas", NULL, lib->ns);
129: pcr_before_hex = lib->settings->get_str(lib->settings,
130: "%s.plugins.imc-attestation.pcr17_before", NULL, lib->ns);
131: pcr_after_hex = lib->settings->get_str(lib->settings,
132: "%s.plugins.imc-attestation.pcr17_after", NULL, lib->ns);
133: extended_pcr = PCR_TBOOT_POLICY;
134: break;
135: case 1:
136: /* dummy data since currently the TBOOT log is not retrieved */
137: meas_hex = lib->settings->get_str(lib->settings,
138: "%s.plugins.imc-attestation.pcr18_meas", NULL, lib->ns);
139: pcr_before_hex = lib->settings->get_str(lib->settings,
140: "%s.plugins.imc-attestation.pcr18_before", NULL, lib->ns);
141: pcr_after_hex = lib->settings->get_str(lib->settings,
142: "%s.plugins.imc-attestation.pcr18_after", NULL, lib->ns);
143: extended_pcr = PCR_TBOOT_MLE;
144: break;
145: default:
146: return FAILED;
147: }
148:
149: if (meas_hex == NULL || pcr_before_hex == NULL || pcr_after_hex == NULL)
150: {
151: return FAILED;
152: }
153:
154: hash_algo = PTS_MEAS_ALGO_SHA1;
155: pcr_len = HASH_SIZE_SHA1;
156: pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
157:
158: /* get and check the measurement data */
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);
165: if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
166: measurement.len != pcr_len)
167: {
168: DBG1(DBG_PTS, "TBOOT measurement or PCR data have the wrong size");
169: free(measurement.ptr);
170: free(pcr_before.ptr);
171: free(pcr_after.ptr);
172: return FAILED;
173: }
174:
175: pcrs = pts->get_pcrs(pts);
1.1.1.2 ! misho 176: if (!pcrs)
! 177: {
! 178: return FAILED;
! 179: }
1.1 misho 180: pcrs->set(pcrs, extended_pcr, pcr_after);
181: evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
182: this->depth, extended_pcr, hash_algo, pcr_transform,
183: this->measurement_time, measurement);
184: evid->set_pcr_info(evid, pcr_before, pcr_after);
185:
186: return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
187: }
188:
189: METHOD(pts_component_t, verify, status_t,
190: pts_ita_comp_tboot_t *this, uint8_t qualifier,pts_t *pts,
191: pts_comp_evidence_t *evidence)
192: {
193: bool has_pcr_info;
194: uint32_t extended_pcr, vid, name;
195: enum_name_t *names;
196: pts_meas_algorithms_t algo;
197: pts_pcr_transform_t transform;
198: pts_pcr_t *pcrs;
199: time_t measurement_time;
200: chunk_t measurement, pcr_before, pcr_after;
201: status_t status;
202:
203: this->aik_id = pts->get_aik_id(pts);
204: pcrs = pts->get_pcrs(pts);
1.1.1.2 ! misho 205: if (!pcrs)
! 206: {
! 207: return FAILED;
! 208: }
1.1 misho 209: measurement = evidence->get_measurement(evidence, &extended_pcr,
210: &algo, &transform, &measurement_time);
211:
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)
216: {
217: return status;
218: }
219: vid = this->name->get_vendor_id(this->name);
220: name = this->name->get_name(this->name);
221: names = imcv_pts_components->get_comp_func_names(imcv_pts_components, vid);
222:
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;
233: }
234:
235: if (this->is_registering)
236: {
237: status = this->pts_db->insert_comp_measurement(this->pts_db,
238: measurement, this->cid, this->aik_id,
239: ++this->seq_no, extended_pcr, algo);
240: if (status != SUCCESS)
241: {
242: return status;
243: }
244: this->count = this->seq_no + 1;
245: }
246: else
247: {
248: status = this->pts_db->check_comp_measurement(this->pts_db,
249: measurement, this->cid, this->aik_id,
250: ++this->seq_no, extended_pcr, algo);
251: if (status != SUCCESS)
252: {
253: return status;
254: }
255: }
256:
257: has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
258: if (has_pcr_info)
259: {
260: if (!chunk_equals_const(pcr_before, pcrs->get(pcrs, extended_pcr)))
261: {
262: DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
263: extended_pcr);
264: }
265: if (pcrs->set(pcrs, extended_pcr, pcr_after))
266: {
267: return SUCCESS;
268: }
269: }
270:
271: return SUCCESS;
272: }
273:
274: METHOD(pts_component_t, finalize, bool,
275: pts_ita_comp_tboot_t *this, uint8_t qualifier, bio_writer_t *result)
276: {
277: char result_buf[BUF_LEN];
278:
279: if (this->is_registering)
280: {
281: /* close registration */
282: this->is_registering = FALSE;
283:
284: snprintf(result_buf, BUF_LEN, "registered %d evidence measurements",
285: this->seq_no);
286: }
287: else if (this->seq_no < this->count)
288: {
289: snprintf(result_buf, BUF_LEN, "%d of %d evidence measurements "
290: "missing", this->count - this->seq_no, this->count);
291: return FALSE;
292: }
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));
300:
301: return TRUE;
302: }
303:
304: METHOD(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:
311: METHOD(pts_component_t, destroy, void,
312: pts_ita_comp_tboot_t *this)
313: {
314: int count;
315: uint32_t vid, name;
316: enum_name_t *names;
317:
318: if (ref_put(&this->ref))
319: {
320: if (this->is_registering)
321: {
322: count = this->pts_db->delete_comp_measurements(this->pts_db,
323: this->cid, this->aik_id);
324: vid = this->name->get_vendor_id(this->name);
325: name = this->name->get_name(this->name);
326: names = imcv_pts_components->get_comp_func_names(imcv_pts_components,
327: vid);
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);
332: free(this);
333: }
334: }
335:
336: /**
337: * See header
338: */
339: pts_component_t *pts_ita_comp_tboot_create(uint32_t depth,
340: pts_database_t *pts_db)
341: {
342: pts_ita_comp_tboot_t *this;
343:
344: INIT(this,
345: .public = {
346: .get_comp_func_name = _get_comp_func_name,
347: .get_evidence_flags = _get_evidence_flags,
348: .get_depth = _get_depth,
349: .measure = _measure,
350: .verify = _verify,
351: .finalize = _finalize,
352: .get_ref = _get_ref,
353: .destroy = _destroy,
354: },
355: .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
356: PTS_ITA_QUALIFIER_FLAG_KERNEL |
357: PTS_ITA_QUALIFIER_TYPE_TRUSTED),
358: .depth = depth,
359: .pts_db = pts_db,
360: .ref = 1,
361: );
362:
363: return &this->public;
364: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>