summaryrefslogtreecommitdiff
path: root/src/libpts
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2014-07-11 07:23:31 +0200
committerYves-Alexis Perez <corsac@debian.org>2014-07-11 07:23:31 +0200
commit81c63b0eed39432878f78727f60a1e7499645199 (patch)
tree82387d8fecd1c20788fd8bd784a9b0bde091fb6b /src/libpts
parentc5ebfc7b9c16551fe825dc1d79c3f7e2f096f6c9 (diff)
downloadvyos-strongswan-81c63b0eed39432878f78727f60a1e7499645199.tar.gz
vyos-strongswan-81c63b0eed39432878f78727f60a1e7499645199.zip
Imported Upstream version 5.2.0
Diffstat (limited to 'src/libpts')
-rw-r--r--src/libpts/Android.mk78
-rw-r--r--src/libpts/Makefile.am8
-rw-r--r--src/libpts/Makefile.in39
-rw-r--r--src/libpts/plugins/imc_attestation/Makefile.am2
-rw-r--r--src/libpts/plugins/imc_attestation/Makefile.in8
-rw-r--r--src/libpts/plugins/imc_attestation/imc_attestation.c54
-rw-r--r--src/libpts/plugins/imc_swid/Makefile.am2
-rw-r--r--src/libpts/plugins/imc_swid/Makefile.in8
-rw-r--r--src/libpts/plugins/imc_swid/imc_swid.c208
-rw-r--r--src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in40
-rw-r--r--src/libpts/plugins/imv_attestation/Makefile.am2
-rw-r--r--src/libpts/plugins/imv_attestation/Makefile.in8
-rw-r--r--src/libpts/plugins/imv_attestation/attest.c57
-rw-r--r--src/libpts/plugins/imv_attestation/attest_db.c207
-rw-r--r--src/libpts/plugins/imv_attestation/attest_db.h10
-rwxr-xr-xsrc/libpts/plugins/imv_attestation/build-database.sh293
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_agent.c230
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_build.c14
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_process.c93
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_state.c68
-rw-r--r--src/libpts/plugins/imv_attestation/imv_attestation_state.h26
-rw-r--r--src/libpts/plugins/imv_swid/Makefile.am8
-rw-r--r--src/libpts/plugins/imv_swid/Makefile.in17
-rw-r--r--src/libpts/plugins/imv_swid/imv_swid_agent.c359
-rw-r--r--src/libpts/plugins/imv_swid/imv_swid_rest.c122
-rw-r--r--src/libpts/plugins/imv_swid/imv_swid_rest.h63
-rw-r--r--src/libpts/plugins/imv_swid/imv_swid_state.c172
-rw-r--r--src/libpts/plugins/imv_swid/imv_swid_state.h63
-rw-r--r--src/libpts/pts/components/ita/ita_comp_ima.c694
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tboot.c95
-rw-r--r--src/libpts/pts/components/ita/ita_comp_tgrub.c7
-rw-r--r--src/libpts/pts/components/pts_component.h5
-rw-r--r--src/libpts/pts/pts.c152
-rw-r--r--src/libpts/pts/pts.h22
-rw-r--r--src/libpts/pts/pts_database.c172
-rw-r--r--src/libpts/pts/pts_database.h62
-rw-r--r--src/libpts/pts/pts_file_meas.c117
-rw-r--r--src/libpts/pts/pts_file_meas.h5
-rw-r--r--src/libpts/pts/pts_ima_bios_list.c294
-rw-r--r--src/libpts/pts/pts_ima_bios_list.h74
-rw-r--r--src/libpts/pts/pts_ima_event_list.c330
-rw-r--r--src/libpts/pts/pts_ima_event_list.h80
-rw-r--r--src/libpts/pts/pts_meas_algo.c7
-rw-r--r--src/libpts/pts/pts_meas_algo.h4
-rw-r--r--src/libpts/swid/swid_error.c2
-rw-r--r--src/libpts/swid/swid_inventory.c238
-rw-r--r--src/libpts/swid/swid_inventory.h9
-rw-r--r--src/libpts/swid/swid_tag.c40
-rw-r--r--src/libpts/swid/swid_tag.h19
-rw-r--r--src/libpts/swid/swid_tag_id.c42
-rw-r--r--src/libpts/swid/swid_tag_id.h19
-rw-r--r--src/libpts/tcg/swid/tcg_swid_attr_req.c7
-rw-r--r--src/libpts/tcg/swid/tcg_swid_attr_req.h4
-rw-r--r--src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c66
-rw-r--r--src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h25
-rw-r--r--src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c60
-rw-r--r--src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h24
57 files changed, 3308 insertions, 1626 deletions
diff --git a/src/libpts/Android.mk b/src/libpts/Android.mk
new file mode 100644
index 000000000..ce328c52c
--- /dev/null
+++ b/src/libpts/Android.mk
@@ -0,0 +1,78 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+libpts_la_SOURCES := \
+ libpts.h libpts.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 \
+ 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,$(libpts_la_SOURCES))
+
+# build libpts -----------------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+ $(strongswan_PATH)/src/libtncif \
+ $(strongswan_PATH)/src/libimcv \
+ $(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS)
+
+LOCAL_MODULE := libpts
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SHARED_LIBRARIES += libstrongswan libimcv
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/src/libpts/Makefile.am b/src/libpts/Makefile.am
index 48bb46c7a..ea685d837 100644
--- a/src/libpts/Makefile.am
+++ b/src/libpts/Makefile.am
@@ -13,6 +13,10 @@ libpts_la_LIBADD = \
$(top_builddir)/src/libtncif/libtncif.la \
$(top_builddir)/src/libimcv/libimcv.la
+if USE_WINDOWS
+ libpts_la_LIBADD += -lws2_32
+endif
+
if USE_TROUSERS
libpts_la_LIBADD += -ltspi
endif
@@ -31,6 +35,8 @@ libpts_la_SOURCES = \
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 \
@@ -67,6 +73,8 @@ libpts_la_SOURCES = \
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
+EXTRA_DIST = Android.mk
+
SUBDIRS = .
if USE_IMC_ATTESTATION
diff --git a/src/libpts/Makefile.in b/src/libpts/Makefile.in
index af5eafd7f..405b5f7ce 100644
--- a/src/libpts/Makefile.in
+++ b/src/libpts/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -78,11 +78,12 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-@USE_TROUSERS_TRUE@am__append_1 = -ltspi
-@USE_IMC_ATTESTATION_TRUE@am__append_2 = plugins/imc_attestation
-@USE_IMV_ATTESTATION_TRUE@am__append_3 = plugins/imv_attestation
-@USE_IMC_SWID_TRUE@am__append_4 = plugins/imc_swid
-@USE_IMV_SWID_TRUE@am__append_5 = plugins/imv_swid
+@USE_WINDOWS_TRUE@am__append_1 = -lws2_32
+@USE_TROUSERS_TRUE@am__append_2 = -ltspi
+@USE_IMC_ATTESTATION_TRUE@am__append_3 = plugins/imc_attestation
+@USE_IMV_ATTESTATION_TRUE@am__append_4 = plugins/imv_attestation
+@USE_IMC_SWID_TRUE@am__append_5 = plugins/imc_swid
+@USE_IMV_SWID_TRUE@am__append_6 = plugins/imv_swid
subdir = src/libpts
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/depcomp
@@ -136,12 +137,14 @@ am__DEPENDENCIES_1 =
libpts_la_DEPENDENCIES = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(top_builddir)/src/libtncif/libtncif.la \
- $(top_builddir)/src/libimcv/libimcv.la $(am__DEPENDENCIES_1)
+ $(top_builddir)/src/libimcv/libimcv.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
am__dirstamp = $(am__leading_dot)dirstamp
am_libpts_la_OBJECTS = libpts.lo pts/pts.lo pts/pts_error.lo \
pts/pts_pcr.lo pts/pts_creds.lo pts/pts_database.lo \
pts/pts_dh_group.lo pts/pts_file_meas.lo pts/pts_file_meta.lo \
- pts/pts_file_type.lo pts/pts_meas_algo.lo \
+ pts/pts_file_type.lo pts/pts_ima_bios_list.lo \
+ pts/pts_ima_event_list.lo pts/pts_meas_algo.lo \
pts/components/pts_component_manager.lo \
pts/components/pts_comp_evidence.lo \
pts/components/pts_comp_func_name.lo \
@@ -341,6 +344,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -359,6 +363,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -386,6 +391,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -477,6 +483,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -498,7 +505,8 @@ AM_LDFLAGS = \
ipseclib_LTLIBRARIES = libpts.la
libpts_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la \
$(top_builddir)/src/libtncif/libtncif.la \
- $(top_builddir)/src/libimcv/libimcv.la $(am__append_1)
+ $(top_builddir)/src/libimcv/libimcv.la $(am__append_1) \
+ $(am__append_2)
libpts_la_SOURCES = \
libpts.h libpts.c \
pts/pts.h pts/pts.c \
@@ -513,6 +521,8 @@ libpts_la_SOURCES = \
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 \
@@ -549,8 +559,9 @@ libpts_la_SOURCES = \
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
-SUBDIRS = . $(am__append_2) $(am__append_3) $(am__append_4) \
- $(am__append_5)
+EXTRA_DIST = Android.mk
+SUBDIRS = . $(am__append_3) $(am__append_4) $(am__append_5) \
+ $(am__append_6)
all: all-recursive
.SUFFIXES:
@@ -638,6 +649,10 @@ pts/pts_file_meta.lo: pts/$(am__dirstamp) \
pts/$(DEPDIR)/$(am__dirstamp)
pts/pts_file_type.lo: pts/$(am__dirstamp) \
pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_ima_bios_list.lo: pts/$(am__dirstamp) \
+ pts/$(DEPDIR)/$(am__dirstamp)
+pts/pts_ima_event_list.lo: pts/$(am__dirstamp) \
+ pts/$(DEPDIR)/$(am__dirstamp)
pts/pts_meas_algo.lo: pts/$(am__dirstamp) \
pts/$(DEPDIR)/$(am__dirstamp)
pts/components/$(am__dirstamp):
@@ -787,6 +802,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_file_meas.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_file_meta.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_file_type.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_ima_bios_list.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_ima_event_list.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_meas_algo.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@pts/$(DEPDIR)/pts_pcr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@pts/components/$(DEPDIR)/pts_comp_evidence.Plo@am__quote@
diff --git a/src/libpts/plugins/imc_attestation/Makefile.am b/src/libpts/plugins/imc_attestation/Makefile.am
index 3f1b52a88..88d9ddd8b 100644
--- a/src/libpts/plugins/imc_attestation/Makefile.am
+++ b/src/libpts/plugins/imc_attestation/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libpts
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
imcv_LTLIBRARIES = imc-attestation.la
diff --git a/src/libpts/plugins/imc_attestation/Makefile.in b/src/libpts/plugins/imc_attestation/Makefile.in
index dd347d2d8..1f12af63a 100644
--- a/src/libpts/plugins/imc_attestation/Makefile.in
+++ b/src/libpts/plugins/imc_attestation/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -418,7 +422,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libpts
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
imcv_LTLIBRARIES = imc-attestation.la
imc_attestation_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
diff --git a/src/libpts/plugins/imc_attestation/imc_attestation.c b/src/libpts/plugins/imc_attestation/imc_attestation.c
index c71b21666..74bbc468f 100644
--- a/src/libpts/plugins/imc_attestation/imc_attestation.c
+++ b/src/libpts/plugins/imc_attestation/imc_attestation.c
@@ -61,10 +61,10 @@ 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_Initialize(TNC_IMCID imc_id,
- TNC_Version min_version,
- TNC_Version max_version,
- TNC_Version *actual_version)
+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;
@@ -103,9 +103,9 @@ TNC_Result TNC_IMC_Initialize(TNC_IMCID imc_id,
/**
* 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)
+TNC_Result TNC_IMC_API TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_ConnectionState new_state)
{
imc_state_t *state;
@@ -142,8 +142,8 @@ TNC_Result TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
/**
* 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)
+TNC_Result TNC_IMC_API TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id)
{
if (!imc_attestation)
{
@@ -228,11 +228,11 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
/**
* 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)
+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;
@@ -259,15 +259,15 @@ TNC_Result TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
/**
* 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)
+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;
@@ -294,8 +294,8 @@ TNC_Result TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
/**
* 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)
+TNC_Result TNC_IMC_API TNC_IMC_BatchEnding(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id)
{
if (!imc_attestation)
{
@@ -308,7 +308,7 @@ TNC_Result TNC_IMC_BatchEnding(TNC_IMCID imc_id,
/**
* see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
*/
-TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
+TNC_Result TNC_IMC_API TNC_IMC_Terminate(TNC_IMCID imc_id)
{
if (!imc_attestation)
{
@@ -327,7 +327,7 @@ TNC_Result TNC_IMC_Terminate(TNC_IMCID imc_id)
/**
* see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
*/
-TNC_Result TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
+TNC_Result TNC_IMC_API TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
TNC_TNCC_BindFunctionPointer bind_function)
{
if (!imc_attestation)
diff --git a/src/libpts/plugins/imc_swid/Makefile.am b/src/libpts/plugins/imc_swid/Makefile.am
index d73c6d168..ddf596465 100644
--- a/src/libpts/plugins/imc_swid/Makefile.am
+++ b/src/libpts/plugins/imc_swid/Makefile.am
@@ -25,7 +25,7 @@ AM_CPPFLAGS = \
-DSWID_DIRECTORY=\"${prefix}/share\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
imcv_LTLIBRARIES = imc-swid.la
diff --git a/src/libpts/plugins/imc_swid/Makefile.in b/src/libpts/plugins/imc_swid/Makefile.in
index 58402636f..6c3923ae2 100644
--- a/src/libpts/plugins/imc_swid/Makefile.in
+++ b/src/libpts/plugins/imc_swid/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -265,6 +265,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -283,6 +284,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -310,6 +312,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -401,6 +404,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -427,7 +431,7 @@ AM_CPPFLAGS = \
-DSWID_DIRECTORY=\"${prefix}/share\"
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
imcv_LTLIBRARIES = imc-swid.la
imc_swid_la_LIBADD = \
diff --git a/src/libpts/plugins/imc_swid/imc_swid.c b/src/libpts/plugins/imc_swid/imc_swid.c
index d4aaeff4d..ef3a6a3e3 100644
--- a/src/libpts/plugins/imc_swid/imc_swid.c
+++ b/src/libpts/plugins/imc_swid/imc_swid.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -24,12 +24,15 @@
#include <imc/imc_agent.h>
#include <imc/imc_msg.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_angel.h>
#include <tncif_pa_subtypes.h>
#include <pen/pen.h>
#include <utils/debug.h>
+#define SWID_GENERATOR "/usr/local/bin/swid_generator"
/* IMC definitions */
@@ -128,12 +131,177 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
return TNC_RESULT_SUCCESS;
}
-static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
+/**
+ * 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)
{
- imc_msg_t *out_msg;
+ 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, tag_file_path;
+
+ /* 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))
+ {
+ tag_file_path = tag->get_tag_file_path(tag);
+ encoding = tag->get_encoding(tag);
+ entry_size = 2 + tag_file_path.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;
+ chunk_t tag_creator, unique_sw_id, tag_file_path;
+
+ /* At least one TCG Tag ID Inventory attribute is sent */
+ attr_size = PA_TNC_ATTR_HEADER_SIZE + TCG_SWID_TAG_ID_INV_MIN_SIZE;
+ 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))
+ {
+ tag_creator = tag_id->get_tag_creator(tag_id);
+ unique_sw_id = tag_id->get_unique_sw_id(tag_id, &tag_file_path);
+ entry_size = 2 + tag_creator.len + 2 + unique_sw_id.len +
+ 2 + tag_file_path.len;
+
+ 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 ID 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 ID Inventory attribute */
+ attr_size = PA_TNC_ATTR_HEADER_SIZE +
+ TCG_SWID_TAG_ID_INV_MIN_SIZE;
+ attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1);
+ }
+ swid_id_attr = (tcg_swid_attr_tag_id_inv_t*)attr;
+ swid_id_attr->add(swid_id_attr, tag_id->get_ref(tag_id));
+ attr_size += entry_size;
+ }
+ 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;
@@ -145,18 +313,16 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
return result;
}
out_msg = imc_msg_create_as_reply(in_msg);
- swid_state = (imc_swid_state_t*)state;
/* analyze PA-TNC attributes */
enumerator = in_msg->create_attribute_enumerator(in_msg);
while (enumerator->enumerate(enumerator, &attr))
{
tcg_swid_attr_req_t *attr_req;
- u_int8_t flags;
- u_int32_t request_id, eid_epoch;
- swid_inventory_t *swid_inventory, *targets;
- char *swid_directory;
+ uint8_t flags;
+ uint32_t request_id;
bool full_tags;
+ swid_inventory_t *targets;
type = attr->get_type(attr);
@@ -169,7 +335,6 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
flags = attr_req->get_flags(attr_req);
request_id = attr_req->get_request_id(attr_req);
targets = attr_req->get_targets(attr_req);
- eid_epoch = swid_state->get_eid_epoch(swid_state);
if (flags & (TCG_SWID_ATTR_REQ_FLAG_S | TCG_SWID_ATTR_REQ_FLAG_C))
{
@@ -180,33 +345,10 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
}
full_tags = (flags & TCG_SWID_ATTR_REQ_FLAG_R) == 0;
- swid_directory = lib->settings->get_str(lib->settings,
- "%s.plugins.imc-swid.swid_directory",
- SWID_DIRECTORY, lib->ns);
- swid_inventory = swid_inventory_create(full_tags);
- if (!swid_inventory->collect(swid_inventory, swid_directory, targets))
+ if (!add_swid_inventory(state, out_msg, request_id, full_tags, targets))
{
- swid_inventory->destroy(swid_inventory);
- attr = swid_error_create(TCG_SWID_ERROR, request_id,
- 0, "error in SWID tag collection");
- out_msg->add_attribute(out_msg, attr);
break;
}
- 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");
-
- if (full_tags)
- {
- attr = tcg_swid_attr_tag_inv_create(request_id, eid_epoch, 1,
- swid_inventory);
- }
- else
- {
- attr = tcg_swid_attr_tag_id_inv_create(request_id, eid_epoch, 1,
- swid_inventory);
- }
- out_msg->add_attribute(out_msg, attr);
}
enumerator->destroy(enumerator);
diff --git a/src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in b/src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in
index 6945d8769..8b7b50fdf 100644
--- a/src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in
+++ b/src/libpts/plugins/imc_swid/regid.2004-03.org.strongswan_strongSwan.swidtag.in
@@ -1,30 +1,12 @@
<?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>strongSwan</product_title>
- <product_version>
- <name>@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_BUILD@@VERSION_REVIEW@</name>
- <numeric>
- <major>@VERSION_MAJOR@</major>
- <minor>@VERSION_MINOR@</minor>
- <build>@VERSION_BUILD@</build>
- <review>@VERSION_REVIEW@</review>
- </numeric>
- </product_version>
- <software_creator>
- <name>strongSwan Project</name>
- <regid>regid.2004-03.org.strongswan</regid>
- </software_creator>
- <software_licensor>
- <name>strongSwan Project</name>
- <regid>regid.2004-03.org.strongswan</regid>
- </software_licensor>
- <software_id>
- <unique_id>strongSwan-@VERSION_MAJOR@-@VERSION_MINOR@-@VERSION_BUILD@@VERSION_REVIEW@</unique_id>
- <tag_creator_regid>regid.2004-03.org.strongswan</tag_creator_regid>
- </software_id>
- <tag_creator>
- <name>strongSwan Project</name>
- <regid>regid.2004-03.org.strongswan</regid>
- </tag_creator>
-</software_identification_tag>
+
+<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>
diff --git a/src/libpts/plugins/imv_attestation/Makefile.am b/src/libpts/plugins/imv_attestation/Makefile.am
index 8d18f1404..8dc74fd54 100644
--- a/src/libpts/plugins/imv_attestation/Makefile.am
+++ b/src/libpts/plugins/imv_attestation/Makefile.am
@@ -6,7 +6,7 @@ AM_CPPFLAGS = \
-DPLUGINS=\""${attest_plugins}\""
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
imcv_LTLIBRARIES = imv-attestation.la
diff --git a/src/libpts/plugins/imv_attestation/Makefile.in b/src/libpts/plugins/imv_attestation/Makefile.in
index ff94363bf..b0e3787ae 100644
--- a/src/libpts/plugins/imv_attestation/Makefile.in
+++ b/src/libpts/plugins/imv_attestation/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -275,6 +275,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -293,6 +294,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -320,6 +322,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -411,6 +414,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -429,7 +433,7 @@ AM_CPPFLAGS = \
-DPLUGINS=\""${attest_plugins}\""
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
imcv_LTLIBRARIES = imv-attestation.la
imv_attestation_la_LIBADD = \
diff --git a/src/libpts/plugins/imv_attestation/attest.c b/src/libpts/plugins/imv_attestation/attest.c
index 8f4df39e7..63c0023a7 100644
--- a/src/libpts/plugins/imv_attestation/attest.c
+++ b/src/libpts/plugins/imv_attestation/attest.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -19,8 +19,10 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
-#include <syslog.h>
#include <libgen.h>
+#ifdef HAVE_SYSLOG
+# include <syslog.h>
+#endif
#include <library.h>
#include <utils/debug.h>
@@ -43,9 +45,6 @@ static bool stderr_quiet = TRUE;
*/
static void attest_dbg(debug_t group, level_t level, char *fmt, ...)
{
- int priority = LOG_INFO;
- char buffer[8192];
- char *current = buffer, *next;
va_list args;
if (level <= debug_level)
@@ -58,22 +57,30 @@ static void attest_dbg(debug_t group, level_t level, char *fmt, ...)
va_end(args);
}
- /* 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)
+#ifdef HAVE_SYSLOG
{
- next = strchr(current, '\n');
- if (next)
+ 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++) = '\0';
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ syslog(priority, "%s\n", current);
+ current = next;
}
- syslog(priority, "%s\n", current);
- current = next;
}
+#endif /* HAVE_SYSLOG */
}
}
@@ -91,7 +98,9 @@ static void cleanup(void)
attest->destroy(attest);
libpts_deinit();
libimcv_deinit();
+#ifdef HAVE_SYSLOG
closelog();
+#endif
}
static void do_args(int argc, char *argv[])
@@ -144,9 +153,9 @@ static void do_args(int argc, char *argv[])
{ "directory", required_argument, NULL, 'D' },
{ "dir", required_argument, NULL, 'D' },
{ "file", required_argument, NULL, 'F' },
- { "sha1-ima", no_argument, NULL, 'I' },
{ "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' },
@@ -294,9 +303,6 @@ static void do_args(int argc, char *argv[])
exit(EXIT_FAILURE);
}
continue;
- case 'I':
- attest->set_algo(attest, PTS_MEAS_ALGO_SHA1_IMA);
- continue;
case 'K':
{
chunk_t aik;
@@ -308,6 +314,12 @@ static void do_args(int argc, char *argv[])
}
continue;
}
+ case 'M':
+ if (!attest->set_meas_directory(attest, optarg))
+ {
+ exit(EXIT_FAILURE);
+ }
+ continue;
case 'O':
attest->set_owner(attest, optarg);
continue;
@@ -437,7 +449,9 @@ int main(int argc, char *argv[])
/* enable attest debugging hook */
dbg = attest_dbg;
+#ifdef HAVE_SYSLOG
openlog("attest", 0, LOG_DEBUG);
+#endif
atexit(library_deinit);
@@ -471,4 +485,3 @@ int main(int argc, char *argv[])
exit(EXIT_SUCCESS);
}
-
diff --git a/src/libpts/plugins/imv_attestation/attest_db.c b/src/libpts/plugins/imv_attestation/attest_db.c
index 7a8a1135a..d7f45ad29 100644
--- a/src/libpts/plugins/imv_attestation/attest_db.c
+++ b/src/libpts/plugins/imv_attestation/attest_db.c
@@ -79,6 +79,11 @@ struct private_attest_db_t {
int fid;
/**
+ * Directory where file measurement are to be taken
+ */
+ char *meas_dir;
+
+ /**
* AIK to be queried
*/
chunk_t key;
@@ -193,6 +198,21 @@ char* print_cfn(pts_comp_func_name_t *cfn)
return buf;
}
+/**
+ * Get the directory separator to append to a path
+ */
+static const char* get_separator(const char *path)
+{
+ if (streq(path, DIRECTORY_SEPARATOR))
+ { /* root directory on Unix file system, no separator */
+ return "";
+ }
+ else
+ { /* non-root or Windows path, use system specific separator */
+ return DIRECTORY_SEPARATOR;
+ }
+}
+
METHOD(attest_db_t, set_component, bool,
private_attest_db_t *this, char *comp, bool create)
{
@@ -309,9 +329,9 @@ METHOD(attest_db_t, set_directory, bool,
return FALSE;
}
- /* remove trailing '/' character if not root directory */
+ /* remove trailing '/' or '\' character if not root directory */
len = strlen(dir);
- if (len > 1 && dir[len-1] == '/')
+ if (len > 1 && dir[len-1] == DIRECTORY_SEPARATOR[0])
{
dir[len-1] = '\0';
}
@@ -385,7 +405,6 @@ METHOD(attest_db_t, set_file, bool,
private_attest_db_t *this, char *file, bool create)
{
int fid;
- char *sep;
enumerator_t *e;
if (this->file)
@@ -399,7 +418,6 @@ METHOD(attest_db_t, set_file, bool,
{
return TRUE;
}
- sep = streq(this->dir, "/") ? "" : "/";
e = this->db->query(this->db, "SELECT id FROM files "
"WHERE dir = ? AND name = ?",
DB_INT, this->did, DB_TEXT, file, DB_INT);
@@ -418,7 +436,8 @@ METHOD(attest_db_t, set_file, bool,
if (!create)
{
- printf("file '%s%s%s' not found in database\n", this->dir, sep, file);
+ printf("file '%s%s%s' not found in database\n",
+ this->dir, get_separator(this->dir), file);
return FALSE;
}
@@ -429,8 +448,8 @@ METHOD(attest_db_t, set_file, bool,
{
this->fid = fid;
}
- printf("file '%s%s%s' %sinserted into database\n", this->dir, sep, file,
- this->fid ? "" : "could not be ");
+ printf("file '%s%s%s' %sinserted into database\n", this->dir,
+ get_separator(this->dir), file, this->fid ? "" : "could not be ");
return this->fid > 0;
}
@@ -470,6 +489,22 @@ METHOD(attest_db_t, set_fid, bool,
return this->fid > 0;
}
+METHOD(attest_db_t, set_meas_directory, bool,
+ private_attest_db_t *this, char *dir)
+{
+ size_t len;
+
+ /* remove trailing '/' character if not root directory */
+ len = strlen(dir);
+ if (len > 1 && dir[len-1] == '/')
+ {
+ dir[len-1] = '\0';
+ }
+ this->meas_dir = strdup(dir);
+
+ return TRUE;
+}
+
METHOD(attest_db_t, set_key, bool,
private_attest_db_t *this, chunk_t key, bool create)
{
@@ -1297,7 +1332,7 @@ METHOD(attest_db_t, list_hashes, void,
printf("%d %N value%s found for file '%s%s%s'\n", count,
pts_meas_algorithm_names, this->algo,
(count == 1) ? "" : "s", this->dir,
- streq(this->dir, "/") ? "" : "/", this->file);
+ get_separator(this->dir), this->file);
}
}
else if (this->file)
@@ -1568,12 +1603,13 @@ METHOD(attest_db_t, list_sessions, void,
*/
static bool insert_file_hash(private_attest_db_t *this,
pts_meas_algorithms_t algo,
- chunk_t measurement, int fid, bool ima,
+ chunk_t measurement, int fid,
int *hashes_added, int *hashes_updated)
{
enumerator_t *e;
chunk_t hash;
char *label;
+ bool insert = TRUE, update = FALSE;
label = "could not be created";
@@ -1581,46 +1617,50 @@ static bool insert_file_hash(private_attest_db_t *this,
"SELECT hash FROM file_hashes WHERE algo = ? "
"AND file = ? AND product = ? AND device = 0",
DB_INT, algo, DB_UINT, fid, DB_UINT, this->pid, DB_BLOB);
+
if (!e)
{
printf("file_hashes query failed\n");
return FALSE;
}
- if (e->enumerate(e, &hash))
+
+ while (e->enumerate(e, &hash))
{
+ update = TRUE;
+
if (chunk_equals(measurement, hash))
{
label = "exists and equals";
- }
- else
- {
- if (this->db->execute(this->db, NULL,
- "UPDATE file_hashes SET hash = ? WHERE algo = ? "
- "AND file = ? AND product = ? and device = 0",
- DB_BLOB, measurement, DB_INT, algo, DB_UINT, fid,
- DB_UINT, this->pid) == 1)
- {
- label = "updated";
- (*hashes_updated)++;
- }
+ insert = FALSE;
+ break;
}
}
- else
+ e->destroy(e);
+
+ if (insert)
{
if (this->db->execute(this->db, NULL,
"INSERT INTO file_hashes "
"(file, product, device, algo, hash) "
"VALUES (?, ?, 0, ?, ?)",
DB_UINT, fid, DB_UINT, this->pid,
- DB_INT, algo, DB_BLOB, measurement) == 1)
+ DB_INT, algo, DB_BLOB, measurement) != 1)
+ {
+ printf("file_hash insertion failed\n");
+ return FALSE;
+ }
+ if (update)
+ {
+ label = "updated";
+ (*hashes_updated)++;
+ }
+ else
{
label = "created";
(*hashes_added)++;
}
}
- e->destroy(e);
-
- printf(" %#B - %s%s\n", &measurement, ima ? "ima - " : "", label);
+ printf(" %#B - %s\n", &measurement, label);
return TRUE;
}
@@ -1629,33 +1669,24 @@ static bool insert_file_hash(private_attest_db_t *this,
*/
static bool add_hash(private_attest_db_t *this)
{
- char *pathname, *filename, *sep, *label, *pos;
- char ima_buffer[IMA_MAX_NAME_LEN + 1];
- chunk_t measurement, ima_template;
+ char *pathname, *filename, *label;
+ const char *sep;
pts_file_meas_t *measurements;
+ chunk_t measurement;
hasher_t *hasher = NULL;
- bool ima = FALSE;
int fid, files_added = 0, hashes_added = 0, hashes_updated = 0;
- int len, ima_hashes_added = 0, ima_hashes_updated = 0;
enumerator_t *enumerator, *e;
- if (this->algo == PTS_MEAS_ALGO_SHA1_IMA)
+ if (!this->meas_dir)
{
- ima = TRUE;
- this->algo = PTS_MEAS_ALGO_SHA1;
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!hasher)
- {
- printf("could not create hasher\n");
- return FALSE;
- }
+ this->meas_dir = strdup(this->dir);
}
- sep = streq(this->dir, "/") ? "" : "/";
+ sep = get_separator(this->meas_dir);
if (this->fid)
{
/* build pathname from directory path and relative filename */
- if (asprintf(&pathname, "%s%s%s", this->dir, sep, this->file) == -1)
+ if (asprintf(&pathname, "%s%s%s", this->meas_dir, sep, this->file) == -1)
{
return FALSE;
}
@@ -1665,7 +1696,7 @@ static bool add_hash(private_attest_db_t *this)
}
else
{
- measurements = pts_file_meas_create_from_path(0, this->dir, TRUE,
+ measurements = pts_file_meas_create_from_path(0, this->meas_dir, TRUE,
TRUE, this->algo);
}
if (!measurements)
@@ -1717,59 +1748,18 @@ static bool add_hash(private_attest_db_t *this)
printf("%4d: %s - %s\n", fid, filename, label);
/* compute file measurement hash */
- if (!insert_file_hash(this, this->algo, measurement, fid, FALSE,
+ if (!insert_file_hash(this, this->algo, measurement, fid,
&hashes_added, &hashes_updated))
{
break;
}
- if (!ima)
- {
- continue;
- }
-
- /* compute IMA template hash */
- pos = ima_buffer;
- len = IMA_MAX_NAME_LEN;
- if (!this->relative)
- {
- strncpy(pos, this->dir, len);
- len = max(0, len - strlen(this->dir));
- pos = ima_buffer + IMA_MAX_NAME_LEN - len;
- strncpy(pos, sep, len);
- len = max(0, len - strlen(sep));
- pos = ima_buffer + IMA_MAX_NAME_LEN - len;
- }
- strncpy(pos, filename, len);
- ima_buffer[IMA_MAX_NAME_LEN] = '\0';
- ima_template = chunk_create(ima_buffer, sizeof(ima_buffer));
- if (!hasher->get_hash(hasher, measurement, NULL) ||
- !hasher->get_hash(hasher, ima_template, measurement.ptr))
- {
- printf("could not compute IMA template hash\n");
- break;
- }
- if (!insert_file_hash(this, PTS_MEAS_ALGO_SHA1_IMA, measurement, fid,
- TRUE, &ima_hashes_added, &ima_hashes_updated))
- {
- break;
- }
}
enumerator->destroy(enumerator);
- printf("%d measurements, added %d new files, %d file hashes",
- measurements->get_file_count(measurements), files_added,
- hashes_added);
- if (ima)
- {
- printf(", %d ima hashes", ima_hashes_added);
- hasher->destroy(hasher);
- }
- printf(", updated %d file hashes", hashes_updated);
- if (ima)
- {
- printf(", %d ima hashes", ima_hashes_updated);
- }
- printf("\n");
+ printf("%d measurements, added %d new files, %d file hashes, "
+ "updated %d file hashes\n",
+ measurements->get_file_count(measurements),
+ files_added, hashes_added, hashes_updated);
measurements->destroy(measurements);
return TRUE;
@@ -1780,22 +1770,6 @@ METHOD(attest_db_t, add, bool,
{
bool success = FALSE;
- /* add key/component pair */
- if (this->kid && this->cid)
- {
- success = this->db->execute(this->db, NULL,
- "INSERT INTO key_component (key, component, seq_no) "
- "VALUES (?, ?, ?)",
- DB_UINT, this->kid, DB_UINT, this->cid,
- DB_UINT, this->seq_no) == 1;
-
- printf("key/component pair (%d/%d) %sinserted into database at "
- "position %d\n", this->kid, this->cid,
- success ? "" : "could not be ", this->seq_no);
-
- return success;
- }
-
/* add directory or file hash measurement for a given product */
if (this->did && this->pid)
{
@@ -1844,8 +1818,8 @@ METHOD(attest_db_t, delete, bool,
DB_UINT, this->algo, DB_UINT, this->pid,
DB_UINT, this->fid) > 0;
- printf("%4d: %s%s%s\n", this->fid, this->dir,
- streq(this->dir, "/") ? "" : "/", this->file);
+ printf("%4d: %s%s%s\n", this->fid, this->dir, get_separator(this->dir),
+ this->file);
printf("%N value for product '%s' %sdeleted from database\n",
pts_meas_algorithm_names, this->algo, this->product,
success ? "" : "could not be ");
@@ -1869,19 +1843,6 @@ METHOD(attest_db_t, delete, bool,
return success;
}
- /* delete key/component pair */
- if (this->kid && this->cid)
- {
- success = this->db->execute(this->db, NULL,
- "DELETE FROM key_component "
- "WHERE key = ? AND component = ?",
- DB_UINT, this->kid, DB_UINT, this->cid) > 0;
-
- printf("key/component pair (%d/%d) %sdeleted from database\n",
- this->kid, this->cid, success ? "" : "could not be ");
- return success;
- }
-
if (this->cid)
{
success = this->db->execute(this->db, NULL,
@@ -1900,7 +1861,7 @@ METHOD(attest_db_t, delete, bool,
DB_UINT, this->fid) > 0;
printf("file '%s%s%s' %sdeleted from database\n", this->dir,
- streq(this->dir, "/") ? "" : "/", this->file,
+ get_separator(this->dir), this->file,
success ? "" : "could not be ");
return success;
}
@@ -1970,6 +1931,7 @@ METHOD(attest_db_t, destroy, void,
free(this->version);
free(this->file);
free(this->dir);
+ free(this->meas_dir);
free(this->owner);
free(this->key.ptr);
free(this);
@@ -1990,6 +1952,7 @@ attest_db_t *attest_db_create(char *uri)
.set_did = _set_did,
.set_file = _set_file,
.set_fid = _set_fid,
+ .set_meas_directory = _set_meas_directory,
.set_key = _set_key,
.set_kid = _set_kid,
.set_package = _set_package,
diff --git a/src/libpts/plugins/imv_attestation/attest_db.h b/src/libpts/plugins/imv_attestation/attest_db.h
index d0a48d844..07e55cce7 100644
--- a/src/libpts/plugins/imv_attestation/attest_db.h
+++ b/src/libpts/plugins/imv_attestation/attest_db.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -84,6 +84,14 @@ struct attest_db_t {
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
diff --git a/src/libpts/plugins/imv_attestation/build-database.sh b/src/libpts/plugins/imv_attestation/build-database.sh
index be1024de0..f16b5d152 100755
--- a/src/libpts/plugins/imv_attestation/build-database.sh
+++ b/src/libpts/plugins/imv_attestation/build-database.sh
@@ -1,221 +1,84 @@
#!/bin/sh
-p="Ubuntu 12.04 i686"
+p="Ubuntu 14.04 x86_64"
+a="x86_64-linux-gnu"
+k="3.13.0-30-generic"
-ipsec attest --add --product "$p" --sha1-ima --dir /sbin
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/sbin
-ipsec attest --add --product "$p" --sha1-ima --dir /bin
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/bin
-ipsec attest --add --product "$p" --sha1-ima --dir /etc/acpi
-ipsec attest --add --product "$p" --sha1-ima --file /etc/init.d/rc
-ipsec attest --add --product "$p" --sha1-ima --file /etc/init.d/rcS
-ipsec attest --add --product "$p" --sha1-ima --dir /etc/network/if-post-down.d
-ipsec attest --add --product "$p" --sha1-ima --dir /etc/network/if-pre-up.d
-ipsec attest --add --product "$p" --sha1-ima --dir /etc/network/if-up.d
-ipsec attest --add --product "$p" --sha1-ima --file /etc/NetworkManager/dispatcher.d/01ifupdown
-ipsec attest --add --product "$p" --sha1-ima --dir /etc/ppp/ip-down.d
-ipsec attest --add --product "$p" --sha1-ima --dir /etc/rc2.d
-ipsec attest --add --product "$p" --sha1-ima --dir /etc/rcS.d
-ipsec attest --add --product "$p" --sha1-ima --file /etc/rc.local
-ipsec attest --add --product "$p" --sha1-ima --dir /etc/resolvconf/update.d
-ipsec attest --add --product "$p" --sha1-ima --file /etc/resolvconf/update-libc.d/avahi-daemon
-ipsec attest --add --product "$p" --sha1-ima --dir /etc/update-motd.d
-ipsec attest --add --product "$p" --sha1-ima --file /lib/crda/setregdomain
-ipsec attest --add --product "$p" --sha1-ima --file /lib/init/apparmor-profile-load
-ipsec attest --add --product "$p" --sha1-ima --file /lib/resolvconf/list-records
-ipsec attest --add --product "$p" --sha1-ima --dir /lib/udev
-ipsec attest --add --product "$p" --sha1-ima --file /lib/ufw/ufw-init
-ipsec attest --add --product "$p" --sha1-ima --file /opt/Adobe/Reader9/Reader/intellinux/bin/acroread
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/accountsservice/accounts-daemon
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/apt/methods
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/at-spi2-core
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/avahi/avahi-daemon-check-dns.sh
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/bamf/bamfdaemon
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ConsoleKit
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ConsoleKit/run-seat.d
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ConsoleKit/run-session.d
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/cups/notifier
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/dconf/dconf-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/dbus-1.0/dbus-daemon-launch-helper
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/deja-dup/deja-dup/deja-dup-monitor
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/evolution/3.2/evolution-alarm-notify
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/firefox/firefox
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/firefox/plugin-container
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gcc/i686-linux-gnu/4.6/cc1
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gcc/i686-linux-gnu/4.6/collect2
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/geoclue/geoclue-master
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/git-core
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-desktop3/check_gl_texture_size
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-disk-utility/gdu-notification-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-online-accounts/goa-daemon
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/gnome-settings-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-user-share/gnome-user-share
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gnome-screensaver/gnome-screensaver-dialog
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/gvfs
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/gvfs//gvfs-fuse-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/i386-linux-gnu/colord/colord
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/i386-linux-gnu/gconf
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-application/indicator-application-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-appmenu/hud-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-datetime/indicator-datetime-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-messages/indicator-messages-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-printers/indicator-printers-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-session/indicator-session-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/indicator-sound/indicator-sound-service
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/lightdm
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/NetworkManager/nm-dhcp-client.action
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/NetworkManager/nm-dispatcher.action
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/notify-osd/notify-osd
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/nux/unity_support_test
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/pm-utils/power.d
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/pm-utils/sleep.d
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/policykit-1/polkitd
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/pulseaudio/pulse/gconf-helper
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/rtkit/rtkit-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/system-service/system-service-d
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/telepathy/mission-control-5
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/thunderbird/thunderbird
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ubuntuone-client
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/ubuntu-geoip/ubuntu-geoip-provider
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/ubuntu-sso-client
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/udisks
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity/unity-panel-service
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-lens-applications/unity-applications-daemon
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-lens-files/unity-files-daemon
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/unity-lens-music
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-lens-video/unity-lens-video
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/unity-scope-video-remote/unity-scope-video-remote
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/update-manager/release-upgrade-motd
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/lib/update-notifier
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/upower/upowerd
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/libvte-2.90-9/gnome-pty-helper
-ipsec attest --add --product "$p" --sha1-ima --file /usr/lib/zeitgeist/zeitgeist-fts
-ipsec attest --add --product "$p" --sha1-ima --file /usr/share/apport/apport
-ipsec attest --add --product "$p" --sha1-ima --file /usr/share/apport/apport-checkreports
-ipsec attest --add --product "$p" --sha1-ima --file /usr/share/apport/apport-gtk
-ipsec attest --add --product "$p" --sha1-ima --dir /usr/share/language-tools
-ipsec attest --add --product "$p" --sha1-ima --file /usr/share/virtualbox/VBoxCreateUSBNode.sh
-ipsec attest --add --product "$p" --sha1-ima --relative --file /etc/ld.so.cache
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/i386-linux-gnu
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/i386-linux-gnu/security
-for file in `find /lib/modules/3.2.21ima/kernel -name *.ko`
+for hash in sha1 sha256
do
-ipsec attest --add --product "$p" --sha1-ima --relative --file $file
-done
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/plymouth
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/plymouth/renderers
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /lib/security
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /opt/Adobe/Reader9/Reader/intellinux/lib
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/apache2/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/compiz
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/compizconfig/backends/
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/enchant
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/evolution/3.2/libemiscwidgets.so.0.0.0
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/evolution/3.2/libeutil.so.0.0.0
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/evolution/3.2/libgnomecanvas.so.0.0.0
-for file in /usr/lib/firefox/*.so
-do
-ipsec attest --add --product "$p" --sha1-ima --relative --file $file
-done
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox/components/libbrowsercomps.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox/components/libdbusservice.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox/components/libmozgnome.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox-addons/extensions/globalmenu@ubuntu.com/components/libglobalmenu.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/firefox-addons/plugins/nppdf.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/flashplugin-installer/libflashplayer.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gedit/plugins
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gnome-bluetooth
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gnome-settings-daemon-3.0
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gtk-2.0/2.10.0/menuproxies
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gtk-3.0/3.0.0/menuproxies
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/gtk-3.0/3.0.0/theming-engines
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/alsa-lib
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/dri
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gconf/2
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gconv
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gio/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-2.0/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-2.0/2.10.0/engines
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-2.0/2.10.0/immodules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-3.0/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/immodules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/gvfs
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/libcanberra-0.28
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/mesa
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/mit-krb5
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/openssl-1.0.0/engines
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/pango/1.6.0/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/pkcs11
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/polkit-1/extensions
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/nss
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/sane
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/i386-linux-gnu/sse2
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/indicators3/7
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/indicator-messages/status-providers/1
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/libpeas-1.0/loaders
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/man-db/libman-2.6.1.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/man-db/libmandb-2.6.1.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/mission-control-plugins.0
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/ModemManager
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/nautilus/extensions-3.0
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/NetworkManager/libnm-settings-plugin-ifupdown.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/perl/5.14.2/auto/File/Glob/Glob.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/pulse-1.1/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/python2.7/lib-dynload
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/apt_inst.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/apt_pkg.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/cairo/_cairo.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/dbus/mainloop/qt.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/_dbus_bindings.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/_dbus_glib_bindings.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/duplicity/_librsync.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gi/_gi.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gi/_gobject/_gobject.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gi/_glib/_glib.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/glib/_glib.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gobject/_gobject.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/atk.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/gtk/_gtk.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/gio/_gio.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/gio/unix.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/pango.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/pangocairo.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/gtk-2.0/pynotify/_pynotify.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/OpenSSL/crypto.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/OpenSSL/rand.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/OpenSSL/SSL.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/PyQt4/QtCore.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/simplejson/_speedups.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/sip.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/twisted/internet/_sigchld.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/twisted/python/_initgroups.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/xapian/_xapian.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/python2.7/dist-packages/zope/interface/_zope_interface_coptimizations.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/rsyslog
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/sane
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/sse2
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/sudo
-for file in /usr/lib/thunderbird/*.so
-do
-ipsec attest --add --product "$p" --sha1-ima --relative --file $file
+ 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
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/thunderbird/components/libdbusservice.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/thunderbird/components/libmozgnome.so
-ipsec attest --add --product "$p" --sha1-ima --relative --file /usr/lib/thunderbird-addons/extensions/globalmenu@ubuntu.com/components/libglobalmenu.so
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/xorg/modules
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/xorg/modules/drivers
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/xorg/modules/extensions
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/lib/xorg/modules/input
-ipsec attest --add --product "$p" --sha1-ima --relative --dir /usr/share/fonts/truetype/ubuntu-font-family
-ipsec attest --del --product "$p" --sha1 --file /lib/resolvconf/list-records
-ipsec attest --del --product "$p" --sha1-ima --file /lib/resolvconf/list-records
-ipsec attest --del --product "$p" --sha1 --file /usr/bin/lsb_release
-ipsec attest --del --product "$p" --sha1-ima --file /usr/bin/lsb_release
-ipsec attest --del --product "$p" --sha1 --file /usr/share/language-tools/language-options
-ipsec attest --del --product "$p" --sha1-ima --file /usr/share/language-tools/language-options
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_agent.c b/src/libpts/plugins/imv_attestation/imv_attestation_agent.c
index ae2660bae..fcfee31c1 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_agent.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_agent.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2011-2012 Sansar Choinyambuu
- * Copyright (C) 2011-2013 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -25,11 +25,15 @@
#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 <libpts.h>
@@ -111,7 +115,9 @@ 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)
{
@@ -120,6 +126,35 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
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);
}
@@ -131,15 +166,14 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
imv_state_t *state, imv_msg_t *in_msg)
{
- imv_attestation_state_t *attestation_state;
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;
- pts_t *pts;
- chunk_t os_name = chunk_empty;
- chunk_t os_version = chunk_empty;
+ chunk_t os_name, os_version;
bool fatal_error = FALSE;
/* parse received PA-TNC message and handle local and remote errors */
@@ -149,8 +183,8 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
return result;
}
- attestation_state = (imv_attestation_state_t*)state;
- pts = attestation_state->get_pts(attestation_state);
+ session = state->get_session(state);
+ os_info = session->get_os_info(session);
out_msg = imv_msg_create_as_reply(in_msg);
out_msg->set_msg_type(out_msg, msg_types[0]);
@@ -188,17 +222,64 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
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, NULL, NULL);
+ 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:
@@ -218,15 +299,6 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
}
enumerator->destroy(enumerator);
- /**
- * The IETF Product Information and String Version attributes
- * are supposed to arrive in the same PA-TNC message
- */
- if (os_name.len && os_version.len)
- {
- pts->set_platform_info(pts, os_name, os_version);
- }
-
if (fatal_error || result != TNC_RESULT_SUCCESS)
{
state->set_recommendation(state,
@@ -288,6 +360,31 @@ METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
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)
{
@@ -302,7 +399,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
TNC_IMVID imv_id;
TNC_Result result = TNC_RESULT_SUCCESS;
pts_t *pts;
- char *platform_info;
+ int pid;
+ uint32_t actions;
enumerator_t *enumerator;
if (!this->agent->get_state(this->agent, id, &state))
@@ -312,40 +410,59 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
attestation_state = (imv_attestation_state_t*)state;
pts = attestation_state->get_pts(attestation_state);
handshake_state = attestation_state->get_handshake_state(attestation_state);
- platform_info = pts->get_platform_info(pts);
+ 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 (state->get_action_flags(state) & IMV_ATTESTATION_FLAG_REC)
+ if (actions & IMV_ATTESTATION_REC)
{
return TNC_RESULT_SUCCESS;
}
/* send an IETF attribute request if no platform info was received */
- if (!platform_info &&
- !(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_ATTR_REQ))
+ if (!(actions & IMV_ATTESTATION_ATTR_REQ))
{
- pa_tnc_attr_t *attr;
- ietf_attr_attr_request_t *attr_cast;
- imv_msg_t *os_msg;
+ if ((actions & IMV_ATTESTATION_ATTR_MUST) != IMV_ATTESTATION_ATTR_MUST)
+ {
+ imv_msg_t *os_msg;
- attr = ietf_attr_attr_request_create(PEN_IETF,
- IETF_ATTR_PRODUCT_INFORMATION);
- attr_cast = (ietf_attr_attr_request_t*)attr;
- attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_STRING_VERSION);
+ /* 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);
- os_msg = imv_msg_create(this->agent, state, id, imv_id, TNC_IMCID_ANY,
- msg_types[1]);
- os_msg->add_attribute(os_msg, attr);
- 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 (result != TNC_RESULT_SUCCESS)
+ 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)
{
- return result;
+ /* 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);
}
- state->set_action_flags(state, IMV_ATTESTATION_FLAG_ATTR_REQ);
}
if (handshake_state == IMV_ATTESTATION_STATE_INIT)
@@ -378,22 +495,24 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
}
/* exit if we are not ready yet for PTS measurements */
- if (!platform_info || !session ||
- !(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_ALGO))
+ 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 (!(state->get_action_flags(state) & IMV_ATTESTATION_FLAG_FILE_MEAS))
+ if (!(actions & IMV_ATTESTATION_FILE_MEAS))
{
bool is_dir, no_workitems = TRUE;
- u_int32_t delimiter = SOLIDUS_UTF;
- u_int16_t request_id;
+ uint32_t delimiter = SOLIDUS_UTF;
+ uint16_t request_id;
pa_tnc_attr_t *attr;
char *pathname;
@@ -555,7 +674,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
enumerator->destroy(enumerator);
/* sent all file and directory measurement and metadata requests */
- state->set_action_flags(state, IMV_ATTESTATION_FLAG_FILE_MEAS);
+ state->set_action_flags(state, IMV_ATTESTATION_FILE_MEAS);
if (no_workitems)
{
@@ -600,14 +719,14 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
enumerator->destroy(enumerator);
/* finalized all workitems? */
- if (session && session->get_policy_started(session) &&
+ 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_FLAG_REC);
+ state->set_action_flags(state, IMV_ATTESTATION_REC);
if (result != TNC_RESULT_SUCCESS)
{
@@ -642,14 +761,16 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
session = state->get_session(state);
imv_id = this->agent->get_id(this->agent);
- if (session)
+ if (imcv_db)
{
TNC_IMV_Evaluation_Result eval;
TNC_IMV_Action_Recommendation rec;
imv_workitem_t *workitem;
enumerator_t *enumerator;
- char *result_str;
int pending_file_meas = 0;
+ char *result_str;
+ chunk_t result_buf;
+ bio_writer_t *result;
enumerator = session->create_workitem_enumerator(session);
if (enumerator)
@@ -660,20 +781,28 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
{
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";
+ result_str = "pending file measurements";
pending_file_meas++;
break;
case IMV_WORKITEM_TPM_ATTEST:
- attestation_state->finalize_components(attestation_state);
- result_str = "Pending component evidence";
+ 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);
@@ -682,6 +811,7 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
state->update_recommendation(state, rec, eval);
imcv_db->finalize_workitem(imcv_db, workitem);
workitem->destroy(workitem);
+ result->destroy(result);
}
enumerator->destroy(enumerator);
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_build.c b/src/libpts/plugins/imv_attestation/imv_attestation_build.c
index 84023c6c6..120fe3eaa 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_build.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_build.c
@@ -62,6 +62,11 @@ bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
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);
@@ -89,17 +94,14 @@ bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
tcg_pts_attr_req_func_comp_evid_t *attr_cast;
enumerator_t *enumerator;
pts_comp_func_name_t *name;
- chunk_t keyid;
- int kid;
- u_int8_t flags;
- u_int32_t depth;
+ 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_keyid(pts, &keyid) ||
- pts_db->check_aik_keyid(pts_db, keyid, &kid) != SUCCESS)
+ if (!pts->get_aik_id(pts))
{
attestation_state->set_measurement_error(attestation_state,
IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_process.c b/src/libpts/plugins/imv_attestation/imv_attestation_process.c
index e40c92a24..26a57d15c 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_process.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_process.c
@@ -46,10 +46,12 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
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);
@@ -80,7 +82,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
return FALSE;
}
pts->set_meas_algorithm(pts, selected_algorithm);
- state->set_action_flags(state, IMV_ATTESTATION_FLAG_ALGO);
+ state->set_action_flags(state, IMV_ATTESTATION_ALGO);
break;
}
case TCG_PTS_DH_NONCE_PARAMS_RESP:
@@ -140,6 +142,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
{
return FALSE;
}
+ state->set_action_flags(state, IMV_ATTESTATION_DH_NONCE);
break;
}
case TCG_PTS_TPM_VERSION_INFO:
@@ -157,9 +160,10 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
tcg_pts_attr_aik_t *attr_cast;
certificate_t *aik, *issuer;
public_key_t *public;
- chunk_t keyid;
+ chunk_t keyid, keyid_hex, device_id;
+ int aik_id;
enumerator_t *e;
- bool trusted = FALSE;
+ bool trusted = FALSE, trusted_chain = FALSE;
attr_cast = (tcg_pts_attr_aik_t*)attr;
aik = attr_cast->get_aik(attr_cast);
@@ -170,12 +174,27 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
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)
{
- public = aik->get_public_key(aik);
- public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid);
- DBG1(DBG_IMV, "verifying AIK certificate with keyid %#B", &keyid);
- public->destroy(public);
e = pts_credmgr->create_trusted_enumerator(pts_credmgr,
KEY_ANY, aik->get_issuer(aik), FALSE);
@@ -183,21 +202,22 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
{
if (aik->issued_by(aik, issuer, NULL))
{
- trusted = TRUE;
+ trusted_chain = TRUE;
break;
}
}
e->destroy(e);
DBG1(DBG_IMV, "AIK certificate is %strusted",
- trusted ? "" : "not ");
- if (!trusted)
+ trusted_chain ? "" : "not ");
+ if (!trusted || !trusted_chain)
{
attestation_state->set_measurement_error(attestation_state,
IMV_ATTESTATION_ERROR_NO_TRUSTED_AIK);
break;
}
}
- pts->set_aik(pts, aik);
+ session->get_session_id(session, NULL, &aik_id);
+ pts->set_aik(pts, aik, aik_id);
break;
}
case TCG_PTS_FILE_MEAS:
@@ -205,21 +225,18 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
TNC_IMV_Evaluation_Result eval;
TNC_IMV_Action_Recommendation rec;
tcg_pts_attr_file_meas_t *attr_cast;
- u_int16_t request_id;
+ uint16_t request_id;
int arg_int, file_count;
pts_meas_algorithms_t algo;
pts_file_meas_t *measurements;
- imv_session_t *session;
imv_workitem_t *workitem, *found = NULL;
imv_workitem_type_t type;
- char result_str[BUF_LEN], *platform_info;
+ char result_str[BUF_LEN];
bool is_dir, correct;
enumerator_t *enumerator;
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
- session = state->get_session(state);
algo = pts->get_meas_algorithm(pts);
- platform_info = pts->get_platform_info(pts);
attr_cast = (tcg_pts_attr_file_meas_t*)attr;
measurements = attr_cast->get_measurements(attr_cast);
request_id = measurements->get_request_id(measurements);
@@ -272,7 +289,8 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
/* check hashes from database against measurements */
e = pts_db->create_file_hash_enumerator(pts_db,
- platform_info, algo, is_dir, arg_int);
+ pts->get_platform_id(pts),
+ algo, is_dir, arg_int);
if (!e)
{
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
@@ -304,8 +322,8 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
while (e->enumerate(e, &filename, &measurement))
{
if (pts_db->add_file_measurement(pts_db,
- platform_info, algo, measurement, filename,
- is_dir, arg_int) != SUCCESS)
+ pts->get_platform_id(pts), algo, measurement,
+ filename, is_dir, arg_int) != SUCCESS)
{
eval = TNC_IMV_EVALUATION_RESULT_ERROR;
}
@@ -328,7 +346,8 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
}
else
{
- measurements->check(measurements, pts_db, platform_info, algo);
+ measurements->check(measurements, pts_db,
+ pts->get_platform_id(pts), algo);
}
break;
}
@@ -373,7 +392,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
pts_comp_func_name_t *name;
pts_comp_evidence_t *evidence;
pts_component_t *comp;
- u_int32_t depth;
+ uint32_t depth;
status_t status;
attr_cast = (tcg_pts_attr_simple_comp_evid_t*)attr;
@@ -398,14 +417,15 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
case TCG_PTS_SIMPLE_EVID_FINAL:
{
tcg_pts_attr_simple_evid_final_t *attr_cast;
- u_int8_t flags;
+ 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;
- imv_session_t *session;
+ 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,
@@ -451,9 +471,10 @@ quote_error:
* Finalize any pending measurement registrations and check
* if all expected component measurements were received
*/
- attestation_state->finalize_components(attestation_state);
+ result = bio_writer_create(128);
+ attestation_state->finalize_components(attestation_state,
+ result);
- session = state->get_session(state);
enumerator = session->create_workitem_enumerator(session);
while (enumerator->enumerate(enumerator, &workitem))
{
@@ -461,8 +482,7 @@ quote_error:
{
TNC_IMV_Action_Recommendation rec;
TNC_IMV_Evaluation_Result eval;
- char *result_str;
- u_int32_t error;
+ uint32_t error;
error = attestation_state->get_measurement_error(
attestation_state);
@@ -470,34 +490,35 @@ quote_error:
IMV_ATTESTATION_ERROR_COMP_EVID_PEND |
IMV_ATTESTATION_ERROR_TPM_QUOTE_FAIL))
{
- imv_reason_string_t *reason_string;
- chunk_t result;
-
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);
+ 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
{
- result_str = strdup("attestation successful");
eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
}
session->remove_workitem(session, enumerator);
- rec = workitem->set_result(workitem, result_str, eval);
+
+ 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);
- free(result_str);
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))
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.c b/src/libpts/plugins/imv_attestation/imv_attestation_state.c
index 9304b9a13..11afbc29d 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_state.c
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.c
@@ -63,22 +63,12 @@ struct private_imv_attestation_state_t {
/**
* Maximum PA-TNC message size for this TNCCS connection
*/
- u_int32_t max_msg_len;
+ uint32_t max_msg_len;
/**
* Flags set for completed actions
*/
- u_int32_t action_flags;
-
- /**
- * Access Requestor ID Type
- */
- u_int32_t ar_id_type;
-
- /**
- * Access Requestor ID Value
- */
- chunk_t ar_id_value;
+ uint32_t action_flags;
/**
* IMV database session associated with TNCCS connection
@@ -113,7 +103,7 @@ struct private_imv_attestation_state_t {
/**
* Measurement error flags
*/
- u_int32_t measurement_error;
+ uint32_t measurement_error;
/**
* TNC Reason String
@@ -215,46 +205,29 @@ METHOD(imv_state_t, set_flags, void,
}
METHOD(imv_state_t, set_max_msg_len, void,
- private_imv_attestation_state_t *this, u_int32_t max_msg_len)
+ 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, u_int32_t,
+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, u_int32_t flags)
+ private_imv_attestation_state_t *this, uint32_t flags)
{
this->action_flags |= flags;
}
-METHOD(imv_state_t, get_action_flags, u_int32_t,
+METHOD(imv_state_t, get_action_flags, uint32_t,
private_imv_attestation_state_t *this)
{
return this->action_flags;
}
-METHOD(imv_state_t, set_ar_id, void,
- private_imv_attestation_state_t *this, u_int32_t id_type, chunk_t id_value)
-{
- this->ar_id_type = id_type;
- this->ar_id_value = chunk_clone(id_value);
-}
-
-METHOD(imv_state_t, get_ar_id, chunk_t,
- private_imv_attestation_state_t *this, u_int32_t *id_type)
-{
- if (id_type)
- {
- *id_type = this->ar_id_type;
- }
- return this->ar_id_value;
-}
-
METHOD(imv_state_t, set_session, void,
private_imv_attestation_state_t *this, imv_session_t *session)
{
@@ -362,7 +335,6 @@ METHOD(imv_state_t, destroy, void,
DESTROY_IF(this->reason_string);
this->components->destroy_function(this->components, (void *)free_func_comp);
this->pts->destroy(this->pts);
- free(this->ar_id_value.ptr);
free(this);
}
@@ -387,7 +359,7 @@ METHOD(imv_attestation_state_t, get_pts, pts_t*,
METHOD(imv_attestation_state_t, create_component, pts_component_t*,
private_imv_attestation_state_t *this, pts_comp_func_name_t *name,
- u_int32_t depth, pts_database_t *pts_db)
+ uint32_t depth, pts_database_t *pts_db)
{
enumerator_t *enumerator;
func_comp_t *entry, *new_entry;
@@ -437,8 +409,8 @@ METHOD(imv_attestation_state_t, create_component, pts_component_t*,
/**
* Enumerate file measurement entries
*/
-static bool entry_filter(void *null, func_comp_t **entry, u_int8_t *flags,
- void *i2, u_int32_t *depth,
+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;
@@ -482,28 +454,38 @@ METHOD(imv_attestation_state_t, get_component, pts_component_t*,
return found;
}
-METHOD(imv_attestation_state_t, get_measurement_error, u_int32_t,
+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, u_int32_t error)
+ 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)
+ 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)))
+ entry->name->get_qualifier(entry->name),
+ result))
{
set_measurement_error(this, IMV_ATTESTATION_ERROR_COMP_EVID_PEND);
}
@@ -529,8 +511,6 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id)
.get_max_msg_len = _get_max_msg_len,
.set_action_flags = _set_action_flags,
.get_action_flags = _get_action_flags,
- .set_ar_id = _set_ar_id,
- .get_ar_id = _get_ar_id,
.set_session = _set_session,
.get_session = _get_session,
.change_state = _change_state,
diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.h b/src/libpts/plugins/imv_attestation/imv_attestation_state.h
index 9369d30a2..b72857552 100644
--- a/src/libpts/plugins/imv_attestation/imv_attestation_state.h
+++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.h
@@ -29,7 +29,9 @@
#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;
@@ -40,10 +42,15 @@ typedef enum imv_meas_error_t imv_meas_error_t;
* IMV Attestation Flags set for completed actions
*/
enum imv_attestation_flag_t {
- IMV_ATTESTATION_FLAG_ATTR_REQ = (1<<0),
- IMV_ATTESTATION_FLAG_ALGO = (1<<1),
- IMV_ATTESTATION_FLAG_FILE_MEAS = (1<<2),
- IMV_ATTESTATION_FLAG_REC = (1<<3)
+ 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)
};
/**
@@ -114,7 +121,7 @@ struct imv_attestation_state_t {
*/
pts_component_t* (*create_component)(imv_attestation_state_t *this,
pts_comp_func_name_t *name,
- u_int32_t depth,
+ uint32_t depth,
pts_database_t *pts_db);
/**
@@ -136,15 +143,18 @@ struct imv_attestation_state_t {
/**
* 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);
+ void (*finalize_components)(imv_attestation_state_t *this,
+ bio_writer_t *result);
/**
* Indicates the types of measurement errors that occurred
*
* @return Measurement error flags
*/
- u_int32_t (*get_measurement_error)(imv_attestation_state_t *this);
+ uint32_t (*get_measurement_error)(imv_attestation_state_t *this);
/**
* Call if a measurement error is encountered
@@ -152,7 +162,7 @@ struct imv_attestation_state_t {
* @param error Measurement error type
*/
void (*set_measurement_error)(imv_attestation_state_t *this,
- u_int32_t error);
+ uint32_t error);
/**
* Returns a concatenation of File Measurement reason strings
diff --git a/src/libpts/plugins/imv_swid/Makefile.am b/src/libpts/plugins/imv_swid/Makefile.am
index 29c05e0ab..77f33e6c6 100644
--- a/src/libpts/plugins/imv_swid/Makefile.am
+++ b/src/libpts/plugins/imv_swid/Makefile.am
@@ -5,17 +5,19 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libpts
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
imcv_LTLIBRARIES = imv-swid.la
imv_swid_la_LIBADD = \
$(top_builddir)/src/libimcv/libimcv.la \
$(top_builddir)/src/libpts/libpts.la \
- $(top_builddir)/src/libstrongswan/libstrongswan.la
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ -ljson
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_agent.h imv_swid_agent.c \
+ imv_swid_rest.h imv_swid_rest.c
imv_swid_la_LDFLAGS = -module -avoid-version -no-undefined
diff --git a/src/libpts/plugins/imv_swid/Makefile.in b/src/libpts/plugins/imv_swid/Makefile.in
index f9bd93ce0..bd89a6f90 100644
--- a/src/libpts/plugins/imv_swid/Makefile.in
+++ b/src/libpts/plugins/imv_swid/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.13.3 from Makefile.am.
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -131,7 +131,7 @@ imv_swid_la_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la \
$(top_builddir)/src/libpts/libpts.la \
$(top_builddir)/src/libstrongswan/libstrongswan.la
am_imv_swid_la_OBJECTS = imv_swid.lo imv_swid_state.lo \
- imv_swid_agent.lo
+ imv_swid_agent.lo imv_swid_rest.lo
imv_swid_la_OBJECTS = $(am_imv_swid_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -263,6 +263,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
@@ -281,6 +282,7 @@ PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
PTHREADLIB = @PTHREADLIB@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
@@ -308,6 +310,7 @@ abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
@@ -399,6 +402,7 @@ srcdir = @srcdir@
starter_plugins = @starter_plugins@
strongswan_conf = @strongswan_conf@
strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
sysconfdir = @sysconfdir@
systemdsystemunitdir = @systemdsystemunitdir@
t_plugins = @t_plugins@
@@ -416,17 +420,19 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/libpts
AM_CFLAGS = \
- -rdynamic
+ $(PLUGIN_CFLAGS)
imcv_LTLIBRARIES = imv-swid.la
imv_swid_la_LIBADD = \
$(top_builddir)/src/libimcv/libimcv.la \
$(top_builddir)/src/libpts/libpts.la \
- $(top_builddir)/src/libstrongswan/libstrongswan.la
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ -ljson
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_agent.h imv_swid_agent.c \
+ imv_swid_rest.h imv_swid_rest.c
imv_swid_la_LDFLAGS = -module -avoid-version -no-undefined
all: all-am
@@ -510,6 +516,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_swid.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_swid_agent.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_swid_rest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_swid_state.Plo@am__quote@
.c.o:
diff --git a/src/libpts/plugins/imv_swid/imv_swid_agent.c b/src/libpts/plugins/imv_swid/imv_swid_agent.c
index a0326f88d..3053b2643 100644
--- a/src/libpts/plugins/imv_swid/imv_swid_agent.c
+++ b/src/libpts/plugins/imv_swid/imv_swid_agent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -13,8 +13,12 @@
* 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 "libpts.h"
#include "swid/swid_error.h"
@@ -27,6 +31,8 @@
#include <ietf/ietf_attr_pa_tnc_error.h>
#include <imv/imv_agent.h>
#include <imv/imv_msg.h>
+#include <ita/ita_attr.h>
+#include <ita/ita_attr_angel.h>
#include <tncif_names.h>
#include <tncif_pa_subtypes.h>
@@ -43,6 +49,14 @@ static pen_type_t msg_types[] = {
};
/**
+ * 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 {
@@ -57,6 +71,11 @@ struct private_imv_swid_agent_t {
*/
imv_agent_t *agent;
+ /**
+ * REST API to strongTNC manager
+ */
+ imv_swid_rest_t *rest_api;
+
};
METHOD(imv_agent_if_t, bind_functions, TNC_Result,
@@ -89,8 +108,8 @@ METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
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;
- imv_session_t *session;
enumerator_t *enumerator;
pa_tnc_attr_t *attr;
TNC_Result result;
@@ -103,22 +122,16 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
return result;
}
- session = state->get_session(state);
+ swid_state = (imv_swid_state_t*)state;
/* analyze PA-TNC attributes */
enumerator = in_msg->create_attribute_enumerator(in_msg);
while (enumerator->enumerate(enumerator, &attr))
{
- TNC_IMV_Evaluation_Result eval;
- TNC_IMV_Action_Recommendation rec;
- pen_type_t type;
- u_int32_t request_id, last_eid, eid_epoch;
+ uint32_t request_id = 0, last_eid, eid_epoch;
swid_inventory_t *inventory;
- int tag_count;
- char result_str[BUF_LEN], *tag_item;
- imv_workitem_t *workitem, *found = NULL;
- enumerator_t *et, *ew;
-
+ pen_type_t type;
+
type = attr->get_type(attr);
if (type.vendor_id == PEN_IETF && type.type == IETF_ATTR_PA_TNC_ERROR)
@@ -127,7 +140,7 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
pen_type_t error_code;
chunk_t msg_info, description;
bio_reader_t *reader;
- u_int32_t request_id = 0, max_attr_size;
+ uint32_t max_attr_size;
bool success;
error_attr = (ietf_attr_pa_tnc_error_t*)attr;
@@ -166,6 +179,20 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
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;
@@ -176,33 +203,30 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
case TCG_SWID_TAG_ID_INVENTORY:
{
tcg_swid_attr_tag_id_inv_t *attr_cast;
- swid_tag_id_t *tag_id;
- chunk_t tag_creator, unique_sw_id;
+ 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_item = "tag ID";
- DBG2(DBG_IMV, "received SWID %s inventory for request %d "
- "at eid %d of epoch 0x%08x", tag_item,
+ 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);
- et = inventory->create_enumerator(inventory);
- while (et->enumerate(et, &tag_id))
+ if (request_id == swid_state->get_request_id(swid_state))
{
- tag_creator = tag_id->get_tag_creator(tag_id);
- unique_sw_id = tag_id->get_unique_sw_id(tag_id, NULL);
- DBG3(DBG_IMV, " %.*s_%.*s.swidtag",
- tag_creator.len, tag_creator.ptr,
- unique_sw_id.len, unique_sw_id.ptr);
+ swid_state->set_swid_inventory(swid_state, inventory);
+ swid_state->set_count(swid_state, tag_id_count, 0);
}
- et->destroy(et);
-
- if (request_id == 0)
+ else
{
- /* TODO handle subscribed messages */
- break;
+ DBG1(DBG_IMV, "no workitem found for SWID tag ID inventory "
+ "with request ID %d", request_id);
}
break;
}
@@ -211,62 +235,64 @@ static TNC_Result receive_msg(private_imv_swid_agent_t *this,
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_item = "tag";
- DBG2(DBG_IMV, "received SWID %s inventory for request %d "
- "at eid %d of epoch 0x%08x", tag_item,
+ 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);
- et = inventory->create_enumerator(inventory);
- while (et->enumerate(et, &tag))
+
+ if (request_id == swid_state->get_request_id(swid_state))
{
- tag_encoding = tag->get_encoding(tag);
- DBG3(DBG_IMV, "%.*s", tag_encoding.len, tag_encoding.ptr);
- }
- et->destroy(et);
+ swid_state->set_count(swid_state, 0, tag_count);
- if (request_id == 0)
+ 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
{
- /* TODO handle subscribed messages */
- break;
+ DBG1(DBG_IMV, "no workitem found for SWID tag inventory "
+ "with request ID %d", request_id);
}
- break;
}
default:
continue;
}
-
- ew = session->create_workitem_enumerator(session);
- while (ew->enumerate(ew, &workitem))
- {
- if (workitem->get_id(workitem) == request_id)
- {
- found = workitem;
- break;
- }
- }
- if (!found)
- {
- DBG1(DBG_IMV, "no workitem found for SWID %s inventory "
- "with request ID %d", tag_item, request_id);
- ew->destroy(ew);
- continue;
- }
-
- eval = TNC_IMV_EVALUATION_RESULT_COMPLIANT;
- tag_count = inventory->get_count(inventory);
- snprintf(result_str, BUF_LEN, "received inventory of %d SWID %s%s",
- tag_count, tag_item, (tag_count == 1) ? "" : "s");
- session->remove_workitem(session, ew);
- ew->destroy(ew);
- rec = found->set_result(found, result_str, eval);
- state->update_recommendation(state, rec, eval);
- imcv_db->finalize_workitem(imcv_db, found);
- found->destroy(found);
}
enumerator->destroy(enumerator);
@@ -342,8 +368,8 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
TNC_IMVID imv_id;
TNC_Result result = TNC_RESULT_SUCCESS;
bool no_workitems = TRUE;
- u_int32_t request_id;
- u_int8_t flags;
+ uint32_t request_id, received;
+ uint8_t flags;
enumerator_t *enumerator;
if (!this->agent->get_state(this->agent, id, &state))
@@ -360,11 +386,11 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
return TNC_RESULT_SUCCESS;
}
- /* create an empty out message - we might need it */
+ /* 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 (!session)
+ if (!imcv_db)
{
DBG2(DBG_IMV, "no workitems available - no evaluation possible");
state->set_recommendation(state,
@@ -381,7 +407,9 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
return this->agent->provide_recommendation(this->agent, state);
}
- if (handshake_state == IMV_SWID_STATE_INIT)
+ /* Look for SWID tag workitem and create SWID tag request */
+ if (handshake_state == IMV_SWID_STATE_INIT &&
+ session->get_policy_started(session))
{
enumerator = session->create_workitem_enumerator(session);
if (enumerator)
@@ -408,13 +436,14 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
flags |= TCG_SWID_ATTR_REQ_FLAG_C;
}
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);
@@ -431,6 +460,171 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
}
}
+ 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)
@@ -471,6 +665,7 @@ METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
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);
libpts_deinit();
@@ -484,6 +679,8 @@ imv_agent_if_t *imv_swid_agent_create(const char *name, TNC_IMVID id,
{
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);
@@ -505,6 +702,14 @@ imv_agent_if_t *imv_swid_agent_create(const char *name, TNC_IMVID id,
.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);
+ }
libpts_init();
return &this->public;
diff --git a/src/libpts/plugins/imv_swid/imv_swid_rest.c b/src/libpts/plugins/imv_swid/imv_swid_rest.c
new file mode 100644
index 000000000..143b0b239
--- /dev/null
+++ b/src/libpts/plugins/imv_swid/imv_swid_rest.c
@@ -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;
+}
+
+
diff --git a/src/libpts/plugins/imv_swid/imv_swid_rest.h b/src/libpts/plugins/imv_swid/imv_swid_rest.h
new file mode 100644
index 000000000..93e3d6ab9
--- /dev/null
+++ b/src/libpts/plugins/imv_swid/imv_swid_rest.h
@@ -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/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_ @}*/
diff --git a/src/libpts/plugins/imv_swid/imv_swid_state.c b/src/libpts/plugins/imv_swid/imv_swid_state.c
index 5be8c0254..c68b57e4d 100644
--- a/src/libpts/plugins/imv_swid/imv_swid_state.c
+++ b/src/libpts/plugins/imv_swid/imv_swid_state.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,9 +14,11 @@
*/
#include "imv_swid_state.h"
-#include "imv/imv_lang_string.h"
-#include "imv/imv_reason_string.h"
-#include "imv/imv_remediation_string.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>
@@ -58,22 +60,12 @@ struct private_imv_swid_state_t {
/**
* Maximum PA-TNC message size for this TNCCS connection
*/
- u_int32_t max_msg_len;
+ uint32_t max_msg_len;
/**
* Flags set for completed actions
*/
- u_int32_t action_flags;
-
- /**
- * Access Requestor ID Type
- */
- u_int32_t ar_id_type;
-
- /**
- * Access Requestor ID Value
- */
- chunk_t ar_id_value;
+ uint32_t action_flags;
/**
* IMV database session associatied with TNCCS connection
@@ -105,6 +97,36 @@ struct private_imv_swid_state_t {
*/
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,
@@ -133,46 +155,29 @@ METHOD(imv_state_t, set_flags, void,
}
METHOD(imv_state_t, set_max_msg_len, void,
- private_imv_swid_state_t *this, u_int32_t max_msg_len)
+ 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, u_int32_t,
+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, u_int32_t flags)
+ private_imv_swid_state_t *this, uint32_t flags)
{
this->action_flags |= flags;
}
-METHOD(imv_state_t, get_action_flags, u_int32_t,
+METHOD(imv_state_t, get_action_flags, uint32_t,
private_imv_swid_state_t *this)
{
return this->action_flags;
}
-METHOD(imv_state_t, set_ar_id, void,
- private_imv_swid_state_t *this, u_int32_t id_type, chunk_t id_value)
-{
- this->ar_id_type = id_type;
- this->ar_id_value = chunk_clone(id_value);
-}
-
-METHOD(imv_state_t, get_ar_id, chunk_t,
- private_imv_swid_state_t *this, u_int32_t *id_type)
-{
- if (id_type)
- {
- *id_type = this->ar_id_type;
- }
- return this->ar_id_value;
-}
-
METHOD(imv_state_t, set_session, void,
private_imv_swid_state_t *this, imv_session_t *session)
{
@@ -232,10 +237,10 @@ METHOD(imv_state_t, get_remediation_instructions, bool,
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);
- free(this->ar_id_value.ptr);
free(this);
}
@@ -251,6 +256,83 @@ METHOD(imv_swid_state_t, get_handshake_state, imv_swid_handshake_state_t,
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.
*/
@@ -269,8 +351,6 @@ imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
.get_max_msg_len = _get_max_msg_len,
.set_action_flags = _set_action_flags,
.get_action_flags = _get_action_flags,
- .set_ar_id = _set_ar_id,
- .get_ar_id = _get_ar_id,
.set_session = _set_session,
.get_session= _get_session,
.change_state = _change_state,
@@ -283,13 +363,25 @@ imv_state_t *imv_swid_state_create(TNC_ConnectionID connection_id)
},
.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,
+ .jobj = json_object_new_object(),
+ .jarray = json_object_new_array(),
);
+ json_object_object_add(this->jobj, "data", this->jarray);
+
return &this->public.interface;
}
diff --git a/src/libpts/plugins/imv_swid/imv_swid_state.h b/src/libpts/plugins/imv_swid/imv_swid_state.h
index d6e5840df..7ffabfd26 100644
--- a/src/libpts/plugins/imv_swid/imv_swid_state.h
+++ b/src/libpts/plugins/imv_swid/imv_swid_state.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -25,8 +25,11 @@
#define IMV_SWID_STATE_H_
#include <imv/imv_state.h>
+#include <swid/swid_inventory.h>
#include <library.h>
+#include <json/json.h>
+
typedef struct imv_swid_state_t imv_swid_state_t;
typedef enum imv_swid_handshake_state_t imv_swid_handshake_state_t;
@@ -64,6 +67,64 @@ struct imv_swid_state_t {
*/
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);
+
};
/**
diff --git a/src/libpts/pts/components/ita/ita_comp_ima.c b/src/libpts/pts/components/ita/ita_comp_ima.c
index c6b4131bf..be8aa40ad 100644
--- a/src/libpts/pts/components/ita/ita_comp_ima.c
+++ b/src/libpts/pts/components/ita/ita_comp_ima.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,27 +18,20 @@
#include "libpts.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>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.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_PCR 10
-#define IMA_TYPE_LEN 3
-#define IMA_FILENAME_LEN_MAX 255
+#define IMA_FILENAME_LEN_MAX 255
typedef struct pts_ita_comp_ima_t pts_ita_comp_ima_t;
-typedef struct bios_entry_t bios_entry_t;
-typedef struct ima_entry_t ima_entry_t;
typedef enum ima_state_t ima_state_t;
enum ima_state_t {
@@ -66,14 +59,9 @@ struct pts_ita_comp_ima_t {
pts_comp_func_name_t *name;
/**
- * AIK keyid
- */
- chunk_t keyid;
-
- /**
* Sub-component depth
*/
- u_int32_t depth;
+ uint32_t depth;
/**
* PTS measurement database
@@ -83,7 +71,7 @@ struct pts_ita_comp_ima_t {
/**
* Primary key for AIK database entry
*/
- int kid;
+ int aik_id;
/**
* Primary key for IMA BIOS Component Functional Name database entry
@@ -118,12 +106,12 @@ struct pts_ita_comp_ima_t {
/**
* IMA BIOS measurements
*/
- linked_list_t *bios_list;
+ pts_ima_bios_list_t *bios_list;
/**
* IMA runtime file measurements
*/
- linked_list_t *ima_list;
+ pts_ima_event_list_t *ima_list;
/**
* Whether to send pcr_before and pcr_after info
@@ -131,9 +119,9 @@ struct pts_ita_comp_ima_t {
bool pcr_info;
/**
- * IMA measurement time
+ * Creation time of measurement
*/
- time_t measurement_time;
+ time_t creation_time;
/**
* IMA state machine
@@ -173,222 +161,11 @@ struct pts_ita_comp_ima_t {
};
/**
- * Linux IMA BIOS measurement entry
- */
-struct bios_entry_t {
-
- /**
- * PCR register
- */
- u_int32_t pcr;
-
- /**
- * SHA1 measurement hash
- */
- chunk_t measurement;
-};
-
-/**
- * Linux IMA runtime file measurement entry
- */
-struct ima_entry_t {
-
- /**
- * SHA1 measurement hash
- */
- chunk_t measurement;
-
- /**
- * absolute path of executable files or basename of dynamic libraries
- */
- char *filename;
-};
-
-/**
- * Free a bios_entry_t object
- */
-static void free_bios_entry(bios_entry_t *this)
-{
- free(this->measurement.ptr);
- free(this);
-}
-
-/**
- * Free an ima_entry_t object
- */
-static void free_ima_entry(ima_entry_t *this)
-{
- free(this->measurement.ptr);
- free(this->filename);
- free(this);
-}
-
-/**
- * Load a PCR measurement file and determine the creation date
- */
-static bool load_bios_measurements(char *file, linked_list_t *list,
- time_t *created)
-{
- u_int32_t pcr, num, len;
- 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 FALSE;
- }
-
- if (fstat(fd, &st) == -1)
- {
- DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
- strerror(errno));
- close(fd);
- return FALSE;
- }
- *created = st.st_ctime;
-
- while (TRUE)
- {
- res = read(fd, &pcr, 4);
- if (res == 0)
- {
- DBG2(DBG_PTS, "loaded bios measurements '%s' (%d entries)",
- file, list->get_count(list));
- close(fd);
- return TRUE;
- }
-
- entry = malloc_thing(bios_entry_t);
- entry->pcr = pcr;
- entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
-
- if (res != 4)
- {
- break;
- }
- if (read(fd, &num, 4) != 4)
- {
- break;
- }
- if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
- {
- break;
- }
- if (read(fd, &len, 4) != 4)
- {
- break;
- }
- if (lseek(fd, len, SEEK_CUR) == -1)
- {
- break;
- }
- list->insert_last(list, entry);
- }
-
- DBG1(DBG_PTS, "loading bios measurements '%s' failed: %s", file,
- strerror(errno));
- free_bios_entry(entry);
- close(fd);
- return FALSE;
-}
-
-/**
- * Load an IMA runtime measurement file and determine the creation and
- * update dates
- */
-static bool load_runtime_measurements(char *file, linked_list_t *list,
- time_t *created)
-{
- u_int32_t pcr, len;
- ima_entry_t *entry;
- char type[IMA_TYPE_LEN];
- 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 TRUE;
- }
-
- if (fstat(fd, &st) == -1)
- {
- DBG1(DBG_PTS, "getting statistics of '%s' failed: %s", file,
- strerror(errno));
- close(fd);
- return FALSE;
- }
- *created = st.st_ctime;
-
- while (TRUE)
- {
- res = read(fd, &pcr, 4);
- if (res == 0)
- {
- DBG2(DBG_PTS, "loaded ima measurements '%s' (%d entries)",
- file, list->get_count(list));
- close(fd);
- return TRUE;
- }
-
- entry = malloc_thing(ima_entry_t);
- entry->measurement = chunk_alloc(HASH_SIZE_SHA1);
- entry->filename = NULL;
-
- if (res != 4 || pcr != IMA_PCR)
- {
- break;
- }
- if (read(fd, entry->measurement.ptr, HASH_SIZE_SHA1) != HASH_SIZE_SHA1)
- {
- break;
- }
- if (read(fd, &len, 4) != 4 || len != IMA_TYPE_LEN)
- {
- break;
- }
- if (read(fd, type, IMA_TYPE_LEN) != IMA_TYPE_LEN ||
- memcmp(type, "ima", IMA_TYPE_LEN))
- {
- break;
- }
- if (lseek(fd, HASH_SIZE_SHA1, SEEK_CUR) == -1)
- {
- break;
- }
- if (read(fd, &len, 4) != 4)
- {
- break;
- }
- entry->filename = malloc(len + 1);
- if (read(fd, entry->filename, len) != len)
- {
- break;
- }
- entry->filename[len] = '\0';
-
- list->insert_last(list, entry);
- }
-
- DBG1(DBG_PTS, "loading ima measurements '%s' failed: %s",
- file, strerror(errno));
- free_ima_entry(entry);
- close(fd);
- return FALSE;
-}
-
-/**
- * Extend measurement into PCR an create evidence
+ * Extend measurement into PCR and create evidence
*/
static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
- u_int8_t qualifier, pts_pcr_t *pcrs,
- u_int32_t pcr, chunk_t measurement)
+ uint8_t qualifier, pts_pcr_t *pcrs,
+ uint32_t pcr, chunk_t measurement)
{
size_t pcr_len;
pts_pcr_transform_t pcr_transform;
@@ -414,7 +191,7 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
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->measurement_time, measurement);
+ pcr_transform, this->creation_time, measurement);
if (this->pcr_info)
{
pcr_after =chunk_clone(pcrs->get(pcrs, pcr));
@@ -424,15 +201,83 @@ static pts_comp_evidence_t* extend_pcr(pts_ita_comp_ima_t* this,
}
/**
+ * 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)
+static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement,
+ char *algo)
{
- u_int32_t i;
- u_char filename_buffer[IMA_FILENAME_LEN_MAX + 1];
u_char pcr_buffer[HASH_SIZE_SHA1];
- chunk_t file_name, boot_aggregate;
+ chunk_t boot_aggregate;
hasher_t *hasher;
+ uint32_t i;
bool success, pcr_ok = TRUE;
hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
@@ -448,19 +293,20 @@ static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement)
}
if (pcr_ok)
{
- boot_aggregate = chunk_create(pcr_buffer, sizeof(pcr_buffer));
- memset(filename_buffer, 0, sizeof(filename_buffer));
- strcpy(filename_buffer, "boot_aggregate");
- file_name = chunk_create (filename_buffer, sizeof(filename_buffer));
-
- pcr_ok = hasher->get_hash(hasher, chunk_empty, pcr_buffer) &&
- hasher->get_hash(hasher, boot_aggregate, NULL) &&
- hasher->get_hash(hasher, file_name, boot_aggregate.ptr);
+ 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");
@@ -479,26 +325,28 @@ METHOD(pts_component_t, get_comp_func_name, pts_comp_func_name_t*,
return this->name;
}
-METHOD(pts_component_t, get_evidence_flags, u_int8_t,
+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, u_int32_t,
+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, u_int8_t qualifier, pts_t *pts,
+ pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
pts_comp_evidence_t **evidence)
{
- bios_entry_t *bios_entry;
- ima_entry_t *ima_entry;
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);
@@ -509,25 +357,25 @@ METHOD(pts_component_t, measure, status_t,
switch (this->state)
{
case IMA_STATE_INIT:
- if (!load_bios_measurements(IMA_BIOS_MEASUREMENTS,
- this->bios_list, &this->measurement_time))
+ 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->remove_first(this->bios_list,
- (void**)&bios_entry);
+ 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, bios_entry->pcr,
- bios_entry->measurement);
- free(bios_entry);
+ evid = extend_pcr(this, qualifier, pcrs, pcr, measurement);
this->state = this->bios_list->get_count(this->bios_list) ?
IMA_STATE_BIOS : IMA_STATE_INIT;
@@ -542,17 +390,20 @@ METHOD(pts_component_t, measure, status_t,
switch (this->state)
{
case IMA_STATE_INIT:
- if (!load_runtime_measurements(IMA_RUNTIME_MEASUREMENTS,
- this->ima_list, &this->measurement_time))
+ 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->remove_first(this->ima_list,
- (void**)&ima_entry);
+ status = this->ima_list->get_next(this->ima_list, &measurement,
+ &algo, &name);
if (status != SUCCESS)
{
DBG1(DBG_PTS, "could not retrieve ima measurement entry");
@@ -560,20 +411,33 @@ METHOD(pts_component_t, measure, status_t,
}
if (this->state == IMA_STATE_BOOT_AGGREGATE && this->bios_count)
{
- if (!check_boot_aggregate(pcrs, ima_entry->measurement))
+ if (!check_boot_aggregate(pcrs, measurement, algo))
{
return FAILED;
}
}
evid = extend_pcr(this, qualifier, pcrs, IMA_PCR,
- ima_entry->measurement);
+ 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,
- ima_entry->filename);
+ uri);
+ free(uri);
}
- free(ima_entry->filename);
- free(ima_entry);
+ free(name);
+ free(algo);
this->state = this->ima_list->get_count(this->ima_list) ?
IMA_STATE_RUNTIME : IMA_STATE_END;
@@ -598,40 +462,80 @@ METHOD(pts_component_t, measure, status_t,
SUCCESS : NEED_MORE;
}
-METHOD(pts_component_t, verify, status_t,
- pts_ita_comp_ima_t *this, u_int8_t qualifier, pts_t *pts,
- pts_comp_evidence_t *evidence)
+/**
+ * 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)
{
- bool has_pcr_info;
- u_int32_t 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;
- char *uri;
+ pts_meas_algorithms_t hash_algo;
+ char *uri, *pos, *algo, *name;
- /* some first time initializations */
- if (!this->keyid.ptr)
+ evidence->get_validation(evidence, &uri);
+
+ /* IMA-NG format? */
+ pos = strchr(uri, ':');
+ if (pos && (pos - uri + 1) < IMA_ALGO_LEN_MAX)
{
- if (!pts->get_aik_keyid(pts, &this->keyid))
+ 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:"))
{
- DBG1(DBG_PTS, "AIK keyid not available");
- return FAILED;
+ hash_algo = PTS_MEAS_ALGO_SHA256;
}
- this->keyid = chunk_clone(this->keyid);
- if (!this->pts_db)
+ else if (streq(algo, "sha384:"))
{
- DBG1(DBG_PTS, "pts database not available");
- return FAILED;
+ 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,
- &measurement_time);
+ &creation_time);
if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
PTS_ITA_QUALIFIER_TYPE_TRUSTED))
@@ -641,26 +545,22 @@ METHOD(pts_component_t, verify, status_t,
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->keyid, algo, &this->bios_cid,
- &this->kid, &this->bios_count);
+ 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;
}
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
if (this->bios_count)
{
- DBG1(DBG_PTS, "checking %d %N '%N' BIOS evidence measurements",
- this->bios_count, pen_names, vid, names, name);
+ DBG1(DBG_PTS, "checking %d BIOS evidence measurements",
+ this->bios_count);
}
else
{
- DBG1(DBG_PTS, "registering %N '%N' BIOS evidence measurements",
- pen_names, vid, names, name);
+ DBG1(DBG_PTS, "registering BIOS evidence measurements");
this->is_bios_registering = TRUE;
}
@@ -670,8 +570,8 @@ METHOD(pts_component_t, verify, status_t,
if (this->is_bios_registering)
{
status = this->pts_db->insert_comp_measurement(this->pts_db,
- measurement, this->bios_cid, this->kid,
- ++this->seq_no, pcr, algo);
+ measurement, this->bios_cid, this->aik_id,
+ ++this->seq_no, pcr, algo);
if (status != SUCCESS)
{
return status;
@@ -681,8 +581,8 @@ METHOD(pts_component_t, verify, status_t,
else
{
status = this->pts_db->check_comp_measurement(this->pts_db,
- measurement, this->bios_cid, this->kid,
- ++this->seq_no, pcr, algo);
+ measurement, this->bios_cid, this->aik_id,
+ ++this->seq_no, pcr, algo);
if (status == FAILED)
{
return status;
@@ -697,13 +597,34 @@ METHOD(pts_component_t, verify, status_t,
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:
- if (!check_boot_aggregate(pcrs, measurement))
+ 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))
{
- this->state = IMA_STATE_RUNTIME;
return FAILED;
}
this->state = IMA_STATE_INIT;
@@ -711,33 +632,30 @@ METHOD(pts_component_t, verify, status_t,
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->keyid, algo,
- &this->ima_cid, &this->kid, &ima_count);
+ 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;
}
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
if (ima_count)
{
- DBG1(DBG_PTS, "checking %N '%N' boot aggregate evidence "
- "measurement", pen_names, vid, names, name);
+ DBG1(DBG_PTS, "checking boot aggregate evidence "
+ "measurement");
status = this->pts_db->check_comp_measurement(this->pts_db,
measurement, this->ima_cid,
- this->kid, 1, pcr, algo);
+ this->aik_id, 1, pcr, algo);
}
else
{
- DBG1(DBG_PTS, "registering %N '%N' boot aggregate evidence "
- "measurement", pen_names, vid, names, name);
+ 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->kid, 1, pcr, algo);
+ this->aik_id, 1, pcr, algo);
}
this->state = IMA_STATE_RUNTIME;
@@ -747,42 +665,76 @@ METHOD(pts_component_t, verify, status_t,
}
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, &uri) !=
+ if (evidence->get_validation(evidence, NULL) !=
PTS_COMP_EVID_VALIDATION_PASSED)
{
- DBG1(DBG_PTS, "policy URI could no be retrieved");
+ DBG1(DBG_PTS, "evidence validation failed");
this->count_failed++;
return FAILED;
}
- status = this->pts_db->check_file_measurement(this->pts_db,
- pts->get_platform_info(pts),
- PTS_MEAS_ALGO_SHA1_IMA,
- measurement, uri);
+ 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, uri);
+ &measurement, ima_name);
this->count_ok++;
break;
case NOT_FOUND:
DBG2(DBG_PTS, "%#B for '%s' not found",
- &measurement, uri);
+ &measurement, ima_name);
this->count_unknown++;
break;
case VERIFY_ERROR:
DBG1(DBG_PTS, "%#B for '%s' differs",
- &measurement, uri);
+ &measurement, ima_name);
this->count_differ++;
break;
case FAILED:
default:
DBG1(DBG_PTS, "%#B for '%s' failed",
- &measurement, uri);
+ &measurement, ima_name);
this->count_failed++;
}
break;
+ }
default:
return FAILED;
}
@@ -818,16 +770,15 @@ METHOD(pts_component_t, verify, status_t,
}
METHOD(pts_component_t, finalize, bool,
- pts_ita_comp_ima_t *this, u_int8_t qualifier)
+ pts_ita_comp_ima_t *this, uint8_t qualifier, bio_writer_t *result)
{
- u_int32_t vid, name;
- enum_name_t *names;
+ 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);
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
if (qualifier == (PTS_ITA_QUALIFIER_FLAG_KERNEL |
PTS_ITA_QUALIFIER_TYPE_TRUSTED))
@@ -838,16 +789,20 @@ METHOD(pts_component_t, finalize, bool,
/* close registration */
this->is_bios_registering = FALSE;
- DBG1(DBG_PTS, "registered %d %N '%N' BIOS evidence measurements",
- this->seq_no, pen_names, vid, names, name);
+ snprintf(pos, len, "registered %d BIOS evidence measurements",
+ this->seq_no);
}
else if (this->seq_no < this->bios_count)
{
- DBG1(DBG_PTS, "%d of %d %N '%N' BIOS evidence measurements missing",
- this->bios_count - this->seq_no, this->bios_count,
- pen_names, vid, names, name);
+ 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))
@@ -858,26 +813,34 @@ METHOD(pts_component_t, finalize, bool,
/* close registration */
this->is_ima_registering = FALSE;
- DBG1(DBG_PTS, "registered %N '%N' boot aggregate evidence "
- "measurement", pen_names, vid, names, name);
+ written = snprintf(pos, len, "registered IMA boot aggregate "
+ "evidence measurement; ");
+ pos += written;
+ len -= written;
}
if (this->count)
{
- DBG1(DBG_PTS, "processed %d %N '%N' file evidence measurements: "
- "%d ok, %d unknown, %d differ, %d failed",
- this->count, pen_names, vid, names, name,
- this->count_ok, this->count_unknown,
- this->count_differ, this->count_failed);
- success = !this->count_differ && !this->count_failed;
+ 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
{
- DBG1(DBG_PTS, "unsupported functional component name qualifier");
+ 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;
}
@@ -892,35 +855,28 @@ METHOD(pts_component_t, destroy, void,
pts_ita_comp_ima_t *this)
{
int count;
- u_int32_t vid, name;
- enum_name_t *names;
if (ref_put(&this->ref))
{
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
if (this->is_bios_registering)
{
count = this->pts_db->delete_comp_measurements(this->pts_db,
- this->bios_cid, this->kid);
- DBG1(DBG_PTS, "deleted %d registered %N '%N' BIOS evidence "
- "measurements", count, pen_names, vid, names, name);
+ 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->kid);
- DBG1(DBG_PTS, "deleted registered %N '%N' boot aggregate evidence "
- "measurement", pen_names, vid, names, name);
+ this->ima_cid, this->aik_id);
+ DBG1(DBG_PTS, "deleted registered boot aggregate evidence "
+ "measurement");
}
- this->bios_list->destroy_function(this->bios_list,
- (void *)free_bios_entry);
- this->ima_list->destroy_function(this->ima_list,
- (void *)free_ima_entry);
+ DESTROY_IF(this->bios_list);
+ DESTROY_IF(this->ima_list);
this->name->destroy(this->name);
- free(this->keyid.ptr);
+
free(this);
}
}
@@ -928,7 +884,7 @@ METHOD(pts_component_t, destroy, void,
/**
* See header
*/
-pts_component_t *pts_ita_comp_ima_create(u_int32_t depth,
+pts_component_t *pts_ita_comp_ima_create(uint32_t depth,
pts_database_t *pts_db)
{
pts_ita_comp_ima_t *this;
@@ -948,10 +904,8 @@ pts_component_t *pts_ita_comp_ima_create(u_int32_t depth,
PTS_QUALIFIER_UNKNOWN),
.depth = depth,
.pts_db = pts_db,
- .bios_list = linked_list_create(),
- .ima_list = linked_list_create(),
.pcr_info = lib->settings->get_bool(lib->settings,
- "%s.plugins.imc-attestation.pcr_info", TRUE, lib->ns),
+ "%s.plugins.imc-attestation.pcr_info", FALSE, lib->ns),
.ref = 1,
);
diff --git a/src/libpts/pts/components/ita/ita_comp_tboot.c b/src/libpts/pts/components/ita/ita_comp_tboot.c
index f4859f801..67be1ca3a 100644
--- a/src/libpts/pts/components/ita/ita_comp_tboot.c
+++ b/src/libpts/pts/components/ita/ita_comp_tboot.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -41,11 +41,6 @@ struct pts_ita_comp_tboot_t {
pts_comp_func_name_t *name;
/**
- * AIK keyid
- */
- chunk_t keyid;
-
- /**
* Sub-component depth
*/
u_int32_t depth;
@@ -56,6 +51,11 @@ struct pts_ita_comp_tboot_t {
pts_database_t *pts_db;
/**
+ * Primary key for AIK database entry
+ */
+ int aik_id;
+
+ /**
* Primary key for Component Functional Name database entry
*/
int cid;
@@ -201,51 +201,38 @@ METHOD(pts_component_t, verify, status_t,
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);
- if (!this->keyid.ptr)
+ status = this->pts_db->get_comp_measurement_count(this->pts_db,
+ this->name, this->aik_id, algo,
+ &this->cid, &this->count);
+ if (status != SUCCESS)
{
- if (!pts->get_aik_keyid(pts, &this->keyid))
- {
- return FAILED;
- }
- this->keyid = chunk_clone(this->keyid);
-
- if (!this->pts_db)
- {
- DBG1(DBG_PTS, "pts database not available");
- return FAILED;
- }
- status = this->pts_db->get_comp_measurement_count(this->pts_db,
- this->name, this->keyid, algo, &this->cid,
- &this->kid, &this->count);
- if (status != SUCCESS)
- {
- return status;
- }
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
+ return status;
+ }
+ vid = this->name->get_vendor_id(this->name);
+ name = this->name->get_name(this->name);
+ names = pts_components->get_comp_func_names(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->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->kid,
+ measurement, this->cid, this->aik_id,
++this->seq_no, extended_pcr, algo);
if (status != SUCCESS)
{
@@ -282,30 +269,31 @@ METHOD(pts_component_t, verify, status_t,
}
METHOD(pts_component_t, finalize, bool,
- pts_ita_comp_tboot_t *this, u_int8_t qualifier)
+ pts_ita_comp_tboot_t *this, u_int8_t qualifier, bio_writer_t *result)
{
- u_int32_t vid, name;
- enum_name_t *names;
-
- vid = this->name->get_vendor_id(this->name);
- name = this->name->get_name(this->name);
- names = pts_components->get_comp_func_names(pts_components, vid);
+ char result_buf[BUF_LEN];
if (this->is_registering)
{
/* close registration */
this->is_registering = FALSE;
- DBG1(DBG_PTS, "registered %d %N '%N' functional component evidence "
- "measurements", this->seq_no, pen_names, vid, names, name);
+ snprintf(result_buf, BUF_LEN, "registered %d evidence measurements",
+ this->seq_no);
}
else if (this->seq_no < this->count)
{
- DBG1(DBG_PTS, "%d of %d %N '%N' functional component evidence "
- "measurements missing", this->count - this->seq_no,
- this->count, pen_names, vid, names, name);
+ 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;
}
@@ -329,7 +317,7 @@ METHOD(pts_component_t, destroy, void,
if (this->is_registering)
{
count = this->pts_db->delete_comp_measurements(this->pts_db,
- this->cid, this->kid);
+ this->cid, this->aik_id);
vid = this->name->get_vendor_id(this->name);
name = this->name->get_name(this->name);
names = pts_components->get_comp_func_names(pts_components, vid);
@@ -337,7 +325,6 @@ METHOD(pts_component_t, destroy, void,
"evidence measurements", count, pen_names, vid, names, name);
}
this->name->destroy(this->name);
- free(this->keyid.ptr);
free(this);
}
}
diff --git a/src/libpts/pts/components/ita/ita_comp_tgrub.c b/src/libpts/pts/components/ita/ita_comp_tgrub.c
index e3acd8774..097e4c89c 100644
--- a/src/libpts/pts/components/ita/ita_comp_tgrub.c
+++ b/src/libpts/pts/components/ita/ita_comp_tgrub.c
@@ -49,7 +49,6 @@ struct pts_ita_comp_tgrub_t {
*/
pts_database_t *pts_db;
-
/**
* Reference count
*/
@@ -126,7 +125,8 @@ METHOD(pts_component_t, verify, status_t,
pts_pcr_transform_t transform;
pts_pcr_t *pcrs;
time_t measurement_time;
- chunk_t measurement, pcr_before, pcr_after;
+ chunk_t pcr_before, pcr_after;
+ chunk_t measurement __attribute__((unused));
pcrs = pts->get_pcrs(pts);
measurement = evidence->get_measurement(evidence, &extended_pcr,
@@ -155,7 +155,7 @@ METHOD(pts_component_t, verify, status_t,
}
METHOD(pts_component_t, finalize, bool,
- pts_ita_comp_tgrub_t *this, u_int8_t qualifier)
+ pts_ita_comp_tgrub_t *this, u_int8_t qualifier, bio_writer_t *result)
{
return FALSE;
}
@@ -206,4 +206,3 @@ pts_component_t *pts_ita_comp_tgrub_create(u_int32_t depth,
return &this->public;
}
-
diff --git a/src/libpts/pts/components/pts_component.h b/src/libpts/pts/components/pts_component.h
index da339a55f..71b1ad59c 100644
--- a/src/libpts/pts/components/pts_component.h
+++ b/src/libpts/pts/components/pts_component.h
@@ -30,6 +30,7 @@ typedef struct pts_component_t pts_component_t;
#include "pts/components/pts_comp_evidence.h"
#include <library.h>
+#include <bio/bio_writer.h>
/**
* PTS Functional Component Interface
@@ -85,9 +86,11 @@ struct pts_component_t {
* 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);
+ bool (*finalize)(pts_component_t *this, u_int8_t qualifier,
+ bio_writer_t *result);
/**
* Get a new reference to the PTS Functional Component
diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c
index 3ab9b92e6..2fff4c901 100644
--- a/src/libpts/pts/pts.c
+++ b/src/libpts/pts/pts.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * 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
@@ -21,6 +22,10 @@
#include <bio/bio_reader.h>
#ifdef TSS_TROUSERS
+#ifdef _BASETSD_H_
+/* MinGW defines _BASETSD_H_, but TSS checks for _BASETSD_H */
+# define _BASETSD_H
+#endif
#include <trousers/tss.h>
#include <trousers/trousers.h>
#else
@@ -34,7 +39,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/utsname.h>
#include <libgen.h>
#include <unistd.h>
#include <errno.h>
@@ -88,9 +92,9 @@ struct private_pts_t {
chunk_t secret;
/**
- * Platform and OS Info
+ * Primary key of platform entry in database
*/
- char *platform_info;
+ int platform_id;
/**
* TRUE if IMC-PTS, FALSE if IMV-PTS
@@ -118,6 +122,11 @@ struct private_pts_t {
certificate_t *aik;
/**
+ * Primary key referening AIK in database
+ */
+ int aik_id;
+
+ /**
* Shadow PCR set
*/
pts_pcr_t *pcrs;
@@ -296,29 +305,23 @@ METHOD(pts_t, calculate_secret, bool,
*/
static void print_tpm_version_info(private_pts_t *this)
{
- TPM_CAP_VERSION_INFO versionInfo;
- UINT64 offset = 0;
- TSS_RESULT result;
+ TPM_CAP_VERSION_INFO *info;
- result = Trspi_UnloadBlob_CAP_VERSION_INFO(&offset,
- this->tpm_version_info.ptr, &versionInfo);
- if (result != TSS_SUCCESS)
+ info = (TPM_CAP_VERSION_INFO*)this->tpm_version_info.ptr;
+
+ if (this->tpm_version_info.len >=
+ sizeof(*info) - sizeof(info->vendorSpecific))
{
- DBG1(DBG_PTS, "could not parse tpm version info: tss error 0x%x",
- result);
+ DBG2(DBG_PTS, "TPM Version Info: Chip Version: %u.%u.%u.%u, "
+ "Spec Level: %u, Errata Rev: %u, Vendor ID: %.4s",
+ info->version.major, info->version.minor,
+ info->version.revMajor, info->version.revMinor,
+ untoh16(&info->specLevel), info->errataRev, info->tpmVendorID);
}
else
{
- DBG2(DBG_PTS, "TPM 1.2 Version Info: Chip Version: %hhu.%hhu.%hhu.%hhu,"
- " Spec Level: %hu, Errata Rev: %hhu, Vendor ID: %.4s [%.*s]",
- versionInfo.version.major, versionInfo.version.minor,
- versionInfo.version.revMajor, versionInfo.version.revMinor,
- versionInfo.specLevel, versionInfo.errataRev,
- versionInfo.tpmVendorID, versionInfo.vendorSpecificSize,
- versionInfo.vendorSpecificSize ?
- (char*)versionInfo.vendorSpecific : "");
+ DBG1(DBG_PTS, "could not parse tpm version info");
}
- free(versionInfo.vendorSpecific);
}
#else
@@ -330,22 +333,16 @@ static void print_tpm_version_info(private_pts_t *this)
#endif /* TSS_TROUSERS */
-METHOD(pts_t, get_platform_info, char*,
+METHOD(pts_t, get_platform_id, int,
private_pts_t *this)
{
- return this->platform_info;
+ return this->platform_id;
}
-METHOD(pts_t, set_platform_info, void,
- private_pts_t *this, chunk_t name, chunk_t version)
+METHOD(pts_t, set_platform_id, void,
+ private_pts_t *this, int pid)
{
- int len = name.len + 1 + version.len + 1;
-
- /* platform info is a concatenation of OS name and OS version */
- free(this->platform_info);
- this->platform_info = malloc(len);
- snprintf(this->platform_info, len, "%.*s %.*s", (int)name.len, name.ptr,
- (int)version.len, version.ptr);
+ this->platform_id = pid;
}
METHOD(pts_t, get_tpm_version_info, bool,
@@ -372,42 +369,31 @@ METHOD(pts_t, set_tpm_version_info, void,
*/
static void load_aik_blob(private_pts_t *this)
{
- char *blob_path;
- FILE *fp;
- u_int32_t aikBlobLen;
+ char *path;
+ chunk_t *map;
- blob_path = lib->settings->get_str(lib->settings,
+ path = lib->settings->get_str(lib->settings,
"%s.plugins.imc-attestation.aik_blob", NULL, lib->ns);
-
- if (blob_path)
+ if (path)
{
- /* Read aik key blob from a file */
- if ((fp = fopen(blob_path, "r")) == NULL)
- {
- DBG1(DBG_PTS, "unable to open AIK Blob file: %s", blob_path);
- return;
- }
-
- fseek(fp, 0, SEEK_END);
- aikBlobLen = ftell(fp);
- fseek(fp, 0L, SEEK_SET);
-
- this->aik_blob = chunk_alloc(aikBlobLen);
- if (fread(this->aik_blob.ptr, 1, aikBlobLen, fp) == aikBlobLen)
+ map = chunk_map(path, FALSE);
+ if (map)
{
- DBG2(DBG_PTS, "loaded AIK Blob from '%s'", blob_path);
- DBG3(DBG_PTS, "AIK Blob: %B", &this->aik_blob);
+ DBG2(DBG_PTS, "loaded AIK Blob from '%s'", path);
+ DBG3(DBG_PTS, "AIK Blob: %B", map);
+ this->aik_blob = chunk_clone(*map);
+ chunk_unmap(map);
}
else
{
- DBG1(DBG_PTS, "unable to read AIK Blob file '%s'", blob_path);
- chunk_free(&this->aik_blob);
+ DBG1(DBG_PTS, "unable to map AIK Blob file '%s': %s",
+ path, strerror(errno));
}
- fclose(fp);
- return;
}
-
- DBG1(DBG_PTS, "AIK Blob is not available");
+ else
+ {
+ DBG1(DBG_PTS, "AIK Blob is not available");
+ }
}
/**
@@ -421,7 +407,7 @@ static void load_aik(private_pts_t *this)
cert_path = lib->settings->get_str(lib->settings,
"%s.plugins.imc-attestation.aik_cert", NULL, lib->ns);
key_path = lib->settings->get_str(lib->settings,
- "%s.plugins.imc-attestation.aik_key", NULL, lib->ns);
+ "%s.plugins.imc-attestation.aik_pubkey", NULL, lib->ns);
if (cert_path)
{
@@ -456,37 +442,17 @@ METHOD(pts_t, get_aik, certificate_t*,
}
METHOD(pts_t, set_aik, void,
- private_pts_t *this, certificate_t *aik)
+ private_pts_t *this, certificate_t *aik, int aik_id)
{
DESTROY_IF(this->aik);
this->aik = aik->get_ref(aik);
+ this->aik_id = aik_id;
}
-METHOD(pts_t, get_aik_keyid, bool,
- private_pts_t *this, chunk_t *keyid)
+METHOD(pts_t, get_aik_id, int,
+ private_pts_t *this)
{
- public_key_t *public;
- bool success;
-
- if (!this->aik)
- {
- DBG1(DBG_PTS, "no AIK certificate available");
- return FALSE;
- }
- public = this->aik->get_public_key(this->aik);
- if (!public)
- {
- DBG1(DBG_PTS, "no AIK public key available");
- return FALSE;
- }
- success = public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, keyid);
- if (!success)
- {
- DBG1(DBG_PTS, "no SHA-1 AIK public key info ID available");
- }
- public->destroy(public);
-
- return success;
+ return this->aik_id;
}
METHOD(pts_t, is_path_valid, bool,
@@ -557,6 +523,7 @@ static bool file_metadata(char *pathname, pts_file_metadata_t **entry)
{
this->type = PTS_FILE_FIFO;
}
+#ifndef WIN32
else if (S_ISLNK(st.st_mode))
{
this->type = PTS_FILE_SYM_LINK;
@@ -565,6 +532,7 @@ static bool file_metadata(char *pathname, pts_file_metadata_t **entry)
{
this->type = PTS_FILE_SOCKET;
}
+#endif /* WIN32 */
else
{
this->type = PTS_FILE_OTHER;
@@ -644,7 +612,8 @@ METHOD(pts_t, read_pcr, bool,
TSS_HCONTEXT hContext;
TSS_HTPM hTPM;
TSS_RESULT result;
- chunk_t rgbPcrValue;
+ BYTE *buf;
+ UINT32 len;
bool success = FALSE;
@@ -665,12 +634,12 @@ METHOD(pts_t, read_pcr, bool,
{
goto err;
}
- result = Tspi_TPM_PcrRead(hTPM, pcr_num, (UINT32*)&rgbPcrValue.len, &rgbPcrValue.ptr);
+ result = Tspi_TPM_PcrRead(hTPM, pcr_num, &len, &buf);
if (result != TSS_SUCCESS)
{
goto err;
}
- *pcr_value = chunk_clone(rgbPcrValue);
+ *pcr_value = chunk_clone(chunk_create(buf, len));
DBG3(DBG_PTS, "PCR %d value:%B", pcr_num, pcr_value);
success = TRUE;
@@ -1093,7 +1062,6 @@ METHOD(pts_t, destroy, void,
free(this->initiator_nonce.ptr);
free(this->responder_nonce.ptr);
free(this->secret.ptr);
- free(this->platform_info);
free(this->aik_blob.ptr);
free(this->tpm_version_info.ptr);
free(this);
@@ -1187,13 +1155,13 @@ pts_t *pts_create(bool is_imc)
.get_my_public_value = _get_my_public_value,
.set_peer_public_value = _set_peer_public_value,
.calculate_secret = _calculate_secret,
- .get_platform_info = _get_platform_info,
- .set_platform_info = _set_platform_info,
+ .get_platform_id = _get_platform_id,
+ .set_platform_id = _set_platform_id,
.get_tpm_version_info = _get_tpm_version_info,
.set_tpm_version_info = _set_tpm_version_info,
.get_aik = _get_aik,
.set_aik = _set_aik,
- .get_aik_keyid = _get_aik_keyid,
+ .get_aik_id = _get_aik_id,
.is_path_valid = _is_path_valid,
.get_metadata = _get_metadata,
.read_pcr = _read_pcr,
diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h
index 11154aa38..fead588ae 100644
--- a/src/libpts/pts/pts.h
+++ b/src/libpts/pts/pts.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -162,19 +163,18 @@ struct pts_t {
bool (*calculate_secret) (pts_t *this);
/**
- * Get Platform and OS Info
+ * Get primary key of platform entry in database
*
* @return Platform and OS info
*/
- char* (*get_platform_info)(pts_t *this);
+ int (*get_platform_id)(pts_t *this);
/**
- * Set Platform and OS Info
+ * Set primary key of platform entry in database
*
- * @param name OS name
- * @param version OS version
+ * @param pid Primary key of platform entry in database
*/
- void (*set_platform_info)(pts_t *this, chunk_t name, chunk_t version);
+ void (*set_platform_id)(pts_t *this, int pid);
/**
* Get TPM 1.2 Version Info
@@ -202,16 +202,16 @@ struct pts_t {
* 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);
+ void (*set_aik)(pts_t *this, certificate_t *aik, int aik_id);
/**
- * Get SHA-1 Attestation Identity Public Key Info ID
+ * Get primary key referencing AIK in database
*
- * @param keyid AIK ID
- * @return TRUE if AIK ID exists
+ * @return Primary key referencing AIK in database
*/
- bool (*get_aik_keyid)(pts_t *this, chunk_t *keyid);
+ int (*get_aik_id)(pts_t *this);
/**
* Check whether path is valid file/directory on filesystem
diff --git a/src/libpts/pts/pts_database.c b/src/libpts/pts/pts_database.c
index fda644a6a..d7b85c138 100644
--- a/src/libpts/pts/pts_database.c
+++ b/src/libpts/pts/pts_database.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen
+ * 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
@@ -47,7 +48,7 @@ METHOD(pts_database_t, get_pathname, char*,
private_pts_database_t *this, bool is_dir, int id)
{
enumerator_t *e;
- char *path, *name, *pathname;
+ char *path, *name, *sep, *pathname = NULL;
if (is_dir)
{
@@ -69,11 +70,21 @@ METHOD(pts_database_t, get_pathname, char*,
"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) ||
- asprintf(&pathname, "%s%s%s",
- path, streq(path, "/") ? "" : "/", name) == -1)
+ if (e && e->enumerate(e, &path, &name))
{
- pathname = NULL;
+ 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);
@@ -82,7 +93,7 @@ METHOD(pts_database_t, get_pathname, char*,
}
METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
- private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
+ private_pts_database_t *this, int pid, pts_meas_algorithms_t algo,
bool is_dir, int id)
{
enumerator_t *e;
@@ -90,73 +101,34 @@ METHOD(pts_database_t, create_file_hash_enumerator, enumerator_t*,
if (is_dir)
{
e = this->db->query(this->db,
- "SELECT f.name, fh.hash FROM file_hashes AS fh "
+ "SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
- "JOIN products AS p ON p.id = fh.product "
"JOIN directories as d ON d.id = f.dir "
- "WHERE p.name = ? AND fh.algo = ? AND d.id = ? "
+ "WHERE fh.product = ? AND fh.algo = ? AND d.id = ? "
"ORDER BY f.name",
- DB_TEXT, product, DB_INT, algo, DB_INT, id, DB_TEXT, DB_BLOB);
+ DB_INT, pid, DB_INT, algo, DB_INT, id, DB_INT, DB_TEXT, DB_BLOB);
}
else
{
e = this->db->query(this->db,
- "SELECT f.name, fh.hash FROM file_hashes AS fh "
+ "SELECT f.id, f.name, fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
- "JOIN products AS p ON p.id = fh.product "
- "WHERE p.name = ? AND fh.algo = ? AND fh.file = ?",
- DB_TEXT, product, DB_INT, algo, DB_INT, id, DB_TEXT, DB_BLOB);
+ "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, check_aik_keyid, status_t,
- private_pts_database_t *this, chunk_t keyid, int *kid)
-{
- enumerator_t *e;
-
- /* If the AIK is registered get the primary key */
- e = this->db->query(this->db,
- "SELECT id FROM keys WHERE keyid = ?", DB_BLOB, keyid, DB_INT);
- if (!e)
- {
- DBG1(DBG_PTS, "no database query enumerator returned");
- return FAILED;
- }
- if (!e->enumerate(e, kid))
- {
- DBG1(DBG_PTS, "AIK %#B is not registered in database", &keyid);
- e->destroy(e);
- return FAILED;
- }
- e->destroy(e);
-
- return SUCCESS;
-}
-
METHOD(pts_database_t, add_file_measurement, status_t,
- private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
+ 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, pid = 0;
+ int hash_id, fid;
status_t status = SUCCESS;
- /* get primary key of product string */
- e = this->db->query(this->db,
- "SELECT id FROM products WHERE name = ?", DB_TEXT, product, DB_INT);
- if (e)
- {
- e->enumerate(e, &pid);
- e->destroy(e);
- }
- if (pid == 0)
- {
- return FAILED;
- }
-
if (is_dir)
{
/* does filename entry already exist? */
@@ -242,18 +214,16 @@ METHOD(pts_database_t, add_file_measurement, status_t,
return status;
}
-METHOD(pts_database_t, check_file_measurement, status_t,
- private_pts_database_t *this, char *product, pts_meas_algorithms_t algo,
- chunk_t measurement, char *filename)
+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;
- chunk_t hash;
- status_t status = NOT_FOUND;
char *dir, *file;
if (strlen(filename) < 1)
{
- return INVALID_ARG;
+ return NULL;
}
/* separate filename into directory and basename components */
@@ -265,84 +235,40 @@ METHOD(pts_database_t, check_file_measurement, status_t,
e = this->db->query(this->db,
"SELECT fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
- "JOIN products AS p ON p.id = fh.product "
- "WHERE p.name = ? AND f.name = ? AND fh.algo = ?",
- DB_TEXT, product, DB_TEXT, file, DB_INT, algo, DB_BLOB);
+ "WHERE fh.product = ? AND f.name = ? AND fh.algo = ?",
+ DB_INT, pid, DB_TEXT, file, DB_INT, algo, DB_BLOB);
}
else
{ /* absolute pathname */
- bool dir_found;
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)
+
+ if (!e || !e->enumerate(e, &did))
{
- status = FAILED;
goto err;
}
- dir_found = e->enumerate(e, &did);
e->destroy(e);
- if (!dir_found)
- {
- status = NOT_FOUND;
- goto err;
- }
e = this->db->query(this->db,
"SELECT fh.hash FROM file_hashes AS fh "
"JOIN files AS f ON f.id = fh.file "
- "JOIN products AS p ON p.id = fh.product "
- "WHERE p.name = ? AND f.dir = ? AND f.name = ? AND fh.algo = ?",
- DB_TEXT, product, DB_INT, did, DB_TEXT, file, DB_INT, algo,
- DB_BLOB);
- }
- if (!e)
- {
- status = FAILED;
- goto err;
+ "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);
}
- while (e->enumerate(e, &hash))
- {
- /* with relative filenames there might be multiple entries */
- if (chunk_equals(measurement, hash))
- {
- status = SUCCESS;
- break;
- }
- else
- {
- status = VERIFY_ERROR;
- }
- }
- e->destroy(e);
err:
free(file);
free(dir);
- return status;
-}
-
-METHOD(pts_database_t, create_comp_evid_enumerator, enumerator_t*,
- private_pts_database_t *this, int kid)
-{
- enumerator_t *e;
-
- /* look for all entries belonging to an AIK in the components table */
- e = this->db->query(this->db,
- "SELECT c.vendor_id, c.name, c.qualifier, kc.depth "
- "FROM components AS c "
- "JOIN key_component AS kc ON c.id = kc.component "
- "WHERE kc.key = ? ORDER BY kc.seq_no",
- DB_INT, kid, DB_INT, DB_INT, DB_INT, DB_INT);
return e;
}
METHOD(pts_database_t, check_comp_measurement, status_t,
- private_pts_database_t *this, chunk_t measurement, int cid, int kid,
+ 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;
@@ -353,7 +279,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
"SELECT hash FROM component_hashes "
"WHERE component = ? AND key = ? "
"AND seq_no = ? AND pcr = ? AND algo = ? ",
- DB_INT, cid, DB_INT, kid, DB_INT, seq_no,
+ DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no,
DB_INT, pcr, DB_INT, algo, DB_BLOB);
if (!e)
{
@@ -390,7 +316,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
}
METHOD(pts_database_t, insert_comp_measurement, status_t,
- private_pts_database_t *this, chunk_t measurement, int cid, int kid,
+ 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;
@@ -399,7 +325,7 @@ METHOD(pts_database_t, insert_comp_measurement, status_t,
"INSERT INTO component_hashes "
"(component, key, seq_no, pcr, algo, hash) "
"VALUES (?, ?, ?, ?, ?, ?)",
- DB_INT, cid, DB_INT, kid, DB_INT, seq_no, DB_INT, pcr,
+ DB_INT, cid, DB_INT, aik_id, DB_INT, seq_no, DB_INT, pcr,
DB_INT, algo, DB_BLOB, measurement) == 1)
{
return SUCCESS;
@@ -410,17 +336,17 @@ METHOD(pts_database_t, insert_comp_measurement, status_t,
}
METHOD(pts_database_t, delete_comp_measurements, int,
- private_pts_database_t *this, int cid, int kid)
+ 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, kid);
+ 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,
- chunk_t keyid, pts_meas_algorithms_t algo, int *cid, int *kid, int *count)
+ int aik_id, pts_meas_algorithms_t algo, int *cid, int *count)
{
enumerator_t *e;
status_t status = SUCCESS;
@@ -428,11 +354,6 @@ METHOD(pts_database_t, get_comp_measurement_count, status_t,
/* Initialize count */
*count = 0;
- if (_check_aik_keyid(this, keyid, kid) != SUCCESS)
- {
- return FAILED;
- }
-
/* Get the primary key of the Component Functional Name */
e = this->db->query(this->db,
"SELECT id FROM components "
@@ -458,7 +379,7 @@ METHOD(pts_database_t, get_comp_measurement_count, status_t,
e = this->db->query(this->db,
"SELECT COUNT(*) FROM component_hashes AS ch "
"WHERE component = ? AND key = ? AND algo = ?",
- DB_INT, *cid, DB_INT, *kid, DB_INT, algo, DB_INT);
+ DB_INT, *cid, DB_INT, aik_id, DB_INT, algo, DB_INT);
if (!e)
{
DBG1(DBG_PTS, "no database query enumerator returned");
@@ -495,11 +416,9 @@ pts_database_t *pts_database_create(imv_database_t *imv_db)
INIT(this,
.public = {
.get_pathname = _get_pathname,
- .create_comp_evid_enumerator = _create_comp_evid_enumerator,
.create_file_hash_enumerator = _create_file_hash_enumerator,
- .check_aik_keyid = _check_aik_keyid,
.add_file_measurement = _add_file_measurement,
- .check_file_measurement = _check_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,
@@ -511,4 +430,3 @@ pts_database_t *pts_database_create(imv_database_t *imv_db)
return &this->public;
}
-
diff --git a/src/libpts/pts/pts_database.h b/src/libpts/pts/pts_database.h
index eb8aca346..a6c9fb3b6 100644
--- a/src/libpts/pts/pts_database.h
+++ b/src/libpts/pts/pts_database.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -47,37 +47,20 @@ struct pts_database_t {
/**
* Get stored measurement hash for single file or directory entries
*
- * @param product Software product (os, vpn client, etc.)
+ * @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,
- char *product, pts_meas_algorithms_t algo,
+ int pid, pts_meas_algorithms_t algo,
bool is_dir, int id);
/**
- * Check if an AIK given by its keyid is registered in the database
- *
- * @param keyid AIK keyid (SHA-1 hash of the AIK public key info)
- * @param kid Primary key of AIK entry in keys table
- * @return SUCCESS if AIK is present, FAILED otherwise
- */
- status_t (*check_aik_keyid)(pts_database_t *this, chunk_t keyid, int *kid);
-
- /**
- * Get functional components to request evidence of
- *
- * @param kid Primary key of AIK entry in keys table
- * @return Enumerator over all matching components
- */
- enumerator_t* (*create_comp_evid_enumerator)(pts_database_t *this, int kid);
-
- /**
* Add PTS file measurement reference value
*
- * @param product Software product (os, vpn client, etc.)
+ * @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
@@ -85,37 +68,36 @@ struct pts_database_t {
* @param id Primary key into direcories/files table
* @return Status
*/
- status_t (*add_file_measurement)(pts_database_t *this, char *product,
+ 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);
/**
- * Check PTS file measurement against reference stored in database
+ * Get PTS measurement[s] for a given filename stored in database
*
- * @param product Software product (os, vpn client, etc.)
+ * @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
- * @return Status
+ * @param filename Name of the file to be checked
+ * @return Enumerator over all matching measurement hashes
*/
- status_t (*check_file_measurement)(pts_database_t *this, char *product,
- pts_meas_algorithms_t algo,
- chunk_t measurement, char *filename);
+ 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 kid Primary key of AIK entry in keys table
+ * @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 kid, int seq_no, int pcr,
+ int cid, int aik_id, int seq_no, int pcr,
pts_meas_algorithms_t algo);
/**
@@ -123,40 +105,38 @@ struct pts_database_t {
*
* @param measurement Measurement hash
* @param cid Primary key of Component Functional Name entry
- * @param kid Primary key of AIK entry in keys table
+ * @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 kid, int seq_no, int pcr,
+ 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 kid Primary key of AIK entry in keys table
+ * @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 kid);
+ 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 keyid SHA-1 hash of AIK public key info
+ * @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 kid Primary key of AIK entry in keys table
* @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, chunk_t keyid,
- pts_meas_algorithms_t algo, int *cid, int *kid,
- int *count);
+ 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.
diff --git a/src/libpts/pts/pts_file_meas.c b/src/libpts/pts/pts_file_meas.c
index 77a0957bb..478892aea 100644
--- a/src/libpts/pts/pts_file_meas.c
+++ b/src/libpts/pts/pts_file_meas.c
@@ -1,5 +1,6 @@
/*
* 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
@@ -112,19 +113,43 @@ METHOD(pts_file_meas_t, create_enumerator, enumerator_t*,
}
METHOD(pts_file_meas_t, check, bool,
- private_pts_file_meas_t *this, pts_database_t *pts_db, char *product,
+ private_pts_file_meas_t *this, pts_database_t *pts_db, int pid,
pts_meas_algorithms_t algo)
{
- enumerator_t *enumerator;
+ 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 = pts_db->check_file_measurement(pts_db, product, algo,
- entry->measurement, entry->filename);
+ 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:
@@ -159,47 +184,75 @@ METHOD(pts_file_meas_t, check, bool,
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;
- bool found, success = TRUE;
+ enumerator_t *enumerator = NULL;
+ bool found = FALSE, match = FALSE, success = TRUE;
- while (e_hash->enumerate(e_hash, &filename, &measurement))
+ while (e_hash->enumerate(e_hash, &fid, &filename, &measurement))
{
- found = FALSE;
-
- enumerator = this->list->create_enumerator(this->list);
- while (enumerator->enumerate(enumerator, &entry))
+ if (fid != fid_last)
{
- if (!is_dir || streq(filename, entry->filename))
+ if (found && !match)
{
- found = TRUE;
- break;
+ /* 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);
}
- }
- enumerator->destroy(enumerator);
- if (!found)
- {
- DBG1(DBG_PTS, " no measurement found for '%s'", filename);
- success = FALSE;
- continue;
- }
- if (chunk_equals(measurement, entry->measurement))
- {
- DBG2(DBG_PTS, " %#B for '%s' is ok", &measurement, filename);
- }
- else
- {
- DBG1(DBG_PTS, " %#B for '%s' is incorrect", &measurement, filename);
- success = FALSE;
+ /* 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 (!is_dir)
+
+ if (found && !match)
{
- break;
+ 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;
}
diff --git a/src/libpts/pts/pts_file_meas.h b/src/libpts/pts/pts_file_meas.h
index a13bb29ba..4bf28e280 100644
--- a/src/libpts/pts/pts_file_meas.h
+++ b/src/libpts/pts/pts_file_meas.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -65,11 +66,11 @@ struct pts_file_meas_t {
* Check PTS File Measurements against reference value in the database
*
* @param db PTS Measurement database
- * @param product Software product (os, vpn client, etc.)
+ * @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, char* product,
+ bool (*check)(pts_file_meas_t *this, pts_database_t *db, int pid,
pts_meas_algorithms_t algo);
/**
diff --git a/src/libpts/pts/pts_ima_bios_list.c b/src/libpts/pts/pts_ima_bios_list.c
new file mode 100644
index 000000000..5051b6c2d
--- /dev/null
+++ b/src/libpts/pts/pts_ima_bios_list.c
@@ -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;
+}
diff --git a/src/libpts/pts/pts_ima_bios_list.h b/src/libpts/pts/pts_ima_bios_list.h
new file mode 100644
index 000000000..ad162e15a
--- /dev/null
+++ b/src/libpts/pts/pts_ima_bios_list.h
@@ -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_ @}*/
diff --git a/src/libpts/pts/pts_ima_event_list.c b/src/libpts/pts/pts_ima_event_list.c
new file mode 100644
index 000000000..9bff4654b
--- /dev/null
+++ b/src/libpts/pts/pts_ima_event_list.c
@@ -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;
+}
diff --git a/src/libpts/pts/pts_ima_event_list.h b/src/libpts/pts/pts_ima_event_list.h
new file mode 100644
index 000000000..bf5478a51
--- /dev/null
+++ b/src/libpts/pts/pts_ima_event_list.h
@@ -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_ @}*/
diff --git a/src/libpts/pts/pts_meas_algo.c b/src/libpts/pts/pts_meas_algo.c
index 16a66e7b3..c06371123 100644
--- a/src/libpts/pts/pts_meas_algo.c
+++ b/src/libpts/pts/pts_meas_algo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -28,10 +28,7 @@ ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA256, PTS_MEAS_ALGO_SHA256,
ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1, PTS_MEAS_ALGO_SHA1,
PTS_MEAS_ALGO_SHA256,
"SHA1");
-ENUM_NEXT(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1_IMA, PTS_MEAS_ALGO_SHA1_IMA,
- PTS_MEAS_ALGO_SHA1,
- "SHA1-IMA");
-ENUM_END(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1_IMA);
+ENUM_END(pts_meas_algorithm_names, PTS_MEAS_ALGO_SHA1);
/**
* Described in header.
diff --git a/src/libpts/pts/pts_meas_algo.h b/src/libpts/pts/pts_meas_algo.h
index 27cdaea7e..eec7e7981 100644
--- a/src/libpts/pts/pts_meas_algo.h
+++ b/src/libpts/pts/pts_meas_algo.h
@@ -1,5 +1,6 @@
/*
* 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
@@ -33,8 +34,7 @@ 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),
- PTS_MEAS_ALGO_SHA1_IMA = (1<<16), /* internal use only */
+ PTS_MEAS_ALGO_SHA1 = (1<<15)
};
/**
diff --git a/src/libpts/swid/swid_error.c b/src/libpts/swid/swid_error.c
index 7f7da7688..7f3c34476 100644
--- a/src/libpts/swid/swid_error.c
+++ b/src/libpts/swid/swid_error.c
@@ -40,7 +40,7 @@ pa_tnc_attr_t* swid_error_create(swid_error_code_t code, u_int32_t request_id,
writer->write_uint32(writer, request_id);
if (code == TCG_SWID_RESPONSE_TOO_LARGE)
{
- writer->write_uint16(writer, max_attr_size);
+ writer->write_uint32(writer, max_attr_size);
}
if (description)
{
diff --git a/src/libpts/swid/swid_inventory.c b/src/libpts/swid/swid_inventory.c
index a71682f43..a9f081efa 100644
--- a/src/libpts/swid/swid_inventory.c
+++ b/src/libpts/swid/swid_inventory.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,7 @@
#include "swid_tag_id.h"
#include <collections/linked_list.h>
+#include <bio/bio_writer.h>
#include <utils/debug.h>
#include <stdio.h>
@@ -51,6 +52,194 @@ struct private_swid_inventory_t {
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)
{
@@ -72,7 +261,8 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
{
char * start, *stop;
chunk_t tag_creator;
- chunk_t unique_sw_id = chunk_empty, unique_seq_id = chunk_empty;
+ chunk_t unique_sw_id = chunk_empty, tag_file_path = chunk_empty;
+
if (!strstr(rel_name, "regid."))
{
continue;
@@ -121,14 +311,7 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
goto end;
}
tag_creator = chunk_create(start, stop-start);
-
start = stop + 1;
- stop = strchr(start, '_');
- if (stop)
- {
- unique_sw_id = chunk_create(start, stop-start);
- start = stop + 1;
- }
stop = strstr(start, ".swidtag");
if (!stop)
@@ -137,18 +320,13 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
DBG1(DBG_IMC, " swidtag postfix not found");
goto end;
}
- if (unique_sw_id.ptr)
- {
- unique_seq_id = chunk_create(start, stop-start);
- }
- else
- {
- unique_sw_id = chunk_create(start, stop-start);
- }
+ 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;
@@ -156,10 +334,11 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
target_enumerator = targets->create_enumerator(targets);
while (target_enumerator->enumerate(target_enumerator, &tag_id))
{
- if (chunk_equals(tag_id->get_unique_sw_id(tag_id, NULL),
- unique_sw_id) &&
- chunk_equals(tag_id->get_tag_creator(tag_id),
- tag_creator))
+ 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;
@@ -187,7 +366,7 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
goto end;
}
- tag = swid_tag_create(*xml_tag, unique_seq_id);
+ tag = swid_tag_create(*xml_tag, tag_file_path);
this->list->insert_last(this->list, tag);
chunk_unmap(xml_tag);
}
@@ -195,10 +374,9 @@ static bool collect_tags(private_swid_inventory_t *this, char *pathname,
{
swid_tag_id_t *tag_id;
- tag_id = swid_tag_id_create(tag_creator, unique_sw_id, unique_seq_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;
@@ -210,8 +388,18 @@ end:
}
METHOD(swid_inventory_t, collect, bool,
- private_swid_inventory_t *this, char *directory, swid_inventory_t *targets)
+ 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);
}
diff --git a/src/libpts/swid/swid_inventory.h b/src/libpts/swid/swid_inventory.h
index 68d3047aa..7de8bb221 100644
--- a/src/libpts/swid/swid_inventory.h
+++ b/src/libpts/swid/swid_inventory.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -34,11 +34,14 @@ 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,
- swid_inventory_t *targets);
+ 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
diff --git a/src/libpts/swid/swid_tag.c b/src/libpts/swid/swid_tag.c
index 0b6519693..c71d5d2bd 100644
--- a/src/libpts/swid/swid_tag.c
+++ b/src/libpts/swid/swid_tag.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -34,10 +34,14 @@ struct private_swid_tag_t {
chunk_t encoding;
/**
- * Optional Unique Sequence ID
+ * Optional Tag File Path
*/
- chunk_t unique_seq_id;
+ chunk_t tag_file_path;
+ /**
+ * Reference count
+ */
+ refcount_t ref;
};
METHOD(swid_tag_t, get_encoding, chunk_t,
@@ -46,39 +50,51 @@ METHOD(swid_tag_t, get_encoding, chunk_t,
return this->encoding;
}
-METHOD(swid_tag_t, get_unique_seq_id, chunk_t,
+METHOD(swid_tag_t, get_tag_file_path, chunk_t,
private_swid_tag_t *this)
{
- return this->unique_seq_id;
+ return this->tag_file_path;
+}
+
+METHOD(swid_tag_t, get_ref, swid_tag_t*,
+ private_swid_tag_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
}
METHOD(swid_tag_t, destroy, void,
private_swid_tag_t *this)
{
- free(this->encoding.ptr);
- free(this->unique_seq_id.ptr);
- free(this);
+ if (ref_put(&this->ref))
+ {
+ free(this->encoding.ptr);
+ free(this->tag_file_path.ptr);
+ free(this);
+ }
}
/**
* See header
*/
-swid_tag_t *swid_tag_create(chunk_t encoding, chunk_t unique_seq_id)
+swid_tag_t *swid_tag_create(chunk_t encoding, chunk_t tag_file_path)
{
private_swid_tag_t *this;
INIT(this,
.public = {
.get_encoding = _get_encoding,
- .get_unique_seq_id = _get_unique_seq_id,
+ .get_tag_file_path = _get_tag_file_path,
+ .get_ref = _get_ref,
.destroy = _destroy,
},
.encoding = chunk_clone(encoding),
+ .ref = 1,
);
- if (unique_seq_id.len > 0)
+ if (tag_file_path.len > 0)
{
- this->unique_seq_id = chunk_clone(unique_seq_id);
+ this->tag_file_path = chunk_clone(tag_file_path);
}
return &this->public;
diff --git a/src/libpts/swid/swid_tag.h b/src/libpts/swid/swid_tag.h
index 9d3f86333..e20c538ea 100644
--- a/src/libpts/swid/swid_tag.h
+++ b/src/libpts/swid/swid_tag.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -39,11 +39,18 @@ struct swid_tag_t {
chunk_t (*get_encoding)(swid_tag_t *this);
/**
- * Get th Optional Unique Sequence ID
+ * Get th Optional Tag File Path
*
- * @return Optional Unique Sequence ID
+ * @return Optional Tag File Path
*/
- chunk_t (*get_unique_seq_id)(swid_tag_t *this);
+ chunk_t (*get_tag_file_path)(swid_tag_t *this);
+
+ /**
+ * Get a new reference to the swid_tag object
+ *
+ * @return this, with an increased refcount
+ */
+ swid_tag_t* (*get_ref)(swid_tag_t *this);
/**
* Destroys a swid_tag_t object.
@@ -56,8 +63,8 @@ struct swid_tag_t {
* Creates a swid_tag_t object
*
* @param encoding XML encoding of SWID tag
- * @param unique_seq_id Unique Sequence ID or empty chunk
+ * @param tag_file_path Tag File Path or empty chunk
*/
-swid_tag_t* swid_tag_create(chunk_t encoding, chunk_t unique_seq_id);
+swid_tag_t* swid_tag_create(chunk_t encoding, chunk_t tag_file_path);
#endif /** SWID_TAG_H_ @}*/
diff --git a/src/libpts/swid/swid_tag_id.c b/src/libpts/swid/swid_tag_id.c
index 7ad486d4b..8bede28a0 100644
--- a/src/libpts/swid/swid_tag_id.c
+++ b/src/libpts/swid/swid_tag_id.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -39,10 +39,14 @@ struct private_swid_tag_id_t {
chunk_t unique_sw_id;
/**
- * Optional Unique Sequence ID
+ * Tag File Path
*/
- chunk_t unique_seq_id;
+ chunk_t tag_file_path;
+ /**
+ * Reference count
+ */
+ refcount_t ref;
};
METHOD(swid_tag_id_t, get_tag_creator, chunk_t,
@@ -52,29 +56,39 @@ METHOD(swid_tag_id_t, get_tag_creator, chunk_t,
}
METHOD(swid_tag_id_t, get_unique_sw_id, chunk_t,
- private_swid_tag_id_t *this, chunk_t *unique_seq_id)
+ private_swid_tag_id_t *this, chunk_t *tag_file_path)
{
- if (unique_seq_id)
+ if (tag_file_path)
{
- *unique_seq_id = this->unique_seq_id;
+ *tag_file_path = this->tag_file_path;
}
return this->unique_sw_id;
}
+METHOD(swid_tag_id_t, get_ref, swid_tag_id_t*,
+ private_swid_tag_id_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public;
+}
+
METHOD(swid_tag_id_t, destroy, void,
private_swid_tag_id_t *this)
{
- free(this->tag_creator.ptr);
- free(this->unique_sw_id.ptr);
- free(this->unique_seq_id.ptr);
- free(this);
+ if (ref_put(&this->ref))
+ {
+ free(this->tag_creator.ptr);
+ free(this->unique_sw_id.ptr);
+ free(this->tag_file_path.ptr);
+ free(this);
+ }
}
/**
* See header
*/
swid_tag_id_t *swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
- chunk_t unique_seq_id)
+ chunk_t tag_file_path)
{
private_swid_tag_id_t *this;
@@ -82,15 +96,17 @@ swid_tag_id_t *swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
.public = {
.get_tag_creator = _get_tag_creator,
.get_unique_sw_id = _get_unique_sw_id,
+ .get_ref = _get_ref,
.destroy = _destroy,
},
.tag_creator = chunk_clone(tag_creator),
.unique_sw_id = chunk_clone(unique_sw_id),
+ .ref = 1,
);
- if (unique_seq_id.len > 0)
+ if (tag_file_path.len > 0)
{
- this->unique_seq_id = chunk_clone(unique_seq_id);
+ this->tag_file_path = chunk_clone(tag_file_path);
}
return &this->public;
diff --git a/src/libpts/swid/swid_tag_id.h b/src/libpts/swid/swid_tag_id.h
index d4715967d..d2a783b35 100644
--- a/src/libpts/swid/swid_tag_id.h
+++ b/src/libpts/swid/swid_tag_id.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -39,12 +39,19 @@ struct swid_tag_id_t {
chunk_t (*get_tag_creator)(swid_tag_id_t *this);
/**
- * Get the Unique Software ID and optional Unique Sequence ID
+ * Get the Unique Software ID and optional Tag File Path
*
- * @param Optional Unique Sequence ID
+ * @param Optional Tag File Path
* @return Unique Software ID
*/
- chunk_t (*get_unique_sw_id)(swid_tag_id_t *this, chunk_t *unique_seq_id);
+ chunk_t (*get_unique_sw_id)(swid_tag_id_t *this, chunk_t *tag_file_path);
+
+ /**
+ * Get a new reference to the swid_tag_id object
+ *
+ * @return this, with an increased refcount
+ */
+ swid_tag_id_t* (*get_ref)(swid_tag_id_t *this);
/**
* Destroys a swid_tag_id_t object.
@@ -58,9 +65,9 @@ struct swid_tag_id_t {
*
* @param tag_creator Tag Creator
* @param unique_sw_id Unique Software ID
- * @param unique_seq_id Unique Sequence ID or empty chunk
+ * @param tag_file_path Tag File Path or empty chunk
*/
swid_tag_id_t* swid_tag_id_create(chunk_t tag_creator, chunk_t unique_sw_id,
- chunk_t unique_seq_id);
+ chunk_t tag_file_path);
#endif /** SWID_TAG_ID_H_ @}*/
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_req.c b/src/libpts/tcg/swid/tcg_swid_attr_req.c
index b8e7962c1..c403d06f9 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_req.c
+++ b/src/libpts/tcg/swid/tcg_swid_attr_req.c
@@ -44,7 +44,6 @@ typedef struct private_tcg_swid_attr_req_t private_tcg_swid_attr_req_t;
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-#define SWID_REQ_SIZE 12
#define SWID_REQ_RESERVED_MASK 0x03
/**
@@ -135,7 +134,7 @@ METHOD(pa_tnc_attr_t, build, void,
return;
}
- writer = bio_writer_create(SWID_REQ_SIZE);
+ writer = bio_writer_create(TCG_SWID_REQ_MIN_SIZE);
writer->write_uint8 (writer, this->flags);
writer->write_uint24(writer, this->targets->get_count(this->targets));
writer->write_uint32(writer, this->request_id);
@@ -163,7 +162,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
chunk_t tag_creator, unique_sw_id;
swid_tag_id_t *tag_id;
- if (this->value.len < SWID_REQ_SIZE)
+ if (this->value.len < TCG_SWID_REQ_MIN_SIZE)
{
DBG1(DBG_TNC, "insufficient data for SWID Request");
*offset = 0;
@@ -181,7 +180,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
*offset = 4;
return FAILED;
}
- *offset = SWID_REQ_SIZE;
+ *offset = TCG_SWID_REQ_MIN_SIZE;
this->flags &= SWID_REQ_RESERVED_MASK;
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_req.h b/src/libpts/tcg/swid/tcg_swid_attr_req.h
index 851b68d3b..59b597d84 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_req.h
+++ b/src/libpts/tcg/swid/tcg_swid_attr_req.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -21,6 +21,8 @@
#ifndef TCG_SWID_ATTR_REQ_H_
#define TCG_SWID_ATTR_REQ_H_
+#define TCG_SWID_REQ_MIN_SIZE 12
+
typedef struct tcg_swid_attr_req_t tcg_swid_attr_req_t;
typedef enum tcg_swid_attr_req_flag_t tcg_swid_attr_req_flag_t;
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c b/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c
index 429919edd..33aa16d53 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c
+++ b/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -42,12 +42,11 @@ typedef struct private_tcg_swid_attr_tag_id_inv_t private_tcg_swid_attr_tag_id_i
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Unique Software ID Length |Unique Software ID (var length)|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Unique Sequence ID Length |Unique Sequence ID (var length)|
+ * | Tag File Path Length | Tag File Path (var. length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-#define SWID_TAG_ID_INV_SIZE 16
-#define SWID_TAG_ID_INV_RESERVED 0x00
+#define TCG_SWID_TAG_ID_INV_RESERVED 0x00
/**
* Private data of an tcg_swid_attr_tag_id_inv_t object.
@@ -77,17 +76,17 @@ struct private_tcg_swid_attr_tag_id_inv_t {
/**
* Request ID
*/
- u_int32_t request_id;
+ uint32_t request_id;
/**
* Event ID Epoch
*/
- u_int32_t eid_epoch;
+ uint32_t eid_epoch;
/**
* Last Event ID
*/
- u_int32_t last_eid;
+ uint32_t last_eid;
/**
* SWID Tag ID Inventory
@@ -129,7 +128,7 @@ METHOD(pa_tnc_attr_t, build, void,
{
bio_writer_t *writer;
swid_tag_id_t *tag_id;
- chunk_t tag_creator, unique_sw_id, unique_seq_id;
+ chunk_t tag_creator, unique_sw_id, tag_file_path;
enumerator_t *enumerator;
if (this->value.ptr)
@@ -137,8 +136,8 @@ METHOD(pa_tnc_attr_t, build, void,
return;
}
- writer = bio_writer_create(SWID_TAG_ID_INV_SIZE);
- writer->write_uint8 (writer, SWID_TAG_ID_INV_RESERVED);
+ writer = bio_writer_create(TCG_SWID_TAG_ID_INV_MIN_SIZE);
+ writer->write_uint8 (writer, TCG_SWID_TAG_ID_INV_RESERVED);
writer->write_uint24(writer, this->inventory->get_count(this->inventory));
writer->write_uint32(writer, this->request_id);
writer->write_uint32(writer, this->eid_epoch);
@@ -148,10 +147,10 @@ METHOD(pa_tnc_attr_t, build, void,
while (enumerator->enumerate(enumerator, &tag_id))
{
tag_creator = tag_id->get_tag_creator(tag_id);
- unique_sw_id = tag_id->get_unique_sw_id(tag_id, &unique_seq_id);
+ unique_sw_id = tag_id->get_unique_sw_id(tag_id, &tag_file_path);
writer->write_data16(writer, tag_creator);
writer->write_data16(writer, unique_sw_id);
- writer->write_data16(writer, unique_seq_id);
+ writer->write_data16(writer, tag_file_path);
}
enumerator->destroy(enumerator);
@@ -160,15 +159,15 @@ METHOD(pa_tnc_attr_t, build, void,
}
METHOD(pa_tnc_attr_t, process, status_t,
- private_tcg_swid_attr_tag_id_inv_t *this, u_int32_t *offset)
+ private_tcg_swid_attr_tag_id_inv_t *this, uint32_t *offset)
{
bio_reader_t *reader;
- u_int32_t tag_id_count;
- u_int8_t reserved;
- chunk_t tag_creator, unique_sw_id, unique_seq_id;
+ uint32_t tag_id_count;
+ uint8_t reserved;
+ chunk_t tag_creator, unique_sw_id, tag_file_path;
swid_tag_id_t *tag_id;
- if (this->value.len < SWID_TAG_ID_INV_SIZE)
+ if (this->value.len < TCG_SWID_TAG_ID_INV_MIN_SIZE)
{
DBG1(DBG_TNC, "insufficient data for SWID Tag Identifier Inventory");
*offset = 0;
@@ -181,7 +180,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
reader->read_uint32(reader, &this->request_id);
reader->read_uint32(reader, &this->eid_epoch);
reader->read_uint32(reader, &this->last_eid);
- *offset = SWID_TAG_ID_INV_SIZE;
+ *offset = TCG_SWID_TAG_ID_INV_MIN_SIZE;
while (tag_id_count--)
{
@@ -199,14 +198,14 @@ METHOD(pa_tnc_attr_t, process, status_t,
}
*offset += 2 + unique_sw_id.len;
- if (!reader->read_data16(reader, &unique_seq_id))
+ if (!reader->read_data16(reader, &tag_file_path))
{
- DBG1(DBG_TNC, "insufficient data for Unique Sequence ID");
+ DBG1(DBG_TNC, "insufficient data for Tag File Path");
return FAILED;
}
- *offset += 2 + unique_seq_id.len;
+ *offset += 2 + tag_file_path.len;
- tag_id = swid_tag_id_create(tag_creator, unique_sw_id, unique_seq_id);
+ tag_id = swid_tag_id_create(tag_creator, unique_sw_id, tag_file_path);
this->inventory->add(this->inventory, tag_id);
}
reader->destroy(reader);
@@ -232,14 +231,20 @@ METHOD(pa_tnc_attr_t, destroy, void,
}
}
-METHOD(tcg_swid_attr_tag_id_inv_t, get_request_id, u_int32_t,
+METHOD(tcg_swid_attr_tag_id_inv_t, add, void,
+ private_tcg_swid_attr_tag_id_inv_t *this, swid_tag_id_t *tag_id)
+{
+ this->inventory->add(this->inventory, tag_id);
+}
+
+METHOD(tcg_swid_attr_tag_id_inv_t, get_request_id, uint32_t,
private_tcg_swid_attr_tag_id_inv_t *this)
{
return this->request_id;
}
-METHOD(tcg_swid_attr_tag_id_inv_t, get_last_eid, u_int32_t,
- private_tcg_swid_attr_tag_id_inv_t *this, u_int32_t *eid_epoch)
+METHOD(tcg_swid_attr_tag_id_inv_t, get_last_eid, uint32_t,
+ private_tcg_swid_attr_tag_id_inv_t *this, uint32_t *eid_epoch)
{
if (eid_epoch)
{
@@ -257,10 +262,9 @@ METHOD(tcg_swid_attr_tag_id_inv_t, get_inventory, swid_inventory_t*,
/**
* Described in header.
*/
-pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(u_int32_t request_id,
- u_int32_t eid_epoch,
- u_int32_t eid,
- swid_inventory_t *inventory)
+pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(uint32_t request_id,
+ uint32_t eid_epoch,
+ uint32_t eid)
{
private_tcg_swid_attr_tag_id_inv_t *this;
@@ -276,6 +280,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(u_int32_t request_id,
.get_ref = _get_ref,
.destroy = _destroy,
},
+ .add = _add,
.get_request_id = _get_request_id,
.get_last_eid = _get_last_eid,
.get_inventory = _get_inventory,
@@ -284,7 +289,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create(u_int32_t request_id,
.request_id = request_id,
.eid_epoch = eid_epoch,
.last_eid = eid,
- .inventory = inventory,
+ .inventory = swid_inventory_create(FALSE),
.ref = 1,
);
@@ -311,6 +316,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_id_inv_create_from_data(chunk_t data)
.get_ref = _get_ref,
.destroy = _destroy,
},
+ .add = _add,
.get_request_id = _get_request_id,
.get_last_eid = _get_last_eid,
.get_inventory = _get_inventory,
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h b/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h
index 1a0cbe7d2..c4ade904e 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h
+++ b/src/libpts/tcg/swid/tcg_swid_attr_tag_id_inv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@ typedef struct tcg_swid_attr_tag_id_inv_t tcg_swid_attr_tag_id_inv_t;
#include <pa_tnc/pa_tnc_attr.h>
+#define TCG_SWID_TAG_ID_INV_MIN_SIZE 16
+
/**
* Class implementing the TCG SWID Tag Identifier Inventory attribute
*
@@ -41,11 +43,18 @@ struct tcg_swid_attr_tag_id_inv_t {
pa_tnc_attr_t pa_tnc_attribute;
/**
+ * Add a Tag ID to the attribute
+ *
+ * @param tag_id SWID Tag ID to be added
+ */
+ void (*add)(tcg_swid_attr_tag_id_inv_t *this, swid_tag_id_t *tag_id);
+
+ /**
* Get Request ID
*
* @return Request ID
*/
- u_int32_t (*get_request_id)(tcg_swid_attr_tag_id_inv_t *this);
+ uint32_t (*get_request_id)(tcg_swid_attr_tag_id_inv_t *this);
/**
* Get Last Event ID
@@ -53,8 +62,8 @@ struct tcg_swid_attr_tag_id_inv_t {
* @param eid_epoch Event ID Epoch
* @return Last Event ID
*/
- u_int32_t (*get_last_eid)(tcg_swid_attr_tag_id_inv_t *this,
- u_int32_t *eid_epoch);
+ uint32_t (*get_last_eid)(tcg_swid_attr_tag_id_inv_t *this,
+ uint32_t *eid_epoch);
/**
* Get Inventory of SWID tag IDs
@@ -71,12 +80,10 @@ struct tcg_swid_attr_tag_id_inv_t {
* @param request_id Copy of the Request ID
* @param eid_epoch Event ID Epoch
* @param eid Last Event ID
- * @param inventory SWID Tag Inventory
*/
-pa_tnc_attr_t* tcg_swid_attr_tag_id_inv_create(u_int32_t request_id,
- u_int32_t eid_epoch,
- u_int32_t eid,
- swid_inventory_t *inventory);
+pa_tnc_attr_t* tcg_swid_attr_tag_id_inv_create(uint32_t request_id,
+ uint32_t eid_epoch,
+ uint32_t eid);
/**
* Creates an tcg_swid_attr_tag_id_inv_t object from received data
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c b/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c
index 82b9ef958..fbb94c6c2 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c
+++ b/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@ typedef struct private_tcg_swid_attr_tag_inv_t private_tcg_swid_attr_tag_inv_t;
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Last EID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Unique Sequence ID Length |Unique Sequence ID (var length)|
+ * | Tag File Path Length | Tag File Path (var length) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Tag Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -46,8 +46,7 @@ typedef struct private_tcg_swid_attr_tag_inv_t private_tcg_swid_attr_tag_inv_t;
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-#define SWID_TAG_INV_SIZE 16
-#define SWID_TAG_INV_RESERVED 0x00
+#define TCG_SWID_TAG_INV_RESERVED 0x00
/**
* Private data of an tcg_swid_attr_tag_inv_t object.
@@ -77,17 +76,17 @@ struct private_tcg_swid_attr_tag_inv_t {
/**
* Request ID
*/
- u_int32_t request_id;
+ uint32_t request_id;
/**
* Event ID Epoch
*/
- u_int32_t eid_epoch;
+ uint32_t eid_epoch;
/**
* Last Event ID
*/
- u_int32_t last_eid;
+ uint32_t last_eid;
/**
* SWID Tag Inventory
@@ -136,8 +135,8 @@ METHOD(pa_tnc_attr_t, build, void,
return;
}
- writer = bio_writer_create(SWID_TAG_INV_SIZE);
- writer->write_uint8 (writer, SWID_TAG_INV_RESERVED);
+ writer = bio_writer_create(TCG_SWID_TAG_INV_MIN_SIZE);
+ writer->write_uint8 (writer, TCG_SWID_TAG_INV_RESERVED);
writer->write_uint24(writer, this->inventory->get_count(this->inventory));
writer->write_uint32(writer, this->request_id);
writer->write_uint32(writer, this->eid_epoch);
@@ -146,7 +145,7 @@ METHOD(pa_tnc_attr_t, build, void,
enumerator = this->inventory->create_enumerator(this->inventory);
while (enumerator->enumerate(enumerator, &tag))
{
- writer->write_data16(writer, tag->get_unique_seq_id(tag));
+ writer->write_data16(writer, tag->get_tag_file_path(tag));
writer->write_data32(writer, tag->get_encoding(tag));
}
enumerator->destroy(enumerator);
@@ -156,15 +155,15 @@ METHOD(pa_tnc_attr_t, build, void,
}
METHOD(pa_tnc_attr_t, process, status_t,
- private_tcg_swid_attr_tag_inv_t *this, u_int32_t *offset)
+ private_tcg_swid_attr_tag_inv_t *this, uint32_t *offset)
{
bio_reader_t *reader;
- u_int32_t tag_count;
- u_int8_t reserved;
- chunk_t tag_encoding, unique_seq_id;
+ uint32_t tag_count;
+ uint8_t reserved;
+ chunk_t tag_encoding, tag_file_path;
swid_tag_t *tag;
- if (this->value.len < SWID_TAG_INV_SIZE)
+ if (this->value.len < TCG_SWID_TAG_INV_MIN_SIZE)
{
DBG1(DBG_TNC, "insufficient data for SWID Tag Inventory");
*offset = 0;
@@ -177,16 +176,16 @@ METHOD(pa_tnc_attr_t, process, status_t,
reader->read_uint32(reader, &this->request_id);
reader->read_uint32(reader, &this->eid_epoch);
reader->read_uint32(reader, &this->last_eid);
- *offset = SWID_TAG_INV_SIZE;
+ *offset = TCG_SWID_TAG_INV_MIN_SIZE;
while (tag_count--)
{
- if (!reader->read_data16(reader, &unique_seq_id))
+ if (!reader->read_data16(reader, &tag_file_path))
{
- DBG1(DBG_TNC, "insufficient data for Unique Sequence ID");
+ DBG1(DBG_TNC, "insufficient data for Tag File Path");
return FAILED;
}
- *offset += 2 + unique_seq_id.len;
+ *offset += 2 + tag_file_path.len;
if (!reader->read_data32(reader, &tag_encoding))
{
@@ -195,7 +194,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
}
*offset += 4 + tag_encoding.len;
- tag = swid_tag_create(tag_encoding, unique_seq_id);
+ tag = swid_tag_create(tag_encoding, tag_file_path);
this->inventory->add(this->inventory, tag);
}
reader->destroy(reader);
@@ -221,14 +220,20 @@ METHOD(pa_tnc_attr_t, destroy, void,
}
}
-METHOD(tcg_swid_attr_tag_inv_t, get_request_id, u_int32_t,
+METHOD(tcg_swid_attr_tag_inv_t, add, void,
+ private_tcg_swid_attr_tag_inv_t *this, swid_tag_t *tag)
+{
+ this->inventory->add(this->inventory, tag);
+}
+
+METHOD(tcg_swid_attr_tag_inv_t, get_request_id, uint32_t,
private_tcg_swid_attr_tag_inv_t *this)
{
return this->request_id;
}
-METHOD(tcg_swid_attr_tag_inv_t, get_last_eid, u_int32_t,
- private_tcg_swid_attr_tag_inv_t *this, u_int32_t *eid_epoch)
+METHOD(tcg_swid_attr_tag_inv_t, get_last_eid, uint32_t,
+ private_tcg_swid_attr_tag_inv_t *this, uint32_t *eid_epoch)
{
if (eid_epoch)
{
@@ -246,9 +251,8 @@ METHOD(tcg_swid_attr_tag_inv_t, get_inventory, swid_inventory_t*,
/**
* Described in header.
*/
-pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(u_int32_t request_id,
- u_int32_t eid_epoch, u_int32_t eid,
- swid_inventory_t *inventory)
+pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(uint32_t request_id,
+ uint32_t eid_epoch, uint32_t eid)
{
private_tcg_swid_attr_tag_inv_t *this;
@@ -264,6 +268,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(u_int32_t request_id,
.get_ref = _get_ref,
.destroy = _destroy,
},
+ .add = _add,
.get_request_id = _get_request_id,
.get_last_eid = _get_last_eid,
.get_inventory = _get_inventory,
@@ -272,7 +277,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_inv_create(u_int32_t request_id,
.request_id = request_id,
.eid_epoch = eid_epoch,
.last_eid = eid,
- .inventory = inventory,
+ .inventory = swid_inventory_create(TRUE),
.ref = 1,
);
@@ -299,6 +304,7 @@ pa_tnc_attr_t *tcg_swid_attr_tag_inv_create_from_data(chunk_t data)
.get_ref = _get_ref,
.destroy = _destroy,
},
+ .add = _add,
.get_request_id = _get_request_id,
.get_last_eid = _get_last_eid,
.get_inventory = _get_inventory,
diff --git a/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h b/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h
index 433f55ee0..69966c7d6 100644
--- a/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h
+++ b/src/libpts/tcg/swid/tcg_swid_attr_tag_inv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Andreas Steffen
+ * Copyright (C) 2013-2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@ typedef struct tcg_swid_attr_tag_inv_t tcg_swid_attr_tag_inv_t;
#include <pa_tnc/pa_tnc_attr.h>
+#define TCG_SWID_TAG_INV_MIN_SIZE 16
+
/**
* Class implementing the TCG SWID Tag Inventory attribute
*
@@ -41,11 +43,17 @@ struct tcg_swid_attr_tag_inv_t {
pa_tnc_attr_t pa_tnc_attribute;
/**
+ * Add a Tag ID to the attribute
+ *
+ * @param tag SWID Tag to be added
+ */
+ void (*add)(tcg_swid_attr_tag_inv_t *this, swid_tag_t *tag);
+ /**
* Get Request ID
*
* @return Request ID
*/
- u_int32_t (*get_request_id)(tcg_swid_attr_tag_inv_t *this);
+ uint32_t (*get_request_id)(tcg_swid_attr_tag_inv_t *this);
/**
* Get Last Event ID
@@ -53,8 +61,8 @@ struct tcg_swid_attr_tag_inv_t {
* @param eid_epoch Event ID Epoch
* @return Last Event ID
*/
- u_int32_t (*get_last_eid)(tcg_swid_attr_tag_inv_t *this,
- u_int32_t *eid_epoch);
+ uint32_t (*get_last_eid)(tcg_swid_attr_tag_inv_t *this,
+ uint32_t *eid_epoch);
/**
* Get Inventory of SWID tags
@@ -71,12 +79,10 @@ struct tcg_swid_attr_tag_inv_t {
* @param request_id Copy of the Request ID
* @param eid_epoch Event ID Epoch
* @param eid Last Event ID
- * @param inventory SWID Tag Inventory
*/
-pa_tnc_attr_t* tcg_swid_attr_tag_inv_create(u_int32_t request_id,
- u_int32_t eid_epoch,
- u_int32_t eid,
- swid_inventory_t *inventory);
+pa_tnc_attr_t* tcg_swid_attr_tag_inv_create(uint32_t request_id,
+ uint32_t eid_epoch,
+ uint32_t eid);
/**
* Creates an tcg_swid_attr_tag_inv_t object from received data