check if TNC client has a valid and registered AIK
[strongswan.git] / src / libpts / plugins / imv_attestation / imv_attestation.c
index 3469979..6bd5984 100644 (file)
@@ -58,11 +58,6 @@ static pts_meas_algorithms_t supported_algorithms = PTS_MEAS_ALGO_NONE;
 static pts_dh_group_t supported_dh_groups = PTS_DH_GROUP_NONE;
 
 /**
- * Supported PTS Diffie Hellman Groups
- */
-static pts_dh_group_t supported_dh_groups = PTS_DH_GROUP_NONE;
-
-/**
  * PTS file measurement database
  */
 static pts_database_t *pts_db;
@@ -78,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,
@@ -97,10 +92,6 @@ TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
        {
                return TNC_RESULT_FATAL;
        }
-       if (!pts_probe_dh_groups(&supported_dh_groups))
-       {
-               return TNC_RESULT_FATAL;
-       }
        imv_attestation = imv_agent_create(imv_name, IMV_VENDOR_ID, IMV_SUBTYPE,
                                                                           imv_id, actual_version);
        if (!imv_attestation)
@@ -127,28 +118,6 @@ TNC_Result TNC_IMV_Initialize(TNC_IMVID imv_id,
                return TNC_RESULT_FATAL;
        }
 
-       /**
-        * Specify supported PTS Diffie-Hellman groups
-        *
-        * modp1024: PTS_DH_GROUP_IKE2
-        * modp1536: PTS_DH_GROUP_IKE2  | PTS_DH_GROUP_IKE5
-        * modp2048: PTS_DH_GROUP_IKE2  | PTS_DH_GROUP_IKE5  | PTS_DH_GROUP_IKE14
-        * ecp256:   PTS_DH_GROUP_IKE2  | PTS_DH_GROUP_IKE5  | PTS_DH_GROUP_IKE14 |
-        *           PTS_DH_GROUP_IKE19
-        * ecp384:   PTS_DH_GROUP_IKE2  | PTS_DH_GROUP_IKE5  | PTS_DH_GROUP_IKE14 |
-        *           PTS_DH_GROUP_IKE19 | PTS_DH_GROUP_IKE20
-        *
-        * we expect the PTS-IMC to select the strongest supported group
-        */
-       dh_group = lib->settings->get_str(lib->settings,
-                               "libimcv.plugins.imv-attestation.dh_group", "ecp256");
-
-       if (!pts_meas_algo_update(hash_alg, &supported_algorithms) ||
-               !pts_dh_group_update(dh_group, &supported_dh_groups))
-       {
-               return TNC_RESULT_FATAL;
-       }
-
        /* create a PTS credential manager */
        pts_credmgr = credential_manager_create();
 
@@ -170,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,
@@ -200,200 +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();
 
