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 "imv_attestation_state.h"
18 #include <imv/imv_agent.h>
19 #include <pa_tnc/pa_tnc_msg.h>
20 #include <ietf/ietf_attr.h>
21 #include <ietf/ietf_attr_pa_tnc_error.h>
22 #include <tcg/tcg_attr.h>
24 #include <tncif_pa_subtypes.h>
31 static const char imv_name
[] = "Attestation";
33 #define IMV_VENDOR_ID PEN_TCG
34 #define IMV_SUBTYPE PA_SUBTYPE_TCG_PTS
36 static imv_agent_t
*imv_attestation
;
39 * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
41 TNC_Result
TNC_IMV_Initialize(TNC_IMVID imv_id
,
42 TNC_Version min_version
,
43 TNC_Version max_version
,
44 TNC_Version
*actual_version
)
48 DBG1(DBG_IMV
, "IMV \"%s\" has already been initialized", imv_name
);
49 return TNC_RESULT_ALREADY_INITIALIZED
;
51 imv_attestation
= imv_agent_create(imv_name
, IMV_VENDOR_ID
, IMV_SUBTYPE
,
52 imv_id
, actual_version
);
55 return TNC_RESULT_FATAL
;
57 if (min_version
> TNC_IFIMV_VERSION_1
|| max_version
< TNC_IFIMV_VERSION_1
)
59 DBG1(DBG_IMV
, "no common IF-IMV version");
60 return TNC_RESULT_NO_COMMON_VERSION
;
62 return TNC_RESULT_SUCCESS
;
66 * see section 3.7.2 of TCG TNC IF-IMV Specification 1.2
68 TNC_Result
TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id
,
69 TNC_ConnectionID connection_id
,
70 TNC_ConnectionState new_state
)
73 imv_attestation_state_t
*attestation_state
;
77 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
78 return TNC_RESULT_NOT_INITIALIZED
;
82 case TNC_CONNECTION_STATE_CREATE
:
83 state
= imv_attestation_state_create(connection_id
);
84 return imv_attestation
->create_state(imv_attestation
, state
);
85 case TNC_CONNECTION_STATE_DELETE
:
86 return imv_attestation
->delete_state(imv_attestation
, connection_id
);
87 case TNC_CONNECTION_STATE_HANDSHAKE
:
88 if (!imv_attestation
->get_state(imv_attestation
, connection_id
, &state
))
90 return TNC_RESULT_FATAL
;
92 state
->change_state(state
, new_state
);
93 attestation_state
= (imv_attestation_state_t
*)state
;
95 * do any attestation specific configuration here
97 return TNC_RESULT_SUCCESS
;
99 return imv_attestation
->change_state(imv_attestation
, connection_id
,
104 static TNC_Result
send_message(TNC_ConnectionID connection_id
)
110 msg
= pa_tnc_msg_create();
112 * add TCG PTS attributes
115 result
= imv_attestation
->send_message(imv_attestation
, connection_id
,
116 msg
->get_encoding(msg
));
123 * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
125 TNC_Result
TNC_IMV_ReceiveMessage(TNC_IMVID imv_id
,
126 TNC_ConnectionID connection_id
,
127 TNC_BufferReference msg
,
129 TNC_MessageType msg_type
)
131 pa_tnc_msg_t
*pa_tnc_msg
;
134 imv_attestation_state_t
*imv_attestation_state
;
135 enumerator_t
*enumerator
;
137 bool fatal_error
= FALSE
;
139 if (!imv_attestation
)
141 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
142 return TNC_RESULT_NOT_INITIALIZED
;
145 /* get current IMV state */
146 if (!imv_attestation
->get_state(imv_attestation
, connection_id
, &state
))
148 return TNC_RESULT_FATAL
;
151 /* parse received PA-TNC message and automatically handle any errors */
152 result
= imv_attestation
->receive_message(imv_attestation
, connection_id
,
153 chunk_create(msg
, msg_len
), msg_type
,
156 /* no parsed PA-TNC attributes available if an error occurred */
162 /* analyze PA-TNC attributes */
163 enumerator
= pa_tnc_msg
->create_attribute_enumerator(pa_tnc_msg
);
164 while (enumerator
->enumerate(enumerator
, &attr
))
166 if (attr
->get_vendor_id(attr
) == PEN_IETF
&&
167 attr
->get_type(attr
) == IETF_ATTR_PA_TNC_ERROR
)
169 ietf_attr_pa_tnc_error_t
*error_attr
;
170 pa_tnc_error_code_t error_code
;
171 chunk_t msg_info
, attr_info
;
174 error_attr
= (ietf_attr_pa_tnc_error_t
*)attr
;
175 error_code
= error_attr
->get_error_code(error_attr
);
176 msg_info
= error_attr
->get_msg_info(error_attr
);
178 DBG1(DBG_IMV
, "received PA-TNC error '%N' concerning message %#B",
179 pa_tnc_error_code_names
, error_code
, &msg_info
);
182 case PA_ERROR_INVALID_PARAMETER
:
183 offset
= error_attr
->get_offset(error_attr
);
184 DBG1(DBG_IMC
, " occurred at offset of %u bytes", offset
);
186 case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED
:
187 attr_info
= error_attr
->get_attr_info(error_attr
);
188 DBG1(DBG_IMC
, " unsupported attribute %#B", &attr_info
);
195 else if (attr
->get_vendor_id(attr
) == PEN_TCG
)
198 * Handle TCG PTS attributes
202 enumerator
->destroy(enumerator
);
203 pa_tnc_msg
->destroy(pa_tnc_msg
);
207 state
->set_recommendation(state
,
208 TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION
,
209 TNC_IMV_EVALUATION_RESULT_ERROR
);
210 return imv_attestation
->provide_recommendation(imv_attestation
, connection_id
);
213 return imv_attestation
->provide_recommendation(imv_attestation
, connection_id
);
217 * see section 3.7.4 of TCG TNC IF-IMV Specification 1.2
219 TNC_Result
TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id
,
220 TNC_ConnectionID connection_id
)
222 if (!imv_attestation
)
224 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
225 return TNC_RESULT_NOT_INITIALIZED
;
227 return imv_attestation
->provide_recommendation(imv_attestation
, connection_id
);
231 * see section 3.7.5 of TCG TNC IF-IMV Specification 1.2
233 TNC_Result
TNC_IMV_BatchEnding(TNC_IMVID imv_id
,
234 TNC_ConnectionID connection_id
)
236 if (!imv_attestation
)
238 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
239 return TNC_RESULT_NOT_INITIALIZED
;
241 return TNC_RESULT_SUCCESS
;
245 * see section 3.7.6 of TCG TNC IF-IMV Specification 1.2
247 TNC_Result
TNC_IMV_Terminate(TNC_IMVID imv_id
)
249 if (!imv_attestation
)
251 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
252 return TNC_RESULT_NOT_INITIALIZED
;
254 imv_attestation
->destroy(imv_attestation
);
255 imv_attestation
= NULL
;
257 return TNC_RESULT_SUCCESS
;
261 * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.2
263 TNC_Result
TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id
,
264 TNC_TNCS_BindFunctionPointer bind_function
)
266 if (!imv_attestation
)
268 DBG1(DBG_IMV
, "IMV \"%s\" has not been initialized", imv_name
);
269 return TNC_RESULT_NOT_INITIALIZED
;
271 return imv_attestation
->bind_functions(imv_attestation
, bind_function
);