check if TNC client has a valid and registered AIK
[strongswan.git] / src / libpts / plugins / imv_attestation / imv_attestation.c
index 094628a..6bd5984 100644 (file)
@@ -73,7 +73,7 @@ static pts_creds_t *pts_creds;
 static credential_manager_t *pts_credmgr;
 
 /**
- * see section 3.7.1 of TCG TNC IF-IMV Specification 1.2
+ * see section 3.8.1 of TCG TNC IF-IMV Specification 1.3
  */
 TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
                                                          TNC_Version min_version,
@@ -139,7 +139,7 @@ TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
 }
 
 /**
- * see section 3.7.2 of TCG TNC IF-IMV Specification 1.2
+ * see section 3.8.2 of TCG TNC IF-IMV Specification 1.3
  */
 TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
                                                                                  TNC_ConnectionID connection_id,
@@ -169,42 +169,64 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
 static TNC_Result send_message(TNC_ConnectionID connection_id)
 {
        pa_tnc_msg_t *msg;
+       pa_tnc_attr_t *attr;
        imv_state_t *state;
        imv_attestation_state_t *attestation_state;
        TNC_Result result;
+       linked_list_t *attr_list;
+       enumerator_t *enumerator;
 
        if (!imv_attestation->get_state(imv_attestation, connection_id, &state))
        {
                return TNC_RESULT_FATAL;
        }
        attestation_state = (imv_attestation_state_t*)state;
-       msg = pa_tnc_msg_create();
+       attr_list = linked_list_create();
 
-       if (imv_attestation_build(msg, attestation_state, supported_algorithms,
+       if (imv_attestation_build(attr_list, attestation_state, supported_algorithms,
                                                          supported_dh_groups, pts_db))
        {
-               msg->build(msg);
-               result = imv_attestation->send_message(imv_attestation, connection_id,
-                                                                                          FALSE, 0, TNC_IMCID_ANY,
-                                                                                          msg->get_encoding(msg));
+               if (attr_list->get_count(attr_list))
+               {
+                       msg = pa_tnc_msg_create();
+
+                       /* move PA-TNC attributes to PA-TNC message */
+                       enumerator = attr_list->create_enumerator(attr_list);
+                       while (enumerator->enumerate(enumerator, &attr))
+                       {
+                               msg->add_attribute(msg, attr);
+                       }
+                       enumerator->destroy(enumerator);
+
+                       msg->build(msg);
+                       result = imv_attestation->send_message(imv_attestation,
+                                                       connection_id, FALSE, 0, TNC_IMCID_ANY,
+                                                       msg->get_encoding(msg));
+                       msg->destroy(msg);
+               }
+               else
+               {
+                       result = TNC_RESULT_SUCCESS;
+               }
+               attr_list->destroy(attr_list);
        }
        else
        {
+               attr_list->destroy_offset(attr_list, offsetof(pa_tnc_attr_t, destroy));
                result = TNC_RESULT_FATAL;
        }
-       msg->destroy(msg);
 
        return result;
 }
 
-/**
- * see section 3.7.3 of TCG TNC IF-IMV Specification 1.2
- */
-TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
+static TNC_Result receive_message(TNC_IMVID imv_id,
                                                                  TNC_ConnectionID connection_id,
-                                                                 TNC_BufferReference msg,
-                                                                 TNC_UInt32 msg_len,
-                                                                 TNC_MessageType msg_type)
+                                                                 TNC_UInt32 msg_flags,
+                                                                 chunk_t msg,
+                                                                 TNC_VendorID msg_vid,
+                                                                 TNC_MessageSubtype msg_subtype,
+                                                                 TNC_UInt32 src_imc_id,
+                                                                 TNC_UInt32 dst_imv_id)
 {
        pa_tnc_msg_t *pa_tnc_msg;
        pa_tnc_attr_t *attr;
@@ -230,9 +252,8 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
        pts = attestation_state->get_pts(attestation_state);
 
        /* parse received PA-TNC message and automatically handle any errors */
-       result = imv_attestation->receive_message(imv_attestation, connection_id,
-                                                                          chunk_create(msg, msg_len), msg_type,
-                                                                          &pa_tnc_msg);
+       result = imv_attestation->receive_message(imv_attestation, state, msg,
+                                        msg_vid, msg_subtype, src_imc_id, dst_imv_id, &pa_tnc_msg);
 
        /* no parsed PA-TNC attributes available if an error occurred */
        if (!pa_tnc_msg)
@@ -240,8 +261,11 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
                return result;
        }
 
+       /* preprocess any IETF standard error attributes */
+       result = pa_tnc_msg->process_ietf_std_errors(pa_tnc_msg) ?
+                                       TNC_RESULT_FATAL : TNC_RESULT_SUCCESS;
+
        attr_list = linked_list_create();
-       result = TNC_RESULT_SUCCESS;
 
        /* analyze PA-TNC attributes */
        enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg);
@@ -254,43 +278,22 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
                                ietf_attr_pa_tnc_error_t *error_attr;
                                pen_t error_vendor_id;
                                pa_tnc_error_code_t error_code;
-                               chunk_t msg_info, attr_info;
-                               u_int32_t offset;
+                               chunk_t msg_info;
 
                                error_attr = (ietf_attr_pa_tnc_error_t*)attr;
                                error_vendor_id = error_attr->get_vendor_id(error_attr);
-                               error_code = error_attr->get_error_code(error_attr);
-                               msg_info = error_attr->get_msg_info(error_attr);
 
