Merged libpts into libimcv
This commit is contained in:
+53
-1
@@ -41,7 +41,59 @@ libimcv_la_SOURCES := \
|
||||
os_info/os_info.h os_info/os_info.c \
|
||||
pa_tnc/pa_tnc_attr.h \
|
||||
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
|
||||
pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
|
||||
pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c \
|
||||
pts/pts.h pts/pts.c \
|
||||
pts/pts_error.h pts/pts_error.c \
|
||||
pts/pts_pcr.h pts/pts_pcr.c \
|
||||
pts/pts_proto_caps.h \
|
||||
pts/pts_req_func_comp_evid.h \
|
||||
pts/pts_simple_evid_final.h \
|
||||
pts/pts_creds.h pts/pts_creds.c \
|
||||
pts/pts_database.h pts/pts_database.c \
|
||||
pts/pts_dh_group.h pts/pts_dh_group.c \
|
||||
pts/pts_file_meas.h pts/pts_file_meas.c \
|
||||
pts/pts_file_meta.h pts/pts_file_meta.c \
|
||||
pts/pts_file_type.h pts/pts_file_type.c \
|
||||
pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
|
||||
pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
|
||||
pts/pts_meas_algo.h pts/pts_meas_algo.c \
|
||||
pts/components/pts_component.h \
|
||||
pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
|
||||
pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
|
||||
pts/components/pts_comp_func_name.h pts/components/pts_comp_func_name.c \
|
||||
pts/components/ita/ita_comp_func_name.h pts/components/ita/ita_comp_func_name.c \
|
||||
pts/components/ita/ita_comp_ima.h pts/components/ita/ita_comp_ima.c \
|
||||
pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
|
||||
pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
|
||||
pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
|
||||
seg/seg_contract.h seg/seg_contract.c \
|
||||
seg/seg_contract_manager.h seg/seg_contract_manager.c \
|
||||
seg/seg_env.h seg/seg_env.c \
|
||||
swid/swid_error.h swid/swid_error.c \
|
||||
swid/swid_inventory.h swid/swid_inventory.c \
|
||||
swid/swid_tag.h swid/swid_tag.c \
|
||||
swid/swid_tag_id.h swid/swid_tag_id.c \
|
||||
tcg/tcg_attr.h tcg/tcg_attr.c \
|
||||
tcg/pts/tcg_pts_attr_proto_caps.h tcg/pts/tcg_pts_attr_proto_caps.c \
|
||||
tcg/pts/tcg_pts_attr_dh_nonce_params_req.h tcg/pts/tcg_pts_attr_dh_nonce_params_req.c \
|
||||
tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c \
|
||||
tcg/pts/tcg_pts_attr_dh_nonce_finish.h tcg/pts/tcg_pts_attr_dh_nonce_finish.c \
|
||||
tcg/pts/tcg_pts_attr_meas_algo.h tcg/pts/tcg_pts_attr_meas_algo.c \
|
||||
tcg/pts/tcg_pts_attr_get_tpm_version_info.h tcg/pts/tcg_pts_attr_get_tpm_version_info.c \
|
||||
tcg/pts/tcg_pts_attr_tpm_version_info.h tcg/pts/tcg_pts_attr_tpm_version_info.c \
|
||||
tcg/pts/tcg_pts_attr_get_aik.h tcg/pts/tcg_pts_attr_get_aik.c \
|
||||
tcg/pts/tcg_pts_attr_aik.h tcg/pts/tcg_pts_attr_aik.c \
|
||||
tcg/pts/tcg_pts_attr_req_func_comp_evid.h tcg/pts/tcg_pts_attr_req_func_comp_evid.c \
|
||||
tcg/pts/tcg_pts_attr_gen_attest_evid.h tcg/pts/tcg_pts_attr_gen_attest_evid.c \
|
||||
tcg/pts/tcg_pts_attr_simple_comp_evid.h tcg/pts/tcg_pts_attr_simple_comp_evid.c \
|
||||
tcg/pts/tcg_pts_attr_simple_evid_final.h tcg/pts/tcg_pts_attr_simple_evid_final.c \
|
||||
tcg/pts/tcg_pts_attr_req_file_meas.h tcg/pts/tcg_pts_attr_req_file_meas.c \
|
||||
tcg/pts/tcg_pts_attr_file_meas.h tcg/pts/tcg_pts_attr_file_meas.c \
|
||||
tcg/pts/tcg_pts_attr_req_file_meta.h tcg/pts/tcg_pts_attr_req_file_meta.c \
|
||||
tcg/pts/tcg_pts_attr_unix_file_meta.h tcg/pts/tcg_pts_attr_unix_file_meta.c \
|
||||
tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
|
||||
tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
|
||||
tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
|
||||
|
||||
LOCAL_SRC_FILES := $(filter %.c,$(libimcv_la_SOURCES))
|
||||
|
||||
|
||||
+73
-1
@@ -12,6 +12,10 @@ libimcv_la_LIBADD = \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la \
|
||||
$(top_builddir)/src/libtncif/libtncif.la
|
||||
|
||||
if USE_TROUSERS
|
||||
libimcv_la_LIBADD += -ltspi
|
||||
endif
|
||||
|
||||
if USE_WINDOWS
|
||||
libimcv_la_LIBADD += -lws2_32
|
||||
endif
|
||||
@@ -56,9 +60,61 @@ libimcv_la_SOURCES = \
|
||||
pa_tnc/pa_tnc_attr.h \
|
||||
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
|
||||
pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c \
|
||||
pts/pts.h pts/pts.c \
|
||||
pts/pts_error.h pts/pts_error.c \
|
||||
pts/pts_pcr.h pts/pts_pcr.c \
|
||||
pts/pts_proto_caps.h \
|
||||
pts/pts_req_func_comp_evid.h \
|
||||
pts/pts_simple_evid_final.h \
|
||||
pts/pts_creds.h pts/pts_creds.c \
|
||||
pts/pts_database.h pts/pts_database.c \
|
||||
pts/pts_dh_group.h pts/pts_dh_group.c \
|
||||
pts/pts_file_meas.h pts/pts_file_meas.c \
|
||||
pts/pts_file_meta.h pts/pts_file_meta.c \
|
||||
pts/pts_file_type.h pts/pts_file_type.c \
|
||||
pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
|
||||
pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
|
||||
pts/pts_meas_algo.h pts/pts_meas_algo.c \
|
||||
pts/components/pts_component.h \
|
||||
pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
|
||||
pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
|
||||
pts/components/pts_comp_func_name.h pts/components/pts_comp_func_name.c \
|
||||
pts/components/ita/ita_comp_func_name.h pts/components/ita/ita_comp_func_name.c \
|
||||
pts/components/ita/ita_comp_ima.h pts/components/ita/ita_comp_ima.c \
|
||||
pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
|
||||
pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
|
||||
pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
|
||||
seg/seg_contract.h seg/seg_contract.c \
|
||||
seg/seg_contract_manager.h seg/seg_contract_manager.c \
|
||||
seg/seg_env.h seg/seg_env.c
|
||||
seg/seg_env.h seg/seg_env.c \
|
||||
swid/swid_error.h swid/swid_error.c \
|
||||
swid/swid_inventory.h swid/swid_inventory.c \
|
||||
swid/swid_tag.h swid/swid_tag.c \
|
||||
swid/swid_tag_id.h swid/swid_tag_id.c \
|
||||
tcg/tcg_attr.h tcg/tcg_attr.c \
|
||||
tcg/pts/tcg_pts_attr_proto_caps.h tcg/pts/tcg_pts_attr_proto_caps.c \
|
||||
tcg/pts/tcg_pts_attr_dh_nonce_params_req.h tcg/pts/tcg_pts_attr_dh_nonce_params_req.c \
|
||||
tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h tcg/pts/tcg_pts_attr_dh_nonce_params_resp.c \
|
||||
tcg/pts/tcg_pts_attr_dh_nonce_finish.h tcg/pts/tcg_pts_attr_dh_nonce_finish.c \
|
||||
tcg/pts/tcg_pts_attr_meas_algo.h tcg/pts/tcg_pts_attr_meas_algo.c \
|
||||
tcg/pts/tcg_pts_attr_get_tpm_version_info.h tcg/pts/tcg_pts_attr_get_tpm_version_info.c \
|
||||
tcg/pts/tcg_pts_attr_tpm_version_info.h tcg/pts/tcg_pts_attr_tpm_version_info.c \
|
||||
tcg/pts/tcg_pts_attr_get_aik.h tcg/pts/tcg_pts_attr_get_aik.c \
|
||||
tcg/pts/tcg_pts_attr_aik.h tcg/pts/tcg_pts_attr_aik.c \
|
||||
tcg/pts/tcg_pts_attr_req_func_comp_evid.h tcg/pts/tcg_pts_attr_req_func_comp_evid.c \
|
||||
tcg/pts/tcg_pts_attr_gen_attest_evid.h tcg/pts/tcg_pts_attr_gen_attest_evid.c \
|
||||
tcg/pts/tcg_pts_attr_simple_comp_evid.h tcg/pts/tcg_pts_attr_simple_comp_evid.c \
|
||||
tcg/pts/tcg_pts_attr_simple_evid_final.h tcg/pts/tcg_pts_attr_simple_evid_final.c \
|
||||
tcg/pts/tcg_pts_attr_req_file_meas.h tcg/pts/tcg_pts_attr_req_file_meas.c \
|
||||
tcg/pts/tcg_pts_attr_file_meas.h tcg/pts/tcg_pts_attr_file_meas.c \
|
||||
tcg/pts/tcg_pts_attr_req_file_meta.h tcg/pts/tcg_pts_attr_req_file_meta.c \
|
||||
tcg/pts/tcg_pts_attr_unix_file_meta.h tcg/pts/tcg_pts_attr_unix_file_meta.c \
|
||||
tcg/seg/tcg_seg_attr_max_size.h tcg/seg/tcg_seg_attr_max_size.c \
|
||||
tcg/seg/tcg_seg_attr_seg_env.h tcg/seg/tcg_seg_attr_seg_env.c \
|
||||
tcg/seg/tcg_seg_attr_next_seg.h tcg/seg/tcg_seg_attr_next_seg.c \
|
||||
tcg/swid/tcg_swid_attr_req.h tcg/swid/tcg_swid_attr_req.c \
|
||||
tcg/swid/tcg_swid_attr_tag_id_inv.h tcg/swid/tcg_swid_attr_tag_id_inv.c \
|
||||
tcg/swid/tcg_swid_attr_tag_inv.h tcg/swid/tcg_swid_attr_tag_inv.c
|
||||
|
||||
ipsec_SCRIPTS = imv/_imv_policy
|
||||
EXTRA_DIST = imv/_imv_policy Android.mk
|
||||
@@ -99,3 +155,19 @@ endif
|
||||
if USE_IMV_OS
|
||||
SUBDIRS += plugins/imv_os
|
||||
endif
|
||||
|
||||
if USE_IMC_ATTESTATION
|
||||
SUBDIRS += plugins/imc_attestation
|
||||
endif
|
||||
|
||||
if USE_IMV_ATTESTATION
|
||||
SUBDIRS += plugins/imv_attestation
|
||||
endif
|
||||
|
||||
if USE_IMC_SWID
|
||||
SUBDIRS += plugins/imc_swid
|
||||
endif
|
||||
|
||||
if USE_IMV_SWID
|
||||
SUBDIRS += plugins/imv_swid
|
||||
endif
|
||||
|
||||
@@ -18,14 +18,13 @@
|
||||
#include "ietf/ietf_attr.h"
|
||||
#include "ietf/ietf_attr_assess_result.h"
|
||||
#include "ietf/ietf_attr_remediation_instr.h"
|
||||
#include "tcg/seg/tcg_seg_attr_max_size.h"
|
||||
#include "tcg/seg/tcg_seg_attr_seg_env.h"
|
||||
#include "tcg/seg/tcg_seg_attr_next_seg.h"
|
||||
|
||||
#include <tncif_names.h>
|
||||
#include <tncif_pa_subtypes.h>
|
||||
|
||||
#include <tcg/seg/tcg_seg_attr_max_size.h>
|
||||
#include <tcg/seg/tcg_seg_attr_seg_env.h>
|
||||
#include <tcg/seg/tcg_seg_attr_next_seg.h>
|
||||
|
||||
#include <pen/pen.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
@@ -15,6 +15,14 @@
|
||||
#include "imcv.h"
|
||||
#include "ietf/ietf_attr.h"
|
||||
#include "ita/ita_attr.h"
|
||||
#include "tcg/tcg_attr.h"
|
||||
#include "pts/components/pts_component.h"
|
||||
#include "pts/components/pts_component_manager.h"
|
||||
#include "pts/components/tcg/tcg_comp_func_name.h"
|
||||
#include "pts/components/ita/ita_comp_func_name.h"
|
||||
#include "pts/components/ita/ita_comp_ima.h"
|
||||
#include "pts/components/ita/ita_comp_tboot.h"
|
||||
#include "pts/components/ita/ita_comp_tgrub.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <utils/utils.h>
|
||||
@@ -43,6 +51,11 @@ imv_session_manager_t *imcv_sessions;
|
||||
*/
|
||||
imv_database_t *imcv_db;
|
||||
|
||||
/**
|
||||
* PTS Functional Component manager
|
||||
*/
|
||||
pts_component_manager_t *imcv_pts_components;
|
||||
|
||||
/**
|
||||
* Reference count for libimcv
|
||||
*/
|
||||
@@ -162,7 +175,26 @@ bool libimcv_init(bool is_imv)
|
||||
ietf_attr_create_from_data, ietf_attr_names);
|
||||
imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_ITA,
|
||||
ita_attr_create_from_data, ita_attr_names);
|
||||
imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_TCG,
|
||||
tcg_attr_create_from_data, tcg_attr_names);
|
||||
|
||||
imcv_pts_components = pts_component_manager_create();
|
||||
imcv_pts_components->add_vendor(imcv_pts_components, PEN_TCG,
|
||||
pts_tcg_comp_func_names, PTS_TCG_QUALIFIER_TYPE_SIZE,
|
||||
pts_tcg_qualifier_flag_names, pts_tcg_qualifier_type_names);
|
||||
imcv_pts_components->add_vendor(imcv_pts_components, PEN_ITA,
|
||||
pts_ita_comp_func_names, PTS_ITA_QUALIFIER_TYPE_SIZE,
|
||||
pts_ita_qualifier_flag_names, pts_ita_qualifier_type_names);
|
||||
|
||||
imcv_pts_components->add_component(imcv_pts_components, PEN_ITA,
|
||||
PTS_ITA_COMP_FUNC_NAME_TGRUB,
|
||||
pts_ita_comp_tgrub_create);
|
||||
imcv_pts_components->add_component(imcv_pts_components, PEN_ITA,
|
||||
PTS_ITA_COMP_FUNC_NAME_TBOOT,
|
||||
pts_ita_comp_tboot_create);
|
||||
imcv_pts_components->add_component(imcv_pts_components, PEN_ITA,
|
||||
PTS_ITA_COMP_FUNC_NAME_IMA,
|
||||
pts_ita_comp_ima_create);
|
||||
if (is_imv)
|
||||
{
|
||||
/* instantiate global IMV session manager */
|
||||
@@ -193,8 +225,13 @@ void libimcv_deinit(void)
|
||||
{
|
||||
if (ref_put(&libimcv_ref))
|
||||
{
|
||||
imcv_pts_components->remove_vendor(imcv_pts_components, PEN_TCG);
|
||||
imcv_pts_components->remove_vendor(imcv_pts_components, PEN_ITA);
|
||||
imcv_pts_components->destroy(imcv_pts_components);
|
||||
|
||||
imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_IETF);
|
||||
imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_ITA);
|
||||
imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_TCG);
|
||||
DESTROY_IF(imcv_pa_tnc_attributes);
|
||||
imcv_pa_tnc_attributes = NULL;
|
||||
DESTROY_IF(imcv_db);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "pa_tnc/pa_tnc_attr_manager.h"
|
||||
#include "imv/imv_database.h"
|
||||
#include "imv/imv_session_manager.h"
|
||||
#include "pts/components/pts_component_manager.h"
|
||||
|
||||
#include <library.h>
|
||||
|
||||
@@ -68,4 +69,9 @@ extern imv_database_t* imcv_db;
|
||||
*/
|
||||
extern imv_session_manager_t* imcv_sessions;
|
||||
|
||||
/**
|
||||
* PTS Functional Component manager
|
||||
*/
|
||||
extern pts_component_manager_t* imcv_pts_components;
|
||||
|
||||
#endif /** IMCV_H_ @}*/
|
||||
|
||||
@@ -18,14 +18,13 @@
|
||||
#include "ietf/ietf_attr.h"
|
||||
#include "ietf/ietf_attr_assess_result.h"
|
||||
#include "ietf/ietf_attr_remediation_instr.h"
|
||||
#include "tcg/seg/tcg_seg_attr_max_size.h"
|
||||
#include "tcg/seg/tcg_seg_attr_seg_env.h"
|
||||
#include "tcg/seg/tcg_seg_attr_next_seg.h"
|
||||
|
||||
#include <tncif_names.h>
|
||||
#include <tncif_pa_subtypes.h>
|
||||
|
||||
#include <tcg/seg/tcg_seg_attr_max_size.h>
|
||||
#include <tcg/seg/tcg_seg_attr_seg_env.h>
|
||||
#include <tcg/seg/tcg_seg_attr_next_seg.h>
|
||||
|
||||
#include <pen/pen.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-I$(top_srcdir)/src/libtncif \
|
||||
-I$(top_srcdir)/src/libimcv
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(PLUGIN_CFLAGS)
|
||||
|
||||
imcv_LTLIBRARIES = imc-attestation.la
|
||||
|
||||
imc_attestation_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||
|
||||
imc_attestation_la_SOURCES = imc_attestation.c \
|
||||
imc_attestation_state.h imc_attestation_state.c \
|
||||
imc_attestation_process.h imc_attestation_process.c
|
||||
|
||||
imc_attestation_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imc_attestation_state.h"
|
||||
#include "imc_attestation_process.h"
|
||||
|
||||
#include <imc/imc_agent.h>
|
||||
#include <imc/imc_msg.h>
|
||||
#include <ietf/ietf_attr.h>
|
||||
#include <ietf/ietf_attr_pa_tnc_error.h>
|
||||
#include <ietf/ietf_attr_product_info.h>
|
||||
#include <ietf/ietf_attr_string_version.h>
|
||||
#include <ietf/ietf_attr_assess_result.h>
|
||||
#include <tcg/pts/tcg_pts_attr_proto_caps.h>
|
||||
#include <tcg/pts/tcg_pts_attr_meas_algo.h>
|
||||
#include <os_info/os_info.h>
|
||||
#include <pts/pts_error.h>
|
||||
|
||||
#include <tncif_pa_subtypes.h>
|
||||
|
||||
#include <pen/pen.h>
|
||||
#include <utils/debug.h>
|
||||
#include <collections/linked_list.h>
|
||||
|
||||
/* IMC definitions */
|
||||
|
||||
static const char imc_name[] = "Attestation";
|
||||
|
||||
static pen_type_t msg_types[] = {
|
||||
{ PEN_TCG, PA_SUBTYPE_TCG_PTS }
|
||||
};
|
||||
|
||||
static imc_agent_t *imc_attestation;
|
||||
|
||||
/**
|
||||
* Supported PTS measurement algorithms
|
||||
*/
|
||||
static pts_meas_algorithms_t supported_algorithms = PTS_MEAS_ALGO_NONE;
|
||||
|
||||
/**
|
||||
* Supported PTS Diffie Hellman Groups
|
||||
*/
|
||||
static pts_dh_group_t supported_dh_groups = PTS_DH_GROUP_NONE;
|
||||
|
||||
/**
|
||||
* see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id,
|
||||
TNC_Version min_version,
|
||||
TNC_Version max_version,
|
||||
TNC_Version *actual_version)
|
||||
{
|
||||
bool mandatory_dh_groups;
|
||||
|
||||
if (imc_attestation)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
|
||||
return TNC_RESULT_ALREADY_INITIALIZED;
|
||||
}
|
||||
imc_attestation = imc_agent_create(imc_name, msg_types, countof(msg_types),
|
||||
imc_id, actual_version);
|
||||
if (!imc_attestation)
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
|
||||
mandatory_dh_groups = lib->settings->get_bool(lib->settings,
|
||||
"%s.plugins.imc-attestation.mandatory_dh_groups", TRUE, lib->ns);
|
||||
|
||||
if (!pts_meas_algo_probe(&supported_algorithms) ||
|
||||
!pts_dh_group_probe(&supported_dh_groups, mandatory_dh_groups))
|
||||
{
|
||||
imc_attestation->destroy(imc_attestation);
|
||||
imc_attestation = NULL;
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
|
||||
if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
|
||||
{
|
||||
DBG1(DBG_IMC, "no common IF-IMC version");
|
||||
return TNC_RESULT_NO_COMMON_VERSION;
|
||||
}
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_API TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id,
|
||||
TNC_ConnectionState new_state)
|
||||
{
|
||||
imc_state_t *state;
|
||||
|
||||
if (!imc_attestation)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
switch (new_state)
|
||||
{
|
||||
case TNC_CONNECTION_STATE_CREATE:
|
||||
state = imc_attestation_state_create(connection_id);
|
||||
return imc_attestation->create_state(imc_attestation, state);
|
||||
case TNC_CONNECTION_STATE_HANDSHAKE:
|
||||
if (imc_attestation->change_state(imc_attestation, connection_id,
|
||||
new_state, &state) != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
state->set_result(state, imc_id,
|
||||
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
|
||||
return TNC_RESULT_SUCCESS;
|
||||
case TNC_CONNECTION_STATE_DELETE:
|
||||
return imc_attestation->delete_state(imc_attestation, connection_id);
|
||||
case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
|
||||
case TNC_CONNECTION_STATE_ACCESS_NONE:
|
||||
default:
|
||||
return imc_attestation->change_state(imc_attestation, connection_id,
|
||||
new_state, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_API TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id)
|
||||
{
|
||||
if (!imc_attestation)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
|
||||
{
|
||||
imc_msg_t *out_msg;
|
||||
imc_attestation_state_t *attestation_state;
|
||||
enumerator_t *enumerator;
|
||||
pa_tnc_attr_t *attr;
|
||||
pen_type_t type;
|
||||
TNC_Result result;
|
||||
bool fatal_error = FALSE;
|
||||
|
||||
/* generate an outgoing PA-TNC message - we might need it */
|
||||
out_msg = imc_msg_create_as_reply(in_msg);
|
||||
|
||||
/* parse received PA-TNC message and handle local and remote errors */
|
||||
result = in_msg->receive(in_msg, out_msg, &fatal_error);
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
out_msg->destroy(out_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* analyze PA-TNC attributes */
|
||||
enumerator = in_msg->create_attribute_enumerator(in_msg);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
type = attr->get_type(attr);
|
||||
|
||||
if (type.vendor_id == PEN_IETF)
|
||||
{
|
||||
if (type.type == IETF_ATTR_PA_TNC_ERROR)
|
||||
{
|
||||
ietf_attr_pa_tnc_error_t *error_attr;
|
||||
pen_type_t error_code;
|
||||
chunk_t msg_info;
|
||||
|
||||
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
|
||||
error_code = error_attr->get_error_code(error_attr);
|
||||
|
||||
if (error_code.vendor_id == PEN_TCG)
|
||||
{
|
||||
msg_info = error_attr->get_msg_info(error_attr);
|
||||
|
||||
DBG1(DBG_IMC, "received TCG-PTS error '%N'",
|
||||
pts_error_code_names, error_code.type);
|
||||
DBG1(DBG_IMC, "error information: %B", &msg_info);
|
||||
|
||||
result = TNC_RESULT_FATAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type.vendor_id == PEN_TCG)
|
||||
{
|
||||
attestation_state = (imc_attestation_state_t*)state;
|
||||
|
||||
if (!imc_attestation_process(attr, out_msg, attestation_state,
|
||||
supported_algorithms, supported_dh_groups))
|
||||
{
|
||||
result = TNC_RESULT_FATAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (result == TNC_RESULT_SUCCESS)
|
||||
{
|
||||
/* send PA-TNC message with the EXCL flag set */
|
||||
result = out_msg->send(out_msg, TRUE);
|
||||
}
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id,
|
||||
TNC_BufferReference msg,
|
||||
TNC_UInt32 msg_len,
|
||||
TNC_MessageType msg_type)
|
||||
{
|
||||
imc_state_t *state;
|
||||
imc_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!imc_attestation)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
|
||||
in_msg = imc_msg_create_from_data(imc_attestation, state, connection_id,
|
||||
msg_type, chunk_create(msg, msg_len));
|
||||
result = receive_message(state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_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_imv_id,
|
||||
TNC_UInt32 dst_imc_id)
|
||||
{
|
||||
imc_state_t *state;
|
||||
imc_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!imc_attestation)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
if (!imc_attestation->get_state(imc_attestation, connection_id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imc_msg_create_from_long_data(imc_attestation, state, connection_id,
|
||||
src_imv_id, dst_imc_id, msg_vid, msg_subtype,
|
||||
chunk_create(msg, msg_len));
|
||||
result =receive_message(state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_API TNC_IMC_BatchEnding(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id)
|
||||
{
|
||||
if (!imc_attestation)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_API TNC_IMC_Terminate(TNC_IMCID imc_id)
|
||||
{
|
||||
if (!imc_attestation)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
imc_attestation->destroy(imc_attestation);
|
||||
imc_attestation = NULL;
|
||||
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_API TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
|
||||
TNC_TNCC_BindFunctionPointer bind_function)
|
||||
{
|
||||
if (!imc_attestation)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
return imc_attestation->bind_functions(imc_attestation, bind_function);
|
||||
}
|
||||
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
/* for isdigit */
|
||||
#include <ctype.h>
|
||||
|
||||
#include "imc_attestation_process.h"
|
||||
|
||||
#include <ietf/ietf_attr_pa_tnc_error.h>
|
||||
|
||||
#include <pts/pts.h>
|
||||
|
||||
#include <tcg/pts/tcg_pts_attr_proto_caps.h>
|
||||
#include <tcg/pts/tcg_pts_attr_meas_algo.h>
|
||||
#include <tcg/pts/tcg_pts_attr_dh_nonce_params_req.h>
|
||||
#include <tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h>
|
||||
#include <tcg/pts/tcg_pts_attr_dh_nonce_finish.h>
|
||||
#include <tcg/pts/tcg_pts_attr_get_tpm_version_info.h>
|
||||
#include <tcg/pts/tcg_pts_attr_tpm_version_info.h>
|
||||
#include <tcg/pts/tcg_pts_attr_get_aik.h>
|
||||
#include <tcg/pts/tcg_pts_attr_aik.h>
|
||||
#include <tcg/pts/tcg_pts_attr_req_func_comp_evid.h>
|
||||
#include <tcg/pts/tcg_pts_attr_gen_attest_evid.h>
|
||||
#include <tcg/pts/tcg_pts_attr_simple_comp_evid.h>
|
||||
#include <tcg/pts/tcg_pts_attr_simple_evid_final.h>
|
||||
#include <tcg/pts/tcg_pts_attr_req_file_meas.h>
|
||||
#include <tcg/pts/tcg_pts_attr_file_meas.h>
|
||||
#include <tcg/pts/tcg_pts_attr_req_file_meta.h>
|
||||
#include <tcg/pts/tcg_pts_attr_unix_file_meta.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <utils/lexparser.h>
|
||||
|
||||
#define DEFAULT_NONCE_LEN 20
|
||||
|
||||
bool imc_attestation_process(pa_tnc_attr_t *attr, imc_msg_t *msg,
|
||||
imc_attestation_state_t *attestation_state,
|
||||
pts_meas_algorithms_t supported_algorithms,
|
||||
pts_dh_group_t supported_dh_groups)
|
||||
{
|
||||
chunk_t attr_info;
|
||||
pts_t *pts;
|
||||
pts_error_code_t pts_error;
|
||||
pen_type_t attr_type;
|
||||
bool valid_path;
|
||||
|
||||
pts = attestation_state->get_pts(attestation_state);
|
||||
attr_type = attr->get_type(attr);
|
||||
|
||||
switch (attr_type.type)
|
||||
{
|
||||
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);
|
||||
msg->add_attribute(msg, 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);
|
||||
msg->add_attribute(msg, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Send Measurement Algorithm Selection attribute */
|
||||
pts->set_meas_algorithm(pts, selected_algorithm);
|
||||
attr = tcg_pts_attr_meas_algo_create(selected_algorithm, TRUE);
|
||||
msg->add_attribute(msg, 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,
|
||||
"%s.plugins.imc-attestation.nonce_len",
|
||||
DEFAULT_NONCE_LEN, lib->ns);
|
||||
|
||||
attr_cast = (tcg_pts_attr_dh_nonce_params_req_t*)attr;
|
||||
min_nonce_len = attr_cast->get_min_nonce_len(attr_cast);
|
||||
if (nonce_len < PTS_MIN_NONCE_LEN ||
|
||||
(min_nonce_len > 0 && nonce_len < min_nonce_len))
|
||||
{
|
||||
attr = pts_dh_nonce_error_create(nonce_len, PTS_MAX_NONCE_LEN);
|
||||
msg->add_attribute(msg, 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 = pts_dh_group_error_create(supported_dh_groups);
|
||||
msg->add_attribute(msg, 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);
|
||||
msg->add_attribute(msg, 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 FALSE;
|
||||
}
|
||||
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 = lib->settings->get_int(lib->settings,
|
||||
"%s.plugins.imc-attestation.nonce_len",
|
||||
DEFAULT_NONCE_LEN, lib->ns);
|
||||
if (nonce_len != initiator_nonce.len)
|
||||
{
|
||||
DBG1(DBG_IMC, "initiator and responder DH nonces "
|
||||
"have differing lengths");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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;
|
||||
pen_type_t error_code = { PEN_TCG, TCG_PTS_TPM_VERS_NOT_SUPPORTED };
|
||||
|
||||
if (!pts->get_tpm_version_info(pts, &tpm_version_info))
|
||||
{
|
||||
attr_info = attr->get_value(attr);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
|
||||
msg->add_attribute(msg, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Send TPM Version Info attribute */
|
||||
attr = tcg_pts_attr_tpm_version_info_create(tpm_version_info);
|
||||
msg->add_attribute(msg, 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);
|
||||
msg->add_attribute(msg, 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;
|
||||
pen_type_t error_code;
|
||||
|
||||
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)
|
||||
{
|
||||
error_code = pen_type_create(PEN_TCG, pts_error);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
|
||||
msg->add_attribute(msg, attr);
|
||||
break;
|
||||
}
|
||||
else if (!valid_path)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
|
||||
{
|
||||
error_code = pen_type_create(PEN_TCG,
|
||||
TCG_PTS_INVALID_DELIMITER);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
|
||||
msg->add_attribute(msg, 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_file_meas_create_from_path(request_id,
|
||||
pathname, is_directory, TRUE,
|
||||
pts->get_meas_algorithm(pts));
|
||||
if (!measurements)
|
||||
{
|
||||
/* TODO handle error codes from measurements */
|
||||
return FALSE;
|
||||
}
|
||||
attr = tcg_pts_attr_file_meas_create(measurements);
|
||||
attr->set_noskip_flag(attr, TRUE);
|
||||
msg->add_attribute(msg, attr);
|
||||
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;
|
||||
pen_type_t error_code;
|
||||
|
||||
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)
|
||||
{
|
||||
error_code = pen_type_create(PEN_TCG, pts_error);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
|
||||
msg->add_attribute(msg, attr);
|
||||
break;
|
||||
}
|
||||
else if (!valid_path)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (delimiter != SOLIDUS_UTF && delimiter != REVERSE_SOLIDUS_UTF)
|
||||
{
|
||||
error_code = pen_type_create(PEN_TCG,
|
||||
TCG_PTS_INVALID_DELIMITER);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
|
||||
msg->add_attribute(msg, 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);
|
||||
msg->add_attribute(msg, attr);
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_REQ_FUNC_COMP_EVID:
|
||||
{
|
||||
tcg_pts_attr_req_func_comp_evid_t *attr_cast;
|
||||
pts_proto_caps_flag_t negotiated_caps;
|
||||
pts_comp_func_name_t *name;
|
||||
pts_comp_evidence_t *evid;
|
||||
pts_component_t *comp;
|
||||
pen_type_t error_code;
|
||||
u_int32_t depth;
|
||||
u_int8_t flags;
|
||||
status_t status;
|
||||
enumerator_t *e;
|
||||
|
||||
attr_info = attr->get_value(attr);
|
||||
attr_cast = (tcg_pts_attr_req_func_comp_evid_t*)attr;
|
||||
|
||||
DBG1(DBG_IMC, "evidence requested for %d functional components",
|
||||
attr_cast->get_count(attr_cast));
|
||||
|
||||
e = attr_cast->create_enumerator(attr_cast);
|
||||
while (e->enumerate(e, &flags, &depth, &name))
|
||||
{
|
||||
name->log(name, "* ");
|
||||
negotiated_caps = pts->get_proto_caps(pts);
|
||||
|
||||
if (flags & PTS_REQ_FUNC_COMP_EVID_TTC)
|
||||
{
|
||||
error_code = pen_type_create(PEN_TCG,
|
||||
TCG_PTS_UNABLE_DET_TTC);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
|
||||
msg->add_attribute(msg, attr);
|
||||
break;
|
||||
}
|
||||
if (flags & PTS_REQ_FUNC_COMP_EVID_VER &&
|
||||
!(negotiated_caps & PTS_PROTO_CAPS_V))
|
||||
{
|
||||
error_code = pen_type_create(PEN_TCG,
|
||||
TCG_PTS_UNABLE_LOCAL_VAL);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
|
||||
msg->add_attribute(msg, attr);
|
||||
break;
|
||||
}
|
||||
if (flags & PTS_REQ_FUNC_COMP_EVID_CURR &&
|
||||
!(negotiated_caps & PTS_PROTO_CAPS_C))
|
||||
{
|
||||
error_code = pen_type_create(PEN_TCG,
|
||||
TCG_PTS_UNABLE_CUR_EVID);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
|
||||
msg->add_attribute(msg, attr);
|
||||
break;
|
||||
}
|
||||
if (flags & PTS_REQ_FUNC_COMP_EVID_PCR &&
|
||||
!(negotiated_caps & PTS_PROTO_CAPS_T))
|
||||
{
|
||||
error_code = pen_type_create(PEN_TCG,
|
||||
TCG_PTS_UNABLE_DET_PCR);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, attr_info);
|
||||
msg->add_attribute(msg, attr);
|
||||
break;
|
||||
}
|
||||
if (depth > 0)
|
||||
{
|
||||
DBG1(DBG_IMC, "the Attestation IMC currently does not "
|
||||
"support sub component measurements");
|
||||
return FALSE;
|
||||
}
|
||||
comp = attestation_state->create_component(attestation_state,
|
||||
name, depth);
|
||||
if (!comp)
|
||||
{
|
||||
DBG2(DBG_IMC, " not registered: no evidence provided");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* do the component evidence measurement[s] and cache them */
|
||||
do
|
||||
{
|
||||
status = comp->measure(comp, name->get_qualifier(name),
|
||||
pts, &evid);
|
||||
if (status == FAILED)
|
||||
{
|
||||
break;
|
||||
}
|
||||
attestation_state->add_evidence(attestation_state, evid);
|
||||
}
|
||||
while (status == NEED_MORE);
|
||||
}
|
||||
e->destroy(e);
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_GEN_ATTEST_EVID:
|
||||
{
|
||||
pts_simple_evid_final_flag_t flags;
|
||||
pts_meas_algorithms_t comp_hash_algorithm;
|
||||
pts_comp_evidence_t *evid;
|
||||
chunk_t pcr_composite, quote_sig;
|
||||
bool use_quote2;
|
||||
|
||||
/* Send cached Component Evidence entries */
|
||||
while (attestation_state->next_evidence(attestation_state, &evid))
|
||||
{
|
||||
attr = tcg_pts_attr_simple_comp_evid_create(evid);
|
||||
msg->add_attribute(msg, attr);
|
||||
}
|
||||
|
||||
use_quote2 = lib->settings->get_bool(lib->settings,
|
||||
"%s.plugins.imc-attestation.use_quote2", TRUE,
|
||||
lib->ns);
|
||||
if (!pts->quote_tpm(pts, use_quote2, &pcr_composite, "e_sig))
|
||||
{
|
||||
DBG1(DBG_IMC, "error occurred during TPM quote operation");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Send Simple Evidence Final attribute */
|
||||
flags = use_quote2 ? PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2 :
|
||||
PTS_SIMPLE_EVID_FINAL_QUOTE_INFO;
|
||||
comp_hash_algorithm = PTS_MEAS_ALGO_SHA1;
|
||||
|
||||
attr = tcg_pts_attr_simple_evid_final_create(flags,
|
||||
comp_hash_algorithm, pcr_composite, quote_sig);
|
||||
msg->add_attribute(msg, 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;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef IMC_ATTESTATION_PROCESS_H_
|
||||
#define IMC_ATTESTATION_PROCESS_H_
|
||||
|
||||
#include "imc_attestation_state.h"
|
||||
|
||||
#include <library.h>
|
||||
|
||||
#include <imc/imc_msg.h>
|
||||
#include <pa_tnc/pa_tnc_attr.h>
|
||||
|
||||
#include <pts/pts_dh_group.h>
|
||||
#include <pts/pts_meas_algo.h>
|
||||
|
||||
/**
|
||||
* Process a TCG PTS attribute
|
||||
*
|
||||
* @param attr PA-TNC attribute to be processed
|
||||
* @param msg outbound PA-TNC message to be assembled
|
||||
* @param attestation_state attestation state of a given connection
|
||||
* @param supported_algorithms supported PTS measurement algorithms
|
||||
* @param supported_dh_groups supported DH groups
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool imc_attestation_process(pa_tnc_attr_t *attr, imc_msg_t *msg,
|
||||
imc_attestation_state_t *attestation_state,
|
||||
pts_meas_algorithms_t supported_algorithms,
|
||||
pts_dh_group_t supported_dh_groups);
|
||||
|
||||
#endif /** IMC_ATTESTATION_PROCESS_H_ @}*/
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imc_attestation_state.h"
|
||||
|
||||
#include <imcv.h>
|
||||
|
||||
#include <tncif_names.h>
|
||||
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_imc_attestation_state_t private_imc_attestation_state_t;
|
||||
typedef struct func_comp_t func_comp_t;
|
||||
|
||||
/**
|
||||
* Private data of an imc_attestation_state_t object.
|
||||
*/
|
||||
struct private_imc_attestation_state_t {
|
||||
|
||||
/**
|
||||
* Public members of imc_attestation_state_t
|
||||
*/
|
||||
imc_attestation_state_t public;
|
||||
|
||||
/**
|
||||
* TNCCS connection ID
|
||||
*/
|
||||
TNC_ConnectionID connection_id;
|
||||
|
||||
/**
|
||||
* TNCCS connection state
|
||||
*/
|
||||
TNC_ConnectionState state;
|
||||
|
||||
/**
|
||||
* Assessment/Evaluation Result
|
||||
*/
|
||||
TNC_IMV_Evaluation_Result result;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support long message types?
|
||||
*/
|
||||
bool has_long;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support exclusive delivery?
|
||||
*/
|
||||
bool has_excl;
|
||||
|
||||
/**
|
||||
* Maximum PA-TNC message size for this TNCCS connection
|
||||
*/
|
||||
u_int32_t max_msg_len;
|
||||
|
||||
/**
|
||||
* PA-TNC attribute segmentation contracts associated with TNCCS connection
|
||||
*/
|
||||
seg_contract_manager_t *contracts;
|
||||
|
||||
/**
|
||||
* PTS object
|
||||
*/
|
||||
pts_t *pts;
|
||||
|
||||
/**
|
||||
* List of Functional Components
|
||||
*/
|
||||
linked_list_t *components;
|
||||
|
||||
/**
|
||||
* Functional Component Evidence cache list
|
||||
*/
|
||||
linked_list_t *list;
|
||||
|
||||
};
|
||||
|
||||
METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
|
||||
private_imc_attestation_state_t *this)
|
||||
{
|
||||
return this->connection_id;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, has_long, bool,
|
||||
private_imc_attestation_state_t *this)
|
||||
{
|
||||
return this->has_long;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, has_excl, bool,
|
||||
private_imc_attestation_state_t *this)
|
||||
{
|
||||
return this->has_excl;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, set_flags, void,
|
||||
private_imc_attestation_state_t *this, bool has_long, bool has_excl)
|
||||
{
|
||||
this->has_long = has_long;
|
||||
this->has_excl = has_excl;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, set_max_msg_len, void,
|
||||
private_imc_attestation_state_t *this, u_int32_t max_msg_len)
|
||||
{
|
||||
this->max_msg_len = max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, get_max_msg_len, u_int32_t,
|
||||
private_imc_attestation_state_t *this)
|
||||
{
|
||||
return this->max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, get_contracts, seg_contract_manager_t*,
|
||||
private_imc_attestation_state_t *this)
|
||||
{
|
||||
return this->contracts;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, change_state, void,
|
||||
private_imc_attestation_state_t *this, TNC_ConnectionState new_state)
|
||||
{
|
||||
this->state = new_state;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, set_result, void,
|
||||
private_imc_attestation_state_t *this, TNC_IMCID id,
|
||||
TNC_IMV_Evaluation_Result result)
|
||||
{
|
||||
this->result = result;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, get_result, bool,
|
||||
private_imc_attestation_state_t *this, TNC_IMCID id,
|
||||
TNC_IMV_Evaluation_Result *result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
*result = this->result;
|
||||
}
|
||||
return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, destroy, void,
|
||||
private_imc_attestation_state_t *this)
|
||||
{
|
||||
this->pts->destroy(this->pts);
|
||||
this->components->destroy_offset(this->components,
|
||||
offsetof(pts_component_t, destroy));
|
||||
this->list->destroy_offset(this->list,
|
||||
offsetof(pts_comp_evidence_t, destroy));
|
||||
this->contracts->destroy(this->contracts);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(imc_attestation_state_t, get_pts, pts_t*,
|
||||
private_imc_attestation_state_t *this)
|
||||
{
|
||||
return this->pts;
|
||||
}
|
||||
|
||||
METHOD(imc_attestation_state_t, create_component, pts_component_t*,
|
||||
private_imc_attestation_state_t *this, pts_comp_func_name_t *name,
|
||||
u_int32_t depth)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
pts_component_t *component;
|
||||
bool found = FALSE;
|
||||
|
||||
enumerator = this->components->create_enumerator(this->components);
|
||||
while (enumerator->enumerate(enumerator, &component))
|
||||
{
|
||||
if (name->equals(name, component->get_comp_func_name(component)))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
component = imcv_pts_components->create(imcv_pts_components,
|
||||
name, depth, NULL);
|
||||
if (!component)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
this->components->insert_last(this->components, component);
|
||||
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
METHOD(imc_attestation_state_t, add_evidence, void,
|
||||
private_imc_attestation_state_t *this, pts_comp_evidence_t *evid)
|
||||
{
|
||||
this->list->insert_last(this->list, evid);
|
||||
}
|
||||
|
||||
METHOD(imc_attestation_state_t, next_evidence, bool,
|
||||
private_imc_attestation_state_t *this, pts_comp_evidence_t **evid)
|
||||
{
|
||||
return this->list->remove_first(this->list, (void**)evid) == SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imc_state_t *imc_attestation_state_create(TNC_ConnectionID connection_id)
|
||||
{
|
||||
private_imc_attestation_state_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.interface = {
|
||||
.get_connection_id = _get_connection_id,
|
||||
.has_long = _has_long,
|
||||
.has_excl = _has_excl,
|
||||
.set_flags = _set_flags,
|
||||
.set_max_msg_len = _set_max_msg_len,
|
||||
.get_max_msg_len = _get_max_msg_len,
|
||||
.get_contracts = _get_contracts,
|
||||
.change_state = _change_state,
|
||||
.set_result = _set_result,
|
||||
.get_result = _get_result,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_pts = _get_pts,
|
||||
.create_component = _create_component,
|
||||
.add_evidence = _add_evidence,
|
||||
.next_evidence = _next_evidence,
|
||||
},
|
||||
.connection_id = connection_id,
|
||||
.state = TNC_CONNECTION_STATE_CREATE,
|
||||
.result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
|
||||
.contracts = seg_contract_manager_create(),
|
||||
.pts = pts_create(TRUE),
|
||||
.components = linked_list_create(),
|
||||
.list = linked_list_create(),
|
||||
);
|
||||
|
||||
return &this->public.interface;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 imc_attestation
|
||||
* @ingroup libimcv_plugins
|
||||
*
|
||||
* @defgroup imc_attestation_state_t imc_attestation_state
|
||||
* @{ @ingroup imc_attestation
|
||||
*/
|
||||
|
||||
#ifndef IMC_ATTESTATION_STATE_H_
|
||||
#define IMC_ATTESTATION_STATE_H_
|
||||
|
||||
#include <imc/imc_state.h>
|
||||
#include <pts/pts.h>
|
||||
#include <pts/components/pts_component.h>
|
||||
#include <pts/components/pts_comp_evidence.h>
|
||||
#include <library.h>
|
||||
|
||||
typedef struct imc_attestation_state_t imc_attestation_state_t;
|
||||
|
||||
/**
|
||||
* Internal state of an imc_attestation_t connection instance
|
||||
*/
|
||||
struct imc_attestation_state_t {
|
||||
|
||||
/**
|
||||
* imc_state_t interface
|
||||
*/
|
||||
imc_state_t interface;
|
||||
|
||||
/**
|
||||
* Get the PTS object
|
||||
*
|
||||
* @return PTS object
|
||||
*/
|
||||
pts_t* (*get_pts)(imc_attestation_state_t *this);
|
||||
|
||||
/**
|
||||
* Create and add an entry to the list of Functional Components
|
||||
*
|
||||
* @param name Component Functional Name
|
||||
* @param depth Sub-component Depth
|
||||
* @return created functional component instance or NULL
|
||||
*/
|
||||
pts_component_t* (*create_component)(imc_attestation_state_t *this,
|
||||
pts_comp_func_name_t *name, u_int32_t depth);
|
||||
|
||||
/**
|
||||
* Add an entry to the Component Evidence cache list
|
||||
*
|
||||
* @param evid Component Evidence entry
|
||||
*/
|
||||
void (*add_evidence)(imc_attestation_state_t *this, pts_comp_evidence_t *evid);
|
||||
|
||||
/**
|
||||
* Removes next entry from the Component Evidence cache list and returns it
|
||||
*
|
||||
* @param evid Next Component Evidence entry
|
||||
* @return TRUE if next entry is available
|
||||
*/
|
||||
bool (*next_evidence)(imc_attestation_state_t *this, pts_comp_evidence_t** evid);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an imc_attestation_state_t instance
|
||||
*
|
||||
* @param id connection ID
|
||||
*/
|
||||
imc_state_t* imc_attestation_state_create(TNC_ConnectionID id);
|
||||
|
||||
#endif /** IMC_ATTESTATION_STATE_H_ @}*/
|
||||
@@ -0,0 +1 @@
|
||||
regid.2004-03.org.strongswan*.swidtag
|
||||
@@ -0,0 +1,37 @@
|
||||
regid = regid.2004-03.org.strongswan
|
||||
unique_sw_id = strongSwan-$(PACKAGE_VERSION_MAJOR)-$(PACKAGE_VERSION_MINOR)-$(PACKAGE_VERSION_BUILD)$(PACKAGE_VERSION_REVIEW)
|
||||
swid_tag = $(regid)_$(unique_sw_id).swidtag
|
||||
|
||||
swiddir = $(prefix)/share/$(regid)
|
||||
swid_DATA = $(swid_tag)
|
||||
ipsec_DATA = $(swid_tag)
|
||||
EXTRA_DIST = $(regid)_strongSwan.swidtag.in
|
||||
CLEANFILES = $(regid)_strongSwan*.swidtag
|
||||
|
||||
$(swid_tag) : regid.2004-03.org.strongswan_strongSwan.swidtag.in
|
||||
$(AM_V_GEN) \
|
||||
sed \
|
||||
-e "s:@VERSION_MAJOR@:$(PACKAGE_VERSION_MAJOR):" \
|
||||
-e "s:@VERSION_MINOR@:$(PACKAGE_VERSION_MINOR):" \
|
||||
-e "s:@VERSION_BUILD@:$(PACKAGE_VERSION_BUILD):" \
|
||||
-e "s:@VERSION_REVIEW@:$(PACKAGE_VERSION_REVIEW):" \
|
||||
$(srcdir)/$(regid)_strongSwan.swidtag.in > $@
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-I$(top_srcdir)/src/libtncif \
|
||||
-I$(top_srcdir)/src/libimcv \
|
||||
-DSWID_DIRECTORY=\"${prefix}/share\"
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(PLUGIN_CFLAGS)
|
||||
|
||||
imcv_LTLIBRARIES = imc-swid.la
|
||||
|
||||
imc_swid_la_LIBADD = \
|
||||
$(top_builddir)/src/libimcv/libimcv.la \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||
|
||||
imc_swid_la_SOURCES = imc_swid.c imc_swid_state.h imc_swid_state.c
|
||||
|
||||
imc_swid_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imc_swid_state.h"
|
||||
|
||||
#include <imc/imc_agent.h>
|
||||
#include <imc/imc_msg.h>
|
||||
#include <ita/ita_attr.h>
|
||||
#include <ita/ita_attr_angel.h>
|
||||
#include "tcg/swid/tcg_swid_attr_req.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_inv.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
|
||||
#include "swid/swid_inventory.h"
|
||||
#include "swid/swid_error.h"
|
||||
|
||||
#include <tncif_pa_subtypes.h>
|
||||
|
||||
#include <pen/pen.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#define SWID_GENERATOR "/usr/local/bin/swid_generator"
|
||||
|
||||
/* IMC definitions */
|
||||
|
||||
static const char imc_name[] = "SWID";
|
||||
|
||||
static pen_type_t msg_types[] = {
|
||||
{ PEN_TCG, PA_SUBTYPE_TCG_SWID }
|
||||
};
|
||||
|
||||
static imc_agent_t *imc_swid;
|
||||
|
||||
/**
|
||||
* see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
|
||||
TNC_Version min_version,
|
||||
TNC_Version max_version,
|
||||
TNC_Version *actual_version)
|
||||
{
|
||||
if (imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
|
||||
return TNC_RESULT_ALREADY_INITIALIZED;
|
||||
}
|
||||
imc_swid = imc_agent_create(imc_name, msg_types, countof(msg_types),
|
||||
imc_id, actual_version);
|
||||
if (!imc_swid)
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
|
||||
{
|
||||
DBG1(DBG_IMC, "no common IF-IMC version");
|
||||
return TNC_RESULT_NO_COMMON_VERSION;
|
||||
}
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id,
|
||||
TNC_ConnectionState new_state)
|
||||
{
|
||||
imc_state_t *state;
|
||||
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
switch (new_state)
|
||||
{
|
||||
case TNC_CONNECTION_STATE_CREATE:
|
||||
state = imc_swid_state_create(connection_id);
|
||||
return imc_swid->create_state(imc_swid, state);
|
||||
case TNC_CONNECTION_STATE_HANDSHAKE:
|
||||
if (imc_swid->change_state(imc_swid, connection_id, new_state,
|
||||
&state) != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
state->set_result(state, imc_id,
|
||||
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
|
||||
return TNC_RESULT_SUCCESS;
|
||||
case TNC_CONNECTION_STATE_DELETE:
|
||||
return imc_swid->delete_state(imc_swid, connection_id);
|
||||
default:
|
||||
return imc_swid->change_state(imc_swid, connection_id,
|
||||
new_state, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id)
|
||||
{
|
||||
imc_state_t *state;
|
||||
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
if (!imc_swid->get_state(imc_swid, connection_id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one or multiple SWID Inventory attributes to the send queue
|
||||
*/
|
||||
static bool add_swid_inventory(imc_state_t *state, imc_msg_t *msg,
|
||||
uint32_t request_id, bool full_tags,
|
||||
swid_inventory_t *targets)
|
||||
{
|
||||
pa_tnc_attr_t *attr, *attr_angel, *attr_error;
|
||||
imc_swid_state_t *swid_state;
|
||||
swid_inventory_t *swid_inventory;
|
||||
char *swid_directory, *swid_generator;
|
||||
uint32_t eid_epoch;
|
||||
size_t max_attr_size, attr_size, entry_size;
|
||||
bool first = TRUE, swid_pretty, swid_full;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
swid_directory = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imc-swid.swid_directory",
|
||||
SWID_DIRECTORY, lib->ns);
|
||||
swid_generator = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imc-swid.swid_generator",
|
||||
SWID_GENERATOR, lib->ns);
|
||||
swid_pretty = lib->settings->get_bool(lib->settings,
|
||||
"%s.plugins.imc-swid.swid_pretty",
|
||||
FALSE, lib->ns);
|
||||
swid_full = lib->settings->get_bool(lib->settings,
|
||||
"%s.plugins.imc-swid.swid_full",
|
||||
FALSE, lib->ns);
|
||||
|
||||
swid_inventory = swid_inventory_create(full_tags);
|
||||
if (!swid_inventory->collect(swid_inventory, swid_directory, swid_generator,
|
||||
targets, swid_pretty, swid_full))
|
||||
{
|
||||
swid_inventory->destroy(swid_inventory);
|
||||
attr_error = swid_error_create(TCG_SWID_ERROR, request_id,
|
||||
0, "error in SWID tag collection");
|
||||
msg->add_attribute(msg, attr_error);
|
||||
return FALSE;
|
||||
}
|
||||
DBG1(DBG_IMC, "collected %d SWID tag%s%s",
|
||||
swid_inventory->get_count(swid_inventory), full_tags ? "" : " ID",
|
||||
swid_inventory->get_count(swid_inventory) == 1 ? "" : "s");
|
||||
|
||||
swid_state = (imc_swid_state_t*)state;
|
||||
eid_epoch = swid_state->get_eid_epoch(swid_state);
|
||||
|
||||
/**
|
||||
* Compute the maximum TCG SWID Tag [ID] Inventory attribute size
|
||||
* leaving space for an additional ITA Angel attribute
|
||||
*/
|
||||
max_attr_size = state->get_max_msg_len(state) -
|
||||
PA_TNC_HEADER_SIZE - PA_TNC_ATTR_HEADER_SIZE;
|
||||
|
||||
if (full_tags)
|
||||
{
|
||||
tcg_swid_attr_tag_inv_t *swid_attr;
|
||||
swid_tag_t *tag;
|
||||
chunk_t encoding, instance_id;
|
||||
|
||||
/* At least one TCG Tag Inventory attribute is sent */
|
||||
attr_size = PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_TAG_INV_MIN_SIZE;
|
||||
attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1);
|
||||
|
||||
enumerator = swid_inventory->create_enumerator(swid_inventory);
|
||||
while (enumerator->enumerate(enumerator, &tag))
|
||||
{
|
||||
instance_id = tag->get_instance_id(tag);
|
||||
encoding = tag->get_encoding(tag);
|
||||
entry_size = 2 + instance_id.len + 4 + encoding.len;
|
||||
|
||||
/* Check for oversize tags that cannot be transported */
|
||||
if (PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_TAG_INV_MIN_SIZE +
|
||||
entry_size > max_attr_size)
|
||||
{
|
||||
attr_error = swid_error_create(TCG_SWID_RESPONSE_TOO_LARGE,
|
||||
request_id, max_attr_size,
|
||||
"oversize SWID tag omitted");
|
||||
msg->add_attribute(msg, attr_error);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attr_size + entry_size > max_attr_size)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
/**
|
||||
* Send an ITA Start Angel attribute to the IMV signalling
|
||||
* that multiple TGC SWID Tag Inventory attributes follow
|
||||
*/
|
||||
attr_angel = ita_attr_angel_create(TRUE);
|
||||
msg->add_attribute(msg, attr_angel);
|
||||
first = FALSE;
|
||||
}
|
||||
msg->add_attribute(msg, attr);
|
||||
|
||||
/* create the next TCG SWID Tag Inventory attribute */
|
||||
attr_size = PA_TNC_ATTR_HEADER_SIZE +
|
||||
TCG_SWID_TAG_INV_MIN_SIZE;
|
||||
attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1);
|
||||
}
|
||||
swid_attr = (tcg_swid_attr_tag_inv_t*)attr;
|
||||
swid_attr->add(swid_attr, tag->get_ref(tag));
|
||||
attr_size += entry_size;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
tcg_swid_attr_tag_id_inv_t *swid_id_attr;
|
||||
swid_tag_id_t *tag_id;
|
||||
|
||||
/* Send a TCG Tag ID Inventory attribute */
|
||||
attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
|
||||
swid_id_attr = (tcg_swid_attr_tag_id_inv_t*)attr;
|
||||
|
||||
enumerator = swid_inventory->create_enumerator(swid_inventory);
|
||||
while (enumerator->enumerate(enumerator, &tag_id))
|
||||
{
|
||||
swid_id_attr->add(swid_id_attr, tag_id->get_ref(tag_id));
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
msg->add_attribute(msg, attr);
|
||||
swid_inventory->destroy(swid_inventory);
|
||||
|
||||
if (!first)
|
||||
{
|
||||
/**
|
||||
* If we sent an ITA Start Angel attribute in the first place,
|
||||
* terminate by appending a matching ITA Stop Angel attribute.
|
||||
*/
|
||||
attr_angel = ita_attr_angel_create(FALSE);
|
||||
msg->add_attribute(msg, attr_angel);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
|
||||
{
|
||||
imc_msg_t *out_msg;
|
||||
pa_tnc_attr_t *attr;
|
||||
enumerator_t *enumerator;
|
||||
pen_type_t type;
|
||||
TNC_Result result;
|
||||
bool fatal_error = FALSE;
|
||||
|
||||
/* generate an outgoing PA-TNC message - we might need it */
|
||||
out_msg = imc_msg_create_as_reply(in_msg);
|
||||
|
||||
/* parse received PA-TNC message and handle local and remote errors */
|
||||
result = in_msg->receive(in_msg, out_msg, &fatal_error);
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
out_msg->destroy(out_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* analyze PA-TNC attributes */
|
||||
enumerator = in_msg->create_attribute_enumerator(in_msg);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
tcg_swid_attr_req_t *attr_req;
|
||||
uint8_t flags;
|
||||
uint32_t request_id;
|
||||
bool full_tags;
|
||||
swid_inventory_t *targets;
|
||||
|
||||
type = attr->get_type(attr);
|
||||
|
||||
if (type.vendor_id != PEN_TCG || type.type != TCG_SWID_REQUEST)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
attr_req = (tcg_swid_attr_req_t*)attr;
|
||||
flags = attr_req->get_flags(attr_req);
|
||||
request_id = attr_req->get_request_id(attr_req);
|
||||
targets = attr_req->get_targets(attr_req);
|
||||
|
||||
if (flags & (TCG_SWID_ATTR_REQ_FLAG_S | TCG_SWID_ATTR_REQ_FLAG_C))
|
||||
{
|
||||
attr = swid_error_create(TCG_SWID_SUBSCRIPTION_DENIED, request_id,
|
||||
0, "no subscription available yet");
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
break;
|
||||
}
|
||||
full_tags = (flags & TCG_SWID_ATTR_REQ_FLAG_R) == 0;
|
||||
|
||||
if (!add_swid_inventory(state, out_msg, request_id, full_tags, targets))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (fatal_error)
|
||||
{
|
||||
result = TNC_RESULT_FATAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* send PA-TNC message with the EXCL flag set */
|
||||
result = out_msg->send(out_msg, TRUE);
|
||||
}
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
|
||||
|
||||
*/
|
||||
TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id,
|
||||
TNC_BufferReference msg,
|
||||
TNC_UInt32 msg_len,
|
||||
TNC_MessageType msg_type)
|
||||
{
|
||||
imc_state_t *state;
|
||||
imc_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
if (!imc_swid->get_state(imc_swid, connection_id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imc_msg_create_from_data(imc_swid, state, connection_id, msg_type,
|
||||
chunk_create(msg, msg_len));
|
||||
result = receive_message(state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_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_imv_id,
|
||||
TNC_UInt32 dst_imc_id)
|
||||
{
|
||||
imc_state_t *state;
|
||||
imc_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
if (!imc_swid->get_state(imc_swid, connection_id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imc_msg_create_from_long_data(imc_swid, state, connection_id,
|
||||
src_imv_id, dst_imc_id,msg_vid, msg_subtype,
|
||||
chunk_create(msg, msg_len));
|
||||
result =receive_message(state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
|
||||
TNC_ConnectionID connection_id)
|
||||
{
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
|
||||
{
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
imc_swid->destroy(imc_swid);
|
||||
imc_swid = NULL;
|
||||
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
|
||||
*/
|
||||
TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
|
||||
TNC_TNCC_BindFunctionPointer bind_function)
|
||||
{
|
||||
if (!imc_swid)
|
||||
{
|
||||
DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
|
||||
return TNC_RESULT_NOT_INITIALIZED;
|
||||
}
|
||||
return imc_swid->bind_functions(imc_swid, bind_function);
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imc_swid_state.h"
|
||||
|
||||
#include <tncif_names.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_imc_swid_state_t private_imc_swid_state_t;
|
||||
|
||||
/**
|
||||
* Private data of an imc_swid_state_t object.
|
||||
*/
|
||||
struct private_imc_swid_state_t {
|
||||
|
||||
/**
|
||||
* Public members of imc_swid_state_t
|
||||
*/
|
||||
imc_swid_state_t public;
|
||||
|
||||
/**
|
||||
* TNCCS connection ID
|
||||
*/
|
||||
TNC_ConnectionID connection_id;
|
||||
|
||||
/**
|
||||
* TNCCS connection state
|
||||
*/
|
||||
TNC_ConnectionState state;
|
||||
|
||||
/**
|
||||
* Assessment/Evaluation Result
|
||||
*/
|
||||
TNC_IMV_Evaluation_Result result;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support long message types?
|
||||
*/
|
||||
bool has_long;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support exclusive delivery?
|
||||
*/
|
||||
bool has_excl;
|
||||
|
||||
/**
|
||||
* Maximum PA-TNC message size for this TNCCS connection
|
||||
*/
|
||||
u_int32_t max_msg_len;
|
||||
|
||||
/**
|
||||
* PA-TNC attribute segmentation contracts associated with TNCCS connection
|
||||
*/
|
||||
seg_contract_manager_t *contracts;
|
||||
|
||||
/**
|
||||
* Event ID Epoch
|
||||
*/
|
||||
u_int32_t eid_epoch;
|
||||
};
|
||||
|
||||
METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->connection_id;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, has_long, bool,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->has_long;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, has_excl, bool,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->has_excl;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, set_flags, void,
|
||||
private_imc_swid_state_t *this, bool has_long, bool has_excl)
|
||||
{
|
||||
this->has_long = has_long;
|
||||
this->has_excl = has_excl;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, set_max_msg_len, void,
|
||||
private_imc_swid_state_t *this, u_int32_t max_msg_len)
|
||||
{
|
||||
this->max_msg_len = max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, get_max_msg_len, u_int32_t,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, get_contracts, seg_contract_manager_t*,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->contracts;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, change_state, void,
|
||||
private_imc_swid_state_t *this, TNC_ConnectionState new_state)
|
||||
{
|
||||
this->state = new_state;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, set_result, void,
|
||||
private_imc_swid_state_t *this, TNC_IMCID id,
|
||||
TNC_IMV_Evaluation_Result result)
|
||||
{
|
||||
this->result = result;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, get_result, bool,
|
||||
private_imc_swid_state_t *this, TNC_IMCID id,
|
||||
TNC_IMV_Evaluation_Result *result)
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
*result = this->result;
|
||||
}
|
||||
return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
|
||||
}
|
||||
|
||||
METHOD(imc_state_t, destroy, void,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
this->contracts->destroy(this->contracts);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(imc_swid_state_t, get_eid_epoch, u_int32_t,
|
||||
private_imc_swid_state_t *this)
|
||||
{
|
||||
return this->eid_epoch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imc_state_t *imc_swid_state_create(TNC_ConnectionID connection_id)
|
||||
{
|
||||
private_imc_swid_state_t *this;
|
||||
u_int32_t eid_epoch;
|
||||
nonce_gen_t *ng;
|
||||
|
||||
ng = lib->crypto->create_nonce_gen(lib->crypto);
|
||||
if (!ng || !ng->get_nonce(ng, 4, (u_int8_t*)&eid_epoch))
|
||||
{
|
||||
DBG1(DBG_TNC, "failed to generate random EID epoch value");
|
||||
DESTROY_IF(ng);
|
||||
return NULL;
|
||||
}
|
||||
ng->destroy(ng);
|
||||
|
||||
DBG1(DBG_IMC, "creating random EID epoch 0x%08x", eid_epoch);
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.interface = {
|
||||
.get_connection_id = _get_connection_id,
|
||||
.has_long = _has_long,
|
||||
.has_excl = _has_excl,
|
||||
.set_flags = _set_flags,
|
||||
.set_max_msg_len = _set_max_msg_len,
|
||||
.get_max_msg_len = _get_max_msg_len,
|
||||
.get_contracts = _get_contracts,
|
||||
.change_state = _change_state,
|
||||
.set_result = _set_result,
|
||||
.get_result = _get_result,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_eid_epoch = _get_eid_epoch,
|
||||
},
|
||||
.state = TNC_CONNECTION_STATE_CREATE,
|
||||
.result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
|
||||
.connection_id = connection_id,
|
||||
.contracts = seg_contract_manager_create(),
|
||||
.eid_epoch = eid_epoch,
|
||||
);
|
||||
|
||||
|
||||
return &this->public.interface;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Andreas Steffen, 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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_swid imc_swid
|
||||
* @ingroup libimcv_plugins
|
||||
*
|
||||
* @defgroup imc_swid_state_t imc_swid_state
|
||||
* @{ @ingroup imc_swid
|
||||
*/
|
||||
|
||||
#ifndef IMC_SWID_STATE_H_
|
||||
#define IMC_SWID_STATE_H_
|
||||
|
||||
#include <imc/imc_state.h>
|
||||
#include <library.h>
|
||||
|
||||
typedef struct imc_swid_state_t imc_swid_state_t;
|
||||
|
||||
/**
|
||||
* Internal state of an imc_swid_t connection instance
|
||||
*/
|
||||
struct imc_swid_state_t {
|
||||
|
||||
/**
|
||||
* imc_state_t interface
|
||||
*/
|
||||
imc_state_t interface;
|
||||
|
||||
/**
|
||||
* Get Event ID Epoch
|
||||
*
|
||||
* @return Event ID Epoch
|
||||
*/
|
||||
u_int32_t (*get_eid_epoch)(imc_swid_state_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an imc_swid_state_t instance
|
||||
*
|
||||
* @param id connection ID
|
||||
*/
|
||||
imc_state_t* imc_swid_state_create(TNC_ConnectionID id);
|
||||
|
||||
#endif /** IMC_SWID_STATE_H_ @}*/
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
|
||||
<entitlement_required_indicator>true</entitlement_required_indicator>
|
||||
<product_title>apache2</product_title>
|
||||
<product_version>
|
||||
<name>2.2-22-13</name>
|
||||
<numeric>
|
||||
<major>2</major>
|
||||
<minor>2</minor>
|
||||
<build>22</build>
|
||||
<review>13</review>
|
||||
</numeric>
|
||||
</product_version>
|
||||
<software_creator>
|
||||
<name>Apache Software Foundation</name>
|
||||
<regid>regid.1995-04.org.apache</regid>
|
||||
</software_creator>
|
||||
<software_licensor>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</software_licensor>
|
||||
<software_id>
|
||||
<unique_id>apache-2-2-22-13</unique_id>
|
||||
<tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
|
||||
</software_id>
|
||||
<tag_creator>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</tag_creator>
|
||||
</software_identification_tag>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
|
||||
<entitlement_required_indicator>true</entitlement_required_indicator>
|
||||
<product_title>bind9</product_title>
|
||||
<product_version>
|
||||
<name>9-8-4-dfsg</name>
|
||||
<numeric>
|
||||
<major>9</major>
|
||||
<minor>8</minor>
|
||||
<build>4</build>
|
||||
<review>dfsg</review>
|
||||
</numeric>
|
||||
</product_version>
|
||||
<software_creator>
|
||||
<name>Internet Systems Consortium</name>
|
||||
<regid>regid.1994-04.org.isc</regid>
|
||||
</software_creator>
|
||||
<software_licensor>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</software_licensor>
|
||||
<software_id>
|
||||
<unique_id>bind-9-8-4-dfsg</unique_id>
|
||||
<tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
|
||||
</software_id>
|
||||
<tag_creator>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</tag_creator>
|
||||
</software_identification_tag>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
|
||||
<entitlement_required_indicator>true</entitlement_required_indicator>
|
||||
<product_title>libsqlite3</product_title>
|
||||
<product_version>
|
||||
<name>3.7.13-1</name>
|
||||
<numeric>
|
||||
<major>3</major>
|
||||
<minor>7</minor>
|
||||
<build>13</build>
|
||||
<review>1</review>
|
||||
</numeric>
|
||||
</product_version>
|
||||
<software_creator>
|
||||
<name>SQLite Project</name>
|
||||
<regid>regid.2002-08.org.sqlite</regid>
|
||||
</software_creator>
|
||||
<software_licensor>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</software_licensor>
|
||||
<software_id>
|
||||
<unique_id>libsqlite-3-7-13-1</unique_id>
|
||||
<tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
|
||||
</software_id>
|
||||
<tag_creator>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</tag_creator>
|
||||
</software_identification_tag>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
|
||||
<entitlement_required_indicator>true</entitlement_required_indicator>
|
||||
<product_title>libssl1.0.0</product_title>
|
||||
<product_version>
|
||||
<name>1.0.1e-2</name>
|
||||
<numeric>
|
||||
<major>1</major>
|
||||
<minor>0</minor>
|
||||
<build>1e</build>
|
||||
<review>2</review>
|
||||
</numeric>
|
||||
</product_version>
|
||||
<software_creator>
|
||||
<name>OpenSSL Project</name>
|
||||
<regid>regid.1998-12.org.openssl</regid>
|
||||
</software_creator>
|
||||
<software_licensor>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</software_licensor>
|
||||
<software_id>
|
||||
<unique_id>libssl-1-0-1e-2</unique_id>
|
||||
<tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
|
||||
</software_id>
|
||||
<tag_creator>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</tag_creator>
|
||||
</software_identification_tag>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
|
||||
<entitlement_required_indicator>true</entitlement_required_indicator>
|
||||
<product_title>libssl-dev</product_title>
|
||||
<product_version>
|
||||
<name>1.0.1e-2</name>
|
||||
<numeric>
|
||||
<major>1</major>
|
||||
<minor>0</minor>
|
||||
<build>1e</build>
|
||||
<review>2</review>
|
||||
</numeric>
|
||||
</product_version>
|
||||
<software_creator>
|
||||
<name>OpenSSL Project</name>
|
||||
<regid>regid.1998-12.org.openssl</regid>
|
||||
</software_creator>
|
||||
<software_licensor>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</software_licensor>
|
||||
<software_id>
|
||||
<unique_id>libssl-dev-1-0-1e-2</unique_id>
|
||||
<tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
|
||||
</software_id>
|
||||
<tag_creator>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</tag_creator>
|
||||
</software_identification_tag>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
|
||||
<entitlement_required_indicator>true</entitlement_required_indicator>
|
||||
<product_title>openssl</product_title>
|
||||
<product_version>
|
||||
<name>1.0.1e-2</name>
|
||||
<numeric>
|
||||
<major>1</major>
|
||||
<minor>0</minor>
|
||||
<build>1e</build>
|
||||
<review>2</review>
|
||||
</numeric>
|
||||
</product_version>
|
||||
<software_creator>
|
||||
<name>OpenSSL Project</name>
|
||||
<regid>regid.1998-12.org.openssl</regid>
|
||||
</software_creator>
|
||||
<software_licensor>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</software_licensor>
|
||||
<software_id>
|
||||
<unique_id>openssl-1-0-1e-2</unique_id>
|
||||
<tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
|
||||
</software_id>
|
||||
<tag_creator>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</tag_creator>
|
||||
</software_identification_tag>
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<software_identification_tag xmlns="http://standards.iso.org/iso/19770/-2/2009/schema.xsd">
|
||||
<entitlement_required_indicator>true</entitlement_required_indicator>
|
||||
<product_title>sqlite3</product_title>
|
||||
<product_version>
|
||||
<name>3.7.13-1</name>
|
||||
<numeric>
|
||||
<major>3</major>
|
||||
<minor>7</minor>
|
||||
<build>13</build>
|
||||
<review>1</review>
|
||||
</numeric>
|
||||
</product_version>
|
||||
<software_creator>
|
||||
<name>SQLite Project</name>
|
||||
<regid>regid.2002-08.org.sqlite</regid>
|
||||
</software_creator>
|
||||
<software_licensor>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</software_licensor>
|
||||
<software_id>
|
||||
<unique_id>sqlite-3-7-13-1</unique_id>
|
||||
<tag_creator_regid>regid.1999-03.org.debian</tag_creator_regid>
|
||||
</software_id>
|
||||
<tag_creator>
|
||||
<name>Debian Project</name>
|
||||
<regid>regid.1999-03.org.debian</regid>
|
||||
</tag_creator>
|
||||
</software_identification_tag>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<SoftwareIdentity
|
||||
name="strongSwan"
|
||||
uniqueId="strongSwan-@VERSION_MAJOR@-@VERSION_MINOR@-@VERSION_BUILD@@VERSION_REVIEW@"
|
||||
version="@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_BUILD@@VERSION_REVIEW@" versionScheme="alphanumeric"
|
||||
xmlns="http://standards.iso.org/iso/19770/-2/2014/schema.xsd">
|
||||
<Entity
|
||||
name="strongSwan Project"
|
||||
regid="regid.2004-03.org.strongswan"
|
||||
role="publisher licensor tagcreator"/>
|
||||
</SoftwareIdentity>
|
||||
@@ -0,0 +1 @@
|
||||
attest
|
||||
@@ -0,0 +1,33 @@
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-I$(top_srcdir)/src/libtncif \
|
||||
-I$(top_srcdir)/src/libimcv \
|
||||
-DPLUGINS=\""${attest_plugins}\""
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(PLUGIN_CFLAGS)
|
||||
|
||||
imcv_LTLIBRARIES = imv-attestation.la
|
||||
|
||||
imv_attestation_la_LIBADD = \
|
||||
$(top_builddir)/src/libimcv/libimcv.la \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||
|
||||
imv_attestation_la_SOURCES = imv_attestation.c \
|
||||
imv_attestation_state.h imv_attestation_state.c \
|
||||
imv_attestation_agent.h imv_attestation_agent.c \
|
||||
imv_attestation_process.h imv_attestation_process.c \
|
||||
imv_attestation_build.h imv_attestation_build.c
|
||||
|
||||
imv_attestation_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||
|
||||
ipsec_PROGRAMS = attest
|
||||
attest_SOURCES = attest.c \
|
||||
attest_usage.h attest_usage.c \
|
||||
attest_db.h attest_db.c
|
||||
attest_LDADD = \
|
||||
$(top_builddir)/src/libimcv/libimcv.la \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||
attest.o : $(top_builddir)/config.status
|
||||
|
||||
EXTRA_DIST = build-database.sh
|
||||
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 <getopt.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#ifdef HAVE_SYSLOG
|
||||
# include <syslog.h>
|
||||
#endif
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <imcv.h>
|
||||
#include <pts/pts_meas_algo.h>
|
||||
|
||||
#include "attest_db.h"
|
||||
#include "attest_usage.h"
|
||||
|
||||
/**
|
||||
* global debug output variables
|
||||
*/
|
||||
static int debug_level = 1;
|
||||
static bool stderr_quiet = TRUE;
|
||||
|
||||
/**
|
||||
* attest dbg function
|
||||
*/
|
||||
static void attest_dbg(debug_t group, level_t level, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (level <= debug_level)
|
||||
{
|
||||
if (!stderr_quiet)
|
||||
{
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYSLOG
|
||||
{
|
||||
int priority = LOG_INFO;
|
||||
char buffer[8192];
|
||||
char *current = buffer, *next;
|
||||
|
||||
/* write in memory buffer first */
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
/* do a syslog with every line */
|
||||
while (current)
|
||||
{
|
||||
next = strchr(current, '\n');
|
||||
if (next)
|
||||
{
|
||||
*(next++) = '\0';
|
||||
}
|
||||
syslog(priority, "%s\n", current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SYSLOG */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* global attestation database object
|
||||
*/
|
||||
attest_db_t *attest;
|
||||
|
||||
|
||||
/**
|
||||
* atexit handler to close db on shutdown
|
||||
*/
|
||||
static void cleanup(void)
|
||||
{
|
||||
attest->destroy(attest);
|
||||
libimcv_deinit();
|
||||
#ifdef HAVE_SYSLOG
|
||||
closelog();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void do_args(int argc, char *argv[])
|
||||
{
|
||||
enum {
|
||||
OP_UNDEF,
|
||||
OP_USAGE,
|
||||
OP_KEYS,
|
||||
OP_COMPONENTS,
|
||||
OP_DEVICES,
|
||||
OP_DIRECTORIES,
|
||||
OP_FILES,
|
||||
OP_HASHES,
|
||||
OP_MEASUREMENTS,
|
||||
OP_PACKAGES,
|
||||
OP_PRODUCTS,
|
||||
OP_SESSIONS,
|
||||
OP_ADD,
|
||||
OP_DEL,
|
||||
} op = OP_UNDEF;
|
||||
|
||||
/* reinit getopt state */
|
||||
optind = 0;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
int c;
|
||||
|
||||
struct option long_opts[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "components", no_argument, NULL, 'c' },
|
||||
{ "devices", no_argument, NULL, 'e' },
|
||||
{ "directories", no_argument, NULL, 'd' },
|
||||
{ "dirs", no_argument, NULL, 'd' },
|
||||
{ "files", no_argument, NULL, 'f' },
|
||||
{ "keys", no_argument, NULL, 'k' },
|
||||
{ "packages", no_argument, NULL, 'g' },
|
||||
{ "products", no_argument, NULL, 'p' },
|
||||
{ "hashes", no_argument, NULL, 'H' },
|
||||
{ "measurements", no_argument, NULL, 'm' },
|
||||
{ "sessions", no_argument, NULL, 's' },
|
||||
{ "add", no_argument, NULL, 'a' },
|
||||
{ "delete", no_argument, NULL, 'r' },
|
||||
{ "del", no_argument, NULL, 'r' },
|
||||
{ "remove", no_argument, NULL, 'r' },
|
||||
{ "aik", required_argument, NULL, 'A' },
|
||||
{ "blacklist", no_argument, NULL, 'B' },
|
||||
{ "component", required_argument, NULL, 'C' },
|
||||
{ "comp", required_argument, NULL, 'C' },
|
||||
{ "directory", required_argument, NULL, 'D' },
|
||||
{ "dir", required_argument, NULL, 'D' },
|
||||
{ "file", required_argument, NULL, 'F' },
|
||||
{ "package", required_argument, NULL, 'G' },
|
||||
{ "key", required_argument, NULL, 'K' },
|
||||
{ "measdir", required_argument, NULL, 'M' },
|
||||
{ "owner", required_argument, NULL, 'O' },
|
||||
{ "product", required_argument, NULL, 'P' },
|
||||
{ "relative", no_argument, NULL, 'R' },
|
||||
{ "rel", no_argument, NULL, 'R' },
|
||||
{ "sequence", required_argument, NULL, 'S' },
|
||||
{ "seq", required_argument, NULL, 'S' },
|
||||
{ "utc", no_argument, NULL, 'U' },
|
||||
{ "version", required_argument, NULL, 'V' },
|
||||
{ "security", no_argument, NULL, 'Y' },
|
||||
{ "sha1", no_argument, NULL, '1' },
|
||||
{ "sha256", no_argument, NULL, '2' },
|
||||
{ "sha384", no_argument, NULL, '3' },
|
||||
{ "did", required_argument, NULL, '4' },
|
||||
{ "fid", required_argument, NULL, '5' },
|
||||
{ "pid", required_argument, NULL, '6' },
|
||||
{ "cid", required_argument, NULL, '7' },
|
||||
{ "kid", required_argument, NULL, '8' },
|
||||
{ "gid", required_argument, NULL, '9' },
|
||||
{ 0,0,0,0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "", long_opts, NULL);
|
||||
switch (c)
|
||||
{
|
||||
case EOF:
|
||||
break;
|
||||
case 'h':
|
||||
op = OP_USAGE;
|
||||
break;
|
||||
case 'c':
|
||||
op = OP_COMPONENTS;
|
||||
continue;
|
||||
case 'd':
|
||||
op = OP_DIRECTORIES;
|
||||
continue;
|
||||
case 'e':
|
||||
op = OP_DEVICES;
|
||||
continue;
|
||||
case 'f':
|
||||
op = OP_FILES;
|
||||
continue;
|
||||
case 'g':
|
||||
op = OP_PACKAGES;
|
||||
continue;
|
||||
case 'k':
|
||||
op = OP_KEYS;
|
||||
continue;
|
||||
case 'p':
|
||||
op = OP_PRODUCTS;
|
||||
continue;
|
||||
case 'H':
|
||||
op = OP_HASHES;
|
||||
continue;
|
||||
case 'm':
|
||||
op = OP_MEASUREMENTS;
|
||||
continue;
|
||||
case 's':
|
||||
op = OP_SESSIONS;
|
||||
continue;
|
||||
case 'a':
|
||||
op = OP_ADD;
|
||||
continue;
|
||||
case 'r':
|
||||
op = OP_DEL;
|
||||
continue;
|
||||
case 'A':
|
||||
{
|
||||
certificate_t *aik_cert;
|
||||
public_key_t *aik_key;
|
||||
chunk_t aik;
|
||||
|
||||
aik_cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
||||
CERT_X509, BUILD_FROM_FILE, optarg, BUILD_END);
|
||||
if (!aik_cert)
|
||||
{
|
||||
printf("AIK certificate '%s' could not be loaded\n", optarg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
aik_key = aik_cert->get_public_key(aik_cert);
|
||||
aik_cert->destroy(aik_cert);
|
||||
|
||||
if (!aik_key)
|
||||
{
|
||||
printf("AIK public key could not be retrieved\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!aik_key->get_fingerprint(aik_key, KEYID_PUBKEY_INFO_SHA1,
|
||||
&aik))
|
||||
{
|
||||
printf("AIK fingerprint could not be computed\n");
|
||||
aik_key->destroy(aik_key);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
aik = chunk_clone(aik);
|
||||
aik_key->destroy(aik_key);
|
||||
|
||||
if (!attest->set_key(attest, aik, op == OP_ADD))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case 'B':
|
||||
attest->set_package_state(attest, OS_PACKAGE_STATE_BLACKLIST);
|
||||
continue;
|
||||
case 'C':
|
||||
if (!attest->set_component(attest, optarg, op == OP_ADD))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case 'D':
|
||||
if (!attest->set_directory(attest, optarg, op == OP_ADD))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case 'F':
|
||||
{
|
||||
char *dir = path_dirname(optarg);
|
||||
char *file = path_basename(optarg);
|
||||
|
||||
if (*dir != '.')
|
||||
{
|
||||
if (!attest->set_directory(attest, dir, op == OP_ADD))
|
||||
{
|
||||
free(file);
|
||||
free(dir);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
free(dir);
|
||||
|
||||
if (!attest->set_file(attest, file, op == OP_ADD))
|
||||
{
|
||||
free(file);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
free(file);
|
||||
continue;
|
||||
}
|
||||
case 'G':
|
||||
if (!attest->set_package(attest, optarg, op == OP_ADD))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case 'K':
|
||||
{
|
||||
chunk_t aik;
|
||||
|
||||
aik = chunk_from_hex(chunk_create(optarg, strlen(optarg)), NULL);
|
||||
if (!attest->set_key(attest, aik, op == OP_ADD))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case 'M':
|
||||
if (!attest->set_meas_directory(attest, optarg))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case 'O':
|
||||
attest->set_owner(attest, optarg);
|
||||
continue;
|
||||
case 'P':
|
||||
if (!attest->set_product(attest, optarg, op == OP_ADD))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case 'R':
|
||||
attest->set_relative(attest);
|
||||
continue;
|
||||
case 'S':
|
||||
attest->set_sequence(attest, atoi(optarg));
|
||||
continue;
|
||||
case 'U':
|
||||
attest->set_utc(attest);
|
||||
continue;
|
||||
case 'V':
|
||||
if (!attest->set_version(attest, optarg))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case 'Y':
|
||||
attest->set_package_state(attest, OS_PACKAGE_STATE_SECURITY);
|
||||
continue;
|
||||
case '1':
|
||||
attest->set_algo(attest, PTS_MEAS_ALGO_SHA1);
|
||||
continue;
|
||||
case '2':
|
||||
attest->set_algo(attest, PTS_MEAS_ALGO_SHA256);
|
||||
continue;
|
||||
case '3':
|
||||
attest->set_algo(attest, PTS_MEAS_ALGO_SHA384);
|
||||
continue;
|
||||
case '4':
|
||||
if (!attest->set_did(attest, atoi(optarg)))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case '5':
|
||||
if (!attest->set_fid(attest, atoi(optarg)))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case '6':
|
||||
if (!attest->set_pid(attest, atoi(optarg)))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case '7':
|
||||
if (!attest->set_cid(attest, atoi(optarg)))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case '8':
|
||||
if (!attest->set_kid(attest, atoi(optarg)))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
case '9':
|
||||
if (!attest->set_gid(attest, atoi(optarg)))
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case OP_USAGE:
|
||||
usage();
|
||||
break;
|
||||
case OP_PACKAGES:
|
||||
attest->list_packages(attest);
|
||||
break;
|
||||
case OP_PRODUCTS:
|
||||
attest->list_products(attest);
|
||||
break;
|
||||
case OP_KEYS:
|
||||
attest->list_keys(attest);
|
||||
break;
|
||||
case OP_COMPONENTS:
|
||||
attest->list_components(attest);
|
||||
break;
|
||||
case OP_DEVICES:
|
||||
attest->list_devices(attest);
|
||||
break;
|
||||
case OP_DIRECTORIES:
|
||||
attest->list_directories(attest);
|
||||
break;
|
||||
case OP_FILES:
|
||||
attest->list_files(attest);
|
||||
break;
|
||||
case OP_HASHES:
|
||||
attest->list_hashes(attest);
|
||||
break;
|
||||
case OP_MEASUREMENTS:
|
||||
attest->list_measurements(attest);
|
||||
break;
|
||||
case OP_SESSIONS:
|
||||
attest->list_sessions(attest);
|
||||
break;
|
||||
case OP_ADD:
|
||||
attest->add(attest);
|
||||
break;
|
||||
case OP_DEL:
|
||||
attest->delete(attest);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *uri;
|
||||
|
||||
/* enable attest debugging hook */
|
||||
dbg = attest_dbg;
|
||||
#ifdef HAVE_SYSLOG
|
||||
openlog("attest", 0, LOG_DEBUG);
|
||||
#endif
|
||||
|
||||
atexit(library_deinit);
|
||||
|
||||
/* initialize library */
|
||||
if (!library_init(NULL, "attest"))
|
||||
{
|
||||
exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
|
||||
}
|
||||
if (!lib->plugins->load(lib->plugins,
|
||||
lib->settings->get_str(lib->settings, "attest.load", PLUGINS)))
|
||||
{
|
||||
exit(SS_RC_INITIALIZATION_FAILED);
|
||||
}
|
||||
|
||||
uri = lib->settings->get_str(lib->settings, "attest.database", NULL);
|
||||
if (!uri)
|
||||
{
|
||||
fprintf(stderr, "database URI attest.database not set.\n");
|
||||
exit(SS_RC_INITIALIZATION_FAILED);
|
||||
}
|
||||
attest = attest_db_create(uri);
|
||||
if (!attest)
|
||||
{
|
||||
exit(SS_RC_INITIALIZATION_FAILED);
|
||||
}
|
||||
atexit(cleanup);
|
||||
libimcv_init(FALSE);
|
||||
|
||||
do_args(argc, argv);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 attest_db_t attest_db
|
||||
* @{ @ingroup libpts
|
||||
*/
|
||||
|
||||
#ifndef ATTEST_DB_H_
|
||||
#define ATTEST_DB_H_
|
||||
|
||||
#include <pts/pts_meas_algo.h>
|
||||
#include <os_info/os_info.h>
|
||||
#include <library.h>
|
||||
|
||||
typedef struct attest_db_t attest_db_t;
|
||||
|
||||
/**
|
||||
* Attestation database object
|
||||
*/
|
||||
struct attest_db_t {
|
||||
|
||||
/**
|
||||
* Set functional component to be queried
|
||||
*
|
||||
* @param comp functional component
|
||||
* @param create if TRUE create database entry if it doesn't exist
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_component)(attest_db_t *this, char *comp, bool create);
|
||||
|
||||
/**
|
||||
* Set primary key of the functional component to be queried
|
||||
*
|
||||
* @param fid primary key of functional component
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_cid)(attest_db_t *this, int fid);
|
||||
|
||||
/**
|
||||
* Set directory to be queried
|
||||
*
|
||||
* @param dir directory
|
||||
* @param create if TRUE create database entry if it doesn't exist
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_directory)(attest_db_t *this, char *dir, bool create);
|
||||
|
||||
/**
|
||||
* Set primary key of the directory to be queried
|
||||
*
|
||||
* @param did primary key of directory
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_did)(attest_db_t *this, int did);
|
||||
|
||||
/**
|
||||
* Set measurement file to be queried
|
||||
*
|
||||
* @param file measurement file
|
||||
* @param create if TRUE create database entry if it doesn't exist
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_file)(attest_db_t *this, char *file, bool create);
|
||||
|
||||
/**
|
||||
* Set primary key of the measurement file to be queried
|
||||
*
|
||||
* @param fid primary key of measurement file
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_fid)(attest_db_t *this, int fid);
|
||||
|
||||
/**
|
||||
* Set path to directory where file[s] are to be measured
|
||||
*
|
||||
* @param meas_dir measurement directory
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_meas_directory)(attest_db_t *this, char *dir);
|
||||
|
||||
/**
|
||||
* Set functional component to be queried
|
||||
*
|
||||
* @param key AIK
|
||||
* @param create if TRUE create database entry if it doesn't exist
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_key)(attest_db_t *this, chunk_t key, bool create);
|
||||
|
||||
/**
|
||||
* Set primary key of the AIK to be queried
|
||||
*
|
||||
* @param kid primary key of AIK
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_kid)(attest_db_t *this, int kid);
|
||||
|
||||
/**
|
||||
* Set software package to be queried
|
||||
*
|
||||
* @param product software package
|
||||
* @param create if TRUE create database entry if it doesn't exist
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_package)(attest_db_t *this, char *package, bool create);
|
||||
|
||||
/**
|
||||
* Set primary key of the software package to be queried
|
||||
*
|
||||
* @param gid primary key of software package
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_gid)(attest_db_t *this, int gid);
|
||||
|
||||
/**
|
||||
* Set software product to be queried
|
||||
*
|
||||
* @param product software product
|
||||
* @param create if TRUE create database entry if it doesn't exist
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_product)(attest_db_t *this, char *product, bool create);
|
||||
|
||||
/**
|
||||
* Set primary key of the software product to be queried
|
||||
*
|
||||
* @param pid primary key of software product
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_pid)(attest_db_t *this, int pid);
|
||||
|
||||
/**
|
||||
* Set software package version to be queried
|
||||
*
|
||||
* @param version software package version
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*set_version)(attest_db_t *this, char *version);
|
||||
|
||||
/**
|
||||
* Set measurement hash algorithm
|
||||
*
|
||||
* @param algo hash algorithm
|
||||
*/
|
||||
void (*set_algo)(attest_db_t *this, pts_meas_algorithms_t algo);
|
||||
|
||||
/**
|
||||
* Set that the IMA-specific SHA-1 template hash be computed
|
||||
*/
|
||||
void (*set_ima)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* Set that relative filenames are to be used
|
||||
*/
|
||||
void (*set_relative)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* Set the package security or blacklist state
|
||||
*/
|
||||
void (*set_package_state)(attest_db_t *this, os_package_state_t package_state);
|
||||
|
||||
/**
|
||||
* Set the sequence number
|
||||
*/
|
||||
void (*set_sequence)(attest_db_t *this, int seq_no);
|
||||
|
||||
/**
|
||||
* Set owner [user/host] of an AIK
|
||||
*
|
||||
* @param owner user/host name
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
void (*set_owner)(attest_db_t *this, char *owner);
|
||||
|
||||
/**
|
||||
* Display all dates in UTC
|
||||
*/
|
||||
void (*set_utc)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List all packages stored in the database
|
||||
*/
|
||||
void (*list_packages)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List all products stored in the database
|
||||
*/
|
||||
void (*list_products)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List all directories stored in the database
|
||||
*/
|
||||
void (*list_directories)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List selected files stored in the database
|
||||
*/
|
||||
void (*list_files)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List all components stored in the database
|
||||
*/
|
||||
void (*list_components)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List all devices stored in the database
|
||||
*/
|
||||
void (*list_devices)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List all AIKs stored in the database
|
||||
*/
|
||||
void (*list_keys)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List selected measurement hashes stored in the database
|
||||
*/
|
||||
void (*list_hashes)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List selected component measurement stored in the database
|
||||
*/
|
||||
void (*list_measurements)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* List sessions stored in the database
|
||||
*/
|
||||
void (*list_sessions)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* Add an entry to the database
|
||||
*/
|
||||
bool (*add)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* Delete an entry from the database
|
||||
*/
|
||||
bool (*delete)(attest_db_t *this);
|
||||
|
||||
/**
|
||||
* Destroy attest_db_t object
|
||||
*/
|
||||
void (*destroy)(attest_db_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an attest_db_t instance
|
||||
*
|
||||
* @param uri database URI
|
||||
*/
|
||||
attest_db_t* attest_db_create(char *uri);
|
||||
|
||||
#endif /** ATTEST_DB_H_ @}*/
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "attest_usage.h"
|
||||
|
||||
/**
|
||||
* print attest usage info
|
||||
*/
|
||||
void usage(void)
|
||||
{
|
||||
printf("\
|
||||
Usage:\n\
|
||||
ipsec attest --components|--devices|--sessions|--files|--hashes|--keys [options]\n\
|
||||
\n\
|
||||
ipsec attest --measurements|--packages|--products|--add|--del [options]\n\
|
||||
\n\
|
||||
ipsec attest --components [--key <digest>|--kid <id>]\n\
|
||||
Show a list of components with an AIK digest or\n\
|
||||
its primary key as an optional selector.\n\
|
||||
\n\
|
||||
ipsec attest --devices [--utc]\n\
|
||||
Show a list of registered devices and associated collected information\n\
|
||||
\n\
|
||||
ipsec attest --sessions [--utc]\n\
|
||||
Show a chronologically sorted list of all TNC sessions\n\
|
||||
\n\
|
||||
ipsec attest --files [--product <name>|--pid <id>]\n\
|
||||
Show a list of files with a software product name or\n\
|
||||
its primary key as an optional selector.\n\
|
||||
\n\
|
||||
ipsec attest --hashes [--sha1|--sha256|--sha384] [--product <name>|--pid <id>]\n\
|
||||
Show a list of measurement hashes for a given software product or\n\
|
||||
its primary key as an optional selector.\n\
|
||||
\n\
|
||||
ipsec attest --hashes [--sha1|--sha1-ima|--sha256|--sha384] [--file <path>|--fid <id>]\n\
|
||||
Show a list of measurement hashes for a given file or\n\
|
||||
its primary key as an optional selector.\n\
|
||||
\n\
|
||||
ipsec attest --keys [--components <cfn>|--cid <id>]\n\
|
||||
Show a list of AIK key digests with a component or\n\
|
||||
its primary key as an optional selector.\n\
|
||||
\n\
|
||||
ipsec attest --measurements --sha1|--sha256|--sha384 [--component <cfn>|--cid <id>]\n\
|
||||
Show a list of component measurements for a given component or\n\
|
||||
its primary key as an optional selector.\n\
|
||||
\n\
|
||||
ipsec attest --measurements --sha1|--sha256|--sha384 [--key <digest>|--kid <id>|--aik <path>]\n\
|
||||
Show a list of component measurements for a given AIK or\n\
|
||||
its primary key as an optional selector.\n\
|
||||
\n\
|
||||
ipsec attest --packages [--product <name>|--pid <id>] [--utc]\n\
|
||||
Show a list of software packages for a given product or\n\
|
||||
its primary key as an optional selector.\n\
|
||||
\n\
|
||||
ipsec attest --products [--file <path>|--fid <id>]\n\
|
||||
Show a list of supported software products with a file path or\n\
|
||||
its primary key as an optional selector.\n\
|
||||
\n\
|
||||
ipsec attest --add --file <path>|--dir <path>|--product <name>|--component <cfn>\n\
|
||||
Add a file, directory, product or component entry\n\
|
||||
Component <cfn> entries must be of the form <vendor_id>/<name>-<qualifier>\n\
|
||||
\n\
|
||||
ipsec attest --add [--owner <name>] --key <digest>|--aik <path>\n\
|
||||
Add an AIK public key digest entry preceded by an optional owner name\n\
|
||||
\n\
|
||||
ipsec attest --add --product <name>|--pid <id> --sha1|--sha1-ima|--sha256|--sha384\n\
|
||||
[--relative|--rel] --dir <path>|--file <path>\n\
|
||||
Add hashes of a single file or all files in a directory under absolute or relative filenames\n\
|
||||
\n\
|
||||
ipsec attest --add --key <digest|--kid <id> --component <cfn>|--cid <id> --sequence <no>|--seq <no>\n\
|
||||
Add an ordered key/component entry\n\
|
||||
\n\
|
||||
ipsec attest --add --package <name> --version <string> [--security|--blacklist]\n\
|
||||
[--product <name>|--pid <id>]\n\
|
||||
Add a package version for a given product optionally with security or blacklist flag\n\
|
||||
\n\
|
||||
ipsec attest --del --file <path>|--fid <id>|--dir <path>|--did <id>\n\
|
||||
Delete a file or directory entry referenced either by value or primary key\n\
|
||||
\n\
|
||||
ipsec attest --del --product <name>|--pid <id>|--component <cfn>|--cid <id>\n\
|
||||
Delete a product or component entry referenced either by value or primary key\n\
|
||||
\n\
|
||||
ipsec attest --del --product <name>|--pid <id> --file <path>|--fid <id>|--dir <path>|--did <id>\n\
|
||||
Delete a product/file entry referenced either by value or primary key\n\
|
||||
\n\
|
||||
ipsec attest --del --key <digest>|--kid <id>|--aik <path>\n\
|
||||
Delete an AIK entry referenced either by value or primary key\n\
|
||||
\n\
|
||||
ipsec attest --del --key <digest|--kid <id> --component <cfn>|--cid <id>\n\
|
||||
Delete a key/component entry\n\
|
||||
\n\
|
||||
ipsec attest --del --product <name>|--pid <id> --sha1|--sha1-ima|--sha256|--sha384\n\
|
||||
[--dir <path>|--did <id>] --file <path>|--fid <id>\n\
|
||||
Delete a file hash given an absolute or relative filename\n\
|
||||
\n");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ATTEST_USAGE_H_
|
||||
#define ATTEST_USAGE_H_
|
||||
|
||||
/**
|
||||
* print attest usage info
|
||||
*/
|
||||
void usage(void);
|
||||
|
||||
|
||||
#endif /* ATTEST_USAGE_H_ */
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
|
||||
p="Ubuntu 14.04 x86_64"
|
||||
a="x86_64-linux-gnu"
|
||||
k="3.13.0-34-generic"
|
||||
|
||||
for hash in sha1 sha256
|
||||
do
|
||||
ipsec attest --add --product "$p" --$hash --dir /sbin
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/sbin
|
||||
ipsec attest --add --product "$p" --$hash --dir /bin
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/bin
|
||||
|
||||
ipsec attest --add --product "$p" --$hash --file /etc/init.d/rc
|
||||
ipsec attest --add --product "$p" --$hash --file /etc/init.d/rcS
|
||||
ipsec attest --add --product "$p" --$hash --dir /etc/network/if-pre-up.d
|
||||
ipsec attest --add --product "$p" --$hash --dir /etc/network/if-up.d
|
||||
ipsec attest --add --product "$p" --$hash --dir /etc/ppp/ip-down.d
|
||||
ipsec attest --add --product "$p" --$hash --dir /etc/rcS.d
|
||||
ipsec attest --add --product "$p" --$hash --dir /etc/rc2.d
|
||||
ipsec attest --add --product "$p" --$hash --file /etc/rc.local
|
||||
ipsec attest --add --product "$p" --$hash --dir /etc/resolvconf/update.d
|
||||
ipsec attest --add --product "$p" --$hash --file /etc/resolvconf/update-libc.d/avahi-daemon
|
||||
ipsec attest --add --product "$p" --$hash --dir /etc/update-motd.d
|
||||
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib
|
||||
ipsec attest --add --product "$p" --$hash --file /lib/crda/setregdomain
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib/ebtables
|
||||
ipsec attest --add --product "$p" --$hash --file /lib/init/apparmor-profile-load
|
||||
ipsec attest --add --product "$p" --$hash --file /lib/resolvconf/list-records
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib/ufw
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib/udev
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib/systemd
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib/xtables
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib/$a
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib/$a/plymouth
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib/$a/plymouth/renderers
|
||||
ipsec attest --add --product "$p" --$hash --dir /lib/$a/security
|
||||
|
||||
ipsec attest --add --product "$p" --$hash --file /lib64/ld-linux-x86-64.so.2
|
||||
|
||||
for file in `find /usr/lib -name *.so`
|
||||
do
|
||||
ipsec attest --add --product "$p" --$hash --file $file
|
||||
done
|
||||
|
||||
for file in `find /usr/lib -name *service`
|
||||
do
|
||||
ipsec attest --add --product "$p" --$hash --file $file
|
||||
done
|
||||
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/accountsservice
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/at-spi2-core
|
||||
ipsec attest --add --product "$p" --$hash --file /usr/lib/avahi/avahi-daemon-check-dns.sh
|
||||
ipsec attest --add --product "$p" --$hash --file /usr/lib/dbus-1.0/dbus-daemon-launch-helper
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/gvfs
|
||||
ipsec attest --add --product "$p" --$hash --file /usr/lib/firefox/firefox
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/NetworkManager
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/pm-utils/power.d
|
||||
ipsec attest --add --product "$p" --$hash --file /usr/lib/policykit-1/polkitd
|
||||
ipsec attest --add --product "$p" --$hash --file /usr/lib/thunderbird/thunderbird
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/ubuntu-release-upgrader
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/update-notifier
|
||||
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/$a
|
||||
ipsec attest --add --product "$p" --$hash --file /usr/lib/$a/mesa/libGL.so.1.2.0
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/$a/samba
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/lib/$a/sasl2
|
||||
|
||||
ipsec attest --add --product "$p" --$hash --dir /usr/share/language-tools
|
||||
|
||||
ipsec attest --add --product "$p" --$hash --file /init \
|
||||
--measdir /usr/share/initramfs-tools
|
||||
|
||||
ipsec attest --add --product "$p" --$hash --file /scripts/functions \
|
||||
--measdir /usr/share/initramfs-tools/scripts
|
||||
|
||||
for file in `find /lib/modules/$k -name *.ko`
|
||||
do
|
||||
ipsec attest --add --product "$p" --$hash --file $file
|
||||
done
|
||||
done
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imv_attestation_agent.h"
|
||||
|
||||
static const char imv_name[] = "Attestation";
|
||||
static const imv_agent_create_t imv_agent_create = imv_attestation_agent_create;
|
||||
|
||||
/* include generic TGC TNC IF-IMV API code below */
|
||||
|
||||
#include <imv/imv_if.h>
|
||||
|
||||
@@ -0,0 +1,904 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 /* for stdndup() */
|
||||
#include <string.h>
|
||||
|
||||
#include "imv_attestation_agent.h"
|
||||
#include "imv_attestation_state.h"
|
||||
#include "imv_attestation_process.h"
|
||||
#include "imv_attestation_build.h"
|
||||
|
||||
#include <imcv.h>
|
||||
#include <imv/imv_agent.h>
|
||||
#include <imv/imv_msg.h>
|
||||
#include <imv/imv_session.h>
|
||||
#include <imv/imv_os_info.h>
|
||||
#include <ietf/ietf_attr.h>
|
||||
#include <ietf/ietf_attr_attr_request.h>
|
||||
#include <ietf/ietf_attr_pa_tnc_error.h>
|
||||
#include <ietf/ietf_attr_product_info.h>
|
||||
#include <ietf/ietf_attr_string_version.h>
|
||||
#include <ita/ita_attr.h>
|
||||
#include <ita/ita_attr_device_id.h>
|
||||
#include <tcg/tcg_attr.h>
|
||||
#include <tcg/pts/tcg_pts_attr_meas_algo.h>
|
||||
#include <tcg/pts/tcg_pts_attr_proto_caps.h>
|
||||
#include <tcg/pts/tcg_pts_attr_req_file_meas.h>
|
||||
#include <tcg/pts/tcg_pts_attr_req_file_meta.h>
|
||||
#include <pts/pts.h>
|
||||
#include <pts/pts_database.h>
|
||||
#include <pts/pts_creds.h>
|
||||
#include <pts/components/ita/ita_comp_func_name.h>
|
||||
|
||||
#include <tncif_pa_subtypes.h>
|
||||
|
||||
#include <pen/pen.h>
|
||||
#include <utils/debug.h>
|
||||
#include <credentials/credential_manager.h>
|
||||
#include <collections/linked_list.h>
|
||||
|
||||
typedef struct private_imv_attestation_agent_t private_imv_attestation_agent_t;
|
||||
|
||||
/* Subscribed PA-TNC message subtypes */
|
||||
static pen_type_t msg_types[] = {
|
||||
{ PEN_TCG, PA_SUBTYPE_TCG_PTS },
|
||||
{ PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM }
|
||||
};
|
||||
|
||||
/**
|
||||
* Private data of an imv_attestation_agent_t object.
|
||||
*/
|
||||
struct private_imv_attestation_agent_t {
|
||||
|
||||
/**
|
||||
* Public members of imv_attestation_agent_t
|
||||
*/
|
||||
imv_agent_if_t public;
|
||||
|
||||
/**
|
||||
* IMV agent responsible for generic functions
|
||||
*/
|
||||
imv_agent_t *agent;
|
||||
|
||||
/**
|
||||
* Supported PTS measurement algorithms
|
||||
*/
|
||||
pts_meas_algorithms_t supported_algorithms;
|
||||
|
||||
/**
|
||||
* Supported PTS Diffie Hellman Groups
|
||||
*/
|
||||
pts_dh_group_t supported_dh_groups;
|
||||
|
||||
/**
|
||||
* PTS file measurement database
|
||||
*/
|
||||
pts_database_t *pts_db;
|
||||
|
||||
/**
|
||||
* PTS credentials
|
||||
*/
|
||||
pts_creds_t *pts_creds;
|
||||
|
||||
/**
|
||||
* PTS credential manager
|
||||
*/
|
||||
credential_manager_t *pts_credmgr;
|
||||
|
||||
};
|
||||
|
||||
METHOD(imv_agent_if_t, bind_functions, TNC_Result,
|
||||
private_imv_attestation_agent_t *this, TNC_TNCS_BindFunctionPointer bind_function)
|
||||
{
|
||||
return this->agent->bind_functions(this->agent, bind_function);
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
|
||||
private_imv_attestation_agent_t *this, TNC_ConnectionID id,
|
||||
TNC_ConnectionState new_state)
|
||||
{
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
imv_state_t *state;
|
||||
imv_session_t *session;
|
||||
|
||||
switch (new_state)
|
||||
{
|
||||
case TNC_CONNECTION_STATE_CREATE:
|
||||
state = imv_attestation_state_create(id);
|
||||
return this->agent->create_state(this->agent, state);
|
||||
case TNC_CONNECTION_STATE_DELETE:
|
||||
return this->agent->delete_state(this->agent, id);
|
||||
case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
|
||||
case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
|
||||
case TNC_CONNECTION_STATE_ACCESS_NONE:
|
||||
if (this->agent->get_state(this->agent, id, &state) && imcv_db)
|
||||
{
|
||||
session = state->get_session(state);
|
||||
|
||||
if (session->get_policy_started(session))
|
||||
{
|
||||
switch (new_state)
|
||||
{
|
||||
case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
|
||||
rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
|
||||
break;
|
||||
case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
|
||||
rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
|
||||
break;
|
||||
case TNC_CONNECTION_STATE_ACCESS_NONE:
|
||||
default:
|
||||
rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
|
||||
}
|
||||
imcv_db->add_recommendation(imcv_db, session, rec);
|
||||
if (!imcv_db->policy_script(imcv_db, session, FALSE))
|
||||
{
|
||||
DBG1(DBG_IMV, "error in policy script stop");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* fall through to default state */
|
||||
default:
|
||||
return this->agent->change_state(this->agent, id, new_state, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a received message
|
||||
*/
|
||||
static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
|
||||
imv_state_t *state, imv_msg_t *in_msg)
|
||||
{
|
||||
imv_msg_t *out_msg;
|
||||
imv_session_t *session;
|
||||
imv_os_info_t *os_info;
|
||||
enumerator_t *enumerator;
|
||||
pa_tnc_attr_t *attr;
|
||||
pen_type_t type;
|
||||
TNC_Result result;
|
||||
chunk_t os_name, os_version;
|
||||
bool fatal_error = FALSE;
|
||||
|
||||
/* generate an outgoing PA-TNC message - we might need it */
|
||||
out_msg = imv_msg_create_as_reply(in_msg);
|
||||
out_msg->set_msg_type(out_msg, msg_types[0]);
|
||||
|
||||
/* parse received PA-TNC message and handle local and remote errors */
|
||||
result = in_msg->receive(in_msg, out_msg, &fatal_error);
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
out_msg->destroy(out_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
session = state->get_session(state);
|
||||
os_info = session->get_os_info(session);
|
||||
|
||||
/* analyze PA-TNC attributes */
|
||||
enumerator = in_msg->create_attribute_enumerator(in_msg);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
type = attr->get_type(attr);
|
||||
|
||||
if (type.vendor_id == PEN_IETF)
|
||||
{
|
||||
switch (type.type)
|
||||
{
|
||||
case IETF_ATTR_PA_TNC_ERROR:
|
||||
{
|
||||
ietf_attr_pa_tnc_error_t *error_attr;
|
||||
pen_type_t error_code;
|
||||
chunk_t msg_info;
|
||||
|
||||
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
|
||||
error_code = error_attr->get_error_code(error_attr);
|
||||
|
||||
if (error_code.vendor_id == PEN_TCG)
|
||||
{
|
||||
msg_info = error_attr->get_msg_info(error_attr);
|
||||
|
||||
DBG1(DBG_IMV, "received TCG-PTS error '%N'",
|
||||
pts_error_code_names, error_code.type);
|
||||
DBG1(DBG_IMV, "error information: %B", &msg_info);
|
||||
fatal_error = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IETF_ATTR_PRODUCT_INFORMATION:
|
||||
{
|
||||
ietf_attr_product_info_t *attr_cast;
|
||||
pen_t vendor_id;
|
||||
|
||||
state->set_action_flags(state,
|
||||
IMV_ATTESTATION_ATTR_PRODUCT_INFO);
|
||||
attr_cast = (ietf_attr_product_info_t*)attr;
|
||||
os_name = attr_cast->get_info(attr_cast, &vendor_id, NULL);
|
||||
os_info->set_name(os_info, os_name);
|
||||
|
||||
if (vendor_id != PEN_IETF)
|
||||
{
|
||||
DBG1(DBG_IMV, "operating system name is '%.*s' "
|
||||
"from vendor %N", os_name.len, os_name.ptr,
|
||||
pen_names, vendor_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IMV, "operating system name is '%.*s'",
|
||||
os_name.len, os_name.ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
case IETF_ATTR_STRING_VERSION:
|
||||
{
|
||||
ietf_attr_string_version_t *attr_cast;
|
||||
|
||||
state->set_action_flags(state,
|
||||
IMV_ATTESTATION_ATTR_STRING_VERSION);
|
||||
attr_cast = (ietf_attr_string_version_t*)attr;
|
||||
os_version = attr_cast->get_version(attr_cast, NULL, NULL);
|
||||
os_info->set_version(os_info, os_version);
|
||||
|
||||
if (os_version.len)
|
||||
{
|
||||
DBG1(DBG_IMV, "operating system version is '%.*s'",
|
||||
os_version.len, os_version.ptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (type.vendor_id == PEN_ITA)
|
||||
{
|
||||
switch (type.type)
|
||||
{
|
||||
case ITA_ATTR_DEVICE_ID:
|
||||
{
|
||||
chunk_t value;
|
||||
|
||||
state->set_action_flags(state,
|
||||
IMV_ATTESTATION_ATTR_DEVICE_ID);
|
||||
|
||||
value = attr->get_value(attr);
|
||||
DBG1(DBG_IMV, "device ID is %.*s", value.len, value.ptr);
|
||||
session->set_device_id(session, value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (type.vendor_id == PEN_TCG)
|
||||
{
|
||||
if (!imv_attestation_process(attr, out_msg, state,
|
||||
this->supported_algorithms, this->supported_dh_groups,
|
||||
this->pts_db, this->pts_credmgr))
|
||||
{
|
||||
result = TNC_RESULT_FATAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (fatal_error || result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
state->set_recommendation(state,
|
||||
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
|
||||
TNC_IMV_EVALUATION_RESULT_ERROR);
|
||||
result = out_msg->send_assessment(out_msg);
|
||||
if (result == TNC_RESULT_SUCCESS)
|
||||
{
|
||||
result = this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* send PA-TNC message with the EXCL flag set */
|
||||
result = out_msg->send(out_msg, TRUE);
|
||||
}
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, receive_message, TNC_Result,
|
||||
private_imv_attestation_agent_t *this, TNC_ConnectionID id,
|
||||
TNC_MessageType msg_type, chunk_t msg)
|
||||
{
|
||||
imv_state_t *state;
|
||||
imv_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imv_msg_create_from_data(this->agent, state, id, msg_type, msg);
|
||||
result = receive_msg(this, state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
|
||||
private_imv_attestation_agent_t *this, TNC_ConnectionID id,
|
||||
TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
|
||||
TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, chunk_t msg)
|
||||
{
|
||||
imv_state_t *state;
|
||||
imv_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imv_msg_create_from_long_data(this->agent, state, id,
|
||||
src_imc_id, dst_imv_id, msg_vid, msg_subtype, msg);
|
||||
result = receive_msg(this, state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an IETF Attribute Request attribute for missing attributes
|
||||
*/
|
||||
static pa_tnc_attr_t* build_attr_request(uint32_t received)
|
||||
{
|
||||
pa_tnc_attr_t *attr;
|
||||
ietf_attr_attr_request_t *attr_cast;
|
||||
|
||||
attr = ietf_attr_attr_request_create(PEN_RESERVED, 0);
|
||||
attr_cast = (ietf_attr_attr_request_t*)attr;
|
||||
|
||||
if (!(received & IMV_ATTESTATION_ATTR_PRODUCT_INFO) ||
|
||||
!(received & IMV_ATTESTATION_ATTR_STRING_VERSION))
|
||||
{
|
||||
attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_PRODUCT_INFORMATION);
|
||||
attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION);
|
||||
}
|
||||
if (!(received & IMV_ATTESTATION_ATTR_DEVICE_ID))
|
||||
{
|
||||
attr_cast->add(attr_cast, PEN_ITA, ITA_ATTR_DEVICE_ID);
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, batch_ending, TNC_Result,
|
||||
private_imv_attestation_agent_t *this, TNC_ConnectionID id)
|
||||
{
|
||||
imv_msg_t *out_msg;
|
||||
imv_state_t *state;
|
||||
imv_session_t *session;
|
||||
imv_attestation_state_t *attestation_state;
|
||||
imv_attestation_handshake_state_t handshake_state;
|
||||
imv_workitem_t *workitem;
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
TNC_IMVID imv_id;
|
||||
TNC_Result result = TNC_RESULT_SUCCESS;
|
||||
pts_t *pts;
|
||||
int pid;
|
||||
uint32_t actions;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
attestation_state = (imv_attestation_state_t*)state;
|
||||
pts = attestation_state->get_pts(attestation_state);
|
||||
handshake_state = attestation_state->get_handshake_state(attestation_state);
|
||||
actions = state->get_action_flags(state);
|
||||
session = state->get_session(state);
|
||||
imv_id = this->agent->get_id(this->agent);
|
||||
|
||||
/* exit if a recommendation has already been provided */
|
||||
if (actions & IMV_ATTESTATION_REC)
|
||||
{
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/* send an IETF attribute request if no platform info was received */
|
||||
if (!(actions & IMV_ATTESTATION_ATTR_REQ))
|
||||
{
|
||||
if ((actions & IMV_ATTESTATION_ATTR_MUST) != IMV_ATTESTATION_ATTR_MUST)
|
||||
{
|
||||
imv_msg_t *os_msg;
|
||||
|
||||
/* create attribute request for missing mandatory attributes */
|
||||
os_msg = imv_msg_create(this->agent, state, id, imv_id,
|
||||
TNC_IMCID_ANY, msg_types[1]);
|
||||
os_msg->add_attribute(os_msg, build_attr_request(actions));
|
||||
result = os_msg->send(os_msg, FALSE);
|
||||
os_msg->destroy(os_msg);
|
||||
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
state->set_action_flags(state, IMV_ATTESTATION_ATTR_REQ);
|
||||
}
|
||||
|
||||
if (!session->get_policy_started(session) &&
|
||||
(actions & IMV_ATTESTATION_ATTR_PRODUCT_INFO) &&
|
||||
(actions & IMV_ATTESTATION_ATTR_STRING_VERSION) &&
|
||||
(actions & IMV_ATTESTATION_ATTR_DEVICE_ID))
|
||||
{
|
||||
if (imcv_db)
|
||||
{
|
||||
/* start the policy script */
|
||||
if (!imcv_db->policy_script(imcv_db, session, TRUE))
|
||||
{
|
||||
DBG1(DBG_IMV, "error in policy script start");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG2(DBG_IMV, "no workitems available - no evaluation possible");
|
||||
state->set_recommendation(state,
|
||||
TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
|
||||
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
|
||||
session->set_policy_started(session, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (handshake_state == IMV_ATTESTATION_STATE_INIT)
|
||||
{
|
||||
pa_tnc_attr_t *attr;
|
||||
pts_proto_caps_flag_t flags;
|
||||
|
||||
out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
|
||||
msg_types[0]);
|
||||
|
||||
/* 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);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
/* Send Measurement Algorithms attribute */
|
||||
attr = tcg_pts_attr_meas_algo_create(this->supported_algorithms, FALSE);
|
||||
attr->set_noskip_flag(attr, TRUE);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
attestation_state->set_handshake_state(attestation_state,
|
||||
IMV_ATTESTATION_STATE_DISCOVERY);
|
||||
|
||||
/* send these initial PTS attributes and exit */
|
||||
result = out_msg->send(out_msg, FALSE);
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* exit if we are not ready yet for PTS measurements */
|
||||
if (!(actions & IMV_ATTESTATION_ALGO))
|
||||
{
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
session->get_session_id(session, &pid, NULL);
|
||||
pts->set_platform_id(pts, pid);
|
||||
|
||||
/* create an empty out message - we might need it */
|
||||
out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
|
||||
msg_types[0]);
|
||||
|
||||
/* establish the PTS measurements to be taken */
|
||||
if (!(actions & IMV_ATTESTATION_FILE_MEAS))
|
||||
{
|
||||
bool is_dir, no_workitems = TRUE;
|
||||
uint32_t delimiter = SOLIDUS_UTF;
|
||||
uint16_t request_id;
|
||||
pa_tnc_attr_t *attr;
|
||||
char *pathname;
|
||||
|
||||
attestation_state->set_handshake_state(attestation_state,
|
||||
IMV_ATTESTATION_STATE_END);
|
||||
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
if (enumerator)
|
||||
{
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_imv_id(workitem) != TNC_IMVID_ANY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (workitem->get_type(workitem))
|
||||
{
|
||||
case IMV_WORKITEM_FILE_REF_MEAS:
|
||||
case IMV_WORKITEM_FILE_MEAS:
|
||||
case IMV_WORKITEM_FILE_META:
|
||||
is_dir = FALSE;
|
||||
break;
|
||||
case IMV_WORKITEM_DIR_REF_MEAS:
|
||||
case IMV_WORKITEM_DIR_MEAS:
|
||||
case IMV_WORKITEM_DIR_META:
|
||||
is_dir = TRUE;
|
||||
break;
|
||||
case IMV_WORKITEM_TPM_ATTEST:
|
||||
{
|
||||
pts_component_t *comp;
|
||||
pts_comp_func_name_t *comp_name;
|
||||
bool no_d_flag, no_t_flag;
|
||||
char result_str[BUF_LEN];
|
||||
|
||||
workitem->set_imv_id(workitem, imv_id);
|
||||
no_workitems = FALSE;
|
||||
no_d_flag = !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_D);
|
||||
no_t_flag = !(pts->get_proto_caps(pts) & PTS_PROTO_CAPS_T);
|
||||
if (no_d_flag || no_t_flag)
|
||||
{
|
||||
snprintf(result_str, BUF_LEN, "%s%s%s",
|
||||
(no_t_flag) ? "no TPM available" : "",
|
||||
(no_t_flag && no_d_flag) ? ", " : "",
|
||||
(no_d_flag) ? "no DH nonce negotiation" : "");
|
||||
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
|
||||
session->remove_workitem(session, enumerator);
|
||||
rec = workitem->set_result(workitem, result_str, eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, workitem);
|
||||
workitem->destroy(workitem);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* do TPM BIOS measurements */
|
||||
if (strchr(workitem->get_arg_str(workitem), 'B'))
|
||||
{
|
||||
comp_name = pts_comp_func_name_create(PEN_ITA,
|
||||
PTS_ITA_COMP_FUNC_NAME_IMA,
|
||||
PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_TRUSTED);
|
||||
comp = attestation_state->create_component(
|
||||
attestation_state, comp_name,
|
||||
0, this->pts_db);
|
||||
if (!comp)
|
||||
{
|
||||
comp_name->log(comp_name, "unregistered ");
|
||||
comp_name->destroy(comp_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* do TPM IMA measurements */
|
||||
if (strchr(workitem->get_arg_str(workitem), 'I'))
|
||||
{
|
||||
comp_name = pts_comp_func_name_create(PEN_ITA,
|
||||
PTS_ITA_COMP_FUNC_NAME_IMA,
|
||||
PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_OS);
|
||||
comp = attestation_state->create_component(
|
||||
attestation_state, comp_name,
|
||||
0, this->pts_db);
|
||||
if (!comp)
|
||||
{
|
||||
comp_name->log(comp_name, "unregistered ");
|
||||
comp_name->destroy(comp_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* do TPM TRUSTED BOOT measurements */
|
||||
if (strchr(workitem->get_arg_str(workitem), 'T'))
|
||||
{
|
||||
comp_name = pts_comp_func_name_create(PEN_ITA,
|
||||
PTS_ITA_COMP_FUNC_NAME_TBOOT,
|
||||
PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_TRUSTED);
|
||||
comp = attestation_state->create_component(
|
||||
attestation_state, comp_name,
|
||||
0, this->pts_db);
|
||||
if (!comp)
|
||||
{
|
||||
comp_name->log(comp_name, "unregistered ");
|
||||
comp_name->destroy(comp_name);
|
||||
}
|
||||
}
|
||||
attestation_state->set_handshake_state(attestation_state,
|
||||
IMV_ATTESTATION_STATE_NONCE_REQ);
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
/* initiate file and directory measurements */
|
||||
pathname = this->pts_db->get_pathname(this->pts_db, is_dir,
|
||||
workitem->get_arg_int(workitem));
|
||||
if (!pathname)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
workitem->set_imv_id(workitem, imv_id);
|
||||
no_workitems = FALSE;
|
||||
|
||||
if (workitem->get_type(workitem) == IMV_WORKITEM_FILE_META)
|
||||
{
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
char result_str[BUF_LEN];
|
||||
|
||||
DBG2(DBG_IMV, "IMV %d requests metadata for %s '%s'",
|
||||
imv_id, is_dir ? "directory" : "file", pathname);
|
||||
|
||||
/* currently just fire and forget metadata requests */
|
||||
attr = tcg_pts_attr_req_file_meta_create(is_dir,
|
||||
delimiter, pathname);
|
||||
snprintf(result_str, BUF_LEN, "%s metadata requested",
|
||||
is_dir ? "directory" : "file");
|
||||
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
|
||||
session->remove_workitem(session, enumerator);
|
||||
rec = workitem->set_result(workitem, result_str, eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, workitem);
|
||||
workitem->destroy(workitem);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* use lower 16 bits of the workitem ID as request ID */
|
||||
request_id = workitem->get_id(workitem) & 0xffff;
|
||||
|
||||
DBG2(DBG_IMV, "IMV %d requests measurement %d for %s '%s'",
|
||||
imv_id, request_id, is_dir ? "directory" : "file",
|
||||
pathname);
|
||||
attr = tcg_pts_attr_req_file_meas_create(is_dir, request_id,
|
||||
delimiter, pathname);
|
||||
}
|
||||
free(pathname);
|
||||
attr->set_noskip_flag(attr, TRUE);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
/* sent all file and directory measurement and metadata requests */
|
||||
state->set_action_flags(state, IMV_ATTESTATION_FILE_MEAS);
|
||||
|
||||
if (no_workitems)
|
||||
{
|
||||
DBG2(DBG_IMV, "IMV %d has no workitems - "
|
||||
"no evaluation requested", imv_id);
|
||||
state->set_recommendation(state,
|
||||
TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
|
||||
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check the IMV state for the next PA-TNC attributes to send */
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_type(workitem) == IMV_WORKITEM_TPM_ATTEST)
|
||||
{
|
||||
if (!imv_attestation_build(out_msg, state,
|
||||
this->supported_dh_groups, this->pts_db))
|
||||
{
|
||||
imv_reason_string_t *reason_string;
|
||||
chunk_t result;
|
||||
char *result_str;
|
||||
|
||||
reason_string = imv_reason_string_create("en", ", ");
|
||||
attestation_state->add_comp_evid_reasons(attestation_state,
|
||||
reason_string);
|
||||
result = reason_string->get_encoding(reason_string);
|
||||
result_str = strndup(result.ptr, result.len);
|
||||
reason_string->destroy(reason_string);
|
||||
|
||||
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
|
||||
session->remove_workitem(session, enumerator);
|
||||
rec = workitem->set_result(workitem, result_str, eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, workitem);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
/* finalized all workitems? */
|
||||
if (session->get_policy_started(session) &&
|
||||
session->get_workitem_count(session, imv_id) == 0 &&
|
||||
attestation_state->get_handshake_state(attestation_state) ==
|
||||
IMV_ATTESTATION_STATE_END)
|
||||
{
|
||||
result = out_msg->send_assessment(out_msg);
|
||||
out_msg->destroy(out_msg);
|
||||
state->set_action_flags(state, IMV_ATTESTATION_REC);
|
||||
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
|
||||
/* send non-empty PA-TNC message with excl flag not set */
|
||||
if (out_msg->get_attribute_count(out_msg))
|
||||
{
|
||||
result = out_msg->send(out_msg, FALSE);
|
||||
}
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
|
||||
private_imv_attestation_agent_t *this, TNC_ConnectionID id)
|
||||
{
|
||||
TNC_IMVID imv_id;
|
||||
imv_state_t *state;
|
||||
imv_attestation_state_t *attestation_state;
|
||||
imv_session_t *session;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
attestation_state = (imv_attestation_state_t*)state;
|
||||
session = state->get_session(state);
|
||||
imv_id = this->agent->get_id(this->agent);
|
||||
|
||||
if (imcv_db)
|
||||
{
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
imv_workitem_t *workitem;
|
||||
enumerator_t *enumerator;
|
||||
int pending_file_meas = 0;
|
||||
char *result_str;
|
||||
chunk_t result_buf;
|
||||
bio_writer_t *result;
|
||||
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
if (enumerator)
|
||||
{
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_imv_id(workitem) != imv_id)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
result = bio_writer_create(128);
|
||||
|
||||
switch (workitem->get_type(workitem))
|
||||
{
|
||||
case IMV_WORKITEM_FILE_REF_MEAS:
|
||||
case IMV_WORKITEM_FILE_MEAS:
|
||||
case IMV_WORKITEM_DIR_REF_MEAS:
|
||||
case IMV_WORKITEM_DIR_MEAS:
|
||||
result_str = "pending file measurements";
|
||||
pending_file_meas++;
|
||||
break;
|
||||
case IMV_WORKITEM_TPM_ATTEST:
|
||||
attestation_state->finalize_components(attestation_state,
|
||||
result);
|
||||
result->write_data(result,
|
||||
chunk_from_str("; pending component evidence"));
|
||||
result->write_uint8(result, '\0');
|
||||
result_buf = result->get_buf(result);
|
||||
result_str = result_buf.ptr;
|
||||
break;
|
||||
default:
|
||||
result->destroy(result);
|
||||
continue;
|
||||
}
|
||||
session->remove_workitem(session, enumerator);
|
||||
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
|
||||
rec = workitem->set_result(workitem, result_str, eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, workitem);
|
||||
workitem->destroy(workitem);
|
||||
result->destroy(result);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (pending_file_meas)
|
||||
{
|
||||
DBG1(DBG_IMV, "failure due to %d pending file measurements",
|
||||
pending_file_meas);
|
||||
attestation_state->set_measurement_error(attestation_state,
|
||||
IMV_ATTESTATION_ERROR_FILE_MEAS_PEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
return this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, destroy, void,
|
||||
private_imv_attestation_agent_t *this)
|
||||
{
|
||||
if (this->pts_creds)
|
||||
{
|
||||
this->pts_credmgr->remove_set(this->pts_credmgr,
|
||||
this->pts_creds->get_set(this->pts_creds));
|
||||
this->pts_creds->destroy(this->pts_creds);
|
||||
}
|
||||
DESTROY_IF(this->pts_db);
|
||||
DESTROY_IF(this->pts_credmgr);
|
||||
DESTROY_IF(this->agent);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imv_agent_if_t *imv_attestation_agent_create(const char *name, TNC_IMVID id,
|
||||
TNC_Version *actual_version)
|
||||
{
|
||||
private_imv_attestation_agent_t *this;
|
||||
imv_agent_t *agent;
|
||||
char *hash_alg, *dh_group, *cadir;
|
||||
bool mandatory_dh_groups;
|
||||
|
||||
agent = imv_agent_create(name, msg_types, countof(msg_types), id,
|
||||
actual_version);
|
||||
if (!agent)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hash_alg = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imv-attestation.hash_algorithm", "sha256", lib->ns);
|
||||
dh_group = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imv-attestation.dh_group", "ecp256", lib->ns);
|
||||
mandatory_dh_groups = lib->settings->get_bool(lib->settings,
|
||||
"%s.plugins.imv-attestation.mandatory_dh_groups", TRUE, lib->ns);
|
||||
cadir = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imv-attestation.cadir", NULL, lib->ns);
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.bind_functions = _bind_functions,
|
||||
.notify_connection_change = _notify_connection_change,
|
||||
.receive_message = _receive_message,
|
||||
.receive_message_long = _receive_message_long,
|
||||
.batch_ending = _batch_ending,
|
||||
.solicit_recommendation = _solicit_recommendation,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.agent = agent,
|
||||
.supported_algorithms = PTS_MEAS_ALGO_NONE,
|
||||
.supported_dh_groups = PTS_DH_GROUP_NONE,
|
||||
.pts_credmgr = credential_manager_create(),
|
||||
.pts_creds = pts_creds_create(cadir),
|
||||
.pts_db = pts_database_create(imcv_db),
|
||||
);
|
||||
|
||||
if (!pts_meas_algo_probe(&this->supported_algorithms) ||
|
||||
!pts_dh_group_probe(&this->supported_dh_groups, mandatory_dh_groups) ||
|
||||
!pts_meas_algo_update(hash_alg, &this->supported_algorithms) ||
|
||||
!pts_dh_group_update(dh_group, &this->supported_dh_groups))
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (this->pts_creds)
|
||||
{
|
||||
this->pts_credmgr->add_set(this->pts_credmgr,
|
||||
this->pts_creds->get_set(this->pts_creds));
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 imv_attestation_agent_t imv_attestation_agent
|
||||
* @{ @ingroup imv_attestation
|
||||
*/
|
||||
|
||||
#ifndef IMV_ATTESTATION_AGENT_H_
|
||||
#define IMV_ATTESTATION_AGENT_H_
|
||||
|
||||
#include <imv/imv_agent_if.h>
|
||||
|
||||
/**
|
||||
* Creates a Attestation IMV agent
|
||||
*
|
||||
* @param name Name of the IMV
|
||||
* @param id ID of the IMV
|
||||
* @param actual_version TNC IF-IMV version
|
||||
*/
|
||||
imv_agent_if_t* imv_attestation_agent_create(const char* name, TNC_IMVID id,
|
||||
TNC_Version *actual_version);
|
||||
|
||||
#endif /** IMV_ATTESTATION_AGENT_H_ @}*/
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imv_attestation_build.h"
|
||||
#include "imv_attestation_state.h"
|
||||
|
||||
#include <tcg/pts/tcg_pts_attr_dh_nonce_params_req.h>
|
||||
#include <tcg/pts/tcg_pts_attr_dh_nonce_finish.h>
|
||||
#include <tcg/pts/tcg_pts_attr_get_tpm_version_info.h>
|
||||
#include <tcg/pts/tcg_pts_attr_get_aik.h>
|
||||
#include <tcg/pts/tcg_pts_attr_req_func_comp_evid.h>
|
||||
#include <tcg/pts/tcg_pts_attr_gen_attest_evid.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
|
||||
pts_dh_group_t supported_dh_groups,
|
||||
pts_database_t *pts_db)
|
||||
{
|
||||
imv_attestation_state_t *attestation_state;
|
||||
imv_attestation_handshake_state_t handshake_state;
|
||||
pts_t *pts;
|
||||
pa_tnc_attr_t *attr = NULL;
|
||||
|
||||
attestation_state = (imv_attestation_state_t*)state;
|
||||
handshake_state = attestation_state->get_handshake_state(attestation_state);
|
||||
pts = attestation_state->get_pts(attestation_state);
|
||||
|
||||
switch (handshake_state)
|
||||
{
|
||||
case IMV_ATTESTATION_STATE_NONCE_REQ:
|
||||
{
|
||||
int min_nonce_len;
|
||||
|
||||
/* Send DH nonce parameters request attribute */
|
||||
min_nonce_len = lib->settings->get_int(lib->settings,
|
||||
"%s.plugins.imv-attestation.min_nonce_len", 0, lib->ns);
|
||||
attr = tcg_pts_attr_dh_nonce_params_req_create(min_nonce_len,
|
||||
supported_dh_groups);
|
||||
attr->set_noskip_flag(attr, TRUE);
|
||||
out_msg->add_attribute(out_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;
|
||||
|
||||
if (!(state->get_action_flags(state) & IMV_ATTESTATION_DH_NONCE))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
/* Send Get TPM Version attribute */
|
||||
attr = tcg_pts_attr_get_tpm_version_info_create();
|
||||
attr->set_noskip_flag(attr, TRUE);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
/* Send Get AIK attribute */
|
||||
attr = tcg_pts_attr_get_aik_create();
|
||||
attr->set_noskip_flag(attr, TRUE);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
attestation_state->set_handshake_state(attestation_state,
|
||||
IMV_ATTESTATION_STATE_COMP_EVID);
|
||||
break;
|
||||
}
|
||||
case IMV_ATTESTATION_STATE_COMP_EVID:
|
||||
{
|
||||
tcg_pts_attr_req_func_comp_evid_t *attr_cast;
|
||||
enumerator_t *enumerator;
|
||||
pts_comp_func_name_t *name;
|
||||
uint8_t flags;
|
||||
uint32_t depth;
|
||||
bool first_component = TRUE;
|
||||
|
||||
attestation_state->set_handshake_state(attestation_state,
|
||||
IMV_ATTESTATION_STATE_END);
|
||||
|
||||
if (!pts->get_aik_id(pts))
|
||||
{
|
||||
attestation_state->set_measurement_error(attestation_state,
|
||||
IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
enumerator = attestation_state->create_component_enumerator(
|
||||
attestation_state);
|
||||
while (enumerator->enumerate(enumerator, &flags, &depth, &name))
|
||||
{
|
||||
if (first_component)
|
||||
{
|
||||
attr = tcg_pts_attr_req_func_comp_evid_create();
|
||||
attr->set_noskip_flag(attr, TRUE);
|
||||
first_component = FALSE;
|
||||
DBG2(DBG_IMV, "evidence request by");
|
||||
}
|
||||
name->log(name, " ");
|
||||
|
||||
/* TODO check flags against negotiated_caps */
|
||||
attr_cast = (tcg_pts_attr_req_func_comp_evid_t *)attr;
|
||||
attr_cast->add_component(attr_cast, flags, depth, name);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (attr)
|
||||
{
|
||||
/* Send Request Functional Component Evidence attribute */
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
/* Send Generate Attestation Evidence attribute */
|
||||
attr = tcg_pts_attr_gen_attest_evid_create();
|
||||
attr->set_noskip_flag(attr, TRUE);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
attestation_state->set_handshake_state(attestation_state,
|
||||
IMV_ATTESTATION_STATE_EVID_FINAL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 imv_attestation_build_t imv_attestation_build
|
||||
* @{ @ingroup imv_attestation
|
||||
*/
|
||||
|
||||
#ifndef IMV_ATTESTATION_BUILD_H_
|
||||
#define IMV_ATTESTATION_BUILD_H_
|
||||
|
||||
#include "imv_attestation_state.h"
|
||||
|
||||
#include <imv/imv_msg.h>
|
||||
#include <library.h>
|
||||
|
||||
#include <pts/pts_database.h>
|
||||
#include <pts/pts_dh_group.h>
|
||||
#include <pts/pts_meas_algo.h>
|
||||
|
||||
/**
|
||||
* Process a TCG PTS attribute
|
||||
*
|
||||
* @param out_msg outbound PA-TNC message to be built
|
||||
* @param state state of a given connection
|
||||
* @param supported_dh_groups supported DH groups
|
||||
* @param pts_db PTS configuration database
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
|
||||
pts_dh_group_t supported_dh_groups,
|
||||
pts_database_t *pts_db);
|
||||
|
||||
#endif /** IMV_ATTESTATION_BUILD_H_ @}*/
|
||||
@@ -0,0 +1,563 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 /* for stdndup() */
|
||||
#include <string.h>
|
||||
|
||||
#include "imv_attestation_process.h"
|
||||
|
||||
#include <imcv.h>
|
||||
#include <ietf/ietf_attr_pa_tnc_error.h>
|
||||
|
||||
#include <pts/pts.h>
|
||||
|
||||
#include <tcg/pts/tcg_pts_attr_aik.h>
|
||||
#include <tcg/pts/tcg_pts_attr_dh_nonce_params_resp.h>
|
||||
#include <tcg/pts/tcg_pts_attr_file_meas.h>
|
||||
#include <tcg/pts/tcg_pts_attr_meas_algo.h>
|
||||
#include <tcg/pts/tcg_pts_attr_proto_caps.h>
|
||||
#include <tcg/pts/tcg_pts_attr_simple_comp_evid.h>
|
||||
#include <tcg/pts/tcg_pts_attr_simple_evid_final.h>
|
||||
#include <tcg/pts/tcg_pts_attr_tpm_version_info.h>
|
||||
#include <tcg/pts/tcg_pts_attr_unix_file_meta.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
|
||||
imv_state_t *state,
|
||||
pts_meas_algorithms_t supported_algorithms,
|
||||
pts_dh_group_t supported_dh_groups,
|
||||
pts_database_t *pts_db,
|
||||
credential_manager_t *pts_credmgr)
|
||||
{
|
||||
imv_session_t *session;
|
||||
imv_attestation_state_t *attestation_state;
|
||||
pen_type_t attr_type;
|
||||
pts_t *pts;
|
||||
|
||||
session = state->get_session(state);
|
||||
attestation_state = (imv_attestation_state_t*)state;
|
||||
pts = attestation_state->get_pts(attestation_state);
|
||||
attr_type = attr->get_type(attr);
|
||||
|
||||
switch (attr_type.type)
|
||||
{
|
||||
case TCG_PTS_PROTO_CAPS:
|
||||
{
|
||||
tcg_pts_attr_proto_caps_t *attr_cast;
|
||||
pts_proto_caps_flag_t flags;
|
||||
|
||||
attr_cast = (tcg_pts_attr_proto_caps_t*)attr;
|
||||
flags = attr_cast->get_flags(attr_cast);
|
||||
pts->set_proto_caps(pts, flags);
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_MEAS_ALGO_SELECTION:
|
||||
{
|
||||
tcg_pts_attr_meas_algo_t *attr_cast;
|
||||
pts_meas_algorithms_t selected_algorithm;
|
||||
|
||||
attr_cast = (tcg_pts_attr_meas_algo_t*)attr;
|
||||
selected_algorithm = attr_cast->get_algorithms(attr_cast);
|
||||
if (!(selected_algorithm & supported_algorithms))
|
||||
{
|
||||
DBG1(DBG_IMV, "PTS-IMC selected unsupported"
|
||||
" measurement algorithm");
|
||||
return FALSE;
|
||||
}
|
||||
pts->set_meas_algorithm(pts, selected_algorithm);
|
||||
state->set_action_flags(state, IMV_ATTESTATION_ALGO);
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_DH_NONCE_PARAMS_RESP:
|
||||
{
|
||||
tcg_pts_attr_dh_nonce_params_resp_t *attr_cast;
|
||||
int nonce_len, min_nonce_len;
|
||||
pts_dh_group_t dh_group;
|
||||
pts_meas_algorithms_t offered_algorithms, selected_algorithm;
|
||||
chunk_t responder_value, responder_nonce;
|
||||
|
||||
attr_cast = (tcg_pts_attr_dh_nonce_params_resp_t*)attr;
|
||||
responder_nonce = attr_cast->get_responder_nonce(attr_cast);
|
||||
|
||||
/* check compliance of responder nonce length */
|
||||
min_nonce_len = lib->settings->get_int(lib->settings,
|
||||
"%s.plugins.imv-attestation.min_nonce_len", 0, lib->ns);
|
||||
nonce_len = responder_nonce.len;
|
||||
if (nonce_len < PTS_MIN_NONCE_LEN ||
|
||||
(min_nonce_len > 0 && nonce_len < min_nonce_len))
|
||||
{
|
||||
attr = pts_dh_nonce_error_create(
|
||||
max(PTS_MIN_NONCE_LEN, min_nonce_len),
|
||||
PTS_MAX_NONCE_LEN);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
dh_group = attr_cast->get_dh_group(attr_cast);
|
||||
if (!(dh_group & supported_dh_groups))
|
||||
{
|
||||
DBG1(DBG_IMV, "PTS-IMC selected unsupported DH group");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
offered_algorithms = attr_cast->get_hash_algo_set(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);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
break;
|
||||
}
|
||||
pts->set_dh_hash_algorithm(pts, selected_algorithm);
|
||||
|
||||
if (!pts->create_dh_nonce(pts, dh_group, nonce_len))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
responder_value = attr_cast->get_responder_value(attr_cast);
|
||||
pts->set_peer_public_value(pts, responder_value,
|
||||
responder_nonce);
|
||||
|
||||
/* Calculate secret assessment value */
|
||||
if (!pts->calculate_secret(pts))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
state->set_action_flags(state, IMV_ATTESTATION_DH_NONCE);
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_TPM_VERSION_INFO:
|
||||
{
|
||||
tcg_pts_attr_tpm_version_info_t *attr_cast;
|
||||
chunk_t tpm_version_info;
|
||||
|
||||
attr_cast = (tcg_pts_attr_tpm_version_info_t*)attr;
|
||||
tpm_version_info = attr_cast->get_tpm_version_info(attr_cast);
|
||||
pts->set_tpm_version_info(pts, tpm_version_info);
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_AIK:
|
||||
{
|
||||
tcg_pts_attr_aik_t *attr_cast;
|
||||
certificate_t *aik, *issuer;
|
||||
public_key_t *public;
|
||||
chunk_t keyid, keyid_hex, device_id;
|
||||
int aik_id;
|
||||
enumerator_t *e;
|
||||
bool trusted = FALSE, trusted_chain = FALSE;
|
||||
|
||||
attr_cast = (tcg_pts_attr_aik_t*)attr;
|
||||
aik = attr_cast->get_aik(attr_cast);
|
||||
if (!aik)
|
||||
{
|
||||
DBG1(DBG_IMV, "AIK unavailable");
|
||||
attestation_state->set_measurement_error(attestation_state,
|
||||
IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
|
||||
break;
|
||||
}
|
||||
|
||||
/* check trust into public key as stored in the database */
|
||||
public = aik->get_public_key(aik);
|
||||
public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid);
|
||||
DBG1(DBG_IMV, "verifying AIK with keyid %#B", &keyid);
|
||||
keyid_hex = chunk_to_hex(keyid, NULL, FALSE);
|
||||
if (session->get_device_id(session, &device_id) &&
|
||||
chunk_equals(keyid_hex, device_id))
|
||||
{
|
||||
trusted = session->get_device_trust(session);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IMV, "device ID unknown or different from AIK keyid");
|
||||
}
|
||||
DBG1(DBG_IMV, "AIK public key is %strusted", trusted ? "" : "not ");
|
||||
public->destroy(public);
|
||||
chunk_free(&keyid_hex);
|
||||
|
||||
if (aik->get_type(aik) == CERT_X509)
|
||||
{
|
||||
|
||||
e = pts_credmgr->create_trusted_enumerator(pts_credmgr,
|
||||
KEY_ANY, aik->get_issuer(aik), FALSE);
|
||||
while (e->enumerate(e, &issuer))
|
||||
{
|
||||
if (aik->issued_by(aik, issuer, NULL))
|
||||
{
|
||||
trusted_chain = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
DBG1(DBG_IMV, "AIK certificate is %strusted",
|
||||
trusted_chain ? "" : "not ");
|
||||
if (!trusted || !trusted_chain)
|
||||
{
|
||||
attestation_state->set_measurement_error(attestation_state,
|
||||
IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
session->get_session_id(session, NULL, &aik_id);
|
||||
pts->set_aik(pts, aik, aik_id);
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_FILE_MEAS:
|
||||
{
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
tcg_pts_attr_file_meas_t *attr_cast;
|
||||
uint16_t request_id;
|
||||
int arg_int, file_count;
|
||||
pts_meas_algorithms_t algo;
|
||||
pts_file_meas_t *measurements;
|
||||
imv_workitem_t *workitem, *found = NULL;
|
||||
imv_workitem_type_t type;
|
||||
char result_str[BUF_LEN];
|
||||
bool is_dir, correct;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
|
||||
algo = pts->get_meas_algorithm(pts);
|
||||
attr_cast = (tcg_pts_attr_file_meas_t*)attr;
|
||||
measurements = attr_cast->get_measurements(attr_cast);
|
||||
request_id = measurements->get_request_id(measurements);
|
||||
file_count = measurements->get_file_count(measurements);
|
||||
|
||||
DBG1(DBG_IMV, "measurement request %d returned %d file%s:",
|
||||
request_id, file_count, (file_count == 1) ? "":"s");
|
||||
|
||||
if (request_id)
|
||||
{
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
/* request ID consist of lower 16 bits of workitem ID */
|
||||
if ((workitem->get_id(workitem) & 0xffff) == request_id)
|
||||
{
|
||||
found = workitem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
DBG1(DBG_IMV, " no entry found for file measurement "
|
||||
"request %d", request_id);
|
||||
enumerator->destroy(enumerator);
|
||||
break;
|
||||
}
|
||||
type = found->get_type(found);
|
||||
arg_int = found->get_arg_int(found);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case IMV_WORKITEM_FILE_REF_MEAS:
|
||||
case IMV_WORKITEM_FILE_MEAS:
|
||||
is_dir = FALSE;
|
||||
break;
|
||||
case IMV_WORKITEM_DIR_REF_MEAS:
|
||||
case IMV_WORKITEM_DIR_MEAS:
|
||||
is_dir = TRUE;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case IMV_WORKITEM_FILE_MEAS:
|
||||
case IMV_WORKITEM_DIR_MEAS:
|
||||
{
|
||||
enumerator_t *e;
|
||||
|
||||
/* check hashes from database against measurements */
|
||||
e = pts_db->create_file_hash_enumerator(pts_db,
|
||||
pts->get_platform_id(pts),
|
||||
algo, is_dir, arg_int);
|
||||
if (!e)
|
||||
{
|
||||
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
correct = measurements->verify(measurements, e, is_dir);
|
||||
if (!correct)
|
||||
{
|
||||
attestation_state->set_measurement_error(
|
||||
attestation_state,
|
||||
IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL);
|
||||
eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
snprintf(result_str, BUF_LEN, "%s measurement%s correct",
|
||||
is_dir ? "directory" : "file",
|
||||
correct ? "" : " not");
|
||||
break;
|
||||
}
|
||||
case IMV_WORKITEM_FILE_REF_MEAS:
|
||||
case IMV_WORKITEM_DIR_REF_MEAS:
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *filename;
|
||||
chunk_t measurement;
|
||||
|
||||
e = measurements->create_enumerator(measurements);
|
||||
while (e->enumerate(e, &filename, &measurement))
|
||||
{
|
||||
if (pts_db->add_file_measurement(pts_db,
|
||||
pts->get_platform_id(pts), algo, measurement,
|
||||
filename, is_dir, arg_int) != SUCCESS)
|
||||
{
|
||||
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
snprintf(result_str, BUF_LEN, "%s reference measurement "
|
||||
"successful", is_dir ? "directory" : "file");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
session->remove_workitem(session, enumerator);
|
||||
enumerator->destroy(enumerator);
|
||||
rec = found->set_result(found, result_str, eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, found);
|
||||
found->destroy(found);
|
||||
}
|
||||
else
|
||||
{
|
||||
measurements->check(measurements, pts_db,
|
||||
pts->get_platform_id(pts), algo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_UNIX_FILE_META:
|
||||
{
|
||||
tcg_pts_attr_file_meta_t *attr_cast;
|
||||
int file_count;
|
||||
pts_file_meta_t *metadata;
|
||||
pts_file_metadata_t *entry;
|
||||
time_t created, modified, accessed;
|
||||
bool utc = FALSE;
|
||||
enumerator_t *e;
|
||||
|
||||
attr_cast = (tcg_pts_attr_file_meta_t*)attr;
|
||||
metadata = attr_cast->get_metadata(attr_cast);
|
||||
file_count = metadata->get_file_count(metadata);
|
||||
|
||||
DBG1(DBG_IMV, "metadata request returned %d file%s:",
|
||||
file_count, (file_count == 1) ? "":"s");
|
||||
|
||||
e = metadata->create_enumerator(metadata);
|
||||
while (e->enumerate(e, &entry))
|
||||
{
|
||||
DBG1(DBG_IMV, " '%s' (%"PRIu64" bytes)"
|
||||
" owner %"PRIu64", group %"PRIu64", type %N",
|
||||
entry->filename, entry->filesize, entry->owner,
|
||||
entry->group, pts_file_type_names, entry->type);
|
||||
|
||||
created = entry->created;
|
||||
modified = entry->modified;
|
||||
accessed = entry->accessed;
|
||||
|
||||
DBG1(DBG_IMV, " created %T, modified %T, accessed %T",
|
||||
&created, utc, &modified, utc, &accessed, utc);
|
||||
}
|
||||
e->destroy(e);
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_SIMPLE_COMP_EVID:
|
||||
{
|
||||
tcg_pts_attr_simple_comp_evid_t *attr_cast;
|
||||
pts_comp_func_name_t *name;
|
||||
pts_comp_evidence_t *evidence;
|
||||
pts_component_t *comp;
|
||||
uint32_t depth;
|
||||
status_t status;
|
||||
|
||||
attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr;
|
||||
evidence = attr_cast->get_comp_evidence(attr_cast);
|
||||
name = evidence->get_comp_func_name(evidence, &depth);
|
||||
|
||||
comp = attestation_state->get_component(attestation_state, name);
|
||||
if (!comp)
|
||||
{
|
||||
DBG1(DBG_IMV, " no entry found for component evidence request");
|
||||
break;
|
||||
}
|
||||
status = comp->verify(comp, name->get_qualifier(name), pts, evidence);
|
||||
if (status == VERIFY_ERROR || status == FAILED)
|
||||
{
|
||||
attestation_state->set_measurement_error(attestation_state,
|
||||
IMV_ATTESTATION_ERROR_COMP_EVID_FAIL);
|
||||
name->log(name, " measurement mismatch for ");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TCG_PTS_SIMPLE_EVID_FINAL:
|
||||
{
|
||||
tcg_pts_attr_simple_evid_final_t *attr_cast;
|
||||
uint8_t flags;
|
||||
pts_meas_algorithms_t comp_hash_algorithm;
|
||||
chunk_t pcr_comp, tpm_quote_sig, evid_sig;
|
||||
chunk_t pcr_composite, quote_info, result_buf;
|
||||
imv_workitem_t *workitem;
|
||||
imv_reason_string_t *reason_string;
|
||||
enumerator_t *enumerator;
|
||||
bool use_quote2, use_ver_info;
|
||||
bio_writer_t *result;
|
||||
|
||||
attr_cast = (tcg_pts_attr_simple_evid_final_t*)attr;
|
||||
flags = attr_cast->get_quote_info(attr_cast, &comp_hash_algorithm,
|
||||
&pcr_comp, &tpm_quote_sig);
|
||||
|
||||
if (flags != PTS_SIMPLE_EVID_FINAL_NO)
|
||||
{
|
||||
use_quote2 = (flags == PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2 ||
|
||||
flags == PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2_CAP_VER);
|
||||
use_ver_info = (flags == PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2_CAP_VER);
|
||||
|
||||
/* Construct PCR Composite and TPM Quote Info structures */
|
||||
if (!pts->get_quote_info(pts, use_quote2, use_ver_info,
|
||||
comp_hash_algorithm, &pcr_composite, "e_info))
|
||||
{
|
||||
DBG1(DBG_IMV, "unable to construct TPM Quote Info");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!chunk_equals(pcr_comp, pcr_composite))
|
||||
{
|
||||
DBG1(DBG_IMV, "received PCR Composite does not match "
|
||||
"constructed one");
|
||||
attestation_state->set_measurement_error(attestation_state,
|
||||
IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL);
|
||||
goto quote_error;
|
||||
}
|
||||
DBG2(DBG_IMV, "received PCR Composite matches constructed one");
|
||||
|
||||
if (!pts->verify_quote_signature(pts, quote_info, tpm_quote_sig))
|
||||
{
|
||||
attestation_state->set_measurement_error(attestation_state,
|
||||
IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL);
|
||||
goto quote_error;
|
||||
}
|
||||
DBG2(DBG_IMV, "TPM Quote Info signature verification successful");
|
||||
|
||||
quote_error:
|
||||
free(pcr_composite.ptr);
|
||||
free(quote_info.ptr);
|
||||
|
||||
/**
|
||||
* Finalize any pending measurement registrations and check
|
||||
* if all expected component measurements were received
|
||||
*/
|
||||
result = bio_writer_create(128);
|
||||
attestation_state->finalize_components(attestation_state,
|
||||
result);
|
||||
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_type(workitem) == IMV_WORKITEM_TPM_ATTEST)
|
||||
{
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
uint32_t error;
|
||||
|
||||
error = attestation_state->get_measurement_error(
|
||||
attestation_state);
|
||||
if (error & (IMV_ATTESTATION_ERROR_COMP_EVID_FAIL |
|
||||
IMV_ATTESTATION_ERROR_COMP_EVID_PEND |
|
||||
IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL))
|
||||
{
|
||||
reason_string = imv_reason_string_create("en", ", ");
|
||||
attestation_state->add_comp_evid_reasons(
|
||||
attestation_state, reason_string);
|
||||
result->write_data(result, chunk_from_str("; "));
|
||||
result->write_data(result,
|
||||
reason_string->get_encoding(reason_string));
|
||||
reason_string->destroy(reason_string);
|
||||
eval = TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MINOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
|
||||
}
|
||||
session->remove_workitem(session, enumerator);
|
||||
|
||||
result->write_uint8(result, '\0');
|
||||
result_buf = result->get_buf(result);
|
||||
rec = workitem->set_result(workitem, result_buf.ptr,
|
||||
eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, workitem);
|
||||
workitem->destroy(workitem);
|
||||
attestation_state->set_handshake_state(attestation_state,
|
||||
IMV_ATTESTATION_STATE_END);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
result->destroy(result);
|
||||
}
|
||||
|
||||
if (attr_cast->get_evid_sig(attr_cast, &evid_sig))
|
||||
{
|
||||
/** TODO: What to do with Evidence Signature */
|
||||
DBG1(DBG_IMV, "this version of the Attestation IMV can not "
|
||||
"handle Evidence Signatures");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: Not implemented yet */
|
||||
case TCG_PTS_INTEG_MEAS_LOG:
|
||||
/* Attributes using XML */
|
||||
case TCG_PTS_TEMPL_REF_MANI_SET_META:
|
||||
case TCG_PTS_VERIFICATION_RESULT:
|
||||
case TCG_PTS_INTEG_REPORT:
|
||||
/* On Windows only*/
|
||||
case TCG_PTS_WIN_FILE_META:
|
||||
case TCG_PTS_REGISTRY_VALUE:
|
||||
/* Received on IMC side only*/
|
||||
case TCG_PTS_REQ_PROTO_CAPS:
|
||||
case TCG_PTS_DH_NONCE_PARAMS_REQ:
|
||||
case TCG_PTS_DH_NONCE_FINISH:
|
||||
case TCG_PTS_MEAS_ALGO:
|
||||
case TCG_PTS_GET_TPM_VERSION_INFO:
|
||||
case TCG_PTS_REQ_TEMPL_REF_MANI_SET_META:
|
||||
case TCG_PTS_UPDATE_TEMPL_REF_MANI:
|
||||
case TCG_PTS_GET_AIK:
|
||||
case TCG_PTS_REQ_FUNC_COMP_EVID:
|
||||
case TCG_PTS_GEN_ATTEST_EVID:
|
||||
case TCG_PTS_REQ_FILE_META:
|
||||
case TCG_PTS_REQ_FILE_MEAS:
|
||||
case TCG_PTS_REQ_INTEG_MEAS_LOG:
|
||||
default:
|
||||
DBG1(DBG_IMV, "received unsupported attribute '%N'",
|
||||
tcg_attr_names, attr->get_type(attr));
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 imv_attestation_process_t imv_attestation_process
|
||||
* @{ @ingroup imv_attestation
|
||||
*/
|
||||
|
||||
#ifndef IMV_ATTESTATION_PROCESS_H_
|
||||
#define IMV_ATTESTATION_PROCESS_H_
|
||||
|
||||
#include "imv_attestation_state.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <credentials/credential_manager.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
#include <imv/imv_msg.h>
|
||||
#include <pa_tnc/pa_tnc_attr.h>
|
||||
|
||||
#include <pts/pts_database.h>
|
||||
#include <pts/pts_dh_group.h>
|
||||
#include <pts/pts_meas_algo.h>
|
||||
|
||||
/**
|
||||
* Process a TCG PTS attribute
|
||||
*
|
||||
* @param attr PA-TNC attribute to be processed
|
||||
* @param out_msg PA-TNC message containing error messages
|
||||
* @param state state of a given connection
|
||||
* @param supported_algorithms supported PTS measurement algorithms
|
||||
* @param supported_dh_groups supported DH groups
|
||||
* @param pts_db PTS configuration database
|
||||
* @param pts_credmgr PTS credential manager
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
|
||||
imv_state_t *state,
|
||||
pts_meas_algorithms_t supported_algorithms,
|
||||
pts_dh_group_t supported_dh_groups,
|
||||
pts_database_t *pts_db,
|
||||
credential_manager_t *pts_credmgr);
|
||||
|
||||
#endif /** IMV_ATTESTATION_PROCESS_H_ @}*/
|
||||
@@ -0,0 +1,560 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imv_attestation_state.h"
|
||||
|
||||
#include <imcv.h>
|
||||
#include <imv/imv_lang_string.h>
|
||||
#include "imv/imv_reason_string.h"
|
||||
|
||||
#include <tncif_policy.h>
|
||||
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_imv_attestation_state_t private_imv_attestation_state_t;
|
||||
typedef struct file_meas_request_t file_meas_request_t;
|
||||
typedef struct func_comp_t func_comp_t;
|
||||
|
||||
/**
|
||||
* Private data of an imv_attestation_state_t object.
|
||||
*/
|
||||
struct private_imv_attestation_state_t {
|
||||
|
||||
/**
|
||||
* Public members of imv_attestation_state_t
|
||||
*/
|
||||
imv_attestation_state_t public;
|
||||
|
||||
/**
|
||||
* TNCCS connection ID
|
||||
*/
|
||||
TNC_ConnectionID connection_id;
|
||||
|
||||
/**
|
||||
* TNCCS connection state
|
||||
*/
|
||||
TNC_ConnectionState state;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support long message types?
|
||||
*/
|
||||
bool has_long;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support exclusive delivery?
|
||||
*/
|
||||
bool has_excl;
|
||||
|
||||
/**
|
||||
* Maximum PA-TNC message size for this TNCCS connection
|
||||
*/
|
||||
uint32_t max_msg_len;
|
||||
|
||||
/**
|
||||
* Flags set for completed actions
|
||||
*/
|
||||
uint32_t action_flags;
|
||||
|
||||
/**
|
||||
* IMV database session associated with TNCCS connection
|
||||
*/
|
||||
imv_session_t *session;
|
||||
|
||||
/**
|
||||
* PA-TNC attribute segmentation contracts associated with TNCCS connection
|
||||
*/
|
||||
seg_contract_manager_t *contracts;
|
||||
|
||||
/**
|
||||
* IMV Attestation handshake state
|
||||
*/
|
||||
imv_attestation_handshake_state_t handshake_state;
|
||||
|
||||
/**
|
||||
* IMV action recommendation
|
||||
*/
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
|
||||
/**
|
||||
* IMV evaluation result
|
||||
*/
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
|
||||
/**
|
||||
* List of Functional Components
|
||||
*/
|
||||
linked_list_t *components;
|
||||
|
||||
/**
|
||||
* PTS object
|
||||
*/
|
||||
pts_t *pts;
|
||||
|
||||
/**
|
||||
* Measurement error flags
|
||||
*/
|
||||
uint32_t measurement_error;
|
||||
|
||||
/**
|
||||
* TNC Reason String
|
||||
*/
|
||||
imv_reason_string_t *reason_string;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* PTS Functional Component entry
|
||||
*/
|
||||
struct func_comp_t {
|
||||
pts_component_t *comp;
|
||||
pts_comp_func_name_t* name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Frees a func_comp_t object
|
||||
*/
|
||||
static void free_func_comp(func_comp_t *this)
|
||||
{
|
||||
this->comp->destroy(this->comp);
|
||||
this->name->destroy(this->name);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supported languages
|
||||
*/
|
||||
static char* languages[] = { "en", "de", "mn" };
|
||||
|
||||
/**
|
||||
* Table of reason strings
|
||||
*/
|
||||
static imv_lang_string_t reason_file_meas_fail[] = {
|
||||
{ "en", "Incorrect file measurement" },
|
||||
{ "de", "Falsche Dateimessung" },
|
||||
{ "mn", "Буруу байгаа файл" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static imv_lang_string_t reason_file_meas_pend[] = {
|
||||
{ "en", "Pending file measurement" },
|
||||
{ "de", "Ausstehende Dateimessung" },
|
||||
{ "mn", "Xүлээгдэж байгаа файл" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static imv_lang_string_t reason_no_trusted_aik[] = {
|
||||
{ "en", "No trusted AIK available" },
|
||||
{ "de", "Kein vetrauenswürdiger AIK verfügbar" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static imv_lang_string_t reason_comp_evid_fail[] = {
|
||||
{ "en", "Incorrect component evidence" },
|
||||
{ "de", "Falsche Komponenten-Evidenz" },
|
||||
{ "mn", "Буруу компонент хэмжилт" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static imv_lang_string_t reason_comp_evid_pend[] = {
|
||||
{ "en", "Pending component evidence" },
|
||||
{ "de", "Ausstehende Komponenten-Evidenz" },
|
||||
{ "mn", "Xүлээгдэж компонент хэмжилт" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static imv_lang_string_t reason_tpm_quote_fail[] = {
|
||||
{ "en", "Invalid TPM Quote signature received" },
|
||||
{ "de", "Falsche TPM Quote Signature erhalten" },
|
||||
{ "mn", "Буруу TPM Quote гарын үсэг" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->connection_id;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, has_long, bool,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->has_long;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, has_excl, bool,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->has_excl;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_flags, void,
|
||||
private_imv_attestation_state_t *this, bool has_long, bool has_excl)
|
||||
{
|
||||
this->has_long = has_long;
|
||||
this->has_excl = has_excl;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_max_msg_len, void,
|
||||
private_imv_attestation_state_t *this, uint32_t max_msg_len)
|
||||
{
|
||||
this->max_msg_len = max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_max_msg_len, uint32_t,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_action_flags, void,
|
||||
private_imv_attestation_state_t *this, uint32_t flags)
|
||||
{
|
||||
this->action_flags |= flags;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_action_flags, uint32_t,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->action_flags;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_session, void,
|
||||
private_imv_attestation_state_t *this, imv_session_t *session)
|
||||
{
|
||||
this->session = session;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_session, imv_session_t*,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->session;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->contracts;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, change_state, void,
|
||||
private_imv_attestation_state_t *this, TNC_ConnectionState new_state)
|
||||
{
|
||||
this->state = new_state;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_recommendation, void,
|
||||
private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation *rec,
|
||||
TNC_IMV_Evaluation_Result *eval)
|
||||
{
|
||||
*rec = this->rec;
|
||||
*eval = this->eval;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_recommendation, void,
|
||||
private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation rec,
|
||||
TNC_IMV_Evaluation_Result eval)
|
||||
{
|
||||
this->rec = rec;
|
||||
this->eval = eval;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, update_recommendation, void,
|
||||
private_imv_attestation_state_t *this, TNC_IMV_Action_Recommendation rec,
|
||||
TNC_IMV_Evaluation_Result eval)
|
||||
{
|
||||
this->rec = tncif_policy_update_recommendation(this->rec, rec);
|
||||
this->eval = tncif_policy_update_evaluation(this->eval, eval);
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, add_file_meas_reasons, void,
|
||||
private_imv_attestation_state_t *this, imv_reason_string_t *reason_string)
|
||||
{
|
||||
if (this->measurement_error & IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL)
|
||||
{
|
||||
reason_string->add_reason(reason_string, reason_file_meas_fail);
|
||||
}
|
||||
if (this->measurement_error & IMV_ATTESTATION_ERROR_FILE_MEAS_PEND)
|
||||
{
|
||||
reason_string->add_reason(reason_string, reason_file_meas_pend);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, add_comp_evid_reasons, void,
|
||||
private_imv_attestation_state_t *this, imv_reason_string_t *reason_string)
|
||||
{
|
||||
if (this->measurement_error & IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK)
|
||||
{
|
||||
reason_string->add_reason(reason_string, reason_no_trusted_aik);
|
||||
}
|
||||
if (this->measurement_error & IMV_ATTESTATION_ERROR_COMP_EVID_FAIL)
|
||||
{
|
||||
reason_string->add_reason(reason_string, reason_comp_evid_fail);
|
||||
}
|
||||
if (this->measurement_error & IMV_ATTESTATION_ERROR_COMP_EVID_PEND)
|
||||
{
|
||||
reason_string->add_reason(reason_string, reason_comp_evid_pend);
|
||||
}
|
||||
if (this->measurement_error & IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL)
|
||||
{
|
||||
reason_string->add_reason(reason_string, reason_tpm_quote_fail);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_reason_string, bool,
|
||||
private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
|
||||
chunk_t *reason_string, char **reason_language)
|
||||
{
|
||||
*reason_language = imv_lang_string_select_lang(language_enumerator,
|
||||
languages, countof(languages));
|
||||
|
||||
/* Instantiate a TNC Reason String object */
|
||||
DESTROY_IF(this->reason_string);
|
||||
this->reason_string = imv_reason_string_create(*reason_language, "\n");
|
||||
add_file_meas_reasons(this, this->reason_string);
|
||||
add_comp_evid_reasons(this, this->reason_string);
|
||||
*reason_string = this->reason_string->get_encoding(this->reason_string);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_remediation_instructions, bool,
|
||||
private_imv_attestation_state_t *this, enumerator_t *language_enumerator,
|
||||
chunk_t *string, char **lang_code, char **uri)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, destroy, void,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
DESTROY_IF(this->session);
|
||||
DESTROY_IF(this->reason_string);
|
||||
this->components->destroy_function(this->components, (void *)free_func_comp);
|
||||
this->pts->destroy(this->pts);
|
||||
this->contracts->destroy(this->contracts);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, get_handshake_state,
|
||||
imv_attestation_handshake_state_t, private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->handshake_state;
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, set_handshake_state, void,
|
||||
private_imv_attestation_state_t *this,
|
||||
imv_attestation_handshake_state_t new_state)
|
||||
{
|
||||
this->handshake_state = new_state;
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, get_pts, pts_t*,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->pts;
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, create_component, pts_component_t*,
|
||||
private_imv_attestation_state_t *this, pts_comp_func_name_t *name,
|
||||
uint32_t depth, pts_database_t *pts_db)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
func_comp_t *entry, *new_entry;
|
||||
pts_component_t *component;
|
||||
bool found = FALSE;
|
||||
|
||||
enumerator = this->components->create_enumerator(this->components);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (name->equals(name, entry->comp->get_comp_func_name(entry->comp)))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (name->equals(name, entry->name))
|
||||
{
|
||||
/* duplicate entry */
|
||||
return NULL;
|
||||
}
|
||||
new_entry = malloc_thing(func_comp_t);
|
||||
new_entry->name = name->clone(name);
|
||||
new_entry->comp = entry->comp->get_ref(entry->comp);
|
||||
this->components->insert_last(this->components, new_entry);
|
||||
return entry->comp;
|
||||
}
|
||||
else
|
||||
{
|
||||
component = imcv_pts_components->create(imcv_pts_components,
|
||||
name, depth, pts_db);
|
||||
if (!component)
|
||||
{
|
||||
/* unsupported component */
|
||||
return NULL;
|
||||
}
|
||||
new_entry = malloc_thing(func_comp_t);
|
||||
new_entry->name = name->clone(name);
|
||||
new_entry->comp = component;
|
||||
this->components->insert_last(this->components, new_entry);
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerate file measurement entries
|
||||
*/
|
||||
static bool entry_filter(void *null, func_comp_t **entry, uint8_t *flags,
|
||||
void *i2, uint32_t *depth,
|
||||
void *i3, pts_comp_func_name_t **comp_name)
|
||||
{
|
||||
pts_component_t *comp;
|
||||
pts_comp_func_name_t *name;
|
||||
|
||||
comp = (*entry)->comp;
|
||||
name = (*entry)->name;
|
||||
|
||||
*flags = comp->get_evidence_flags(comp);
|
||||
*depth = comp->get_depth(comp);
|
||||
*comp_name = name;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, create_component_enumerator, enumerator_t*,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return enumerator_create_filter(
|
||||
this->components->create_enumerator(this->components),
|
||||
(void*)entry_filter, NULL, NULL);
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, get_component, pts_component_t*,
|
||||
private_imv_attestation_state_t *this, pts_comp_func_name_t *name)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
func_comp_t *entry;
|
||||
pts_component_t *found = NULL;
|
||||
|
||||
enumerator = this->components->create_enumerator(this->components);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (name->equals(name, entry->name))
|
||||
{
|
||||
found = entry->comp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
return found;
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, get_measurement_error, uint32_t,
|
||||
private_imv_attestation_state_t *this)
|
||||
{
|
||||
return this->measurement_error;
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, set_measurement_error, void,
|
||||
private_imv_attestation_state_t *this, uint32_t error)
|
||||
{
|
||||
this->measurement_error |= error;
|
||||
}
|
||||
|
||||
METHOD(imv_attestation_state_t, finalize_components, void,
|
||||
private_imv_attestation_state_t *this, bio_writer_t *result)
|
||||
{
|
||||
func_comp_t *entry;
|
||||
bool first = TRUE;
|
||||
|
||||
while (this->components->remove_last(this->components,
|
||||
(void**)&entry) == SUCCESS)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
first = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
result->write_data(result, chunk_from_str("; "));
|
||||
}
|
||||
if (!entry->comp->finalize(entry->comp,
|
||||
entry->name->get_qualifier(entry->name),
|
||||
result))
|
||||
{
|
||||
set_measurement_error(this, IMV_ATTESTATION_ERROR_COMP_EVID_PEND);
|
||||
}
|
||||
free_func_comp(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
|
||||
{
|
||||
private_imv_attestation_state_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.interface = {
|
||||
.get_connection_id = _get_connection_id,
|
||||
.has_long = _has_long,
|
||||
.has_excl = _has_excl,
|
||||
.set_flags = _set_flags,
|
||||
.set_max_msg_len = _set_max_msg_len,
|
||||
.get_max_msg_len = _get_max_msg_len,
|
||||
.set_action_flags = _set_action_flags,
|
||||
.get_action_flags = _get_action_flags,
|
||||
.set_session = _set_session,
|
||||
.get_session = _get_session,
|
||||
.get_contracts = _get_contracts,
|
||||
.change_state = _change_state,
|
||||
.get_recommendation = _get_recommendation,
|
||||
.set_recommendation = _set_recommendation,
|
||||
.update_recommendation = _update_recommendation,
|
||||
.get_reason_string = _get_reason_string,
|
||||
.get_remediation_instructions = _get_remediation_instructions,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_handshake_state = _get_handshake_state,
|
||||
.set_handshake_state = _set_handshake_state,
|
||||
.get_pts = _get_pts,
|
||||
.create_component = _create_component,
|
||||
.create_component_enumerator = _create_component_enumerator,
|
||||
.get_component = _get_component,
|
||||
.finalize_components = _finalize_components,
|
||||
.get_measurement_error = _get_measurement_error,
|
||||
.set_measurement_error = _set_measurement_error,
|
||||
.add_file_meas_reasons = _add_file_meas_reasons,
|
||||
.add_comp_evid_reasons = _add_comp_evid_reasons,
|
||||
},
|
||||
.connection_id = connection_id,
|
||||
.state = TNC_CONNECTION_STATE_CREATE,
|
||||
.handshake_state = IMV_ATTESTATION_STATE_INIT,
|
||||
.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
|
||||
.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
|
||||
.contracts = seg_contract_manager_create(),
|
||||
.components = linked_list_create(),
|
||||
.pts = pts_create(FALSE),
|
||||
);
|
||||
|
||||
return &this->public.interface;
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 imv_attestation imv_attestation
|
||||
* @ingroup libimcv_plugins
|
||||
*
|
||||
* @defgroup imv_attestation_state_t imv_attestation_state
|
||||
* @{ @ingroup imv_attestation
|
||||
*/
|
||||
|
||||
#ifndef IMV_ATTESTATION_STATE_H_
|
||||
#define IMV_ATTESTATION_STATE_H_
|
||||
|
||||
#include <imv/imv_state.h>
|
||||
#include <imv/imv_reason_string.h>
|
||||
#include <pts/pts.h>
|
||||
#include <pts/pts_database.h>
|
||||
#include <pts/components/pts_component.h>
|
||||
|
||||
#include <library.h>
|
||||
#include <bio/bio_writer.h>
|
||||
|
||||
typedef struct imv_attestation_state_t imv_attestation_state_t;
|
||||
typedef enum imv_attestation_flag_t imv_attestation_flag_t;
|
||||
typedef enum imv_attestation_handshake_state_t imv_attestation_handshake_state_t;
|
||||
typedef enum imv_meas_error_t imv_meas_error_t;
|
||||
|
||||
/**
|
||||
* IMV Attestation Flags set for completed actions
|
||||
*/
|
||||
enum imv_attestation_flag_t {
|
||||
IMV_ATTESTATION_ATTR_PRODUCT_INFO = (1<<0),
|
||||
IMV_ATTESTATION_ATTR_STRING_VERSION = (1<<1),
|
||||
IMV_ATTESTATION_ATTR_DEVICE_ID = (1<<2),
|
||||
IMV_ATTESTATION_ATTR_MUST = (1<<3)-1,
|
||||
IMV_ATTESTATION_ATTR_REQ = (1<<3),
|
||||
IMV_ATTESTATION_ALGO = (1<<4),
|
||||
IMV_ATTESTATION_DH_NONCE = (1<<5),
|
||||
IMV_ATTESTATION_FILE_MEAS = (1<<6),
|
||||
IMV_ATTESTATION_REC = (1<<7)
|
||||
};
|
||||
|
||||
/**
|
||||
* IMV Attestation Handshake States (state machine)
|
||||
*/
|
||||
enum imv_attestation_handshake_state_t {
|
||||
IMV_ATTESTATION_STATE_INIT,
|
||||
IMV_ATTESTATION_STATE_DISCOVERY,
|
||||
IMV_ATTESTATION_STATE_NONCE_REQ,
|
||||
IMV_ATTESTATION_STATE_TPM_INIT,
|
||||
IMV_ATTESTATION_STATE_COMP_EVID,
|
||||
IMV_ATTESTATION_STATE_EVID_FINAL,
|
||||
IMV_ATTESTATION_STATE_END,
|
||||
};
|
||||
|
||||
/**
|
||||
* IMV Measurement Error Types
|
||||
*/
|
||||
enum imv_meas_error_t {
|
||||
IMV_ATTESTATION_ERROR_FILE_MEAS_FAIL = 1,
|
||||
IMV_ATTESTATION_ERROR_FILE_MEAS_PEND = 2,
|
||||
IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK = 4,
|
||||
IMV_ATTESTATION_ERROR_COMP_EVID_FAIL = 8,
|
||||
IMV_ATTESTATION_ERROR_COMP_EVID_PEND = 16,
|
||||
IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL = 32
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal state of an imv_attestation_t connection instance
|
||||
*/
|
||||
struct imv_attestation_state_t {
|
||||
|
||||
/**
|
||||
* imv_state_t interface
|
||||
*/
|
||||
imv_state_t interface;
|
||||
|
||||
/**
|
||||
* Get state of the handshake
|
||||
*
|
||||
* @return the handshake state of IMV
|
||||
*/
|
||||
imv_attestation_handshake_state_t (*get_handshake_state)(
|
||||
imv_attestation_state_t *this);
|
||||
|
||||
/**
|
||||
* Set state of the handshake
|
||||
*
|
||||
* @param new_state the handshake state of IMV
|
||||
*/
|
||||
void (*set_handshake_state)(imv_attestation_state_t *this,
|
||||
imv_attestation_handshake_state_t new_state);
|
||||
|
||||
/**
|
||||
* Get the PTS object
|
||||
*
|
||||
* @return PTS object
|
||||
*/
|
||||
pts_t* (*get_pts)(imv_attestation_state_t *this);
|
||||
|
||||
/**
|
||||
* Create and add an entry to the list of Functional Components
|
||||
*
|
||||
* @param name Component Functional Name
|
||||
* @param depth Sub-component Depth
|
||||
* @param pts_db PTS measurement database
|
||||
* @return created functional component instance or NULL
|
||||
*/
|
||||
pts_component_t* (*create_component)(imv_attestation_state_t *this,
|
||||
pts_comp_func_name_t *name,
|
||||
uint32_t depth,
|
||||
pts_database_t *pts_db);
|
||||
|
||||
/**
|
||||
* Enumerate over all Functional Components
|
||||
*
|
||||
* @return Functional Component enumerator
|
||||
*/
|
||||
enumerator_t* (*create_component_enumerator)(imv_attestation_state_t *this);
|
||||
|
||||
/**
|
||||
* Get a Functional Component with a given name
|
||||
*
|
||||
* @param name Name of the requested Functional Component
|
||||
* @return Functional Component if found, NULL otherwise
|
||||
*/
|
||||
pts_component_t* (*get_component)(imv_attestation_state_t *this,
|
||||
pts_comp_func_name_t *name);
|
||||
|
||||
/**
|
||||
* Tell the Functional Components to finalize any measurement registrations
|
||||
* and to check if all expected measurements were received
|
||||
*
|
||||
* @param result Writer appending component measurement results
|
||||
*/
|
||||
void (*finalize_components)(imv_attestation_state_t *this,
|
||||
bio_writer_t *result);
|
||||
|
||||
/**
|
||||
* Indicates the types of measurement errors that occurred
|
||||
*
|
||||
* @return Measurement error flags
|
||||
*/
|
||||
uint32_t (*get_measurement_error)(imv_attestation_state_t *this);
|
||||
|
||||
/**
|
||||
* Call if a measurement error is encountered
|
||||
*
|
||||
* @param error Measurement error type
|
||||
*/
|
||||
void (*set_measurement_error)(imv_attestation_state_t *this,
|
||||
uint32_t error);
|
||||
|
||||
/**
|
||||
* Returns a concatenation of File Measurement reason strings
|
||||
*
|
||||
* @param reason_string Concatenated reason strings
|
||||
*/
|
||||
void (*add_file_meas_reasons)(imv_attestation_state_t *this,
|
||||
imv_reason_string_t *reason_string);
|
||||
|
||||
/**
|
||||
* Returns a concatenation of Component Evidence reason strings
|
||||
*
|
||||
* @param reason_string Concatenated reason strings
|
||||
*/
|
||||
void (*add_comp_evid_reasons)(imv_attestation_state_t *this,
|
||||
imv_reason_string_t *reason_string);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an imv_attestation_state_t instance
|
||||
*
|
||||
* @param id connection ID
|
||||
*/
|
||||
imv_state_t* imv_attestation_state_create(TNC_ConnectionID id);
|
||||
|
||||
#endif /** IMV_ATTESTATION_STATE_H_ @}*/
|
||||
@@ -0,0 +1,21 @@
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-I$(top_srcdir)/src/libtncif \
|
||||
-I$(top_srcdir)/src/libimcv
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(PLUGIN_CFLAGS) $(json_CFLAGS)
|
||||
|
||||
imcv_LTLIBRARIES = imv-swid.la
|
||||
|
||||
imv_swid_la_LIBADD = \
|
||||
$(top_builddir)/src/libimcv/libimcv.la \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la \
|
||||
$(json_LIBS)
|
||||
|
||||
imv_swid_la_SOURCES = \
|
||||
imv_swid.c imv_swid_state.h imv_swid_state.c \
|
||||
imv_swid_agent.h imv_swid_agent.c \
|
||||
imv_swid_rest.h imv_swid_rest.c
|
||||
|
||||
imv_swid_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imv_swid_agent.h"
|
||||
|
||||
static const char imv_name[] = "SWID";
|
||||
static const imv_agent_create_t imv_agent_create = imv_swid_agent_create;
|
||||
|
||||
/* include generic TGC TNC IF-IMV API code below */
|
||||
|
||||
#include <imv/imv_if.h>
|
||||
|
||||
@@ -0,0 +1,751 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
|
||||
#include "imv_swid_agent.h"
|
||||
#include "imv_swid_state.h"
|
||||
#include "imv_swid_rest.h"
|
||||
|
||||
#include <imcv.h>
|
||||
#include <imv/imv_agent.h>
|
||||
#include <imv/imv_msg.h>
|
||||
#include <ietf/ietf_attr_pa_tnc_error.h>
|
||||
#include <ita/ita_attr.h>
|
||||
#include <ita/ita_attr_angel.h>
|
||||
#include "tcg/seg/tcg_seg_attr_max_size.h"
|
||||
#include "tcg/seg/tcg_seg_attr_seg_env.h"
|
||||
#include "tcg/swid/tcg_swid_attr_req.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_inv.h"
|
||||
#include "tcg/swid/tcg_swid_attr_tag_id_inv.h"
|
||||
#include "swid/swid_error.h"
|
||||
#include "swid/swid_inventory.h"
|
||||
|
||||
#include <tncif_names.h>
|
||||
#include <tncif_pa_subtypes.h>
|
||||
|
||||
#include <pen/pen.h>
|
||||
#include <utils/debug.h>
|
||||
#include <bio/bio_reader.h>
|
||||
|
||||
typedef struct private_imv_swid_agent_t private_imv_swid_agent_t;
|
||||
|
||||
#define SWID_MAX_ATTR_SIZE 1000000000
|
||||
|
||||
/* Subscribed PA-TNC message subtypes */
|
||||
static pen_type_t msg_types[] = {
|
||||
{ PEN_TCG, PA_SUBTYPE_TCG_SWID }
|
||||
};
|
||||
|
||||
/**
|
||||
* Flag set when corresponding attribute has been received
|
||||
*/
|
||||
enum imv_swid_attr_t {
|
||||
IMV_SWID_ATTR_TAG_INV = (1<<0),
|
||||
IMV_SWID_ATTR_TAG_ID_INV = (1<<1)
|
||||
};
|
||||
|
||||
/**
|
||||
* Private data of an imv_swid_agent_t object.
|
||||
*/
|
||||
struct private_imv_swid_agent_t {
|
||||
|
||||
/**
|
||||
* Public members of imv_swid_agent_t
|
||||
*/
|
||||
imv_agent_if_t public;
|
||||
|
||||
/**
|
||||
* IMV agent responsible for generic functions
|
||||
*/
|
||||
imv_agent_t *agent;
|
||||
|
||||
/**
|
||||
* REST API to strongTNC manager
|
||||
*/
|
||||
imv_swid_rest_t *rest_api;
|
||||
|
||||
};
|
||||
|
||||
METHOD(imv_agent_if_t, bind_functions, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_TNCS_BindFunctionPointer bind_function)
|
||||
{
|
||||
return this->agent->bind_functions(this->agent, bind_function);
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id,
|
||||
TNC_ConnectionState new_state)
|
||||
{
|
||||
imv_state_t *state;
|
||||
|
||||
switch (new_state)
|
||||
{
|
||||
case TNC_CONNECTION_STATE_CREATE:
|
||||
state = imv_swid_state_create(id);
|
||||
return this->agent->create_state(this->agent, state);
|
||||
case TNC_CONNECTION_STATE_DELETE:
|
||||
return this->agent->delete_state(this->agent, id);
|
||||
default:
|
||||
return this->agent->change_state(this->agent, id, new_state, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a received message
|
||||
*/
|
||||
static TNC_Result receive_msg(private_imv_swid_agent_t *this,
|
||||
imv_state_t *state, imv_msg_t *in_msg)
|
||||
{
|
||||
imv_swid_state_t *swid_state;
|
||||
imv_msg_t *out_msg;
|
||||
enumerator_t *enumerator;
|
||||
pa_tnc_attr_t *attr;
|
||||
TNC_Result result;
|
||||
bool fatal_error = FALSE;
|
||||
|
||||
/* generate an outgoing PA-TNC message - we might need it */
|
||||
out_msg = imv_msg_create_as_reply(in_msg);
|
||||
|
||||
/* parse received PA-TNC message and handle local and remote errors */
|
||||
result = in_msg->receive(in_msg, out_msg, &fatal_error);
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
out_msg->destroy(out_msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
swid_state = (imv_swid_state_t*)state;
|
||||
|
||||
/* analyze PA-TNC attributes */
|
||||
enumerator = in_msg->create_attribute_enumerator(in_msg);
|
||||
while (enumerator->enumerate(enumerator, &attr))
|
||||
{
|
||||
uint32_t request_id = 0, last_eid, eid_epoch;
|
||||
swid_inventory_t *inventory;
|
||||
pen_type_t type;
|
||||
|
||||
type = attr->get_type(attr);
|
||||
|
||||
if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
|
||||
{
|
||||
ietf_attr_pa_tnc_error_t *error_attr;
|
||||
pen_type_t error_code;
|
||||
chunk_t msg_info, description;
|
||||
bio_reader_t *reader;
|
||||
uint32_t max_attr_size;
|
||||
bool success;
|
||||
|
||||
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
|
||||
error_code = error_attr->get_error_code(error_attr);
|
||||
|
||||
if (error_code.vendor_id == PEN_TCG)
|
||||
{
|
||||
fatal_error = TRUE;
|
||||
msg_info = error_attr->get_msg_info(error_attr);
|
||||
reader = bio_reader_create(msg_info);
|
||||
success = reader->read_uint32(reader, &request_id);
|
||||
|
||||
DBG1(DBG_IMV, "received TCG error '%N' for request %d",
|
||||
swid_error_code_names, error_code.type, request_id);
|
||||
if (!success)
|
||||
{
|
||||
reader->destroy(reader);
|
||||
continue;
|
||||
}
|
||||
if (error_code.type == TCG_SWID_RESPONSE_TOO_LARGE)
|
||||
{
|
||||
if (!reader->read_uint32(reader, &max_attr_size))
|
||||
{
|
||||
reader->destroy(reader);
|
||||
continue;
|
||||
}
|
||||
DBG1(DBG_IMV, " maximum PA-TNC attribute size is %u bytes",
|
||||
max_attr_size);
|
||||
}
|
||||
description = reader->peek(reader);
|
||||
if (description.len)
|
||||
{
|
||||
DBG1(DBG_IMV, " description: %.*s", description.len,
|
||||
description.ptr);
|
||||
}
|
||||
reader->destroy(reader);
|
||||
}
|
||||
}
|
||||
else if (type.vendor_id == PEN_ITA)
|
||||
{
|
||||
switch (type.type)
|
||||
{
|
||||
case ITA_ATTR_START_ANGEL:
|
||||
swid_state->set_angel_count(swid_state, TRUE);
|
||||
continue;
|
||||
case ITA_ATTR_STOP_ANGEL:
|
||||
swid_state->set_angel_count(swid_state, FALSE);
|
||||
continue;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (type.vendor_id != PEN_TCG)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (type.type)
|
||||
{
|
||||
case TCG_SWID_TAG_ID_INVENTORY:
|
||||
{
|
||||
tcg_swid_attr_tag_id_inv_t *attr_cast;
|
||||
int tag_id_count;
|
||||
|
||||
state->set_action_flags(state, IMV_SWID_ATTR_TAG_ID_INV);
|
||||
|
||||
attr_cast = (tcg_swid_attr_tag_id_inv_t*)attr;
|
||||
request_id = attr_cast->get_request_id(attr_cast);
|
||||
last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
|
||||
inventory = attr_cast->get_inventory(attr_cast);
|
||||
tag_id_count = inventory->get_count(inventory);
|
||||
|
||||
DBG2(DBG_IMV, "received SWID tag ID inventory with %d item%s "
|
||||
"for request %d at eid %d of epoch 0x%08x",
|
||||
tag_id_count, (tag_id_count == 1) ? "" : "s",
|
||||
request_id, last_eid, eid_epoch);
|
||||
|
||||
if (request_id == swid_state->get_request_id(swid_state))
|
||||
{
|
||||
swid_state->set_swid_inventory(swid_state, inventory);
|
||||
swid_state->set_count(swid_state, tag_id_count, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IMV, "no workitem found for SWID tag ID inventory "
|
||||
"with request ID %d", request_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TCG_SWID_TAG_INVENTORY:
|
||||
{
|
||||
tcg_swid_attr_tag_inv_t *attr_cast;
|
||||
swid_tag_t *tag;
|
||||
chunk_t tag_encoding;
|
||||
json_object *jobj, *jarray, *jstring;
|
||||
char *tag_str;
|
||||
int tag_count;
|
||||
enumerator_t *e;
|
||||
|
||||
state->set_action_flags(state, IMV_SWID_ATTR_TAG_INV);
|
||||
|
||||
attr_cast = (tcg_swid_attr_tag_inv_t*)attr;
|
||||
request_id = attr_cast->get_request_id(attr_cast);
|
||||
last_eid = attr_cast->get_last_eid(attr_cast, &eid_epoch);
|
||||
inventory = attr_cast->get_inventory(attr_cast);
|
||||
tag_count = inventory->get_count(inventory);
|
||||
|
||||
DBG2(DBG_IMV, "received SWID tag inventory with %d item%s for "
|
||||
"request %d at eid %d of epoch 0x%08x",
|
||||
tag_count, (tag_count == 1) ? "" : "s",
|
||||
request_id, last_eid, eid_epoch);
|
||||
|
||||
|
||||
if (request_id == swid_state->get_request_id(swid_state))
|
||||
{
|
||||
swid_state->set_count(swid_state, 0, tag_count);
|
||||
|
||||
if (this->rest_api)
|
||||
{
|
||||
jobj = json_object_new_object();
|
||||
jarray = json_object_new_array();
|
||||
json_object_object_add(jobj, "data", jarray);
|
||||
|
||||
e = inventory->create_enumerator(inventory);
|
||||
while (e->enumerate(e, &tag))
|
||||
{
|
||||
tag_encoding = tag->get_encoding(tag);
|
||||
tag_str = strndup(tag_encoding.ptr, tag_encoding.len);
|
||||
DBG3(DBG_IMV, "%s", tag_str);
|
||||
jstring = json_object_new_string(tag_str);
|
||||
json_object_array_add(jarray, jstring);
|
||||
free(tag_str);
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
if (this->rest_api->post(this->rest_api,
|
||||
"swid/add-tags/", jobj, NULL) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IMV, "error in REST API add-tags request");
|
||||
}
|
||||
json_object_put(jobj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IMV, "no workitem found for SWID tag inventory "
|
||||
"with request ID %d", request_id);
|
||||
}
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (fatal_error)
|
||||
{
|
||||
state->set_recommendation(state,
|
||||
TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
|
||||
TNC_IMV_EVALUATION_RESULT_ERROR);
|
||||
result = out_msg->send_assessment(out_msg);
|
||||
if (result == TNC_RESULT_SUCCESS)
|
||||
{
|
||||
result = this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* send PA-TNC message with the EXCL flag set */
|
||||
result = out_msg->send(out_msg, TRUE);
|
||||
}
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, receive_message, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id,
|
||||
TNC_MessageType msg_type, chunk_t msg)
|
||||
{
|
||||
imv_state_t *state;
|
||||
imv_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imv_msg_create_from_data(this->agent, state, id, msg_type, msg);
|
||||
result = receive_msg(this, state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id,
|
||||
TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
|
||||
TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, chunk_t msg)
|
||||
{
|
||||
imv_state_t *state;
|
||||
imv_msg_t *in_msg;
|
||||
TNC_Result result;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
in_msg = imv_msg_create_from_long_data(this->agent, state, id,
|
||||
src_imc_id, dst_imv_id, msg_vid, msg_subtype, msg);
|
||||
result = receive_msg(this, state, in_msg);
|
||||
in_msg->destroy(in_msg);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, batch_ending, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id)
|
||||
{
|
||||
imv_msg_t *out_msg;
|
||||
imv_state_t *state;
|
||||
imv_session_t *session;
|
||||
imv_workitem_t *workitem;
|
||||
imv_swid_state_t *swid_state;
|
||||
imv_swid_handshake_state_t handshake_state;
|
||||
pa_tnc_attr_t *attr;
|
||||
TNC_IMVID imv_id;
|
||||
TNC_Result result = TNC_RESULT_SUCCESS;
|
||||
bool no_workitems = TRUE;
|
||||
uint32_t request_id, received;
|
||||
uint8_t flags;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
swid_state = (imv_swid_state_t*)state;
|
||||
handshake_state = swid_state->get_handshake_state(swid_state);
|
||||
session = state->get_session(state);
|
||||
imv_id = this->agent->get_id(this->agent);
|
||||
|
||||
if (handshake_state == IMV_SWID_STATE_END)
|
||||
{
|
||||
return TNC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Create an empty out message - we might need it */
|
||||
out_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
|
||||
msg_types[0]);
|
||||
|
||||
if (!imcv_db)
|
||||
{
|
||||
DBG2(DBG_IMV, "no workitems available - no evaluation possible");
|
||||
state->set_recommendation(state,
|
||||
TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
|
||||
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
|
||||
result = out_msg->send_assessment(out_msg);
|
||||
out_msg->destroy(out_msg);
|
||||
swid_state->set_handshake_state(swid_state, IMV_SWID_STATE_END);
|
||||
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
|
||||
/* Look for SWID tag workitem and create SWID tag request */
|
||||
if (handshake_state == IMV_SWID_STATE_INIT &&
|
||||
session->get_policy_started(session))
|
||||
{
|
||||
size_t max_attr_size = SWID_MAX_ATTR_SIZE;
|
||||
size_t max_seg_size;
|
||||
seg_contract_t *contract;
|
||||
seg_contract_manager_t *contracts;
|
||||
char buf[BUF_LEN];
|
||||
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
if (enumerator)
|
||||
{
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_imv_id(workitem) != TNC_IMVID_ANY ||
|
||||
workitem->get_type(workitem) != IMV_WORKITEM_SWID_TAGS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
flags = TCG_SWID_ATTR_REQ_FLAG_NONE;
|
||||
if (strchr(workitem->get_arg_str(workitem), 'R'))
|
||||
{
|
||||
flags |= TCG_SWID_ATTR_REQ_FLAG_R;
|
||||
}
|
||||
if (strchr(workitem->get_arg_str(workitem), 'S'))
|
||||
{
|
||||
flags |= TCG_SWID_ATTR_REQ_FLAG_S;
|
||||
}
|
||||
if (strchr(workitem->get_arg_str(workitem), 'C'))
|
||||
{
|
||||
flags |= TCG_SWID_ATTR_REQ_FLAG_C;
|
||||
}
|
||||
|
||||
/* Determine maximum PA-TNC attribute segment size */
|
||||
max_seg_size = state->get_max_msg_len(state)
|
||||
- PA_TNC_HEADER_SIZE
|
||||
- PA_TNC_ATTR_HEADER_SIZE
|
||||
- TCG_SEG_ATTR_SEG_ENV_HEADER;
|
||||
|
||||
/* Announce support of PA-TNC segmentation to IMC */
|
||||
contract = seg_contract_create(msg_types[0], max_attr_size,
|
||||
max_seg_size, TRUE, imv_id, FALSE);
|
||||
contract->get_info_string(contract, buf, BUF_LEN, TRUE);
|
||||
DBG2(DBG_IMV, "%s", buf);
|
||||
contracts = state->get_contracts(state);
|
||||
contracts->add_contract(contracts, contract);
|
||||
attr = tcg_seg_attr_max_size_create(max_attr_size,
|
||||
max_seg_size, TRUE);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
/* Issue a SWID request */
|
||||
request_id = workitem->get_id(workitem);
|
||||
swid_state->set_request_id(swid_state, request_id);
|
||||
attr = tcg_swid_attr_req_create(flags, request_id, 0);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
workitem->set_imv_id(workitem, imv_id);
|
||||
no_workitems = FALSE;
|
||||
DBG2(DBG_IMV, "IMV %d issues SWID request %d",
|
||||
imv_id, request_id);
|
||||
break;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (no_workitems)
|
||||
{
|
||||
DBG2(DBG_IMV, "IMV %d has no workitems - "
|
||||
"no evaluation requested", imv_id);
|
||||
state->set_recommendation(state,
|
||||
TNC_IMV_ACTION_RECOMMENDATION_ALLOW,
|
||||
TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
|
||||
}
|
||||
handshake_state = IMV_SWID_STATE_WORKITEMS;
|
||||
swid_state->set_handshake_state(swid_state, handshake_state);
|
||||
}
|
||||
}
|
||||
|
||||
received = state->get_action_flags(state);
|
||||
|
||||
if (handshake_state == IMV_SWID_STATE_WORKITEMS &&
|
||||
(received & (IMV_SWID_ATTR_TAG_INV|IMV_SWID_ATTR_TAG_ID_INV)) &&
|
||||
swid_state->get_angel_count(swid_state) <= 0)
|
||||
{
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
char result_str[BUF_LEN], *error_str = "", *command;
|
||||
char *target, *separator;
|
||||
int tag_id_count, tag_count, i;
|
||||
size_t max_attr_size, attr_size, entry_size;
|
||||
chunk_t tag_creator, unique_sw_id;
|
||||
json_object *jrequest, *jresponse, *jvalue;
|
||||
tcg_swid_attr_req_t *cast_attr;
|
||||
swid_tag_id_t *tag_id;
|
||||
status_t status = SUCCESS;
|
||||
|
||||
if (this->rest_api && (received & IMV_SWID_ATTR_TAG_ID_INV))
|
||||
{
|
||||
if (asprintf(&command, "sessions/%d/swid-measurement/",
|
||||
session->get_session_id(session, NULL, NULL)) < 0)
|
||||
{
|
||||
error_str = "allocation of command string failed";
|
||||
status = FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
jrequest = swid_state->get_swid_inventory(swid_state);
|
||||
status = this->rest_api->post(this->rest_api, command,
|
||||
jrequest, &jresponse);
|
||||
if (status == FAILED)
|
||||
{
|
||||
error_str = "error in REST API swid-measurement request";
|
||||
}
|
||||
free(command);
|
||||
}
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case SUCCESS:
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
|
||||
{
|
||||
swid_state->get_count(swid_state, &tag_id_count,
|
||||
&tag_count);
|
||||
snprintf(result_str, BUF_LEN, "received inventory of "
|
||||
"%d SWID tag ID%s and %d SWID tag%s",
|
||||
tag_id_count, (tag_id_count == 1) ? "" : "s",
|
||||
tag_count, (tag_count == 1) ? "" : "s");
|
||||
session->remove_workitem(session, enumerator);
|
||||
|
||||
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
|
||||
rec = workitem->set_result(workitem, result_str, eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, workitem);
|
||||
workitem->destroy(workitem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
break;
|
||||
case NEED_MORE:
|
||||
if (received & IMV_SWID_ATTR_TAG_INV)
|
||||
{
|
||||
error_str = "not all requested SWID tags were received";
|
||||
status = FAILED;
|
||||
json_object_put(jresponse);
|
||||
break;
|
||||
}
|
||||
if (json_object_get_type(jresponse) != json_type_array)
|
||||
{
|
||||
error_str = "response was not a json_array";
|
||||
status = FAILED;
|
||||
json_object_put(jresponse);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Compute the maximum TCG SWID Request attribute size */
|
||||
max_attr_size = state->get_max_msg_len(state) -
|
||||
PA_TNC_HEADER_SIZE;
|
||||
|
||||
/* Create the [first] TCG SWID Request attribute */
|
||||
attr_size = PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_REQ_MIN_SIZE;
|
||||
attr = tcg_swid_attr_req_create(TCG_SWID_ATTR_REQ_FLAG_NONE,
|
||||
swid_state->get_request_id(swid_state), 0);
|
||||
|
||||
tag_id_count = json_object_array_length(jresponse);
|
||||
DBG1(DBG_IMV, "%d SWID tag target%s", tag_id_count,
|
||||
(tag_id_count == 1) ? "" : "s");
|
||||
|
||||
for (i = 0; i < tag_id_count; i++)
|
||||
{
|
||||
jvalue = json_object_array_get_idx(jresponse, i);
|
||||
if (json_object_get_type(jvalue) != json_type_string)
|
||||
{
|
||||
error_str = "json_string element expected in json_array";
|
||||
status = FAILED;
|
||||
json_object_put(jresponse);
|
||||
break;
|
||||
}
|
||||
target = (char*)json_object_get_string(jvalue);
|
||||
DBG1(DBG_IMV, " %s", target);
|
||||
|
||||
/* Separate target into tag_creator and unique_sw_id */
|
||||
separator = strchr(target, '_');
|
||||
if (!separator)
|
||||
{
|
||||
error_str = "separation of regid from "
|
||||
"unique software ID failed";
|
||||
break;
|
||||
}
|
||||
tag_creator = chunk_create(target, separator - target);
|
||||
separator++;
|
||||
unique_sw_id = chunk_create(separator, strlen(target) -
|
||||
tag_creator.len - 1);
|
||||
tag_id = swid_tag_id_create(tag_creator, unique_sw_id,
|
||||
chunk_empty);
|
||||
entry_size = 2 + tag_creator.len + 2 + unique_sw_id.len;
|
||||
|
||||
/* Have we reached the maximum attribute size? */
|
||||
if (attr_size + entry_size > max_attr_size)
|
||||
{
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
attr_size = PA_TNC_ATTR_HEADER_SIZE +
|
||||
TCG_SWID_REQ_MIN_SIZE;
|
||||
attr = tcg_swid_attr_req_create(
|
||||
TCG_SWID_ATTR_REQ_FLAG_NONE,
|
||||
swid_state->get_request_id(swid_state), 0);
|
||||
}
|
||||
cast_attr = (tcg_swid_attr_req_t*)attr;
|
||||
cast_attr->add_target(cast_attr, tag_id);
|
||||
}
|
||||
json_object_put(jresponse);
|
||||
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
break;
|
||||
case FAILED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == FAILED)
|
||||
{
|
||||
enumerator = session->create_workitem_enumerator(session);
|
||||
while (enumerator->enumerate(enumerator, &workitem))
|
||||
{
|
||||
if (workitem->get_type(workitem) == IMV_WORKITEM_SWID_TAGS)
|
||||
{
|
||||
session->remove_workitem(session, enumerator);
|
||||
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
|
||||
rec = workitem->set_result(workitem, error_str, eval);
|
||||
state->update_recommendation(state, rec, eval);
|
||||
imcv_db->finalize_workitem(imcv_db, workitem);
|
||||
workitem->destroy(workitem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
}
|
||||
|
||||
/* finalized all workitems ? */
|
||||
if (handshake_state == IMV_SWID_STATE_WORKITEMS &&
|
||||
session->get_workitem_count(session, imv_id) == 0)
|
||||
{
|
||||
result = out_msg->send_assessment(out_msg);
|
||||
out_msg->destroy(out_msg);
|
||||
swid_state->set_handshake_state(swid_state, IMV_SWID_STATE_END);
|
||||
|
||||
if (result != TNC_RESULT_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
return this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
|
||||
/* send non-empty PA-TNC message with excl flag not set */
|
||||
if (out_msg->get_attribute_count(out_msg))
|
||||
{
|
||||
result = out_msg->send(out_msg, FALSE);
|
||||
}
|
||||
out_msg->destroy(out_msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
|
||||
private_imv_swid_agent_t *this, TNC_ConnectionID id)
|
||||
{
|
||||
imv_state_t *state;
|
||||
|
||||
if (!this->agent->get_state(this->agent, id, &state))
|
||||
{
|
||||
return TNC_RESULT_FATAL;
|
||||
}
|
||||
return this->agent->provide_recommendation(this->agent, state);
|
||||
}
|
||||
|
||||
METHOD(imv_agent_if_t, destroy, void,
|
||||
private_imv_swid_agent_t *this)
|
||||
{
|
||||
DESTROY_IF(this->rest_api);
|
||||
this->agent->destroy(this->agent);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imv_agent_if_t *imv_swid_agent_create(const char *name, TNC_IMVID id,
|
||||
TNC_Version *actual_version)
|
||||
{
|
||||
private_imv_swid_agent_t *this;
|
||||
imv_agent_t *agent;
|
||||
char *rest_api_uri;
|
||||
u_int rest_api_timeout;
|
||||
|
||||
agent = imv_agent_create(name, msg_types, countof(msg_types), id,
|
||||
actual_version);
|
||||
if (!agent)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
agent->add_non_fatal_attr_type(agent,
|
||||
pen_type_create(PEN_TCG, TCG_SEG_MAX_ATTR_SIZE_REQ));
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.bind_functions = _bind_functions,
|
||||
.notify_connection_change = _notify_connection_change,
|
||||
.receive_message = _receive_message,
|
||||
.receive_message_long = _receive_message_long,
|
||||
.batch_ending = _batch_ending,
|
||||
.solicit_recommendation = _solicit_recommendation,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.agent = agent,
|
||||
);
|
||||
|
||||
rest_api_uri = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imv-swid.rest_api_uri", NULL, lib->ns);
|
||||
rest_api_timeout = lib->settings->get_int(lib->settings,
|
||||
"%s.plugins.imv-swid.rest_api_timeout", 120, lib->ns);
|
||||
if (rest_api_uri)
|
||||
{
|
||||
this->rest_api = imv_swid_rest_create(rest_api_uri, rest_api_timeout);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 imv_swid_agent_t imv_swid_agent
|
||||
* @{ @ingroup imv_swid
|
||||
*/
|
||||
|
||||
#ifndef IMV_SWID_AGENT_H_
|
||||
#define IMV_SWID_AGENT_H_
|
||||
|
||||
#include <imv/imv_agent_if.h>
|
||||
|
||||
/**
|
||||
* Creates an SWID IMV agent
|
||||
*
|
||||
* @param name Name of the IMV
|
||||
* @param id ID of the IMV
|
||||
* @param actual_version TNC IF-IMV version
|
||||
*/
|
||||
imv_agent_if_t* imv_swid_agent_create(const char* name, TNC_IMVID id,
|
||||
TNC_Version *actual_version);
|
||||
|
||||
#endif /** IMV_SWID_AGENT_H_ @}*/
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
|
||||
#include "imv_swid_rest.h"
|
||||
|
||||
typedef struct private_imv_swid_rest_t private_imv_swid_rest_t;
|
||||
|
||||
/**
|
||||
* Private data of an imv_swid_rest_t object.
|
||||
*/
|
||||
struct private_imv_swid_rest_t {
|
||||
|
||||
/**
|
||||
* Public members of imv_swid_rest_t
|
||||
*/
|
||||
imv_swid_rest_t public;
|
||||
|
||||
/**
|
||||
* URI of REST API
|
||||
*/
|
||||
char *uri;
|
||||
|
||||
/**
|
||||
* Timeout of REST API connection
|
||||
*/
|
||||
u_int timeout;
|
||||
|
||||
};
|
||||
|
||||
#define HTTP_STATUS_CODE_PRECONDITION_FAILED 412
|
||||
|
||||
METHOD(imv_swid_rest_t, post, status_t,
|
||||
private_imv_swid_rest_t *this, char *command, json_object *jrequest,
|
||||
json_object **jresponse)
|
||||
{
|
||||
struct json_tokener *tokener;
|
||||
chunk_t data, response = chunk_empty;
|
||||
status_t status;
|
||||
char *uri;
|
||||
int code;
|
||||
|
||||
if (asprintf(&uri, "%s%s",this->uri, command) < 0)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
data = chunk_from_str((char*)json_object_to_json_string(jrequest));
|
||||
|
||||
status = lib->fetcher->fetch(lib->fetcher, uri, &response,
|
||||
FETCH_TIMEOUT, this->timeout,
|
||||
FETCH_REQUEST_DATA, data,
|
||||
FETCH_REQUEST_TYPE, "application/json; charset=utf-8",
|
||||
FETCH_REQUEST_HEADER, "Accept: application/json",
|
||||
FETCH_REQUEST_HEADER, "Expect:",
|
||||
FETCH_RESPONSE_CODE, &code,
|
||||
FETCH_END);
|
||||
free(uri);
|
||||
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (code != HTTP_STATUS_CODE_PRECONDITION_FAILED || !response.ptr)
|
||||
{
|
||||
DBG2(DBG_IMV, "REST http request failed with status code: %d", code);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (jresponse)
|
||||
{
|
||||
/* Parse HTTP response into a JSON object */
|
||||
tokener = json_tokener_new();
|
||||
*jresponse = json_tokener_parse_ex(tokener, response.ptr, response.len);
|
||||
json_tokener_free(tokener);
|
||||
}
|
||||
free(response.ptr);
|
||||
|
||||
return NEED_MORE;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_rest_t, destroy, void,
|
||||
private_imv_swid_rest_t *this)
|
||||
{
|
||||
free(this->uri);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imv_swid_rest_t *imv_swid_rest_create(char *uri, u_int timeout)
|
||||
{
|
||||
private_imv_swid_rest_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.post = _post,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.uri = strdup(uri),
|
||||
.timeout = timeout,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 imv_swid imv_swid
|
||||
* @ingroup libimcv_plugins
|
||||
*
|
||||
* @defgroup imv_swid_rest_t imv_swid_rest
|
||||
* @{ @ingroup imv_swid
|
||||
*/
|
||||
|
||||
#ifndef IMV_SWID_REST_H_
|
||||
#define IMV_SWID_REST_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
#include <json.h>
|
||||
|
||||
typedef struct imv_swid_rest_t imv_swid_rest_t;
|
||||
|
||||
/**
|
||||
* Public REST interface
|
||||
*/
|
||||
struct imv_swid_rest_t {
|
||||
|
||||
/**
|
||||
* Post a HTTP request including a JSON object
|
||||
*
|
||||
* @param jreq JSON object in HTTP request
|
||||
* @param jresp JSON object in HTTP response if NEED_MORE
|
||||
* @return Status (SUCCESS, NEED_MORE or FAILED)
|
||||
*/
|
||||
status_t (*post)(imv_swid_rest_t *this, char *command, json_object *jreq,
|
||||
json_object **jresp);
|
||||
|
||||
/**
|
||||
* Destroy imv_swid_rest_t object
|
||||
*/
|
||||
void (*destroy)(imv_swid_rest_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an imv_swid_rest_t instance
|
||||
*
|
||||
* @param uri REST URI (http://username:password@hostname[:port]/api/)
|
||||
* @param timeout Timeout of the REST connection
|
||||
*/
|
||||
imv_swid_rest_t* imv_swid_rest_create(char *uri, u_int timeout);
|
||||
|
||||
#endif /** IMV_SWID_REST_H_ @}*/
|
||||
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imv_swid_state.h"
|
||||
|
||||
#include <imv/imv_lang_string.h>
|
||||
#include <imv/imv_reason_string.h>
|
||||
#include <imv/imv_remediation_string.h>
|
||||
#include <swid/swid_tag_id.h>
|
||||
|
||||
#include <tncif_policy.h>
|
||||
|
||||
#include <utils/lexparser.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_imv_swid_state_t private_imv_swid_state_t;
|
||||
|
||||
/**
|
||||
* Private data of an imv_swid_state_t object.
|
||||
*/
|
||||
struct private_imv_swid_state_t {
|
||||
|
||||
/**
|
||||
* Public members of imv_swid_state_t
|
||||
*/
|
||||
imv_swid_state_t public;
|
||||
|
||||
/**
|
||||
* TNCCS connection ID
|
||||
*/
|
||||
TNC_ConnectionID connection_id;
|
||||
|
||||
/**
|
||||
* TNCCS connection state
|
||||
*/
|
||||
TNC_ConnectionState state;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support long message types?
|
||||
*/
|
||||
bool has_long;
|
||||
|
||||
/**
|
||||
* Does the TNCCS connection support exclusive delivery?
|
||||
*/
|
||||
bool has_excl;
|
||||
|
||||
/**
|
||||
* Maximum PA-TNC message size for this TNCCS connection
|
||||
*/
|
||||
uint32_t max_msg_len;
|
||||
|
||||
/**
|
||||
* Flags set for completed actions
|
||||
*/
|
||||
uint32_t action_flags;
|
||||
|
||||
/**
|
||||
* IMV database session associated with TNCCS connection
|
||||
*/
|
||||
imv_session_t *session;
|
||||
|
||||
/**
|
||||
* PA-TNC attribute segmentation contracts associated with TNCCS connection
|
||||
*/
|
||||
seg_contract_manager_t *contracts;
|
||||
|
||||
/**
|
||||
* IMV action recommendation
|
||||
*/
|
||||
TNC_IMV_Action_Recommendation rec;
|
||||
|
||||
/**
|
||||
* IMV evaluation result
|
||||
*/
|
||||
TNC_IMV_Evaluation_Result eval;
|
||||
|
||||
/**
|
||||
* IMV Scanner handshake state
|
||||
*/
|
||||
imv_swid_handshake_state_t handshake_state;
|
||||
|
||||
/**
|
||||
* TNC Reason String
|
||||
*/
|
||||
imv_reason_string_t *reason_string;
|
||||
|
||||
/**
|
||||
* IETF Remediation Instructions String
|
||||
*/
|
||||
imv_remediation_string_t *remediation_string;
|
||||
|
||||
/**
|
||||
* SWID Tag Request ID
|
||||
*/
|
||||
uint32_t request_id;
|
||||
|
||||
/**
|
||||
* Number of processed SWID Tag IDs
|
||||
*/
|
||||
int tag_id_count;
|
||||
|
||||
/**
|
||||
* Number of processed SWID Tags
|
||||
*/
|
||||
int tag_count;
|
||||
|
||||
/**
|
||||
* Top level JSON object
|
||||
*/
|
||||
json_object *jobj;
|
||||
|
||||
/**
|
||||
* JSON array containing an inventory of SWID Tag IDs
|
||||
*/
|
||||
json_object *jarray;
|
||||
|
||||
/**
|
||||
* Angel count
|
||||
*/
|
||||
int angel_count;
|
||||
|
||||
};
|
||||
|
||||
METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->connection_id;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, has_long, bool,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->has_long;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, has_excl, bool,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->has_excl;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_flags, void,
|
||||
private_imv_swid_state_t *this, bool has_long, bool has_excl)
|
||||
{
|
||||
this->has_long = has_long;
|
||||
this->has_excl = has_excl;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_max_msg_len, void,
|
||||
private_imv_swid_state_t *this, uint32_t max_msg_len)
|
||||
{
|
||||
this->max_msg_len = max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_max_msg_len, uint32_t,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->max_msg_len;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_action_flags, void,
|
||||
private_imv_swid_state_t *this, uint32_t flags)
|
||||
{
|
||||
this->action_flags |= flags;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_action_flags, uint32_t,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->action_flags;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_session, void,
|
||||
private_imv_swid_state_t *this, imv_session_t *session)
|
||||
{
|
||||
this->session = session;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_session, imv_session_t*,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->session;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->contracts;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, change_state, void,
|
||||
private_imv_swid_state_t *this, TNC_ConnectionState new_state)
|
||||
{
|
||||
this->state = new_state;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_recommendation, void,
|
||||
private_imv_swid_state_t *this, TNC_IMV_Action_Recommendation *rec,
|
||||
TNC_IMV_Evaluation_Result *eval)
|
||||
{
|
||||
*rec = this->rec;
|
||||
*eval = this->eval;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, set_recommendation, void,
|
||||
private_imv_swid_state_t *this, TNC_IMV_Action_Recommendation rec,
|
||||
TNC_IMV_Evaluation_Result eval)
|
||||
{
|
||||
this->rec = rec;
|
||||
this->eval = eval;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, update_recommendation, void,
|
||||
private_imv_swid_state_t *this, TNC_IMV_Action_Recommendation rec,
|
||||
TNC_IMV_Evaluation_Result eval)
|
||||
{
|
||||
this->rec = tncif_policy_update_recommendation(this->rec, rec);
|
||||
this->eval = tncif_policy_update_evaluation(this->eval, eval);
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_reason_string, bool,
|
||||
private_imv_swid_state_t *this, enumerator_t *language_enumerator,
|
||||
chunk_t *reason_string, char **reason_language)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, get_remediation_instructions, bool,
|
||||
private_imv_swid_state_t *this, enumerator_t *language_enumerator,
|
||||
chunk_t *string, char **lang_code, char **uri)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(imv_state_t, destroy, void,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
json_object_put(this->jobj);
|
||||
DESTROY_IF(this->session);
|
||||
DESTROY_IF(this->reason_string);
|
||||
DESTROY_IF(this->remediation_string);
|
||||
this->contracts->destroy(this->contracts);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_handshake_state, void,
|
||||
private_imv_swid_state_t *this, imv_swid_handshake_state_t new_state)
|
||||
{
|
||||
this->handshake_state = new_state;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_handshake_state, imv_swid_handshake_state_t,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->handshake_state;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_request_id, void,
|
||||
private_imv_swid_state_t *this, uint32_t request_id)
|
||||
{
|
||||
this->request_id = request_id;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_request_id, uint32_t,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->request_id;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_swid_inventory, void,
|
||||
private_imv_swid_state_t *this, swid_inventory_t *inventory)
|
||||
{
|
||||
chunk_t tag_creator, unique_sw_id;
|
||||
char software_id[256];
|
||||
json_object *jstring;
|
||||
swid_tag_id_t *tag_id;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
enumerator = inventory->create_enumerator(inventory);
|
||||
while (enumerator->enumerate(enumerator, &tag_id))
|
||||
{
|
||||
/* Construct software ID from tag creator and unique software ID */
|
||||
tag_creator = tag_id->get_tag_creator(tag_id);
|
||||
unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
|
||||
snprintf(software_id, 256, "%.*s_%.*s",
|
||||
tag_creator.len, tag_creator.ptr,
|
||||
unique_sw_id.len, unique_sw_id.ptr);
|
||||
DBG3(DBG_IMV, " %s", software_id);
|
||||
|
||||
/* Add software ID to JSON array */
|
||||
jstring = json_object_new_string(software_id);
|
||||
json_object_array_add(this->jarray, jstring);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_swid_inventory, json_object*,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->jobj;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_count, void,
|
||||
private_imv_swid_state_t *this, int tag_id_count, int tag_count)
|
||||
{
|
||||
this->tag_id_count += tag_id_count;
|
||||
this->tag_count += tag_count;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_count, void,
|
||||
private_imv_swid_state_t *this, int *tag_id_count, int *tag_count)
|
||||
{
|
||||
if (tag_id_count)
|
||||
{
|
||||
*tag_id_count = this->tag_id_count;
|
||||
}
|
||||
if (tag_count)
|
||||
{
|
||||
*tag_count = this->tag_count;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, set_angel_count, void,
|
||||
private_imv_swid_state_t *this, bool start)
|
||||
{
|
||||
this->angel_count += start ? 1 : -1;
|
||||
}
|
||||
|
||||
METHOD(imv_swid_state_t, get_angel_count, int,
|
||||
private_imv_swid_state_t *this)
|
||||
{
|
||||
return this->angel_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
|
||||
{
|
||||
private_imv_swid_state_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.interface = {
|
||||
.get_connection_id = _get_connection_id,
|
||||
.has_long = _has_long,
|
||||
.has_excl = _has_excl,
|
||||
.set_flags = _set_flags,
|
||||
.set_max_msg_len = _set_max_msg_len,
|
||||
.get_max_msg_len = _get_max_msg_len,
|
||||
.set_action_flags = _set_action_flags,
|
||||
.get_action_flags = _get_action_flags,
|
||||
.set_session = _set_session,
|
||||
.get_session= _get_session,
|
||||
.get_contracts = _get_contracts,
|
||||
.change_state = _change_state,
|
||||
.get_recommendation = _get_recommendation,
|
||||
.set_recommendation = _set_recommendation,
|
||||
.update_recommendation = _update_recommendation,
|
||||
.get_reason_string = _get_reason_string,
|
||||
.get_remediation_instructions = _get_remediation_instructions,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.set_handshake_state = _set_handshake_state,
|
||||
.get_handshake_state = _get_handshake_state,
|
||||
.set_request_id = _set_request_id,
|
||||
.get_request_id = _get_request_id,
|
||||
.set_swid_inventory = _set_swid_inventory,
|
||||
.get_swid_inventory = _get_swid_inventory,
|
||||
.set_count = _set_count,
|
||||
.get_count = _get_count,
|
||||
.set_angel_count = _set_angel_count,
|
||||
.get_angel_count = _get_angel_count,
|
||||
},
|
||||
.state = TNC_CONNECTION_STATE_CREATE,
|
||||
.rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
|
||||
.eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
|
||||
.connection_id = connection_id,
|
||||
.contracts = seg_contract_manager_create(),
|
||||
.jobj = json_object_new_object(),
|
||||
.jarray = json_object_new_array(),
|
||||
);
|
||||
|
||||
json_object_object_add(this->jobj, "data", this->jarray);
|
||||
|
||||
return &this->public.interface;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 imv_swid imv_swid
|
||||
* @ingroup libimcv_plugins
|
||||
*
|
||||
* @defgroup imv_swid_state_t imv_swid_state
|
||||
* @{ @ingroup imv_swid
|
||||
*/
|
||||
|
||||
#ifndef IMV_SWID_STATE_H_
|
||||
#define IMV_SWID_STATE_H_
|
||||
|
||||
#include <imv/imv_state.h>
|
||||
#include <swid/swid_inventory.h>
|
||||
#include <library.h>
|
||||
|
||||
#include <json.h>
|
||||
|
||||
typedef struct imv_swid_state_t imv_swid_state_t;
|
||||
typedef enum imv_swid_handshake_state_t imv_swid_handshake_state_t;
|
||||
|
||||
/**
|
||||
* IMV OS Handshake States (state machine)
|
||||
*/
|
||||
enum imv_swid_handshake_state_t {
|
||||
IMV_SWID_STATE_INIT,
|
||||
IMV_SWID_STATE_WORKITEMS,
|
||||
IMV_SWID_STATE_END
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal state of an imv_swid_t connection instance
|
||||
*/
|
||||
struct imv_swid_state_t {
|
||||
|
||||
/**
|
||||
* imv_state_t interface
|
||||
*/
|
||||
imv_state_t interface;
|
||||
|
||||
/**
|
||||
* Set state of the handshake
|
||||
*
|
||||
* @param new_state the handshake state of IMV
|
||||
*/
|
||||
void (*set_handshake_state)(imv_swid_state_t *this,
|
||||
imv_swid_handshake_state_t new_state);
|
||||
|
||||
/**
|
||||
* Get state of the handshake
|
||||
*
|
||||
* @return the handshake state of IMV
|
||||
*/
|
||||
imv_swid_handshake_state_t (*get_handshake_state)(imv_swid_state_t *this);
|
||||
|
||||
/**
|
||||
* Set the SWID request ID
|
||||
*
|
||||
* @param request_id SWID request ID to be set
|
||||
*/
|
||||
void (*set_request_id)(imv_swid_state_t *this, uint32_t request_id);
|
||||
|
||||
/**
|
||||
* Get the SWID request ID
|
||||
*
|
||||
* @return SWID request ID
|
||||
*/
|
||||
uint32_t (*get_request_id)(imv_swid_state_t *this);
|
||||
|
||||
/**
|
||||
* Set or extend the SWID Tag ID inventory in the state
|
||||
*
|
||||
* @param inventory SWID Tags ID inventory to be added
|
||||
*/
|
||||
void (*set_swid_inventory)(imv_swid_state_t *this, swid_inventory_t *inventory);
|
||||
|
||||
/**
|
||||
* Get the encoding of the complete SWID Tag ID inventory
|
||||
*
|
||||
* @return SWID Tags ID inventory as a JSON array
|
||||
*/
|
||||
json_object* (*get_swid_inventory)(imv_swid_state_t *this);
|
||||
|
||||
/**
|
||||
* Set [or with multiple attributes increment] SWID Tag [ID] counters
|
||||
*
|
||||
* @param tag_id_count Number of received SWID Tag IDs
|
||||
* @param tag_count Number of received SWID Tags
|
||||
*/
|
||||
void (*set_count)(imv_swid_state_t *this, int tag_id_count, int tag_count);
|
||||
|
||||
/**
|
||||
* Set [or with multiple attributes increment] SWID Tag [ID] counters
|
||||
*
|
||||
* @param tag_id_count Number of received SWID Tag IDs
|
||||
* @param tag_count Number of received SWID Tags
|
||||
*/
|
||||
void (*get_count)(imv_swid_state_t *this, int *tag_id_count, int *tag_count);
|
||||
|
||||
/**
|
||||
* Increase/Decrease the ITA Angel count
|
||||
*
|
||||
* @param start TRUE increases and FALSE decreases count by one
|
||||
*/
|
||||
void (*set_angel_count)(imv_swid_state_t *this, bool start);
|
||||
|
||||
/**
|
||||
* Get the ITA Angel count
|
||||
*
|
||||
* @return ITA Angel count
|
||||
*/
|
||||
int (*get_angel_count)(imv_swid_state_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an imv_swid_state_t instance
|
||||
*
|
||||
* @param id connection ID
|
||||
*/
|
||||
imv_state_t* imv_swid_state_create(TNC_ConnectionID id);
|
||||
|
||||
#endif /** IMV_SWID_STATE_H_ @}*/
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ita_comp_func_name.h"
|
||||
|
||||
char pts_ita_qualifier_flag_names[] = { 'K', 'S' };
|
||||
|
||||
ENUM_BEGIN(pts_ita_qualifier_type_names, PTS_ITA_QUALIFIER_TYPE_UNKNOWN,
|
||||
PTS_ITA_QUALIFIER_TYPE_TNC,
|
||||
"Unknown",
|
||||
"Trusted Platform",
|
||||
"Operating System",
|
||||
"Graphical User Interface",
|
||||
"Application",
|
||||
"Networking",
|
||||
"Library",
|
||||
"TNC Defined Component"
|
||||
);
|
||||
ENUM_NEXT(pts_ita_qualifier_type_names, PTS_ITA_QUALIFIER_TYPE_ALL,
|
||||
PTS_ITA_QUALIFIER_TYPE_ALL,
|
||||
PTS_ITA_QUALIFIER_TYPE_TNC,
|
||||
"All Matching Components"
|
||||
);
|
||||
ENUM_END(pts_ita_qualifier_type_names, PTS_ITA_QUALIFIER_TYPE_ALL);
|
||||
|
||||
ENUM(pts_ita_comp_func_names, PTS_ITA_COMP_FUNC_NAME_IGNORE,
|
||||
PTS_ITA_COMP_FUNC_NAME_IMA,
|
||||
"Ignore",
|
||||
"Trusted GRUB Boot Loader",
|
||||
"Trusted Boot",
|
||||
"Linux IMA"
|
||||
);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_ita_comp_func_name pts_ita_comp_func_name
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_ITA_COMP_FUNC_NAME_H_
|
||||
#define PTS_ITA_COMP_FUNC_NAME_H_
|
||||
|
||||
typedef enum pts_ita_qualifier_type_t pts_ita_qualifier_type_t;
|
||||
typedef enum pts_ita_comp_func_name_t pts_ita_comp_func_name_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name Qualifier Flags for the ITA namespace
|
||||
*/
|
||||
#define PTS_ITA_QUALIFIER_FLAG_KERNEL (1<<5)
|
||||
#define PTS_ITA_QUALIFIER_FLAG_SUB (1<<4)
|
||||
|
||||
extern char pts_ita_qualifier_flag_names[];
|
||||
|
||||
/**
|
||||
* Size of the PTS Component Functional Name Qualifier Type field
|
||||
*/
|
||||
#define PTS_ITA_QUALIFIER_TYPE_SIZE 4
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name Qualifier Types for the ITA namespace
|
||||
* equal to section 5.2 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*/
|
||||
enum pts_ita_qualifier_type_t {
|
||||
/** Unknown */
|
||||
PTS_ITA_QUALIFIER_TYPE_UNKNOWN = 0x0,
|
||||
/** Trusted Platform */
|
||||
PTS_ITA_QUALIFIER_TYPE_TRUSTED = 0x1,
|
||||
/** Operating System */
|
||||
PTS_ITA_QUALIFIER_TYPE_OS = 0x2,
|
||||
/** Graphical User Interface */
|
||||
PTS_ITA_QUALIFIER_TYPE_GUI = 0x3,
|
||||
/** Application */
|
||||
PTS_ITA_QUALIFIER_TYPE_APP = 0x4,
|
||||
/** Networking */
|
||||
PTS_ITA_QUALIFIER_TYPE_NET = 0x5,
|
||||
/** Library */
|
||||
PTS_ITA_QUALIFIER_TYPE_LIB = 0x6,
|
||||
/** TNC Defined Component */
|
||||
PTS_ITA_QUALIFIER_TYPE_TNC = 0x7,
|
||||
/** All Matching Components */
|
||||
PTS_ITA_QUALIFIER_TYPE_ALL = 0xF,
|
||||
};
|
||||
|
||||
extern enum_name_t *pts_ita_qualifier_type_names;
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name Binary Enumeration for the ITA namespace
|
||||
*/
|
||||
enum pts_ita_comp_func_name_t {
|
||||
/** Ignore */
|
||||
PTS_ITA_COMP_FUNC_NAME_IGNORE = 0x0000,
|
||||
/** Trusted GRUB Boot Loader */
|
||||
PTS_ITA_COMP_FUNC_NAME_TGRUB = 0x0001,
|
||||
/** Trusted Boot */
|
||||
PTS_ITA_COMP_FUNC_NAME_TBOOT = 0x0002,
|
||||
/** Linux Integrity Measurement Architecture */
|
||||
PTS_ITA_COMP_FUNC_NAME_IMA = 0x0003,
|
||||
};
|
||||
|
||||
extern enum_name_t *pts_ita_comp_func_names;
|
||||
|
||||
#endif /** PTS_ITA_COMP_FUNC_NAME_H_ @}*/
|
||||
@@ -0,0 +1,914 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ita_comp_ima.h"
|
||||
#include "ita_comp_func_name.h"
|
||||
|
||||
#include "imcv.h"
|
||||
#include "pts/pts_pcr.h"
|
||||
#include "pts/pts_ima_bios_list.h"
|
||||
#include "pts/pts_ima_event_list.h"
|
||||
#include "pts/components/pts_component.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <pen/pen.h>
|
||||
|
||||
#define SECURITY_DIR "/sys/kernel/security/"
|
||||
#define IMA_BIOS_MEASUREMENTS SECURITY_DIR "tpm0/binary_bios_measurements"
|
||||
#define IMA_RUNTIME_MEASUREMENTS SECURITY_DIR "ima/binary_runtime_measurements"
|
||||
#define IMA_FILENAME_LEN_MAX 255
|
||||
|
||||
typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
|
||||
typedef enum ima_state_t ima_state_t;
|
||||
|
||||
enum ima_state_t {
|
||||
IMA_STATE_INIT,
|
||||
IMA_STATE_BIOS,
|
||||
IMA_STATE_BOOT_AGGREGATE,
|
||||
IMA_STATE_RUNTIME,
|
||||
IMA_STATE_END
|
||||
};
|
||||
|
||||
/**
|
||||
* Private data of a pts_ita_comp_ima_t object.
|
||||
*
|
||||
*/
|
||||
struct pts_ita_comp_ima_t {
|
||||
|
||||
/**
|
||||
* Public pts_component_t interface.
|
||||
*/
|
||||
pts_component_t public;
|
||||
|
||||
/**
|
||||
* Component Functional Name
|
||||
*/
|
||||
pts_comp_func_name_t *name;
|
||||
|
||||
/**
|
||||
* Sub-component depth
|
||||
*/
|
||||
uint32_t depth;
|
||||
|
||||
/**
|
||||
* PTS measurement database
|
||||
*/
|
||||
pts_database_t *pts_db;
|
||||
|
||||
/**
|
||||
* Primary key for AIK database entry
|
||||
*/
|
||||
int aik_id;
|
||||
|
||||
/**
|
||||
* Primary key for IMA BIOS Component Functional Name database entry
|
||||
*/
|
||||
int bios_cid;
|
||||
|
||||
/**
|
||||
* Primary key for IMA Runtime Component Functional Name database entry
|
||||
*/
|
||||
int ima_cid;
|
||||
|
||||
/**
|
||||
* Component is registering IMA BIOS measurements
|
||||
*/
|
||||
bool is_bios_registering;
|
||||
|
||||
/**
|
||||
* Component is registering IMA boot aggregate measurement
|
||||
*/
|
||||
bool is_ima_registering;
|
||||
|
||||
/**
|
||||
* Measurement sequence number
|
||||
*/
|
||||
int seq_no;
|
||||
|
||||
/**
|
||||
* Expected IMA BIOS measurement count
|
||||
*/
|
||||
int bios_count;
|
||||
|
||||
/**
|
||||
* IMA BIOS measurements
|
||||
*/
|
||||
pts_ima_bios_list_t *bios_list;
|
||||
|
||||
/**
|
||||
* IMA runtime file measurements
|
||||
*/
|
||||
pts_ima_event_list_t *ima_list;
|
||||
|
||||
/**
|
||||
* Whether to send pcr_before and pcr_after info
|
||||
*/
|
||||
bool pcr_info;
|
||||
|
||||
/**
|
||||
* Creation time of measurement
|
||||
*/
|
||||
time_t creation_time;
|
||||
|
||||
/**
|
||||
* IMA state machine
|
||||
*/
|
||||
ima_state_t state;
|
||||
|
||||
/**
|
||||
* Total number of component measurements
|
||||
*/
|
||||
int count;
|
||||
|
||||
/**
|
||||
* Number of successful component measurements
|
||||
*/
|
||||
int count_ok;
|
||||
|
||||
/**
|
||||
* Number of unknown component measurements
|
||||
*/
|
||||
int count_unknown;
|
||||
|
||||
/**
|
||||
* Number of differing component measurements
|
||||
*/
|
||||
int count_differ;
|
||||
|
||||
/**
|
||||
* Number of failed component measurements
|
||||
*/
|
||||
int count_failed;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Extend measurement into PCR and create evidence
|
||||
*/
|
||||
static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
|
||||
uint8_t qualifier, pts_pcr_t *pcrs,
|
||||
uint32_t pcr, chunk_t measurement)
|
||||
{
|
||||
size_t pcr_len;
|
||||
pts_pcr_transform_t pcr_transform;
|
||||
pts_meas_algorithms_t hash_algo;
|
||||
pts_comp_func_name_t *name;
|
||||
pts_comp_evidence_t *evidence;
|
||||
chunk_t pcr_before = chunk_empty, pcr_after = chunk_empty;
|
||||
|
||||
hash_algo = PTS_MEAS_ALGO_SHA1;
|
||||
pcr_len = HASH_SIZE_SHA1;
|
||||
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
|
||||
|
||||
if (this->pcr_info)
|
||||
{
|
||||
pcr_before = chunk_clone(pcrs->get(pcrs, pcr));
|
||||
}
|
||||
pcr_after = pcrs->extend(pcrs, pcr, measurement);
|
||||
if (!pcr_after.ptr)
|
||||
{
|
||||
free(pcr_before.ptr);
|
||||
return NULL;
|
||||
}
|
||||
name = this->name->clone(this->name);
|
||||
name->set_qualifier(name, qualifier);
|
||||
evidence = pts_comp_evidence_create(name, this->depth, pcr, hash_algo,
|
||||
pcr_transform, this->creation_time, measurement);
|
||||
if (this->pcr_info)
|
||||
{
|
||||
pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
|
||||
evidence->set_pcr_info(evidence, pcr_before, pcr_after);
|
||||
}
|
||||
return evidence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an IMA or IMA-NG hash from an event digest and event name
|
||||
*
|
||||
* @param digest event digest
|
||||
* @param ima_algo hash algorithm string ("sha1:", "sha256:", etc.)
|
||||
* @param ima_name event name
|
||||
* @param little_endian endianness of client platform
|
||||
* @param algo hash algorithm used by TPM
|
||||
* @param hash_buf hash value to be compared with TPM measurement
|
||||
*/
|
||||
static bool ima_hash(chunk_t digest, char *ima_algo, char *ima_name,
|
||||
bool little_endian, pts_meas_algorithms_t algo,
|
||||
char *hash_buf)
|
||||
{
|
||||
hash_algorithm_t hash_alg;
|
||||
hasher_t *hasher;
|
||||
bool success;
|
||||
|
||||
hash_alg = pts_meas_algo_to_hash(algo);
|
||||
hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
|
||||
if (!hasher)
|
||||
{
|
||||
DBG1(DBG_PTS, "%N hasher could not be created",
|
||||
hash_algorithm_short_names, hash_alg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ima_algo)
|
||||
{
|
||||
uint32_t d_len, n_len;
|
||||
chunk_t algo_name, event_name, digest_len, name_len;
|
||||
|
||||
/* IMA-NG hash */
|
||||
algo_name = chunk_create(ima_algo, strlen(ima_algo) + 1);
|
||||
event_name = chunk_create(ima_name, strlen(ima_name) + 1);
|
||||
|
||||
d_len = algo_name.len + digest.len;
|
||||
digest_len = chunk_create((uint8_t*)&d_len, sizeof(d_len));
|
||||
/* TODO handle endianness of both client and server platforms */
|
||||
|
||||
n_len = event_name.len;
|
||||
name_len = chunk_create((uint8_t*)&n_len, sizeof(n_len));
|
||||
/* TODO handle endianness of both client and server platforms */
|
||||
|
||||
success = hasher->get_hash(hasher, digest_len, NULL) &&
|
||||
hasher->get_hash(hasher, algo_name, NULL) &&
|
||||
hasher->get_hash(hasher, digest, NULL) &&
|
||||
hasher->get_hash(hasher, name_len, NULL) &&
|
||||
hasher->get_hash(hasher, event_name, hash_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
|
||||
chunk_t file_name;
|
||||
|
||||
/* IMA legacy hash */
|
||||
memset(filename_buffer, 0, sizeof(filename_buffer));
|
||||
strncpy(filename_buffer, ima_name, IMA_FILENAME_LEN_MAX);
|
||||
file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
|
||||
|
||||
success = hasher->get_hash(hasher, digest, NULL) &&
|
||||
hasher->get_hash(hasher, file_name, hash_buf);
|
||||
}
|
||||
hasher->destroy(hasher);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute and check boot aggregate value by hashing PCR0 to PCR7
|
||||
*/
|
||||
static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement,
|
||||
char *algo)
|
||||
{
|
||||
u_char pcr_buffer[HASH_SIZE_SHA1];
|
||||
chunk_t boot_aggregate;
|
||||
hasher_t *hasher;
|
||||
uint32_t i;
|
||||
bool success, pcr_ok = TRUE;
|
||||
|
||||
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
||||
if (!hasher)
|
||||
{
|
||||
DBG1(DBG_PTS, "%N hasher could not be created",
|
||||
hash_algorithm_short_names, HASH_SHA1);
|
||||
return FALSE;
|
||||
}
|
||||
for (i = 0; i < 8 && pcr_ok; i++)
|
||||
{
|
||||
pcr_ok = hasher->get_hash(hasher, pcrs->get(pcrs, i), NULL);
|
||||
}
|
||||
if (pcr_ok)
|
||||
{
|
||||
pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer);
|
||||
}
|
||||
hasher->destroy(hasher);
|
||||
|
||||
if (pcr_ok)
|
||||
{
|
||||
boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
|
||||
|
||||
/* TODO handle endianness of client platform */
|
||||
pcr_ok = ima_hash(boot_aggregate, algo, "boot_aggregate",
|
||||
TRUE, PTS_MEAS_ALGO_SHA1, pcr_buffer);
|
||||
}
|
||||
if (pcr_ok)
|
||||
{
|
||||
success = chunk_equals(boot_aggregate, measurement);
|
||||
DBG1(DBG_PTS, "boot aggregate value is %scorrect",
|
||||
success ? "":"in");
|
||||
return success;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_PTS, "failed to compute boot aggregate value");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
|
||||
pts_ita_comp_ima_t *this)
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_evidence_flags, uint8_t,
|
||||
pts_ita_comp_ima_t *this)
|
||||
{
|
||||
return PTS_REQ_FUNC_COMP_EVID_PCR;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_depth, uint32_t,
|
||||
pts_ita_comp_ima_t *this)
|
||||
{
|
||||
return this->depth;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, measure, status_t,
|
||||
pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
|
||||
pts_comp_evidence_t **evidence)
|
||||
{
|
||||
pts_pcr_t *pcrs;
|
||||
pts_comp_evidence_t *evid = NULL;
|
||||
size_t algo_len, name_len;
|
||||
chunk_t measurement;
|
||||
char *uri, *algo, *name;
|
||||
uint32_t pcr;
|
||||
status_t status;
|
||||
|
||||
pcrs = pts->get_pcrs(pts);
|
||||
|
||||
if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_TRUSTED))
|
||||
{
|
||||
switch (this->state)
|
||||
{
|
||||
case IMA_STATE_INIT:
|
||||
this->bios_list = pts_ima_bios_list_create(
|
||||
IMA_BIOS_MEASUREMENTS);
|
||||
if (!this->bios_list)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
this->creation_time = this->bios_list->get_time(this->bios_list);
|
||||
this->bios_count = this->bios_list->get_count(this->bios_list);
|
||||
this->state = IMA_STATE_BIOS;
|
||||
/* fall through to next state */
|
||||
case IMA_STATE_BIOS:
|
||||
status = this->bios_list->get_next(this->bios_list, &pcr,
|
||||
&measurement);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_PTS, "could not retrieve bios measurement entry");
|
||||
return status;
|
||||
}
|
||||
evid = extend_pcr(this, qualifier, pcrs, pcr, measurement);
|
||||
|
||||
this->state = this->bios_list->get_count(this->bios_list) ?
|
||||
IMA_STATE_BIOS : IMA_STATE_INIT;
|
||||
break;
|
||||
default:
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_OS))
|
||||
{
|
||||
switch (this->state)
|
||||
{
|
||||
case IMA_STATE_INIT:
|
||||
this->ima_list = pts_ima_event_list_create(
|
||||
IMA_RUNTIME_MEASUREMENTS);
|
||||
if (!this->ima_list)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
this->creation_time = this->ima_list->get_time(this->ima_list);
|
||||
this->count = this->ima_list->get_count(this->ima_list);
|
||||
this->state = IMA_STATE_BOOT_AGGREGATE;
|
||||
/* fall through to next state */
|
||||
case IMA_STATE_BOOT_AGGREGATE:
|
||||
case IMA_STATE_RUNTIME:
|
||||
status = this->ima_list->get_next(this->ima_list, &measurement,
|
||||
&algo, &name);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_PTS, "could not retrieve ima measurement entry");
|
||||
return status;
|
||||
}
|
||||
if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
|
||||
{
|
||||
if (!check_boot_aggregate(pcrs, measurement, algo))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
|
||||
measurement);
|
||||
if (evid)
|
||||
{
|
||||
if (algo)
|
||||
{
|
||||
algo_len = strlen(algo);
|
||||
name_len = strlen(name);
|
||||
uri = malloc(algo_len + name_len + 1);
|
||||
memcpy(uri, algo, algo_len);
|
||||
strcpy(uri + algo_len, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
uri = strdup(name);
|
||||
}
|
||||
evid->set_validation(evid, PTS_COMP_EVID_VALIDATION_PASSED,
|
||||
uri);
|
||||
free(uri);
|
||||
}
|
||||
free(name);
|
||||
free(algo);
|
||||
|
||||
this->state = this->ima_list->get_count(this->ima_list) ?
|
||||
IMA_STATE_RUNTIME : IMA_STATE_END;
|
||||
break;
|
||||
default:
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_PTS, "unsupported functional component name qualifier");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
*evidence = evid;
|
||||
if (!evid)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
return (this->state == IMA_STATE_INIT || this->state == IMA_STATE_END) ?
|
||||
SUCCESS : NEED_MORE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a validation URI of the form <hash algorithm>:<event name>
|
||||
* into its components
|
||||
*/
|
||||
static pts_meas_algorithms_t parse_validation_uri(pts_comp_evidence_t *evidence,
|
||||
char **ima_name, char **ima_algo, char *algo_buf)
|
||||
{
|
||||
pts_meas_algorithms_t hash_algo;
|
||||
char *uri, *pos, *algo, *name;
|
||||
|
||||
evidence->get_validation(evidence, &uri);
|
||||
|
||||
/* IMA-NG format? */
|
||||
pos = strchr(uri, ':');
|
||||
if (pos && (pos - uri + 1) < IMA_ALGO_LEN_MAX)
|
||||
{
|
||||
memset(algo_buf, '\0', IMA_ALGO_LEN_MAX);
|
||||
memcpy(algo_buf, uri, pos - uri + 1);
|
||||
algo = algo_buf;
|
||||
name = pos + 1;
|
||||
|
||||
if (streq(algo, "sha1:") || streq(algo, ":"))
|
||||
{
|
||||
hash_algo = PTS_MEAS_ALGO_SHA1;
|
||||
}
|
||||
else if (streq(algo, "sha256:"))
|
||||
{
|
||||
hash_algo = PTS_MEAS_ALGO_SHA256;
|
||||
}
|
||||
else if (streq(algo, "sha384:"))
|
||||
{
|
||||
hash_algo = PTS_MEAS_ALGO_SHA384;
|
||||
}
|
||||
else
|
||||
{
|
||||
hash_algo = PTS_MEAS_ALGO_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
algo = NULL;
|
||||
name = uri;
|
||||
hash_algo = PTS_MEAS_ALGO_SHA1;
|
||||
}
|
||||
|
||||
if (ima_name)
|
||||
{
|
||||
*ima_name = name;
|
||||
}
|
||||
if (ima_algo)
|
||||
{
|
||||
*ima_algo = algo;
|
||||
}
|
||||
|
||||
return hash_algo;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, verify, status_t,
|
||||
pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
|
||||
pts_comp_evidence_t *evidence)
|
||||
{
|
||||
bool has_pcr_info;
|
||||
uint32_t pcr;
|
||||
pts_meas_algorithms_t algo;
|
||||
pts_pcr_transform_t transform;
|
||||
pts_pcr_t *pcrs;
|
||||
time_t creation_time;
|
||||
chunk_t measurement, pcr_before, pcr_after;
|
||||
status_t status = NOT_FOUND;
|
||||
|
||||
this->aik_id = pts->get_aik_id(pts);
|
||||
pcrs = pts->get_pcrs(pts);
|
||||
measurement = evidence->get_measurement(evidence, &pcr, &algo, &transform,
|
||||
&creation_time);
|
||||
|
||||
if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_TRUSTED))
|
||||
{
|
||||
switch (this->state)
|
||||
{
|
||||
case IMA_STATE_INIT:
|
||||
this->name->set_qualifier(this->name, qualifier);
|
||||
status = this->pts_db->get_comp_measurement_count(this->pts_db,
|
||||
this->name, this->aik_id, algo,
|
||||
&this->bios_cid, &this->bios_count);
|
||||
this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (this->bios_count)
|
||||
{
|
||||
DBG1(DBG_PTS, "checking %d BIOS evidence measurements",
|
||||
this->bios_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_PTS, "registering BIOS evidence measurements");
|
||||
this->is_bios_registering = TRUE;
|
||||
}
|
||||
|
||||
this->state = IMA_STATE_BIOS;
|
||||
/* fall through to next state */
|
||||
case IMA_STATE_BIOS:
|
||||
if (this->is_bios_registering)
|
||||
{
|
||||
status = this->pts_db->insert_comp_measurement(this->pts_db,
|
||||
measurement, this->bios_cid, this->aik_id,
|
||||
++this->seq_no, pcr, algo);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
this->bios_count = this->seq_no + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = this->pts_db->check_comp_measurement(this->pts_db,
|
||||
measurement, this->bios_cid, this->aik_id,
|
||||
++this->seq_no, pcr, algo);
|
||||
if (status == FAILED)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_OS))
|
||||
{
|
||||
int ima_count;
|
||||
char *ima_algo, *ima_name;
|
||||
char algo_buf[IMA_ALGO_LEN_MAX];
|
||||
pts_meas_algorithms_t hash_algo;
|
||||
|
||||
hash_algo = parse_validation_uri(evidence, &ima_name, &ima_algo,
|
||||
algo_buf);
|
||||
|
||||
switch (this->state)
|
||||
{
|
||||
case IMA_STATE_BIOS:
|
||||
this->state = IMA_STATE_RUNTIME;
|
||||
|
||||
if (!streq(ima_name, "boot_aggregate"))
|
||||
{
|
||||
DBG1(DBG_PTS, "ima: name must be 'boot_aggregate' "
|
||||
"but is '%s'", ima_name);
|
||||
return FAILED;
|
||||
}
|
||||
if (hash_algo != PTS_MEAS_ALGO_SHA1)
|
||||
{
|
||||
DBG1(DBG_PTS, "ima: boot_aggregate algorithm must be %N "
|
||||
"but is %N",
|
||||
pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1,
|
||||
pts_meas_algorithm_names, hash_algo);
|
||||
return FAILED;
|
||||
}
|
||||
if (!check_boot_aggregate(pcrs, measurement, ima_algo))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
this->state = IMA_STATE_INIT;
|
||||
/* fall through to next state */
|
||||
case IMA_STATE_INIT:
|
||||
this->name->set_qualifier(this->name, qualifier);
|
||||
status = this->pts_db->get_comp_measurement_count(this->pts_db,
|
||||
this->name, this->aik_id, algo,
|
||||
&this->ima_cid, &ima_count);
|
||||
this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (ima_count)
|
||||
{
|
||||
DBG1(DBG_PTS, "checking boot aggregate evidence "
|
||||
"measurement");
|
||||
status = this->pts_db->check_comp_measurement(this->pts_db,
|
||||
measurement, this->ima_cid,
|
||||
this->aik_id, 1, pcr, algo);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_PTS, "registering boot aggregate evidence "
|
||||
"measurement");
|
||||
this->is_ima_registering = TRUE;
|
||||
status = this->pts_db->insert_comp_measurement(this->pts_db,
|
||||
measurement, this->ima_cid,
|
||||
this->aik_id, 1, pcr, algo);
|
||||
}
|
||||
this->state = IMA_STATE_RUNTIME;
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case IMA_STATE_RUNTIME:
|
||||
{
|
||||
uint8_t hash_buf[HASH_SIZE_SHA512];
|
||||
chunk_t digest, hash;
|
||||
enumerator_t *e;
|
||||
|
||||
this->count++;
|
||||
if (evidence->get_validation(evidence, NULL) !=
|
||||
PTS_COMP_EVID_VALIDATION_PASSED)
|
||||
{
|
||||
DBG1(DBG_PTS, "evidence validation failed");
|
||||
this->count_failed++;
|
||||
return FAILED;
|
||||
}
|
||||
hash = chunk_create(hash_buf, pts_meas_algo_hash_size(algo));
|
||||
|
||||
e = this->pts_db->create_file_meas_enumerator(this->pts_db,
|
||||
pts->get_platform_id(pts),
|
||||
hash_algo, ima_name);
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &digest))
|
||||
{
|
||||
if (!ima_hash(digest, ima_algo, ima_name,
|
||||
FALSE, algo, hash_buf))
|
||||
{
|
||||
status = FAILED;
|
||||
break;
|
||||
}
|
||||
if (chunk_equals(measurement, hash))
|
||||
{
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = VERIFY_ERROR;
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = FAILED;
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case SUCCESS:
|
||||
DBG3(DBG_PTS, "%#B for '%s' is ok",
|
||||
&measurement, ima_name);
|
||||
this->count_ok++;
|
||||
break;
|
||||
case NOT_FOUND:
|
||||
DBG2(DBG_PTS, "%#B for '%s' not found",
|
||||
&measurement, ima_name);
|
||||
this->count_unknown++;
|
||||
break;
|
||||
case VERIFY_ERROR:
|
||||
DBG1(DBG_PTS, "%#B for '%s' differs",
|
||||
&measurement, ima_name);
|
||||
this->count_differ++;
|
||||
break;
|
||||
case FAILED:
|
||||
default:
|
||||
DBG1(DBG_PTS, "%#B for '%s' failed",
|
||||
&measurement, ima_name);
|
||||
this->count_failed++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_PTS, "unsupported functional component name qualifier");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
|
||||
if (has_pcr_info)
|
||||
{
|
||||
if (!chunk_equals(pcr_before, pcrs->get(pcrs, pcr)))
|
||||
{
|
||||
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
|
||||
pcr);
|
||||
}
|
||||
if (pcrs->set(pcrs, pcr, pcr_after))
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pcr_after = pcrs->extend(pcrs, pcr, measurement);
|
||||
if (pcr_after.ptr)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, finalize, bool,
|
||||
pts_ita_comp_ima_t *this, uint8_t qualifier, bio_writer_t *result)
|
||||
{
|
||||
char result_buf[BUF_LEN];
|
||||
char *pos = result_buf;
|
||||
size_t len = BUF_LEN;
|
||||
int written;
|
||||
bool success = TRUE;
|
||||
|
||||
this->name->set_qualifier(this->name, qualifier);
|
||||
|
||||
if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_TRUSTED))
|
||||
{
|
||||
/* finalize BIOS measurements */
|
||||
if (this->is_bios_registering)
|
||||
{
|
||||
/* close registration */
|
||||
this->is_bios_registering = FALSE;
|
||||
|
||||
snprintf(pos, len, "registered %d BIOS evidence measurements",
|
||||
this->seq_no);
|
||||
}
|
||||
else if (this->seq_no < this->bios_count)
|
||||
{
|
||||
snprintf(pos, len, "%d of %d BIOS evidence measurements missing",
|
||||
this->bios_count - this->seq_no, this->bios_count);
|
||||
success = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(pos, len, "%d BIOS evidence measurements are ok",
|
||||
this->bios_count);
|
||||
}
|
||||
}
|
||||
else if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_OS))
|
||||
{
|
||||
/* finalize IMA file measurements */
|
||||
if (this->is_ima_registering)
|
||||
{
|
||||
/* close registration */
|
||||
this->is_ima_registering = FALSE;
|
||||
|
||||
written = snprintf(pos, len, "registered IMA boot aggregate "
|
||||
"evidence measurement; ");
|
||||
pos += written;
|
||||
len -= written;
|
||||
}
|
||||
if (this->count)
|
||||
{
|
||||
snprintf(pos, len, "processed %d IMA file evidence measurements: "
|
||||
"%d ok, %d unknown, %d differ, %d failed",
|
||||
this->count, this->count_ok, this->count_unknown,
|
||||
this->count_differ, this->count_failed);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(pos, len, "no IMA file evidence measurements");
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(pos, len, "unsupported functional component name qualifier");
|
||||
success = FALSE;
|
||||
}
|
||||
this->name->set_qualifier(this->name, PTS_QUALIFIER_UNKNOWN);
|
||||
|
||||
DBG1(DBG_PTS, "%s", result_buf);
|
||||
result->write_data(result, chunk_from_str(result_buf));
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_ref, pts_component_t*,
|
||||
pts_ita_comp_ima_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, destroy, void,
|
||||
pts_ita_comp_ima_t *this)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
|
||||
if (this->is_bios_registering)
|
||||
{
|
||||
count = this->pts_db->delete_comp_measurements(this->pts_db,
|
||||
this->bios_cid, this->aik_id);
|
||||
DBG1(DBG_PTS, "deleted %d registered BIOS evidence measurements",
|
||||
count);
|
||||
}
|
||||
if (this->is_ima_registering)
|
||||
{
|
||||
count = this->pts_db->delete_comp_measurements(this->pts_db,
|
||||
this->ima_cid, this->aik_id);
|
||||
DBG1(DBG_PTS, "deleted registered boot aggregate evidence "
|
||||
"measurement");
|
||||
}
|
||||
DESTROY_IF(this->bios_list);
|
||||
DESTROY_IF(this->ima_list);
|
||||
this->name->destroy(this->name);
|
||||
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_component_t *pts_ita_comp_ima_create(uint32_t depth,
|
||||
pts_database_t *pts_db)
|
||||
{
|
||||
pts_ita_comp_ima_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_comp_func_name = _get_comp_func_name,
|
||||
.get_evidence_flags = _get_evidence_flags,
|
||||
.get_depth = _get_depth,
|
||||
.measure = _measure,
|
||||
.verify = _verify,
|
||||
.finalize = _finalize,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_IMA,
|
||||
PTS_QUALIFIER_UNKNOWN),
|
||||
.depth = depth,
|
||||
.pts_db = pts_db,
|
||||
.pcr_info = lib->settings->get_bool(lib->settings,
|
||||
"%s.plugins.imc-attestation.pcr_info", FALSE, lib->ns),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_ita_comp_func_name pts_ita_comp_func_name
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_ITA_COMP_IMA_H_
|
||||
#define PTS_ITA_COMP_IMA_H_
|
||||
|
||||
#include "pts/components/pts_component.h"
|
||||
|
||||
/**
|
||||
* Create a PTS ITS Functional Component object
|
||||
*
|
||||
* @param depth Sub-component depth
|
||||
* @param pts_db PTS measurement database
|
||||
*/
|
||||
pts_component_t* pts_ita_comp_ima_create(u_int32_t depth,
|
||||
pts_database_t *pts_db);
|
||||
|
||||
#endif /** PTS_ITA_COMP_IMA_H_ @}*/
|
||||
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ita_comp_tboot.h"
|
||||
#include "ita_comp_func_name.h"
|
||||
|
||||
#include "imcv.h"
|
||||
#include "pts/components/pts_component.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <pen/pen.h>
|
||||
|
||||
typedef struct pts_ita_comp_tboot_t pts_ita_comp_tboot_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_ita_comp_tboot_t object.
|
||||
*
|
||||
*/
|
||||
struct pts_ita_comp_tboot_t {
|
||||
|
||||
/**
|
||||
* Public pts_component_t interface.
|
||||
*/
|
||||
pts_component_t public;
|
||||
|
||||
/**
|
||||
* Component Functional Name
|
||||
*/
|
||||
pts_comp_func_name_t *name;
|
||||
|
||||
/**
|
||||
* Sub-component depth
|
||||
*/
|
||||
u_int32_t depth;
|
||||
|
||||
/**
|
||||
* PTS measurement database
|
||||
*/
|
||||
pts_database_t *pts_db;
|
||||
|
||||
/**
|
||||
* Primary key for AIK database entry
|
||||
*/
|
||||
int aik_id;
|
||||
|
||||
/**
|
||||
* Primary key for Component Functional Name database entry
|
||||
*/
|
||||
int cid;
|
||||
|
||||
/**
|
||||
* Primary key for AIK database entry
|
||||
*/
|
||||
int kid;
|
||||
|
||||
/**
|
||||
* Component is registering measurements
|
||||
*/
|
||||
bool is_registering;
|
||||
|
||||
/**
|
||||
* Time of TBOOT measurement
|
||||
*/
|
||||
time_t measurement_time;
|
||||
|
||||
/**
|
||||
* Expected measurement count
|
||||
*/
|
||||
int count;
|
||||
|
||||
/**
|
||||
* Measurement sequence number
|
||||
*/
|
||||
int seq_no;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
|
||||
};
|
||||
|
||||
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
|
||||
pts_ita_comp_tboot_t *this)
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_evidence_flags, u_int8_t,
|
||||
pts_ita_comp_tboot_t *this)
|
||||
{
|
||||
return PTS_REQ_FUNC_COMP_EVID_PCR;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_depth, u_int32_t,
|
||||
pts_ita_comp_tboot_t *this)
|
||||
{
|
||||
return this->depth;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, measure, status_t,
|
||||
pts_ita_comp_tboot_t *this, u_int8_t qualifier, pts_t *pts,
|
||||
pts_comp_evidence_t **evidence)
|
||||
|
||||
{
|
||||
size_t pcr_len;
|
||||
pts_pcr_t *pcrs;
|
||||
pts_pcr_transform_t pcr_transform;
|
||||
pts_meas_algorithms_t hash_algo;
|
||||
pts_comp_evidence_t *evid;
|
||||
char *meas_hex, *pcr_before_hex, *pcr_after_hex;
|
||||
chunk_t measurement, pcr_before, pcr_after;
|
||||
u_int32_t extended_pcr;
|
||||
|
||||
switch (this->seq_no++)
|
||||
{
|
||||
case 0:
|
||||
/* dummy data since currently the TBOOT log is not retrieved */
|
||||
time(&this->measurement_time);
|
||||
meas_hex = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imc-attestation.pcr17_meas", NULL, lib->ns);
|
||||
pcr_before_hex = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imc-attestation.pcr17_before", NULL, lib->ns);
|
||||
pcr_after_hex = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imc-attestation.pcr17_after", NULL, lib->ns);
|
||||
extended_pcr = PCR_TBOOT_POLICY;
|
||||
break;
|
||||
case 1:
|
||||
/* dummy data since currently the TBOOT log is not retrieved */
|
||||
meas_hex = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imc-attestation.pcr18_meas", NULL, lib->ns);
|
||||
pcr_before_hex = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imc-attestation.pcr18_before", NULL, lib->ns);
|
||||
pcr_after_hex = lib->settings->get_str(lib->settings,
|
||||
"%s.plugins.imc-attestation.pcr18_after", NULL, lib->ns);
|
||||
extended_pcr = PCR_TBOOT_MLE;
|
||||
break;
|
||||
default:
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (meas_hex == NULL || pcr_before_hex == NULL || pcr_after_hex == NULL)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
hash_algo = PTS_MEAS_ALGO_SHA1;
|
||||
pcr_len = HASH_SIZE_SHA1;
|
||||
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
|
||||
|
||||
/* get and check the measurement data */
|
||||
measurement = chunk_from_hex(
|
||||
chunk_create(meas_hex, strlen(meas_hex)), NULL);
|
||||
pcr_before = chunk_from_hex(
|
||||
chunk_create(pcr_before_hex, strlen(pcr_before_hex)), NULL);
|
||||
pcr_after = chunk_from_hex(
|
||||
chunk_create(pcr_after_hex, strlen(pcr_after_hex)), NULL);
|
||||
if (pcr_before.len != pcr_len || pcr_after.len != pcr_len ||
|
||||
measurement.len != pcr_len)
|
||||
{
|
||||
DBG1(DBG_PTS, "TBOOT measurement or PCR data have the wrong size");
|
||||
free(measurement.ptr);
|
||||
free(pcr_before.ptr);
|
||||
free(pcr_after.ptr);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
pcrs = pts->get_pcrs(pts);
|
||||
pcrs->set(pcrs, extended_pcr, pcr_after);
|
||||
evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
|
||||
this->depth, extended_pcr, hash_algo, pcr_transform,
|
||||
this->measurement_time, measurement);
|
||||
evid->set_pcr_info(evid, pcr_before, pcr_after);
|
||||
|
||||
return (this->seq_no < 2) ? NEED_MORE : SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, verify, status_t,
|
||||
pts_ita_comp_tboot_t *this, u_int8_t qualifier,pts_t *pts,
|
||||
pts_comp_evidence_t *evidence)
|
||||
{
|
||||
bool has_pcr_info;
|
||||
u_int32_t extended_pcr, vid, name;
|
||||
enum_name_t *names;
|
||||
pts_meas_algorithms_t algo;
|
||||
pts_pcr_transform_t transform;
|
||||
pts_pcr_t *pcrs;
|
||||
time_t measurement_time;
|
||||
chunk_t measurement, pcr_before, pcr_after;
|
||||
status_t status;
|
||||
|
||||
this->aik_id = pts->get_aik_id(pts);
|
||||
pcrs = pts->get_pcrs(pts);
|
||||
measurement = evidence->get_measurement(evidence, &extended_pcr,
|
||||
&algo, &transform, &measurement_time);
|
||||
|
||||
status = this->pts_db->get_comp_measurement_count(this->pts_db,
|
||||
this->name, this->aik_id, algo,
|
||||
&this->cid, &this->count);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
vid = this->name->get_vendor_id(this->name);
|
||||
name = this->name->get_name(this->name);
|
||||
names = imcv_pts_components->get_comp_func_names(imcv_pts_components, vid);
|
||||
|
||||
if (this->count)
|
||||
{
|
||||
DBG1(DBG_PTS, "checking %d %N '%N' functional component evidence "
|
||||
"measurements", this->count, pen_names, vid, names, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_PTS, "registering %N '%N' functional component evidence "
|
||||
"measurements", pen_names, vid, names, name);
|
||||
this->is_registering = TRUE;
|
||||
}
|
||||
|
||||
if (this->is_registering)
|
||||
{
|
||||
status = this->pts_db->insert_comp_measurement(this->pts_db,
|
||||
measurement, this->cid, this->aik_id,
|
||||
++this->seq_no, extended_pcr, algo);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
this->count = this->seq_no + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = this->pts_db->check_comp_measurement(this->pts_db,
|
||||
measurement, this->cid, this->kid,
|
||||
++this->seq_no, extended_pcr, algo);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
|
||||
if (has_pcr_info)
|
||||
{
|
||||
if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
|
||||
{
|
||||
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
|
||||
extended_pcr);
|
||||
}
|
||||
if (pcrs->set(pcrs, extended_pcr, pcr_after))
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, finalize, bool,
|
||||
pts_ita_comp_tboot_t *this, u_int8_t qualifier, bio_writer_t *result)
|
||||
{
|
||||
char result_buf[BUF_LEN];
|
||||
|
||||
if (this->is_registering)
|
||||
{
|
||||
/* close registration */
|
||||
this->is_registering = FALSE;
|
||||
|
||||
snprintf(result_buf, BUF_LEN, "registered %d evidence measurements",
|
||||
this->seq_no);
|
||||
}
|
||||
else if (this->seq_no < this->count)
|
||||
{
|
||||
snprintf(result_buf, BUF_LEN, "%d of %d evidence measurements "
|
||||
"missing", this->count - this->seq_no, this->count);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(result_buf, BUF_LEN, "%d evidence measurements are ok",
|
||||
this->count);
|
||||
}
|
||||
DBG1(DBG_PTS, "%s", result_buf);
|
||||
result->write_data(result, chunk_from_str(result_buf));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_ref, pts_component_t*,
|
||||
pts_ita_comp_tboot_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, destroy, void,
|
||||
pts_ita_comp_tboot_t *this)
|
||||
{
|
||||
int count;
|
||||
u_int32_t vid, name;
|
||||
enum_name_t *names;
|
||||
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
if (this->is_registering)
|
||||
{
|
||||
count = this->pts_db->delete_comp_measurements(this->pts_db,
|
||||
this->cid, this->aik_id);
|
||||
vid = this->name->get_vendor_id(this->name);
|
||||
name = this->name->get_name(this->name);
|
||||
names = imcv_pts_components->get_comp_func_names(imcv_pts_components,
|
||||
vid);
|
||||
DBG1(DBG_PTS, "deleted %d registered %N '%N' functional component "
|
||||
"evidence measurements", count, pen_names, vid, names, name);
|
||||
}
|
||||
this->name->destroy(this->name);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_component_t *pts_ita_comp_tboot_create(u_int32_t depth,
|
||||
pts_database_t *pts_db)
|
||||
{
|
||||
pts_ita_comp_tboot_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_comp_func_name = _get_comp_func_name,
|
||||
.get_evidence_flags = _get_evidence_flags,
|
||||
.get_depth = _get_depth,
|
||||
.measure = _measure,
|
||||
.verify = _verify,
|
||||
.finalize = _finalize,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TBOOT,
|
||||
PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_TRUSTED),
|
||||
.depth = depth,
|
||||
.pts_db = pts_db,
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_ita_comp_func_name pts_ita_comp_func_name
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_ITA_COMP_TBOOT_H_
|
||||
#define PTS_ITA_COMP_TBOOT_H_
|
||||
|
||||
#include "pts/components/pts_component.h"
|
||||
|
||||
/**
|
||||
* Create a PTS ITS Functional Component object
|
||||
*
|
||||
* @param depth Sub-component depth
|
||||
* @param pts_db PTS measurement database
|
||||
*/
|
||||
pts_component_t* pts_ita_comp_tboot_create(u_int32_t depth,
|
||||
pts_database_t *pts_db);
|
||||
|
||||
#endif /** PTS_ITA_COMP_TBOOT_H_ @}*/
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ita_comp_tgrub.h"
|
||||
#include "ita_comp_func_name.h"
|
||||
|
||||
#include "pts/components/pts_component.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <pen/pen.h>
|
||||
|
||||
typedef struct pts_ita_comp_tgrub_t pts_ita_comp_tgrub_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_ita_comp_tgrub_t object.
|
||||
*
|
||||
*/
|
||||
struct pts_ita_comp_tgrub_t {
|
||||
|
||||
/**
|
||||
* Public pts_component_t interface.
|
||||
*/
|
||||
pts_component_t public;
|
||||
|
||||
/**
|
||||
* Component Functional Name
|
||||
*/
|
||||
pts_comp_func_name_t *name;
|
||||
|
||||
/**
|
||||
* Sub-component depth
|
||||
*/
|
||||
u_int32_t depth;
|
||||
|
||||
/**
|
||||
* PTS measurement database
|
||||
*/
|
||||
pts_database_t *pts_db;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
|
||||
};
|
||||
|
||||
METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
|
||||
pts_ita_comp_tgrub_t *this)
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_evidence_flags, u_int8_t,
|
||||
pts_ita_comp_tgrub_t *this)
|
||||
{
|
||||
return PTS_REQ_FUNC_COMP_EVID_PCR;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_depth, u_int32_t,
|
||||
pts_ita_comp_tgrub_t *this)
|
||||
{
|
||||
return this->depth;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, measure, status_t,
|
||||
pts_ita_comp_tgrub_t *this, u_int8_t qualifier, pts_t *pts,
|
||||
pts_comp_evidence_t **evidence)
|
||||
{
|
||||
size_t pcr_len;
|
||||
pts_pcr_transform_t pcr_transform;
|
||||
pts_meas_algorithms_t hash_algo;
|
||||
pts_comp_evidence_t *evid;
|
||||
u_int32_t extended_pcr;
|
||||
time_t measurement_time;
|
||||
chunk_t measurement, pcr_before, pcr_after;
|
||||
|
||||
/* Provisional implementation for TGRUB */
|
||||
extended_pcr = PCR_DEBUG;
|
||||
time(&measurement_time);
|
||||
|
||||
if (!pts->read_pcr(pts, extended_pcr, &pcr_after))
|
||||
{
|
||||
DBG1(DBG_PTS, "error occurred while reading PCR: %d", extended_pcr);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
hash_algo = PTS_MEAS_ALGO_SHA1;
|
||||
pcr_len = HASH_SIZE_SHA1;
|
||||
pcr_transform = pts_meas_algo_to_pcr_transform(hash_algo, pcr_len);
|
||||
|
||||
measurement = chunk_alloc(pcr_len);
|
||||
memset(measurement.ptr, 0x00, measurement.len);
|
||||
|
||||
pcr_before = chunk_alloc(pcr_len);
|
||||
memset(pcr_before.ptr, 0x00, pcr_before.len);
|
||||
|
||||
evid = *evidence = pts_comp_evidence_create(this->name->clone(this->name),
|
||||
this->depth, extended_pcr,
|
||||
hash_algo, pcr_transform,
|
||||
measurement_time, measurement);
|
||||
evid->set_pcr_info(evid, pcr_before, pcr_after);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, verify, status_t,
|
||||
pts_ita_comp_tgrub_t *this, u_int8_t qualifier, pts_t *pts,
|
||||
pts_comp_evidence_t *evidence)
|
||||
{
|
||||
bool has_pcr_info;
|
||||
u_int32_t extended_pcr;
|
||||
pts_meas_algorithms_t algo;
|
||||
pts_pcr_transform_t transform;
|
||||
pts_pcr_t *pcrs;
|
||||
time_t measurement_time;
|
||||
chunk_t pcr_before, pcr_after;
|
||||
chunk_t measurement __attribute__((unused));
|
||||
|
||||
pcrs = pts->get_pcrs(pts);
|
||||
measurement = evidence->get_measurement(evidence, &extended_pcr,
|
||||
&algo, &transform, &measurement_time);
|
||||
if (extended_pcr != PCR_DEBUG)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* TODO check measurement in database */
|
||||
|
||||
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
|
||||
if (has_pcr_info)
|
||||
{
|
||||
if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
|
||||
{
|
||||
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
|
||||
}
|
||||
if (pcrs->set(pcrs, extended_pcr, pcr_after))
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, finalize, bool,
|
||||
pts_ita_comp_tgrub_t *this, u_int8_t qualifier, bio_writer_t *result)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, get_ref, pts_component_t*,
|
||||
pts_ita_comp_tgrub_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, destroy, void,
|
||||
pts_ita_comp_tgrub_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
this->name->destroy(this->name);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_component_t *pts_ita_comp_tgrub_create(u_int32_t depth,
|
||||
pts_database_t *pts_db)
|
||||
{
|
||||
pts_ita_comp_tgrub_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_comp_func_name = _get_comp_func_name,
|
||||
.get_evidence_flags = _get_evidence_flags,
|
||||
.get_depth = _get_depth,
|
||||
.measure = _measure,
|
||||
.verify = _verify,
|
||||
.finalize = _finalize,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.name = pts_comp_func_name_create(PEN_ITA, PTS_ITA_COMP_FUNC_NAME_TGRUB,
|
||||
PTS_ITA_QUALIFIER_FLAG_KERNEL |
|
||||
PTS_ITA_QUALIFIER_TYPE_TRUSTED),
|
||||
.depth = depth,
|
||||
.pts_db = pts_db,
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_ita_comp_func_name pts_ita_comp_func_name
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_ITA_COMP_TGRUB_H_
|
||||
#define PTS_ITA_COMP_TGRUB_H_
|
||||
|
||||
#include "pts/components/pts_component.h"
|
||||
|
||||
/**
|
||||
* Create a PTS ITS Functional Component object
|
||||
*
|
||||
* @param depth Sub-component depth
|
||||
* @param pts_db PTS measurement database
|
||||
*/
|
||||
pts_component_t* pts_ita_comp_tgrub_create(u_int32_t depth,
|
||||
pts_database_t *pts_db);
|
||||
|
||||
#endif /** PTS_ITA_COMP_TGRUB_H_ @}*/
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Sansar Choinyambuu, Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts/components/pts_comp_evidence.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_pts_comp_evidence_t private_pts_comp_evidence_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_comp_evidence_t object.
|
||||
*/
|
||||
struct private_pts_comp_evidence_t {
|
||||
|
||||
/**
|
||||
* Public pts_comp_evidence_t interface.
|
||||
*/
|
||||
pts_comp_evidence_t public;
|
||||
|
||||
/**
|
||||
* Component Functional Name
|
||||
*/
|
||||
pts_comp_func_name_t *name;
|
||||
|
||||
/**
|
||||
* Sub-Component Depth
|
||||
*/
|
||||
u_int32_t depth;
|
||||
|
||||
/**
|
||||
* Measurement Time
|
||||
*/
|
||||
time_t measurement_time;
|
||||
|
||||
/**
|
||||
* Measurement Time
|
||||
*/
|
||||
chunk_t measurement;
|
||||
|
||||
/**
|
||||
* Measurement Hash Algorithm
|
||||
*/
|
||||
pts_meas_algorithms_t hash_algorithm;
|
||||
|
||||
/**
|
||||
* Is PCR Information included?
|
||||
*/
|
||||
bool has_pcr_info;
|
||||
|
||||
/**
|
||||
* PCR the measurement was extended into
|
||||
*/
|
||||
u_int32_t extended_pcr;
|
||||
|
||||
/**
|
||||
* PCR value before extension
|
||||
*/
|
||||
chunk_t pcr_before;
|
||||
|
||||
/**
|
||||
* PCR value after extension
|
||||
*/
|
||||
chunk_t pcr_after;
|
||||
|
||||
/**
|
||||
* Transformation used for extending measurement into PCR
|
||||
*/
|
||||
pts_pcr_transform_t transform;
|
||||
|
||||
/**
|
||||
* Component Validation Result
|
||||
*/
|
||||
pts_comp_evid_validation_t validation;
|
||||
|
||||
/**
|
||||
* Verification Policy URI
|
||||
*/
|
||||
char *policy_uri;
|
||||
|
||||
};
|
||||
|
||||
METHOD(pts_comp_evidence_t, get_comp_func_name, pts_comp_func_name_t*,
|
||||
private_pts_comp_evidence_t *this, u_int32_t *depth)
|
||||
{
|
||||
if (depth)
|
||||
{
|
||||
*depth = this->depth;
|
||||
}
|
||||
return this->name;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_evidence_t, get_extended_pcr, u_int32_t,
|
||||
private_pts_comp_evidence_t *this)
|
||||
{
|
||||
return this->extended_pcr;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_evidence_t, get_measurement, chunk_t,
|
||||
private_pts_comp_evidence_t *this, u_int32_t *extended_pcr,
|
||||
pts_meas_algorithms_t *algo, pts_pcr_transform_t *transform,
|
||||
time_t *measurement_time)
|
||||
{
|
||||
if (extended_pcr)
|
||||
{
|
||||
*extended_pcr = this->extended_pcr;
|
||||
}
|
||||
if (algo)
|
||||
{
|
||||
*algo = this->hash_algorithm;
|
||||
}
|
||||
if (transform)
|
||||
{
|
||||
*transform = this->transform;
|
||||
}
|
||||
if (measurement_time)
|
||||
{
|
||||
*measurement_time = this->measurement_time;
|
||||
}
|
||||
return this->measurement;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_evidence_t, get_pcr_info, bool,
|
||||
private_pts_comp_evidence_t *this, chunk_t *pcr_before, chunk_t *pcr_after)
|
||||
{
|
||||
if (pcr_before)
|
||||
{
|
||||
*pcr_before = this->pcr_before;
|
||||
}
|
||||
if (pcr_after)
|
||||
{
|
||||
*pcr_after = this->pcr_after;
|
||||
}
|
||||
return this->has_pcr_info;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_evidence_t, set_pcr_info, void,
|
||||
private_pts_comp_evidence_t *this, chunk_t pcr_before, chunk_t pcr_after)
|
||||
{
|
||||
this->has_pcr_info = TRUE;
|
||||
this->pcr_before = pcr_before;
|
||||
this->pcr_after = pcr_after;
|
||||
|
||||
DBG3(DBG_PTS, "PCR %2d before value : %#B", this->extended_pcr, &pcr_before);
|
||||
DBG3(DBG_PTS, "PCR %2d after value : %#B", this->extended_pcr, &pcr_after);
|
||||
}
|
||||
|
||||
METHOD(pts_comp_evidence_t, get_validation, pts_comp_evid_validation_t,
|
||||
private_pts_comp_evidence_t *this, char **uri)
|
||||
{
|
||||
if (uri)
|
||||
{
|
||||
*uri = this->policy_uri;
|
||||
}
|
||||
return this->validation;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_evidence_t, set_validation, void,
|
||||
private_pts_comp_evidence_t *this, pts_comp_evid_validation_t validation,
|
||||
char *uri)
|
||||
{
|
||||
this->validation = validation;
|
||||
if (uri)
|
||||
{
|
||||
this->policy_uri = strdup(uri);
|
||||
DBG3(DBG_PTS, "'%s'", uri);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(pts_comp_evidence_t, destroy, void,
|
||||
private_pts_comp_evidence_t *this)
|
||||
{
|
||||
this->name->destroy(this->name);
|
||||
free(this->measurement.ptr);
|
||||
free(this->pcr_before.ptr);
|
||||
free(this->pcr_after.ptr);
|
||||
free(this->policy_uri);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_comp_evidence_t *pts_comp_evidence_create(pts_comp_func_name_t *name,
|
||||
u_int32_t depth,
|
||||
u_int32_t extended_pcr,
|
||||
pts_meas_algorithms_t algo,
|
||||
pts_pcr_transform_t transform,
|
||||
time_t measurement_time,
|
||||
chunk_t measurement)
|
||||
{
|
||||
private_pts_comp_evidence_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_comp_func_name = _get_comp_func_name,
|
||||
.get_extended_pcr = _get_extended_pcr,
|
||||
.get_measurement = _get_measurement,
|
||||
.get_pcr_info = _get_pcr_info,
|
||||
.set_pcr_info = _set_pcr_info,
|
||||
.get_validation = _get_validation,
|
||||
.set_validation = _set_validation,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.name = name,
|
||||
.depth = depth,
|
||||
.extended_pcr = extended_pcr,
|
||||
.hash_algorithm = algo,
|
||||
.transform = transform,
|
||||
.measurement_time = measurement_time,
|
||||
.measurement = measurement,
|
||||
);
|
||||
|
||||
name->log(name, "");
|
||||
DBG3(DBG_PTS, "measurement time: %T", &measurement_time, FALSE);
|
||||
DBG3(DBG_PTS, "PCR %2d extended with: %#B", extended_pcr, &measurement);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_pcr_transform_t pts_meas_algo_to_pcr_transform(pts_meas_algorithms_t algo,
|
||||
size_t pcr_len)
|
||||
{
|
||||
size_t hash_size;
|
||||
|
||||
hash_size = pts_meas_algo_hash_size(algo);
|
||||
if (hash_size == 0)
|
||||
{
|
||||
return PTS_PCR_TRANSFORM_NO;
|
||||
}
|
||||
if (hash_size == pcr_len)
|
||||
{
|
||||
return PTS_PCR_TRANSFORM_MATCH;
|
||||
}
|
||||
if (hash_size > pcr_len)
|
||||
{
|
||||
return PTS_PCR_TRANSFORM_LONG;
|
||||
}
|
||||
return PTS_PCR_TRANSFORM_SHORT;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Sansar Choinyambuu, Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_comp_evidence pts_comp_evidence
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_COMP_EVIDENCE_H_
|
||||
#define PTS_COMP_EVIDENCE_H_
|
||||
|
||||
typedef struct pts_comp_evidence_t pts_comp_evidence_t;
|
||||
typedef enum pts_pcr_transform_t pts_pcr_transform_t;
|
||||
typedef enum pts_comp_evid_validation_t pts_comp_evid_validation_t;
|
||||
|
||||
#include "pts/pts_meas_algo.h"
|
||||
#include "pts/components/pts_comp_func_name.h"
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* PTS PCR Transformations
|
||||
*/
|
||||
enum pts_pcr_transform_t {
|
||||
/** No Transformation */
|
||||
PTS_PCR_TRANSFORM_NO = 0,
|
||||
/** Hash Value matched PCR size */
|
||||
PTS_PCR_TRANSFORM_MATCH = 1,
|
||||
/** Hash value shorter than PCR size */
|
||||
PTS_PCR_TRANSFORM_SHORT = 2,
|
||||
/** Hash value longer than PCR size */
|
||||
PTS_PCR_TRANSFORM_LONG = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* PTS Component Evidence Validation Result Flags
|
||||
*/
|
||||
enum pts_comp_evid_validation_t {
|
||||
/** No Validation was attempted */
|
||||
PTS_COMP_EVID_VALIDATION_NONE = 0x00,
|
||||
/** Attempted validation, unable to verify */
|
||||
PTS_COMP_EVID_VALIDATION_UNABLE = 0x20,
|
||||
/** Attempted validation, verification failed */
|
||||
PTS_COMP_EVID_VALIDATION_FAILED = 0x40,
|
||||
/** Attempted validation, verification passed */
|
||||
PTS_COMP_EVID_VALIDATION_PASSED = 0x60,
|
||||
};
|
||||
|
||||
/**
|
||||
* PTS Functional Component Interface
|
||||
*/
|
||||
struct pts_comp_evidence_t {
|
||||
|
||||
/**
|
||||
* Gets the Component Functional Name and Sub-Component Depth
|
||||
*
|
||||
* @param depth Sub-Component Depth
|
||||
* @result Component Functional Name
|
||||
*/
|
||||
pts_comp_func_name_t* (*get_comp_func_name)(pts_comp_evidence_t *this,
|
||||
u_int32_t *depth);
|
||||
|
||||
/**
|
||||
* Gets the PCR the measurement was extended into
|
||||
*
|
||||
* @result PCR the measurement was extended into
|
||||
*/
|
||||
u_int32_t (*get_extended_pcr)(pts_comp_evidence_t *this);
|
||||
|
||||
/**
|
||||
* Gets the measurement and the algorithms used
|
||||
*
|
||||
* @param extended_pcr PCR the measurement was extended into
|
||||
* @param algo Measurement hash algorithm
|
||||
* @param transform Transformation used for PCR extension
|
||||
* @param measurement_time Time the measurement was taken
|
||||
* @result Measurement hash value
|
||||
*/
|
||||
chunk_t (*get_measurement)(pts_comp_evidence_t *this,
|
||||
u_int32_t *extended_pcr,
|
||||
pts_meas_algorithms_t *algo,
|
||||
pts_pcr_transform_t *transform,
|
||||
time_t *measurement_time);
|
||||
|
||||
/**
|
||||
* Gets the PCR information if available
|
||||
*
|
||||
* @param pcr_before PCR value before extension
|
||||
* @param pcr_after PCR value after extension
|
||||
* @result TRUE if PCR information is available
|
||||
*/
|
||||
bool (*get_pcr_info)(pts_comp_evidence_t *this, chunk_t *pcr_before,
|
||||
chunk_t *pcr_after);
|
||||
|
||||
/**
|
||||
* Sets PCR information if available
|
||||
*
|
||||
* @param pcr_before PCR value before extension
|
||||
* @param pcr_after PCR value after extension
|
||||
*/
|
||||
void (*set_pcr_info)(pts_comp_evidence_t *this, chunk_t pcr_before,
|
||||
chunk_t pcr_after);
|
||||
|
||||
/**
|
||||
* Gets Validation Result if available
|
||||
*
|
||||
* @param uri Verification Policy URI
|
||||
* @return validation Validation Result
|
||||
*/
|
||||
pts_comp_evid_validation_t (*get_validation)(pts_comp_evidence_t *this,
|
||||
char **uri);
|
||||
|
||||
/**
|
||||
* Sets Validation Result if available
|
||||
*
|
||||
* @param validation Validation Result
|
||||
* @param uri Verification Policy URI
|
||||
*/
|
||||
void (*set_validation)(pts_comp_evidence_t *this,
|
||||
pts_comp_evid_validation_t validation, char* uri);
|
||||
|
||||
/**
|
||||
* Destroys a pts_comp_evidence_t object.
|
||||
*/
|
||||
void (*destroy)(pts_comp_evidence_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a pts_comp_evidence_t object
|
||||
*
|
||||
* @param name Component Functional Name
|
||||
* @param depth Sub-component depth
|
||||
* @param extended_pcr PCR the measurement was extended into
|
||||
* @param algo Measurement hash algorithm
|
||||
* @param transform Transformation used for PCR extension
|
||||
* @param measurement_time Time the measurement was taken, 0 if unknown
|
||||
* @param measurement Measurement hash value
|
||||
*/
|
||||
pts_comp_evidence_t* pts_comp_evidence_create(pts_comp_func_name_t *name,
|
||||
u_int32_t depth,
|
||||
u_int32_t extended_pcr,
|
||||
pts_meas_algorithms_t algo,
|
||||
pts_pcr_transform_t transform,
|
||||
time_t measurement_time,
|
||||
chunk_t measurement);
|
||||
|
||||
/**
|
||||
* Determine transform to fit measurement hash into PCR register
|
||||
*
|
||||
* @param algo Measurement hash algorithm
|
||||
* @param pcr_len Length of the PCR registers in bytes
|
||||
* @return PCR transform type
|
||||
*/
|
||||
pts_pcr_transform_t pts_meas_algo_to_pcr_transform(pts_meas_algorithms_t algo,
|
||||
size_t pcr_len);
|
||||
|
||||
#endif /** PTS_COMP_EVIDENCE_H_ @}*/
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "imcv.h"
|
||||
#include "pts/components/pts_comp_func_name.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_pts_comp_func_name_t private_pts_comp_func_name_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_comp_func_name_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_comp_func_name_t {
|
||||
|
||||
/**
|
||||
* Public pts_comp_func_name_t interface.
|
||||
*/
|
||||
pts_comp_func_name_t public;
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name Vendor ID
|
||||
*/
|
||||
u_int32_t vid;
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name
|
||||
*/
|
||||
u_int32_t name;
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name Qualifier
|
||||
*/
|
||||
u_int8_t qualifier;
|
||||
|
||||
};
|
||||
|
||||
METHOD(pts_comp_func_name_t, get_vendor_id, u_int32_t,
|
||||
private_pts_comp_func_name_t *this)
|
||||
{
|
||||
return this->vid;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_func_name_t, get_name, u_int32_t,
|
||||
private_pts_comp_func_name_t *this)
|
||||
{
|
||||
return this->name;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_func_name_t, get_qualifier, u_int8_t,
|
||||
private_pts_comp_func_name_t *this)
|
||||
{
|
||||
return this->qualifier;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_func_name_t, set_qualifier, void,
|
||||
private_pts_comp_func_name_t *this, u_int8_t qualifier)
|
||||
{
|
||||
this->qualifier = qualifier;
|
||||
}
|
||||
|
||||
static bool equals(private_pts_comp_func_name_t *this,
|
||||
private_pts_comp_func_name_t *other)
|
||||
{
|
||||
if (this->vid != other->vid || this->name != other->name)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (this->qualifier == PTS_QUALIFIER_UNKNOWN ||
|
||||
other->qualifier == PTS_QUALIFIER_UNKNOWN)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
/* TODO handle qualifier wildcards */
|
||||
|
||||
return this->qualifier == other->qualifier;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_func_name_t, clone_, pts_comp_func_name_t*,
|
||||
private_pts_comp_func_name_t *this)
|
||||
{
|
||||
private_pts_comp_func_name_t *clone;
|
||||
|
||||
clone = malloc_thing(private_pts_comp_func_name_t);
|
||||
memcpy(clone, this, sizeof(private_pts_comp_func_name_t));
|
||||
|
||||
return &clone->public;
|
||||
}
|
||||
|
||||
METHOD(pts_comp_func_name_t, log_, void,
|
||||
private_pts_comp_func_name_t *this, char *label)
|
||||
{
|
||||
enum_name_t *names, *types;
|
||||
char flags[8];
|
||||
int type;
|
||||
|
||||
names = imcv_pts_components->get_comp_func_names(imcv_pts_components,
|
||||
this->vid);
|
||||
types = imcv_pts_components->get_qualifier_type_names(imcv_pts_components,
|
||||
this->vid);
|
||||
type = imcv_pts_components->get_qualifier(imcv_pts_components,
|
||||
&this->public, flags);
|
||||
|
||||
if (names && types)
|
||||
{
|
||||
DBG2(DBG_PTS, "%s%N functional component '%N' [%s] '%N'",
|
||||
label, pen_names, this->vid, names, this->name, flags, types, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG2(DBG_PTS, "%s0x%06x functional component 0x%08x 0x%02x",
|
||||
label, this->vid, this->name, this->qualifier);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(pts_comp_func_name_t, destroy, void,
|
||||
private_pts_comp_func_name_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_comp_func_name_t* pts_comp_func_name_create(u_int32_t vid, u_int32_t name,
|
||||
u_int8_t qualifier)
|
||||
{
|
||||
private_pts_comp_func_name_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_vendor_id = _get_vendor_id,
|
||||
.get_name = _get_name,
|
||||
.get_qualifier = _get_qualifier,
|
||||
.set_qualifier = _set_qualifier,
|
||||
.equals = (bool(*)(pts_comp_func_name_t*,pts_comp_func_name_t*))equals,
|
||||
.clone = _clone_,
|
||||
.log = _log_,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.vid = vid,
|
||||
.name = name,
|
||||
.qualifier = qualifier,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_comp_func_name pts_comp_func_name
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_FUNC_COMP_NAME_H_
|
||||
#define PTS_FUNC_COMP_NAME_H_
|
||||
|
||||
typedef struct pts_comp_func_name_t pts_comp_func_name_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
#define PTS_QUALIFIER_UNKNOWN 0x00
|
||||
#define PTS_QUALIFIER_WILDCARD 0x3F
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name object
|
||||
*/
|
||||
struct pts_comp_func_name_t {
|
||||
|
||||
/**
|
||||
* Get the PTS Component Functional Name Vendor ID
|
||||
*
|
||||
* @return PTS Component Functional Name Vendor ID
|
||||
*/
|
||||
u_int32_t (*get_vendor_id)(pts_comp_func_name_t *this);
|
||||
|
||||
/**
|
||||
* Get the PTS Component Functional Name
|
||||
*
|
||||
* @return PTS Component Functional Name
|
||||
*/
|
||||
u_int32_t (*get_name)(pts_comp_func_name_t *this);
|
||||
|
||||
/**
|
||||
* Get the PTS Component Functional Name Qualifier
|
||||
*
|
||||
* @return PTS Component Functional Name Qualifier
|
||||
*/
|
||||
u_int8_t (*get_qualifier)(pts_comp_func_name_t *this);
|
||||
|
||||
/**
|
||||
* Set the PTS Component Functional Name Qualifier
|
||||
*
|
||||
* @param qualifier PTS Component Functional Name Qualifier to be set
|
||||
*/
|
||||
void (*set_qualifier)(pts_comp_func_name_t *this, u_int8_t qualifier);
|
||||
|
||||
/**
|
||||
* Check to PTS Component Functional Names for equality
|
||||
*
|
||||
* @param other Other PTS Component Functional Name
|
||||
* @return TRUE if equal
|
||||
*/
|
||||
bool (*equals)(pts_comp_func_name_t *this, pts_comp_func_name_t *other);
|
||||
|
||||
/**
|
||||
* Clone a PTS Component Functional Name
|
||||
*
|
||||
* @return Cloned PTS Component Functional Name
|
||||
*/
|
||||
pts_comp_func_name_t* (*clone)(pts_comp_func_name_t *this);
|
||||
|
||||
/**
|
||||
* Write PTS Component Functional Name information to the standard logfile
|
||||
*
|
||||
* @param label Label added to log output
|
||||
*/
|
||||
void (*log)(pts_comp_func_name_t *this, char *label);
|
||||
|
||||
/**
|
||||
* Destroys a pts_component_t object.
|
||||
*/
|
||||
void (*destroy)(pts_comp_func_name_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a PTS Component Functional Name object
|
||||
*
|
||||
* @param vid PTS Component Functional Name Vendor ID
|
||||
* @param name PTS Component Functional Name
|
||||
* @param qualifier PTS Component Functional Name Qualifier
|
||||
*/
|
||||
pts_comp_func_name_t* pts_comp_func_name_create(u_int32_t vid, u_int32_t name,
|
||||
u_int8_t qualifier);
|
||||
|
||||
#endif /** PTS_FUNC_COMP_NAME_H_ @}*/
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_component pts_component
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_COMPONENT_H_
|
||||
#define PTS_COMPONENT_H_
|
||||
|
||||
typedef struct pts_component_t pts_component_t;
|
||||
|
||||
#include "pts/pts.h"
|
||||
#include "pts/pts_database.h"
|
||||
#include "pts/pts_file_meas.h"
|
||||
#include "pts/components/pts_comp_func_name.h"
|
||||
#include "pts/components/pts_comp_evidence.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <bio/bio_writer.h>
|
||||
|
||||
/**
|
||||
* PTS Functional Component Interface
|
||||
*/
|
||||
struct pts_component_t {
|
||||
|
||||
/**
|
||||
* Get the PTS Component Functional Name
|
||||
*
|
||||
* @return PTS Component Functional Name
|
||||
*/
|
||||
pts_comp_func_name_t* (*get_comp_func_name)(pts_component_t *this);
|
||||
|
||||
/**
|
||||
* Get the PTS Component Evidence Flags
|
||||
*
|
||||
* @return PTS Component Functional Name
|
||||
*/
|
||||
u_int8_t (*get_evidence_flags)(pts_component_t *this);
|
||||
|
||||
/**
|
||||
* Get the PTS Sub-component Depth
|
||||
*
|
||||
* @return PTS Sub-component Depth
|
||||
*/
|
||||
u_int32_t (*get_depth)(pts_component_t *this);
|
||||
|
||||
/**
|
||||
* Do evidence measurements on the PTS Functional Component
|
||||
*
|
||||
* @param qualifier PTS Component Functional Name Qualifier
|
||||
* @param pts PTS interface
|
||||
* @param evidence returns component evidence measureemt
|
||||
* @param measurements additional file measurements (NULL if not present)
|
||||
* @return status return code
|
||||
*/
|
||||
status_t (*measure)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
|
||||
pts_comp_evidence_t** evidence);
|
||||
|
||||
/**
|
||||
* Verify the evidence measurements of the PTS Functional Component
|
||||
*
|
||||
* @param qualifier PTS Component Functional Name Qualifier
|
||||
* @param pts PTS interface
|
||||
* @param evidence component evidence measurement to be verified
|
||||
* @return status return code
|
||||
*/
|
||||
status_t (*verify)(pts_component_t *this, u_int8_t qualifier, pts_t *pts,
|
||||
pts_comp_evidence_t *evidence);
|
||||
|
||||
/**
|
||||
* Tell the PTS Functional Component to finalize pending registrations
|
||||
* and check for missing measurements
|
||||
*
|
||||
* @param qualifier PTS Component Functional Name Qualifier
|
||||
* @param result writer appending concise measurement result
|
||||
* @return TRUE if finalization successful
|
||||
*/
|
||||
bool (*finalize)(pts_component_t *this, u_int8_t qualifier,
|
||||
bio_writer_t *result);
|
||||
|
||||
/**
|
||||
* Get a new reference to the PTS Functional Component
|
||||
*
|
||||
* @return this, with an increased refcount
|
||||
*/
|
||||
pts_component_t* (*get_ref)(pts_component_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a pts_component_t object.
|
||||
*/
|
||||
void (*destroy)(pts_component_t *this);
|
||||
|
||||
};
|
||||
|
||||
#endif /** PTS_COMPONENT_H_ @}*/
|
||||
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts/components/pts_component_manager.h"
|
||||
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_pts_component_manager_t private_pts_component_manager_t;
|
||||
typedef struct vendor_entry_t vendor_entry_t;
|
||||
typedef struct component_entry_t component_entry_t;
|
||||
|
||||
#define PTS_QUALIFIER_SIZE 6
|
||||
|
||||
/**
|
||||
* Vendor-specific namespace information and list of registered components
|
||||
*/
|
||||
struct vendor_entry_t {
|
||||
|
||||
/**
|
||||
* Vendor ID
|
||||
*/
|
||||
pen_t vendor_id;
|
||||
|
||||
/**
|
||||
* Vendor-specific Component Functional names
|
||||
*/
|
||||
enum_name_t *comp_func_names;
|
||||
|
||||
/**
|
||||
* Vendor-specific Qualifier Type names
|
||||
*/
|
||||
enum_name_t *qualifier_type_names;
|
||||
|
||||
/**
|
||||
* Vendor-specific Qualifier Flag names
|
||||
*/
|
||||
char *qualifier_flag_names;
|
||||
|
||||
/**
|
||||
* Vendor-specific size of Qualfiier Type field
|
||||
*/
|
||||
int qualifier_type_size;
|
||||
|
||||
/**
|
||||
* List of vendor-specific registered Functional Components
|
||||
*/
|
||||
linked_list_t *components;
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy a vendor_entry_t object
|
||||
*/
|
||||
static void vendor_entry_destroy(vendor_entry_t *entry)
|
||||
{
|
||||
entry->components->destroy_function(entry->components, free);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creation method for a vendor-specific Functional Component
|
||||
*/
|
||||
struct component_entry_t {
|
||||
|
||||
/**
|
||||
* Vendor-Specific Component Functional Name
|
||||
*/
|
||||
u_int32_t name;
|
||||
|
||||
/**
|
||||
* Functional Component creation method
|
||||
*/
|
||||
pts_component_create_t create;
|
||||
};
|
||||
|
||||
/**
|
||||
* Private data of a pts_component_manager_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_component_manager_t {
|
||||
|
||||
/**
|
||||
* Public pts_component_manager_t interface.
|
||||
*/
|
||||
pts_component_manager_t public;
|
||||
|
||||
/**
|
||||
* List of vendor-specific namespaces and registered components
|
||||
*/
|
||||
linked_list_t *list;
|
||||
};
|
||||
|
||||
METHOD(pts_component_manager_t, add_vendor, void,
|
||||
private_pts_component_manager_t *this, pen_t vendor_id,
|
||||
enum_name_t *comp_func_names, int qualifier_type_size,
|
||||
char *qualifier_flag_names, enum_name_t *qualifier_type_names)
|
||||
{
|
||||
vendor_entry_t *entry;
|
||||
|
||||
entry = malloc_thing(vendor_entry_t);
|
||||
entry->vendor_id = vendor_id;
|
||||
entry->comp_func_names = comp_func_names;
|
||||
entry->qualifier_type_size = qualifier_type_size;
|
||||
entry->qualifier_flag_names = qualifier_flag_names;
|
||||
entry->qualifier_type_names = qualifier_type_names;
|
||||
entry->components = linked_list_create();
|
||||
|
||||
this->list->insert_last(this->list, entry);
|
||||
DBG2(DBG_PTS, "added %N functional component namespace",
|
||||
pen_names, vendor_id);
|
||||
}
|
||||
|
||||
METHOD(pts_component_manager_t, get_comp_func_names, enum_name_t*,
|
||||
private_pts_component_manager_t *this, pen_t vendor_id)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
vendor_entry_t *entry;
|
||||
enum_name_t *names = NULL;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->vendor_id == vendor_id)
|
||||
{
|
||||
names = entry->comp_func_names;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
METHOD(pts_component_manager_t, get_qualifier_type_names, enum_name_t*,
|
||||
private_pts_component_manager_t *this, pen_t vendor_id)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
vendor_entry_t *entry;
|
||||
enum_name_t *names = NULL;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->vendor_id == vendor_id)
|
||||
{
|
||||
names = entry->qualifier_type_names;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
METHOD(pts_component_manager_t, add_component, void,
|
||||
private_pts_component_manager_t *this, pen_t vendor_id, u_int32_t name,
|
||||
pts_component_create_t create)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
vendor_entry_t *entry;
|
||||
component_entry_t *component;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->vendor_id == vendor_id)
|
||||
{
|
||||
component = malloc_thing(component_entry_t);
|
||||
component->name = name;
|
||||
component->create = create;
|
||||
|
||||
entry->components->insert_last(entry->components, component);
|
||||
DBG2(DBG_PTS, "added %N functional component '%N'",
|
||||
pen_names, vendor_id,
|
||||
get_comp_func_names(this, vendor_id), name);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
METHOD(pts_component_manager_t, remove_vendor, void,
|
||||
private_pts_component_manager_t *this, pen_t vendor_id)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
vendor_entry_t *entry;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->vendor_id == vendor_id)
|
||||
{
|
||||
this->list->remove_at(this->list, enumerator);
|
||||
vendor_entry_destroy(entry);
|
||||
DBG2(DBG_PTS, "removed %N functional component namespace",
|
||||
pen_names, vendor_id);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
METHOD(pts_component_manager_t, get_qualifier, u_int8_t,
|
||||
private_pts_component_manager_t *this, pts_comp_func_name_t *name,
|
||||
char *flags)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
vendor_entry_t *entry;
|
||||
u_int8_t qualifier, size, flag, type = 0;
|
||||
int i;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->vendor_id == name->get_vendor_id(name))
|
||||
{
|
||||
qualifier = name->get_qualifier(name);
|
||||
size = entry->qualifier_type_size;
|
||||
|
||||
/* mask qualifier type field */
|
||||
type = qualifier & ((1 << size) - 1);
|
||||
|
||||
/* determine flags */
|
||||
size = PTS_QUALIFIER_SIZE - size;
|
||||
flag = (1 << (PTS_QUALIFIER_SIZE - 1));
|
||||
if (flags)
|
||||
{
|
||||
for (i = 0 ; i < size; i++)
|
||||
{
|
||||
flags[i] = (qualifier & flag) ?
|
||||
entry->qualifier_flag_names[i] : '.';
|
||||
flag >>= 1;
|
||||
}
|
||||
flags[size] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
METHOD(pts_component_manager_t, create, pts_component_t*,
|
||||
private_pts_component_manager_t *this,
|
||||
pts_comp_func_name_t *name, u_int32_t depth, pts_database_t *pts_db)
|
||||
{
|
||||
enumerator_t *enumerator, *e2;
|
||||
vendor_entry_t *entry;
|
||||
component_entry_t *entry2;
|
||||
pts_component_t *component = NULL;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->vendor_id == name->get_vendor_id(name))
|
||||
{
|
||||
e2 = entry->components->create_enumerator(entry->components);
|
||||
while (e2->enumerate(e2, &entry2))
|
||||
{
|
||||
if (entry2->name == name->get_name(name) && entry2->create)
|
||||
{
|
||||
component = entry2->create(depth, pts_db);
|
||||
break;
|
||||
}
|
||||
}
|
||||
e2->destroy(e2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
METHOD(pts_component_manager_t, destroy, void,
|
||||
private_pts_component_manager_t *this)
|
||||
{
|
||||
this->list->destroy_function(this->list, (void *)vendor_entry_destroy);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_component_manager_t *pts_component_manager_create(void)
|
||||
{
|
||||
private_pts_component_manager_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.add_vendor = _add_vendor,
|
||||
.add_component = _add_component,
|
||||
.remove_vendor = _remove_vendor,
|
||||
.get_comp_func_names = _get_comp_func_names,
|
||||
.get_qualifier_type_names = _get_qualifier_type_names,
|
||||
.get_qualifier = _get_qualifier,
|
||||
.create = _create,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.list = linked_list_create(),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_component_manager pts_component_manager
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_COMPONENT_MANAGER_H_
|
||||
#define PTS_COMPONENT_MANAGER_H_
|
||||
|
||||
typedef struct pts_component_manager_t pts_component_manager_t;
|
||||
|
||||
#include "pts/pts_database.h"
|
||||
#include "pts/components/pts_component.h"
|
||||
#include "pts/components/pts_comp_func_name.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <pen/pen.h>
|
||||
|
||||
typedef pts_component_t* (*pts_component_create_t)(u_int32_t depth,
|
||||
pts_database_t *pts_db);
|
||||
|
||||
/**
|
||||
* Manages PTS Functional Components
|
||||
*/
|
||||
struct pts_component_manager_t {
|
||||
|
||||
/**
|
||||
* Add vendor-specific functional component names
|
||||
*
|
||||
* @param vendor_id Private Enterprise Number (PEN)
|
||||
* @param comp_func_names Vendor-specific Component Functional names
|
||||
* @param qualifier_type_size Vendor-specific Qualifier Type size
|
||||
* @param qualifier_flag_names Vendor-specific Qualifier Flag names
|
||||
* @param qualifier_type_names Vendor-specific Qualifier Type names
|
||||
*/
|
||||
void (*add_vendor)(pts_component_manager_t *this, pen_t vendor_id,
|
||||
enum_name_t *comp_func_names,
|
||||
int qualifier_type_size,
|
||||
char *qualifier_flag_names,
|
||||
enum_name_t *qualifier_type_names);
|
||||
|
||||
/**
|
||||
* Add vendor-specific functional component
|
||||
*
|
||||
* @param vendor_id Private Enterprise Number (PEN)
|
||||
* @param names Component Functional Name
|
||||
* @param create Functional Component creation method
|
||||
*/
|
||||
void (*add_component)(pts_component_manager_t *this, pen_t vendor_id,
|
||||
u_int32_t name, pts_component_create_t create);
|
||||
|
||||
/**
|
||||
* Remove vendor-specific components and associated namespace
|
||||
*
|
||||
* @param vendor_id Private Enterprise Number (PEN)
|
||||
*/
|
||||
void (*remove_vendor)(pts_component_manager_t *this, pen_t vendor_id);
|
||||
|
||||
/**
|
||||
* Return the Functional Component names for a given vendor ID
|
||||
*
|
||||
* @param vendor_id Private Enterprise Number (PEN)
|
||||
* @return Comp. Func. names if found, NULL else
|
||||
*/
|
||||
enum_name_t* (*get_comp_func_names)(pts_component_manager_t *this,
|
||||
pen_t vendor_id);
|
||||
|
||||
/**
|
||||
* Return the Functional Component Qualifier Type names for a given vendor ID
|
||||
*
|
||||
* @param vendor_id Private Enterprise Number (PEN)
|
||||
* @return Qualifier Type names if found, NULL else
|
||||
*/
|
||||
enum_name_t* (*get_qualifier_type_names)(pts_component_manager_t *this,
|
||||
pen_t vendor_id);
|
||||
|
||||
/**
|
||||
* Return the Qualifier Type and Flags
|
||||
*
|
||||
* @param name Component Functional Name
|
||||
* @param flags Qualifier Flags as a string in a char buffer
|
||||
* @return Qualifier Type
|
||||
*/
|
||||
u_int8_t (*get_qualifier)(pts_component_manager_t *this,
|
||||
pts_comp_func_name_t *name, char *flags);
|
||||
|
||||
/**
|
||||
* Create a PTS Component object from a Functional Component Name object
|
||||
*
|
||||
* @param name Component Functional Name
|
||||
* @param depth Sub-component Depth
|
||||
* @param pts_db PTS measurement database
|
||||
* @return Component object if supported, NULL else
|
||||
*/
|
||||
pts_component_t* (*create)(pts_component_manager_t *this,
|
||||
pts_comp_func_name_t *name, u_int32_t depth,
|
||||
pts_database_t *pts_db);
|
||||
|
||||
/**
|
||||
* Destroys a pts_component_manager_t object.
|
||||
*/
|
||||
void (*destroy)(pts_component_manager_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a PA-TNC attribute manager
|
||||
*/
|
||||
pts_component_manager_t* pts_component_manager_create(void);
|
||||
|
||||
#endif /** PTS_COMPONENT_MANAGER_H_ @}*/
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "tcg_comp_func_name.h"
|
||||
|
||||
char pts_tcg_qualifier_flag_names[] = { 'K', 'S' };
|
||||
|
||||
ENUM_BEGIN(pts_tcg_qualifier_type_names, PTS_TCG_QUALIFIER_TYPE_UNKNOWN,
|
||||
PTS_TCG_QUALIFIER_TYPE_TNC,
|
||||
"Unknown",
|
||||
"Trusted Platform",
|
||||
"Operating System",
|
||||
"Graphical User Interface",
|
||||
"Application",
|
||||
"Networking",
|
||||
"Library",
|
||||
"TNC Defined Component"
|
||||
);
|
||||
ENUM_NEXT(pts_tcg_qualifier_type_names, PTS_TCG_QUALIFIER_TYPE_ALL,
|
||||
PTS_TCG_QUALIFIER_TYPE_ALL,
|
||||
PTS_TCG_QUALIFIER_TYPE_TNC,
|
||||
"All Matching Components"
|
||||
);
|
||||
ENUM_END(pts_tcg_qualifier_type_names, PTS_TCG_QUALIFIER_TYPE_ALL);
|
||||
|
||||
ENUM(pts_tcg_comp_func_names, PTS_TCG_COMP_FUNC_NAME_IGNORE,
|
||||
PTS_TCG_COMP_FUNC_NAME_OPT_ROMS,
|
||||
"Ignore",
|
||||
"CRTM",
|
||||
"BIOS",
|
||||
"Platform Extensions",
|
||||
"Motherboard Firmware",
|
||||
"Initial Program Loader",
|
||||
"Option ROMs"
|
||||
);
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_tcg_comp_func_name pts_tcg_comp_func_name
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_TCG_COMP_FUNC_NAME_H_
|
||||
#define PTS_TCG_COMP_FUNC_NAME_H_
|
||||
|
||||
typedef enum pts_tcg_qualifier_type_t pts_tcg_qualifier_type_t;
|
||||
typedef enum pts_tcg_comp_func_name_t pts_tcp_comp_func_name_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name Qualifier Flags for the TCG namespace
|
||||
* see section 5.2 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*
|
||||
* 0 1 2 3 4 5
|
||||
* +-+-+-+-+-+-+
|
||||
* |K|S| Type |
|
||||
* +-+-+-+-+-+-+
|
||||
*/
|
||||
#define PTS_TCG_QUALIFIER_FLAG_KERNEL (1<<5)
|
||||
#define PTS_TCG_QUALIFIER_FLAG_SUB (1<<4)
|
||||
|
||||
extern char pts_tcg_qualifier_flag_names[];
|
||||
|
||||
/**
|
||||
* Size of the PTS Component Functional Name Qualifier Type field
|
||||
*/
|
||||
#define PTS_TCG_QUALIFIER_TYPE_SIZE 4
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name Qualifier Types for the TCG namespace
|
||||
* see section 5.2 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*/
|
||||
enum pts_tcg_qualifier_type_t {
|
||||
/** Unknown */
|
||||
PTS_TCG_QUALIFIER_TYPE_UNKNOWN = 0x0,
|
||||
/** Trusted Platform */
|
||||
PTS_TCG_QUALIFIER_TYPE_TRUSTED = 0x1,
|
||||
/** Operating System */
|
||||
PTS_TCG_QUALIFIER_TYPE_OS = 0x2,
|
||||
/** Graphical User Interface */
|
||||
PTS_TCG_QUALIFIER_TYPE_GUI = 0x3,
|
||||
/** Application */
|
||||
PTS_TCG_QUALIFIER_TYPE_APP = 0x4,
|
||||
/** Networking */
|
||||
PTS_TCG_QUALIFIER_TYPE_NET = 0x5,
|
||||
/** Library */
|
||||
PTS_TCG_QUALIFIER_TYPE_LIB = 0x6,
|
||||
/** TNC Defined Component */
|
||||
PTS_TCG_QUALIFIER_TYPE_TNC = 0x7,
|
||||
/** All matching Components */
|
||||
PTS_TCG_QUALIFIER_TYPE_ALL = 0xF,
|
||||
};
|
||||
|
||||
extern enum_name_t *pts_tcg_qualifier_type_names;
|
||||
|
||||
/**
|
||||
* PTS Component Functional Name Binary Enumeration for the TCG namespace
|
||||
* see section 5.3 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*/
|
||||
enum pts_tcg_comp_func_name_t {
|
||||
/** Ignore */
|
||||
PTS_TCG_COMP_FUNC_NAME_IGNORE = 0x0000,
|
||||
/** CRTM */
|
||||
PTS_TCG_COMP_FUNC_NAME_CRTM = 0x0001,
|
||||
/** BIOS */
|
||||
PTS_TCG_COMP_FUNC_NAME_BIOS = 0x0002,
|
||||
/** Platform Extensions */
|
||||
PTS_TCG_COMP_FUNC_NAME_PLATFORM_EXT = 0x0003,
|
||||
/** Motherboard Firmware */
|
||||
PTS_TCG_COMP_FUNC_NAME_BOARD = 0x0004,
|
||||
/** Initial Program Loader */
|
||||
PTS_TCG_COMP_FUNC_NAME_INIT_LOADER = 0x0005,
|
||||
/** Option ROMs */
|
||||
PTS_TCG_COMP_FUNC_NAME_OPT_ROMS = 0x0006,
|
||||
};
|
||||
|
||||
extern enum_name_t *pts_tcg_comp_func_names;
|
||||
|
||||
#endif /** PTS_TCG_COMP_FUNC_NAME_H_ @}*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Sansar Choinyambuu
|
||||
* Copyright (C) 2012-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts pts
|
||||
* @{ @ingroup libpts
|
||||
*/
|
||||
|
||||
#ifndef PTS_H_
|
||||
#define PTS_H_
|
||||
|
||||
typedef struct pts_t pts_t;
|
||||
|
||||
#include "pts_error.h"
|
||||
#include "pts_proto_caps.h"
|
||||
#include "pts_meas_algo.h"
|
||||
#include "pts_file_meas.h"
|
||||
#include "pts_file_meta.h"
|
||||
#include "pts_dh_group.h"
|
||||
#include "pts_pcr.h"
|
||||
#include "pts_req_func_comp_evid.h"
|
||||
#include "pts_simple_evid_final.h"
|
||||
#include "components/pts_comp_func_name.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <collections/linked_list.h>
|
||||
|
||||
/**
|
||||
* UTF-8 encoding of the character used to delimiter the filename
|
||||
*/
|
||||
#define SOLIDUS_UTF 0x2F
|
||||
#define REVERSE_SOLIDUS_UTF 0x5C
|
||||
|
||||
/**
|
||||
* PCR indices used for measurements of various functional components
|
||||
*/
|
||||
#define PCR_BIOS 0
|
||||
#define PCR_PLATFORM_EXT 1
|
||||
#define PCR_MOTHERBOARD 1
|
||||
#define PCR_OPTION_ROMS 2
|
||||
#define PCR_IPL 4
|
||||
|
||||
#define PCR_TBOOT_POLICY 17
|
||||
#define PCR_TBOOT_MLE 18
|
||||
|
||||
#define PCR_TGRUB_MBR_STAGE1 4
|
||||
#define PCR_TGRUB_STAGE2_PART1 8
|
||||
#define PCR_TGRUB_STAGE2_PART2 9
|
||||
#define PCR_TGRUB_CMD_LINE_ARGS 12
|
||||
#define PCR_TGRUB_CHECKFILE 13
|
||||
#define PCR_TGRUB_LOADED_FILES 14
|
||||
|
||||
#define PCR_DEBUG 16
|
||||
|
||||
/**
|
||||
* Length of the generated nonce used for calculation of shared secret
|
||||
*/
|
||||
#define ASSESSMENT_SECRET_LEN 20
|
||||
|
||||
/**
|
||||
* Length of the TPM_QUOTE_INFO structure, TPM Spec 1.2
|
||||
*/
|
||||
#define TPM_QUOTE_INFO_LEN 48
|
||||
|
||||
/**
|
||||
* Hashing algorithm used by tboot and trustedGRUB
|
||||
*/
|
||||
#define TRUSTED_HASH_ALGO PTS_MEAS_ALGO_SHA1
|
||||
|
||||
/**
|
||||
* Class implementing the TCG Platform Trust Service (PTS)
|
||||
*
|
||||
*/
|
||||
struct pts_t {
|
||||
|
||||
/**
|
||||
* Get PTS Protocol Capabilities
|
||||
*
|
||||
* @return Protocol capabilities flags
|
||||
*/
|
||||
pts_proto_caps_flag_t (*get_proto_caps)(pts_t *this);
|
||||
|
||||
/**
|
||||
* Set PTS Protocol Capabilities
|
||||
*
|
||||
* @param flags Protocol capabilities flags
|
||||
*/
|
||||
void (*set_proto_caps)(pts_t *this, pts_proto_caps_flag_t flags);
|
||||
|
||||
/**
|
||||
* Get PTS Measurement Algorithm
|
||||
*
|
||||
* @return PTS measurement algorithm
|
||||
*/
|
||||
pts_meas_algorithms_t (*get_meas_algorithm)(pts_t *this);
|
||||
|
||||
/**
|
||||
* Set PTS Measurement Algorithm
|
||||
*
|
||||
* @param algorithm PTS measurement algorithm
|
||||
*/
|
||||
void (*set_meas_algorithm)(pts_t *this, pts_meas_algorithms_t algorithm);
|
||||
|
||||
/**
|
||||
* Get DH Hash Algorithm
|
||||
*
|
||||
* @return DH hash algorithm
|
||||
*/
|
||||
pts_meas_algorithms_t (*get_dh_hash_algorithm)(pts_t *this);
|
||||
|
||||
/**
|
||||
* Set DH Hash Algorithm
|
||||
*
|
||||
* @param algorithm DH hash algorithm
|
||||
*/
|
||||
void (*set_dh_hash_algorithm)(pts_t *this, pts_meas_algorithms_t algorithm);
|
||||
|
||||
/**
|
||||
* Create PTS Diffie-Hellman object and nonce
|
||||
*
|
||||
* @param group PTS DH group
|
||||
* @param nonce_len Nonce length
|
||||
* @return TRUE if creation was successful
|
||||
*
|
||||
*/
|
||||
bool (*create_dh_nonce)(pts_t *this, pts_dh_group_t group, int nonce_len);
|
||||
|
||||
/**
|
||||
* Get my Diffie-Hellman public value
|
||||
*
|
||||
* @param value My public DH value
|
||||
* @param nonce My DH nonce
|
||||
*/
|
||||
void (*get_my_public_value)(pts_t *this, chunk_t *value, chunk_t *nonce);
|
||||
|
||||
/**
|
||||
* Set peer Diffie.Hellman public value
|
||||
*
|
||||
* @param value Peer public DH value
|
||||
* @param nonce Peer DH nonce
|
||||
*/
|
||||
void (*set_peer_public_value) (pts_t *this, chunk_t value, chunk_t nonce);
|
||||
|
||||
/**
|
||||
* Calculates assessment secret to be used for TPM Quote as ExternalData
|
||||
*
|
||||
* @return TRUE unless both DH public values
|
||||
* and nonces are set
|
||||
*/
|
||||
bool (*calculate_secret) (pts_t *this);
|
||||
|
||||
/**
|
||||
* Get primary key of platform entry in database
|
||||
*
|
||||
* @return Platform and OS info
|
||||
*/
|
||||
int (*get_platform_id)(pts_t *this);
|
||||
|
||||
/**
|
||||
* Set primary key of platform entry in database
|
||||
*
|
||||
* @param pid Primary key of platform entry in database
|
||||
*/
|
||||
void (*set_platform_id)(pts_t *this, int pid);
|
||||
|
||||
/**
|
||||
* Get TPM 1.2 Version Info
|
||||
*
|
||||
* @param info chunk containing a TPM_CAP_VERSION_INFO struct
|
||||
* @return TRUE if TPM Version Info available
|
||||
*/
|
||||
bool (*get_tpm_version_info)(pts_t *this, chunk_t *info);
|
||||
|
||||
/**
|
||||
* Set TPM 1.2 Version Info
|
||||
*
|
||||
* @param info chunk containing a TPM_CAP_VERSION_INFO struct
|
||||
*/
|
||||
void (*set_tpm_version_info)(pts_t *this, chunk_t info);
|
||||
|
||||
/**
|
||||
* Get Attestation Identity Certificate or Public Key
|
||||
*
|
||||
* @return AIK Certificate or Public Key
|
||||
*/
|
||||
certificate_t* (*get_aik)(pts_t *this);
|
||||
|
||||
/**
|
||||
* Set Attestation Identity Certificate or Public Key
|
||||
*
|
||||
* @param aik AIK Certificate or Public Key
|
||||
* @param aik_id Primary key referencing AIK in database
|
||||
*/
|
||||
void (*set_aik)(pts_t *this, certificate_t *aik, int aik_id);
|
||||
|
||||
/**
|
||||
* Get primary key referencing AIK in database
|
||||
*
|
||||
* @return Primary key referencing AIK in database
|
||||
*/
|
||||
int (*get_aik_id)(pts_t *this);
|
||||
|
||||
/**
|
||||
* Check whether path is valid file/directory on filesystem
|
||||
*
|
||||
* @param path Absolute path
|
||||
* @param error_code Output variable for PTS error code
|
||||
* @return TRUE if path is valid or file/directory
|
||||
* doesn't exist or path is invalid
|
||||
* FALSE if local error occurred within stat function
|
||||
*/
|
||||
bool (*is_path_valid)(pts_t *this, char *path, pts_error_code_t *error_code);
|
||||
|
||||
/**
|
||||
* Obtain file metadata
|
||||
*
|
||||
* @param pathname Absolute pathname of file/directory
|
||||
* @param is_dir TRUE if directory contents are requested
|
||||
* @return PTS File Metadata or NULL if FAILED
|
||||
*/
|
||||
pts_file_meta_t* (*get_metadata)(pts_t *this, char *pathname, bool is_dir);
|
||||
|
||||
/**
|
||||
* Reads given PCR value and returns it
|
||||
* Expects owner secret to be WELL_KNOWN_SECRET
|
||||
*
|
||||
* @param pcr_num Number of PCR to read
|
||||
* @param pcr_value Chunk to save pcr read output
|
||||
* @return NULL in case of TSS error, PCR value otherwise
|
||||
*/
|
||||
bool (*read_pcr)(pts_t *this, u_int32_t pcr_num, chunk_t *pcr_value);
|
||||
|
||||
/**
|
||||
* Extends given PCR with given value
|
||||
* Expects owner secret to be WELL_KNOWN_SECRET
|
||||
*
|
||||
* @param pcr_num Number of PCR to extend
|
||||
* @param input Value to extend
|
||||
* @param output Chunk to save PCR value after extension
|
||||
* @return FALSE in case of TSS error, TRUE otherwise
|
||||
*/
|
||||
bool (*extend_pcr)(pts_t *this, u_int32_t pcr_num, chunk_t input,
|
||||
chunk_t *output);
|
||||
|
||||
/**
|
||||
* Quote over PCR's
|
||||
* Expects owner and SRK secret to be WELL_KNOWN_SECRET and no password set for AIK
|
||||
*
|
||||
* @param use_quote2 Version of the Quote function to be used
|
||||
* @param pcr_comp Chunk to save PCR composite structure
|
||||
* @param quote_sig Chunk to save quote operation output
|
||||
* without external data (anti-replay protection)
|
||||
* @return FALSE in case of TSS error, TRUE otherwise
|
||||
*/
|
||||
bool (*quote_tpm)(pts_t *this, bool use_quote2, chunk_t *pcr_comp,
|
||||
chunk_t *quote_sig);
|
||||
|
||||
/**
|
||||
* Get the shadow PCR set
|
||||
*
|
||||
* @return shadow PCR set
|
||||
*/
|
||||
pts_pcr_t* (*get_pcrs)(pts_t *this);
|
||||
|
||||
/**
|
||||
* Constructs and returns TPM Quote Info structure expected from IMC
|
||||
*
|
||||
* @param use_quote2 Version of the TPM_QUOTE_INFO to be constructed
|
||||
* @param use_ver_info Version info is concatenated to TPM_QUOTE_INFO2
|
||||
* @param comp_hash_algo Composite Hash Algorithm
|
||||
* @param pcr_comp Output variable to store PCR Composite
|
||||
* @param quote_info Output variable to store TPM Quote Info
|
||||
* @return FALSE in case of any error, TRUE otherwise
|
||||
*/
|
||||
bool (*get_quote_info)(pts_t *this, bool use_quote2, bool ver_info_included,
|
||||
pts_meas_algorithms_t comp_hash_algo,
|
||||
chunk_t *pcr_comp, chunk_t *quote_info);
|
||||
|
||||
/**
|
||||
* Constructs and returns PCR Quote Digest structure expected from IMC
|
||||
*
|
||||
* @param data Calculated TPM Quote Digest
|
||||
* @param signature TPM Quote Signature received from IMC
|
||||
* @return FALSE if signature is not verified
|
||||
*/
|
||||
bool (*verify_quote_signature)(pts_t *this, chunk_t data, chunk_t signature);
|
||||
|
||||
/**
|
||||
* Destroys a pts_t object.
|
||||
*/
|
||||
void (*destroy)(pts_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an pts_t object
|
||||
*
|
||||
* @param is_imc TRUE if running on an IMC
|
||||
*/
|
||||
pts_t* pts_create(bool is_imc);
|
||||
|
||||
#endif /** PTS_H_ @}*/
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_creds.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <credentials/certificates/x509.h>
|
||||
#include <credentials/sets/mem_cred.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
typedef struct private_pts_creds_t private_pts_creds_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_creds_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_creds_t {
|
||||
|
||||
/**
|
||||
* Public pts_creds_t interface.
|
||||
*/
|
||||
pts_creds_t public;
|
||||
|
||||
/**
|
||||
* Credential set
|
||||
*/
|
||||
mem_cred_t *creds;
|
||||
|
||||
};
|
||||
|
||||
METHOD(pts_creds_t, get_set, credential_set_t*,
|
||||
private_pts_creds_t *this)
|
||||
{
|
||||
return &this->creds->set;
|
||||
}
|
||||
|
||||
|
||||
METHOD(pts_creds_t, destroy, void,
|
||||
private_pts_creds_t *this)
|
||||
{
|
||||
this->creds->destroy(this->creds);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load trusted PTS CA certificates from a directory
|
||||
*/
|
||||
static void load_cacerts(private_pts_creds_t *this, char *path)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
struct stat st;
|
||||
char *file;
|
||||
|
||||
DBG1(DBG_PTS, "loading PTS ca certificates from '%s'", path);
|
||||
|
||||
enumerator = enumerator_create_directory(path);
|
||||
if (!enumerator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (enumerator->enumerate(enumerator, NULL, &file, &st))
|
||||
{
|
||||
certificate_t *cert;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
{
|
||||
/* skip special file */
|
||||
continue;
|
||||
}
|
||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_FROM_FILE, file, BUILD_END);
|
||||
if (cert)
|
||||
{
|
||||
x509_t *x509 = (x509_t*)cert;
|
||||
|
||||
if (!(x509->get_flags(x509) & X509_CA))
|
||||
{
|
||||
DBG1(DBG_PTS, " ca certificate \"%Y\" lacks ca basic constraint"
|
||||
", discarded", cert->get_subject(cert));
|
||||
cert->destroy(cert);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_PTS, " loaded ca certificate \"%Y\" from '%s'",
|
||||
cert->get_subject(cert), file);
|
||||
this->creds->add_cert(this->creds, TRUE, cert);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_PTS, " loading ca certificate from '%s' failed", file);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_creds_t *pts_creds_create(char *path)
|
||||
{
|
||||
private_pts_creds_t *this;
|
||||
|
||||
if (!path)
|
||||
{
|
||||
DBG1(DBG_PTS, "no PTS cacerts directory defined");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_set = _get_set,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.creds = mem_cred_create(),
|
||||
);
|
||||
|
||||
load_cacerts(this, path);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_creds pts_creds
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_CREDS_H_
|
||||
#define PTS_CREDS_H_
|
||||
|
||||
typedef struct pts_creds_t pts_creds_t;
|
||||
|
||||
#include <library.h>
|
||||
#include <credentials/credential_set.h>
|
||||
|
||||
/**
|
||||
* Class implementing a PTS credentials set
|
||||
*/
|
||||
struct pts_creds_t {
|
||||
|
||||
/**
|
||||
* Get the credential set
|
||||
*
|
||||
* @return credential set
|
||||
*/
|
||||
credential_set_t* (*get_set)(pts_creds_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a pts_creds_t object.
|
||||
*/
|
||||
void (*destroy)(pts_creds_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an pts_creds_t object
|
||||
*
|
||||
* @param path path to the PTS cacerts directory
|
||||
*/
|
||||
pts_creds_t* pts_creds_create(char *path);
|
||||
|
||||
#endif /** PTS_CREDS_H_ @}*/
|
||||
@@ -0,0 +1,432 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2012-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "pts_database.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
|
||||
typedef struct private_pts_database_t private_pts_database_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_database_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_database_t {
|
||||
|
||||
/**
|
||||
* Public pts_database_t interface.
|
||||
*/
|
||||
pts_database_t public;
|
||||
|
||||
/**
|
||||
* database instance
|
||||
*/
|
||||
database_t *db;
|
||||
|
||||
};
|
||||
|
||||
METHOD(pts_database_t, get_pathname, char*,
|
||||
private_pts_database_t *this, bool is_dir, int id)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *path, *name, *sep, *pathname = NULL;
|
||||
|
||||
if (is_dir)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT path FROM directories WHERE id = ?",
|
||||
DB_INT, id, DB_TEXT);
|
||||
if (!e || !e->enumerate(e, &path))
|
||||
{
|
||||
pathname = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pathname = strdup(path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT d.path, f.name FROM files AS f "
|
||||
"JOIN directories AS d ON d.id = f.dir WHERE f.id = ?",
|
||||
DB_INT, id, DB_TEXT, DB_TEXT);
|
||||
if (e && e->enumerate(e, &path, &name))
|
||||
{
|
||||
if (path[0] == '/')
|
||||
{ /* Unix style absolute path */
|
||||
sep = "/";
|
||||
}
|
||||
else
|
||||
{ /* Windows absolute path */
|
||||
sep = "\\";
|
||||
}
|
||||
if (asprintf(&pathname, "%s%s%s",
|
||||
path, streq(path, "/") ? "" : sep, name) == -1)
|
||||
{
|
||||
pathname = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
DESTROY_IF(e);
|
||||
|
||||
return pathname;
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
|
||||
private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
|
||||
bool is_dir, int id)
|
||||
{
|
||||
enumerator_t *e;
|
||||
|
||||
if (is_dir)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"JOIN directories as d ON d.id = f.dir "
|
||||
"WHERE fh.product = ? AND fh.algo = ? AND d.id = ? "
|
||||
"ORDER BY f.name",
|
||||
DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"WHERE fh.product = ? AND fh.algo = ? AND fh.file = ?",
|
||||
DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, add_file_measurement, status_t,
|
||||
private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
|
||||
chunk_t measurement, char *filename, bool is_dir, int id)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *name;
|
||||
chunk_t hash_value;
|
||||
int hash_id, fid;
|
||||
status_t status = SUCCESS;
|
||||
|
||||
if (is_dir)
|
||||
{
|
||||
/* does filename entry already exist? */
|
||||
e = this->db->query(this->db,
|
||||
"SELECT id FROM files WHERE name = ? AND dir = ?",
|
||||
DB_TEXT, filename, DB_INT, id, DB_INT);
|
||||
if (!e)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
if (!e->enumerate(e, &fid))
|
||||
{
|
||||
/* create filename entry */
|
||||
if (this->db->execute(this->db, &fid,
|
||||
"INSERT INTO files (name, dir) VALUES (?, ?)",
|
||||
DB_TEXT, filename, DB_INT, id) != 1)
|
||||
{
|
||||
DBG1(DBG_PTS, "could not insert filename into database");
|
||||
status = FAILED;
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
fid = id;
|
||||
|
||||
/* verify filename */
|
||||
e = this->db->query(this->db,
|
||||
"SELECT name FROM files WHERE id = ?", DB_INT, fid, DB_TEXT);
|
||||
if (!e)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
if (!e->enumerate(e, &name) || !streq(name, filename))
|
||||
{
|
||||
DBG1(DBG_PTS, "filename of reference measurement does not match");
|
||||
status = FAILED;
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/* does hash measurement value already exist? */
|
||||
e = this->db->query(this->db,
|
||||
"SELECT fh.id, fh.hash FROM file_hashes AS fh "
|
||||
"WHERE fh.product = ? AND fh.algo = ? AND fh.file = ?",
|
||||
DB_INT, pid, DB_INT, algo, DB_INT, fid, DB_INT, DB_BLOB);
|
||||
if (!e)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
if (e->enumerate(e, &hash_id, &hash_value))
|
||||
{
|
||||
if (!chunk_equals(measurement, hash_value))
|
||||
{
|
||||
/* update hash measurement value */
|
||||
if (this->db->execute(this->db, &hash_id,
|
||||
"UPDATE file_hashes SET hash = ? WHERE id = ?",
|
||||
DB_BLOB, measurement, DB_INT, hash_id) != 1)
|
||||
{
|
||||
status = FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* insert hash measurement value */
|
||||
if (this->db->execute(this->db, &hash_id,
|
||||
"INSERT INTO file_hashes (file, product, algo, hash) "
|
||||
"VALUES (?, ?, ?, ?)", DB_INT, fid, DB_INT, pid,
|
||||
DB_INT, algo, DB_BLOB, measurement) != 1)
|
||||
{
|
||||
status = FAILED;
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, create_file_meas_enumerator, enumerator_t*,
|
||||
private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
|
||||
char *filename)
|
||||
{
|
||||
enumerator_t *e;
|
||||
char *dir, *file;
|
||||
|
||||
if (strlen(filename) < 1)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* separate filename into directory and basename components */
|
||||
dir = path_dirname(filename);
|
||||
file = path_basename(filename);
|
||||
|
||||
if (*dir == '.')
|
||||
{ /* relative pathname */
|
||||
e = this->db->query(this->db,
|
||||
"SELECT fh.hash FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"WHERE fh.product = ? AND f.name = ? AND fh.algo = ?",
|
||||
DB_INT, pid, DB_TEXT, file, DB_INT, algo, DB_BLOB);
|
||||
}
|
||||
else
|
||||
{ /* absolute pathname */
|
||||
int did;
|
||||
|
||||
/* find directory entry first */
|
||||
e = this->db->query(this->db,
|
||||
"SELECT id FROM directories WHERE path = ?",
|
||||
DB_TEXT, dir, DB_INT);
|
||||
|
||||
if (!e || !e->enumerate(e, &did))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
e = this->db->query(this->db,
|
||||
"SELECT fh.hash FROM file_hashes AS fh "
|
||||
"JOIN files AS f ON f.id = fh.file "
|
||||
"WHERE fh.product = ? AND f.dir = ? AND f.name = ? AND fh.algo = ?",
|
||||
DB_INT, pid, DB_INT, did, DB_TEXT, file, DB_INT, algo, DB_BLOB);
|
||||
}
|
||||
|
||||
err:
|
||||
free(file);
|
||||
free(dir);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, check_comp_measurement, status_t,
|
||||
private_pts_database_t *this, chunk_t measurement, int cid, int aik_id,
|
||||
int seq_no, int pcr, pts_meas_algorithms_t algo)
|
||||
{
|
||||
enumerator_t *e;
|
||||
chunk_t hash;
|
||||
status_t status = NOT_FOUND;
|
||||
|
||||
e = this->db->query(this->db,
|
||||
"SELECT hash FROM component_hashes "
|
||||
"WHERE component = ? AND key = ? "
|
||||
"AND seq_no = ? AND pcr = ? AND algo = ? ",
|
||||
DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no,
|
||||
DB_INT, pcr, DB_INT, algo, DB_BLOB);
|
||||
if (!e)
|
||||
{
|
||||
DBG1(DBG_PTS, "no database query enumerator returned");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
while (e->enumerate(e, &hash))
|
||||
{
|
||||
if (chunk_equals(hash, measurement))
|
||||
{
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_PTS, "PCR %2d no matching component measurement #%d "
|
||||
"found in database", pcr, seq_no);
|
||||
DBG1(DBG_PTS, " expected: %#B", &hash);
|
||||
DBG1(DBG_PTS, " received: %#B", &measurement);
|
||||
status = VERIFY_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
if (status == NOT_FOUND)
|
||||
{
|
||||
DBG1(DBG_PTS, "PCR %2d no measurement #%d "
|
||||
"found in database", pcr, seq_no);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, insert_comp_measurement, status_t,
|
||||
private_pts_database_t *this, chunk_t measurement, int cid, int aik_id,
|
||||
int seq_no, int pcr, pts_meas_algorithms_t algo)
|
||||
{
|
||||
int id;
|
||||
|
||||
if (this->db->execute(this->db, &id,
|
||||
"INSERT INTO component_hashes "
|
||||
"(component, key, seq_no, pcr, algo, hash) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?)",
|
||||
DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no, DB_INT, pcr,
|
||||
DB_INT, algo, DB_BLOB, measurement) == 1)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
DBG1(DBG_PTS, "could not insert component measurement into database");
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, delete_comp_measurements, int,
|
||||
private_pts_database_t *this, int cid, int aik_id)
|
||||
{
|
||||
return this->db->execute(this->db, NULL,
|
||||
"DELETE FROM component_hashes "
|
||||
"WHERE component = ? AND key = ?",
|
||||
DB_INT, cid, DB_INT, aik_id);
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, get_comp_measurement_count, status_t,
|
||||
private_pts_database_t *this, pts_comp_func_name_t *comp_name,
|
||||
int aik_id, pts_meas_algorithms_t algo, int *cid, int *count)
|
||||
{
|
||||
enumerator_t *e;
|
||||
status_t status = SUCCESS;
|
||||
|
||||
/* Initialize count */
|
||||
*count = 0;
|
||||
|
||||
/* Get the primary key of the Component Functional Name */
|
||||
e = this->db->query(this->db,
|
||||
"SELECT id FROM components "
|
||||
" WHERE vendor_id = ? AND name = ? AND qualifier = ?",
|
||||
DB_INT, comp_name->get_vendor_id(comp_name),
|
||||
DB_INT, comp_name->get_name(comp_name),
|
||||
DB_INT, comp_name->get_qualifier(comp_name),
|
||||
DB_INT);
|
||||
if (!e)
|
||||
{
|
||||
DBG1(DBG_PTS, "no database query enumerator returned");
|
||||
return FAILED;
|
||||
}
|
||||
if (!e->enumerate(e, cid))
|
||||
{
|
||||
DBG1(DBG_PTS, "component functional name not found in database");
|
||||
e->destroy(e);
|
||||
return FAILED;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
/* Get the number of stored measurements for a given AIK and component */
|
||||
e = this->db->query(this->db,
|
||||
"SELECT COUNT(*) FROM component_hashes AS ch "
|
||||
"WHERE component = ? AND key = ? AND algo = ?",
|
||||
DB_INT, *cid, DB_INT, aik_id, DB_INT, algo, DB_INT);
|
||||
if (!e)
|
||||
{
|
||||
DBG1(DBG_PTS, "no database query enumerator returned");
|
||||
return FAILED;
|
||||
}
|
||||
if (!e->enumerate(e, count))
|
||||
{
|
||||
DBG1(DBG_PTS, "no component measurement count returned from database");
|
||||
status = FAILED;
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(pts_database_t, destroy, void,
|
||||
private_pts_database_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_database_t *pts_database_create(imv_database_t *imv_db)
|
||||
{
|
||||
private_pts_database_t *this;
|
||||
|
||||
if (!imv_db)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_pathname = _get_pathname,
|
||||
.create_file_hash_enumerator = _create_file_hash_enumerator,
|
||||
.add_file_measurement = _add_file_measurement,
|
||||
.create_file_meas_enumerator = _create_file_meas_enumerator,
|
||||
.check_comp_measurement = _check_comp_measurement,
|
||||
.insert_comp_measurement = _insert_comp_measurement,
|
||||
.delete_comp_measurements = _delete_comp_measurements,
|
||||
.get_comp_measurement_count = _get_comp_measurement_count,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.db = imv_db->get_database(imv_db),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_database pts_database
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_DATABASE_H_
|
||||
#define PTS_DATABASE_H_
|
||||
|
||||
typedef struct pts_database_t pts_database_t;
|
||||
|
||||
#include "pts_meas_algo.h"
|
||||
#include "components/pts_comp_func_name.h"
|
||||
|
||||
#include <imv/imv_database.h>
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* Class implementing the PTS File Measurement database
|
||||
*
|
||||
*/
|
||||
struct pts_database_t {
|
||||
|
||||
/**
|
||||
* Get absolute pathname for file or directory measurement
|
||||
*
|
||||
* @param is_dir TRUE if dir, FALSE if file
|
||||
* @param id Primary key into directories or files table
|
||||
* @return Absolute pathname as a text string
|
||||
*/
|
||||
char* (*get_pathname)(pts_database_t *this, bool is_dir, int id);
|
||||
|
||||
/**
|
||||
* Get stored measurement hash for single file or directory entries
|
||||
*
|
||||
* @param pid Primary key of software product in database
|
||||
* @param algo Hash algorithm used for measurement
|
||||
* @param is_dir TRUE if directory was measured
|
||||
* @param id Primary key of measured file/directory
|
||||
* @return Enumerator over all matching measurement hashes
|
||||
*/
|
||||
enumerator_t* (*create_file_hash_enumerator)(pts_database_t *this,
|
||||
int pid, pts_meas_algorithms_t algo,
|
||||
bool is_dir, int id);
|
||||
|
||||
/**
|
||||
* Add PTS file measurement reference value
|
||||
*
|
||||
* @param pid Primary key of software product in database
|
||||
* @param algo File measurement hash algorithm used
|
||||
* @param measurement File measurement hash
|
||||
* @param filename Optional name of the file to be checked
|
||||
* @param is_dir TRUE if part of directory measurement
|
||||
* @param id Primary key into direcories/files table
|
||||
* @return Status
|
||||
*/
|
||||
status_t (*add_file_measurement)(pts_database_t *this, int pid,
|
||||
pts_meas_algorithms_t algo,
|
||||
chunk_t measurement, char *filename,
|
||||
bool is_dir, int id);
|
||||
|
||||
/**
|
||||
* Get PTS measurement[s] for a given filename stored in database
|
||||
*
|
||||
* @param pid Primary key of software product in database
|
||||
* @param algo File measurement hash algorithm used
|
||||
* @param filename Name of the file to be checked
|
||||
* @return Enumerator over all matching measurement hashes
|
||||
*/
|
||||
enumerator_t* (*create_file_meas_enumerator)(pts_database_t *this, int pid,
|
||||
pts_meas_algorithms_t algo,
|
||||
char *filename);
|
||||
|
||||
/**
|
||||
* Check a functional component measurement against value stored in database
|
||||
*
|
||||
* @param measurement measurement hash
|
||||
* @param cid Primary key of Component Functional Name entry
|
||||
* @param aik_id Primary key of AIK entry in database
|
||||
* @param seq_no Measurement sequence number
|
||||
* @param prc Number of the PCR the measurement was extended into
|
||||
* @param algo Hash algorithm used for measurement
|
||||
* @return SUCCESS if check was successful
|
||||
*/
|
||||
status_t (*check_comp_measurement)(pts_database_t *this, chunk_t measurement,
|
||||
int cid, int aik_id, int seq_no, int pcr,
|
||||
pts_meas_algorithms_t algo);
|
||||
|
||||
/**
|
||||
* Insert a functional component measurement into the database
|
||||
*
|
||||
* @param measurement Measurement hash
|
||||
* @param cid Primary key of Component Functional Name entry
|
||||
* @param aik_id Primary key of AIK entry in database
|
||||
* @param seq_no Measurement sequence number
|
||||
* @param prc Number of the PCR the measurement was extended into
|
||||
* @param algo Hash algorithm used for measurement
|
||||
* @return SUCCESS if INSERT was successful
|
||||
*/
|
||||
status_t (*insert_comp_measurement)(pts_database_t *this, chunk_t measurement,
|
||||
int cid, int aik_id, int seq_no, int pcr,
|
||||
pts_meas_algorithms_t algo);
|
||||
|
||||
/**
|
||||
* Delete functional component measurements from the database
|
||||
*
|
||||
* @param cid Primary key of Component Functional Name entry
|
||||
* @param aik_id Primary key of AIK entry in database
|
||||
* @return number of deleted measurement entries
|
||||
*/
|
||||
int (*delete_comp_measurements)(pts_database_t *this, int cid, int aik_id);
|
||||
|
||||
/**
|
||||
* Get the number of measurements for a functional component and AIK
|
||||
*
|
||||
* @param comp_name Component Functional Name
|
||||
* @param aik_id Primary key of AIK entry in database
|
||||
* @param algo Hash algorithm used for measurement
|
||||
* @param cid Primary key of Component Functional Name entry
|
||||
* @param count measurement count
|
||||
* @return SUCCESS if COUNT was successful
|
||||
*/
|
||||
status_t (*get_comp_measurement_count)(pts_database_t *this,
|
||||
pts_comp_func_name_t *comp_name, int aik_id,
|
||||
pts_meas_algorithms_t algo, int *cid, int *count);
|
||||
|
||||
/**
|
||||
* Destroys a pts_database_t object.
|
||||
*/
|
||||
void (*destroy)(pts_database_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an pts_database_t object
|
||||
*
|
||||
* @param imv_db Already attached IMV database
|
||||
*/
|
||||
pts_database_t* pts_database_create(imv_database_t *imv_db);
|
||||
|
||||
#endif /** PTS_DATABASE_H_ @}*/
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_dh_group.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
bool pts_dh_group_probe(pts_dh_group_t *dh_groups, bool mandatory_dh_groups)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
diffie_hellman_group_t dh_group;
|
||||
const char *plugin_name;
|
||||
char format1[] = " %s PTS DH group %N[%s] available";
|
||||
char format2[] = " %s PTS DH group %N not available";
|
||||
|
||||
*dh_groups = PTS_DH_GROUP_NONE;
|
||||
|
||||
enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
|
||||
while (enumerator->enumerate(enumerator, &dh_group, &plugin_name))
|
||||
{
|
||||
if (dh_group == MODP_1024_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE2;
|
||||
DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
else if (dh_group == MODP_1536_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE5;
|
||||
DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
else if (dh_group == MODP_2048_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE14;
|
||||
DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
else if (dh_group == ECP_256_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE19;
|
||||
DBG2(DBG_PTS, format1, "mandatory", diffie_hellman_group_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
else if (dh_group == ECP_384_BIT)
|
||||
{
|
||||
*dh_groups |= PTS_DH_GROUP_IKE20;
|
||||
DBG2(DBG_PTS, format1, "optional ", diffie_hellman_group_names,
|
||||
dh_group, plugin_name);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (*dh_groups & PTS_DH_GROUP_IKE19)
|
||||
{
|
||||
/* mandatory PTS DH group is available */
|
||||
return TRUE;
|
||||
}
|
||||
if (*dh_groups == PTS_DH_GROUP_NONE)
|
||||
{
|
||||
DBG1(DBG_PTS, "no PTS DH group available");
|
||||
return FALSE;
|
||||
}
|
||||
if (mandatory_dh_groups)
|
||||
{
|
||||
DBG1(DBG_PTS, format2, "mandatory", diffie_hellman_group_names,
|
||||
ECP_256_BIT);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* at least one optional PTS DH group is available */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
bool pts_dh_group_update(char *dh_group, pts_dh_group_t *dh_groups)
|
||||
{
|
||||
if (strcaseeq(dh_group, "ecp384"))
|
||||
{
|
||||
/* nothing to update, all groups are supported */
|
||||
return TRUE;
|
||||
}
|
||||
if (strcaseeq(dh_group, "ecp256"))
|
||||
{
|
||||
/* remove DH group 20 */
|
||||
*dh_groups &= ~PTS_DH_GROUP_IKE20;
|
||||
return TRUE;
|
||||
}
|
||||
if (strcaseeq(dh_group, "modp2048"))
|
||||
{
|
||||
/* remove DH groups 19 and 20 */
|
||||
*dh_groups &= ~(PTS_DH_GROUP_IKE20 | PTS_DH_GROUP_IKE19);
|
||||
return TRUE;
|
||||
}
|
||||
if (strcaseeq(dh_group, "modp1536"))
|
||||
{
|
||||
/* remove DH groups 14, 19 and 20 */
|
||||
*dh_groups &= ~(PTS_DH_GROUP_IKE20 | PTS_DH_GROUP_IKE19 |
|
||||
PTS_DH_GROUP_IKE14);
|
||||
return TRUE;
|
||||
}
|
||||
if (strcaseeq(dh_group, "modp1024"))
|
||||
{
|
||||
/* remove DH groups 5, 14, 19 and 20 */
|
||||
*dh_groups &= ~(PTS_DH_GROUP_IKE20 | PTS_DH_GROUP_IKE19 |
|
||||
PTS_DH_GROUP_IKE14 | PTS_DH_GROUP_IKE5);
|
||||
return TRUE;
|
||||
}
|
||||
DBG1(DBG_PTS, "unknown DH group '%s' configured", dh_group);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_dh_groups,
|
||||
pts_dh_group_t offered_dh_groups)
|
||||
{
|
||||
if ((supported_dh_groups & PTS_DH_GROUP_IKE20) &&
|
||||
(offered_dh_groups & PTS_DH_GROUP_IKE20))
|
||||
{
|
||||
return PTS_DH_GROUP_IKE20;
|
||||
}
|
||||
if ((supported_dh_groups & PTS_DH_GROUP_IKE19) &&
|
||||
(offered_dh_groups & PTS_DH_GROUP_IKE19))
|
||||
{
|
||||
return PTS_DH_GROUP_IKE19;
|
||||
}
|
||||
if ((supported_dh_groups & PTS_DH_GROUP_IKE14) &&
|
||||
(offered_dh_groups & PTS_DH_GROUP_IKE14))
|
||||
{
|
||||
return PTS_DH_GROUP_IKE14;
|
||||
}
|
||||
if ((supported_dh_groups & PTS_DH_GROUP_IKE5) &&
|
||||
(offered_dh_groups & PTS_DH_GROUP_IKE5))
|
||||
{
|
||||
return PTS_DH_GROUP_IKE5;
|
||||
}
|
||||
if ((supported_dh_groups & PTS_DH_GROUP_IKE2) &&
|
||||
(offered_dh_groups & PTS_DH_GROUP_IKE2))
|
||||
{
|
||||
return PTS_DH_GROUP_IKE2;
|
||||
}
|
||||
return PTS_DH_GROUP_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
diffie_hellman_group_t pts_dh_group_to_ike(pts_dh_group_t dh_group)
|
||||
{
|
||||
switch (dh_group)
|
||||
{
|
||||
case PTS_DH_GROUP_IKE2:
|
||||
return MODP_1024_BIT;
|
||||
case PTS_DH_GROUP_IKE5:
|
||||
return MODP_1536_BIT;
|
||||
case PTS_DH_GROUP_IKE14:
|
||||
return MODP_2048_BIT;
|
||||
case PTS_DH_GROUP_IKE19:
|
||||
return ECP_256_BIT;
|
||||
case PTS_DH_GROUP_IKE20:
|
||||
return ECP_384_BIT;
|
||||
default:
|
||||
return MODP_NONE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_dh_group pts_dh_group
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_DH_GROUP_H_
|
||||
#define PTS_DH_GROUP_H_
|
||||
|
||||
#include <library.h>
|
||||
#include <crypto/diffie_hellman.h>
|
||||
|
||||
typedef enum pts_dh_group_t pts_dh_group_t;
|
||||
|
||||
/**
|
||||
* PTS Diffie Hellman Group Values
|
||||
*/
|
||||
enum pts_dh_group_t {
|
||||
/** No DH Group */
|
||||
PTS_DH_GROUP_NONE = 0,
|
||||
/** IKE Group 2 */
|
||||
PTS_DH_GROUP_IKE2 = (1<<15),
|
||||
/** IKE Group 5 */
|
||||
PTS_DH_GROUP_IKE5 = (1<<14),
|
||||
/** IKE Group 14 */
|
||||
PTS_DH_GROUP_IKE14 = (1<<13),
|
||||
/** IKE Group 19 */
|
||||
PTS_DH_GROUP_IKE19 = (1<<12),
|
||||
/** IKE Group 20 */
|
||||
PTS_DH_GROUP_IKE20 = (1<<11),
|
||||
};
|
||||
|
||||
/**
|
||||
* Diffie-Hellman Group Values
|
||||
* see section 3.8.6 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*
|
||||
* 1
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |1|2|3|4|5|R|R|R|R|R|R|R|R|R|R|R|
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Probe available PTS Diffie-Hellman groups
|
||||
*
|
||||
* @param dh_groups returns set of available DH groups
|
||||
* @param mandatory_dh_groups if TRUE enforce mandatory PTS DH groups
|
||||
* @return TRUE if mandatory DH groups are available
|
||||
* or at least one optional DH group if
|
||||
* mandatory_dh_groups is set to FALSE.
|
||||
*/
|
||||
bool pts_dh_group_probe(pts_dh_group_t *dh_groups, bool mandatory_dh_groups);
|
||||
|
||||
/**
|
||||
* Update supported Diffie-Hellman groups according to configuration
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* The PTS-IMC is expected to select the strongest supported group
|
||||
*
|
||||
* @param dh_group configured DH group
|
||||
* @param dh_groups returns set of available DH groups
|
||||
*/
|
||||
bool pts_dh_group_update(char *dh_group, pts_dh_group_t *dh_groups);
|
||||
|
||||
/**
|
||||
* Select the strongest supported Diffie-Hellman group
|
||||
* among a set of offered DH groups
|
||||
*
|
||||
* @param supported_groups set of supported DH groups
|
||||
* @param offered_groups set of offered DH groups
|
||||
* @return selected DH group
|
||||
*/
|
||||
pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_groups,
|
||||
pts_dh_group_t offered_groups);
|
||||
|
||||
/**
|
||||
* Convert pts_dh_group_t to diffie_hellman_group_t
|
||||
*
|
||||
* @param dh_group PTS DH group type
|
||||
* @return IKE DH group type
|
||||
*/
|
||||
diffie_hellman_group_t pts_dh_group_to_ike(pts_dh_group_t dh_group);
|
||||
|
||||
#endif /** PTS_DH_GROUP_H_ @}*/
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_error.h"
|
||||
|
||||
#include <bio/bio_writer.h>
|
||||
#include <ietf/ietf_attr_pa_tnc_error.h>
|
||||
|
||||
ENUM(pts_error_code_names, TCG_PTS_RESERVED_ERROR, TCG_PTS_UNABLE_DET_PCR,
|
||||
"Reserved Error",
|
||||
"Hash Algorithm Not Supported",
|
||||
"Invalid Path",
|
||||
"File Not Found",
|
||||
"Registry Not Supported",
|
||||
"Registry Key Not Found",
|
||||
"D-H Group Not Supported",
|
||||
"DH-PN Nonce Not Acceptable",
|
||||
"Invalid Functional Name Family",
|
||||
"TPM Version Information Unavailable",
|
||||
"Invalid File Pathname Delimiter",
|
||||
"PTS Operation Not Supported",
|
||||
"Unable To Update Reference Manifest",
|
||||
"Unable To Perform Local Validation",
|
||||
"Unable To Collect Current Evidence",
|
||||
"Unable To Determine Transitive Trust Chain",
|
||||
"Unable To Determine PCR"
|
||||
);
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t* pts_hash_alg_error_create(pts_meas_algorithms_t algorithms)
|
||||
{
|
||||
bio_writer_t *writer;
|
||||
chunk_t msg_info;
|
||||
pa_tnc_attr_t *attr;
|
||||
pen_type_t error_code = { PEN_TCG, TCG_PTS_HASH_ALG_NOT_SUPPORTED };
|
||||
|
||||
writer = bio_writer_create(4);
|
||||
writer->write_uint16(writer, 0x0000);
|
||||
writer->write_uint16(writer, algorithms);
|
||||
msg_info = writer->get_buf(writer);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
|
||||
writer->destroy(writer);
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t* pts_dh_group_error_create(pts_dh_group_t dh_groups)
|
||||
{
|
||||
bio_writer_t *writer;
|
||||
chunk_t msg_info;
|
||||
pa_tnc_attr_t *attr;
|
||||
pen_type_t error_code = { PEN_TCG, TCG_PTS_DH_GRPS_NOT_SUPPORTED };
|
||||
|
||||
writer = bio_writer_create(4);
|
||||
writer->write_uint16(writer, 0x0000);
|
||||
writer->write_uint16(writer, dh_groups);
|
||||
msg_info = writer->get_buf(writer);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
|
||||
writer->destroy(writer);
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t* pts_dh_nonce_error_create(int min_nonce_len, int max_nonce_len)
|
||||
{
|
||||
bio_writer_t *writer;
|
||||
chunk_t msg_info;
|
||||
pa_tnc_attr_t *attr;
|
||||
pen_type_t error_code = { PEN_TCG, TCG_PTS_BAD_NONCE_LENGTH };
|
||||
|
||||
writer = bio_writer_create(4);
|
||||
writer->write_uint16(writer, min_nonce_len);
|
||||
writer->write_uint16(writer, max_nonce_len);
|
||||
msg_info = writer->get_buf(writer);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
|
||||
writer->destroy(writer);
|
||||
|
||||
return attr;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_error pts_error
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_ERROR_H_
|
||||
#define PTS_ERROR_H_
|
||||
|
||||
typedef enum pts_error_code_t pts_error_code_t;
|
||||
|
||||
#include "pts_meas_algo.h"
|
||||
#include "pts_dh_group.h"
|
||||
#include "pa_tnc/pa_tnc_attr.h"
|
||||
|
||||
#include <library.h>
|
||||
|
||||
#define PTS_MIN_NONCE_LEN 17
|
||||
#define PTS_MAX_NONCE_LEN 0xffff
|
||||
|
||||
/**
|
||||
* PTS Attestation Error Codes
|
||||
* see section 3.14.2 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*/
|
||||
enum pts_error_code_t {
|
||||
TCG_PTS_RESERVED_ERROR = 0,
|
||||
TCG_PTS_HASH_ALG_NOT_SUPPORTED = 1,
|
||||
TCG_PTS_INVALID_PATH = 2,
|
||||
TCG_PTS_FILE_NOT_FOUND = 3,
|
||||
TCG_PTS_REG_NOT_SUPPORTED = 4,
|
||||
TCG_PTS_REG_KEY_NOT_FOUND = 5,
|
||||
TCG_PTS_DH_GRPS_NOT_SUPPORTED = 6,
|
||||
TCG_PTS_BAD_NONCE_LENGTH = 7,
|
||||
TCG_PTS_INVALID_NAME_FAM = 8,
|
||||
TCG_PTS_TPM_VERS_NOT_SUPPORTED = 9,
|
||||
TCG_PTS_INVALID_DELIMITER = 10,
|
||||
TCG_PTS_OPERATION_NOT_SUPPORTED = 11,
|
||||
TCG_PTS_RM_ERROR = 12,
|
||||
TCG_PTS_UNABLE_LOCAL_VAL = 13,
|
||||
TCG_PTS_UNABLE_CUR_EVID = 14,
|
||||
TCG_PTS_UNABLE_DET_TTC = 15,
|
||||
TCG_PTS_UNABLE_DET_PCR = 16,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum name for pts_error_code_t.
|
||||
*/
|
||||
extern enum_name_t *pts_error_code_names;
|
||||
|
||||
/**
|
||||
* Creates a PTS Hash Algorithm Not Supported Error Attribute
|
||||
* see section 4.2.2 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*
|
||||
* @param algorithms supported measurement hash algorithms
|
||||
*/
|
||||
pa_tnc_attr_t* pts_hash_alg_error_create(pts_meas_algorithms_t algorithms);
|
||||
|
||||
/**
|
||||
* Creates a PTS DH Group Not Supported Error Attribute
|
||||
* see section 4.2.4 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*
|
||||
* @param dh_groups supported DH groups
|
||||
*/
|
||||
pa_tnc_attr_t* pts_dh_group_error_create(pts_dh_group_t dh_groups);
|
||||
|
||||
/**
|
||||
* Creates a PTS DH PN Nonce Not Supported Error Attribute
|
||||
* see section 4.2.5 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*
|
||||
* @param min_nonce_len minimum nonce length
|
||||
* @param max_nonce_len maximum nonce length
|
||||
*/
|
||||
pa_tnc_attr_t* pts_dh_nonce_error_create(int min_nonce_len, int max_nonce_len);
|
||||
|
||||
#endif /** PTS_ERROR_H_ @}*/
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Sansar Choinyambuu
|
||||
* Copyright (C) 2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_file_meas.h"
|
||||
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct private_pts_file_meas_t private_pts_file_meas_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_file_meas_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_file_meas_t {
|
||||
|
||||
/**
|
||||
* Public pts_file_meas_t interface.
|
||||
*/
|
||||
pts_file_meas_t public;
|
||||
|
||||
/**
|
||||
* ID of PTS File Measurement Request
|
||||
*/
|
||||
u_int16_t request_id;
|
||||
|
||||
/**
|
||||
* List of File Measurements
|
||||
*/
|
||||
linked_list_t *list;
|
||||
};
|
||||
|
||||
typedef struct entry_t entry_t;
|
||||
|
||||
/**
|
||||
* PTS File Measurement entry
|
||||
*/
|
||||
struct entry_t {
|
||||
char *filename;
|
||||
chunk_t measurement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Free an entry_t object
|
||||
*/
|
||||
static void free_entry(entry_t *entry)
|
||||
{
|
||||
if (entry)
|
||||
{
|
||||
free(entry->filename);
|
||||
free(entry->measurement.ptr);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(pts_file_meas_t, get_request_id, u_int16_t,
|
||||
private_pts_file_meas_t *this)
|
||||
{
|
||||
return this->request_id;
|
||||
}
|
||||
|
||||
METHOD(pts_file_meas_t, get_file_count, int,
|
||||
private_pts_file_meas_t *this)
|
||||
{
|
||||
return this->list->get_count(this->list);
|
||||
}
|
||||
|
||||
METHOD(pts_file_meas_t, add, void,
|
||||
private_pts_file_meas_t *this, char *filename, chunk_t measurement)
|
||||
{
|
||||
entry_t *entry;
|
||||
|
||||
entry = malloc_thing(entry_t);
|
||||
entry->filename = strdup(filename);
|
||||
entry->measurement = chunk_clone(measurement);
|
||||
|
||||
this->list->insert_last(this->list, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerate file measurement entries
|
||||
*/
|
||||
static bool entry_filter(void *null, entry_t **entry, char **filename,
|
||||
void *i2, chunk_t *measurement)
|
||||
{
|
||||
*filename = (*entry)->filename;
|
||||
*measurement = (*entry)->measurement;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
|
||||
private_pts_file_meas_t *this)
|
||||
{
|
||||
return enumerator_create_filter(this->list->create_enumerator(this->list),
|
||||
(void*)entry_filter, NULL, NULL);
|
||||
}
|
||||
|
||||
METHOD(pts_file_meas_t, check, bool,
|
||||
private_pts_file_meas_t *this, pts_database_t *pts_db, int pid,
|
||||
pts_meas_algorithms_t algo)
|
||||
{
|
||||
enumerator_t *enumerator, *e;
|
||||
entry_t *entry;
|
||||
chunk_t hash;
|
||||
int count_ok = 0, count_not_found = 0, count_differ = 0;
|
||||
status_t status;
|
||||
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
status = NOT_FOUND;
|
||||
|
||||
e = pts_db->create_file_meas_enumerator(pts_db, pid, algo,
|
||||
entry->filename);
|
||||
if (e)
|
||||
{
|
||||
while (e->enumerate(e, &hash))
|
||||
{
|
||||
if (chunk_equals(entry->measurement, hash))
|
||||
{
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = VERIFY_ERROR;
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = FAILED;
|
||||
}
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case SUCCESS:
|
||||
DBG3(DBG_PTS, " %#B for '%s' is ok", &entry->measurement,
|
||||
entry->filename);
|
||||
count_ok++;
|
||||
break;
|
||||
case NOT_FOUND:
|
||||
DBG2(DBG_PTS, " %#B for '%s' not found", &entry->measurement,
|
||||
entry->filename);
|
||||
count_not_found++;
|
||||
break;
|
||||
case VERIFY_ERROR:
|
||||
DBG1(DBG_PTS, " %#B for '%s' differs", &entry->measurement,
|
||||
entry->filename);
|
||||
count_differ++;
|
||||
break;
|
||||
case FAILED:
|
||||
default:
|
||||
DBG1(DBG_PTS, " %#B for '%s' failed", &entry->measurement,
|
||||
entry->filename);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
DBG1(DBG_PTS, "%d measurements, %d ok, %d not found, %d differ",
|
||||
this->list->get_count(this->list),
|
||||
count_ok, count_not_found, count_differ);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(pts_file_meas_t, verify, bool,
|
||||
private_pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir)
|
||||
{
|
||||
int fid, fid_last = 0;
|
||||
char *filename;
|
||||
chunk_t measurement;
|
||||
entry_t *entry;
|
||||
enumerator_t *enumerator = NULL;
|
||||
bool found = FALSE, match = FALSE, success = TRUE;
|
||||
|
||||
while (e_hash->enumerate(e_hash, &fid, &filename, &measurement))
|
||||
{
|
||||
if (fid != fid_last)
|
||||
{
|
||||
if (found && !match)
|
||||
{
|
||||
/* no matching hash value found for last filename */
|
||||
success = FALSE;
|
||||
DBG1(DBG_PTS, " %#B for '%s' is incorrect",
|
||||
&entry->measurement, entry->filename);
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
/* get a new filename from the database */
|
||||
found = FALSE;
|
||||
match = FALSE;
|
||||
fid_last = fid;
|
||||
|
||||
/**
|
||||
* check if we find an entry for this filename
|
||||
* in the PTS measurement list
|
||||
*/
|
||||
enumerator = this->list->create_enumerator(this->list);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (!is_dir || streq(filename, entry->filename))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* no PTS measurement returned for this filename */
|
||||
if (!found)
|
||||
{
|
||||
success = FALSE;
|
||||
DBG1(DBG_PTS, " no measurement found for '%s'", filename);
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
}
|
||||
|
||||
if (found && !match)
|
||||
{
|
||||
if (chunk_equals(measurement, entry->measurement))
|
||||
{
|
||||
match = TRUE;
|
||||
DBG2(DBG_PTS, " %#B for '%s' is ok",
|
||||
&entry->measurement, entry->filename);
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found && !match)
|
||||
{
|
||||
/* no matching hash value found for the very last filename */
|
||||
success = FALSE;
|
||||
DBG1(DBG_PTS, " %#B for '%s' is incorrect",
|
||||
&entry->measurement, entry->filename);
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
METHOD(pts_file_meas_t, destroy, void,
|
||||
private_pts_file_meas_t *this)
|
||||
{
|
||||
this->list->destroy_function(this->list, (void *)free_entry);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_file_meas_t *pts_file_meas_create(u_int16_t request_id)
|
||||
{
|
||||
private_pts_file_meas_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_request_id = _get_request_id,
|
||||
.get_file_count = _get_file_count,
|
||||
.add = _add,
|
||||
.create_enumerator = _create_enumerator,
|
||||
.check = _check,
|
||||
.verify = _verify,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.request_id = request_id,
|
||||
.list = linked_list_create(),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash a file with a given absolute pathname
|
||||
*/
|
||||
static bool hash_file(hasher_t *hasher, char *pathname, u_char *hash)
|
||||
{
|
||||
u_char buffer[4096];
|
||||
size_t bytes_read;
|
||||
bool success = TRUE;
|
||||
FILE *file;
|
||||
|
||||
file = fopen(pathname, "rb");
|
||||
if (!file)
|
||||
{
|
||||
DBG1(DBG_PTS," file '%s' can not be opened, %s", pathname,
|
||||
strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
while (TRUE)
|
||||
{
|
||||
bytes_read = fread(buffer, 1, sizeof(buffer), file);
|
||||
if (bytes_read > 0)
|
||||
{
|
||||
if (!hasher->get_hash(hasher, chunk_create(buffer, bytes_read), NULL))
|
||||
{
|
||||
DBG1(DBG_PTS, " hasher increment error");
|
||||
success = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!hasher->get_hash(hasher, chunk_empty, hash))
|
||||
{
|
||||
DBG1(DBG_PTS, " hasher finalize error");
|
||||
success = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_file_meas_t *pts_file_meas_create_from_path(u_int16_t request_id,
|
||||
char *pathname, bool is_dir, bool use_rel_name,
|
||||
pts_meas_algorithms_t alg)
|
||||
{
|
||||
private_pts_file_meas_t *this;
|
||||
hash_algorithm_t hash_alg;
|
||||
hasher_t *hasher;
|
||||
u_char hash[HASH_SIZE_SHA384];
|
||||
chunk_t measurement;
|
||||
char* filename;
|
||||
bool success = TRUE;
|
||||
|
||||
/* Create a hasher and a hash measurement buffer */
|
||||
hash_alg = pts_meas_algo_to_hash(alg);
|
||||
hasher = lib->crypto->create_hasher(lib->crypto, hash_alg);
|
||||
if (!hasher)
|
||||
{
|
||||
DBG1(DBG_PTS, "hasher %N not available", hash_algorithm_names, hash_alg);
|
||||
return NULL;
|
||||
}
|
||||
measurement = chunk_create(hash, hasher->get_hash_size(hasher));
|
||||
this = (private_pts_file_meas_t*)pts_file_meas_create(request_id);
|
||||
|
||||
if (is_dir)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
char *rel_name, *abs_name;
|
||||
struct stat st;
|
||||
|
||||
enumerator = enumerator_create_directory(pathname);
|
||||
if (!enumerator)
|
||||
{
|
||||
DBG1(DBG_PTS, " directory '%s' can not be opened, %s", pathname,
|
||||
strerror(errno));
|
||||
success = FALSE;
|
||||
goto end;
|
||||
}
|
||||
while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
|
||||
{
|
||||
/* measure regular files only */
|
||||
if (S_ISREG(st.st_mode) && *rel_name != '.')
|
||||
{
|
||||
if (!hash_file(hasher, abs_name, hash))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
filename = use_rel_name ? rel_name : abs_name;
|
||||
DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
|
||||
add(this, filename, measurement);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!hash_file(hasher, pathname, hash))
|
||||
{
|
||||
success = FALSE;
|
||||
goto end;
|
||||
}
|
||||
filename = use_rel_name ? path_basename(pathname) : strdup(pathname);
|
||||
DBG2(DBG_PTS, " %#B for '%s'", &measurement, filename);
|
||||
add(this, filename, measurement);
|
||||
free(filename);
|
||||
}
|
||||
|
||||
end:
|
||||
hasher->destroy(hasher);
|
||||
if (success)
|
||||
{
|
||||
return &this->public;
|
||||
}
|
||||
else
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Sansar Choinyambuu
|
||||
* Copyright (C) 2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_file_meas pts_file_meas
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_FILE_MEAS_H_
|
||||
#define PTS_FILE_MEAS_H_
|
||||
|
||||
#include "pts/pts_database.h"
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct pts_file_meas_t pts_file_meas_t;
|
||||
|
||||
/**
|
||||
* Class storing PTS File Measurements
|
||||
*/
|
||||
struct pts_file_meas_t {
|
||||
|
||||
/**
|
||||
* Get the ID of the PTS File Measurement Request
|
||||
*
|
||||
* @return ID of PTS File Measurement Request
|
||||
*/
|
||||
u_int16_t (*get_request_id)(pts_file_meas_t *this);
|
||||
|
||||
/**
|
||||
* Get the number of measured files
|
||||
*
|
||||
* @return Number of measured files
|
||||
*/
|
||||
int (*get_file_count)(pts_file_meas_t *this);
|
||||
|
||||
/**
|
||||
* Add a PTS File Measurement
|
||||
*
|
||||
* @param filename Name of measured file or directory
|
||||
* @param measurement PTS Measurement hash
|
||||
*/
|
||||
void (*add)(pts_file_meas_t *this, char *filename, chunk_t measurement);
|
||||
|
||||
/**
|
||||
* Create a PTS File Measurement enumerator
|
||||
*
|
||||
* @return Enumerator returning filename and measurement
|
||||
*/
|
||||
enumerator_t* (*create_enumerator)(pts_file_meas_t *this);
|
||||
|
||||
/**
|
||||
* Check PTS File Measurements against reference value in the database
|
||||
*
|
||||
* @param db PTS Measurement database
|
||||
* @param pid Primary key of software product in database
|
||||
* @param algo PTS Measurement algorithm used
|
||||
* @return TRUE if all measurements agreed
|
||||
*/
|
||||
bool (*check)(pts_file_meas_t *this, pts_database_t *db, int pid,
|
||||
pts_meas_algorithms_t algo);
|
||||
|
||||
/**
|
||||
* Verify stored hashes against PTS File Measurements
|
||||
*
|
||||
* @param e_hash Hash enumerator
|
||||
* @param is_dir TRUE for directory contents hashes
|
||||
* @return TRUE if all hashes match a measurement
|
||||
*/
|
||||
bool (*verify)(pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir);
|
||||
|
||||
/**
|
||||
* Destroys a pts_file_meas_t object.
|
||||
*/
|
||||
void (*destroy)(pts_file_meas_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a pts_file_meas_t object
|
||||
*
|
||||
* @param request_id ID of PTS File Measurement Request
|
||||
*/
|
||||
pts_file_meas_t* pts_file_meas_create(u_int16_t request_id);
|
||||
|
||||
/**
|
||||
* Creates a pts_file_meas_t object measuring a file/directory
|
||||
*
|
||||
* @param request_id ID of PTS File Measurement Request
|
||||
* @param pathname Absolute file or directory pathname
|
||||
* @param is_dir TRUE if directory path
|
||||
* @param use_rel_name TRUE if relative filenames are to be used
|
||||
* @param alg PTS hash measurement algorithm to be used
|
||||
*/
|
||||
pts_file_meas_t* pts_file_meas_create_from_path(u_int16_t request_id,
|
||||
char* pathname, bool is_dir, bool use_rel_name,
|
||||
pts_meas_algorithms_t alg);
|
||||
|
||||
#endif /** PTS_FILE_MEAS_H_ @}*/
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_file_meta.h"
|
||||
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_pts_file_meta_t private_pts_file_meta_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_file_meta_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_file_meta_t {
|
||||
|
||||
/**
|
||||
* Public pts_file_meta_t interface.
|
||||
*/
|
||||
pts_file_meta_t public;
|
||||
|
||||
/**
|
||||
* List of File Metadata
|
||||
*/
|
||||
linked_list_t *list;
|
||||
};
|
||||
|
||||
/**
|
||||
* Free an pts_file_metadata_t object
|
||||
*/
|
||||
static void free_entry(pts_file_metadata_t *entry)
|
||||
{
|
||||
if (entry)
|
||||
{
|
||||
free(entry->filename);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(pts_file_meta_t, get_file_count, int,
|
||||
private_pts_file_meta_t *this)
|
||||
{
|
||||
return this->list->get_count(this->list);
|
||||
}
|
||||
|
||||
METHOD(pts_file_meta_t, add, void,
|
||||
private_pts_file_meta_t *this, pts_file_metadata_t *metadata)
|
||||
{
|
||||
this->list->insert_last(this->list, metadata);
|
||||
}
|
||||
|
||||
METHOD(pts_file_meta_t, create_enumerator, enumerator_t*,
|
||||
private_pts_file_meta_t *this)
|
||||
{
|
||||
return this->list->create_enumerator(this->list);
|
||||
}
|
||||
|
||||
METHOD(pts_file_meta_t, destroy, void,
|
||||
private_pts_file_meta_t *this)
|
||||
{
|
||||
this->list->destroy_function(this->list, (void *)free_entry);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_file_meta_t *pts_file_meta_create()
|
||||
{
|
||||
private_pts_file_meta_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_file_count = _get_file_count,
|
||||
.add = _add,
|
||||
.create_enumerator = _create_enumerator,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.list = linked_list_create(),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_file_meta pts_file_meta
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_FILE_META_H_
|
||||
#define PTS_FILE_META_H_
|
||||
|
||||
#include "pts_file_type.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <library.h>
|
||||
|
||||
typedef struct pts_file_meta_t pts_file_meta_t;
|
||||
typedef struct pts_file_metadata_t pts_file_metadata_t;
|
||||
|
||||
/**
|
||||
* Structure holding file metadata
|
||||
*/
|
||||
struct pts_file_metadata_t {
|
||||
pts_file_type_t type;
|
||||
u_int64_t filesize;
|
||||
u_int64_t created;
|
||||
u_int64_t modified;
|
||||
u_int64_t accessed;
|
||||
u_int64_t owner;
|
||||
u_int64_t group;
|
||||
char *filename;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class storing PTS File Metadata
|
||||
*/
|
||||
struct pts_file_meta_t {
|
||||
|
||||
/**
|
||||
* Get the number of files
|
||||
*
|
||||
* @return Number of files
|
||||
*/
|
||||
int (*get_file_count)(pts_file_meta_t *this);
|
||||
|
||||
/**
|
||||
* Add PTS File Metadata
|
||||
*
|
||||
* @param filename Name of measured file or directory
|
||||
* @param metadata File metadata
|
||||
*/
|
||||
void (*add)(pts_file_meta_t *this, pts_file_metadata_t *metadata);
|
||||
|
||||
/**
|
||||
* Create a PTS File Metadata enumerator
|
||||
*
|
||||
* @return Enumerator returning file metadata
|
||||
*/
|
||||
enumerator_t* (*create_enumerator)(pts_file_meta_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a pts_file_meta_t object.
|
||||
*/
|
||||
void (*destroy)(pts_file_meta_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a pts_file_meta_t object
|
||||
*/
|
||||
pts_file_meta_t* pts_file_meta_create();
|
||||
|
||||
#endif /** PTS_FILE_MEAS_H_ @}*/
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_file_type.h"
|
||||
|
||||
ENUM(pts_file_type_names, PTS_FILE_OTHER, PTS_FILE_SOCKET,
|
||||
"Other",
|
||||
"FIFO",
|
||||
"Character-Special",
|
||||
"Reserved-3",
|
||||
"Directory",
|
||||
"Reserved-5",
|
||||
"Block-Special",
|
||||
"Reserved-7",
|
||||
"Regular",
|
||||
"Reserved-9",
|
||||
"Symbolic-Link",
|
||||
"Reserved-11",
|
||||
"Socket"
|
||||
);
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_file_type pts_file_type
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_FILE_TYPE_H_
|
||||
#define PTS_FILE_TYPE_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef enum pts_file_type_t pts_file_type_t;
|
||||
|
||||
/**
|
||||
* PTS File Type
|
||||
* see section 3.17.3 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*/
|
||||
enum pts_file_type_t {
|
||||
/** Either unknown or different from standardized types */
|
||||
PTS_FILE_OTHER = 0x0000,
|
||||
/** Pipe communication file */
|
||||
PTS_FILE_FIFO = 0x0001,
|
||||
/** Character special file */
|
||||
PTS_FILE_CHAR_SPEC = 0x0002,
|
||||
/** Reserved */
|
||||
PTS_FILE_RESERVED_3 = 0x0003,
|
||||
/** Directory */
|
||||
PTS_FILE_DIRECTORY = 0x0004,
|
||||
/** Reserved */
|
||||
PTS_FILE_RESERVED_5 = 0x0005,
|
||||
/** Block special file */
|
||||
PTS_FILE_BLOCK_SPEC = 0x0006,
|
||||
/** Reserved */
|
||||
PTS_FILE_RESERVED_7 = 0x0007,
|
||||
/** Regular file */
|
||||
PTS_FILE_REGULAR = 0x0008,
|
||||
/** Reserved */
|
||||
PTS_FILE_RESERVED_9 = 0x0009,
|
||||
/** Symbolic link */
|
||||
PTS_FILE_SYM_LINK = 0x000A,
|
||||
/** Reserved */
|
||||
PTS_FILE_RESERVED_11 = 0x000B,
|
||||
/** Socket communication special file */
|
||||
PTS_FILE_SOCKET = 0x000C,
|
||||
};
|
||||
|
||||
extern enum_name_t *pts_file_type_names;
|
||||
|
||||
#endif /** PTS_FILE_TYPE_H_ @}*/
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_ima_bios_list.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct private_pts_ima_bios_list_t private_pts_ima_bios_list_t;
|
||||
typedef struct bios_entry_t bios_entry_t;
|
||||
typedef enum event_type_t event_type_t;
|
||||
|
||||
enum event_type_t {
|
||||
/* BIOS Events (TCG PC Client Specification for Conventional BIOS 1.21) */
|
||||
EV_PREBOOT_CERT = 0x00000000,
|
||||
EV_POST_CODE = 0x00000001,
|
||||
EV_UNUSED = 0x00000002,
|
||||
EV_NO_ACTION = 0x00000003,
|
||||
EV_SEPARATOR = 0x00000004,
|
||||
EV_ACTION = 0x00000005,
|
||||
EV_EVENT_TAG = 0x00000006,
|
||||
EV_S_CRTM_CONTENTS = 0x00000007,
|
||||
EV_S_CRTM_VERSION = 0x00000008,
|
||||
EV_CPU_MICROCODE = 0x00000009,
|
||||
EV_PLATFORM_CONFIG_FLAGS = 0x0000000A,
|
||||
EV_TABLE_OF_DEVICES = 0x0000000B,
|
||||
EV_COMPACT_HASH = 0x0000000C,
|
||||
EV_IPL = 0x0000000D,
|
||||
EV_IPL_PARTITION_DATA = 0x0000000E,
|
||||
EV_NONHOST_CODE = 0x0000000F,
|
||||
EV_NONHOST_CONFIG = 0x00000010,
|
||||
EV_NONHOST_INFO = 0x00000011,
|
||||
EV_OMIT_BOOT_DEVICE_EVENTS = 0x00000012,
|
||||
|
||||
/* EFI Events (TCG EFI Platform Specification 1.22) */
|
||||
EV_EFI_EVENT_BASE = 0x80000000,
|
||||
EV_EFI_VARIABLE_DRIVER_CONFIG = 0x80000001,
|
||||
EV_EFI_VARIABLE_BOOT = 0x80000002,
|
||||
EV_EFI_BOOT_SERVICES_APPLICATION = 0x80000003,
|
||||
EV_EFI_BOOT_SERVICES_DRIVER = 0x80000004,
|
||||
EV_EFI_RUNTIME_SERVICES_DRIVER = 0x80000005,
|
||||
EV_EFI_GPT_EVENT = 0x80000006,
|
||||
EV_EFI_ACTION = 0x80000007,
|
||||
EV_EFI_PLATFORM_FIRMWARE_BLOB = 0x80000008,
|
||||
EV_EFI_HANDOFF_TABLES = 0x80000009,
|
||||
|
||||
EV_EFI_VARIABLE_AUTHORITY = 0x800000E0
|
||||
};
|
||||
|
||||
ENUM_BEGIN(event_type_names, EV_PREBOOT_CERT, EV_OMIT_BOOT_DEVICE_EVENTS,
|
||||
"Preboot Cert",
|
||||
"POST Code",
|
||||
"Unused",
|
||||
"No Action",
|
||||
"Separator",
|
||||
"Action",
|
||||
"Event Tag",
|
||||
"S-CRTM Contents",
|
||||
"S-CRTM Version",
|
||||
"CPU Microcode",
|
||||
"Platform Config Flags",
|
||||
"Table of Devices",
|
||||
"Compact Hash",
|
||||
"IPL",
|
||||
"IPL Partition Data",
|
||||
"Nonhost Code",
|
||||
"Nonhost Config",
|
||||
"Nonhost Info",
|
||||
"Omit Boot Device Events"
|
||||
);
|
||||
|
||||
ENUM_NEXT(event_type_names, EV_EFI_EVENT_BASE, EV_EFI_HANDOFF_TABLES,
|
||||
EV_OMIT_BOOT_DEVICE_EVENTS,
|
||||
"EFI Event Base",
|
||||
"EFI Variable Driver Config",
|
||||
"EFI Variable Boot",
|
||||
"EFI Boot Services Application",
|
||||
"EFI Boot Services Driver",
|
||||
"EFI Runtime Services Driver",
|
||||
"EFI GPT Event",
|
||||
"EFI Action",
|
||||
"EFI Platform Firmware Blob",
|
||||
"EFI Handoff Tables"
|
||||
);
|
||||
ENUM_NEXT(event_type_names, EV_EFI_VARIABLE_AUTHORITY, EV_EFI_VARIABLE_AUTHORITY,
|
||||
EV_EFI_HANDOFF_TABLES,
|
||||
"EFI Variable Authority"
|
||||
);
|
||||
ENUM_END(event_type_names, EV_EFI_VARIABLE_AUTHORITY);
|
||||
|
||||
/**
|
||||
* Private data of a pts_ima_bios_list_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_ima_bios_list_t {
|
||||
|
||||
/**
|
||||
* Public pts_ima_bios_list_t interface.
|
||||
*/
|
||||
pts_ima_bios_list_t public;
|
||||
|
||||
/**
|
||||
* List of BIOS measurement entries
|
||||
*/
|
||||
linked_list_t *list;
|
||||
|
||||
/**
|
||||
* Time when BIOS measurements were taken
|
||||
*/
|
||||
time_t creation_time;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Linux IMA BIOS measurement entry
|
||||
*/
|
||||
struct bios_entry_t {
|
||||
|
||||
/**
|
||||
* PCR register
|
||||
*/
|
||||
uint32_t pcr;
|
||||
|
||||
/**
|
||||
* SHA1 measurement hash
|
||||
*/
|
||||
chunk_t measurement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Free a bios_entry_t object
|
||||
*/
|
||||
static void free_bios_entry(bios_entry_t *this)
|
||||
{
|
||||
free(this->measurement.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(pts_ima_bios_list_t, get_time, time_t,
|
||||
private_pts_ima_bios_list_t *this)
|
||||
{
|
||||
return this->creation_time;
|
||||
}
|
||||
|
||||
METHOD(pts_ima_bios_list_t, get_count, int,
|
||||
private_pts_ima_bios_list_t *this)
|
||||
{
|
||||
return this->list->get_count(this->list);
|
||||
}
|
||||
|
||||
METHOD(pts_ima_bios_list_t, get_next, status_t,
|
||||
private_pts_ima_bios_list_t *this, uint32_t *pcr, chunk_t *measurement)
|
||||
{
|
||||
bios_entry_t *entry;
|
||||
status_t status;
|
||||
|
||||
status = this->list->remove_first(this->list, (void**)&entry);
|
||||
*pcr = entry->pcr;
|
||||
*measurement = entry->measurement;
|
||||
free(entry);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(pts_ima_bios_list_t, destroy, void,
|
||||
private_pts_ima_bios_list_t *this)
|
||||
{
|
||||
this->list->destroy_function(this->list, (void *)free_bios_entry);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_ima_bios_list_t* pts_ima_bios_list_create(char *file)
|
||||
{
|
||||
private_pts_ima_bios_list_t *this;
|
||||
uint32_t pcr, event_type, event_len, seek_len;
|
||||
uint32_t buf_len = 2048;
|
||||
uint8_t event_buf[buf_len];
|
||||
chunk_t event;
|
||||
bios_entry_t *entry;
|
||||
struct stat st;
|
||||
ssize_t res;
|
||||
int fd;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) == -1)
|
||||
{
|
||||
DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_time = _get_time,
|
||||
.get_count = _get_count,
|
||||
.get_next = _get_next,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.creation_time = st.st_ctime,
|
||||
.list = linked_list_create(),
|
||||
);
|
||||
|
||||
DBG2(DBG_PTS, "PCR Event Type (Size)");
|
||||
while (TRUE)
|
||||
{
|
||||
res = read(fd, &pcr, 4);
|
||||
if (res == 0)
|
||||
{
|
||||
DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)",
|
||||
file, this->list->get_count(this->list));
|
||||
close(fd);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
entry = malloc_thing(bios_entry_t);
|
||||
entry->pcr = pcr;
|
||||
entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
|
||||
|
||||
if (res != 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (read(fd, &event_type, 4) != 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (read(fd, &event_len, 4) != 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
DBG2(DBG_PTS, "%2u %N (%u bytes)", pcr, event_type_names, event_type,
|
||||
event_len);
|
||||
|
||||
seek_len = (event_len > buf_len) ? event_len - buf_len : 0;
|
||||
event_len -= seek_len;
|
||||
|
||||
if (read(fd, event_buf, event_len) != event_len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
event = chunk_create(event_buf, event_len);
|
||||
DBG3(DBG_PTS,"%B", &event);
|
||||
|
||||
if (event_type == EV_ACTION || event_type == EV_EFI_ACTION)
|
||||
{
|
||||
DBG2(DBG_PTS, " '%.*s'", event_len, event_buf);
|
||||
}
|
||||
|
||||
if (seek_len > 0 && lseek(fd, seek_len, SEEK_CUR) == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
this->list->insert_last(this->list, entry);
|
||||
}
|
||||
|
||||
DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file,
|
||||
strerror(errno));
|
||||
free_bios_entry(entry);
|
||||
close(fd);
|
||||
destroy(this);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_ima_bios_list pts_ima_bios_list
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_IMA_BIOS_LIST_H_
|
||||
#define PTS_IMA_BIOS_LIST_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct pts_ima_bios_list_t pts_ima_bios_list_t;
|
||||
|
||||
/**
|
||||
* Class retrieving Linux IMA BIOS measurements
|
||||
*
|
||||
*/
|
||||
struct pts_ima_bios_list_t {
|
||||
|
||||
/**
|
||||
* Get the time the BIOS measurements were taken
|
||||
*
|
||||
* @return Measurement time
|
||||
*/
|
||||
time_t (*get_time)(pts_ima_bios_list_t *this);
|
||||
|
||||
/**
|
||||
* Get the number of non-processed BIOS measurements
|
||||
*
|
||||
* @return Number of measurements left
|
||||
*/
|
||||
int (*get_count)(pts_ima_bios_list_t *this);
|
||||
|
||||
/**
|
||||
* Get the next BIOS measurement and remove it from the list
|
||||
*
|
||||
* @param pcr PCR where the measurement was extended into
|
||||
* @param measurement Measurement hash
|
||||
* @return Return code
|
||||
*/
|
||||
status_t (*get_next)(pts_ima_bios_list_t *this, uint32_t *pcr,
|
||||
chunk_t *measurement);
|
||||
|
||||
/**
|
||||
* Destroys a pts_ima_bios_list_t object.
|
||||
*/
|
||||
void (*destroy)(pts_ima_bios_list_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a PTS IMA BIOS measurement object
|
||||
*
|
||||
* @param file Pathname pointing to the BIOS measurements
|
||||
*/
|
||||
pts_ima_bios_list_t* pts_ima_bios_list_create(char *file);
|
||||
|
||||
#endif /** PTS_IMA_BIOS_LIST_H_ @}*/
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_ima_event_list.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct private_pts_ima_event_list_t private_pts_ima_event_list_t;
|
||||
typedef struct event_entry_t event_entry_t;
|
||||
|
||||
#define IMA_TYPE_LEN 3
|
||||
#define IMA_NG_TYPE_LEN 6
|
||||
#define IMA_TYPE_LEN_MAX 10
|
||||
#define IMA_ALGO_DIGEST_LEN_MAX IMA_ALGO_LEN_MAX + HASH_SIZE_SHA512
|
||||
|
||||
/**
|
||||
* Private data of a pts_ima_event_list_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_ima_event_list_t {
|
||||
|
||||
/**
|
||||
* Public pts_ima_event_list_t interface.
|
||||
*/
|
||||
pts_ima_event_list_t public;
|
||||
|
||||
/**
|
||||
* List of BIOS measurement entries
|
||||
*/
|
||||
linked_list_t *list;
|
||||
|
||||
/**
|
||||
* Time when IMA runtime file measurements were taken
|
||||
*/
|
||||
time_t creation_time;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Linux IMA runtime file measurement entry
|
||||
*/
|
||||
struct event_entry_t {
|
||||
|
||||
/**
|
||||
* SHA1 measurement hash
|
||||
*/
|
||||
chunk_t measurement;
|
||||
|
||||
/**
|
||||
* IMA-NG hash algorithm name or NULL
|
||||
*/
|
||||
char *algo;
|
||||
|
||||
/**
|
||||
* IMA-NG eventname or IMA filename
|
||||
*/
|
||||
char *name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Free an ima_event_t object
|
||||
*/
|
||||
static void free_event_entry(event_entry_t *this)
|
||||
{
|
||||
free(this->measurement.ptr);
|
||||
free(this->algo);
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(pts_ima_event_list_t, get_time, time_t,
|
||||
private_pts_ima_event_list_t *this)
|
||||
{
|
||||
return this->creation_time;
|
||||
}
|
||||
|
||||
METHOD(pts_ima_event_list_t, get_count, int,
|
||||
private_pts_ima_event_list_t *this)
|
||||
{
|
||||
return this->list->get_count(this->list);
|
||||
}
|
||||
|
||||
METHOD(pts_ima_event_list_t, get_next, status_t,
|
||||
private_pts_ima_event_list_t *this, chunk_t *measurement, char **algo,
|
||||
char **name)
|
||||
{
|
||||
event_entry_t *entry;
|
||||
status_t status;
|
||||
|
||||
status = this->list->remove_first(this->list, (void**)&entry);
|
||||
*measurement = entry->measurement;
|
||||
*algo = entry->algo;
|
||||
*name = entry->name;
|
||||
free(entry);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(pts_ima_event_list_t, destroy, void,
|
||||
private_pts_ima_event_list_t *this)
|
||||
{
|
||||
this->list->destroy_function(this->list, (void *)free_event_entry);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_ima_event_list_t* pts_ima_event_list_create(char *file)
|
||||
{
|
||||
private_pts_ima_event_list_t *this;
|
||||
event_entry_t *entry;
|
||||
uint32_t pcr, type_len, name_len, eventdata_len, algo_digest_len, algo_len;
|
||||
char type[IMA_TYPE_LEN_MAX];
|
||||
char algo_digest[IMA_ALGO_DIGEST_LEN_MAX];
|
||||
char *pos, *error = "";
|
||||
struct stat st;
|
||||
ssize_t res;
|
||||
bool ima_ng;
|
||||
int fd;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
DBG1(DBG_PTS, "opening '%s' failed: %s", file, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) == -1)
|
||||
{
|
||||
DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
|
||||
strerror(errno));
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_time = _get_time,
|
||||
.get_count = _get_count,
|
||||
.get_next = _get_next,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.creation_time = st.st_ctime,
|
||||
.list = linked_list_create(),
|
||||
);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
/* read 32 bit PCR number in host order */
|
||||
res = read(fd, &pcr, 4);
|
||||
|
||||
/* exit if no more measurement data is available */
|
||||
if (res == 0)
|
||||
{
|
||||
DBG2(DBG_PTS, "loaded ima measurements '%s' (%d entries)",
|
||||
file, this->list->get_count(this->list));
|
||||
close(fd);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/* create and initialize new IMA entry */
|
||||
entry = malloc_thing(event_entry_t);
|
||||
entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
|
||||
entry->algo = NULL;
|
||||
entry->name = NULL;
|
||||
|
||||
if (res != 4 || pcr != IMA_PCR)
|
||||
{
|
||||
error = "invalid IMA PCR field";
|
||||
break;
|
||||
}
|
||||
|
||||
/* read 20 byte SHA-1 measurement digest */
|
||||
if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
|
||||
{
|
||||
error = "invalid SHA-1 digest field";
|
||||
break;
|
||||
}
|
||||
|
||||
/* read 32 bit length of IMA type string in host order */
|
||||
if (read(fd, &type_len, 4) != 4 || type_len > IMA_TYPE_LEN_MAX)
|
||||
{
|
||||
error = "invalid IMA type field length";
|
||||
break;
|
||||
}
|
||||
|
||||
/* read and interpret IMA type string */
|
||||
if (read(fd, type, type_len) != type_len)
|
||||
{
|
||||
error = "invalid IMA type field";
|
||||
break;
|
||||
}
|
||||
if (type_len == IMA_NG_TYPE_LEN &&
|
||||
memeq(type, "ima-ng", IMA_NG_TYPE_LEN))
|
||||
{
|
||||
ima_ng = TRUE;
|
||||
}
|
||||
else if (type_len == IMA_TYPE_LEN &&
|
||||
memeq(type, "ima", IMA_TYPE_LEN))
|
||||
{
|
||||
ima_ng = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "unknown IMA type";
|
||||
break;
|
||||
}
|
||||
|
||||
if (ima_ng)
|
||||
{
|
||||
/* read the 32 bit length of the event data in host order */
|
||||
if (read(fd, &eventdata_len, 4) != 4 || eventdata_len < 4)
|
||||
{
|
||||
error = "invalid event data field length";
|
||||
break;
|
||||
}
|
||||
|
||||
/* read the 32 bit length of the algo_digest string in host order */
|
||||
if (read(fd, &algo_digest_len, 4) != 4 ||
|
||||
algo_digest_len > IMA_ALGO_DIGEST_LEN_MAX ||
|
||||
eventdata_len < 4 + algo_digest_len + 4)
|
||||
{
|
||||
error = "invalid digest_with_algo field length";
|
||||
break;
|
||||
}
|
||||
|
||||
/* read the IMA algo_digest string */
|
||||
if (read(fd, algo_digest, algo_digest_len) != algo_digest_len)
|
||||
{
|
||||
error = "invalid digest_with_algo field";
|
||||
break;
|
||||
}
|
||||
|
||||
/* extract the hash algorithm name */
|
||||
pos = memchr(algo_digest, '\0', algo_digest_len);
|
||||
if (!pos)
|
||||
{
|
||||
error = "no algo field";
|
||||
break;
|
||||
}
|
||||
algo_len = pos - algo_digest + 1;
|
||||
|
||||
if (algo_len > IMA_ALGO_LEN_MAX ||
|
||||
algo_len < IMA_ALGO_LEN_MIN || *(pos - 1) != ':')
|
||||
{
|
||||
error = "invalid algo field";
|
||||
break;
|
||||
}
|
||||
|
||||
/* copy and store the hash algorithm name */
|
||||
entry->algo = malloc(algo_len);
|
||||
memcpy(entry->algo, algo_digest, algo_len);
|
||||
|
||||
/* read the 32 bit length of the event name in host order */
|
||||
if (read(fd, &name_len, 4) != 4 ||
|
||||
eventdata_len != 4 + algo_digest_len + 4 + name_len)
|
||||
{
|
||||
error = "invalid filename field length";
|
||||
break;
|
||||
}
|
||||
|
||||
/* allocate memory for the file name */
|
||||
entry->name = malloc(name_len);
|
||||
|
||||
/* read file name */
|
||||
if (read(fd, entry->name, name_len) != name_len)
|
||||
{
|
||||
error = "invalid filename field";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip SHA-1 digest of the file content */
|
||||
if (lseek(fd, HASH_SIZE_SHA1, SEEK_CUR) == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* read the 32 bit length of the file name in host order */
|
||||
if (read(fd, &name_len, 4) != 4 || name_len == UINT32_MAX)
|
||||
{
|
||||
error = "invalid filename field length";
|
||||
break;
|
||||
}
|
||||
|
||||
/* allocate memory for the file name */
|
||||
entry->name = malloc(name_len + 1);
|
||||
|
||||
/* read file name */
|
||||
if (read(fd, entry->name, name_len) != name_len)
|
||||
{
|
||||
error = "invalid eventname field";
|
||||
break;
|
||||
}
|
||||
|
||||
/* terminate the file name with a nul character */
|
||||
entry->name[name_len] = '\0';
|
||||
}
|
||||
|
||||
this->list->insert_last(this->list, entry);
|
||||
}
|
||||
|
||||
DBG1(DBG_PTS, "loading ima measurements '%s' failed: %s", file, error);
|
||||
free_event_entry(entry);
|
||||
close(fd);
|
||||
destroy(this);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_ima_event_list pts_ima_event_list
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_IMA_EVENT_LIST_H_
|
||||
#define PTS_IMA_EVENT_LIST_H_
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct pts_ima_event_list_t pts_ima_event_list_t;
|
||||
|
||||
#define IMA_PCR 10
|
||||
#define IMA_ALGO_LEN_MIN 5
|
||||
#define IMA_ALGO_LEN_MAX 8
|
||||
|
||||
|
||||
/**
|
||||
* Class retrieving Linux IMA file measurements
|
||||
*
|
||||
*/
|
||||
struct pts_ima_event_list_t {
|
||||
|
||||
/**
|
||||
* Get the time the file measurements were taken
|
||||
*
|
||||
* @return Measurement time
|
||||
*/
|
||||
time_t (*get_time)(pts_ima_event_list_t *this);
|
||||
|
||||
/**
|
||||
* Get the number of non-processed file measurements
|
||||
*
|
||||
* @return Number of measurements left
|
||||
*/
|
||||
int (*get_count)(pts_ima_event_list_t *this);
|
||||
|
||||
/**
|
||||
* Get the next file measurement and remove it from the list
|
||||
*
|
||||
* @param measurement Measurement hash
|
||||
* @param algo Algorithm used to hash files
|
||||
" @param name Event name (absolute filename or boot_aggregate)
|
||||
* @return Return code
|
||||
*/
|
||||
status_t (*get_next)(pts_ima_event_list_t *this, chunk_t *measurement,
|
||||
char **algo, char **name);
|
||||
|
||||
/**
|
||||
* Destroys a pts_ima_event_list_t object.
|
||||
*/
|
||||
void (*destroy)(pts_ima_event_list_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a PTS IMA runtime file measurement object
|
||||
*
|
||||
* @param file Pathname pointing to the IMA runtme measurements
|
||||
*/
|
||||
pts_ima_event_list_t* pts_ima_event_list_create(char *file);
|
||||
|
||||
#endif /** PTS_IMA_EVENT_LIST_H_ @}*/
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_meas_algo.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
ENUM_BEGIN(pts_meas_algorithm_names, PTS_MEAS_ALGO_NONE, PTS_MEAS_ALGO_NONE,
|
||||
"None");
|
||||
ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA384, PTS_MEAS_ALGO_SHA384,
|
||||
PTS_MEAS_ALGO_NONE,
|
||||
"SHA384");
|
||||
ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA256, PTS_MEAS_ALGO_SHA256,
|
||||
PTS_MEAS_ALGO_SHA384,
|
||||
"SHA256");
|
||||
ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1, PTS_MEAS_ALGO_SHA1,
|
||||
PTS_MEAS_ALGO_SHA256,
|
||||
"SHA1");
|
||||
ENUM_END(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1);
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
hash_algorithm_t hash_alg;
|
||||
const char *plugin_name;
|
||||
char format1[] = " %s PTS measurement algorithm %N[%s] available";
|
||||
char format2[] = " %s PTS measurement algorithm %N not available";
|
||||
|
||||
*algorithms = 0;
|
||||
|
||||
enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
|
||||
while (enumerator->enumerate(enumerator, &hash_alg, &plugin_name))
|
||||
{
|
||||
if (hash_alg == HASH_SHA1)
|
||||
{
|
||||
*algorithms |= PTS_MEAS_ALGO_SHA1;
|
||||
DBG2(DBG_PTS, format1, "mandatory", hash_algorithm_names, hash_alg,
|
||||
plugin_name);
|
||||
}
|
||||
else if (hash_alg == HASH_SHA256)
|
||||
{
|
||||
*algorithms |= PTS_MEAS_ALGO_SHA256;
|
||||
DBG2(DBG_PTS, format1, "mandatory", hash_algorithm_names, hash_alg,
|
||||
plugin_name);
|
||||
}
|
||||
else if (hash_alg == HASH_SHA384)
|
||||
{
|
||||
*algorithms |= PTS_MEAS_ALGO_SHA384;
|
||||
DBG2(DBG_PTS, format1, "optional ", hash_algorithm_names, hash_alg,
|
||||
plugin_name);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (!(*algorithms & PTS_MEAS_ALGO_SHA384))
|
||||
{
|
||||
DBG1(DBG_PTS, format2, "optional ", hash_algorithm_names, HASH_SHA384);
|
||||
}
|
||||
if ((*algorithms & PTS_MEAS_ALGO_SHA1) &&
|
||||
(*algorithms & PTS_MEAS_ALGO_SHA256))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (!(*algorithms & PTS_MEAS_ALGO_SHA1))
|
||||
{
|
||||
DBG1(DBG_PTS, format2, "mandatory", hash_algorithm_names, HASH_SHA1);
|
||||
}
|
||||
if (!(*algorithms & PTS_MEAS_ALGO_SHA256))
|
||||
{
|
||||
DBG1(DBG_PTS, format2, "mandatory", hash_algorithm_names, HASH_SHA256);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
bool pts_meas_algo_update(char *hash_alg, pts_meas_algorithms_t *algorithms)
|
||||
{
|
||||
if (strcaseeq(hash_alg, "sha384") || strcaseeq(hash_alg, "sha2_384"))
|
||||
{
|
||||
/* nothing to update, all algorithms are supported */
|
||||
return TRUE;
|
||||
}
|
||||
if (strcaseeq(hash_alg, "sha256") || strcaseeq(hash_alg, "sha2_256"))
|
||||
{
|
||||
/* remove SHA384algorithm */
|
||||
*algorithms &= ~PTS_MEAS_ALGO_SHA384;
|
||||
return TRUE;
|
||||
}
|
||||
if (strcaseeq(hash_alg, "sha1"))
|
||||
{
|
||||
/* remove SHA384 and SHA256 algorithms */
|
||||
*algorithms &= ~(PTS_MEAS_ALGO_SHA384 | PTS_MEAS_ALGO_SHA256);
|
||||
return TRUE;
|
||||
}
|
||||
DBG1(DBG_PTS, "unknown hash algorithm '%s' configured", hash_alg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pts_meas_algorithms_t pts_meas_algo_select(pts_meas_algorithms_t supported_algos,
|
||||
pts_meas_algorithms_t offered_algos)
|
||||
{
|
||||
if ((supported_algos & PTS_MEAS_ALGO_SHA384) &&
|
||||
(offered_algos & PTS_MEAS_ALGO_SHA384))
|
||||
{
|
||||
return PTS_MEAS_ALGO_SHA384;
|
||||
}
|
||||
if ((supported_algos & PTS_MEAS_ALGO_SHA256) &&
|
||||
(offered_algos & PTS_MEAS_ALGO_SHA256))
|
||||
{
|
||||
return PTS_MEAS_ALGO_SHA256;
|
||||
}
|
||||
if ((supported_algos & PTS_MEAS_ALGO_SHA1) &&
|
||||
(offered_algos & PTS_MEAS_ALGO_SHA1))
|
||||
{
|
||||
return PTS_MEAS_ALGO_SHA1;
|
||||
}
|
||||
return PTS_MEAS_ALGO_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
hash_algorithm_t pts_meas_algo_to_hash(pts_meas_algorithms_t algorithm)
|
||||
{
|
||||
switch (algorithm)
|
||||
{
|
||||
case PTS_MEAS_ALGO_SHA1:
|
||||
return HASH_SHA1;
|
||||
case PTS_MEAS_ALGO_SHA256:
|
||||
return HASH_SHA256;
|
||||
case PTS_MEAS_ALGO_SHA384:
|
||||
return HASH_SHA384;
|
||||
default:
|
||||
return HASH_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
size_t pts_meas_algo_hash_size(pts_meas_algorithms_t algorithm)
|
||||
{
|
||||
switch (algorithm)
|
||||
{
|
||||
case PTS_MEAS_ALGO_SHA1:
|
||||
return HASH_SIZE_SHA1;
|
||||
case PTS_MEAS_ALGO_SHA256:
|
||||
return HASH_SIZE_SHA256;
|
||||
case PTS_MEAS_ALGO_SHA384:
|
||||
return HASH_SIZE_SHA384;
|
||||
case PTS_MEAS_ALGO_NONE:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_meas_algo pts_meas_algo
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_MEAS_ALGO_H_
|
||||
#define PTS_MEAS_ALGO_H_
|
||||
|
||||
#include <library.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
typedef enum pts_meas_algorithms_t pts_meas_algorithms_t;
|
||||
|
||||
/**
|
||||
* PTS Measurement Algorithms
|
||||
*/
|
||||
enum pts_meas_algorithms_t {
|
||||
PTS_MEAS_ALGO_NONE = 0,
|
||||
PTS_MEAS_ALGO_SHA384 = (1<<13),
|
||||
PTS_MEAS_ALGO_SHA256 = (1<<14),
|
||||
PTS_MEAS_ALGO_SHA1 = (1<<15)
|
||||
};
|
||||
|
||||
/**
|
||||
* enum name for pts_meas_algorithms_t.
|
||||
*/
|
||||
extern enum_name_t *pts_meas_algorithm_names;
|
||||
|
||||
/**
|
||||
* Diffie-Hellman Hash Algorithm Values
|
||||
* see section 3.8.5 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*
|
||||
* 1
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |1|2|3|R|R|R|R|R|R|R|R|R|R|R|R|R|
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Probe available PTS measurement algorithms
|
||||
*
|
||||
* @param algorithms set of available algorithms
|
||||
* @return TRUE if mandatory algorithms are available
|
||||
*/
|
||||
bool pts_meas_algo_probe(pts_meas_algorithms_t *algorithms);
|
||||
|
||||
/**
|
||||
* Update supported PTS measurement algorithms according to configuration
|
||||
*
|
||||
* sha1 : PTS_MEAS_ALGO_SHA1
|
||||
* sha256: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256
|
||||
* sha384: PTS_MEAS_ALGO_SHA1 | PTS_MEAS_ALGO_SHA256 | PTS_MEAS_ALGO_SHA384
|
||||
*
|
||||
* The PTS-IMC is expected to select the strongest supported algorithm
|
||||
*
|
||||
* @param hash_alg configured hash algorithm
|
||||
* @param algorithms returns set of available PTS measurement algorithms
|
||||
*/
|
||||
bool pts_meas_algo_update(char *hash_alg, pts_meas_algorithms_t *algorithms);
|
||||
|
||||
/**
|
||||
* Select the strongest PTS measurement algorithm
|
||||
* among a set of offered PTS measurement algorithms
|
||||
*
|
||||
* @param supported_algos set of supported PTS measurement algorithms
|
||||
* @param offered_algos set of offered PTS measurements algorithms
|
||||
* @return selected algorithm
|
||||
*/
|
||||
pts_meas_algorithms_t pts_meas_algo_select(pts_meas_algorithms_t supported_algos,
|
||||
pts_meas_algorithms_t offered_algos);
|
||||
|
||||
/**
|
||||
* Convert pts_meas_algorithms_t to hash_algorithm_t
|
||||
*
|
||||
* @param algorithm PTS measurement algorithm type
|
||||
* @return libstrongswan hash algorithm type
|
||||
*/
|
||||
hash_algorithm_t pts_meas_algo_to_hash(pts_meas_algorithms_t algorithm);
|
||||
|
||||
/**
|
||||
* Return the hash size of a pts_meas_algorithm
|
||||
*
|
||||
* @param algorithm PTS measurement algorithm type
|
||||
* @return hash size in bytes
|
||||
*/
|
||||
size_t pts_meas_algo_hash_size(pts_meas_algorithms_t algorithm);
|
||||
|
||||
#endif /** PTS_MEAS_ALGO_H_ @}*/
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "pts_pcr.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef struct private_pts_pcr_t private_pts_pcr_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_pcr_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_pcr_t {
|
||||
|
||||
/**
|
||||
* Public pts_pcr_t interface.
|
||||
*/
|
||||
pts_pcr_t public;
|
||||
|
||||
/**
|
||||
* Shadow PCR registers
|
||||
*/
|
||||
chunk_t pcrs[PTS_PCR_MAX_NUM];
|
||||
|
||||
/**
|
||||
* Number of extended PCR registers
|
||||
*/
|
||||
u_int32_t pcr_count;
|
||||
|
||||
/**
|
||||
* Highest extended PCR register
|
||||
*/
|
||||
u_int32_t pcr_max;
|
||||
|
||||
/**
|
||||
* Bitmap of extended PCR registers
|
||||
*/
|
||||
u_int8_t pcr_select[PTS_PCR_MAX_NUM / 8];
|
||||
|
||||
/**
|
||||
* Hasher used to extend shadow PCRs
|
||||
*/
|
||||
hasher_t *hasher;
|
||||
|
||||
};
|
||||
|
||||
METHOD(pts_pcr_t, get_count, u_int32_t,
|
||||
private_pts_pcr_t *this)
|
||||
{
|
||||
return this->pcr_count;
|
||||
}
|
||||
|
||||
METHOD(pts_pcr_t, select_pcr, bool,
|
||||
private_pts_pcr_t *this, u_int32_t pcr)
|
||||
{
|
||||
u_int32_t i, f;
|
||||
|
||||
if (pcr >= PTS_PCR_MAX_NUM)
|
||||
{
|
||||
DBG1(DBG_PTS, "PCR %2u: number is larger than maximum of %u",
|
||||
pcr, PTS_PCR_MAX_NUM-1);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Determine PCR selection flag */
|
||||
i = pcr / 8;
|
||||
f = 1 << (pcr - 8*i);
|
||||
|
||||
/* Has this PCR already been selected? */
|
||||
if (!(this->pcr_select[i] & f))
|
||||
{
|
||||
this->pcr_select[i] |= f;
|
||||
this->pcr_max = max(this->pcr_max, pcr);
|
||||
this->pcr_count++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(pts_pcr_t, get_selection_size, size_t,
|
||||
private_pts_pcr_t *this)
|
||||
{
|
||||
|
||||
/**
|
||||
* A TPM v1.2 has 24 PCR Registers so the bitmask field length
|
||||
* used by TrouSerS is at least 3 bytes
|
||||
*/
|
||||
return PTS_PCR_MAX_NUM / 8;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
/** implements enumerator_t */
|
||||
enumerator_t public;
|
||||
/** current PCR */
|
||||
u_int32_t pcr;
|
||||
/** back reference to parent */
|
||||
private_pts_pcr_t *pcrs;
|
||||
} pcr_enumerator_t;
|
||||
|
||||
/**
|
||||
* Implementation of enumerator.enumerate
|
||||
*/
|
||||
static bool pcr_enumerator_enumerate(pcr_enumerator_t *this, ...)
|
||||
{
|
||||
u_int32_t *pcr, i, f;
|
||||
va_list args;
|
||||
|
||||
va_start(args, this);
|
||||
pcr = va_arg(args, u_int32_t*);
|
||||
va_end(args);
|
||||
|
||||
while (this->pcr <= this->pcrs->pcr_max)
|
||||
{
|
||||
/* Determine PCR selection flag */
|
||||
i = this->pcr / 8;
|
||||
f = 1 << (this->pcr - 8*i);
|
||||
|
||||
/* Assign current PCR to output argument and increase */
|
||||
*pcr = this->pcr++;
|
||||
|
||||
/* return if PCR is selected */
|
||||
if (this->pcrs->pcr_select[i] & f)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(pts_pcr_t, create_enumerator, enumerator_t*,
|
||||
private_pts_pcr_t *this)
|
||||
{
|
||||
pcr_enumerator_t *enumerator;
|
||||
|
||||
INIT(enumerator,
|
||||
.public = {
|
||||
.enumerate = (void*)pcr_enumerator_enumerate,
|
||||
.destroy = (void*)free,
|
||||
},
|
||||
.pcrs = this,
|
||||
);
|
||||
|
||||
return (enumerator_t*)enumerator;
|
||||
}
|
||||
|
||||
METHOD(pts_pcr_t, get, chunk_t,
|
||||
private_pts_pcr_t *this, u_int32_t pcr)
|
||||
{
|
||||
return (pcr < PTS_PCR_MAX_NUM) ? this->pcrs[pcr] : chunk_empty;
|
||||
}
|
||||
|
||||
METHOD(pts_pcr_t, set, bool,
|
||||
private_pts_pcr_t *this, u_int32_t pcr, chunk_t value)
|
||||
{
|
||||
if (value.len != PTS_PCR_LEN)
|
||||
{
|
||||
DBG1(DBG_PTS, "PCR %2u: value does not fit", pcr);
|
||||
return FALSE;
|
||||
}
|
||||
if (select_pcr(this, pcr))
|
||||
{
|
||||
memcpy(this->pcrs[pcr].ptr, value.ptr, PTS_PCR_LEN);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(pts_pcr_t, extend, chunk_t,
|
||||
private_pts_pcr_t *this, u_int32_t pcr, chunk_t measurement)
|
||||
{
|
||||
if (measurement.len != PTS_PCR_LEN)
|
||||
{
|
||||
DBG1(DBG_PTS, "PCR %2u: measurement does not fit", pcr);
|
||||
return chunk_empty;
|
||||
}
|
||||
if (!select_pcr(this, pcr))
|
||||
{
|
||||
return chunk_empty;
|
||||
}
|
||||
if (!this->hasher->get_hash(this->hasher, this->pcrs[pcr] , NULL) ||
|
||||
!this->hasher->get_hash(this->hasher, measurement, this->pcrs[pcr].ptr))
|
||||
{
|
||||
DBG1(DBG_PTS, "PCR %2u: not extended due to hasher problem", pcr);
|
||||
return chunk_empty;
|
||||
}
|
||||
return this->pcrs[pcr];
|
||||
}
|
||||
|
||||
METHOD(pts_pcr_t, get_composite, chunk_t,
|
||||
private_pts_pcr_t *this)
|
||||
{
|
||||
chunk_t composite;
|
||||
enumerator_t *enumerator;
|
||||
u_int16_t selection_size;
|
||||
u_int32_t pcr_field_size, pcr;
|
||||
u_char *pos;
|
||||
|
||||
selection_size = get_selection_size(this);
|
||||
pcr_field_size = this->pcr_count * PTS_PCR_LEN;
|
||||
|
||||
composite = chunk_alloc(2 + selection_size + 4 + pcr_field_size);
|
||||
pos = composite.ptr;
|
||||
htoun16(pos, selection_size);
|
||||
pos += 2;
|
||||
memcpy(pos, this->pcr_select, selection_size);
|
||||
pos += selection_size;
|
||||
htoun32(pos, pcr_field_size);
|
||||
pos += 4;
|
||||
|
||||
enumerator = create_enumerator(this);
|
||||
while (enumerator->enumerate(enumerator, &pcr))
|
||||
{
|
||||
memcpy(pos, this->pcrs[pcr].ptr, PTS_PCR_LEN);
|
||||
pos += PTS_PCR_LEN;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
DBG3(DBG_PTS, "constructed PCR Composite: %B", &composite);
|
||||
return composite;
|
||||
}
|
||||
|
||||
METHOD(pts_pcr_t, destroy, void,
|
||||
private_pts_pcr_t *this)
|
||||
{
|
||||
u_int32_t i;
|
||||
|
||||
for (i = 0; i < PTS_PCR_MAX_NUM; i++)
|
||||
{
|
||||
free(this->pcrs[i].ptr);
|
||||
}
|
||||
this->hasher->destroy(this->hasher);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_pcr_t *pts_pcr_create(void)
|
||||
{
|
||||
private_pts_pcr_t *this;
|
||||
hasher_t *hasher;
|
||||
u_int32_t i;
|
||||
|
||||
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
||||
if (!hasher)
|
||||
{
|
||||
DBG1(DBG_PTS, "%N hasher could not be created",
|
||||
hash_algorithm_short_names, HASH_SHA1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_count = _get_count,
|
||||
.select_pcr = _select_pcr,
|
||||
.get_selection_size = _get_selection_size,
|
||||
.create_enumerator = _create_enumerator,
|
||||
.get = _get,
|
||||
.set = _set,
|
||||
.extend = _extend,
|
||||
.get_composite = _get_composite,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.hasher = hasher,
|
||||
);
|
||||
|
||||
for (i = 0; i < PTS_PCR_MAX_NUM; i++)
|
||||
{
|
||||
this->pcrs[i] = chunk_alloc(PTS_PCR_LEN);
|
||||
memset(this->pcrs[i].ptr, 0x00, PTS_PCR_LEN);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_pcr pts_pcr
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_PCR_H_
|
||||
#define PTS_PCR_H_
|
||||
|
||||
typedef struct pts_pcr_t pts_pcr_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* Maximum number of PCR's of TPM, TPM Spec 1.2
|
||||
*/
|
||||
#define PTS_PCR_MAX_NUM 24
|
||||
|
||||
/**
|
||||
* Number of bytes that can be saved in a PCR of TPM, TPM Spec 1.2
|
||||
*/
|
||||
#define PTS_PCR_LEN 20
|
||||
|
||||
/**
|
||||
* Class implementing a shadow PCR register set
|
||||
*/
|
||||
struct pts_pcr_t {
|
||||
|
||||
/**
|
||||
* Get the number of selected PCRs
|
||||
*
|
||||
* @return number of selected PCRs
|
||||
*/
|
||||
u_int32_t (*get_count)(pts_pcr_t *this);
|
||||
|
||||
/**
|
||||
* Mark a PCR as selected
|
||||
*
|
||||
* @param pcr index of PCR
|
||||
* @return TRUE if PCR index exists
|
||||
*/
|
||||
bool (*select_pcr)(pts_pcr_t *this, u_int32_t pcr);
|
||||
|
||||
/**
|
||||
* Get the size of the selection field in bytes
|
||||
*
|
||||
* @return number of bytes written
|
||||
*/
|
||||
size_t (*get_selection_size)(pts_pcr_t *this);
|
||||
|
||||
/**
|
||||
* Create an enumerator over all selected PCR indexes
|
||||
*
|
||||
* @return enumerator
|
||||
*/
|
||||
enumerator_t* (*create_enumerator)(pts_pcr_t *this);
|
||||
|
||||
/**
|
||||
* Get the current content of a PCR
|
||||
*
|
||||
* @param pcr index of PCR
|
||||
* @return content of PCR
|
||||
*/
|
||||
chunk_t (*get)(pts_pcr_t *this, u_int32_t pcr);
|
||||
|
||||
/**
|
||||
* Set the content of a PCR
|
||||
*
|
||||
* @param pcr index of PCR
|
||||
* @param value new value of PCR
|
||||
* @return TRUE if value could be set
|
||||
*/
|
||||
bool (*set)(pts_pcr_t *this, u_int32_t pcr, chunk_t value);
|
||||
|
||||
/**
|
||||
* Extend the content of a PCR
|
||||
*
|
||||
* @param pcr index of PCR
|
||||
* @param measurement measurment value to be extended into PCR
|
||||
* @return new content of PCR
|
||||
*/
|
||||
chunk_t (*extend)(pts_pcr_t *this, u_int32_t pcr, chunk_t measurement);
|
||||
|
||||
/**
|
||||
* Create a PCR Composite object over all selected PCRs
|
||||
*
|
||||
* @return PCR Composite object (must be freed)
|
||||
*/
|
||||
chunk_t (*get_composite)(pts_pcr_t *this);
|
||||
|
||||
/**
|
||||
|
||||
* Destroys a pts_pcr_t object.
|
||||
*/
|
||||
void (*destroy)(pts_pcr_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an pts_pcr_t object
|
||||
*/
|
||||
pts_pcr_t* pts_pcr_create(void);
|
||||
|
||||
#endif /** PTS_PCR_H_ @}*/
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_proto_caps pts_proto_caps
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_PROTO_CAPS_H_
|
||||
#define PTS_PROTO_CAPS_H_
|
||||
|
||||
typedef enum pts_proto_caps_flag_t pts_proto_caps_flag_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* PTS Protocol Capabilities Flags
|
||||
*/
|
||||
enum pts_proto_caps_flag_t {
|
||||
/** XML based Evidence Support flag */
|
||||
PTS_PROTO_CAPS_X = (1<<0),
|
||||
/** Trusted Platform Evidence flag */
|
||||
PTS_PROTO_CAPS_T = (1<<1),
|
||||
/** DH Nonce Negotiation Support flag */
|
||||
PTS_PROTO_CAPS_D = (1<<2),
|
||||
/** Verification Support flag */
|
||||
PTS_PROTO_CAPS_V = (1<<3),
|
||||
/** Current (In-Memory) Evidence Support flag */
|
||||
PTS_PROTO_CAPS_C = (1<<4),
|
||||
};
|
||||
|
||||
#endif /** PTS_PROTO_CAPS_H_ @}*/
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_req_func_comp_evid pts_req_func_comp_evid
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_REQ_FUNC_COMP_EVID_H_
|
||||
#define PTS_REQ_FUNC_COMP_EVID_H_
|
||||
|
||||
typedef enum pts_req_func_comp_evid_t pts_req_func_comp_evid_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* PTS Request Functional Component Evidence Flags
|
||||
*/
|
||||
enum pts_req_func_comp_evid_t {
|
||||
/** Transitive Trust Chain flag */
|
||||
PTS_REQ_FUNC_COMP_EVID_TTC = (1<<7),
|
||||
/** Verify Component flag */
|
||||
PTS_REQ_FUNC_COMP_EVID_VER = (1<<6),
|
||||
/** Current Evidence flag */
|
||||
PTS_REQ_FUNC_COMP_EVID_CURR = (1<<5),
|
||||
/** PCR Information flag */
|
||||
PTS_REQ_FUNC_COMP_EVID_PCR = (1<<4),
|
||||
};
|
||||
|
||||
#endif /** PTS_FUNCT_COMP_EVID_REQ_H_ @}*/
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 pts_simple_evid_final pts_rsimple_evid_final
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_SIMPLE_EVID_FINAL_H_
|
||||
#define PTS_SIMPLE_EVID_FINAL_H_
|
||||
|
||||
typedef enum pts_simple_evid_final_flag_t pts_simple_evid_final_flag_t;
|
||||
|
||||
#include <library.h>
|
||||
|
||||
/**
|
||||
* PTS Simple Evidence Final Flags
|
||||
*/
|
||||
enum pts_simple_evid_final_flag_t {
|
||||
/** TPM PCR Composite and TPM Quote Signature not included */
|
||||
PTS_SIMPLE_EVID_FINAL_NO = 0x00,
|
||||
/** TPM PCR Composite and TPM Quote Signature included
|
||||
* using TPM_QUOTE_INFO */
|
||||
PTS_SIMPLE_EVID_FINAL_QUOTE_INFO = 0x40,
|
||||
/** TPM PCR Composite and TPM Quote Signature included
|
||||
* using TPM_QUOTE_INFO2, TPM_CAP_VERSION_INFO not appended */
|
||||
PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2 = 0x80,
|
||||
/** TPM PCR Composite and TPM Quote Signature included
|
||||
* using TPM_QUOTE_INFO2, TPM_CAP_VERSION_INFO appended */
|
||||
PTS_SIMPLE_EVID_FINAL_QUOTE_INFO2_CAP_VER = 0xC0,
|
||||
/** Evidence Signature included */
|
||||
PTS_SIMPLE_EVID_FINAL_EVID_SIG = 0x20,
|
||||
};
|
||||
|
||||
#endif /** PTS_SIMPLE_EVID_FINAL_H_ @}*/
|
||||
@@ -15,14 +15,13 @@
|
||||
|
||||
#include "seg_contract.h"
|
||||
#include "seg_env.h"
|
||||
#include "tcg/seg/tcg_seg_attr_seg_env.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <bio/bio_writer.h>
|
||||
|
||||
#include <tncif_pa_subtypes.h>
|
||||
|
||||
#include <tcg/seg/tcg_seg_attr_seg_env.h>
|
||||
|
||||
typedef struct private_seg_contract_t private_seg_contract_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,13 +17,12 @@
|
||||
|
||||
#include "imcv.h"
|
||||
#include "pa_tnc/pa_tnc_msg.h"
|
||||
#include "tcg/seg/tcg_seg_attr_seg_env.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
#include <bio/bio_reader.h>
|
||||
#include <bio/bio_writer.h>
|
||||
|
||||
#include <tcg/seg/tcg_seg_attr_seg_env.h>
|
||||
|
||||
#define BASE_ATTR_ID_PREFIX 0xFF
|
||||
|
||||
typedef struct private_seg_env_t private_seg_env_t;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "swid_error.h"
|
||||
|
||||
#include <bio/bio_writer.h>
|
||||
#include <ietf/ietf_attr_pa_tnc_error.h>
|
||||
|
||||
ENUM(swid_error_code_names, TCG_SWID_ERROR, TCG_SWID_RESPONSE_TOO_LARGE,
|
||||
"SWID Error",
|
||||
"SWID Subscription Denied",
|
||||
"SWID Response Too Large"
|
||||
);
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request_id,
|
||||
u_int32_t max_attr_size, char *description)
|
||||
{
|
||||
bio_writer_t *writer;
|
||||
chunk_t msg_info;
|
||||
pa_tnc_attr_t *attr;
|
||||
pen_type_t error_code;
|
||||
|
||||
error_code = pen_type_create( PEN_TCG, code);
|
||||
writer = bio_writer_create(4);
|
||||
writer->write_uint32(writer, request_id);
|
||||
if (code == TCG_SWID_RESPONSE_TOO_LARGE)
|
||||
{
|
||||
writer->write_uint32(writer, max_attr_size);
|
||||
}
|
||||
if (description)
|
||||
{
|
||||
writer->write_data(writer, chunk_from_str(description));
|
||||
}
|
||||
msg_info = writer->get_buf(writer);
|
||||
attr = ietf_attr_pa_tnc_error_create(error_code, msg_info);
|
||||
writer->destroy(writer);
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 swid_error swid_error
|
||||
* @{ @ingroup swid
|
||||
*/
|
||||
|
||||
#ifndef SWID_ERROR_H_
|
||||
#define SWID_ERROR_H_
|
||||
|
||||
typedef enum swid_error_code_t swid_error_code_t;
|
||||
|
||||
#include "pa_tnc/pa_tnc_attr.h"
|
||||
|
||||
#include <library.h>
|
||||
|
||||
|
||||
/**
|
||||
* SWID Error Codes
|
||||
* see section 3.14.2 of PTS Protocol: Binding to TNC IF-M Specification
|
||||
*/
|
||||
enum swid_error_code_t {
|
||||
TCG_SWID_ERROR = 0x20,
|
||||
TCG_SWID_SUBSCRIPTION_DENIED = 0x21,
|
||||
TCG_SWID_RESPONSE_TOO_LARGE = 0x22
|
||||
};
|
||||
|
||||
/**
|
||||
* enum name for swid_error_code_t.
|
||||
*/
|
||||
extern enum_name_t *swid_error_code_names;
|
||||
|
||||
/**
|
||||
* Creates a SWID Error Attribute
|
||||
* see section 4.12 of TNC SWID Message and Attributes for IF-M
|
||||
*
|
||||
* @param code SWID error code
|
||||
* @param request SWID request ID
|
||||
* @param max_attr_size Maximum IF-M attribute size (if applicable)
|
||||
* @param description Optional description string or NULL
|
||||
*/
|
||||
pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request,
|
||||
u_int32_t max_attr_size, char *description);
|
||||
|
||||
#endif /** SWID_ERROR_H_ @}*/
|
||||
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "swid_inventory.h"
|
||||
#include "swid_tag.h"
|
||||
#include "swid_tag_id.h"
|
||||
|
||||
#include <collections/linked_list.h>
|
||||
#include <bio/bio_writer.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
|
||||
typedef struct private_swid_inventory_t private_swid_inventory_t;
|
||||
|
||||
/**
|
||||
* Private data of a swid_inventory_t object.
|
||||
*
|
||||
*/
|
||||
struct private_swid_inventory_t {
|
||||
|
||||
/**
|
||||
* Public swid_inventory_t interface.
|
||||
*/
|
||||
swid_inventory_t public;
|
||||
|
||||
/**
|
||||
* Full SWID tags or just SWID tag IDs
|
||||
*/
|
||||
bool full_tags;
|
||||
|
||||
/**
|
||||
* List of SWID tags or tag IDs
|
||||
*/
|
||||
linked_list_t *list;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read SWID tags issued by the swid_generator tool
|
||||
*/
|
||||
static status_t read_swid_tags(private_swid_inventory_t *this, FILE *file)
|
||||
{
|
||||
swid_tag_t *tag;
|
||||
bio_writer_t *writer;
|
||||
chunk_t tag_encoding, tag_file_path = chunk_empty;
|
||||
bool more_tags = TRUE, last_newline, end_of_tag;
|
||||
char line[8192];
|
||||
size_t len;
|
||||
|
||||
while (more_tags)
|
||||
{
|
||||
last_newline = TRUE;
|
||||
end_of_tag = FALSE;
|
||||
writer = bio_writer_create(512);
|
||||
do
|
||||
{
|
||||
if (!fgets(line, sizeof(line), file))
|
||||
{
|
||||
more_tags = FALSE;
|
||||
end_of_tag = TRUE;
|
||||
break;
|
||||
}
|
||||
len = strlen(line);
|
||||
|
||||
if (last_newline && line[0] == '\n')
|
||||
{
|
||||
end_of_tag = TRUE;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_newline = (line[len-1] == '\n');
|
||||
writer->write_data(writer, chunk_create(line, len));
|
||||
}
|
||||
}
|
||||
while (!end_of_tag);
|
||||
|
||||
tag_encoding = writer->get_buf(writer);
|
||||
|
||||
if (tag_encoding.len > 1)
|
||||
{
|
||||
/* remove trailing newline if present */
|
||||
if (tag_encoding.ptr[tag_encoding.len - 1] == '\n')
|
||||
{
|
||||
tag_encoding.len--;
|
||||
}
|
||||
DBG3(DBG_IMC, " %.*s", tag_encoding.len, tag_encoding.ptr);
|
||||
|
||||
tag = swid_tag_create(tag_encoding, tag_file_path);
|
||||
this->list->insert_last(this->list, tag);
|
||||
}
|
||||
writer->destroy(writer);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read SWID tag or software IDs issued by the swid_generator tool
|
||||
*/
|
||||
static status_t read_swid_tag_ids(private_swid_inventory_t *this, FILE *file)
|
||||
{
|
||||
swid_tag_id_t *tag_id;
|
||||
chunk_t tag_creator, unique_sw_id, tag_file_path = chunk_empty;
|
||||
char line[BUF_LEN];
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
char *separator;
|
||||
size_t len;
|
||||
|
||||
if (!fgets(line, sizeof(line), file))
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
len = strlen(line);
|
||||
|
||||
/* remove trailing newline if present */
|
||||
if (len > 0 && line[len - 1] == '\n')
|
||||
{
|
||||
len--;
|
||||
}
|
||||
DBG3(DBG_IMC, " %.*s", len, line);
|
||||
|
||||
separator = strchr(line, '_');
|
||||
if (!separator)
|
||||
{
|
||||
DBG1(DBG_IMC, "separation of regid from unique software ID failed");
|
||||
return FAILED;
|
||||
}
|
||||
tag_creator = chunk_create(line, separator - line);
|
||||
separator++;
|
||||
|
||||
unique_sw_id = chunk_create(separator, len - (separator - line));
|
||||
tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
|
||||
this->list->insert_last(this->list, tag_id);
|
||||
}
|
||||
}
|
||||
|
||||
static status_t generate_tags(private_swid_inventory_t *this, char *generator,
|
||||
swid_inventory_t *targets, bool pretty, bool full)
|
||||
{
|
||||
FILE *file;
|
||||
char command[BUF_LEN];
|
||||
char doc_separator[] = "'\n\n'";
|
||||
|
||||
status_t status = SUCCESS;
|
||||
|
||||
if (targets->get_count(targets) == 0)
|
||||
{
|
||||
/* Assemble the SWID generator command */
|
||||
if (this->full_tags)
|
||||
{
|
||||
snprintf(command, BUF_LEN, "%s swid --doc-separator %s%s%s",
|
||||
generator, doc_separator, pretty ? " --pretty" : "",
|
||||
full ? " --full" : "");
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(command, BUF_LEN, "%s software-id", generator);
|
||||
}
|
||||
|
||||
/* Open a pipe stream for reading the SWID generator output */
|
||||
file = popen(command, "r");
|
||||
if (!file)
|
||||
{
|
||||
DBG1(DBG_IMC, "failed to run swid_generator command");
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (this->full_tags)
|
||||
{
|
||||
DBG2(DBG_IMC, "SWID tag generation by package manager");
|
||||
status = read_swid_tags(this, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG2(DBG_IMC, "SWID tag ID generation by package manager");
|
||||
status = read_swid_tag_ids(this, file);
|
||||
}
|
||||
pclose(file);
|
||||
}
|
||||
else if (this->full_tags)
|
||||
{
|
||||
swid_tag_id_t *tag_id;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
enumerator = targets->create_enumerator(targets);
|
||||
while (enumerator->enumerate(enumerator, &tag_id))
|
||||
{
|
||||
char software_id[BUF_LEN];
|
||||
chunk_t tag_creator, unique_sw_id;
|
||||
|
||||
tag_creator = tag_id->get_tag_creator(tag_id);
|
||||
unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
|
||||
snprintf(software_id, BUF_LEN, "%.*s_%.*s",
|
||||
tag_creator.len, tag_creator.ptr,
|
||||
unique_sw_id.len, unique_sw_id.ptr);
|
||||
|
||||
/* Assemble the SWID generator command */
|
||||
snprintf(command, BUF_LEN, "%s swid --software-id %s%s%s",
|
||||
generator, software_id, pretty ? " --pretty" : "",
|
||||
full ? " --full" : "");
|
||||
|
||||
/* Open a pipe stream for reading the SWID generator output */
|
||||
file = popen(command, "r");
|
||||
if (!file)
|
||||
{
|
||||
DBG1(DBG_IMC, "failed to run swid_generator command");
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
status = read_swid_tags(this, file);
|
||||
pclose(file);
|
||||
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static bool collect_tags(private_swid_inventory_t *this, char *pathname,
|
||||
swid_inventory_t *targets)
|
||||
{
|
||||
char *rel_name, *abs_name;
|
||||
struct stat st;
|
||||
bool success = FALSE;
|
||||
enumerator_t *enumerator;
|
||||
|
||||
enumerator = enumerator_create_directory(pathname);
|
||||
if (!enumerator)
|
||||
{
|
||||
DBG1(DBG_IMC, "directory '%s' can not be opened, %s",
|
||||
pathname, strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
DBG2(DBG_IMC, "entering %s", pathname);
|
||||
|
||||
while (enumerator->enumerate(enumerator, &rel_name, &abs_name, &st))
|
||||
{
|
||||
char * start, *stop;
|
||||
chunk_t tag_creator;
|
||||
chunk_t unique_sw_id = chunk_empty, tag_file_path = chunk_empty;
|
||||
|
||||
if (!strstr(rel_name, "regid."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
/* In case of a targeted request */
|
||||
if (targets->get_count(targets))
|
||||
{
|
||||
enumerator_t *target_enumerator;
|
||||
swid_tag_id_t *tag_id;
|
||||
bool match = FALSE;
|
||||
|
||||
target_enumerator = targets->create_enumerator(targets);
|
||||
while (target_enumerator->enumerate(target_enumerator, &tag_id))
|
||||
{
|
||||
if (chunk_equals(tag_id->get_tag_creator(tag_id),
|
||||
chunk_from_str(rel_name)))
|
||||
{
|
||||
match = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
target_enumerator->destroy(target_enumerator);
|
||||
|
||||
if (!match)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!collect_tags(this, abs_name, targets))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* parse the regid filename into its components */
|
||||
start = rel_name;
|
||||
stop = strchr(start, '_');
|
||||
if (!stop)
|
||||
{
|
||||
DBG1(DBG_IMC, " %s", rel_name);
|
||||
DBG1(DBG_IMC, " '_' separator not found");
|
||||
goto end;
|
||||
}
|
||||
tag_creator = chunk_create(start, stop-start);
|
||||
start = stop + 1;
|
||||
|
||||
stop = strstr(start, ".swidtag");
|
||||
if (!stop)
|
||||
{
|
||||
DBG1(DBG_IMC, " %s", rel_name);
|
||||
DBG1(DBG_IMC, " swidtag postfix not found");
|
||||
goto end;
|
||||
}
|
||||
unique_sw_id = chunk_create(start, stop-start);
|
||||
tag_file_path = chunk_from_str(abs_name);
|
||||
|
||||
/* In case of a targeted request */
|
||||
if (targets->get_count(targets))
|
||||
{
|
||||
chunk_t target_unique_sw_id, target_tag_creator;
|
||||
enumerator_t *target_enumerator;
|
||||
swid_tag_id_t *tag_id;
|
||||
bool match = FALSE;
|
||||
|
||||
target_enumerator = targets->create_enumerator(targets);
|
||||
while (target_enumerator->enumerate(target_enumerator, &tag_id))
|
||||
{
|
||||
target_unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
|
||||
target_tag_creator = tag_id->get_tag_creator(tag_id);
|
||||
|
||||
if (chunk_equals(target_unique_sw_id, unique_sw_id) &&
|
||||
chunk_equals(target_tag_creator, tag_creator))
|
||||
{
|
||||
match = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
target_enumerator->destroy(target_enumerator);
|
||||
|
||||
if (!match)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
DBG2(DBG_IMC, " %s", rel_name);
|
||||
|
||||
if (this->full_tags)
|
||||
{
|
||||
swid_tag_t *tag;
|
||||
chunk_t *xml_tag;
|
||||
|
||||
xml_tag = chunk_map(abs_name, FALSE);
|
||||
if (!xml_tag)
|
||||
{
|
||||
DBG1(DBG_IMC, " opening '%s' failed: %s", abs_name,
|
||||
strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
|
||||
tag = swid_tag_create(*xml_tag, tag_file_path);
|
||||
this->list->insert_last(this->list, tag);
|
||||
chunk_unmap(xml_tag);
|
||||
}
|
||||
else
|
||||
{
|
||||
swid_tag_id_t *tag_id;
|
||||
|
||||
tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
|
||||
this->list->insert_last(this->list, tag_id);
|
||||
}
|
||||
}
|
||||
success = TRUE;
|
||||
|
||||
end:
|
||||
enumerator->destroy(enumerator);
|
||||
DBG2(DBG_IMC, "leaving %s", pathname);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, collect, bool,
|
||||
private_swid_inventory_t *this, char *directory, char *generator,
|
||||
swid_inventory_t *targets, bool pretty, bool full)
|
||||
{
|
||||
/**
|
||||
* Tags are generated by a package manager
|
||||
*/
|
||||
generate_tags(this, generator, targets, pretty, full);
|
||||
|
||||
/**
|
||||
* Collect swidtag files by iteratively entering all directories in
|
||||
* the tree under the "directory" path.
|
||||
*/
|
||||
return collect_tags(this, directory, targets);
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, add, void,
|
||||
private_swid_inventory_t *this, void *item)
|
||||
{
|
||||
this->list->insert_last(this->list, item);
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, get_count, int,
|
||||
private_swid_inventory_t *this)
|
||||
{
|
||||
return this->list->get_count(this->list);
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, create_enumerator, enumerator_t*,
|
||||
private_swid_inventory_t *this)
|
||||
{
|
||||
return this->list->create_enumerator(this->list);
|
||||
}
|
||||
|
||||
METHOD(swid_inventory_t, destroy, void,
|
||||
private_swid_inventory_t *this)
|
||||
{
|
||||
if (this->full_tags)
|
||||
{
|
||||
this->list->destroy_offset(this->list, offsetof(swid_tag_t, destroy));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->list->destroy_offset(this->list, offsetof(swid_tag_id_t, destroy));
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
swid_inventory_t *swid_inventory_create(bool full_tags)
|
||||
{
|
||||
private_swid_inventory_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.collect = _collect,
|
||||
.add = _add,
|
||||
.get_count = _get_count,
|
||||
.create_enumerator = _create_enumerator,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.full_tags = full_tags,
|
||||
.list = linked_list_create(),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Andreas Steffen
|
||||
* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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 swid_inventory swid_inventory
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef SWID_INVENTORY_H_
|
||||
#define SWID_INVENTORY_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct swid_inventory_t swid_inventory_t;
|
||||
|
||||
/**
|
||||
* Class managing SWID tag inventory
|
||||
*/
|
||||
struct swid_inventory_t {
|
||||
|
||||
/**
|
||||
* Collect the SWID tags stored on the endpoint
|
||||
*
|
||||
* @param directory SWID directory path
|
||||
* @param generator Path to SWID generator
|
||||
* @param targets List of target tag IDs
|
||||
* @param pretty Generate indented XML SWID tags
|
||||
* @param full Include file information in SWID tags
|
||||
* @return TRUE if successful
|
||||
*/
|
||||
bool (*collect)(swid_inventory_t *this, char *directory, char *generator,
|
||||
swid_inventory_t *targets, bool pretty, bool full);
|
||||
|
||||
/**
|
||||
* Collect the SWID tags stored on the endpoint
|
||||
*
|
||||
* @param item SWID tag or tag ID to be added
|
||||
*/
|
||||
void (*add)(swid_inventory_t *this, void *item);
|
||||
|
||||
/**
|
||||
* Get the number of collected SWID tags
|
||||
*
|
||||
* @return Number of collected SWID tags
|
||||
*/
|
||||
int (*get_count)(swid_inventory_t *this);
|
||||
|
||||
/**
|
||||
* Create a SWID tag inventory enumerator
|
||||
*
|
||||
* @return Enumerator returning either tag ID or full tag
|
||||
*/
|
||||
enumerator_t* (*create_enumerator)(swid_inventory_t *this);
|
||||
|
||||
/**
|
||||
* Destroys a swid_inventory_t object.
|
||||
*/
|
||||
void (*destroy)(swid_inventory_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a swid_inventory_t object
|
||||
*
|
||||
* @param full_tags TRUE if full tags, FALSE if tag IDs only
|
||||
*/
|
||||
swid_inventory_t* swid_inventory_create(bool full_tags);
|
||||
|
||||
#endif /** SWID_INVENTORY_H_ @}*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user