-<<<<<<< HEAD
-       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,
-                                                                                          msg->get_encoding(msg));
-=======
-       if (handshake_state == IMV_ATTESTATION_STATE_NONCE_REQ &&
-               !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T))
-       {
-               DBG1(DBG_IMV, "PTS-IMC has no TPM capability - "
-                                         "advancing to PTS measurement phase");
-               handshake_state = IMV_ATTESTATION_STATE_MEAS;
->>>>>>> added the IMV_ATTESTATION_STATE_NONCE_REQ state
-       }
-       else
-       {
-<<<<<<< HEAD
-               result = TNC_RESULT_FATAL;
-=======
-               case IMV_ATTESTATION_STATE_INIT:
-               {
-                       pts_proto_caps_flag_t flags;
-
-                       /* Send Request Protocol Capabilities attribute */
-                       flags = pts->get_proto_caps(pts);
-                       attr = tcg_pts_attr_proto_caps_create(flags, TRUE);
-                       attr->set_noskip_flag(attr, TRUE);
-                       msg->add_attribute(msg, attr);
-
-                       /* Send Measurement Algorithms attribute */
-                       attr = tcg_pts_attr_meas_algo_create(supported_algorithms, FALSE);
-                       attr->set_noskip_flag(attr, TRUE);
-                       msg->add_attribute(msg, attr);
-
-                       attestation_state->set_handshake_state(attestation_state,
-                                                                               IMV_ATTESTATION_STATE_NONCE_REQ);
-                       break;
-               }
-               case IMV_ATTESTATION_STATE_NONCE_REQ:
+               if (attr_list->get_count(attr_list))
                {
-                       int min_nonce_len;
-
-                       /* Send DH nonce parameters request attribute */
-                       min_nonce_len = lib->settings->get_int(lib->settings,
-                                               "libimcv.plugins.imv-attestation.min_nonce_len", 0);
-                       attr = tcg_pts_attr_dh_nonce_params_req_create(min_nonce_len,
-                                                                                                        supported_dh_groups);
-                       attr->set_noskip_flag(attr, TRUE);
-                       msg->add_attribute(msg, attr);
-
-                       attestation_state->set_handshake_state(attestation_state,
-                                                                               IMV_ATTESTATION_STATE_TPM_INIT);
-                       break;
-               }
-               case IMV_ATTESTATION_STATE_TPM_INIT:
-               {
-                       pts_meas_algorithms_t selected_algorithm;
-                       chunk_t initiator_value, initiator_nonce;
-
-                       /* Send DH nonce finish attribute */
-                       selected_algorithm = pts->get_meas_algorithm(pts);
-                       pts->get_my_public_value(pts, &initiator_value, &initiator_nonce);
-                       attr = tcg_pts_attr_dh_nonce_finish_create(selected_algorithm,
-                                                                                initiator_value, initiator_nonce);
-                       attr->set_noskip_flag(attr, TRUE);
-                       msg->add_attribute(msg, attr);
-
-                       /* Send Get TPM Version attribute */
-                       attr = tcg_pts_attr_get_tpm_version_info_create();
-                       attr->set_noskip_flag(attr, TRUE);
-                       msg->add_attribute(msg, attr);
-
-                       /* Send Get AIK attribute */
-                       attr = tcg_pts_attr_get_aik_create();
-                       attr->set_noskip_flag(attr, TRUE);
-                       msg->add_attribute(msg, attr);
-
-                       attestation_state->set_handshake_state(attestation_state,
-                                                                               IMV_ATTESTATION_STATE_MEAS);
-                       break;
-               }
-               case IMV_ATTESTATION_STATE_MEAS:
-               {
-
-                       enumerator_t *enumerator;
-                       u_int32_t delimiter = SOLIDUS_UTF;
-                       char *platform_info, *pathname;
-                       u_int16_t request_id;
-                       int id, type;
-                       bool is_dir;
-
-                       attestation_state->set_handshake_state(attestation_state,
-                                                                               IMV_ATTESTATION_STATE_COMP_EVID);
+                       msg = pa_tnc_msg_create();
 
-                       /* Get Platform and OS of the PTS-IMC */
-                       platform_info = pts->get_platform_info(pts);
-
-                       if (!pts_db || !platform_info)
-                       {
-                               DBG1(DBG_IMV, "%s%s%s not available",
-                                       (pts_db) ? "" : "pts database",
-                                       (!pts_db && !platform_info) ? "and" : "",
-                                       (platform_info) ? "" : "platform info");
-                               break;
-                       }
-                       DBG1(DBG_IMV, "platform is '%s'", platform_info);
-
-                       /* Send Request File Metadata attribute */
-                       attr = tcg_pts_attr_req_file_meta_create(FALSE, SOLIDUS_UTF, "/etc/tnc_config");
-                       attr->set_noskip_flag(attr, TRUE);
-                       msg->add_attribute(msg, attr);
-
-                       /* Send Request File Measurement attribute */
-                       enumerator = pts_db->create_file_enumerator(pts_db, platform_info);
-                       if (!enumerator)
+                       /* move PA-TNC attributes to PA-TNC message */
+                       enumerator = attr_list->create_enumerator(attr_list);
+                       while (enumerator->enumerate(enumerator, &attr))
                        {
-                               break;
-                       }
-                       while (enumerator->enumerate(enumerator, &id, &type, &pathname))
-                       {
-                               is_dir = (type != 0);
-                               request_id = attestation_state->add_request(attestation_state,
-                                                                                                                       id, is_dir);
-                               DBG2(DBG_IMV, "measurement request %d for %s '%s'",
-                                        request_id, is_dir ? "directory" : "file", pathname);
-                               attr = tcg_pts_attr_req_file_meas_create(is_dir, request_id,
-                                                                                                        delimiter, pathname);
-                               attr->set_noskip_flag(attr, TRUE);
                                msg->add_attribute(msg, attr);
                        }
                        enumerator->destroy(enumerator);
-                       break;
+
+                       msg->build(msg);
+                       result = imv_attestation->send_message(imv_attestation,
+                                                       connection_id, FALSE, 0, TNC_IMCID_ANY,
+                                                       msg->get_encoding(msg));
+                       msg->destroy(msg);
                }
-               case IMV_ATTESTATION_STATE_COMP_EVID:
+               else
                {
-                       pts_attr_req_funct_comp_evid_flag_t flags;
-                       u_int32_t sub_comp_depth;
-                       pts_qualifier_t qualifier;
-                       pts_funct_comp_name_t name;
-
-                       attestation_state->set_handshake_state(attestation_state,
-                                                                               IMV_ATTESTATION_STATE_END);
-
-                       flags = PTS_REQ_FUNC_COMP_FLAG_PCR;
-                       sub_comp_depth = 0;
-                       qualifier.kernel = FALSE;
-                       qualifier.sub_component = FALSE;
-                       qualifier.type = PTS_FUNC_COMP_TYPE_ALL;
-                       name = PTS_FUNC_COMP_NAME_BIOS;
-
-                       /* Send Request Functional Component Evidence attribute */
-                       attr = tcg_pts_attr_req_funct_comp_evid_create(flags, sub_comp_depth,
-                                                                                                               PEN_TCG, qualifier, name);
-                       attr->set_noskip_flag(attr, TRUE);
-                       msg->add_attribute(msg, attr);
-                       /* Send Generate Attestation Evidence attribute */
-                       attr = tcg_pts_attr_gen_attest_evid_create();
-                       attr->set_noskip_flag(attr, TRUE);
-                       msg->add_attribute(msg, attr);
-
-                       break;
+                       result = TNC_RESULT_SUCCESS;
                }
-               default:
-                       DBG1(DBG_IMV, "Attestation IMV is in unknown state: \"%s\"",
-                                handshake_state);
-                       return TNC_RESULT_FATAL;
->>>>>>> added the IMV_ATTESTATION_STATE_NONCE_REQ state
+               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;
@@ -419,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)
@@ -429,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);
@@ -443,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)
                        {
@@ -506,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);
@@ -518,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))
                {
@@ -527,7 +342,8 @@ TNC_Result TNC_IMV_ReceiveMessage(TNC_IMVID imv_id,
 
                pa_tnc_msg->build(pa_tnc_msg);
                result = imv_attestation->send_message(imv_attestation, connection_id,
-                                                       pa_tnc_msg->get_encoding(pa_tnc_msg));
+                                                                               FALSE, 0, TNC_IMCID_ANY,
+                                                                               pa_tnc_msg->get_encoding(pa_tnc_msg));
                
                pa_tnc_msg->destroy(pa_tnc_msg);
                attr_list->destroy(attr_list);
@@ -536,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)
        {
@@ -567,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)
@@ -586,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)
@@ -616,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)
 {
@@ -642,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)