2 * Copyright (C) 2011 Sansar Choinyambuu
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>
27 #include <pts/pts_error.h>
29 #include <tcg/tcg_pts_attr_proto_caps.h>
30 #include <tcg/tcg_pts_attr_meas_algo.h>
32 #include <tncif_pa_subtypes.h>
36 #include <utils/linked_list.h>
40 static const char imc_name
[] = "Attestation";
42 #define IMC_VENDOR_ID PEN_TCG
43 #define IMC_SUBTYPE PA_SUBTYPE_TCG_PTS
45 static imc_agent_t
*imc_attestation
;
48 * Supported PTS measurement algorithms
50 static pts_meas_algorithms_t supported_algorithms
= PTS_MEAS_ALGO_NONE
;
53 * Supported PTS Diffie Hellman Groups
55 static pts_dh_group_t supported_dh_groups
= PTS_DH_GROUP_NONE
;
58 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
60 TNC_Result
TNC_IMC_Initialize(TNC_IMCID imc_id
,
61 TNC_Version min_version
,
62 TNC_Version max_version
,
63 TNC_Version
*actual_version
)
67 DBG1(DBG_IMC
, "IMC \"%s\" has already been initialized", imc_name
);
68 return TNC_RESULT_ALREADY_INITIALIZED
;
70 if (!pts_meas_algo_probe(&supported_algorithms
) ||
71 !pts_dh_group_probe(&supported_dh_groups
))
73 return TNC_RESULT_FATAL
;
75 imc_attestation
= imc_agent_create(imc_name
, IMC_VENDOR_ID
, IMC_SUBTYPE
,
76 imc_id
, actual_version
);
79 return TNC_RESULT_FATAL
;
84 if (min_version
> TNC_IFIMC_VERSION_1
|| max_version
< TNC_IFIMC_VERSION_1
)
86 DBG1(DBG_IMC
, "no common IF-IMC version");
87 return TNC_RESULT_NO_COMMON_VERSION
;
89 return TNC_RESULT_SUCCESS
;
93 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
95 TNC_Result
TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id
,
96 TNC_ConnectionID connection_id
,
97 TNC_ConnectionState new_state
)
101 if (!imc_attestation
)
103 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
104 return TNC_RESULT_NOT_INITIALIZED
;
108 case TNC_CONNECTION_STATE_CREATE
:
109 state
= imc_attestation_state_create(connection_id
);
110 return imc_attestation
->create_state(imc_attestation
, state
);
111 case TNC_CONNECTION_STATE_DELETE
:
112 return imc_attestation
->delete_state(imc_attestation
, connection_id
);
113 case TNC_CONNECTION_STATE_HANDSHAKE
:
114 case TNC_CONNECTION_STATE_ACCESS_ISOLATED
:
115 case TNC_CONNECTION_STATE_ACCESS_NONE
:
117 return imc_attestation
->change_state(imc_attestation
, connection_id
,
124 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
126 TNC_Result
TNC_IMC_BeginHandshake(TNC_IMCID imc_id
,
127 TNC_ConnectionID connection_id
)
130 imc_attestation_state_t
*attestation_state
;
133 TNC_Result result
= TNC_RESULT_SUCCESS
;
135 if (!imc_attestation
)
137 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
138 return TNC_RESULT_NOT_INITIALIZED
;
141 /* get current IMC state */
142 if (!imc_attestation
->get_state(imc_attestation
, connection_id
, &state
))
144 return TNC_RESULT_FATAL
;
146 attestation_state
= (imc_attestation_state_t
*)state
;
147 pts
= attestation_state
->get_pts(attestation_state
);
149 platform_info
= pts
->get_platform_info(pts
);
152 pa_tnc_msg_t
*pa_tnc_msg
;
155 pa_tnc_msg
= pa_tnc_msg_create();
156 attr
= ietf_attr_product_info_create(0, 0, platform_info
);
157 pa_tnc_msg
->add_attribute(pa_tnc_msg
, attr
);
158 pa_tnc_msg
->build(pa_tnc_msg
);
159 result
= imc_attestation
->send_message(imc_attestation
, connection_id
,
160 FALSE
, 0, TNC_IMVID_ANY
,
161 pa_tnc_msg
->get_encoding(pa_tnc_msg
));
162 pa_tnc_msg
->destroy(pa_tnc_msg
);
168 static TNC_Result
receive_message(TNC_IMCID imc_id
,
169 TNC_ConnectionID connection_id
,
170 TNC_UInt32 msg_flags
,
172 TNC_VendorID msg_vid
,
173 TNC_MessageSubtype msg_subtype
,
174 TNC_UInt32 src_imv_id
,
175 TNC_UInt32 dst_imc_id
)
177 pa_tnc_msg_t
*pa_tnc_msg
;
179 linked_list_t
*attr_list
;
181 imc_attestation_state_t
*attestation_state
;
182 enumerator_t
*enumerator
;
185 if (!imc_attestation
)
187 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
188 return TNC_RESULT_NOT_INITIALIZED
;
191 /* get current IMC state */
192 if (!imc_attestation
->get_state(imc_attestation
, connection_id
, &state
))
194 return TNC_RESULT_FATAL
;
196 attestation_state
= (imc_attestation_state_t
*)state
;
198 /* parse received PA-TNC message and automatically handle any errors */
199 result
= imc_attestation
->receive_message(imc_attestation
, state
, msg
,
200 msg_vid
, msg_subtype
, src_imv_id
, dst_imc_id
, &pa_tnc_msg
);
202 /* no parsed PA-TNC attributes available if an error occurred */
208 /* preprocess any IETF standard error attributes */
209 result
= pa_tnc_msg
->process_ietf_std_errors(pa_tnc_msg
) ?
210 TNC_RESULT_FATAL
: TNC_RESULT_SUCCESS
;
212 attr_list
= linked_list_create();
214 /* analyze PA-TNC attributes */
215 enumerator
= pa_tnc_msg
->create_attribute_enumerator(pa_tnc_msg
);
216 while (enumerator
->enumerate(enumerator
, &attr
))
218 if (attr
->get_vendor_id(attr
) == PEN_IETF
&&
219 attr
->get_type(attr
) == IETF_ATTR_PA_TNC_ERROR
)
221 ietf_attr_pa_tnc_error_t
*error_attr
;
222 pen_t error_vendor_id
;
223 pa_tnc_error_code_t error_code
;
226 error_attr
= (ietf_attr_pa_tnc_error_t
*)attr
;
227 error_vendor_id
= error_attr
->get_vendor_id(error_attr
);
229 if (error_vendor_id
== PEN_TCG
)
231 error_code
= error_attr
->get_error_code(error_attr
);
232 msg_info
= error_attr
->get_msg_info(error_attr
);
234 DBG1(DBG_IMC
, "received TCG-PTS error '%N'",
235 pts_error_code_names
, error_code
);
236 DBG1(DBG_IMC
, "error information: %B", &msg_info
);
238 result
= TNC_RESULT_FATAL
;
241 else if (attr
->get_vendor_id(attr
) == PEN_TCG
)
243 if (!imc_attestation_process(attr
, attr_list
, attestation_state
,
244 supported_algorithms
, supported_dh_groups
))
246 result
= TNC_RESULT_FATAL
;
251 enumerator
->destroy(enumerator
);
252 pa_tnc_msg
->destroy(pa_tnc_msg
);
254 if (result
== TNC_RESULT_SUCCESS
&& attr_list
->get_count(attr_list
))
256 pa_tnc_msg
= pa_tnc_msg_create();
258 enumerator
= attr_list
->create_enumerator(attr_list
);
259 while (enumerator
->enumerate(enumerator
, &attr
))
261 pa_tnc_msg
->add_attribute(pa_tnc_msg
, attr
);
263 enumerator
->destroy(enumerator
);
265 pa_tnc_msg
->build(pa_tnc_msg
);
266 result
= imc_attestation
->send_message(imc_attestation
, connection_id
,
267 FALSE
, 0, TNC_IMVID_ANY
,
268 pa_tnc_msg
->get_encoding(pa_tnc_msg
));
269 pa_tnc_msg
->destroy(pa_tnc_msg
);
272 attr_list
->destroy(attr_list
);
277 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
279 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
280 TNC_ConnectionID connection_id
,
281 TNC_BufferReference msg
,
283 TNC_MessageType msg_type
)
285 TNC_VendorID msg_vid
;
286 TNC_MessageSubtype msg_subtype
;
288 msg_vid
= msg_type
>> 8;
289 msg_subtype
= msg_type
& TNC_SUBTYPE_ANY
;
291 return receive_message(imc_id
, connection_id
, 0, chunk_create(msg
, msg_len
),
292 msg_vid
, msg_subtype
, 0, TNC_IMCID_ANY
);
296 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
298 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
299 TNC_ConnectionID connection_id
,
300 TNC_UInt32 msg_flags
,
301 TNC_BufferReference msg
,
303 TNC_VendorID msg_vid
,
304 TNC_MessageSubtype msg_subtype
,
305 TNC_UInt32 src_imv_id
,
306 TNC_UInt32 dst_imc_id
)
308 return receive_message(imc_id
, connection_id
, msg_flags
,
309 chunk_create(msg
, msg_len
), msg_vid
, msg_subtype
,
310 src_imv_id
, dst_imc_id
);
314 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
316 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
317 TNC_ConnectionID connection_id
)
319 if (!imc_attestation
)
321 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
322 return TNC_RESULT_NOT_INITIALIZED
;
324 return TNC_RESULT_SUCCESS
;
328 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
330 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
332 if (!imc_attestation
)
334 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
335 return TNC_RESULT_NOT_INITIALIZED
;
340 imc_attestation
->destroy(imc_attestation
);
341 imc_attestation
= NULL
;
343 return TNC_RESULT_SUCCESS
;
347 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
349 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
350 TNC_TNCC_BindFunctionPointer bind_function
)
352 if (!imc_attestation
)
354 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
355 return TNC_RESULT_NOT_INITIALIZED
;
357 return imc_attestation
->bind_functions(imc_attestation
, bind_function
);