implemented Linux IMA functional component
[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 "pts/components/pts_component.h"
21 #include "pts/components/pts_comp_evidence.h"
22
23 #include <debug.h>
24 #include <pen/pen.h>
25
26 #define TBOOT_SEQUENCE 2
27
28 typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t;
29
30 /**
31 * Private data of a pts_ita_comp_tboot_t object.
32 *
33 */
34 struct pts_ita_comp_tboot_t {
35
36 /**
37 * Public pts_component_t interface.
38 */
39 pts_component_t public;
40
41 /**
42 * Component Functional Name
43 */
44 pts_comp_func_name_t *name;
45
46 /**
47 * Sub-component depth
48 */
49 u_int32_t depth;
50
51 /**
52 * Time of TBOOT measurement
53 */
54 time_t measurement_time;
55
56 /**
57 * Measurement sequence number
58 */
59 int seq_no;
60
61 };
62
63 METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
64 pts_ita_comp_tboot_t *this)
65 {
66 return this->name;
67 }
68
69 METHOD(pts_component_t, get_evidence_flags, u_int8_t,
70 pts_ita_comp_tboot_t *this)
71 {
72 return PTS_REQ_FUNC_COMP_EVID_PCR;
73 }
74
75 METHOD(pts_component_t, get_depth, u_int32_t,
76 pts_ita_comp_tboot_t *this)
77 {
78 return this->depth;
79 }
80
81 METHOD(pts_component_t, measure, status_t,
82 pts_ita_comp_tboot_t *this, pts_t *pts, pts_comp_evidence_t **evidence)
83 {
84 pts_comp_evidence_t *evid;
85 char *meas_hex, *pcr_before_hex, *pcr_after_hex;
86 chunk_t measurement, pcr_before, pcr_after;
87 size_t hash_size, pcr_len;
88 u_int32_t extended_pcr;
89 pts_pcr_transform_t pcr_transform;
90 pts_meas_algorithms_t hash_algo;
91
92 switch (this->seq_no++)
93 {
94 case 0:
95 /* dummy data since currently the TBOOT log is not retrieved */
96 time(&this->measurement_time);
97 meas_hex = lib->settings->get_str(lib->settings,
98 "libimcv.plugins.imc-attestation.pcr17_meas", NULL);
99 pcr_before_hex = lib->settings->get_str(lib->settings,
100 "libimcv.plugins.imc-attestation.pcr17_before", NULL);
101 pcr_after_hex = lib->settings->get_str(lib->settings,
102 "libimcv.plugins.imc-attestation.pcr17_after", NULL);
103 extended_pcr = PCR_TBOOT_POLICY;
104 break;
105 case 1:
106 /* dummy data since currently the TBOOT log is not retrieved */
107 meas_hex = lib->settings->get_str(lib->settings,
108 "libimcv.plugins.imc-attestation.pcr18_meas", NULL);
109 pcr_before_hex = lib->settings->get_str(lib->settings,
110 "libimcv.plugins.imc-attestation.pcr18_before", NULL);
111 pcr_after_hex = lib->settings->get_str(lib->settings,
112 "libimcv.plugins.imc-attestation.pcr18_after", NULL);
113 extended_pcr = PCR_TBOOT_MLE;
114 break;
115 default:
116 return FAILED;
117 }
118
119 hash_algo = pts->get_meas_algorithm(pts);
120 hash_size = pts_meas_algo_hash_size(hash_algo);
121 pcr_len = pts->get_pcr_len(pts);
122 pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
123
124 /* get and check the measurement data */
125 measurement = chunk_from_hex(
126 chunk_create(meas_hex, strlen(meas_hex)), NULL);
127 pcr_before = chunk_from_hex(
128 chunk_create(pcr_before_hex, strlen(pcr_before_hex)), NULL);
129 pcr_after = chunk_from_hex(
130 chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
131 if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
132 measurement.len != hash_size)
133 {
134 DBG1(DBG_PTS, "TBOOT measurement or pcr data have the wrong size");
135 free(measurement.ptr);
136 free(pcr_before.ptr);
137 free(pcr_after.ptr);
138 return FAILED;
139 }
140
141 evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
142 this->depth, extended_pcr,
143 hash_algo, pcr_transform,
144 this->measurement_time, measurement);
145 evid->set_pcr_info(evid, pcr_before, pcr_after);
146
147 return (this->seq_no < TBOOT_SEQUENCE) ? NEED_MORE : SUCCESS;
148 }
149
150 METHOD(pts_component_t, verify, status_t,
151 pts_ita_comp_tboot_t *this, pts_t *pts, pts_database_t *pts_db,
152 pts_comp_evidence_t *evidence)
153 {
154 bool has_pcr_info;
155 char *platform_info;
156 u_int32_t extended_pcr;
157 pts_meas_algorithms_t algo;
158 pts_pcr_transform_t transform;
159 time_t measurement_time;
160 chunk_t measurement, pcr_before, pcr_after, hash;
161
162 platform_info = pts->get_platform_info(pts);
163 if (!pts_db || !platform_info)
164 {
165 DBG1(DBG_PTS, "%s%s%s not available",
166 (pts_db) ? "" : "pts database",
167 (!pts_db && !platform_info) ? "and" : "",
168 (platform_info) ? "" : "platform info");
169 return FAILED;
170 }
171 measurement = evidence->get_measurement(evidence, &extended_pcr,
172 &algo, &transform, &measurement_time);
173
174 if (pts_db->check_comp_measurement(pts_db, measurement, this->name,
175 platform_info, ++this->seq_no, extended_pcr, algo) != SUCCESS)
176 {
177 return FAILED;
178 }
179
180 has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
181 if (has_pcr_info)
182 {
183 if (!pts->add_pcr(pts, extended_pcr, pcr_before, pcr_after))
184 {
185 return FAILED;
186 }
187 }
188
189 return (this->seq_no < TBOOT_SEQUENCE) ? NEED_MORE : SUCCESS;
190 }
191
192 METHOD(pts_component_t, destroy, void,
193 pts_ita_comp_tboot_t *this)
194 {
195 this->name->destroy(this->name);
196 free(this);
197 }
198
199 /**
200 * See header
201 */
202 pts_component_t *pts_ita_comp_tboot_create(u_int8_t qualifier, u_int32_t depth)
203 {
204 pts_ita_comp_tboot_t *this;
205
206 INIT(this,
207 .public = {
208 .get_comp_func_name = _get_comp_func_name,
209 .get_evidence_flags = _get_evidence_flags,
210 .get_depth = _get_depth,
211 .measure = _measure,
212 .verify = _verify,
213 .destroy = _destroy,
214 },
215 .name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
216 qualifier),
217 .depth = depth,
218 );
219
220 return &this->public;
221 }
222