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 <imc/imc_msg.h>
21 #include <pa_tnc/pa_tnc_msg.h>
22 #include <ietf/ietf_attr.h>
23 #include <ietf/ietf_attr_pa_tnc_error.h>
24 #include <ietf/ietf_attr_product_info.h>
25 #include <ietf/ietf_attr_string_version.h>
26 #include <ietf/ietf_attr_assess_result.h>
27 #include <os_info/os_info.h>
31 #include <pts/pts_error.h>
33 #include <tcg/tcg_pts_attr_proto_caps.h>
34 #include <tcg/tcg_pts_attr_meas_algo.h>
36 #include <tncif_pa_subtypes.h>
40 #include <utils/linked_list.h>
44 static const char imc_name
[] = "Attestation";
46 static pen_type_t msg_types
[] = {
47 { PEN_TCG
, PA_SUBTYPE_TCG_PTS
}
50 static imc_agent_t
*imc_attestation
;
53 * Supported PTS measurement algorithms
55 static pts_meas_algorithms_t supported_algorithms
= PTS_MEAS_ALGO_NONE
;
58 * Supported PTS Diffie Hellman Groups
60 static pts_dh_group_t supported_dh_groups
= PTS_DH_GROUP_NONE
;
63 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
65 TNC_Result
TNC_IMC_Initialize(TNC_IMCID imc_id
,
66 TNC_Version min_version
,
67 TNC_Version max_version
,
68 TNC_Version
*actual_version
)
72 DBG1(DBG_IMC
, "IMC \"%s\" has already been initialized", imc_name
);
73 return TNC_RESULT_ALREADY_INITIALIZED
;
75 if (!pts_meas_algo_probe(&supported_algorithms
) ||
76 !pts_dh_group_probe(&supported_dh_groups
))
78 return TNC_RESULT_FATAL
;
80 imc_attestation
= imc_agent_create(imc_name
, msg_types
, 1, imc_id
,
84 return TNC_RESULT_FATAL
;
89 if (min_version
> TNC_IFIMC_VERSION_1
|| max_version
< TNC_IFIMC_VERSION_1
)
91 DBG1(DBG_IMC
, "no common IF-IMC version");
92 return TNC_RESULT_NO_COMMON_VERSION
;
94 return TNC_RESULT_SUCCESS
;
98 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
100 TNC_Result
TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id
,
101 TNC_ConnectionID connection_id
,
102 TNC_ConnectionState new_state
)
106 if (!imc_attestation
)
108 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
109 return TNC_RESULT_NOT_INITIALIZED
;
113 case TNC_CONNECTION_STATE_CREATE
:
114 state
= imc_attestation_state_create(connection_id
);
115 return imc_attestation
->create_state(imc_attestation
, state
);
116 case TNC_CONNECTION_STATE_HANDSHAKE
:
117 if (imc_attestation
->change_state(imc_attestation
, connection_id
,
118 new_state
, &state
) != TNC_RESULT_SUCCESS
)
120 return TNC_RESULT_FATAL
;
122 state
->set_result(state
, imc_id
,
123 TNC_IMV_EVALUATION_RESULT_DONT_KNOW
);
124 return TNC_RESULT_SUCCESS
;
125 case TNC_CONNECTION_STATE_DELETE
:
126 return imc_attestation
->delete_state(imc_attestation
, connection_id
);
127 case TNC_CONNECTION_STATE_ACCESS_ISOLATED
:
128 case TNC_CONNECTION_STATE_ACCESS_NONE
:
130 return imc_attestation
->change_state(imc_attestation
, connection_id
,
137 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
139 TNC_Result
TNC_IMC_BeginHandshake(TNC_IMCID imc_id
,
140 TNC_ConnectionID connection_id
)
142 if (!imc_attestation
)
144 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
145 return TNC_RESULT_NOT_INITIALIZED
;
148 return TNC_RESULT_SUCCESS
;
151 static TNC_Result
receive_message(imc_state_t
*state
, imc_msg_t
*in_msg
)
154 imc_attestation_state_t
*attestation_state
;
155 enumerator_t
*enumerator
;
159 bool fatal_error
= FALSE
;
161 /* parse received PA-TNC message and handle local and remote errors */
162 result
= in_msg
->receive(in_msg
, &fatal_error
);
163 if (result
!= TNC_RESULT_SUCCESS
)
167 out_msg
= imc_msg_create_as_reply(in_msg
);
169 /* analyze PA-TNC attributes */
170 enumerator
= in_msg
->create_attribute_enumerator(in_msg
);
171 while (enumerator
->enumerate(enumerator
, &attr
))
173 type
= attr
->get_type(attr
);
175 if (type
.vendor_id
== PEN_IETF
)
177 if (type
.type
== IETF_ATTR_PA_TNC_ERROR
)
179 ietf_attr_pa_tnc_error_t
*error_attr
;
180 pen_type_t error_code
;
183 error_attr
= (ietf_attr_pa_tnc_error_t
*)attr
;
184 error_code
= error_attr
->get_error_code(error_attr
);
186 if (error_code
.vendor_id
== PEN_TCG
)
188 msg_info
= error_attr
->get_msg_info(error_attr
);
190 DBG1(DBG_IMC
, "received TCG-PTS error '%N'",
191 pts_error_code_names
, error_code
.type
);
192 DBG1(DBG_IMC
, "error information: %B", &msg_info
);
194 result
= TNC_RESULT_FATAL
;
198 else if (type
.vendor_id
== PEN_TCG
)
200 attestation_state
= (imc_attestation_state_t
*)state
;
202 if (!imc_attestation_process(attr
, out_msg
, attestation_state
,
203 supported_algorithms
, supported_dh_groups
))
205 result
= TNC_RESULT_FATAL
;
210 enumerator
->destroy(enumerator
);
212 if (result
== TNC_RESULT_SUCCESS
)
214 /* send PA-TNC message with the excl flag set */
215 result
= out_msg
->send(out_msg
, TRUE
);
217 out_msg
->destroy(out_msg
);
223 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
225 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
226 TNC_ConnectionID connection_id
,
227 TNC_BufferReference msg
,
229 TNC_MessageType msg_type
)
235 if (!imc_attestation
)
237 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
238 return TNC_RESULT_NOT_INITIALIZED
;
240 if (!imc_attestation
->get_state(imc_attestation
, connection_id
, &state
))
242 return TNC_RESULT_FATAL
;
245 in_msg
= imc_msg_create_from_data(imc_attestation
, state
, connection_id
,
246 msg_type
, chunk_create(msg
, msg_len
));
247 result
= receive_message(state
, in_msg
);
248 in_msg
->destroy(in_msg
);
254 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
256 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
257 TNC_ConnectionID connection_id
,
258 TNC_UInt32 msg_flags
,
259 TNC_BufferReference msg
,
261 TNC_VendorID msg_vid
,
262 TNC_MessageSubtype msg_subtype
,
263 TNC_UInt32 src_imv_id
,
264 TNC_UInt32 dst_imc_id
)
270 if (!imc_attestation
)
272 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
273 return TNC_RESULT_NOT_INITIALIZED
;
275 if (!imc_attestation
->get_state(imc_attestation
, connection_id
, &state
))
277 return TNC_RESULT_FATAL
;
279 in_msg
= imc_msg_create_from_long_data(imc_attestation
, state
, connection_id
,
280 src_imv_id
, dst_imc_id
, msg_vid
, msg_subtype
,
281 chunk_create(msg
, msg_len
));
282 result
=receive_message(state
, in_msg
);
283 in_msg
->destroy(in_msg
);
289 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
291 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
292 TNC_ConnectionID connection_id
)
294 if (!imc_attestation
)
296 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
297 return TNC_RESULT_NOT_INITIALIZED
;
299 return TNC_RESULT_SUCCESS
;
303 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
305 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
307 if (!imc_attestation
)
309 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
310 return TNC_RESULT_NOT_INITIALIZED
;
315 imc_attestation
->destroy(imc_attestation
);
316 imc_attestation
= NULL
;
318 return TNC_RESULT_SUCCESS
;
322 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
324 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
325 TNC_TNCC_BindFunctionPointer bind_function
)
327 if (!imc_attestation
)
329 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
330 return TNC_RESULT_NOT_INITIALIZED
;
332 return imc_attestation
->bind_functions(imc_attestation
, bind_function
);