Changes according to the new PTS Attributes addition
[strongswan.git] / src / libimcv / plugins / imc_attestation / imc_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 "imc_attestation_state.h"
17
18 #include <imc/imc_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 /* IMC definitions */
30
31 static const char imc_name[] = "Attestation";
32
33 #define IMC_VENDOR_ID PEN_TCG
34 #define IMC_SUBTYPE PA_SUBTYPE_TCG_PTS
35
36 static imc_agent_t *imc_attestation;
37
38 /**
39 * see section 3.7.1 of TCG TNC IF-IMC Specification 1.2
40 */
41 TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
42 TNC_Version min_version,
43 TNC_Version max_version,
44 TNC_Version *actual_version)
45 {
46 if (imc_attestation)
47 {
48 DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
49 return TNC_RESULT_ALREADY_INITIALIZED;
50 }
51 imc_attestation = imc_agent_create(imc_name, IMC_VENDOR_ID, IMC_SUBTYPE,
52 imc_id, actual_version);
53 if (!imc_attestation)
54 {
55 return TNC_RESULT_FATAL;
56 }
57 if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
58 {
59 DBG1(DBG_IMC, "no common IF-IMC 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-IMC Specification 1.2
67 */
68 TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
69 TNC_ConnectionID connection_id,
70 TNC_ConnectionState new_state)
71 {
72 imc_state_t *state;
73 imc_attestation_state_t *test_state;
74
75 if (!imc_attestation)
76 {
77 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
78 return TNC_RESULT_NOT_INITIALIZED;
79 }
80 switch (new_state)
81 {
82 case TNC_CONNECTION_STATE_CREATE:
83 state = imc_attestation_state_create(connection_id);
84 return imc_attestation->create_state(imc_attestation, state);
85 case TNC_CONNECTION_STATE_DELETE:
86 return imc_attestation->delete_state(imc_attestation, connection_id);
87 case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
88 case TNC_CONNECTION_STATE_ACCESS_NONE:
89 default:
90 return imc_attestation->change_state(imc_attestation, connection_id,
91 new_state, NULL);
92 }
93 }
94
95 static TNC_Result send_message(TNC_ConnectionID connection_id)
96 {
97 pa_tnc_msg_t *msg;
98 pa_tnc_attr_t *attr;
99 imc_state_t *state;
100 imc_attestation_state_t *test_state;
101 TNC_Result result;
102
103 if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
104 {
105 return TNC_RESULT_FATAL;
106 }
107 test_state = (imc_attestation_state_t*)state;
108 msg = pa_tnc_msg_create();
109 /**
110 * add TCG PTS attributes
111 */
112 msg->build(msg);
113 result = imc_attestation->send_message(imc_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-IMC Specification 1.2
122 */
123 TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
124 TNC_ConnectionID connection_id)
125 {
126 if (!imc_attestation)
127 {
128 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
129 return TNC_RESULT_NOT_INITIALIZED;
130 }
131 return send_message(connection_id);
132 }
133
134 /**
135 * see section 3.7.4 of TCG TNC IF-IMC Specification 1.2
136 */
137 TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
138 TNC_ConnectionID connection_id,
139 TNC_BufferReference msg,
140 TNC_UInt32 msg_len,
141 TNC_MessageType msg_type)
142 {
143 pa_tnc_msg_t *pa_tnc_msg;
144 pa_tnc_attr_t *attr;
145 enumerator_t *enumerator;
146 TNC_Result result;
147 bool fatal_error = FALSE;
148
149 if (!imc_attestation)
150 {
151 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
152 return TNC_RESULT_NOT_INITIALIZED;
153 }
154
155 /* parse received PA-TNC message and automatically handle any errors */
156 result = imc_attestation->receive_message(imc_attestation, connection_id,
157 chunk_create(msg, msg_len), msg_type,
158 &pa_tnc_msg);
159
160 /* no parsed PA-TNC attributes available if an error occurred */
161 if (!pa_tnc_msg)
162 {
163 return result;
164 }
165
166 /* analyze PA-TNC attributes */
167 enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
168 while (enumerator->enumerate(enumerator, &attr))
169 {
170 if (attr->get_vendor_id(attr) == PEN_IETF &&
171 attr->get_type(attr) == IETF_ATTR_PA_TNC_ERROR)
172 {
173 ietf_attr_pa_tnc_error_t *error_attr;
174 pa_tnc_error_code_t error_code;
175 chunk_t msg_info, attr_info;
176 u_int32_t offset;
177
178 error_attr = (ietf_attr_pa_tnc_error_t*)attr;
179 error_code = error_attr->get_error_code(error_attr);
180 msg_info = error_attr->get_msg_info(error_attr);
181
182 DBG1(DBG_IMC, "received PA-TNC error '%N' concerning message %#B",
183 pa_tnc_error_code_names, error_code, &msg_info);
184 switch (error_code)
185 {
186 case PA_ERROR_INVALID_PARAMETER:
187 offset = error_attr->get_offset(error_attr);
188 DBG1(DBG_IMC, " occurred at offset of %u bytes", offset);
189 break;
190 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
191 attr_info = error_attr->get_attr_info(error_attr);
192 DBG1(DBG_IMC, " unsupported attribute %#B", &attr_info);
193 break;
194 default:
195 break;
196 }
197 fatal_error = TRUE;
198 }
199 else if (attr->get_vendor_id(attr) == PEN_TCG)
200 {
201 /**
202 * Handle TCG PTS attributes
203 */
204 switch(attr->get_type(attr))
205 {
206 case TCG_PTS_REQ_PROTO_CAPS:
207 break;
208 case TCG_PTS_DH_NONCE_PARAMS_REQ:
209 break;
210 case TCG_PTS_DH_NONCE_FINISH:
211 break;
212 case TCG_PTS_MEAS_ALGO:
213 break;
214 case TCG_PTS_GET_TPM_VERSION_INFO:
215 break;
216 case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
217 break;
218 case TCG_PTS_UPDATE_TEMPL_REF_MANI:
219 break;
220 case TCG_PTS_GET_AIK:
221 break;
222
223 /* PTS-based Attestation Evidence */
224 case TCG_PTS_REQ_FUNCT_COMP_EVID:
225 break;
226 case TCG_PTS_GEN_ATTEST_EVID:
227 break;
228 case TCG_PTS_REQ_FILE_META:
229 break;
230 case TCG_PTS_REQ_FILE_MEAS:
231 break;
232 case TCG_PTS_REQ_INTEG_MEAS_LOG:
233 break;
234
235 /* On Windows only*/
236 case TCG_PTS_REQ_REGISTRY_VALUE:
237 /* Received on IMV side only*/
238 case TCG_PTS_PROTO_CAPS:
239 case TCG_PTS_DH_NONCE_PARAMS_RESP:
240 case TCG_PTS_MEAS_ALGO_SELECTION:
241 case TCG_PTS_TPM_VERSION_INFO:
242 case TCG_PTS_TEMPL_REF_MANI_SET_META:
243 case TCG_PTS_AIK:
244 case TCG_PTS_SIMPLE_COMP_EVID:
245 case TCG_PTS_SIMPLE_EVID_FINAL:
246 case TCG_PTS_VERIFICATION_RESULT:
247 case TCG_PTS_INTEG_REPORT:
248 case TCG_PTS_UNIX_FILE_META:
249 case TCG_PTS_FILE_MEAS:
250 case TCG_PTS_INTEG_MEAS_LOG:
251 default:
252 DBG1(DBG_IMC, "received unsupported attribute '%N'",
253 tcg_attr_names, attr->get_type(attr));
254 break;
255 }
256
257
258 }
259 }
260 enumerator->destroy(enumerator);
261 pa_tnc_msg->destroy(pa_tnc_msg);
262
263 /* if no error occurred then always return the same response */
264 return fatal_error ? TNC_RESULT_FATAL : send_message(connection_id);
265 }
266
267 /**
268 * see section 3.7.5 of TCG TNC IF-IMC Specification 1.2
269 */
270 TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
271 TNC_ConnectionID connection_id)
272 {
273 if (!imc_attestation)
274 {
275 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
276 return TNC_RESULT_NOT_INITIALIZED;
277 }
278 return TNC_RESULT_SUCCESS;
279 }
280
281 /**
282 * see section 3.7.6 of TCG TNC IF-IMC Specification 1.2
283 */
284 TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
285 {
286 if (!imc_attestation)
287 {
288 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
289 return TNC_RESULT_NOT_INITIALIZED;
290 }
291 imc_attestation->destroy(imc_attestation);
292 imc_attestation = NULL;
293
294 return TNC_RESULT_SUCCESS;
295 }
296
297 /**
298 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.2
299 */
300 TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
301 TNC_TNCC_BindFunctionPointer bind_function)
302 {
303 if (!imc_attestation)
304 {
305 DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
306 return TNC_RESULT_NOT_INITIALIZED;
307 }
308 return imc_attestation->bind_functions(imc_attestation, bind_function);
309 }