-                               if (error_vendor_id == PEN_IETF)
-                               {
-                                       DBG1(DBG_IMV, "received PA-TNC error '%N' "
-                                                                 "concerning message %#B",
-                                                pa_tnc_error_code_names, error_code, &msg_info);
-
-                                       switch (error_code)
-                                       {
-                                               case PA_ERROR_INVALID_PARAMETER:
-                                                       offset = error_attr->get_offset(error_attr);
-                                                       DBG1(DBG_IMV, "  occurred at offset of %u bytes",
-                                                                offset);
-                                                       break;
-                                               case PA_ERROR_ATTR_TYPE_NOT_SUPPORTED:
-                                                       attr_info = error_attr->get_attr_info(error_attr);
-                                                       DBG1(DBG_IMV, "  unsupported attribute %#B",
-                                                                &attr_info);
-                                                       break;
-                                               default:
-                                                       break;
-                                       }
-                               }
-                               else if (error_vendor_id == PEN_TCG)
+                               if (error_vendor_id == PEN_TCG)
                                {
+                                       error_code = error_attr->get_error_code(error_attr);
+                                       msg_info = error_attr->get_msg_info(error_attr);
+
                                        DBG1(DBG_IMV, "received TCG-PTS error '%N'",
                                                 pts_error_code_names, error_code);
                                        DBG1(DBG_IMV, "error information: %B", &msg_info);
+
+                                       result = TNC_RESULT_FATAL;
                                }
-                               result = TNC_RESULT_FATAL;
                        }
                        else if (attr->get_type(attr) == IETF_ATTR_PRODUCT_INFORMATION)
                        {
@@ -317,7 +320,7 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
 
        if (result != TNC_RESULT_SUCCESS)
        {
-               attr_list->destroy(attr_list);
+               attr_list->destroy_offset(attr_list, offsetof(pa_tnc_attr_t, destroy));
                state->set_recommendation(state,
                                                                TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
                                                                TNC_IMV_EVALUATION_RESULT_ERROR);
@@ -329,6 +332,7 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
        {
                pa_tnc_msg = pa_tnc_msg_create();
 
+               /* move PA-TNC attributes to PA-TNC message */
                enumerator = attr_list->create_enumerator(attr_list);
                while (enumerator->enumerate(enumerator, &attr))
                {
@@ -348,6 +352,17 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
        }
        attr_list->destroy(attr_list);
 
+       /* check the IMV state for the next PA-TNC attributes to send */
+       result = send_message(connection_id);
+       if (result != TNC_RESULT_SUCCESS)
+       {
+               state->set_recommendation(state,
+                                                               TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+                                                               TNC_IMV_EVALUATION_RESULT_ERROR);
+               return imv_attestation->provide_recommendation(imv_attestation,
+                                                                                                          connection_id);
+       }
+
        if (attestation_state->get_handshake_state(attestation_state) ==
                IMV_ATTESTATION_STATE_END)
        {
@@ -379,11 +394,48 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
                                                                                                           connection_id);
        }
 
-       return send_message(connection_id);
+       return result;
+}
+
+/**
+ * see section 3.8.4 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
+                                                                 TNC_ConnectionID connection_id,
+                                                                 TNC_BufferReference msg,
+                                                                 TNC_UInt32 msg_len,
+                                                                 TNC_MessageType msg_type)
+{
+       TNC_VendorID msg_vid;
+       TNC_MessageSubtype msg_subtype;
+
+       msg_vid = msg_type >> 8;
+       msg_subtype = msg_type & TNC_SUBTYPE_ANY;
+
+       return receive_message(imv_id, connection_id, 0, chunk_create(msg, msg_len),
+                                                  msg_vid,     msg_subtype, 0, TNC_IMVID_ANY);
+}
+
+/**
+ * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMV_ReceiveMessageLong(TNC_IMVID imv_id,
+                                                                         TNC_ConnectionID connection_id,
+                                                                         TNC_UInt32 msg_flags,
+                                                                         TNC_BufferReference msg,
+                                                                         TNC_UInt32 msg_len,
+                                                                         TNC_VendorID msg_vid,
+                                                                         TNC_MessageSubtype msg_subtype,
+                                                                         TNC_UInt32 src_imc_id,
+                                                                         TNC_UInt32 dst_imv_id)
+{
+       return receive_message(imv_id, connection_id, msg_flags,
+                                                  chunk_create(msg, msg_len), msg_vid, msg_subtype,
+                                                  src_imc_id, dst_imv_id);
 }
 
 /**
- * see section 3.7.4 of TCG TNC IF-IMV Specification 1.2
+ * see section 3.8.7 of TCG TNC IF-IMV Specification 1.3
  */
 TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
                                                                                 TNC_ConnectionID connection_id)
@@ -398,7 +450,7 @@ TNC_Result TNC_IMV_SolicitRecommendation(TNC_IMVID imv_id,
 }
 
 /**
- * see section 3.7.5 of TCG TNC IF-IMV Specification 1.2
+ * see section 3.8.8 of TCG TNC IF-IMV Specification 1.3
  */
 TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
                                                           TNC_ConnectionID connection_id)
@@ -428,7 +480,7 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id,
 }
 
 /**
- * see section 3.7.6 of TCG TNC IF-IMV Specification 1.2
+ * see section 3.8.9 of TCG TNC IF-IMV Specification 1.3
  */
 TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
 {
@@ -454,7 +506,7 @@ TNC_Result TNC_IMV_Terminate(TNC_IMVID imv_id)
 }
 
 /**
- * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.2
+ * see section 4.2.8.1 of TCG TNC IF-IMV Specification 1.3
  */
 TNC_Result TNC_IMV_ProvideBindFunction(TNC_IMVID imv_id,
                                                                TNC_TNCS_BindFunctionPointer bind_function)