created empty imc_attestation and imv_attestation plugin hulls
[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 <pen/pen.h>
25
26 #include <debug.h>
27
28 /* IMV definitions */
29
30 static const char imv_name[] = "Attestation";
31
32 #define IMV_VENDOR_ID PEN_ITA
33 #define IMV_SUBTYPE 0x02
34
35 static imv_agent_t *imv_attestation;
36
37 /**
38 * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
39 */
40 TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
41 TNC_Version min_version,
42 TNC_Version max_version,
43 TNC_Version *actual_version)
44 {
45 if (imv_attestation)
46 {
47 DBG1(DBG_IMV, "IMV \"%s\" has already been initialized", imv_name);
48 return TNC_RESULT_ALREADY_INITIALIZED;
49 }
50 imv_attestation = imv_agent_create(imv_name, IMV_VENDOR_ID, IMV_SUBTYPE,
51 imv_id, actual_version);
52 if (!imv_attestation)
53 {
54 return TNC_RESULT_FATAL;
55 }
56 if (min_version > TNC_IFIMV_VERSION_1 || max_version < TNC_IFIMV_VERSION_1)
57 {
58 DBG1(DBG_IMV, "no common IF-IMV version");
59 return TNC_RESULT_NO_COMMON_VERSION;
60 }
61 return TNC_RESULT_SUCCESS;
62 }
63
64 /**
65 * see section 3.7.2 of TCG TNC IF-IMV Specification 1.2
66 */
67 TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
68 TNC_ConnectionID connection_id,
69 TNC_ConnectionState new_state)
70 {
71 imv_state_t *state;
72 imv_attestation_state_t *attestation_state;
73
74 if (!imv_attestation)
75 {
76 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
77 return TNC_RESULT_NOT_INITIALIZED;
78 }
79 switch (new_state)
80 {
81 case TNC_CONNECTION_STATE_CREATE:
82 state = imv_attestation_state_create(connection_id);
83 return imv_attestation->create_state(imv_attestation, state);
84 case TNC_CONNECTION_STATE_DELETE:
85 return imv_attestation->delete_state(imv_attestation, connection_id);
86 case TNC_CONNECTION_STATE_HANDSHAKE:
87 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
88 {
89 return TNC_RESULT_FATAL;
90 }
91 state->change_state(state, new_state);
92 attestation_state = (imv_attestation_state_t*)state;
93 /**
94 * do any attestation specific configuration here
95 */
96 return TNC_RESULT_SUCCESS;
97 default:
98 return imv_attestation->change_state(imv_attestation, connection_id, new_state);
99 }
100 }
101
102 static TNC_Result send_message(TNC_ConnectionID connection_id)
103 {
104 pa_tnc_msg_t *msg;
105 pa_tnc_attr_t *attr;
106 TNC_Result result;
107
108 msg = pa_tnc_msg_create();
109 /**
110 * add TCG PTS attributes
111 */
112 msg->build(msg);
113 result = imv_attestation->send_message(imv_attestation, connection_id,
114 msg->get_encoding(msg));
115 msg->destroy(msg);
116
117 return result;
118 }
119
120 /**
121 * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
122 */
123 TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
124 TNC_ConnectionID connection_id,
125 TNC_BufferReference msg,
126 TNC_UInt32 msg_len,
127 TNC_MessageType msg_type)
128 {
129 pa_tnc_msg_t *pa_tnc_msg;
130 pa_tnc_attr_t *attr;
131 imv_state_t *state;
132 imv_attestation_state_t *imv_attestation_state;
133 enumerator_t *enumerator;
134 TNC_Result result;
135 bool fatal_error = FALSE;
136
137 if (!imv_attestation)
138 {
139 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
140 return TNC_RESULT_NOT_INITIALIZED;
141 }
142
143 /* get current IMV state */
144 if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
145 {
146 return TNC_RESULT_FATAL;
147 }
148
149 /* parse received PA-TNC message and automatically handle any errors */
150 result = imv_attestation->receive_message(imv_attestation, connection_id,
151 chunk_create(msg, msg_len), msg_type,
152 &pa_tnc_msg);
153
154 /* no parsed PA-TNC attributes available if an error occurred */
155 if (!pa_tnc_msg)
156 {
157 return result;
158 }
159
160 /* analyze PA-TNC attributes */
161 enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
162 while (enumerator->enumerate(enumerator, &attr))
163 {
164 if (attr->get_vendor_id(attr) == PEN_IETF &&
165 attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
166 {
167 ietf_attr_pa_tnc_error_t *error_attr;
168 pa_tnc_error_code_t error_code;
169 chunk_t msg_info, attr_info;
170
171 error_attr = (ietf_attr_pa_tnc_error_t*)attr;
172 error_code = error_attr->get_error_code(error_attr);
173 msg_info = error_attr->get_msg_info(error_attr);
174
175 DBG1(DBG_IMV, "received PA-TNC error '%N' concerning message %#B",
176 pa_tnc_error_code_names, error_code, &msg_info);
177 switch (error_code)
178 {
179 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
180 attr_info = error_attr->get_attr_info(error_attr);
181 DBG1(DBG_IMV, " unsupported attribute %#B", &attr_info);
182 break;
183 default:
184 break;
185 }
186 fatal_error = TRUE;
187 }
188 else if (attr->get_vendor_id(attr) == PEN_TCG)
189 {
190 /**
191 * Handle TCG PTS attributes
192 */
193 }
194 }
195 enumerator->destroy(enumerator);
196 pa_tnc_msg->destroy(pa_tnc_msg);
197
198 if (fatal_error)
199 {
200 state->set_recommendation(state,
201 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
202 TNC_IMV_EVALUATION_RESULT_ERROR);
203 return imv_attestation->provide_recommendation(imv_attestation, connection_id);
204 }
205
206 return imv_attestation->provide_recommendation(imv_attestation, connection_id);
207 }
208
209 /**
210 * see section 3.7.4 of TCG TNC IF-IMV Specification 1.2
211 */
212 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
213 TNC_ConnectionID connection_id)
214 {
215 if (!imv_attestation)
216 {
217 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
218 return TNC_RESULT_NOT_INITIALIZED;
219 }
220 return imv_attestation->provide_recommendation(imv_attestation, connection_id);
221 }
222
223 /**
224 * see section 3.7.5 of TCG TNC IF-IMV Specification 1.2
225 */
226 TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
227 TNC_ConnectionID connection_id)
228 {
229 if (!imv_attestation)
230 {
231 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
232 return TNC_RESULT_NOT_INITIALIZED;
233 }
234 return TNC_RESULT_SUCCESS;
235 }
236
237 /**
238 * see section 3.7.6 of TCG TNC IF-IMV Specification 1.2
239 */
240 TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
241 {
242 if (!imv_attestation)
243 {
244 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
245 return TNC_RESULT_NOT_INITIALIZED;
246 }
247 imv_attestation->destroy(imv_attestation);
248 imv_attestation = NULL;
249
250 return TNC_RESULT_SUCCESS;
251 }
252
253 /**
254 * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.2
255 */
256 TNC_Result TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
257 TNC_TNCS_BindFunctionPointer bind_function)
258 {
259 if (!imv_attestation)
260 {
261 DBG1(DBG_IMV, "IMV \"%s\" has not been initialized", imv_name);
262 return TNC_RESULT_NOT_INITIALIZED;
263 }
264 return imv_attestation->bind_functions(imv_attestation, bind_function);
265 }