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_inventory.h"
20 #include "swid/swid_error.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>
36 static const char imc_name
[] = "SWID";
38 static pen_type_t msg_types
[] = {
39 { PEN_TCG
, PA_SUBTYPE_TCG_SWID
}
42 static imc_agent_t
*imc_swid
;
45 * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
47 TNC_Result
TNC_IMC_Initialize(TNC_IMCID imc_id
,
48 TNC_Version min_version
,
49 TNC_Version max_version
,
50 TNC_Version
*actual_version
)
54 DBG1(DBG_IMC
, "IMC \"%s\" has already been initialized", imc_name
);
55 return TNC_RESULT_ALREADY_INITIALIZED
;
57 imc_swid
= imc_agent_create(imc_name
, msg_types
, countof(msg_types
),
58 imc_id
, actual_version
);
61 return TNC_RESULT_FATAL
;
66 if (min_version
> TNC_IFIMC_VERSION_1
|| max_version
< TNC_IFIMC_VERSION_1
)
68 DBG1(DBG_IMC
, "no common IF-IMC version");
69 return TNC_RESULT_NO_COMMON_VERSION
;
71 return TNC_RESULT_SUCCESS
;
75 * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
77 TNC_Result
TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id
,
78 TNC_ConnectionID connection_id
,
79 TNC_ConnectionState new_state
)
85 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
86 return TNC_RESULT_NOT_INITIALIZED
;
90 case TNC_CONNECTION_STATE_CREATE
:
91 state
= imc_swid_state_create(connection_id
);
92 return imc_swid
->create_state(imc_swid
, state
);
93 case TNC_CONNECTION_STATE_HANDSHAKE
:
94 if (imc_swid
->change_state(imc_swid
, connection_id
, new_state
,
95 &state
) != TNC_RESULT_SUCCESS
)
97 return TNC_RESULT_FATAL
;
99 state
->set_result(state
, imc_id
,
100 TNC_IMV_EVALUATION_RESULT_DONT_KNOW
);
101 return TNC_RESULT_SUCCESS
;
102 case TNC_CONNECTION_STATE_DELETE
:
103 return imc_swid
->delete_state(imc_swid
, connection_id
);
105 return imc_swid
->change_state(imc_swid
, connection_id
,
111 * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
113 TNC_Result
TNC_IMC_BeginHandshake(TNC_IMCID imc_id
,
114 TNC_ConnectionID connection_id
)
120 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
121 return TNC_RESULT_NOT_INITIALIZED
;
123 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
125 return TNC_RESULT_FATAL
;
128 return TNC_RESULT_SUCCESS
;
131 static TNC_Result
receive_message(imc_state_t
*state
, imc_msg_t
*in_msg
)
134 imc_swid_state_t
*swid_state
;
135 enumerator_t
*enumerator
;
139 bool fatal_error
= FALSE
;
141 /* parse received PA-TNC message and handle local and remote errors */
142 result
= in_msg
->receive(in_msg
, &fatal_error
);
143 if (result
!= TNC_RESULT_SUCCESS
)
147 out_msg
= imc_msg_create_as_reply(in_msg
);
148 swid_state
= (imc_swid_state_t
*)state
;
150 /* analyze PA-TNC attributes */
151 enumerator
= in_msg
->create_attribute_enumerator(in_msg
);
152 while (enumerator
->enumerate(enumerator
, &attr
))
154 tcg_swid_attr_req_t
*attr_req
;
156 u_int32_t request_id
, eid_epoch
;
157 swid_inventory_t
*swid_inventory
;
160 type
= attr
->get_type(attr
);
162 if (type
.vendor_id
!= PEN_TCG
|| type
.type
!= TCG_SWID_REQUEST
)
167 attr_req
= (tcg_swid_attr_req_t
*)attr
;
168 flags
= attr_req
->get_flags(attr_req
);
169 request_id
= attr_req
->get_request_id(attr_req
);
170 eid_epoch
= swid_state
->get_eid_epoch(swid_state
);
172 if (flags
& (TCG_SWID_ATTR_REQ_FLAG_S
| TCG_SWID_ATTR_REQ_FLAG_C
))
174 attr
= swid_error_create(TCG_SWID_SUBSCRIPTION_DENIED
, request_id
,
175 0, "no subscription available yet");
176 out_msg
->add_attribute(out_msg
, attr
);
179 full_tags
= (flags
& TCG_SWID_ATTR_REQ_FLAG_R
) == 0;
181 swid_inventory
= swid_inventory_create(full_tags
);
182 if (!swid_inventory
->collect(swid_inventory
))
184 swid_inventory
->destroy(swid_inventory
);
185 attr
= swid_error_create(TCG_SWID_ERROR
, request_id
,
186 0, "error in SWID tag collection");
187 out_msg
->add_attribute(out_msg
, attr
);
193 attr
= tcg_swid_attr_tag_inv_create(request_id
, eid_epoch
, 1,
198 attr
= tcg_swid_attr_tag_id_inv_create(request_id
, eid_epoch
, 1,
201 out_msg
->add_attribute(out_msg
, attr
);
203 enumerator
->destroy(enumerator
);
207 result
= TNC_RESULT_FATAL
;
211 result
= out_msg
->send(out_msg
, TRUE
);
213 out_msg
->destroy(out_msg
);
219 * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
222 TNC_Result
TNC_IMC_ReceiveMessage(TNC_IMCID imc_id
,
223 TNC_ConnectionID connection_id
,
224 TNC_BufferReference msg
,
226 TNC_MessageType msg_type
)
234 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
235 return TNC_RESULT_NOT_INITIALIZED
;
237 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
239 return TNC_RESULT_FATAL
;
241 in_msg
= imc_msg_create_from_data(imc_swid
, state
, connection_id
, msg_type
,
242 chunk_create(msg
, msg_len
));
243 result
= receive_message(state
, in_msg
);
244 in_msg
->destroy(in_msg
);
250 * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
252 TNC_Result
TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id
,
253 TNC_ConnectionID connection_id
,
254 TNC_UInt32 msg_flags
,
255 TNC_BufferReference msg
,
257 TNC_VendorID msg_vid
,
258 TNC_MessageSubtype msg_subtype
,
259 TNC_UInt32 src_imv_id
,
260 TNC_UInt32 dst_imc_id
)
268 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
269 return TNC_RESULT_NOT_INITIALIZED
;
271 if (!imc_swid
->get_state(imc_swid
, connection_id
, &state
))
273 return TNC_RESULT_FATAL
;
275 in_msg
= imc_msg_create_from_long_data(imc_swid
, state
, connection_id
,
276 src_imv_id
, dst_imc_id
,msg_vid
, msg_subtype
,
277 chunk_create(msg
, msg_len
));
278 result
=receive_message(state
, in_msg
);
279 in_msg
->destroy(in_msg
);
285 * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
287 TNC_Result
TNC_IMC_BatchEnding(TNC_IMCID imc_id
,
288 TNC_ConnectionID connection_id
)
292 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
293 return TNC_RESULT_NOT_INITIALIZED
;
295 return TNC_RESULT_SUCCESS
;
299 * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
301 TNC_Result
TNC_IMC_Terminate(TNC_IMCID imc_id
)
305 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
306 return TNC_RESULT_NOT_INITIALIZED
;
311 imc_swid
->destroy(imc_swid
);
314 return TNC_RESULT_SUCCESS
;
318 * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
320 TNC_Result
TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id
,
321 TNC_TNCC_BindFunctionPointer bind_function
)
325 DBG1(DBG_IMC
, "IMC \"%s\" has not been initialized", imc_name
);
326 return TNC_RESULT_NOT_INITIALIZED
;
328 return imc_swid
->bind_functions(imc_swid
, bind_function
);