2 * Copyright (C) 2013 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_swid_state.h"
19 #include "swid/swid_tag.h"
20 #include "swid/swid_tag_id.h"
21 #include "tcg/swid/tcg_swid_attr_req.h"
22 #include "tcg/swid/tcg_swid_attr_tag_inv.h"
23 #include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
25 #include <imc/imc_agent.h>
26 #include <imc/imc_msg.h>
28 #include <tncif_pa_subtypes.h>
31 #include <utils/debug.h>
33 static char strongswan_tag
[] =
34 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
35 "<software_identification_tag "
36 "xmlns=\"http://standards.iso.org/iso/19770/-2/2009/schema.xsd\">\n"
37 "<entitlement_required_indicator>true</entitlement_required_indicator>\n"
38 "<product_title>strongSwan</product_title>\n"
40 " <name>5.1.1dr1</name>\n"
45 " <review></review>\n"
47 "</product_version>\n"
48 "<software_creator>\n"
49 " <name>strongSwan Project</name>\n"
50 " <regid>regid.2004-03.org.strongswan</regid>\n"
51 "</software_creator>\n"
52 "<software_licensor>\n"
53 " <name>strongSwan Project</name>\n"
54 " <regid>regid.2004-03.org.strongswan</regid>\n"
55 "</software_licensor>\n"
57 " <unique_id>strongSwan-5-1-0</unique_id>\n"
58 " <tag_creator_regid>regid.2004-03.org.strongswan</tag_creator_regid>\n"
61 " <name>strongSwan</name>\n"
62 " <regid>regid.2004-03.org.strongswan</regid>\n"
64 "</software_identification_tag>\n";
68 static const char imc_name
[] = "SWID";
70 static pen_type_t msg_types
[] = {
71 { PEN_TCG
, PA_SUBTYPE_TCG_SWID
}
74 static imc_agent_t
*imc_swid
;
77 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
79 TNC_Result
TNC_IMC_Initialize(TNC_IMCID imc_id
,
80 TNC_Version min_version
,
81 TNC_Version max_version
,
82 TNC_Version
*actual_version
)
86 DBG1(DBG_IMC
, "IMC \"%s\" has already been initialized", imc_name
);
87 return TNC_RESULT_ALREADY_INITIALIZED
;
89 imc_swid
= imc_agent_create(imc_name
, msg_types
, countof(msg_types
),
90 imc_id
, actual_version
);
93 return TNC_RESULT_FATAL
;
98 if (min_version
> TNC_IFIMC_VERSION_1
|| max_version
< TNC_IFIMC_VERSION_1
)
100 DBG1(DBG_IMC
, "no common IF-IMC version");
101 return TNC_RESULT_NO_COMMON_VERSION
;
103 return TNC_RESULT_SUCCESS
;
107 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
109 TNC_Result
TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id
,
110 TNC_ConnectionID connection_id
,
111 TNC_ConnectionState new_state
)
117 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
118 return TNC_RESULT_NOT_INITIALIZED
;
122 case TNC_CONNECTION_STATE_CREATE
:
123 state
= imc_swid_state_create(connection_id
);
124 return imc_swid
->create_state(imc_swid
, state
);
125 case TNC_CONNECTION_STATE_HANDSHAKE
:
126 if (imc_swid
->change_state(imc_swid
, connection_id
, new_state
,
127 &state
) != TNC_RESULT_SUCCESS
)
129 return TNC_RESULT_FATAL
;
131 state
->set_result(state
, imc_id
,
132 TNC_IMV_EVALUATION_RESULT_DONT_KNOW
);
133 return TNC_RESULT_SUCCESS
;
134 case TNC_CONNECTION_STATE_DELETE
:
135 return imc_swid
->delete_state(imc_swid
, connection_id
);
137 return imc_swid
->change_state(imc_swid
, connection_id
,
143 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
145 TNC_Result
TNC_IMC_BeginHandshake(TNC_IMCID imc_id
,
146 TNC_ConnectionID connection_id
)
152 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
153 return TNC_RESULT_NOT_INITIALIZED
;
155 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
157 return TNC_RESULT_FATAL
;
160 return TNC_RESULT_SUCCESS
;
163 static TNC_Result
receive_message(imc_state_t
*state
, imc_msg_t
*in_msg
)
166 imc_swid_state_t
*swid_state
;
167 enumerator_t
*enumerator
;
171 bool fatal_error
= FALSE
;
173 /* parse received PA-TNC message and handle local and remote errors */
174 result
= in_msg
->receive(in_msg
, &fatal_error
);
175 if (result
!= TNC_RESULT_SUCCESS
)
179 out_msg
= imc_msg_create_as_reply(in_msg
);
180 swid_state
= (imc_swid_state_t
*)state
;
182 /* analyze PA-TNC attributes */
183 enumerator
= in_msg
->create_attribute_enumerator(in_msg
);
184 while (enumerator
->enumerate(enumerator
, &attr
))
186 tcg_swid_attr_req_t
*attr_req
;
188 u_int32_t request_id
, eid_epoch
;
190 type
= attr
->get_type(attr
);
192 if (type
.vendor_id
!= PEN_TCG
|| type
.type
!= TCG_SWID_REQUEST
)
197 attr_req
= (tcg_swid_attr_req_t
*)attr
;
198 flags
= attr_req
->get_flags(attr_req
);
199 request_id
= attr_req
->get_request_id(attr_req
);
200 eid_epoch
= swid_state
->get_eid_epoch(swid_state
);
202 if (flags
& TCG_SWID_ATTR_REQ_FLAG_R
)
204 swid_tag_id_t
*tag_id
;
205 tcg_swid_attr_tag_id_inv_t
*attr_cast
;
207 attr
= tcg_swid_attr_tag_id_inv_create(request_id
, eid_epoch
, 1);
208 attr_cast
= (tcg_swid_attr_tag_id_inv_t
*)attr
;
209 tag_id
= swid_tag_id_create(
210 chunk_from_str("regid.2004-03.org.strongswan"),
211 chunk_from_str("strongSwan-5-1-0"),
213 attr_cast
->add_tag_id(attr_cast
, tag_id
);
218 tcg_swid_attr_tag_inv_t
*attr_cast
;
220 attr
= tcg_swid_attr_tag_inv_create(request_id
, eid_epoch
, 1);
221 attr_cast
= (tcg_swid_attr_tag_inv_t
*)attr
;
222 tag
= swid_tag_create(chunk_from_str(strongswan_tag
), chunk_empty
);
223 attr_cast
->add_tag(attr_cast
, tag
);
225 out_msg
->add_attribute(out_msg
, attr
);
227 enumerator
->destroy(enumerator
);
231 result
= TNC_RESULT_FATAL
;
235 result
= out_msg
->send(out_msg
, TRUE
);
237 out_msg
->destroy(out_msg
);
243 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
246 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
247 TNC_ConnectionID connection_id
,
248 TNC_BufferReference msg
,
250 TNC_MessageType msg_type
)
258 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
259 return TNC_RESULT_NOT_INITIALIZED
;
261 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
263 return TNC_RESULT_FATAL
;
265 in_msg
= imc_msg_create_from_data(imc_swid
, state
, connection_id
, msg_type
,
266 chunk_create(msg
, msg_len
));
267 result
= receive_message(state
, in_msg
);
268 in_msg
->destroy(in_msg
);
274 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
276 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
277 TNC_ConnectionID connection_id
,
278 TNC_UInt32 msg_flags
,
279 TNC_BufferReference msg
,
281 TNC_VendorID msg_vid
,
282 TNC_MessageSubtype msg_subtype
,
283 TNC_UInt32 src_imv_id
,
284 TNC_UInt32 dst_imc_id
)
292 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
293 return TNC_RESULT_NOT_INITIALIZED
;
295 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
297 return TNC_RESULT_FATAL
;
299 in_msg
= imc_msg_create_from_long_data(imc_swid
, state
, connection_id
,
300 src_imv_id
, dst_imc_id
,msg_vid
, msg_subtype
,
301 chunk_create(msg
, msg_len
));
302 result
=receive_message(state
, in_msg
);
303 in_msg
->destroy(in_msg
);
309 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
311 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
312 TNC_ConnectionID connection_id
)
316 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
317 return TNC_RESULT_NOT_INITIALIZED
;
319 return TNC_RESULT_SUCCESS
;
323 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
325 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
329 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
330 return TNC_RESULT_NOT_INITIALIZED
;
335 imc_swid
->destroy(imc_swid
);
338 return TNC_RESULT_SUCCESS
;
342 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
344 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
345 TNC_TNCC_BindFunctionPointer bind_function
)
349 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
350 return TNC_RESULT_NOT_INITIALIZED
;
352 return imc_swid
->bind_functions(imc_swid
, bind_function
);