Modified the handling switch for Attributes reception on Attestation IMV/C
[strongswan.git] / src / libimcv / plugins / imv_attestation / imv_attestation.c
1 /*
2 * Copyright (C) 2011 Sansar Choinyambuu
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 "imv_attestation_state.h"
17
18 #include <imv/imv_agent.h>
19 #include <pa_tnc/pa_tnc_msg.h>
20 #include <ietf/ietf_attr.h>
21 #include <ietf/ietf_attr_pa_tnc_error.h>
22 #include <tcg/tcg_attr.h>
23
24 #include <tncif_pa_subtypes.h>
25
26 #include <pen/pen.h>
27 #include <debug.h>
28
29 /* IMV definitions */
30
31 static const char imv_name[] = "Attestation";
32
33 #define IMV_VENDOR_ID PEN_TCG
34 #define IMV_SUBTYPE PA_SUBTYPE_TCG_PTS
35
36 static imv_agent_t *imv_attestation;
37
38 /**
39 * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
40 */
41 TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
42 TNC_Version min_version,
43 TNC_Version max_version,
44 TNC_Version *actual_version)
45 {
46 if (imv_attestation)
47 {
48 DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name);
49 return TNC_RESULT_ALREADY_INITIALIZED;
50 }
51 imv_attestation = imv_agent_create(imv_name, IMV_VENDOR_ID, IMV_SUBTYPE,
52 imv_id, actual_version);
53 if (!imv_attestation)
54 {
55 return TNC_RESULT_FATAL;
56 }
57 if (min_version > TNC_IFIMV_VERSION_1 || max_version < TNC_IFIMV_VERSION_1)
58 {
59 DBG1(DBG_IMV, "no common IF-IMV version");
60 return TNC_RESULT_NO_COMMON_VERSION;
61 }
62 return TNC_RESULT_SUCCESS;
63 }
64
65 /**
66 * see section 3.7.2 of TCG TNC IF-IMV Specification 1.2
67 */
68 TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
69 TNC_ConnectionID connection_id,
70 TNC_ConnectionState new_state)
71 {
72 imv_state_t *state;
73 imv_attestation_state_t *attestation_state;
74
75 if (!imv_attestation)
76 {
77 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
78 return TNC_RESULT_NOT_INITIALIZED;
79 }
80 switch (new_state)
81 {
82 case TNC_CONNECTION_STATE_CREATE:
83 state = imv_attestation_state_create(connection_id);
84 return imv_attestation->create_state(imv_attestation, state);
85 case TNC_CONNECTION_STATE_DELETE:
86 return imv_attestation->delete_state(imv_attestation, connection_id);
87 case TNC_CONNECTION_STATE_HANDSHAKE:
88 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
89 {
90 return TNC_RESULT_FATAL;
91 }
92 state->change_state(state, new_state);
93 attestation_state = (imv_attestation_state_t*)state;
94 /**
95 * do any attestation specific configuration here
96 */
97 return TNC_RESULT_SUCCESS;
98 default:
99 return imv_attestation->change_state(imv_attestation, connection_id,
100 new_state, NULL);
101 }
102 }
103
104 static TNC_Result send_message(TNC_ConnectionID connection_id)
105 {
106 pa_tnc_msg_t *msg;
107 pa_tnc_attr_t *attr;
108 TNC_Result result;
109
110 msg = pa_tnc_msg_create();
111 /**
112 * add TCG PTS attributes
113 */
114 msg->build(msg);
115 result = imv_attestation->send_message(imv_attestation, connection_id,
116 msg->get_encoding(msg));
117 msg->destroy(msg);
118
119 return result;
120 }
121
122 /**
123 * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
124 */
125 TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
126 TNC_ConnectionID connection_id,
127 TNC_BufferReference msg,
128 TNC_UInt32 msg_len,
129 TNC_MessageType msg_type)
130 {
131 pa_tnc_msg_t *pa_tnc_msg;
132 pa_tnc_attr_t *attr;
133 imv_state_t *state;
134 imv_attestation_state_t *imv_attestation_state;
135 enumerator_t *enumerator;
136 TNC_Result result;
137 bool fatal_error = FALSE;
138
139 if (!imv_attestation)
140 {
141 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
142 return TNC_RESULT_NOT_INITIALIZED;
143 }
144
145 /* get current IMV state */
146 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
147 {
148 return TNC_RESULT_FATAL;
149 }
150
151 /* parse received PA-TNC message and automatically handle any errors */
152 result = imv_attestation->receive_message(imv_attestation, connection_id,
153 chunk_create(msg, msg_len), msg_type,
154 &pa_tnc_msg);
155
156 /* no parsed PA-TNC attributes available if an error occurred */
157 if (!pa_tnc_msg)
158 {
159 return result;
160 }
161
162 /* analyze PA-TNC attributes */
163 enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
164 while (enumerator->enumerate(enumerator, &attr))
165 {
166 if (attr->get_vendor_id(attr) == PEN_IETF &&
167 attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
168 {
169 ietf_attr_pa_tnc_error_t *error_attr;
170 pa_tnc_error_code_t error_code;
171 chunk_t msg_info, attr_info;
172 u_int32_t offset;
173
174 error_attr = (ietf_attr_pa_tnc_error_t*)attr;
175 error_code = error_attr->get_error_code(error_attr);
176 msg_info = error_attr->get_msg_info(error_attr);
177
178 DBG1(DBG_IMV, "received PA-TNC error '%N' concerning message %#B",
179 pa_tnc_error_code_names, error_code, &msg_info);
180 switch (error_code)
181 {
182 case PA_ERROR_INVALID_PARAMETER:
183 offset = error_attr->get_offset(error_attr);
184 DBG1(DBG_IMV, " occurred at offset of %u bytes", offset);
185 break;
186 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
187 attr_info = error_attr->get_attr_info(error_attr);
188 DBG1(DBG_IMV, " unsupported attribute %#B", &attr_info);
189 break;
190 default:
191 break;
192 }
193 fatal_error = TRUE;
194 }
195 else if (attr->get_vendor_id(attr) == PEN_TCG)
196 {
197 /**
198 * Handle TCG PTS attributes
199 */
200 switch(attr->get_type(attr))
201 {
202 case TCG_PTS_PROTO_CAPS:
203 break;
204 case TCG_PTS_MEAS_ALGO_SELECTION:
205 break;
206 case TCG_PTS_TPM_VERSION_INFO:
207 break;
208 case TCG_PTS_AIK:
209 break;
210
211 /* PTS-based Attestation Evidence */
212 case TCG_PTS_SIMPLE_COMP_EVID:
213 break;
214 case TCG_PTS_SIMPLE_EVID_FINAL:
215 break;
216 case TCG_PTS_FILE_MEAS:
217 break;
218
219 /* TODO: Not implemented yet */
220 case TCG_PTS_DH_NONCE_PARAMS_RESP:
221 case TCG_PTS_UNIX_FILE_META:
222 case TCG_PTS_INTEG_MEAS_LOG:
223 /* Attributes using XML */
224 case TCG_PTS_TEMPL_REF_MANI_SET_META:
225 case TCG_PTS_VERIFICATION_RESULT:
226 case TCG_PTS_INTEG_REPORT:
227 /* On Windows only*/
228 case TCG_PTS_WIN_FILE_META:
229 case TCG_PTS_REGISTRY_VALUE:
230 /* Received on IMC side only*/
231 case TCG_PTS_REQ_PROTO_CAPS:
232 case TCG_PTS_DH_NONCE_PARAMS_REQ:
233 case TCG_PTS_DH_NONCE_FINISH:
234 case TCG_PTS_MEAS_ALGO:
235 case TCG_PTS_GET_TPM_VERSION_INFO:
236 case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
237 case TCG_PTS_UPDATE_TEMPL_REF_MANI:
238 case TCG_PTS_GET_AIK:
239 case TCG_PTS_REQ_FUNCT_COMP_EVID:
240 case TCG_PTS_GEN_ATTEST_EVID:
241 case TCG_PTS_REQ_FILE_META:
242 case TCG_PTS_REQ_FILE_MEAS:
243 case TCG_PTS_REQ_INTEG_MEAS_LOG:
244 default:
245 DBG1(DBG_IMV, "received unsupported attribute '%N'",
246 tcg_attr_names, attr->get_type(attr));
247 break;
248 }
249 }
250 }
251 enumerator->destroy(enumerator);
252 pa_tnc_msg->destroy(pa_tnc_msg);
253
254 if (fatal_error)
255 {
256 state->set_recommendation(state,
257 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
258 TNC_IMV_EVALUATION_RESULT_ERROR);
259 return imv_attestation->provide_recommendation(imv_attestation, connection_id);
260 }
261
262 return imv_attestation->provide_recommendation(imv_attestation, connection_id);
263 }
264
265 /**
266 * see section 3.7.4 of TCG TNC IF-IMV Specification 1.2
267 */
268 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
269 TNC_ConnectionID connection_id)
270 {
271 if (!imv_attestation)
272 {
273 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
274 return TNC_RESULT_NOT_INITIALIZED;
275 }
276 return imv_attestation->provide_recommendation(imv_attestation, connection_id);
277 }
278
279 /**
280 * see section 3.7.5 of TCG TNC IF-IMV Specification 1.2
281 */
282 TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
283 TNC_ConnectionID connection_id)
284 {
285 if (!imv_attestation)
286 {
287 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
288 return TNC_RESULT_NOT_INITIALIZED;
289 }
290 return TNC_RESULT_SUCCESS;
291 }
292
293 /**
294 * see section 3.7.6 of TCG TNC IF-IMV Specification 1.2
295 */
296 TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
297 {
298 if (!imv_attestation)
299 {
300 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
301 return TNC_RESULT_NOT_INITIALIZED;
302 }
303 imv_attestation->destroy(imv_attestation);
304 imv_attestation = NULL;
305
306 return TNC_RESULT_SUCCESS;
307 }
308
309 /**
310 * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.2
311 */
312 TNC_Result TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
313 TNC_TNCS_BindFunctionPointer bind_function)
314 {
315 if (!imv_attestation)
316 {
317 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
318 return TNC_RESULT_NOT_INITIALIZED;
319 }
320 return imv_attestation->bind_functions(imv_attestation, bind_function);
321 }