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