bound functional component measurements to AIK
[strongswan.git] / src / libpts / pts / components / ita / ita_comp_tboot.c
1 /*
2 * Copyright (C) 2011 Andreas Steffen
3 *
4 * HSR Hochschule fuer Technik Rapperswil
5 *
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>.
10 *
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
14 * for more details.
15 */
16
17 #include "ita_comp_tboot.h"
18 #include "ita_comp_func_name.h"
19
20 #include "libpts.h"
21 #include "pts/components/pts_component.h"
22
23 #include <debug.h>
24 #include <pen/pen.h>
25
26 typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t;
27
28 /**
29 * Private data of a pts_ita_comp_tboot_t object.
30 *
31 */
32 struct pts_ita_comp_tboot_t {
33
34 /**
35 * Public pts_component_t interface.
36 */
37 pts_component_t public;
38
39 /**
40 * Component Functional Name
41 */
42 pts_comp_func_name_t *name;
43
44 /**
45 * Sub-component depth
46 */
47 u_int32_t depth;
48
49 /**
50 * AIK keyid
51 */
52 chunk_t keyid;
53
54 /**
55 * Time of TBOOT measurement
56 */
57 time_t measurement_time;
58
59 /**
60 * Expected measurement count
61 */
62 int count;
63
64 /**
65 * Measurement sequence number
66 */
67 int seq_no;
68
69 };
70
71 METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
72 pts_ita_comp_tboot_t *this)
73 {
74 return this->name;
75 }
76
77 METHOD(pts_component_t, get_evidence_flags, u_int8_t,
78 pts_ita_comp_tboot_t *this)
79 {
80 return PTS_REQ_FUNC_COMP_EVID_PCR;
81 }
82
83 METHOD(pts_component_t, get_depth, u_int32_t,
84 pts_ita_comp_tboot_t *this)
85 {
86 return this->depth;
87 }
88
89 METHOD(pts_component_t, measure, status_t,
90 pts_ita_comp_tboot_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
91 {
92 pts_comp_evidence_t *evid;
93 char *meas_hex, *pcr_before_hex, *pcr_after_hex;
94 chunk_t measurement, pcr_before, pcr_after;
95 size_t hash_size, pcr_len;
96 u_int32_t extended_pcr;
97 pts_pcr_transform_t pcr_transform;
98 pts_meas_algorithms_t hash_algo;
99
100 switch (this->seq_no++)
101 {
102 case 0:
103 /* dummy data since currently the TBOOT log is not retrieved */
104 time(&this->measurement_time);
105 meas_hex = lib->settings->get_str(lib->settings,
106 "libimcv.plugins.imc-attestation.pcr17_meas", NULL);
107 pcr_before_hex = lib->settings->get_str(lib->settings,
108 "libimcv.plugins.imc-attestation.pcr17_before", NULL);
109 pcr_after_hex = lib->settings->get_str(lib->settings,
110 "libimcv.plugins.imc-attestation.pcr17_after", NULL);
111 extended_pcr = PCR_TBOOT_POLICY;
112 break;
113 case 1:
114 /* dummy data since currently the TBOOT log is not retrieved */
115 meas_hex = lib->settings->get_str(lib->settings,
116 "libimcv.plugins.imc-attestation.pcr18_meas", NULL);
117 pcr_before_hex = lib->settings->get_str(lib->settings,
118 "libimcv.plugins.imc-attestation.pcr18_before", NULL);
119 pcr_after_hex = lib->settings->get_str(lib->settings,
120 "libimcv.plugins.imc-attestation.pcr18_after", NULL);
121 extended_pcr = PCR_TBOOT_MLE;
122 break;
123 default:
124 return FAILED;
125 }
126
127 hash_algo = pts->get_meas_algorithm(pts);
128 hash_size = pts_meas_algo_hash_size(hash_algo);
129 pcr_len = pts->get_pcr_len(pts);
130 pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
131
132 /* get and check the measurement data */
133 measurement = chunk_from_hex(
134 chunk_create(meas_hex, strlen(meas_hex)), NULL);
135 pcr_before = chunk_from_hex(
136 chunk_create(pcr_before_hex, strlen(pcr_before_hex)), NULL);
137 pcr_after = chunk_from_hex(
138 chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
139 if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
140 measurement.len != hash_size)
141 {
142 DBG1(DBG_PTS, "TBOOT measurement or pcr data have the wrong size");
143 free(measurement.ptr);
144 free(pcr_before.ptr);
145 free(pcr_after.ptr);
146 return FAILED;
147 }
148
149 evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
150 this->depth, extended_pcr,
151 hash_algo, pcr_transform,
152 this->measurement_time, measurement);
153 evid->set_pcr_info(evid, pcr_before, pcr_after);
154
155 return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
156 }
157
158 METHOD(pts_component_t, verify, status_t,
159 pts_ita_comp_tboot_t *this, pts_t *pts, pts_database_t *pts_db,
160 pts_comp_evidence_t *evidence)
161 {
162 bool has_pcr_info;
163 u_int32_t extended_pcr, vid, name;
164 enum_name_t *names;
165 pts_meas_algorithms_t algo;
166 pts_pcr_transform_t transform;
167 time_t measurement_time;
168 chunk_t measurement, pcr_before, pcr_after;
169
170 measurement = evidence->get_measurement(evidence, &extended_pcr,
171 &algo, &transform, &measurement_time);
172
173 if (!this->keyid.ptr)
174 {
175 if (!pts->get_aik_keyid(pts, &this->keyid))
176 {
177 return FAILED;
178 }
179 this->keyid = chunk_clone(this->keyid);
180
181 if (!pts_db)
182 {
183 DBG1(DBG_PTS, "pts database not available");
184 return FAILED;
185 }
186 if (!pts_db->get_comp_measurement_count(pts_db, this->name, this->keyid,
187 algo, &this->count))
188 {
189 return FAILED;
190 }
191 vid = this->name->get_vendor_id(this->name);
192 name = this->name->get_name(this->name);
193 names = pts_components->get_comp_func_names(pts_components, vid);
194
195 if (this->count == 0)
196 {
197 DBG1(DBG_PTS, "no %N '%N' functional component evidence measurements "
198 "available", pen_names, vid, names, name);
199 return FAILED;
200 }
201 DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence measurements",
202 this->count, pen_names, vid, names, name);
203 }
204
205 if (pts_db->check_comp_measurement(pts_db, measurement, this->name,
206 this->keyid, ++this->seq_no, extended_pcr, algo) != SUCCESS)
207 {
208 return FAILED;
209 }
210
211 has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
212 if (has_pcr_info)
213 {
214 if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
215 {
216 return FAILED;
217 }
218 }
219
220 return (this->seq_no < this->count) ? NEED_MORE : SUCCESS;
221 }
222
223 METHOD(pts_component_t, destroy, void,
224 pts_ita_comp_tboot_t *this)
225 {
226 this->name->destroy(this->name);
227 free(this->keyid.ptr);
228 free(this);
229 }
230
231 /**
232 * See header
233 */
234 pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth)
235 {
236 pts_ita_comp_tboot_t *this;
237
238 INIT(this,
239 .public = {
240 .get_comp_func_name = _get_comp_func_name,
241 .get_evidence_flags = _get_evidence_flags,
242 .get_depth = _get_depth,
243 .measure = _measure,
244 .verify = _verify,
245 .destroy = _destroy,
246 },
247 .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
248 qualifier),
249 .depth = depth,
250 );
251
252 return &this->public;
253 }
254