From: Andreas Steffen Date: Sun, 9 Oct 2011 08:19:10 +0000 (+0200) Subject: moved attribute processing to imc_attestation_process X-Git-Tag: 4.6.2~330 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=325704e1b41077167430eb712d58b5179d74ae1d;p=thirdparty%2Fstrongswan.git moved attribute processing to imc_attestation_process --- diff --git a/src/libimcv/plugins/imc_attestation/Makefile.am b/src/libimcv/plugins/imc_attestation/Makefile.am index ee082319d3..9d78b935aa 100644 --- a/src/libimcv/plugins/imc_attestation/Makefile.am +++ b/src/libimcv/plugins/imc_attestation/Makefile.am @@ -11,7 +11,8 @@ imc_attestation_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \ $(top_builddir)/src/libpts/libpts.la imc_attestation_la_SOURCES = imc_attestation.c \ - imc_attestation_state.h imc_attestation_state.c + imc_attestation_state.h imc_attestation_state.c \ + imc_attestation_process.h imc_attestation_process.c imc_attestation_la_LDFLAGS = -module -avoid-version diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation.c b/src/libimcv/plugins/imc_attestation/imc_attestation.c index 4d93cb88a1..7862dda894 100644 --- a/src/libimcv/plugins/imc_attestation/imc_attestation.c +++ b/src/libimcv/plugins/imc_attestation/imc_attestation.c @@ -13,9 +13,8 @@ * for more details. */ -#define _GNU_SOURCE - #include "imc_attestation_state.h" +#include "imc_attestation_process.h" #include #include @@ -28,22 +27,7 @@ #include #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include @@ -58,9 +42,6 @@ static const char imc_name[] = "Attestation"; #define IMC_VENDOR_ID PEN_TCG #define IMC_SUBTYPE PA_SUBTYPE_TCG_PTS -#define DEFAULT_NONCE_LEN 20 -#define EXTEND_PCR 16 - static imc_agent_t *imc_attestation; /** @@ -210,10 +191,6 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, enumerator_t *enumerator; pts_t *pts; TNC_Result result; - bool fatal_error = FALSE; - chunk_t attr_info; - pts_error_code_t pts_error; - bool valid_path; if (!imc_attestation) { @@ -241,6 +218,7 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, } attr_list = linked_list_create(); + result = TNC_RESULT_SUCCESS; /* analyze PA-TNC attributes */ enumerator = pa_tnc_msg->create_attribute_enumerator(pa_tnc_msg); @@ -273,616 +251,22 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, default: break; } - fatal_error = TRUE; + result = TNC_RESULT_FATAL; } else if (attr->get_vendor_id(attr) == PEN_TCG) { - switch (attr->get_type(attr)) + if (!imc_attestation_process(attr, attr_list, attestation_state, + supported_algorithms, supported_dh_groups, evidences)) { - case TCG_PTS_REQ_PROTO_CAPS: - { - tcg_pts_attr_proto_caps_t *attr_cast; - pts_proto_caps_flag_t imc_caps, imv_caps; - - attr_cast = (tcg_pts_attr_proto_caps_t*)attr; - imv_caps = attr_cast->get_flags(attr_cast); - imc_caps = pts->get_proto_caps(pts); - pts->set_proto_caps(pts, imc_caps & imv_caps); - - /* Send PTS Protocol Capabilities attribute */ - attr = tcg_pts_attr_proto_caps_create(imc_caps & imv_caps, - FALSE); - attr_list->insert_last(attr_list, attr); - break; - } - case TCG_PTS_MEAS_ALGO: - { - tcg_pts_attr_meas_algo_t *attr_cast; - pts_meas_algorithms_t offered_algorithms, selected_algorithm; - - attr_cast = (tcg_pts_attr_meas_algo_t*)attr; - offered_algorithms = attr_cast->get_algorithms(attr_cast); - selected_algorithm = pts_meas_algo_select(supported_algorithms, - offered_algorithms); - if (selected_algorithm == PTS_MEAS_ALGO_NONE) - { - attr = pts_hash_alg_error_create(supported_algorithms); - attr_list->insert_last(attr_list, attr); - break; - } - - /* Send Measurement Algorithm Selection attribute */ - pts->set_meas_algorithm(pts, selected_algorithm); - attr = tcg_pts_attr_meas_algo_create(selected_algorithm, - TRUE); - attr_list->insert_last(attr_list, attr); - break; - } - case TCG_PTS_DH_NONCE_PARAMS_REQ: - { - tcg_pts_attr_dh_nonce_params_req_t *attr_cast; - pts_dh_group_t offered_dh_groups, selected_dh_group; - chunk_t responder_value, responder_nonce; - int nonce_len, min_nonce_len; - - nonce_len = lib->settings->get_int(lib->settings, - "libimcv.plugins.imc-attestation.nonce_len", - DEFAULT_NONCE_LEN); - - attr_cast = (tcg_pts_attr_dh_nonce_params_req_t*)attr; - min_nonce_len = attr_cast->get_min_nonce_len(attr_cast); - if (min_nonce_len > 0 && nonce_len < min_nonce_len) - { - attr_info = attr->get_value(attr); - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_BAD_NONCE_LENGTH, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - - offered_dh_groups = attr_cast->get_dh_groups(attr_cast); - selected_dh_group = pts_dh_group_select(supported_dh_groups, - offered_dh_groups); - if (selected_dh_group == PTS_DH_GROUP_NONE) - { - attr_info = attr->get_value(attr); - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_DH_GRPS_NOT_SUPPORTED, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - - /* Create own DH factor and nonce */ - if (!pts->create_dh_nonce(pts, selected_dh_group, nonce_len)) - { - goto err; - } - pts->get_my_public_value(pts, &responder_value, - &responder_nonce); - - /* Send DH Nonce Parameters Response attribute */ - attr = tcg_pts_attr_dh_nonce_params_resp_create( - selected_dh_group, supported_algorithms, - responder_nonce, responder_value); - attr_list->insert_last(attr_list, attr); - break; - } - case TCG_PTS_DH_NONCE_FINISH: - { - tcg_pts_attr_dh_nonce_finish_t *attr_cast; - pts_meas_algorithms_t selected_algorithm; - chunk_t initiator_nonce, initiator_value; - int nonce_len; - - attr_cast = (tcg_pts_attr_dh_nonce_finish_t*)attr; - selected_algorithm = attr_cast->get_hash_algo(attr_cast); - if (!(selected_algorithm & supported_algorithms)) - { - DBG1(DBG_IMC, "PTS-IMV selected unsupported " - "DH hash algorithm"); - return TNC_RESULT_FATAL; - } - pts->set_dh_hash_algorithm(pts, selected_algorithm); - - initiator_value = attr_cast->get_initiator_value(attr_cast); - initiator_nonce = attr_cast->get_initiator_nonce(attr_cast); - nonce_len = initiator_nonce.len; - if (nonce_len <= 16) /* TODO */ - { - attr_info = attr->get_value(attr); - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_BAD_NONCE_LENGTH, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - - pts->set_peer_public_value(pts, initiator_value, - initiator_nonce); - if (!pts->calculate_secret(pts)) - { - goto err; - } - - break; - } -<<<<<<< HEAD - case TCG_PTS_MEAS_ALGO: - { - tcg_pts_attr_meas_algo_t *attr_cast; - pts_meas_algorithms_t offered_algorithms, selected_algorithm; - - attr_cast = (tcg_pts_attr_meas_algo_t*)attr; - offered_algorithms = attr_cast->get_algorithms(attr_cast); - - if ((supported_algorithms & PTS_MEAS_ALGO_SHA384) && - (offered_algorithms & PTS_MEAS_ALGO_SHA384)) - { - pts->set_meas_algorithm(pts, PTS_MEAS_ALGO_SHA384); - } - else if ((supported_algorithms & PTS_MEAS_ALGO_SHA256) && - (offered_algorithms & PTS_MEAS_ALGO_SHA256)) - { - pts->set_meas_algorithm(pts, PTS_MEAS_ALGO_SHA256); - } - - else if ((supported_algorithms & PTS_MEAS_ALGO_SHA1) && - (offered_algorithms & PTS_MEAS_ALGO_SHA1)) - { - pts->set_meas_algorithm(pts, PTS_MEAS_ALGO_SHA1); - } - else - { - attr = pts_hash_alg_error_create(supported_algorithms); - attr_list->insert_last(attr_list, attr); - break; - } - - /* Send Measurement Algorithm Selection attribute */ - selected_algorithm = pts->get_meas_algorithm(pts); - attr = tcg_pts_attr_meas_algo_create(selected_algorithm, - TRUE); - attr_list->insert_last(attr_list, attr); - break; - } - case TCG_PTS_GET_TPM_VERSION_INFO: - { - chunk_t tpm_version_info, attr_info; - - if (!pts->get_tpm_version_info(pts, &tpm_version_info)) - { - attr_info = attr->get_value(attr); - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_TPM_VERS_NOT_SUPPORTED, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - - /* Send TPM Version Info attribute */ - attr = tcg_pts_attr_tpm_version_info_create(tpm_version_info); - attr_list->insert_last(attr_list, attr); - break; - } - case TCG_PTS_GET_AIK: - { - certificate_t *aik; - - aik = pts->get_aik(pts); - if (!aik) - { - DBG1(DBG_IMC, "no AIK certificate or public key available"); - break; - } - - /* Send AIK attribute */ - attr = tcg_pts_attr_aik_create(aik); - attr_list->insert_last(attr_list, attr); - break; - } - case TCG_PTS_REQ_FUNCT_COMP_EVID: - { - tcg_pts_attr_req_funct_comp_evid_t *attr_cast; - pts_proto_caps_flag_t negotiated_caps; - pts_attr_req_funct_comp_evid_flag_t flags; - u_int32_t sub_comp_depth; - u_int32_t comp_name_vendor_id; - u_int8_t family; - pts_qualifier_t qualifier; - pts_funct_comp_name_t name; - - attr_info = attr->get_value(attr); - attr_cast = (tcg_pts_attr_req_funct_comp_evid_t*)attr; - negotiated_caps = pts->get_proto_caps(pts); - flags = attr_cast->get_flags(attr_cast); - - if (flags & PTS_REQ_FUNC_COMP_FLAG_TTC) - { - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_UNABLE_DET_TTC, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - if (flags & PTS_REQ_FUNC_COMP_FLAG_VER && - !(negotiated_caps & PTS_PROTO_CAPS_V)) - { - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_UNABLE_LOCAL_VAL, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - if (flags & PTS_REQ_FUNC_COMP_FLAG_CURR && - !(negotiated_caps & PTS_PROTO_CAPS_C)) - { - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_UNABLE_CUR_EVID, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - if (flags & PTS_REQ_FUNC_COMP_FLAG_PCR && - !(negotiated_caps & PTS_PROTO_CAPS_T)) - { - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_UNABLE_DET_PCR, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - - sub_comp_depth = attr_cast->get_sub_component_depth(attr_cast); - /* TODO: Implement checking of components with its sub-components */ - if (sub_comp_depth != 0) - { - DBG1(DBG_IMC, "Current version of Attestation IMC does not support" - "sub component measurement deeper than zero. " - "Measuring top level component only."); - } - - comp_name_vendor_id = attr_cast->get_comp_funct_name_vendor_id(attr_cast); - if (comp_name_vendor_id != PEN_TCG) - { - DBG1(DBG_IMC, "Current version of Attestation IMC supports" - "only functional component namings by TCG "); - break; - } - - family = attr_cast->get_family(attr_cast); - if (family) - { - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_INVALID_NAME_FAM, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - - qualifier = attr_cast->get_qualifier(attr_cast); - /* Check if Unknown or Wildcard was set for qualifier */ - if (qualifier.kernel && qualifier.sub_component && - (qualifier.type & PTS_FUNC_COMP_TYPE_ALL)) - { - DBG2(DBG_IMC, "Wildcard was set for the qualifier of functional" - " component. Identifying the component with name binary enumeration"); - } - else if (!qualifier.kernel && !qualifier.sub_component && - (qualifier.type & PTS_FUNC_COMP_TYPE_UNKNOWN)) - { - DBG2(DBG_IMC, "Unknown was set for the qualifier of functional" - " component. Identifying the component with name binary enumeration"); - } - else - { - /* TODO: Implement what todo with received qualifier */ - } - - name = attr_cast->get_comp_funct_name(attr_cast); - switch (name) - { - case PTS_FUNC_COMP_NAME_BIOS: - { - tcg_pts_attr_simple_comp_evid_params_t params; - pts_qualifier_t qualifier; - time_t measurement_time_t; - struct tm *time_now; - char *utc_time; - hasher_t *hasher; - u_char hash_output[HASH_SIZE_SHA384]; - hash_algorithm_t hash_alg; - - /* TODO: Implement BIOS measurement */ - DBG1(DBG_IMC, "Experimental implementation:" - " Extend TPM with etc/tnc_config file"); - - params.flags = PTS_SIMPLE_COMP_EVID_FLAG_PCR | PTS_SIMPLE_COMP_EVID_FLAG_NO_VALID; - params.depth = 0; - params.vendor_id = PEN_TCG; - - qualifier.kernel = FALSE; - qualifier.sub_component = FALSE; - qualifier.type = PTS_FUNC_COMP_TYPE_TNC; - params.qualifier = qualifier; - - params.name = PTS_FUNC_COMP_NAME_BIOS; - params.extended_pcr = EXTEND_PCR; - params.hash_algorithm = pts->get_meas_algorithm(pts); - - if (!(params.flags & PTS_SIMPLE_COMP_EVID_FLAG_PCR)) - { - params.transformation = PTS_PCR_TRANSFORM_NO; - } - else if (pts->get_meas_algorithm(pts) & PTS_MEAS_ALGO_SHA1) - { - params.transformation = PTS_PCR_TRANSFORM_MATCH; - } - else if (pts->get_meas_algorithm(pts) & PTS_MEAS_ALGO_SHA256) - { - params.transformation = PTS_PCR_TRANSFORM_LONG; - } - - /* Create a hasher */ - hash_alg = pts_meas_algo_to_hash(pts->get_meas_algorithm(pts)); - hasher = lib->crypto->create_hasher(lib->crypto, hash_alg); - if (!hasher) - { - DBG1(DBG_IMC, " hasher %N not available", - hash_algorithm_names, hash_alg); - goto err; - } - - if (!pts->hash_file(pts, hasher, "/etc/tnc_config", hash_output)) - { - hasher->destroy(hasher); - goto err; - } - - measurement_time_t = time(NULL); - if (!measurement_time_t) - { - params.measurement_time = chunk_create("0000-00-00T00:00:00Z", 20); - } - else - { - time_now = localtime(&measurement_time_t); - if (asprintf(&utc_time, "%d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2dZ", - time_now->tm_year + 1900, - time_now->tm_mon + 1, - time_now->tm_mday, - time_now->tm_hour, - time_now->tm_min, - time_now->tm_sec) < 0) - { - DBG1(DBG_IMC, "Couldn not format local time to UTC"); - hasher->destroy(hasher); - goto err; - } - params.measurement_time = chunk_create(utc_time, 20); - params.measurement_time = chunk_clone(params.measurement_time); - free(utc_time); - - } - - params.measurement = chunk_create(hash_output, hasher->get_hash_size(hasher)); - hasher->destroy(hasher); - - params.policy_uri = chunk_empty; - if (!pts->read_pcr(pts, EXTEND_PCR, ¶ms.pcr_before)) - { - DBG1(DBG_IMC, "Error occured while reading PCR: %d", EXTEND_PCR); - goto err; - } - - if (!pts->extend_pcr(pts, EXTEND_PCR, - params.measurement, ¶ms.pcr_after)) - { - DBG1(DBG_IMC, "Error occured while extending PCR: %d", EXTEND_PCR); - goto err; - } - - /* Buffer Simple Component Evidence attribute */ - attr = tcg_pts_attr_simple_comp_evid_create(params); - evidences->insert_last(evidences, attr); - - break; - } - case PTS_FUNC_COMP_NAME_IGNORE: - case PTS_FUNC_COMP_NAME_CRTM: - case PTS_FUNC_COMP_NAME_PLATFORM_EXT: - case PTS_FUNC_COMP_NAME_BOARD: - case PTS_FUNC_COMP_NAME_INIT_LOADER: - case PTS_FUNC_COMP_NAME_OPT_ROMS: - default: - { - DBG1(DBG_IMC, "Unsupported Functional Component Name"); - break; - } - } - - break; - } - case TCG_PTS_GEN_ATTEST_EVID: - { - enumerator_t *e; - pts_simple_evid_final_flag_t flags; - chunk_t pcr_composite, quote_signature; - linked_list_t *pcrs; - - /* Send buffered Simple Component Evidences */ - pcrs = linked_list_create(); - - e = evidences->create_enumerator(evidences); - while (e->enumerate(e, &attr)) - { - tcg_pts_attr_simple_comp_evid_t *attr_cast; - u_int32_t extended_pcr; - - attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr; - extended_pcr = attr_cast->get_extended_pcr(attr_cast); - - /* Add extended PCR number to PCR list to quote */ - /* Duplicated PCR numbers have no influence */ - pcrs->insert_last(pcrs, &extended_pcr); - /* Send Simple Compoenent Evidence */ - attr_list->insert_last(attr_list, attr); - } - - /* Quote */ - if (!pts->quote_tpm(pts, pcrs, &pcr_composite, "e_signature)) - { - DBG1(DBG_IMC, "Error occured while TPM quote operation"); - DESTROY_IF(e); - DESTROY_IF(pcrs); - DESTROY_IF(evidences); - goto err; - } - - /* Send Simple Evidence Final attribute */ - flags = PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO; - - attr = tcg_pts_attr_simple_evid_final_create(flags, 0, - pcr_composite, quote_signature, chunk_empty); - attr_list->insert_last(attr_list, attr); - - DESTROY_IF(e); - DESTROY_IF(pcrs); - DESTROY_IF(evidences); - - break; - } - case TCG_PTS_REQ_FILE_META: - { - tcg_pts_attr_req_file_meta_t *attr_cast; - char *pathname; - bool is_directory; - u_int8_t delimiter; - pts_file_meta_t *metadata; - - attr_info = attr->get_value(attr); - attr_cast = (tcg_pts_attr_req_file_meta_t*)attr; - is_directory = attr_cast->get_directory_flag(attr_cast); - delimiter = attr_cast->get_delimiter(attr_cast); - pathname = attr_cast->get_pathname(attr_cast); - - valid_path = pts->is_path_valid(pts, pathname, &pts_error); - if (valid_path && pts_error) - { - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - pts_error, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - else if (!valid_path) - { - break; - } - if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF) - { - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_INVALID_DELIMITER, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - /* Get File Metadata and send them to PTS-IMV */ - DBG2(DBG_IMC, "metadata request for %s '%s'", - is_directory ? "directory" : "file", - pathname); - metadata = pts->get_metadata(pts, pathname, is_directory); - - if (!metadata) - { - /* TODO handle error codes from measurements */ - goto err; - } - attr = tcg_pts_attr_unix_file_meta_create(metadata); - attr->set_noskip_flag(attr, TRUE); - attr_list->insert_last(attr_list, attr); - - break; - } - case TCG_PTS_REQ_FILE_MEAS: - { - tcg_pts_attr_req_file_meas_t *attr_cast; - char *pathname; - u_int16_t request_id; - bool is_directory; - u_int32_t delimiter; - pts_file_meas_t *measurements; - - attr_info = attr->get_value(attr); - attr_cast = (tcg_pts_attr_req_file_meas_t*)attr; - is_directory = attr_cast->get_directory_flag(attr_cast); - request_id = attr_cast->get_request_id(attr_cast); - delimiter = attr_cast->get_delimiter(attr_cast); - pathname = attr_cast->get_pathname(attr_cast); - valid_path = pts->is_path_valid(pts, pathname, &pts_error); - - if (valid_path && pts_error) - { - attr_info = attr->get_value(attr); - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - pts_error, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - else if (!valid_path) - { - break; - } - - if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF) - { - attr_info = attr->get_value(attr); - attr = ietf_attr_pa_tnc_error_create(PEN_TCG, - TCG_PTS_INVALID_DELIMITER, attr_info); - attr_list->insert_last(attr_list, attr); - break; - } - - /* Do PTS File Measurements and send them to PTS-IMV */ - DBG2(DBG_IMC, "measurement request %d for %s '%s'", - request_id, is_directory ? "directory" : "file", - pathname); - measurements = pts->do_measurements(pts, request_id, - pathname, is_directory); - if (!measurements) - { - /* TODO handle error codes from measurements */ - goto err; - } - attr = tcg_pts_attr_file_meas_create(measurements); - attr->set_noskip_flag(attr, TRUE); - attr_list->insert_last(attr_list, attr); - break; - } - /* TODO: Not implemented yet */ - case TCG_PTS_REQ_INTEG_MEAS_LOG: - /* Attributes using XML */ - case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META: - case TCG_PTS_UPDATE_TEMPL_REF_MANI: - /* On Windows only*/ - case TCG_PTS_REQ_REGISTRY_VALUE: - /* Received on IMV side only*/ - case TCG_PTS_PROTO_CAPS: - case TCG_PTS_DH_NONCE_PARAMS_RESP: - case TCG_PTS_MEAS_ALGO_SELECTION: - case TCG_PTS_TPM_VERSION_INFO: - case TCG_PTS_TEMPL_REF_MANI_SET_META: - case TCG_PTS_AIK: - case TCG_PTS_SIMPLE_COMP_EVID: - case TCG_PTS_SIMPLE_EVID_FINAL: - case TCG_PTS_VERIFICATION_RESULT: - case TCG_PTS_INTEG_REPORT: - case TCG_PTS_UNIX_FILE_META: - case TCG_PTS_FILE_MEAS: - case TCG_PTS_INTEG_MEAS_LOG: - default: - DBG1(DBG_IMC, "received unsupported attribute '%N'", - tcg_attr_names, attr->get_type(attr)); - break; + result = TNC_RESULT_FATAL; + break; } } } enumerator->destroy(enumerator); pa_tnc_msg->destroy(pa_tnc_msg); - result = TNC_RESULT_SUCCESS; - - if (attr_list->get_count(attr_list)) + if (result == TNC_RESULT_SUCCESS && attr_list->get_count(attr_list)) { pa_tnc_msg = pa_tnc_msg_create(); @@ -899,12 +283,8 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id, pa_tnc_msg->destroy(pa_tnc_msg); } - DESTROY_IF(attr_list); + attr_list->destroy(attr_list); return result; - - err: - DESTROY_IF(attr_list); - return TNC_RESULT_FATAL; } /** diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation_process.c b/src/libimcv/plugins/imc_attestation/imc_attestation_process.c new file mode 100644 index 0000000000..7eb1797b01 --- /dev/null +++ b/src/libimcv/plugins/imc_attestation/imc_attestation_process.c @@ -0,0 +1,611 @@ +/* + * Copyright (C) 2011 Sansar Choinyambuu + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#define _GNU_SOURCE + +#include + +#include "imc_attestation_process.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DEFAULT_NONCE_LEN 20 +#define EXTEND_PCR 16 + +bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, + imc_attestation_state_t *attestation_state, + pts_meas_algorithms_t supported_algorithms, + pts_dh_group_t supported_dh_groups, + linked_list_t *evidences) +{ + chunk_t attr_info; + pts_t *pts; + pts_error_code_t pts_error; + bool valid_path; + + pts = attestation_state->get_pts(attestation_state); + switch (attr->get_type(attr)) + { + case TCG_PTS_REQ_PROTO_CAPS: + { + tcg_pts_attr_proto_caps_t *attr_cast; + pts_proto_caps_flag_t imc_caps, imv_caps; + + attr_cast = (tcg_pts_attr_proto_caps_t*)attr; + imv_caps = attr_cast->get_flags(attr_cast); + imc_caps = pts->get_proto_caps(pts); + pts->set_proto_caps(pts, imc_caps & imv_caps); + + /* Send PTS Protocol Capabilities attribute */ + attr = tcg_pts_attr_proto_caps_create(imc_caps & imv_caps, FALSE); + attr_list->insert_last(attr_list, attr); + break; + } + case TCG_PTS_MEAS_ALGO: + { + tcg_pts_attr_meas_algo_t *attr_cast; + pts_meas_algorithms_t offered_algorithms, selected_algorithm; + + attr_cast = (tcg_pts_attr_meas_algo_t*)attr; + offered_algorithms = attr_cast->get_algorithms(attr_cast); + selected_algorithm = pts_meas_algo_select(supported_algorithms, + offered_algorithms); + if (selected_algorithm == PTS_MEAS_ALGO_NONE) + { + attr = pts_hash_alg_error_create(supported_algorithms); + attr_list->insert_last(attr_list, attr); + break; + } + + /* Send Measurement Algorithm Selection attribute */ + pts->set_meas_algorithm(pts, selected_algorithm); + attr = tcg_pts_attr_meas_algo_create(selected_algorithm, TRUE); + attr_list->insert_last(attr_list, attr); + break; + } + case TCG_PTS_DH_NONCE_PARAMS_REQ: + { + tcg_pts_attr_dh_nonce_params_req_t *attr_cast; + pts_dh_group_t offered_dh_groups, selected_dh_group; + chunk_t responder_value, responder_nonce; + int nonce_len, min_nonce_len; + + nonce_len = lib->settings->get_int(lib->settings, + "libimcv.plugins.imc-attestation.nonce_len", + DEFAULT_NONCE_LEN); + + attr_cast = (tcg_pts_attr_dh_nonce_params_req_t*)attr; + min_nonce_len = attr_cast->get_min_nonce_len(attr_cast); + if (min_nonce_len > 0 && nonce_len < min_nonce_len) + { + attr_info = attr->get_value(attr); + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_BAD_NONCE_LENGTH, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + + offered_dh_groups = attr_cast->get_dh_groups(attr_cast); + selected_dh_group = pts_dh_group_select(supported_dh_groups, + offered_dh_groups); + if (selected_dh_group == PTS_DH_GROUP_NONE) + { + attr_info = attr->get_value(attr); + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_DH_GRPS_NOT_SUPPORTED, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + + /* Create own DH factor and nonce */ + if (!pts->create_dh_nonce(pts, selected_dh_group, nonce_len)) + { + return FALSE; + } + pts->get_my_public_value(pts, &responder_value, &responder_nonce); + + /* Send DH Nonce Parameters Response attribute */ + attr = tcg_pts_attr_dh_nonce_params_resp_create(selected_dh_group, + supported_algorithms, responder_nonce, responder_value); + attr_list->insert_last(attr_list, attr); + break; + } + case TCG_PTS_DH_NONCE_FINISH: + { + tcg_pts_attr_dh_nonce_finish_t *attr_cast; + pts_meas_algorithms_t selected_algorithm; + chunk_t initiator_nonce, initiator_value; + int nonce_len; + + attr_cast = (tcg_pts_attr_dh_nonce_finish_t*)attr; + selected_algorithm = attr_cast->get_hash_algo(attr_cast); + if (!(selected_algorithm & supported_algorithms)) + { + DBG1(DBG_IMC, "PTS-IMV selected unsupported DH hash algorithm"); + return TNC_RESULT_FATAL; + } + pts->set_dh_hash_algorithm(pts, selected_algorithm); + + initiator_value = attr_cast->get_initiator_value(attr_cast); + initiator_nonce = attr_cast->get_initiator_nonce(attr_cast); + nonce_len = initiator_nonce.len; + if (nonce_len <= 16) /* TODO */ + { + attr_info = attr->get_value(attr); + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_BAD_NONCE_LENGTH, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + + pts->set_peer_public_value(pts, initiator_value, initiator_nonce); + if (!pts->calculate_secret(pts)) + { + return FALSE; + } + break; + } + case TCG_PTS_GET_TPM_VERSION_INFO: + { + chunk_t tpm_version_info, attr_info; + + if (!pts->get_tpm_version_info(pts, &tpm_version_info)) + { + attr_info = attr->get_value(attr); + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_TPM_VERS_NOT_SUPPORTED, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + + /* Send TPM Version Info attribute */ + attr = tcg_pts_attr_tpm_version_info_create(tpm_version_info); + attr_list->insert_last(attr_list, attr); + break; + } + case TCG_PTS_GET_AIK: + { + certificate_t *aik; + + aik = pts->get_aik(pts); + if (!aik) + { + DBG1(DBG_IMC, "no AIK certificate or public key available"); + break; + } + + /* Send AIK attribute */ + attr = tcg_pts_attr_aik_create(aik); + attr_list->insert_last(attr_list, attr); + break; + } + case TCG_PTS_REQ_FUNCT_COMP_EVID: + { + tcg_pts_attr_req_funct_comp_evid_t *attr_cast; + pts_proto_caps_flag_t negotiated_caps; + pts_attr_req_funct_comp_evid_flag_t flags; + u_int32_t sub_comp_depth; + u_int32_t comp_name_vendor_id; + u_int8_t family; + pts_qualifier_t qualifier; + pts_funct_comp_name_t name; + + attr_info = attr->get_value(attr); + attr_cast = (tcg_pts_attr_req_funct_comp_evid_t*)attr; + negotiated_caps = pts->get_proto_caps(pts); + flags = attr_cast->get_flags(attr_cast); + + if (flags & PTS_REQ_FUNC_COMP_FLAG_TTC) + { + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_UNABLE_DET_TTC, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + if (flags & PTS_REQ_FUNC_COMP_FLAG_VER && + !(negotiated_caps & PTS_PROTO_CAPS_V)) + { + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_UNABLE_LOCAL_VAL, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + if (flags & PTS_REQ_FUNC_COMP_FLAG_CURR && + !(negotiated_caps & PTS_PROTO_CAPS_C)) + { + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_UNABLE_CUR_EVID, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + if (flags & PTS_REQ_FUNC_COMP_FLAG_PCR && + !(negotiated_caps & PTS_PROTO_CAPS_T)) + { + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_UNABLE_DET_PCR, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + + sub_comp_depth = attr_cast->get_sub_component_depth(attr_cast); + /* TODO: Implement checking of components with its sub-components */ + if (sub_comp_depth != 0) + { + DBG1(DBG_IMC, "current version of Attestation IMC does not support" + "sub component measurement deeper than zero. " + "Measuring top level component only."); + } + + comp_name_vendor_id = attr_cast->get_comp_funct_name_vendor_id(attr_cast); + if (comp_name_vendor_id != PEN_TCG) + { + DBG1(DBG_IMC, "current version of Attestation IMC supports" + "only functional component namings by TCG "); + break; + } + + family = attr_cast->get_family(attr_cast); + if (family) + { + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_INVALID_NAME_FAM, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + + qualifier = attr_cast->get_qualifier(attr_cast); + + /* Check if Unknown or Wildcard was set for qualifier */ + if (qualifier.kernel && qualifier.sub_component && + (qualifier.type & PTS_FUNC_COMP_TYPE_ALL)) + { + DBG2(DBG_IMC, "wildcard was set for the qualifier of functional" + " component. Identifying the component with name binary enumeration"); + } + else if (!qualifier.kernel && !qualifier.sub_component && + (qualifier.type & PTS_FUNC_COMP_TYPE_UNKNOWN)) + { + DBG2(DBG_IMC, "unknown was set for the qualifier of functional" + " component. Identifying the component with name binary enumeration"); + } + else + { + /* TODO: Implement what todo with received qualifier */ + } + + name = attr_cast->get_comp_funct_name(attr_cast); + switch (name) + { + case PTS_FUNC_COMP_NAME_BIOS: + { + tcg_pts_attr_simple_comp_evid_params_t params; + pts_qualifier_t qualifier; + time_t measurement_time_t; + struct tm *time_now; + char *utc_time; + hasher_t *hasher; + u_char hash_output[HASH_SIZE_SHA384]; + hash_algorithm_t hash_alg; + + /* TODO: Implement BIOS measurement */ + DBG1(DBG_IMC, "experimental implementation:" + " Extend TPM with etc/tnc_config file"); + + params.flags = PTS_SIMPLE_COMP_EVID_FLAG_PCR | PTS_SIMPLE_COMP_EVID_FLAG_NO_VALID; + params.depth = 0; + params.vendor_id = PEN_TCG; + + qualifier.kernel = FALSE; + qualifier.sub_component = FALSE; + qualifier.type = PTS_FUNC_COMP_TYPE_TNC; + params.qualifier = qualifier; + + params.name = PTS_FUNC_COMP_NAME_BIOS; + params.extended_pcr = EXTEND_PCR; + params.hash_algorithm = pts->get_meas_algorithm(pts); + + if (!(params.flags & PTS_SIMPLE_COMP_EVID_FLAG_PCR)) + { + params.transformation = PTS_PCR_TRANSFORM_NO; + } + else if (pts->get_meas_algorithm(pts) & PTS_MEAS_ALGO_SHA1) + { + params.transformation = PTS_PCR_TRANSFORM_MATCH; + } + else if (pts->get_meas_algorithm(pts) & PTS_MEAS_ALGO_SHA256) + { + params.transformation = PTS_PCR_TRANSFORM_LONG; + } + + /* Create a hasher */ + hash_alg = pts_meas_algo_to_hash(pts->get_meas_algorithm(pts)); + hasher = lib->crypto->create_hasher(lib->crypto, hash_alg); + if (!hasher) + { + DBG1(DBG_IMC, " hasher %N not available", + hash_algorithm_names, hash_alg); + return FALSE; + } + + if (!pts->hash_file(pts, hasher, "/etc/tnc_config", hash_output)) + { + hasher->destroy(hasher); + return FALSE; + } + + measurement_time_t = time(NULL); + if (!measurement_time_t) + { + params.measurement_time = chunk_create("0000-00-00T00:00:00Z", 20); + } + else + { + time_now = localtime(&measurement_time_t); + if (asprintf(&utc_time, "%d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2dZ", + time_now->tm_year + 1900, + time_now->tm_mon + 1, + time_now->tm_mday, + time_now->tm_hour, + time_now->tm_min, + time_now->tm_sec) < 0) + { + DBG1(DBG_IMC, "could not format local time to UTC"); + hasher->destroy(hasher); + return FALSE; + } + params.measurement_time = chunk_create(utc_time, 20); + params.measurement_time = chunk_clone(params.measurement_time); + free(utc_time); + + } + + params.measurement = chunk_create(hash_output, hasher->get_hash_size(hasher)); + hasher->destroy(hasher); + + params.policy_uri = chunk_empty; + if (!pts->read_pcr(pts, EXTEND_PCR, ¶ms.pcr_before)) + { + DBG1(DBG_IMC, "error occured while reading PCR: %d", EXTEND_PCR); + return FALSE; + } + + if (!pts->extend_pcr(pts, EXTEND_PCR, + params.measurement, ¶ms.pcr_after)) + { + DBG1(DBG_IMC, "error occured while extending PCR: %d", EXTEND_PCR); + return FALSE; + } + + /* Buffer Simple Component Evidence attribute */ + attr = tcg_pts_attr_simple_comp_evid_create(params); + evidences->insert_last(evidences, attr); + + break; + } + case PTS_FUNC_COMP_NAME_IGNORE: + case PTS_FUNC_COMP_NAME_CRTM: + case PTS_FUNC_COMP_NAME_PLATFORM_EXT: + case PTS_FUNC_COMP_NAME_BOARD: + case PTS_FUNC_COMP_NAME_INIT_LOADER: + case PTS_FUNC_COMP_NAME_OPT_ROMS: + default: + { + DBG1(DBG_IMC, "unsupported Functional Component Name"); + break; + } + } + break; + } + case TCG_PTS_GEN_ATTEST_EVID: + { + enumerator_t *e; + pts_simple_evid_final_flag_t flags; + chunk_t pcr_composite, quote_signature; + linked_list_t *pcrs; + + /* Send buffered Simple Component Evidences */ + pcrs = linked_list_create(); + + e = evidences->create_enumerator(evidences); + while (e->enumerate(e, &attr)) + { + tcg_pts_attr_simple_comp_evid_t *attr_cast; + u_int32_t extended_pcr; + + attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr; + extended_pcr = attr_cast->get_extended_pcr(attr_cast); + + /* Add extended PCR number to PCR list to quote */ + /* Duplicated PCR numbers have no influence */ + pcrs->insert_last(pcrs, &extended_pcr); + /* Send Simple Compoenent Evidence */ + attr_list->insert_last(attr_list, attr); + } + + /* Quote */ + if (!pts->quote_tpm(pts, pcrs, &pcr_composite, "e_signature)) + { + DBG1(DBG_IMC, "error occured while TPM quote operation"); + DESTROY_IF(e); + DESTROY_IF(pcrs); + DESTROY_IF(evidences); + return FALSE; + } + + /* Send Simple Evidence Final attribute */ + flags = PTS_SIMPLE_EVID_FINAL_FLAG_TPM_QUOTE_INFO; + + attr = tcg_pts_attr_simple_evid_final_create(flags, 0, + pcr_composite, quote_signature, chunk_empty); + attr_list->insert_last(attr_list, attr); + + DESTROY_IF(e); + DESTROY_IF(pcrs); + DESTROY_IF(evidences); + + break; + } + case TCG_PTS_REQ_FILE_META: + { + tcg_pts_attr_req_file_meta_t *attr_cast; + char *pathname; + bool is_directory; + u_int8_t delimiter; + pts_file_meta_t *metadata; + + attr_info = attr->get_value(attr); + attr_cast = (tcg_pts_attr_req_file_meta_t*)attr; + is_directory = attr_cast->get_directory_flag(attr_cast); + delimiter = attr_cast->get_delimiter(attr_cast); + pathname = attr_cast->get_pathname(attr_cast); + + valid_path = pts->is_path_valid(pts, pathname, &pts_error); + if (valid_path && pts_error) + { + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + pts_error, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + else if (!valid_path) + { + break; + } + if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF) + { + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_INVALID_DELIMITER, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + /* Get File Metadata and send them to PTS-IMV */ + DBG2(DBG_IMC, "metadata request for %s '%s'", + is_directory ? "directory" : "file", + pathname); + metadata = pts->get_metadata(pts, pathname, is_directory); + + if (!metadata) + { + /* TODO handle error codes from measurements */ + return FALSE; + } + attr = tcg_pts_attr_unix_file_meta_create(metadata); + attr->set_noskip_flag(attr, TRUE); + attr_list->insert_last(attr_list, attr); + + break; + } + case TCG_PTS_REQ_FILE_MEAS: + { + tcg_pts_attr_req_file_meas_t *attr_cast; + char *pathname; + u_int16_t request_id; + bool is_directory; + u_int32_t delimiter; + pts_file_meas_t *measurements; + + attr_info = attr->get_value(attr); + attr_cast = (tcg_pts_attr_req_file_meas_t*)attr; + is_directory = attr_cast->get_directory_flag(attr_cast); + request_id = attr_cast->get_request_id(attr_cast); + delimiter = attr_cast->get_delimiter(attr_cast); + pathname = attr_cast->get_pathname(attr_cast); + valid_path = pts->is_path_valid(pts, pathname, &pts_error); + + if (valid_path && pts_error) + { + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + pts_error, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + else if (!valid_path) + { + break; + } + + if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF) + { + attr = ietf_attr_pa_tnc_error_create(PEN_TCG, + TCG_PTS_INVALID_DELIMITER, attr_info); + attr_list->insert_last(attr_list, attr); + break; + } + + /* Do PTS File Measurements and send them to PTS-IMV */ + DBG2(DBG_IMC, "measurement request %d for %s '%s'", + request_id, is_directory ? "directory" : "file", + pathname); + measurements = pts->do_measurements(pts, request_id, + pathname, is_directory); + if (!measurements) + { + /* TODO handle error codes from measurements */ + return FALSE; + } + attr = tcg_pts_attr_file_meas_create(measurements); + attr->set_noskip_flag(attr, TRUE); + attr_list->insert_last(attr_list, attr); + break; + } + /* TODO: Not implemented yet */ + case TCG_PTS_REQ_INTEG_MEAS_LOG: + /* Attributes using XML */ + case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META: + case TCG_PTS_UPDATE_TEMPL_REF_MANI: + /* On Windows only*/ + case TCG_PTS_REQ_REGISTRY_VALUE: + /* Received on IMV side only*/ + case TCG_PTS_PROTO_CAPS: + case TCG_PTS_DH_NONCE_PARAMS_RESP: + case TCG_PTS_MEAS_ALGO_SELECTION: + case TCG_PTS_TPM_VERSION_INFO: + case TCG_PTS_TEMPL_REF_MANI_SET_META: + case TCG_PTS_AIK: + case TCG_PTS_SIMPLE_COMP_EVID: + case TCG_PTS_SIMPLE_EVID_FINAL: + case TCG_PTS_VERIFICATION_RESULT: + case TCG_PTS_INTEG_REPORT: + case TCG_PTS_UNIX_FILE_META: + case TCG_PTS_FILE_MEAS: + case TCG_PTS_INTEG_MEAS_LOG: + default: + DBG1(DBG_IMC, "received unsupported attribute '%N'", + tcg_attr_names, attr->get_type(attr)); + break; + } + return TRUE; +} diff --git a/src/libimcv/plugins/imc_attestation/imc_attestation_process.h b/src/libimcv/plugins/imc_attestation/imc_attestation_process.h new file mode 100644 index 0000000000..d2d4447164 --- /dev/null +++ b/src/libimcv/plugins/imc_attestation/imc_attestation_process.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 Sansar Choinyambuu + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * + * @defgroup imc_attestation_process_t imc_attestation_process + * @{ @ingroup imc_attestation_process + */ + +#ifndef IMC_ATTESTATION_PROCESS_H_ +#define IMC_ATTESTATION_PROCESS_H_ + +#include "imc_attestation_state.h" + +#include +#include + +#include + +#include +#include + +/** + * Process a TCG PTS attribute + * + * @param attr PA-TNC attribute to be processed + * @param attr_list list with PA-TNC error attributes + * @param attestation_state attestation state of a given connection + * @param supported_algorithms supported PTS measurement algorithms + * @param supported_dh_groups supported DH groups + * @param evidences evidence + * @return TRUE if successful + */ +bool imc_attestation_process(pa_tnc_attr_t *attr, linked_list_t *attr_list, + imc_attestation_state_t *attestation_state, + pts_meas_algorithms_t supported_algorithms, + pts_dh_group_t supported_dh_groups, + linked_list_t *evidences); + +#endif /** IMC_ATTESTATION_PROCESS_H_ @}*/