2 * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "imc_attestation_state.h"
17 #include "imc_attestation_process.h"
19 #include <imc/imc_agent.h>
20 #include <pa_tnc/pa_tnc_msg.h>
21 #include <ietf/ietf_attr.h>
22 #include <ietf/ietf_attr_pa_tnc_error.h>
23 #include <ietf/ietf_attr_product_info.h>
24 #include <ietf/ietf_attr_string_version.h>
25 #include <ietf/ietf_attr_assess_result.h>
26 #include <os_info/os_info.h>
30 #include <pts/pts_error.h>
32 #include <tcg/tcg_pts_attr_proto_caps.h>
33 #include <tcg/tcg_pts_attr_meas_algo.h>
35 #include <tncif_pa_subtypes.h>
39 #include <utils/linked_list.h>
43 static const char imc_name
[] = "Attestation";
45 static pen_type_t msg_types
[] = {
46 { PEN_TCG
, PA_SUBTYPE_TCG_PTS
}
49 static imc_agent_t
*imc_attestation
;
52 * Supported PTS measurement algorithms
54 static pts_meas_algorithms_t supported_algorithms
= PTS_MEAS_ALGO_NONE
;
57 * Supported PTS Diffie Hellman Groups
59 static pts_dh_group_t supported_dh_groups
= PTS_DH_GROUP_NONE
;
62 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
64 TNC_Result
TNC_IMC_Initialize(TNC_IMCID imc_id
,
65 TNC_Version min_version
,
66 TNC_Version max_version
,
67 TNC_Version
*actual_version
)
71 DBG1(DBG_IMC
, "IMC \"%s\" has already been initialized", imc_name
);
72 return TNC_RESULT_ALREADY_INITIALIZED
;
74 if (!pts_meas_algo_probe(&supported_algorithms
) ||
75 !pts_dh_group_probe(&supported_dh_groups
))
77 return TNC_RESULT_FATAL
;
79 imc_attestation
= imc_agent_create(imc_name
, msg_types
, 1, imc_id
,
83 return TNC_RESULT_FATAL
;
88 if (min_version
> TNC_IFIMC_VERSION_1
|| max_version
< TNC_IFIMC_VERSION_1
)
90 DBG1(DBG_IMC
, "no common IF-IMC version");
91 return TNC_RESULT_NO_COMMON_VERSION
;
93 return TNC_RESULT_SUCCESS
;
97 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
99 TNC_Result
TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id
,
100 TNC_ConnectionID connection_id
,
101 TNC_ConnectionState new_state
)
105 if (!imc_attestation
)
107 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
108 return TNC_RESULT_NOT_INITIALIZED
;
112 case TNC_CONNECTION_STATE_CREATE
:
113 state
= imc_attestation_state_create(connection_id
);
114 return imc_attestation
->create_state(imc_attestation
, state
);
115 case TNC_CONNECTION_STATE_HANDSHAKE
:
116 if (imc_attestation
->change_state(imc_attestation
, connection_id
,
117 new_state
, &state
) != TNC_RESULT_SUCCESS
)
119 return TNC_RESULT_FATAL
;
121 state
->set_result(state
, imc_id
,
122 TNC_IMV_EVALUATION_RESULT_DONT_KNOW
);
123 return TNC_RESULT_SUCCESS
;
124 case TNC_CONNECTION_STATE_DELETE
:
125 return imc_attestation
->delete_state(imc_attestation
, connection_id
);
126 case TNC_CONNECTION_STATE_ACCESS_ISOLATED
:
127 case TNC_CONNECTION_STATE_ACCESS_NONE
:
129 return imc_attestation
->change_state(imc_attestation
, connection_id
,
136 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
138 TNC_Result
TNC_IMC_BeginHandshake(TNC_IMCID imc_id
,
139 TNC_ConnectionID connection_id
)
141 if (!imc_attestation
)
143 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
144 return TNC_RESULT_NOT_INITIALIZED
;
147 return TNC_RESULT_SUCCESS
;
150 static TNC_Result
receive_message(TNC_IMCID imc_id
,
151 TNC_ConnectionID connection_id
,
152 TNC_UInt32 msg_flags
,
154 TNC_VendorID msg_vid
,
155 TNC_MessageSubtype msg_subtype
,
156 TNC_UInt32 src_imv_id
,
157 TNC_UInt32 dst_imc_id
)
159 pa_tnc_msg_t
*pa_tnc_msg
;
162 linked_list_t
*attr_list
;
164 imc_attestation_state_t
*attestation_state
;
165 enumerator_t
*enumerator
;
167 TNC_UInt32 target_imc_id
;
169 if (!imc_attestation
)
171 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
172 return TNC_RESULT_NOT_INITIALIZED
;
175 /* get current IMC state */
176 if (!imc_attestation
->get_state(imc_attestation
, connection_id
, &state
))
178 return TNC_RESULT_FATAL
;
180 attestation_state
= (imc_attestation_state_t
*)state
;
182 /* parse received PA-TNC message and automatically handle any errors */
183 result
= imc_attestation
->receive_message(imc_attestation
, state
, msg
,
184 msg_vid
, msg_subtype
, src_imv_id
, dst_imc_id
, &pa_tnc_msg
);
186 /* no parsed PA-TNC attributes available if an error occurred */
191 target_imc_id
= (dst_imc_id
== TNC_IMCID_ANY
) ? imc_id
: dst_imc_id
;
193 /* preprocess any IETF standard error attributes */
194 result
= pa_tnc_msg
->process_ietf_std_errors(pa_tnc_msg
) ?
195 TNC_RESULT_FATAL
: TNC_RESULT_SUCCESS
;
197 attr_list
= linked_list_create();
199 /* analyze PA-TNC attributes */
200 enumerator
= pa_tnc_msg
->create_attribute_enumerator(pa_tnc_msg
);
201 while (enumerator
->enumerate(enumerator
, &attr
))
203 type
= attr
->get_type(attr
);
205 if (type
.vendor_id
== PEN_IETF
)
207 if (type
.type
== IETF_ATTR_PA_TNC_ERROR
)
209 ietf_attr_pa_tnc_error_t
*error_attr
;
210 pen_type_t error_code
;
213 error_attr
= (ietf_attr_pa_tnc_error_t
*)attr
;
214 error_code
= error_attr
->get_error_code(error_attr
);
216 if (error_code
.vendor_id
== PEN_TCG
)
218 msg_info
= error_attr
->get_msg_info(error_attr
);
220 DBG1(DBG_IMC
, "received TCG-PTS error '%N'",
221 pts_error_code_names
, error_code
.type
);
222 DBG1(DBG_IMC
, "error information: %B", &msg_info
);
224 result
= TNC_RESULT_FATAL
;
227 else if (type
.type
== IETF_ATTR_ASSESSMENT_RESULT
)
229 ietf_attr_assess_result_t
*ietf_attr
;
231 ietf_attr
= (ietf_attr_assess_result_t
*)attr
;
232 state
->set_result(state
, target_imc_id
,
233 ietf_attr
->get_result(ietf_attr
));
236 else if (type
.vendor_id
== PEN_TCG
)
238 if (!imc_attestation_process(attr
, attr_list
, attestation_state
,
239 supported_algorithms
, supported_dh_groups
))
241 result
= TNC_RESULT_FATAL
;
246 enumerator
->destroy(enumerator
);
247 pa_tnc_msg
->destroy(pa_tnc_msg
);
249 if (result
== TNC_RESULT_SUCCESS
&& attr_list
->get_count(attr_list
))
251 result
= imc_attestation
->send_message(imc_attestation
, connection_id
,
252 FALSE
, 0, TNC_IMVID_ANY
, PEN_TCG
, PA_SUBTYPE_TCG_PTS
,
255 attr_list
->destroy(attr_list
);
261 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
263 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
264 TNC_ConnectionID connection_id
,
265 TNC_BufferReference msg
,
267 TNC_MessageType msg_type
)
269 TNC_VendorID msg_vid
;
270 TNC_MessageSubtype msg_subtype
;
272 msg_vid
= msg_type
>> 8;
273 msg_subtype
= msg_type
& TNC_SUBTYPE_ANY
;
275 return receive_message(imc_id
, connection_id
, 0, chunk_create(msg
, msg_len
),
276 msg_vid
, msg_subtype
, 0, TNC_IMCID_ANY
);
280 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
282 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
283 TNC_ConnectionID connection_id
,
284 TNC_UInt32 msg_flags
,
285 TNC_BufferReference msg
,
287 TNC_VendorID msg_vid
,
288 TNC_MessageSubtype msg_subtype
,
289 TNC_UInt32 src_imv_id
,
290 TNC_UInt32 dst_imc_id
)
292 return receive_message(imc_id
, connection_id
, msg_flags
,
293 chunk_create(msg
, msg_len
), msg_vid
, msg_subtype
,
294 src_imv_id
, dst_imc_id
);
298 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
300 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
301 TNC_ConnectionID connection_id
)
303 if (!imc_attestation
)
305 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
306 return TNC_RESULT_NOT_INITIALIZED
;
308 return TNC_RESULT_SUCCESS
;
312 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
314 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
316 if (!imc_attestation
)
318 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
319 return TNC_RESULT_NOT_INITIALIZED
;
324 imc_attestation
->destroy(imc_attestation
);
325 imc_attestation
= NULL
;
327 return TNC_RESULT_SUCCESS
;
331 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
333 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
334 TNC_TNCC_BindFunctionPointer bind_function
)
336 if (!imc_attestation
)
338 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
339 return TNC_RESULT_NOT_INITIALIZED
;
341 return imc_attestation
->bind_functions(imc_attestation
, bind_function
);